mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Improve error messages (#1577)
JerryScript-DCO-1.0-Signed-off-by: Yanhui Shen shen.elf@gmail.com
This commit is contained in:
parent
319702cdd2
commit
a2a160d6f9
@ -13,7 +13,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "ecma-builtins.h"
|
||||
#include "ecma-conversion.h"
|
||||
#include "ecma-exceptions.h"
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-globals.h"
|
||||
@ -156,6 +158,95 @@ ecma_raise_standard_error (ecma_standard_error_t error_type, /**< error type */
|
||||
return ecma_make_error_obj_value (error_obj_p);
|
||||
} /* ecma_raise_standard_error */
|
||||
|
||||
#ifdef JERRY_ENABLE_ERROR_MESSAGES
|
||||
|
||||
/**
|
||||
* Raise a standard ecma-error with the given format string and arguments.
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_raise_standard_error_with_format (ecma_standard_error_t error_type, /**< error type */
|
||||
const char *format, /**< format string */
|
||||
...) /**< ecma-values */
|
||||
{
|
||||
JERRY_ASSERT (format != NULL);
|
||||
|
||||
ecma_string_t *error_msg_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY);
|
||||
ecma_string_t *string1_p;
|
||||
ecma_string_t *string2_p;
|
||||
|
||||
const char *start_p = format;
|
||||
const char *end_p = format;
|
||||
|
||||
va_list args;
|
||||
|
||||
va_start (args, format);
|
||||
|
||||
while (*end_p)
|
||||
{
|
||||
if (*end_p == '%')
|
||||
{
|
||||
/* Concat template string. */
|
||||
if (end_p > start_p)
|
||||
{
|
||||
string1_p = error_msg_p;
|
||||
string2_p = ecma_new_ecma_string_from_utf8 ((const lit_utf8_byte_t *) start_p,
|
||||
(lit_utf8_size_t) (end_p - start_p));
|
||||
error_msg_p = ecma_concat_ecma_strings (string1_p, string2_p);
|
||||
ecma_deref_ecma_string (string1_p);
|
||||
ecma_deref_ecma_string (string2_p);
|
||||
}
|
||||
|
||||
/* Convert an argument to string without side effects. */
|
||||
ecma_string_t *arg_string_p;
|
||||
const ecma_value_t arg_val = va_arg (args, ecma_value_t);
|
||||
if (unlikely (ecma_is_value_object (arg_val)))
|
||||
{
|
||||
ecma_object_t *arg_object_p = ecma_get_object_from_value (arg_val);
|
||||
lit_magic_string_id_t class_name = ecma_object_get_class_name (arg_object_p);
|
||||
arg_string_p = ecma_get_magic_string (class_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
jerry_value_t str_val = ecma_op_to_string (arg_val);
|
||||
arg_string_p = ecma_get_string_from_value (str_val);
|
||||
}
|
||||
|
||||
/* Concat argument. */
|
||||
string1_p = error_msg_p;
|
||||
string2_p = arg_string_p;
|
||||
error_msg_p = ecma_concat_ecma_strings (string1_p, string2_p);
|
||||
ecma_deref_ecma_string (string1_p);
|
||||
ecma_deref_ecma_string (string2_p);
|
||||
|
||||
start_p = end_p + 1;
|
||||
}
|
||||
|
||||
end_p++;
|
||||
}
|
||||
|
||||
va_end (args);
|
||||
|
||||
/* Concat reset of template string. */
|
||||
if (start_p < end_p)
|
||||
{
|
||||
string1_p = error_msg_p;
|
||||
string2_p = ecma_new_ecma_string_from_utf8 ((const lit_utf8_byte_t *) start_p,
|
||||
(lit_utf8_size_t) (end_p - start_p));
|
||||
error_msg_p = ecma_concat_ecma_strings (string1_p, string2_p);
|
||||
ecma_deref_ecma_string (string1_p);
|
||||
ecma_deref_ecma_string (string2_p);
|
||||
}
|
||||
|
||||
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);
|
||||
} /* ecma_raise_standard_error_with_format */
|
||||
|
||||
#endif /* JERRY_ENABLE_ERROR_MESSAGES */
|
||||
|
||||
/**
|
||||
* Raise a common error with the given message.
|
||||
*
|
||||
|
||||
@ -51,6 +51,9 @@ typedef enum
|
||||
ecma_object_t *ecma_new_standard_error (ecma_standard_error_t error_type);
|
||||
ecma_object_t *ecma_new_standard_error_with_message (ecma_standard_error_t error_type, ecma_string_t *message_string_p);
|
||||
ecma_value_t ecma_raise_standard_error (ecma_standard_error_t error_type, const lit_utf8_byte_t *msg_p);
|
||||
#ifdef JERRY_ENABLE_ERROR_MESSAGES
|
||||
ecma_value_t ecma_raise_standard_error_with_format (ecma_standard_error_t error_type, const char *msg_p, ...);
|
||||
#endif /* JERRY_ENABLE_ERROR_MESSAGES */
|
||||
ecma_value_t ecma_raise_common_error (const char *msg_p);
|
||||
ecma_value_t ecma_raise_eval_error (const char *msg_p);
|
||||
ecma_value_t ecma_raise_range_error (const char *msg_p);
|
||||
|
||||
@ -52,7 +52,15 @@ ecma_op_get_value_lex_env_base (ecma_object_t *ref_base_lex_env_p, /**< referenc
|
||||
/* 3. */
|
||||
if (unlikely (is_unresolvable_reference))
|
||||
{
|
||||
return ecma_raise_reference_error (ECMA_ERR_MSG ("Cannot resolve reference."));
|
||||
#ifdef JERRY_ENABLE_ERROR_MESSAGES
|
||||
ecma_value_t var_name_val = ecma_make_string_value (var_name_string_p);
|
||||
ecma_value_t error_value = ecma_raise_standard_error_with_format (ECMA_ERROR_REFERENCE,
|
||||
"% is not defined",
|
||||
var_name_val);
|
||||
#else /* !JERRY_ENABLE_ERROR_MESSAGES */
|
||||
ecma_value_t error_value = ecma_raise_reference_error (NULL);
|
||||
#endif /* JERRY_ENABLE_ERROR_MESSAGES */
|
||||
return error_value;
|
||||
}
|
||||
|
||||
/* 5. */
|
||||
@ -149,7 +157,15 @@ ecma_op_put_value_lex_env_base (ecma_object_t *ref_base_lex_env_p, /**< referenc
|
||||
/* 3.a. */
|
||||
if (is_strict)
|
||||
{
|
||||
return ecma_raise_reference_error (ECMA_ERR_MSG ("Cannot resolve reference."));
|
||||
#ifdef JERRY_ENABLE_ERROR_MESSAGES
|
||||
ecma_value_t var_name_val = ecma_make_string_value (var_name_string_p);
|
||||
ecma_value_t error_value = ecma_raise_standard_error_with_format (ECMA_ERROR_REFERENCE,
|
||||
"% is not defined",
|
||||
var_name_val);
|
||||
#else /* !JERRY_ENABLE_ERROR_MESSAGES */
|
||||
ecma_value_t error_value = ecma_raise_reference_error (NULL);
|
||||
#endif /* JERRY_ENABLE_ERROR_MESSAGES */
|
||||
return error_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -123,7 +123,15 @@ ecma_op_resolve_reference_value (ecma_object_t *lex_env_p, /**< starting lexical
|
||||
lex_env_p = ecma_get_lex_env_outer_reference (lex_env_p);
|
||||
}
|
||||
|
||||
return ecma_raise_reference_error (ECMA_ERR_MSG ("Cannot resolve reference."));
|
||||
#ifdef JERRY_ENABLE_ERROR_MESSAGES
|
||||
ecma_value_t name_val = ecma_make_string_value (name_p);
|
||||
ecma_value_t error_value = ecma_raise_standard_error_with_format (ECMA_ERROR_REFERENCE,
|
||||
"% is not defined",
|
||||
name_val);
|
||||
#else /* !JERRY_ENABLE_ERROR_MESSAGES */
|
||||
ecma_value_t error_value = ecma_raise_reference_error (NULL);
|
||||
#endif /* JERRY_ENABLE_ERROR_MESSAGES */
|
||||
return error_value;
|
||||
} /* ecma_op_resolve_reference_value */
|
||||
|
||||
/**
|
||||
|
||||
@ -2345,13 +2345,6 @@ parser_send_breakpoints (parser_context_t *context_p, /**< context */
|
||||
|
||||
#endif /* JERRY_DEBUGGER */
|
||||
|
||||
#define PARSE_ERR_POS_START " [line: "
|
||||
#define PARSE_ERR_POS_START_SIZE ((uint32_t) sizeof (PARSE_ERR_POS_START) - 1)
|
||||
#define PARSE_ERR_POS_MIDDLE ", column: "
|
||||
#define PARSE_ERR_POS_MIDDLE_SIZE ((uint32_t) sizeof (PARSE_ERR_POS_MIDDLE) - 1)
|
||||
#define PARSE_ERR_POS_END "]"
|
||||
#define PARSE_ERR_POS_END_SIZE ((uint32_t) sizeof (PARSE_ERR_POS_END))
|
||||
|
||||
#endif /* JERRY_JS_PARSER */
|
||||
|
||||
/**
|
||||
@ -2397,50 +2390,23 @@ parser_parse_script (const uint8_t *source_p, /**< source code */
|
||||
return ecma_make_error_value (ecma_make_simple_value (ECMA_SIMPLE_VALUE_NULL));
|
||||
}
|
||||
#ifdef JERRY_ENABLE_ERROR_MESSAGES
|
||||
const char *err_str_p = parser_error_to_string (parser_error.error);
|
||||
uint32_t err_str_size = lit_zt_utf8_string_size ((const lit_utf8_byte_t *) err_str_p);
|
||||
const lit_utf8_byte_t *err_bytes_p = (const lit_utf8_byte_t *) parser_error_to_string (parser_error.error);
|
||||
lit_utf8_size_t err_bytes_size = lit_zt_utf8_string_size (err_bytes_p);
|
||||
|
||||
char line_str_p[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32];
|
||||
uint32_t line_len = ecma_uint32_to_utf8_string (parser_error.line,
|
||||
(lit_utf8_byte_t *) line_str_p,
|
||||
ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32);
|
||||
ecma_string_t *err_str_p = ecma_new_ecma_string_from_utf8 (err_bytes_p, err_bytes_size);
|
||||
ecma_value_t err_str_val = ecma_make_string_value (err_str_p);
|
||||
ecma_value_t line_str_val = ecma_make_uint32_value (parser_error.line);
|
||||
ecma_value_t col_str_val = ecma_make_uint32_value (parser_error.column);
|
||||
|
||||
char col_str_p[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32];
|
||||
uint32_t col_len = ecma_uint32_to_utf8_string (parser_error.column,
|
||||
(lit_utf8_byte_t *) col_str_p,
|
||||
ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32);
|
||||
ecma_value_t error_value = ecma_raise_standard_error_with_format (ECMA_ERROR_SYNTAX,
|
||||
"% [line: %, column: %]",
|
||||
err_str_val,
|
||||
line_str_val,
|
||||
col_str_val);
|
||||
|
||||
uint32_t msg_size = (err_str_size
|
||||
+ line_len
|
||||
+ col_len
|
||||
+ PARSE_ERR_POS_START_SIZE
|
||||
+ PARSE_ERR_POS_MIDDLE_SIZE
|
||||
+ PARSE_ERR_POS_END_SIZE);
|
||||
|
||||
ecma_value_t error_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
|
||||
|
||||
JMEM_DEFINE_LOCAL_ARRAY (error_msg_p, msg_size, char);
|
||||
char *err_msg_pos_p = error_msg_p;
|
||||
|
||||
strncpy (err_msg_pos_p, err_str_p, err_str_size);
|
||||
err_msg_pos_p += err_str_size;
|
||||
|
||||
strncpy (err_msg_pos_p, PARSE_ERR_POS_START, PARSE_ERR_POS_START_SIZE);
|
||||
err_msg_pos_p += PARSE_ERR_POS_START_SIZE;
|
||||
|
||||
strncpy (err_msg_pos_p, line_str_p, line_len);
|
||||
err_msg_pos_p += line_len;
|
||||
|
||||
strncpy (err_msg_pos_p, PARSE_ERR_POS_MIDDLE, PARSE_ERR_POS_MIDDLE_SIZE);
|
||||
err_msg_pos_p += PARSE_ERR_POS_MIDDLE_SIZE;
|
||||
|
||||
strncpy (err_msg_pos_p, col_str_p, col_len);
|
||||
err_msg_pos_p += col_len;
|
||||
|
||||
strncpy (err_msg_pos_p, PARSE_ERR_POS_END, PARSE_ERR_POS_END_SIZE);
|
||||
|
||||
error_value = ecma_raise_syntax_error (error_msg_p);
|
||||
JMEM_FINALIZE_LOCAL_ARRAY (error_msg_p);
|
||||
ecma_free_value (col_str_val);
|
||||
ecma_free_value (line_str_val);
|
||||
ecma_free_value (err_str_val);
|
||||
|
||||
return error_value;
|
||||
#else /* !JERRY_ENABLE_ERROR_MESSAGES */
|
||||
|
||||
@ -96,7 +96,15 @@ vm_op_get_value (ecma_value_t object, /**< base object */
|
||||
|
||||
if (unlikely (ecma_is_value_undefined (object) || ecma_is_value_null (object)))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Base object cannot be null or undefined."));
|
||||
#ifdef JERRY_ENABLE_ERROR_MESSAGES
|
||||
ecma_value_t error_value = ecma_raise_standard_error_with_format (ECMA_ERROR_TYPE,
|
||||
"Cannot read property '%' of %",
|
||||
property,
|
||||
object);
|
||||
#else /* !JERRY_ENABLE_ERROR_MESSAGES */
|
||||
ecma_value_t error_value = ecma_raise_type_error (NULL);
|
||||
#endif /* JERRY_ENABLE_ERROR_MESSAGES */
|
||||
return error_value;
|
||||
}
|
||||
|
||||
ecma_value_t prop_to_string_result = ecma_op_to_string (property);
|
||||
@ -136,8 +144,20 @@ vm_op_set_value (ecma_value_t object, /**< base object */
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (to_object))
|
||||
{
|
||||
#ifdef JERRY_ENABLE_ERROR_MESSAGES
|
||||
ecma_free_value (to_object);
|
||||
|
||||
ecma_value_t error_value = ecma_raise_standard_error_with_format (ECMA_ERROR_TYPE,
|
||||
"Cannot set property '%' of %",
|
||||
property,
|
||||
object);
|
||||
ecma_free_value (property);
|
||||
|
||||
return error_value;
|
||||
#else /* !JERRY_ENABLE_ERROR_MESSAGES */
|
||||
ecma_free_value (property);
|
||||
return to_object;
|
||||
#endif /* JERRY_ENABLE_ERROR_MESSAGES */
|
||||
}
|
||||
|
||||
object = to_object;
|
||||
@ -1082,16 +1102,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
ref_base_lex_env_p = ecma_op_resolve_reference_base (frame_ctx_p->lex_env_p,
|
||||
name_p);
|
||||
|
||||
if (ref_base_lex_env_p != NULL)
|
||||
{
|
||||
result = ecma_op_get_value_lex_env_base (ref_base_lex_env_p,
|
||||
name_p,
|
||||
is_strict);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = ecma_raise_reference_error (ECMA_ERR_MSG ("Cannot resolve reference."));
|
||||
}
|
||||
result = ecma_op_get_value_lex_env_base (ref_base_lex_env_p,
|
||||
name_p,
|
||||
is_strict);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user