diff --git a/jerry-core/api/jerry-snapshot.c b/jerry-core/api/jerry-snapshot.c index 4ed845f66..472fb51b4 100644 --- a/jerry-core/api/jerry-snapshot.c +++ b/jerry-core/api/jerry-snapshot.c @@ -534,7 +534,7 @@ jerry_parse_and_save_snapshot_with_args (const jerry_char_t *source_p, /**< scri if (ECMA_IS_VALUE_ERROR (parse_status)) { - ecma_free_value (parse_status); + ecma_free_value (JERRY_CONTEXT (error_value)); return 0; } @@ -728,6 +728,11 @@ jerry_snapshot_result_at (const uint32_t *snapshot_p, /**< snapshot */ ecma_bytecode_deref (bytecode_p); } + if (ECMA_IS_VALUE_ERROR (ret_val)) + { + return ecma_create_error_reference (JERRY_CONTEXT (error_value)); + } + return ret_val; } /* jerry_snapshot_result_at */ #endif /* JERRY_ENABLE_SNAPSHOT_EXEC */ @@ -1312,14 +1317,14 @@ jerry_parse_and_save_literals (const jerry_char_t *source_p, /**< script source is_strict, &bytecode_data_p); - const bool error = ECMA_IS_VALUE_ERROR (parse_status); - ecma_free_value (parse_status); - - if (error) + if (ECMA_IS_VALUE_ERROR (parse_status)) { + ecma_free_value (JERRY_CONTEXT (error_value)); return 0; } + ecma_free_value (parse_status); + ecma_bytecode_deref (bytecode_data_p); ecma_lit_storage_item_t *string_list_p = JERRY_CONTEXT (string_list_first_p); diff --git a/jerry-core/api/jerry.c b/jerry-core/api/jerry.c index 8c2c8bee6..be6c961f1 100644 --- a/jerry-core/api/jerry.c +++ b/jerry-core/api/jerry.c @@ -123,16 +123,51 @@ jerry_make_api_unavailable (void) } /* jerry_make_api_unavailable */ /** - * Construct new TypeError object + * Remove the error flag from the argument value. * - * @return TypeError object value + * Note: + * Compatiblity function, should go away with JerryScript 2.0 + * + * @return return value for Jerry API functions + */ +static inline jerry_value_t __attr_always_inline___ +jerry_get_arg_value (jerry_value_t value) /**< return value */ +{ + if (unlikely (ecma_is_value_error_reference (value))) + { + value = ecma_get_error_reference_from_value (value)->value; + } + + return value; +} /* jerry_get_arg_value */ + +/** + * Create an API compatible return value. + * + * @return return value for Jerry API functions */ static jerry_value_t -jerry_create_type_error (void) +jerry_return (jerry_value_t value) /**< return value */ { - ecma_object_t *type_error_obj_p = ecma_new_standard_error (ECMA_ERROR_TYPE); - return ecma_make_error_obj_value (type_error_obj_p); -} /* jerry_create_type_error */ + if (ECMA_IS_VALUE_ERROR (value)) + { + value = ecma_create_error_reference (JERRY_CONTEXT (error_value)); + } + + return value; +} /* jerry_return */ + +/** + * Throw an API compatible return value. + * + * @return return value for Jerry API functions + */ +static inline jerry_value_t __attr_always_inline___ +jerry_throw (jerry_value_t value) /**< return value */ +{ + JERRY_ASSERT (ECMA_IS_VALUE_ERROR (value)); + return ecma_create_error_reference (JERRY_CONTEXT (error_value)); +} /* jerry_throw */ /** * Jerry engine initialization @@ -310,11 +345,11 @@ jerry_run_simple (const jerry_char_t *script_source_p, /**< script source */ jerry_value_t parse_ret_val = jerry_parse (script_source_p, script_source_size, false); - if (!ECMA_IS_VALUE_ERROR (parse_ret_val)) + if (!ecma_is_value_error_reference (parse_ret_val)) { jerry_value_t run_ret_val = jerry_run (parse_ret_val); - if (!ECMA_IS_VALUE_ERROR (run_ret_val)) + if (!ecma_is_value_error_reference (run_ret_val)) { result = true; } @@ -355,7 +390,7 @@ jerry_parse (const jerry_char_t *source_p, /**< script source */ if (ECMA_IS_VALUE_ERROR (parse_status)) { - return parse_status; + return ecma_create_error_reference (JERRY_CONTEXT (error_value)); } ecma_free_value (parse_status); @@ -371,7 +406,7 @@ jerry_parse (const jerry_char_t *source_p, /**< script source */ JERRY_UNUSED (source_size); JERRY_UNUSED (is_strict); - return ecma_raise_syntax_error (ECMA_ERR_MSG ("The parser has been disabled.")); + return jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("The parser has been disabled."))); #endif /* !JERRY_DISABLE_JS_PARSER */ } /* jerry_parse */ @@ -457,7 +492,7 @@ jerry_parse_function (const jerry_char_t *resource_name_p, /**< resource name (u if (ECMA_IS_VALUE_ERROR (parse_status)) { - return parse_status; + return ecma_create_error_reference (JERRY_CONTEXT (error_value)); } ecma_free_value (parse_status); @@ -475,7 +510,7 @@ jerry_parse_function (const jerry_char_t *resource_name_p, /**< resource name (u JERRY_UNUSED (source_size); JERRY_UNUSED (is_strict); - return ecma_raise_syntax_error (ECMA_ERR_MSG ("The parser has been disabled.")); + return jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("The parser has been disabled."))); #endif /* !JERRY_DISABLE_JS_PARSER */ } /* jerry_parse_function */ @@ -495,7 +530,7 @@ jerry_run (const jerry_value_t func_val) /**< function to run */ if (!ecma_is_value_object (func_val)) { - return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } ecma_object_t *func_obj_p = ecma_get_object_from_value (func_val); @@ -503,7 +538,7 @@ jerry_run (const jerry_value_t func_val) /**< function to run */ if (ecma_get_object_type (func_obj_p) != ECMA_OBJECT_TYPE_FUNCTION || ecma_get_object_is_builtin (func_obj_p)) { - return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_obj_p; @@ -513,14 +548,14 @@ jerry_run (const jerry_value_t func_val) /**< function to run */ if (scope_p != ecma_get_global_environment ()) { - return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } const ecma_compiled_code_t *bytecode_data_p; bytecode_data_p = ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t, ext_func_p->u.function.bytecode_cp); - return vm_run_global (bytecode_data_p); + return jerry_return (vm_run_global (bytecode_data_p)); } /* jerry_run */ /** @@ -538,10 +573,10 @@ jerry_eval (const jerry_char_t *source_p, /**< source code */ { jerry_assert_api_available (); - return ecma_op_eval_chars_buffer ((const lit_utf8_byte_t *) source_p, - source_size, - false, - is_strict); + return jerry_return (ecma_op_eval_chars_buffer ((const lit_utf8_byte_t *) source_p, + source_size, + false, + is_strict)); } /* jerry_eval */ /** @@ -591,8 +626,9 @@ jerry_value_is_array (const jerry_value_t value) /**< jerry api value */ { jerry_assert_api_available (); - return (ecma_is_value_object (value) - && ecma_get_object_type (ecma_get_object_from_value (value)) == ECMA_OBJECT_TYPE_ARRAY); + jerry_value_t array = jerry_get_arg_value (value); + return (ecma_is_value_object (array) + && ecma_get_object_type (ecma_get_object_from_value (array)) == ECMA_OBJECT_TYPE_ARRAY); } /* jerry_value_is_array */ /** @@ -606,7 +642,7 @@ jerry_value_is_boolean (const jerry_value_t value) /**< api value */ { jerry_assert_api_available (); - return ecma_is_value_boolean (value); + return ecma_is_value_boolean (jerry_get_arg_value (value)); } /* jerry_value_is_boolean */ /** @@ -620,7 +656,7 @@ jerry_value_is_constructor (const jerry_value_t value) /**< jerry api value */ { jerry_assert_api_available (); - return ecma_is_constructor (value); + return ecma_is_constructor (jerry_get_arg_value (value)); } /* jerry_value_is_constructor */ /** @@ -634,7 +670,7 @@ jerry_value_is_function (const jerry_value_t value) /**< api value */ { jerry_assert_api_available (); - return ecma_op_is_callable (value); + return ecma_op_is_callable (jerry_get_arg_value (value)); } /* jerry_value_is_function */ /** @@ -648,7 +684,7 @@ jerry_value_is_number (const jerry_value_t value) /**< api value */ { jerry_assert_api_available (); - return ecma_is_value_number (value); + return ecma_is_value_number (jerry_get_arg_value (value)); } /* jerry_value_is_number */ /** @@ -662,7 +698,7 @@ jerry_value_is_null (const jerry_value_t value) /**< api value */ { jerry_assert_api_available (); - return ecma_is_value_null (value); + return ecma_is_value_null (jerry_get_arg_value (value)); } /* jerry_value_is_null */ /** @@ -676,7 +712,7 @@ jerry_value_is_object (const jerry_value_t value) /**< api value */ { jerry_assert_api_available (); - return ecma_is_value_object (value); + return ecma_is_value_object (jerry_get_arg_value (value)); } /* jerry_value_is_object */ #ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN @@ -692,8 +728,9 @@ jerry_value_is_promise (const jerry_value_t value) /**< api value */ { jerry_assert_api_available (); - return (ecma_is_value_object (value) - && ecma_is_promise (ecma_get_object_from_value (value))); + jerry_value_t promise = jerry_get_arg_value (value); + return (ecma_is_value_object (promise) + && ecma_is_promise (ecma_get_object_from_value (promise))); } /* jerry_value_is_promise */ #endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */ @@ -709,7 +746,7 @@ jerry_value_is_string (const jerry_value_t value) /**< api value */ { jerry_assert_api_available (); - return ecma_is_value_string (value); + return ecma_is_value_string (jerry_get_arg_value (value)); } /* jerry_value_is_string */ /** @@ -723,7 +760,7 @@ jerry_value_is_undefined (const jerry_value_t value) /**< api value */ { jerry_assert_api_available (); - return ecma_is_value_undefined (value); + return ecma_is_value_undefined (jerry_get_arg_value (value)); } /* jerry_value_is_undefined */ /** @@ -781,7 +818,7 @@ jerry_value_has_error_flag (const jerry_value_t value) /**< api value */ { jerry_assert_api_available (); - return ECMA_IS_VALUE_ERROR (value); + return ecma_is_value_error_reference (value); } /* jerry_value_has_error_flag */ /** @@ -792,7 +829,10 @@ jerry_value_clear_error_flag (jerry_value_t *value_p) { jerry_assert_api_available (); - *value_p = (*value_p) & ~ECMA_VALUE_ERROR_FLAG; + if (ecma_is_value_error_reference (*value_p)) + { + *value_p = ecma_clear_error_reference (*value_p); + } } /* jerry_value_clear_error_flag */ /** @@ -803,7 +843,10 @@ jerry_value_set_error_flag (jerry_value_t *value_p) { jerry_assert_api_available (); - *value_p = (*value_p) | ECMA_VALUE_ERROR_FLAG; + if (!ecma_is_value_error_reference (*value_p)) + { + *value_p = ecma_create_error_reference (*value_p); + } } /* jerry_value_set_error_flag */ /** @@ -816,12 +859,14 @@ jerry_get_boolean_value (const jerry_value_t value) /**< api value */ { jerry_assert_api_available (); - if (!jerry_value_is_boolean (value)) + jerry_value_t boolean = jerry_get_arg_value (value); + + if (!ecma_is_value_boolean (boolean)) { return false; } - return ecma_is_value_true (value); + return ecma_is_value_true (boolean); } /* jerry_get_boolean_value */ /** @@ -834,12 +879,14 @@ jerry_get_number_value (const jerry_value_t value) /**< api value */ { jerry_assert_api_available (); - if (!jerry_value_is_number (value)) + jerry_value_t number = jerry_get_arg_value (value); + + if (!ecma_is_value_number (number)) { return 0; } - return (double) ecma_get_number_from_value (value); + return (double) ecma_get_number_from_value (number); } /* jerry_get_number_value */ /** @@ -853,7 +900,7 @@ jerry_value_to_boolean (const jerry_value_t value) /**< input value */ { jerry_assert_api_available (); - if (ECMA_IS_VALUE_ERROR (value)) + if (ecma_is_value_error_reference (value)) { return false; } @@ -875,12 +922,12 @@ jerry_value_to_number (const jerry_value_t value) /**< input value */ { jerry_assert_api_available (); - if (ECMA_IS_VALUE_ERROR (value)) + if (ecma_is_value_error_reference (value)) { - return ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p))); } - return ecma_op_to_number (value); + return jerry_return (ecma_op_to_number (value)); } /* jerry_value_to_number */ /** @@ -897,12 +944,12 @@ jerry_value_to_object (const jerry_value_t value) /**< input value */ { jerry_assert_api_available (); - if (ECMA_IS_VALUE_ERROR (value)) + if (ecma_is_value_error_reference (value)) { - return ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p))); } - return ecma_op_to_object (value); + return jerry_return (ecma_op_to_object (value)); } /* jerry_value_to_object */ /** @@ -919,12 +966,12 @@ jerry_value_to_primitive (const jerry_value_t value) /**< input value */ { jerry_assert_api_available (); - if (ECMA_IS_VALUE_ERROR (value)) + if (ecma_is_value_error_reference (value)) { - return ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p))); } - return ecma_op_to_primitive (value, ECMA_PREFERRED_TYPE_NO); + return jerry_return (ecma_op_to_primitive (value, ECMA_PREFERRED_TYPE_NO)); } /* jerry_value_to_primitive */ /** @@ -942,12 +989,12 @@ jerry_value_to_string (const jerry_value_t value) /**< input value */ jerry_assert_api_available (); - if (ECMA_IS_VALUE_ERROR (value)) + if (ecma_is_value_error_reference (value)) { - return ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p))); } - return ecma_op_to_string (value); + return jerry_return (ecma_op_to_string (value)); } /* jerry_value_to_string */ /** @@ -963,6 +1010,12 @@ jerry_acquire_value (jerry_value_t value) /**< API value */ { jerry_assert_api_available (); + if (unlikely (ecma_is_value_error_reference (value))) + { + ecma_ref_error_reference (ecma_get_error_reference_from_value (value)); + return value; + } + return ecma_copy_value (value); } /* jerry_acquire_value */ @@ -974,6 +1027,12 @@ jerry_release_value (jerry_value_t value) /**< API value */ { jerry_assert_api_available (); + if (unlikely (ecma_is_value_error_reference (value))) + { + ecma_deref_error_reference (ecma_get_error_reference_from_value (value)); + return; + } + ecma_free_value (value); } /* jerry_release_value */ @@ -992,7 +1051,7 @@ jerry_create_array (uint32_t size) /**< size of array */ ecma_value_t array_length = ecma_make_uint32_value (size); - jerry_length_t argument_size = 1; + const jerry_length_t argument_size = 1; ecma_value_t array_value = ecma_op_create_array_object (&array_length, argument_size, true); ecma_free_value (array_length); @@ -1011,7 +1070,8 @@ jerry_create_boolean (bool value) /**< bool value from which a jerry_value_t wil { jerry_assert_api_available (); - return ecma_make_boolean_value (value); + value = jerry_get_arg_value (value); + return jerry_return (ecma_make_boolean_value (value)); } /* jerry_create_boolean */ /** @@ -1052,7 +1112,7 @@ jerry_create_error_sz (jerry_error_t error_type, /**< type of error */ if (message_p == NULL || message_size == 0) { - return ecma_make_error_obj_value (ecma_new_standard_error ((ecma_standard_error_t) error_type)); + return ecma_create_error_object_reference (ecma_new_standard_error ((ecma_standard_error_t) error_type)); } else { @@ -1064,7 +1124,7 @@ jerry_create_error_sz (jerry_error_t error_type, /**< type of error */ ecma_deref_ecma_string (message_string_p); - return ecma_make_error_obj_value (error_object_p); + return ecma_create_error_object_reference (error_object_p); } } /* jerry_create_error_sz */ @@ -1135,6 +1195,19 @@ jerry_create_number_nan (void) return ecma_make_nan_value (); } /* jerry_create_number_nan */ +/** + * Creates a jerry_value_t representing an undefined value. + * + * @return value of undefined + */ +jerry_value_t +jerry_create_undefined (void) +{ + jerry_assert_api_available (); + + return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); +} /* jerry_create_undefined */ + /** * Creates and returns a jerry_value_t with type null object. * @@ -1164,8 +1237,6 @@ jerry_create_object (void) return ecma_make_object_value (ecma_op_create_object_object_noarg ()); } /* jerry_create_object */ -#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN - /** * Create an empty Promise object which can be resolve/reject later * by calling jerry_resolve_or_reject_promise. @@ -1180,10 +1251,12 @@ jerry_create_promise (void) { jerry_assert_api_available (); +#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN return ecma_op_create_promise_object (ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY), ECMA_PROMISE_EXECUTOR_EMPTY); -} /* jerry_create_promise */ - +#else /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */ + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Promise not supported."))); #endif /* CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */ +} /* jerry_create_promise */ /** * Create string from a valid UTF-8 string @@ -1252,19 +1325,6 @@ jerry_create_string_sz (const jerry_char_t *str_p, /**< pointer to string */ return ecma_make_string_value (ecma_str_p); } /* jerry_create_string_sz */ -/** - * Creates a jerry_value_t representing an undefined value. - * - * @return value of undefined - */ -jerry_value_t -jerry_create_undefined (void) -{ - jerry_assert_api_available (); - - return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); -} /* jerry_create_undefined */ - /** * Get length of an array object * @@ -1278,7 +1338,9 @@ jerry_get_array_length (const jerry_value_t value) { jerry_assert_api_available (); - if (!jerry_value_is_array (value)) + jerry_value_t array = jerry_get_arg_value (value); + + if (!jerry_value_is_array (array)) { return 0; } @@ -1287,7 +1349,7 @@ jerry_get_array_length (const jerry_value_t value) ecma_string_t magic_string_length; ecma_init_ecma_length_string (&magic_string_length); - ecma_value_t len_value = ecma_op_object_get (ecma_get_object_from_value (value), + ecma_value_t len_value = ecma_op_object_get (ecma_get_object_from_value (array), &magic_string_length); length = ecma_number_to_uint32 (ecma_get_number_from_value (len_value)); @@ -1309,12 +1371,14 @@ jerry_get_string_size (const jerry_value_t value) /**< input string */ { jerry_assert_api_available (); - if (!ecma_is_value_string (value)) + jerry_value_t string = jerry_get_arg_value (value); + + if (!ecma_is_value_string (string)) { return 0; } - return ecma_string_get_size (ecma_get_string_from_value (value)); + return ecma_string_get_size (ecma_get_string_from_value (string)); } /* jerry_get_string_size */ /** @@ -1330,12 +1394,14 @@ jerry_get_utf8_string_size (const jerry_value_t value) { jerry_assert_api_available (); - if (!ecma_is_value_string (value)) + jerry_value_t string = jerry_get_arg_value (value); + + if (!ecma_is_value_string (string)) { return 0; } - return ecma_string_get_utf8_size (ecma_get_string_from_value (value)); + return ecma_string_get_utf8_size (ecma_get_string_from_value (string)); } /* jerry_get_utf8_string_size */ /** @@ -1351,12 +1417,14 @@ jerry_get_string_length (const jerry_value_t value) /**< input string */ { jerry_assert_api_available (); - if (!ecma_is_value_string (value)) + jerry_value_t string = jerry_get_arg_value (value); + + if (!ecma_is_value_string (string)) { return 0; } - return ecma_string_get_length (ecma_get_string_from_value (value)); + return ecma_string_get_length (ecma_get_string_from_value (string)); } /* jerry_get_string_length */ /** @@ -1372,12 +1440,14 @@ jerry_get_utf8_string_length (const jerry_value_t value) /**< input string */ { jerry_assert_api_available (); - if (!ecma_is_value_string (value)) + jerry_value_t string = jerry_get_arg_value (value); + + if (!ecma_is_value_string (string)) { return 0; } - return ecma_string_get_utf8_length (ecma_get_string_from_value (value)); + return ecma_string_get_utf8_length (ecma_get_string_from_value (string)); } /* jerry_get_utf8_string_length */ /** @@ -1397,12 +1467,14 @@ jerry_string_to_char_buffer (const jerry_value_t value, /**< input string value { jerry_assert_api_available (); - if (!ecma_is_value_string (value) || buffer_p == NULL) + jerry_value_t string = jerry_get_arg_value (value); + + if (!ecma_is_value_string (string) || buffer_p == NULL) { return 0; } - ecma_string_t *str_p = ecma_get_string_from_value (value); + ecma_string_t *str_p = ecma_get_string_from_value (string); if (ecma_string_get_size (str_p) > buffer_size) { @@ -1431,12 +1503,14 @@ jerry_string_to_utf8_char_buffer (const jerry_value_t value, /**< input string v { jerry_assert_api_available (); - if (!ecma_is_value_string (value) || buffer_p == NULL) + jerry_value_t string = jerry_get_arg_value (value); + + if (!ecma_is_value_string (string) || buffer_p == NULL) { return 0; } - ecma_string_t *str_p = ecma_get_string_from_value (value); + ecma_string_t *str_p = ecma_get_string_from_value (string); if (ecma_string_get_utf8_size (str_p) > buffer_size) { @@ -1468,12 +1542,14 @@ jerry_substring_to_char_buffer (const jerry_value_t value, /**< input string val { jerry_assert_api_available (); - if (!ecma_is_value_string (value) || buffer_p == NULL) + jerry_value_t string = jerry_get_arg_value (value); + + if (!ecma_is_value_string (string) || buffer_p == NULL) { return 0; } - ecma_string_t *str_p = ecma_get_string_from_value (value); + ecma_string_t *str_p = ecma_get_string_from_value (string); return ecma_substring_copy_to_cesu8_buffer (str_p, start_pos, @@ -1502,12 +1578,14 @@ jerry_substring_to_utf8_char_buffer (const jerry_value_t value, /**< input strin { jerry_assert_api_available (); - if (!ecma_is_value_string (value) || buffer_p == NULL) + jerry_value_t string = jerry_get_arg_value (value); + + if (!ecma_is_value_string (string) || buffer_p == NULL) { return 0; } - ecma_string_t *str_p = ecma_get_string_from_value (value); + ecma_string_t *str_p = ecma_get_string_from_value (string); return ecma_substring_copy_to_utf8_buffer (str_p, start_pos, @@ -1528,14 +1606,17 @@ jerry_has_property (const jerry_value_t obj_val, /**< object value */ { jerry_assert_api_available (); - if (!ecma_is_value_object (obj_val) - || !ecma_is_value_string (prop_name_val)) + jerry_value_t obj_value = jerry_get_arg_value (obj_val); + jerry_value_t prop_name_value = jerry_get_arg_value (prop_name_val); + + if (!ecma_is_value_object (obj_value) + || !ecma_is_value_string (prop_name_value)) { - return false; + return ecma_make_boolean_value (false); } - bool has_property = ecma_op_object_has_property (ecma_get_object_from_value (obj_val), - ecma_get_string_from_value (prop_name_val)); + bool has_property = ecma_op_object_has_property (ecma_get_object_from_value (obj_value), + ecma_get_string_from_value (prop_name_value)); return ecma_make_boolean_value (has_property); } /* jerry_has_property */ @@ -1552,14 +1633,17 @@ jerry_has_own_property (const jerry_value_t obj_val, /**< object value */ { jerry_assert_api_available (); - if (!ecma_is_value_object (obj_val) - || !ecma_is_value_string (prop_name_val)) + jerry_value_t obj_value = jerry_get_arg_value (obj_val); + jerry_value_t prop_name_value = jerry_get_arg_value (prop_name_val); + + if (!ecma_is_value_object (obj_value) + || !ecma_is_value_string (prop_name_value)) { - return false; + return ecma_make_boolean_value (false); } - bool has_property = ecma_op_object_has_own_property (ecma_get_object_from_value (obj_val), - ecma_get_string_from_value (prop_name_val)); + bool has_property = ecma_op_object_has_own_property (ecma_get_object_from_value (obj_value), + ecma_get_string_from_value (prop_name_value)); return ecma_make_boolean_value (has_property); } /* jerry_has_own_property */ @@ -1576,14 +1660,17 @@ jerry_delete_property (const jerry_value_t obj_val, /**< object value */ { jerry_assert_api_available (); - if (!ecma_is_value_object (obj_val) - || !ecma_is_value_string (prop_name_val)) + jerry_value_t obj_value = jerry_get_arg_value (obj_val); + jerry_value_t prop_name_value = jerry_get_arg_value (prop_name_val); + + if (!ecma_is_value_object (obj_value) + || !ecma_is_value_string (prop_name_value)) { return false; } - ecma_value_t ret_value = ecma_op_object_delete (ecma_get_object_from_value (obj_val), - ecma_get_string_from_value (prop_name_val), + ecma_value_t ret_value = ecma_op_object_delete (ecma_get_object_from_value (obj_value), + ecma_get_string_from_value (prop_name_value), false); return ecma_is_value_true (ret_value); } /* jerry_delete_property */ @@ -1600,14 +1687,16 @@ jerry_delete_property_by_index (const jerry_value_t obj_val, /**< object value * { jerry_assert_api_available (); - if (!ecma_is_value_object (obj_val)) + jerry_value_t obj_value = jerry_get_arg_value (obj_val); + + if (!ecma_is_value_object (obj_value)) { return false; } ecma_string_t str_idx; ecma_init_ecma_string_from_uint32 (&str_idx, index); - ecma_value_t ret_value = ecma_op_object_delete (ecma_get_object_from_value (obj_val), + ecma_value_t ret_value = ecma_op_object_delete (ecma_get_object_from_value (obj_value), &str_idx, false); return ecma_is_value_true (ret_value); @@ -1628,14 +1717,18 @@ jerry_get_property (const jerry_value_t obj_val, /**< object value */ { jerry_assert_api_available (); - if (!ecma_is_value_object (obj_val) - || !ecma_is_value_string (prop_name_val)) + jerry_value_t obj_value = jerry_get_arg_value (obj_val); + jerry_value_t prop_name_value = jerry_get_arg_value (prop_name_val); + + if (!ecma_is_value_object (obj_value) + || !ecma_is_value_string (prop_name_value)) { - return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } - return ecma_op_object_get (ecma_get_object_from_value (obj_val), - ecma_get_string_from_value (prop_name_val)); + jerry_value_t ret_value = ecma_op_object_get (ecma_get_object_from_value (obj_value), + ecma_get_string_from_value (prop_name_value)); + return jerry_return (ret_value); } /* jerry_get_property */ /** @@ -1653,16 +1746,18 @@ jerry_get_property_by_index (const jerry_value_t obj_val, /**< object value */ { jerry_assert_api_available (); - if (!ecma_is_value_object (obj_val)) + jerry_value_t obj_value = jerry_get_arg_value (obj_val); + + if (!ecma_is_value_object (obj_value)) { - return jerry_create_type_error (); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } ecma_string_t str_idx; ecma_init_ecma_string_from_uint32 (&str_idx, index); - ecma_value_t ret_value = ecma_op_object_get (ecma_get_object_from_value (obj_val), &str_idx); + ecma_value_t ret_value = ecma_op_object_get (ecma_get_object_from_value (obj_value), &str_idx); - return ret_value; + return jerry_return (ret_value); } /* jerry_get_property_by_index */ /** @@ -1681,17 +1776,20 @@ jerry_set_property (const jerry_value_t obj_val, /**< object value */ { jerry_assert_api_available (); - if (ECMA_IS_VALUE_ERROR (value_to_set) - || !ecma_is_value_object (obj_val) - || !ecma_is_value_string (prop_name_val)) + jerry_value_t obj_value = jerry_get_arg_value (obj_val); + jerry_value_t prop_name_value = jerry_get_arg_value (prop_name_val); + + if (ecma_is_value_error_reference (value_to_set) + || !ecma_is_value_object (obj_value) + || !ecma_is_value_string (prop_name_value)) { - return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } - return ecma_op_object_put (ecma_get_object_from_value (obj_val), - ecma_get_string_from_value (prop_name_val), - value_to_set, - true); + return jerry_return (ecma_op_object_put (ecma_get_object_from_value (obj_value), + ecma_get_string_from_value (prop_name_value), + value_to_set, + true)); } /* jerry_set_property */ /** @@ -1710,20 +1808,22 @@ jerry_set_property_by_index (const jerry_value_t obj_val, /**< object value */ { jerry_assert_api_available (); - if (ECMA_IS_VALUE_ERROR (value_to_set) - || !ecma_is_value_object (obj_val)) + jerry_value_t obj_value = jerry_get_arg_value (obj_val); + + if (ecma_is_value_error_reference (value_to_set) + || !ecma_is_value_object (obj_value)) { - return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } ecma_string_t *str_idx_p = ecma_new_ecma_string_from_uint32 ((uint32_t) index); - ecma_value_t ret_value = ecma_op_object_put (ecma_get_object_from_value (obj_val), + ecma_value_t ret_value = ecma_op_object_put (ecma_get_object_from_value (obj_value), str_idx_p, value_to_set, true); ecma_deref_ecma_string (str_idx_p); - return ret_value; + return jerry_return (ret_value); } /* jerry_set_property_by_index */ /** @@ -1762,16 +1862,19 @@ jerry_define_own_property (const jerry_value_t obj_val, /**< object value */ { jerry_assert_api_available (); - if (!ecma_is_value_object (obj_val) - || !ecma_is_value_string (prop_name_val)) + jerry_value_t obj_value = jerry_get_arg_value (obj_val); + jerry_value_t prop_name_value = jerry_get_arg_value (prop_name_val); + + if (!ecma_is_value_object (obj_value) + || !ecma_is_value_string (prop_name_value)) { - return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } if ((prop_desc_p->is_writable_defined || prop_desc_p->is_value_defined) && (prop_desc_p->is_get_defined || prop_desc_p->is_set_defined)) { - return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); @@ -1787,9 +1890,9 @@ jerry_define_own_property (const jerry_value_t obj_val, /**< object value */ if (prop_desc_p->is_value_defined) { - if (ECMA_IS_VALUE_ERROR (prop_desc_p->value)) + if (ecma_is_value_error_reference (prop_desc_p->value)) { - return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } prop_desc.value = prop_desc_p->value; @@ -1804,9 +1907,9 @@ jerry_define_own_property (const jerry_value_t obj_val, /**< object value */ ecma_value_t getter = prop_desc_p->getter; prop_desc.is_get_defined = true; - if (ECMA_IS_VALUE_ERROR (getter)) + if (ecma_is_value_error_reference (getter)) { - return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } if (ecma_op_is_callable (getter)) @@ -1815,7 +1918,7 @@ jerry_define_own_property (const jerry_value_t obj_val, /**< object value */ } else if (!ecma_is_value_null (getter)) { - return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } } @@ -1824,9 +1927,9 @@ jerry_define_own_property (const jerry_value_t obj_val, /**< object value */ ecma_value_t setter = prop_desc_p->setter; prop_desc.is_set_defined = true; - if (ECMA_IS_VALUE_ERROR (setter)) + if (ecma_is_value_error_reference (setter)) { - return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } if (ecma_op_is_callable (setter)) @@ -1835,12 +1938,12 @@ jerry_define_own_property (const jerry_value_t obj_val, /**< object value */ } else if (!ecma_is_value_null (setter)) { - return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } } - return ecma_op_object_define_own_property (ecma_get_object_from_value (obj_val), - ecma_get_string_from_value (prop_name_val), + return ecma_op_object_define_own_property (ecma_get_object_from_value (obj_value), + ecma_get_string_from_value (prop_name_value), &prop_desc, true); } /* jerry_define_own_property */ @@ -1858,16 +1961,19 @@ jerry_get_own_property_descriptor (const jerry_value_t obj_val, /**< object val { jerry_assert_api_available (); - if (!ecma_is_value_object (obj_val) - || !ecma_is_value_string (prop_name_val)) + jerry_value_t obj_value = jerry_get_arg_value (obj_val); + jerry_value_t prop_name_value = jerry_get_arg_value (prop_name_val); + + if (!ecma_is_value_object (obj_value) + || !ecma_is_value_string (prop_name_value)) { return false; } ecma_property_descriptor_t prop_desc; - if (!ecma_op_object_get_own_property_descriptor (ecma_get_object_from_value (obj_val), - ecma_get_string_from_value (prop_name_val), + if (!ecma_op_object_get_own_property_descriptor (ecma_get_object_from_value (obj_value), + ecma_get_string_from_value (prop_name_value), &prop_desc)) { return false; @@ -1929,17 +2035,17 @@ jerry_free_property_descriptor_fields (const jerry_property_descriptor_t *prop_d { if (prop_desc_p->is_value_defined) { - ecma_free_value (prop_desc_p->value); + jerry_release_value (prop_desc_p->value); } if (prop_desc_p->is_get_defined) { - ecma_free_value (prop_desc_p->getter); + jerry_release_value (prop_desc_p->getter); } if (prop_desc_p->is_set_defined) { - ecma_free_value (prop_desc_p->setter); + jerry_release_value (prop_desc_p->setter); } } /* jerry_free_property_descriptor_fields */ @@ -1964,17 +2070,17 @@ jerry_invoke_function (bool is_invoke_as_constructor, /**< true - invoke functio { JERRY_ASSERT (args_count == 0 || args_p != NULL); - if (ECMA_IS_VALUE_ERROR (func_obj_val) - || ECMA_IS_VALUE_ERROR (this_val)) + if (ecma_is_value_error_reference (func_obj_val) + || ecma_is_value_error_reference (this_val)) { - return ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p))); } for (uint32_t i = 0; i < args_count; i++) { - if (ECMA_IS_VALUE_ERROR (args_p[i])) + if (ecma_is_value_error_reference (args_p[i])) { - return ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p))); } } @@ -1982,18 +2088,18 @@ jerry_invoke_function (bool is_invoke_as_constructor, /**< true - invoke functio { JERRY_ASSERT (jerry_value_is_constructor (func_obj_val)); - return ecma_op_function_construct (ecma_get_object_from_value (func_obj_val), - args_p, - args_count); + return jerry_return (ecma_op_function_construct (ecma_get_object_from_value (func_obj_val), + args_p, + args_count)); } else { JERRY_ASSERT (jerry_value_is_function (func_obj_val)); - return ecma_op_function_call (ecma_get_object_from_value (func_obj_val), - this_val, - args_p, - args_count); + return jerry_return (ecma_op_function_call (ecma_get_object_from_value (func_obj_val), + this_val, + args_p, + args_count)); } } /* jerry_invoke_function */ @@ -2019,7 +2125,7 @@ jerry_call_function (const jerry_value_t func_obj_val, /**< function object to c return jerry_invoke_function (false, func_obj_val, this_val, args_p, args_count); } - return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } /* jerry_call_function */ /** @@ -2045,7 +2151,7 @@ jerry_construct_object (const jerry_value_t func_obj_val, /**< function object t return jerry_invoke_function (true, func_obj_val, this_val, args_p, args_count); } - return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } /* jerry_construct_object */ /** @@ -2062,12 +2168,14 @@ jerry_get_object_keys (const jerry_value_t obj_val) /**< object value */ { jerry_assert_api_available (); - if (!ecma_is_value_object (obj_val)) + jerry_value_t obj_value = jerry_get_arg_value (obj_val); + + if (!ecma_is_value_object (obj_value)) { - return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } - return ecma_builtin_helper_object_get_properties (ecma_get_object_from_value (obj_val), true); + return ecma_builtin_helper_object_get_properties (ecma_get_object_from_value (obj_value), true); } /* jerry_get_object_keys */ /** @@ -2081,12 +2189,14 @@ jerry_get_prototype (const jerry_value_t obj_val) /**< object value */ { jerry_assert_api_available (); - if (!ecma_is_value_object (obj_val)) + jerry_value_t obj_value = jerry_get_arg_value (obj_val); + + if (!ecma_is_value_object (obj_value)) { - return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } - ecma_object_t *proto_obj_p = ecma_get_object_prototype (ecma_get_object_from_value (obj_val)); + ecma_object_t *proto_obj_p = ecma_get_object_prototype (ecma_get_object_from_value (obj_value)); if (proto_obj_p == NULL) { @@ -2108,20 +2218,22 @@ jerry_set_prototype (const jerry_value_t obj_val, /**< object value */ { jerry_assert_api_available (); - if (!ecma_is_value_object (obj_val) - || ECMA_IS_VALUE_ERROR (proto_obj_val) + jerry_value_t obj_value = jerry_get_arg_value (obj_val); + + if (!ecma_is_value_object (obj_value) + || ecma_is_value_error_reference (proto_obj_val) || (!ecma_is_value_object (proto_obj_val) && !ecma_is_value_null (proto_obj_val))) { - return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } if (ecma_is_value_null (proto_obj_val)) { - ECMA_SET_POINTER (ecma_get_object_from_value (obj_val)->prototype_or_outer_reference_cp, NULL); + ECMA_SET_POINTER (ecma_get_object_from_value (obj_value)->prototype_or_outer_reference_cp, NULL); } else { - ECMA_SET_POINTER (ecma_get_object_from_value (obj_val)->prototype_or_outer_reference_cp, + ECMA_SET_POINTER (ecma_get_object_from_value (obj_value)->prototype_or_outer_reference_cp, ecma_get_object_from_value (proto_obj_val)); } @@ -2142,13 +2254,15 @@ jerry_get_object_native_handle (const jerry_value_t obj_val, /**< object to get { jerry_assert_api_available (); - if (!ecma_is_value_object (obj_val)) + jerry_value_t obj_value = jerry_get_arg_value (obj_val); + + if (!ecma_is_value_object (obj_value)) { return false; } ecma_native_pointer_t *native_pointer_p; - native_pointer_p = ecma_get_native_pointer_value (ecma_get_object_from_value (obj_val), + native_pointer_p = ecma_get_native_pointer_value (ecma_get_object_from_value (obj_value), LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE); if (native_pointer_p == NULL) @@ -2181,9 +2295,11 @@ jerry_set_object_native_handle (const jerry_value_t obj_val, /**< object to set { jerry_assert_api_available (); - if (ecma_is_value_object (obj_val)) + jerry_value_t obj_value = jerry_get_arg_value (obj_val); + + if (ecma_is_value_object (obj_value)) { - ecma_object_t *object_p = ecma_get_object_from_value (obj_val); + ecma_object_t *object_p = ecma_get_object_from_value (obj_value); ecma_create_native_handle_property (object_p, (void *) handle_p, @@ -2209,13 +2325,15 @@ jerry_get_object_native_pointer (const jerry_value_t obj_val, /**< object to get { jerry_assert_api_available (); - if (!ecma_is_value_object (obj_val)) + jerry_value_t obj_value = jerry_get_arg_value (obj_val); + + if (!ecma_is_value_object (obj_value)) { return false; } ecma_native_pointer_t *native_pointer_p; - native_pointer_p = ecma_get_native_pointer_value (ecma_get_object_from_value (obj_val), + native_pointer_p = ecma_get_native_pointer_value (ecma_get_object_from_value (obj_value), LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER); if (native_pointer_p == NULL) @@ -2256,9 +2374,11 @@ jerry_set_object_native_pointer (const jerry_value_t obj_val, /**< object to set { jerry_assert_api_available (); - if (ecma_is_value_object (obj_val)) + jerry_value_t obj_value = jerry_get_arg_value (obj_val); + + if (ecma_is_value_object (obj_value)) { - ecma_object_t *object_p = ecma_get_object_from_value (obj_val); + ecma_object_t *object_p = ecma_get_object_from_value (obj_value); ecma_create_native_pointer_property (object_p, native_pointer_p, (void *) native_info_p); } @@ -2280,8 +2400,15 @@ jerry_foreach_object_property (const jerry_value_t obj_val, /**< object value */ { jerry_assert_api_available (); + jerry_value_t obj_value = jerry_get_arg_value (obj_val); + + if (!ecma_is_value_object (obj_value)) + { + return false; + } + ecma_collection_iterator_t names_iter; - ecma_object_t *object_p = ecma_get_object_from_value (obj_val); + ecma_object_t *object_p = ecma_get_object_from_value (obj_value); ecma_collection_header_t *names_p = ecma_op_object_get_property_names (object_p, false, true, true); ecma_collection_iterator_init (&names_iter, names_p); @@ -2311,12 +2438,10 @@ jerry_foreach_object_property (const jerry_value_t obj_val, /**< object value */ return true; } - ecma_free_value (property_value); + ecma_free_value (JERRY_CONTEXT (error_value)); return false; } /* jerry_foreach_object_property */ -#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN - /** * Resolve or reject the promise with an argument. * @@ -2330,9 +2455,10 @@ jerry_resolve_or_reject_promise (jerry_value_t promise, /**< the promise value * { jerry_assert_api_available (); +#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN if (!ecma_is_value_object (promise) || !ecma_is_promise (ecma_get_object_from_value (promise))) { - return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } ecma_string_t str; @@ -2356,9 +2482,14 @@ jerry_resolve_or_reject_promise (jerry_value_t promise, /**< the promise value * ecma_free_value (function); return ret; -} /* jerry_resolve_or_reject_promise */ +#else /* CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */ + JERRY_UNUSED (promise); + JERRY_UNUSED (argument); + JERRY_UNUSED (is_resolve); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Promise not supported."))); #endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */ +} /* jerry_resolve_or_reject_promise */ /** * Validate UTF-8 string diff --git a/jerry-core/debugger/debugger.c b/jerry-core/debugger/debugger.c index 1e8151ed9..48797156c 100644 --- a/jerry-core/debugger/debugger.c +++ b/jerry-core/debugger/debugger.c @@ -164,6 +164,7 @@ jerry_debugger_send_eval (const lit_utf8_byte_t *eval_string_p, /**< evaluated s if (ECMA_IS_VALUE_ERROR (result)) { type = JERRY_DEBUGGER_EVAL_ERROR; + result = JERRY_CONTEXT (error_value); if (ecma_is_value_object (result)) { @@ -980,18 +981,19 @@ jerry_debugger_exception_object_to_string (ecma_value_t exception_obj_value) /** * false - otherwise */ bool -jerry_debugger_send_exception_string (ecma_value_t exception_value) /**< error value */ +jerry_debugger_send_exception_string (void) { ecma_string_t *string_p = NULL; + ecma_value_t exception_value = JERRY_CONTEXT (error_value); + if (ecma_is_value_object (exception_value)) { - ecma_value_t object_value = ecma_get_value_from_error_value (exception_value); + string_p = jerry_debugger_exception_object_to_string (exception_value); - string_p = jerry_debugger_exception_object_to_string (object_value); if (string_p == NULL) { - string_p = ecma_get_string_from_value (ecma_builtin_helper_object_to_string (object_value)); + string_p = ecma_get_string_from_value (ecma_builtin_helper_object_to_string (exception_value)); } } else if (ecma_is_value_string (exception_value)) diff --git a/jerry-core/debugger/debugger.h b/jerry-core/debugger/debugger.h index c59fba74c..e4039405e 100644 --- a/jerry-core/debugger/debugger.h +++ b/jerry-core/debugger/debugger.h @@ -352,7 +352,7 @@ bool jerry_debugger_send_string (uint8_t message_type, uint8_t sub_type, const u bool jerry_debugger_send_function_cp (jerry_debugger_header_type_t type, ecma_compiled_code_t *compiled_code_p); bool jerry_debugger_send_parse_function (uint32_t line, uint32_t column); void jerry_debugger_send_memstats (void); -bool jerry_debugger_send_exception_string (ecma_value_t exception_value); +bool jerry_debugger_send_exception_string (void); #endif /* JERRY_DEBUGGER */ diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index f386b173c..28a85eb77 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -69,11 +69,12 @@ typedef enum */ typedef enum { - ECMA_TYPE_DIRECT, /**< directly encoded value, a 28 bit signed integer or a simple value */ - ECMA_TYPE_FLOAT, /**< pointer to a 64 or 32 bit floating point number */ - ECMA_TYPE_STRING, /**< pointer to description of a string */ - ECMA_TYPE_OBJECT, /**< pointer to description of an object */ - ECMA_TYPE___MAX = ECMA_TYPE_OBJECT /** highest value for ecma types */ + ECMA_TYPE_DIRECT = 0, /**< directly encoded value, a 28 bit signed integer or a simple value */ + ECMA_TYPE_FLOAT = 1, /**< pointer to a 64 or 32 bit floating point number */ + ECMA_TYPE_STRING = 2, /**< pointer to description of a string */ + ECMA_TYPE_OBJECT = 3, /**< pointer to description of an object */ + ECMA_TYPE_ERROR = 7, /**< pointer to description of an error reference */ + ECMA_TYPE___MAX = ECMA_TYPE_ERROR /** highest value for ecma types */ } ecma_type_t; /** @@ -88,11 +89,12 @@ typedef enum * - special register or stack values for vm */ ECMA_SIMPLE_VALUE_EMPTY, /**< uninitialized value */ - ECMA_SIMPLE_VALUE_ARRAY_HOLE, /**< array hole, used for initialization of an array literal */ + ECMA_SIMPLE_VALUE_ERROR, /**< an error is currently thrown */ ECMA_SIMPLE_VALUE_FALSE, /**< boolean false */ ECMA_SIMPLE_VALUE_TRUE, /**< boolean true */ ECMA_SIMPLE_VALUE_UNDEFINED, /**< undefined value */ ECMA_SIMPLE_VALUE_NULL, /**< null value */ + ECMA_SIMPLE_VALUE_ARRAY_HOLE, /**< array hole, used for initialization of an array literal */ ECMA_SIMPLE_VALUE_NOT_FOUND, /**< a special value returned by ecma_op_object_find */ ECMA_SIMPLE_VALUE_REGISTER_REF, /**< register reference, a special "base" value for vm */ ECMA_SIMPLE_VALUE__COUNT /** count of simple ecma values */ @@ -122,12 +124,7 @@ typedef int32_t ecma_integer_value_t; /** * Mask for ecma types in ecma_type_t */ -#define ECMA_VALUE_TYPE_MASK 0x3u - -/** - * Error flag in ecma_type_t - */ -#define ECMA_VALUE_ERROR_FLAG 0x4u +#define ECMA_VALUE_TYPE_MASK 0x7u /** * Shift for value part in ecma_type_t @@ -199,7 +196,7 @@ typedef int32_t ecma_integer_value_t; * Checks whether the error flag is set. */ #define ECMA_IS_VALUE_ERROR(value) \ - (unlikely ((value & ECMA_VALUE_ERROR_FLAG) != 0)) + (unlikely ((value) == ecma_make_simple_value (ECMA_SIMPLE_VALUE_ERROR))) /** * Representation for native external pointer @@ -1139,6 +1136,15 @@ typedef struct lit_utf8_size_t long_utf8_string_length; /**< length of this long utf-8 string in bytes */ } ecma_long_string_t; +/** + * Representation of a thrown value on API level. + */ +typedef struct +{ + uint32_t refs; /**< reference counter */ + ecma_value_t value; /**< referenced value */ +} ecma_error_reference_t; + /** * Compiled byte code data. */ diff --git a/jerry-core/ecma/base/ecma-helpers-value.c b/jerry-core/ecma/base/ecma-helpers-value.c index a6626d8ed..5ae429390 100644 --- a/jerry-core/ecma/base/ecma-helpers-value.c +++ b/jerry-core/ecma/base/ecma-helpers-value.c @@ -28,15 +28,10 @@ * @{ */ -/** - * Masking the type and flags - */ -#define ECMA_VALUE_FULL_MASK (ECMA_VALUE_TYPE_MASK | ECMA_VALUE_ERROR_FLAG) - JERRY_STATIC_ASSERT (ECMA_TYPE___MAX <= ECMA_VALUE_TYPE_MASK, ecma_types_must_be_less_than_mask); -JERRY_STATIC_ASSERT ((ECMA_VALUE_FULL_MASK + 1) == (1 << ECMA_VALUE_SHIFT), +JERRY_STATIC_ASSERT ((ECMA_VALUE_TYPE_MASK + 1) == (1 << ECMA_VALUE_SHIFT), ecma_value_part_must_start_after_flags); JERRY_STATIC_ASSERT (ECMA_VALUE_SHIFT <= JMEM_ALIGNMENT_LOG, @@ -83,7 +78,7 @@ ecma_pointer_to_ecma_value (const void *ptr) /**< pointer */ #ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY uintptr_t uint_ptr = (uintptr_t) ptr; - JERRY_ASSERT ((uint_ptr & ECMA_VALUE_FULL_MASK) == 0); + JERRY_ASSERT ((uint_ptr & ECMA_VALUE_TYPE_MASK) == 0); return (ecma_value_t) uint_ptr; #else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ @@ -104,7 +99,7 @@ static inline void * __attr_pure___ __attr_always_inline___ ecma_get_pointer_from_ecma_value (ecma_value_t value) /**< value */ { #ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY - return (void *) (uintptr_t) ((value) & ~ECMA_VALUE_FULL_MASK); + return (void *) (uintptr_t) ((value) & ~ECMA_VALUE_TYPE_MASK); #else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ return ECMA_GET_NON_NULL_POINTER (ecma_number_t, value >> ECMA_VALUE_SHIFT); @@ -145,7 +140,7 @@ static inline bool __attr_const___ __attr_always_inline___ ecma_is_value_equal_to_simple_value (ecma_value_t value, /**< ecma value */ ecma_simple_value_t simple_value) /**< simple value */ { - return (value | ECMA_VALUE_ERROR_FLAG) == (ecma_make_simple_value (simple_value) | ECMA_VALUE_ERROR_FLAG); + return value == ecma_make_simple_value (simple_value); } /* ecma_is_value_equal_to_simple_value */ /** @@ -321,6 +316,18 @@ ecma_is_value_object (ecma_value_t value) /**< ecma value */ return (ecma_get_value_type_field (value) == ECMA_TYPE_OBJECT); } /* ecma_is_value_object */ +/** + * Check if the value is error reference. + * + * @return true - if the value contains object value, + * false - otherwise + */ +inline bool __attr_const___ __attr_always_inline___ +ecma_is_value_error_reference (ecma_value_t value) /**< ecma value */ +{ + return (ecma_get_value_type_field (value) == ECMA_TYPE_ERROR); +} /* ecma_is_value_error_reference */ + /** * Debug assertion that specified value's type is one of ECMA-defined * script-visible types, i.e.: undefined, null, boolean, number, string, object. @@ -485,7 +492,7 @@ ecma_make_uint32_value (uint32_t uint32_number) /**< uint32 number to be encoded /** * String value constructor */ -ecma_value_t __attr_pure___ +inline ecma_value_t __attr_pure___ __attr_always_inline___ ecma_make_string_value (const ecma_string_t *ecma_string_p) /**< string to reference in value */ { JERRY_ASSERT (ecma_string_p != NULL); @@ -496,7 +503,7 @@ ecma_make_string_value (const ecma_string_t *ecma_string_p) /**< string to refer /** * Object value constructor */ -ecma_value_t __attr_pure___ +inline ecma_value_t __attr_pure___ __attr_always_inline___ ecma_make_object_value (const ecma_object_t *object_p) /**< object to reference in value */ { JERRY_ASSERT (object_p != NULL); @@ -505,25 +512,15 @@ ecma_make_object_value (const ecma_object_t *object_p) /**< object to reference } /* ecma_make_object_value */ /** - * Error value constructor + * Error reference constructor */ -ecma_value_t __attr_const___ -ecma_make_error_value (ecma_value_t value) /**< original ecma value */ +inline ecma_value_t __attr_pure___ __attr_always_inline___ +ecma_make_error_reference_value (const ecma_error_reference_t *error_ref_p) /**< error reference */ { - /* Error values cannot be converted. */ - JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (value)); + JERRY_ASSERT (error_ref_p != NULL); - return value | ECMA_VALUE_ERROR_FLAG; -} /* ecma_make_error_value */ - -/** - * Error value constructor - */ -ecma_value_t __attr_pure___ -ecma_make_error_obj_value (const ecma_object_t *object_p) /**< object to reference in value */ -{ - return ecma_make_error_value (ecma_make_object_value (object_p)); -} /* ecma_make_error_obj_value */ + return ecma_pointer_to_ecma_value (error_ref_p) | ECMA_TYPE_ERROR; +} /* ecma_make_error_reference_value */ /** * Get integer value from an integer ecma value @@ -588,6 +585,19 @@ ecma_get_object_from_value (ecma_value_t value) /**< ecma value */ return (ecma_object_t *) ecma_get_pointer_from_ecma_value (value); } /* ecma_get_object_from_value */ +/** + * Get pointer to error reference from ecma value + * + * @return the pointer + */ +inline ecma_error_reference_t *__attr_pure___ __attr_always_inline___ +ecma_get_error_reference_from_value (ecma_value_t value) /**< ecma value */ +{ + JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_ERROR); + + return (ecma_error_reference_t *) ecma_get_pointer_from_ecma_value (value); +} /* ecma_get_error_reference_from_value */ + /** * Invert a boolean value * @@ -601,23 +611,6 @@ ecma_invert_boolean_value (ecma_value_t value) /**< ecma value */ return (value ^ (1 << ECMA_DIRECT_SHIFT)); } /* ecma_invert_boolean_value */ -/** - * Get the value from an error ecma value - * - * @return ecma value - */ -ecma_value_t __attr_const___ -ecma_get_value_from_error_value (ecma_value_t value) /**< ecma value */ -{ - JERRY_ASSERT (ECMA_IS_VALUE_ERROR (value)); - - value = (ecma_value_t) (value & ~ECMA_VALUE_ERROR_FLAG); - - JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (value)); - - return value; -} /* ecma_get_value_from_error_value */ - /** * Copy ecma value. * @@ -648,9 +641,12 @@ ecma_copy_value (ecma_value_t value) /**< value description */ ecma_ref_object (ecma_get_object_from_value (value)); return value; } + default: + { + JERRY_UNREACHABLE (); + return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); + } } - - JERRY_UNREACHABLE (); } /* ecma_copy_value */ /** @@ -840,6 +836,12 @@ ecma_free_value (ecma_value_t value) /**< value description */ ecma_deref_object (ecma_get_object_from_value (value)); break; } + + default: + { + JERRY_UNREACHABLE (); + break; + } } } /* ecma_free_value */ diff --git a/jerry-core/ecma/base/ecma-helpers.c b/jerry-core/ecma/base/ecma-helpers.c index 22fc27e5e..8ca331c44 100644 --- a/jerry-core/ecma/base/ecma-helpers.c +++ b/jerry-core/ecma/base/ecma-helpers.c @@ -1320,6 +1320,103 @@ ecma_free_property_descriptor (ecma_property_descriptor_t *prop_desc_p) /**< pro *prop_desc_p = ecma_make_empty_property_descriptor (); } /* ecma_free_property_descriptor */ +/** + * The size of error reference must be 8 bytes to use jmem_pools_alloc(). + */ +JERRY_STATIC_ASSERT (sizeof (ecma_error_reference_t) == 8, + ecma_error_reference_size_must_be_8_bytes); + +/** + * Create an error reference from a given value. + * + * Note: + * Reference of the value is taken. + * + * @return error reference value + */ +ecma_value_t +ecma_create_error_reference (ecma_value_t value) /**< referenced value */ +{ + ecma_error_reference_t *error_ref_p = (ecma_error_reference_t *) jmem_pools_alloc (sizeof (ecma_error_reference_t)); + + error_ref_p->refs = 1; + error_ref_p->value = value; + return ecma_make_error_reference_value (error_ref_p); +} /* ecma_create_error_reference */ + +/** + * Create an error reference from a given object. + * + * Note: + * Reference of the value is taken. + * + * @return error reference value + */ +inline ecma_value_t __attr_always_inline___ +ecma_create_error_object_reference (ecma_object_t *object_p) /**< referenced object */ +{ + return ecma_create_error_reference (ecma_make_object_value (object_p)); +} /* ecma_create_error_object_reference */ + +/** + * Increase ref count of an error reference. + */ +void +ecma_ref_error_reference (ecma_error_reference_t *error_ref_p) /**< error reference */ +{ + if (likely (error_ref_p->refs < UINT32_MAX)) + { + error_ref_p->refs++; + } + else + { + jerry_fatal (ERR_REF_COUNT_LIMIT); + } +} /* ecma_ref_error_reference */ + +/** + * Decrease ref count of an error reference. + */ +void +ecma_deref_error_reference (ecma_error_reference_t *error_ref_p) /**< error reference */ +{ + JERRY_ASSERT (error_ref_p->refs > 0); + + error_ref_p->refs--; + + if (error_ref_p->refs == 0) + { + ecma_free_value (error_ref_p->value); + jmem_pools_free (error_ref_p, sizeof (ecma_error_reference_t)); + } +} /* ecma_deref_error_reference */ + +/** + * Clears error reference, and returns with the value. + * + * @return value referenced by the error + */ +ecma_value_t +ecma_clear_error_reference (ecma_value_t value) +{ + ecma_error_reference_t *error_ref_p = ecma_get_error_reference_from_value (value); + + JERRY_ASSERT (error_ref_p->refs > 0); + + ecma_value_t referenced_value = error_ref_p->value; + + if (error_ref_p->refs > 1) + { + error_ref_p->refs--; + } + else + { + jmem_pools_free (error_ref_p, sizeof (ecma_error_reference_t)); + } + + return referenced_value; +} /* ecma_clear_error_reference */ + /** * Increase reference counter of Compact * Byte Code or regexp byte code. diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index 35cbbdd41..b8aa14e2a 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -128,6 +128,7 @@ bool ecma_is_value_float_number (ecma_value_t value) __attr_const___; bool ecma_is_value_number (ecma_value_t value) __attr_const___; bool ecma_is_value_string (ecma_value_t value) __attr_const___; bool ecma_is_value_object (ecma_value_t value) __attr_const___; +bool ecma_is_value_error_reference (ecma_value_t value) __attr_const___; void ecma_check_value_type_is_spec_defined (ecma_value_t value); @@ -140,14 +141,13 @@ ecma_value_t ecma_make_int32_value (int32_t int32_number); ecma_value_t ecma_make_uint32_value (uint32_t uint32_number); ecma_value_t ecma_make_string_value (const ecma_string_t *ecma_string_p) __attr_pure___; ecma_value_t ecma_make_object_value (const ecma_object_t *object_p) __attr_pure___; -ecma_value_t ecma_make_error_value (ecma_value_t value) __attr_const___; -ecma_value_t ecma_make_error_obj_value (const ecma_object_t *object_p) __attr_pure___; +ecma_value_t ecma_make_error_reference_value (const ecma_error_reference_t *error_ref_p) __attr_pure___; ecma_integer_value_t ecma_get_integer_from_value (ecma_value_t value) __attr_const___; ecma_number_t ecma_get_float_from_value (ecma_value_t value) __attr_pure___; ecma_number_t ecma_get_number_from_value (ecma_value_t value) __attr_pure___; ecma_string_t *ecma_get_string_from_value (ecma_value_t value) __attr_pure___; ecma_object_t *ecma_get_object_from_value (ecma_value_t value) __attr_pure___; -ecma_value_t ecma_get_value_from_error_value (ecma_value_t value) __attr_const___; +ecma_error_reference_t *ecma_get_error_reference_from_value (ecma_value_t value) __attr_pure___; ecma_value_t ecma_invert_boolean_value (ecma_value_t value) __attr_const___; ecma_value_t ecma_copy_value (ecma_value_t value); ecma_value_t ecma_fast_copy_value (ecma_value_t value); @@ -339,7 +339,11 @@ void ecma_set_property_lcached (ecma_property_t *property_p, bool is_lcached); ecma_property_descriptor_t ecma_make_empty_property_descriptor (void); void ecma_free_property_descriptor (ecma_property_descriptor_t *prop_desc_p); -ecma_property_t *ecma_get_next_property_pair (ecma_property_pair_t *); +ecma_value_t ecma_create_error_reference (ecma_value_t value); +ecma_value_t ecma_create_error_object_reference (ecma_object_t *object_p); +void ecma_ref_error_reference (ecma_error_reference_t *error_ref_p); +void ecma_deref_error_reference (ecma_error_reference_t *error_ref_p); +ecma_value_t ecma_clear_error_reference (ecma_value_t value); void ecma_bytecode_ref (ecma_compiled_code_t *bytecode_p); void ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-promise.c b/jerry-core/ecma/builtin-objects/ecma-builtin-promise.c index 3438bde28..6e34e5a8e 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-promise.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-promise.c @@ -20,6 +20,7 @@ #include "ecma-globals.h" #include "ecma-number-object.h" #include "ecma-promise-object.h" +#include "jcontext.h" #ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN @@ -124,10 +125,9 @@ ecma_builtin_promise_reject_or_resolve (ecma_value_t this_arg, /**< "this" argum * Returned value must be freed with ecma_free_value. */ inline static ecma_value_t -ecma_builtin_promise_reject_abrupt (ecma_value_t abrupt_value, - ecma_value_t capability) +ecma_builtin_promise_reject_abrupt (ecma_value_t capability) /**< reject description */ { - ecma_value_t reason = ecma_get_value_from_error_value (abrupt_value); + ecma_value_t reason = JERRY_CONTEXT (error_value); ecma_string_t *str_reject = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_REJECT); ecma_value_t reject = ecma_op_object_get (ecma_get_object_from_value (capability), str_reject); ecma_deref_ecma_string (str_reject); @@ -590,9 +590,9 @@ ecma_builtin_promise_race_or_all (ecma_value_t this_arg, /**< 'this' argument */ if (!ecma_is_value_object (array) || ecma_get_object_type (ecma_get_object_from_value (array)) != ECMA_OBJECT_TYPE_ARRAY) { - ecma_value_t error = ecma_raise_type_error (ECMA_ERR_MSG ("Second argument is not an array.")); - ret = ecma_builtin_promise_reject_abrupt (error, capability); - ecma_free_value (error); + ecma_raise_type_error (ECMA_ERR_MSG ("Second argument is not an array.")); + ret = ecma_builtin_promise_reject_abrupt (capability); + ecma_free_value (JERRY_CONTEXT (error_value)); ecma_free_value (capability); return ret; @@ -609,7 +609,7 @@ ecma_builtin_promise_race_or_all (ecma_value_t this_arg, /**< 'this' argument */ if (ECMA_IS_VALUE_ERROR (ret)) { - ret = ecma_get_value_from_error_value (ret); + ret = JERRY_CONTEXT (error_value); } ecma_free_value (capability); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c index dc9361e72..9b2b81adf 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c @@ -26,6 +26,7 @@ #include "ecma-objects.h" #include "ecma-string-object.h" #include "ecma-try-catch-macro.h" +#include "jcontext.h" #include "jrt.h" #include "jrt-libc-includes.h" #include "lit-char-helpers.h" @@ -1593,6 +1594,11 @@ ecma_builtin_string_prototype_object_split (ecma_value_t this_arg, /**< this arg match_result = ecma_regexp_exec_helper (regexp_value, ecma_make_string_value (substr_str_p), true); should_return = !ecma_is_value_null (match_result); + if (ECMA_IS_VALUE_ERROR (match_result)) + { + match_result = JERRY_CONTEXT (error_value); + } + ecma_deref_ecma_string (substr_str_p); ecma_free_value (match_result); #else @@ -1684,6 +1690,10 @@ ecma_builtin_string_prototype_object_split (ecma_value_t this_arg, /**< this arg if (ecma_is_value_null (match_result) || ECMA_IS_VALUE_ERROR (match_result)) { curr_pos++; + if (ECMA_IS_VALUE_ERROR (match_result)) + { + ecma_free_value (JERRY_CONTEXT (error_value)); + } } else { diff --git a/jerry-core/ecma/operations/ecma-exceptions.c b/jerry-core/ecma/operations/ecma-exceptions.c index 872f922e6..7da098c5b 100644 --- a/jerry-core/ecma/operations/ecma-exceptions.c +++ b/jerry-core/ecma/operations/ecma-exceptions.c @@ -21,6 +21,7 @@ #include "ecma-globals.h" #include "ecma-helpers.h" #include "ecma-objects.h" +#include "jcontext.h" #include "jrt.h" /** \addtogroup ecma ECMA @@ -155,7 +156,8 @@ ecma_raise_standard_error (ecma_standard_error_t error_type, /**< error type */ error_obj_p = ecma_new_standard_error (error_type); } - return ecma_make_error_obj_value (error_obj_p); + JERRY_CONTEXT (error_value) = ecma_make_object_value (error_obj_p); + return ecma_make_simple_value (ECMA_SIMPLE_VALUE_ERROR); } /* ecma_raise_standard_error */ #ifdef JERRY_ENABLE_ERROR_MESSAGES @@ -242,7 +244,9 @@ ecma_raise_standard_error_with_format (ecma_standard_error_t error_type, /**< er ecma_object_t *error_obj_p = ecma_new_standard_error_with_message (error_type, error_msg_p); ecma_deref_ecma_string (error_msg_p); - return ecma_make_error_obj_value (error_obj_p); + + JERRY_CONTEXT (error_value) = ecma_make_object_value (error_obj_p); + return ecma_make_simple_value (ECMA_SIMPLE_VALUE_ERROR); } /* ecma_raise_standard_error_with_format */ #endif /* JERRY_ENABLE_ERROR_MESSAGES */ diff --git a/jerry-core/ecma/operations/ecma-function-object.c b/jerry-core/ecma/operations/ecma-function-object.c index 9af402ea0..2fb7fe851 100644 --- a/jerry-core/ecma/operations/ecma-function-object.c +++ b/jerry-core/ecma/operations/ecma-function-object.c @@ -468,6 +468,12 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */ this_arg_value, arguments_list_p, arguments_list_len); + + if (unlikely (ecma_is_value_error_reference (ret_value))) + { + JERRY_CONTEXT (error_value) = ecma_clear_error_reference (ret_value); + ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_ERROR); + } } else { diff --git a/jerry-core/ecma/operations/ecma-jobqueue.c b/jerry-core/ecma/operations/ecma-jobqueue.c index f7bbcbd4e..05a88ad47 100644 --- a/jerry-core/ecma/operations/ecma-jobqueue.c +++ b/jerry-core/ecma/operations/ecma-jobqueue.c @@ -179,7 +179,7 @@ ecma_process_promise_reaction_job (void *obj_p) /**< the job to be operated */ { if (ECMA_IS_VALUE_ERROR (handler_result)) { - handler_result = ecma_get_value_from_error_value (handler_result); + handler_result = JERRY_CONTEXT (error_value); } /* 7. */ diff --git a/jerry-core/ecma/operations/ecma-promise-object.c b/jerry-core/ecma/operations/ecma-promise-object.c index 990488596..ac22b4ed1 100644 --- a/jerry-core/ecma/operations/ecma-promise-object.c +++ b/jerry-core/ecma/operations/ecma-promise-object.c @@ -24,6 +24,7 @@ #include "ecma-objects.h" #include "ecma-objects-general.h" #include "ecma-promise-object.h" +#include "jcontext.h" #ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN @@ -547,7 +548,7 @@ ecma_op_create_promise_object (ecma_value_t executor, /**< the executor function if (ECMA_IS_VALUE_ERROR (completion)) { /* 10.a. */ - completion = ecma_get_value_from_error_value (completion); + completion = JERRY_CONTEXT (error_value); status = ecma_op_function_call (ecma_get_object_from_value (funcs->reject), ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED), &completion, diff --git a/jerry-core/jcontext/jcontext.h b/jerry-core/jcontext/jcontext.h index ac4a32c46..72e58a1ff 100644 --- a/jerry-core/jcontext/jcontext.h +++ b/jerry-core/jcontext/jcontext.h @@ -81,6 +81,7 @@ typedef struct size_t jmem_heap_allocated_size; /**< size of allocated regions */ size_t jmem_heap_limit; /**< current limit of heap usage, that is upon being reached, * causes call of "try give memory back" callbacks */ + ecma_value_t error_value; /**< currently thrown error value */ uint32_t lit_magic_string_ex_count; /**< external magic strings count */ uint32_t jerry_init_flags; /**< run-time configuration flags */ uint8_t is_direct_eval_form_call; /**< direct call from eval */ diff --git a/jerry-core/parser/js/js-parser.c b/jerry-core/parser/js/js-parser.c index 740af1467..28fd3a83f 100644 --- a/jerry-core/parser/js/js-parser.c +++ b/jerry-core/parser/js/js-parser.c @@ -2721,7 +2721,8 @@ parser_parse_script (const uint8_t *arg_list_p, /**< function argument list */ { /* It is unlikely that memory can be allocated in an out-of-memory * situation. However, a simple value can still be thrown. */ - return ecma_make_error_value (ecma_make_simple_value (ECMA_SIMPLE_VALUE_NULL)); + JERRY_CONTEXT (error_value) = ecma_make_simple_value (ECMA_SIMPLE_VALUE_NULL); + return ecma_make_simple_value (ECMA_SIMPLE_VALUE_ERROR); } #ifdef JERRY_ENABLE_ERROR_MESSAGES const lit_utf8_byte_t *err_bytes_p = (const lit_utf8_byte_t *) parser_error_to_string (parser_error.error); diff --git a/jerry-core/vm/opcodes-ecma-bitwise.c b/jerry-core/vm/opcodes-ecma-bitwise.c index 237551860..1b368529d 100644 --- a/jerry-core/vm/opcodes-ecma-bitwise.c +++ b/jerry-core/vm/opcodes-ecma-bitwise.c @@ -44,8 +44,8 @@ do_number_bitwise_logic (number_bitwise_logic_op op, /**< number bitwise logic o { JERRY_STATIC_ASSERT (ECMA_DIRECT_TYPE_INTEGER_VALUE == 0, ecma_direct_type_integer_value_must_be_zero_for_bitwise_logic); - JERRY_STATIC_ASSERT ((ECMA_DIRECT_TYPE_MASK | ECMA_VALUE_ERROR_FLAG) == ((1 << ECMA_DIRECT_SHIFT) - 1), - direct_type_mask_and_error_flag_must_fill_all_bits_before_the_value_starts); + JERRY_STATIC_ASSERT (ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1), + direct_type_mask_must_fill_all_bits_before_the_value_starts); JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index 87822c4e3..cef5f1df0 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -679,7 +679,15 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ name_p, is_strict, lit_value); - ecma_free_value (put_value_result); + + JERRY_ASSERT (ecma_is_value_boolean (put_value_result) + || ecma_is_value_empty (put_value_result) + || ECMA_IS_VALUE_ERROR (put_value_result)); + + if (ECMA_IS_VALUE_ERROR (put_value_result)) + { + ecma_free_value (JERRY_CONTEXT (error_value)); + } } if (value_index >= register_end) @@ -882,10 +890,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ { JERRY_CONTEXT (vm_exec_stop_counter) = 1; - if (!ECMA_IS_VALUE_ERROR (result)) + if (!ecma_is_value_error_reference (result)) { - result = ecma_make_error_value (result); + JERRY_CONTEXT (error_value) = result; } + else + { + JERRY_CONTEXT (error_value) = ecma_clear_error_reference (result); + } + result = ecma_make_simple_value (ECMA_SIMPLE_VALUE_ERROR); goto error; } } @@ -1399,7 +1412,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } case VM_OC_THROW: { - result = ecma_make_error_value (left_value); + JERRY_CONTEXT (error_value) = left_value; + result = ecma_make_simple_value (ECMA_SIMPLE_VALUE_ERROR); left_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); goto error; } @@ -2322,11 +2336,12 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } case VM_CONTEXT_FINALLY_THROW: { - result = stack_top_p[-2]; + JERRY_CONTEXT (error_value) = stack_top_p[-2]; VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION); stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION; + result = ecma_make_simple_value (ECMA_SIMPLE_VALUE_ERROR); goto error; } case VM_CONTEXT_FINALLY_RETURN: @@ -2567,7 +2582,7 @@ error: && !(frame_ctx_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_DEBUGGER_IGNORE) && !(JERRY_CONTEXT (debugger_flags) & (JERRY_DEBUGGER_VM_IGNORE_EXCEPTION | JERRY_DEBUGGER_VM_IGNORE))) { - if (jerry_debugger_send_exception_string (result)) + if (jerry_debugger_send_exception_string ()) { jerry_debugger_breakpoint_hit (JERRY_DEBUGGER_EXCEPTION_HIT); } @@ -2621,7 +2636,7 @@ error: ecma_object_t *catch_env_p; ecma_string_t *catch_name_p; - *stack_top_p++ = ecma_get_value_from_error_value (result); + *stack_top_p++ = JERRY_CONTEXT (error_value); JERRY_ASSERT (byte_code_p[0] == CBC_ASSIGN_SET_IDENT); @@ -2644,7 +2659,7 @@ error: else { JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FINALLY_THROW); - stack_top_p[-2] = result; + stack_top_p[-2] = JERRY_CONTEXT (error_value); } #ifdef JERRY_VM_EXEC_STOP @@ -2664,10 +2679,15 @@ error: left_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); right_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); - if (!ECMA_IS_VALUE_ERROR (result)) + if (!ecma_is_value_error_reference (result)) { - result = ecma_make_error_value (result); + JERRY_CONTEXT (error_value) = result; } + else + { + JERRY_CONTEXT (error_value) = ecma_clear_error_reference (result); + } + result = ecma_make_simple_value (ECMA_SIMPLE_VALUE_ERROR); goto error; } } diff --git a/jerry-main/main-unix.c b/jerry-main/main-unix.c index 65dd5ff58..e1590d007 100644 --- a/jerry-main/main-unix.c +++ b/jerry-main/main-unix.c @@ -133,9 +133,8 @@ jerry_value_is_syntax_error (jerry_value_t error_value) /**< error value */ static void print_unhandled_exception (jerry_value_t error_value) /**< error value */ { - assert (jerry_value_has_error_flag (error_value)); + assert (!jerry_value_has_error_flag (error_value)); - jerry_value_clear_error_flag (&error_value); jerry_value_t err_str_val = jerry_value_to_string (error_value); jerry_size_t err_str_size = jerry_get_string_size (err_str_val); jerry_char_t err_str_buf[256]; @@ -262,6 +261,7 @@ register_js_function (const char *name_p, /**< name of the function */ if (jerry_value_has_error_flag (result_val)) { jerry_port_log (JERRY_LOG_LEVEL_WARNING, "Warning: failed to register '%s' method.", name_p); + jerry_value_clear_error_flag (&result_val); print_unhandled_exception (result_val); } @@ -870,11 +870,13 @@ main (int argc, if (jerry_value_has_error_flag (ret_val_eval)) { + jerry_value_clear_error_flag (&ret_val_eval); print_unhandled_exception (ret_val_eval); } } else { + jerry_value_clear_error_flag (&ret_val_eval); print_unhandled_exception (ret_val_eval); } @@ -887,6 +889,7 @@ main (int argc, if (jerry_value_has_error_flag (ret_value)) { + jerry_value_clear_error_flag (&ret_value); print_unhandled_exception (ret_value); ret_code = JERRY_STANDALONE_EXIT_CODE_FAIL; @@ -898,6 +901,7 @@ main (int argc, if (jerry_value_has_error_flag (ret_value)) { + jerry_value_clear_error_flag (&ret_value); print_unhandled_exception (ret_value); ret_code = JERRY_STANDALONE_EXIT_CODE_FAIL; }