Skip to content

Commit 919db82

Browse files
committed
Improve error message
JerryScript-DCO-1.0-Signed-off-by: Yanhui Shen [email protected]
1 parent 319702c commit 919db82

File tree

6 files changed

+162
-65
lines changed

6 files changed

+162
-65
lines changed

jerry-core/ecma/operations/ecma-exceptions.c

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
* limitations under the License.
1414
*/
1515

16+
#include <stdarg.h>
1617
#include "ecma-builtins.h"
18+
#include "ecma-conversion.h"
1719
#include "ecma-exceptions.h"
1820
#include "ecma-gc.h"
1921
#include "ecma-globals.h"
@@ -156,6 +158,95 @@ ecma_raise_standard_error (ecma_standard_error_t error_type, /**< error type */
156158
return ecma_make_error_obj_value (error_obj_p);
157159
} /* ecma_raise_standard_error */
158160

161+
#ifdef JERRY_ENABLE_ERROR_MESSAGES
162+
163+
/**
164+
* Raise a standard ecma-error with the given format string and arguments.
165+
*
166+
* @return ecma value
167+
* Returned value must be freed with ecma_free_value
168+
*/
169+
ecma_value_t
170+
ecma_raise_standard_error_with_format (ecma_standard_error_t error_type, /**< error type */
171+
const char *format, /**< format string */
172+
...) /**< ecma-values */
173+
{
174+
JERRY_ASSERT (format != NULL);
175+
176+
ecma_string_t *error_msg_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY);
177+
ecma_string_t *string1_p;
178+
ecma_string_t *string2_p;
179+
180+
const char *start_p = format;
181+
const char *end_p = format;
182+
183+
va_list args;
184+
185+
va_start (args, format);
186+
187+
while (*end_p)
188+
{
189+
if (*end_p == '%')
190+
{
191+
/* Concat template string. */
192+
if (end_p > start_p)
193+
{
194+
string1_p = error_msg_p;
195+
string2_p = ecma_new_ecma_string_from_utf8 ((const lit_utf8_byte_t *) start_p,
196+
(lit_utf8_size_t) (end_p - start_p));
197+
error_msg_p = ecma_concat_ecma_strings (string1_p, string2_p);
198+
ecma_deref_ecma_string (string1_p);
199+
ecma_deref_ecma_string (string2_p);
200+
}
201+
202+
/* Convert an argument to string without side effects. */
203+
ecma_string_t *arg_string_p;
204+
const ecma_value_t arg_val = va_arg (args, ecma_value_t);
205+
if (unlikely (ecma_is_value_object (arg_val)))
206+
{
207+
ecma_object_t *arg_object_p = ecma_get_object_from_value (arg_val);
208+
lit_magic_string_id_t class_name = ecma_object_get_class_name (arg_object_p);
209+
arg_string_p = ecma_get_magic_string (class_name);
210+
}
211+
else
212+
{
213+
jerry_value_t str_val = ecma_op_to_string (arg_val);
214+
arg_string_p = ecma_get_string_from_value (str_val);
215+
}
216+
217+
/* Concat argument. */
218+
string1_p = error_msg_p;
219+
string2_p = arg_string_p;
220+
error_msg_p = ecma_concat_ecma_strings (string1_p, string2_p);
221+
ecma_deref_ecma_string (string1_p);
222+
ecma_deref_ecma_string (string2_p);
223+
224+
start_p = end_p + 1;
225+
}
226+
227+
end_p++;
228+
}
229+
230+
va_end (args);
231+
232+
/* Concat reset of template string. */
233+
if (start_p < end_p)
234+
{
235+
string1_p = error_msg_p;
236+
string2_p = ecma_new_ecma_string_from_utf8 ((const lit_utf8_byte_t *) start_p,
237+
(lit_utf8_size_t) (end_p - start_p));
238+
error_msg_p = ecma_concat_ecma_strings (string1_p, string2_p);
239+
ecma_deref_ecma_string (string1_p);
240+
ecma_deref_ecma_string (string2_p);
241+
}
242+
243+
ecma_object_t *error_obj_p = ecma_new_standard_error_with_message (error_type, error_msg_p);
244+
ecma_deref_ecma_string (error_msg_p);
245+
return ecma_make_error_obj_value (error_obj_p);
246+
} /* ecma_raise_standard_error_with_format */
247+
248+
#endif /* JERRY_ENABLE_ERROR_MESSAGES */
249+
159250
/**
160251
* Raise a common error with the given message.
161252
*

jerry-core/ecma/operations/ecma-exceptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ typedef enum
5151
ecma_object_t *ecma_new_standard_error (ecma_standard_error_t error_type);
5252
ecma_object_t *ecma_new_standard_error_with_message (ecma_standard_error_t error_type, ecma_string_t *message_string_p);
5353
ecma_value_t ecma_raise_standard_error (ecma_standard_error_t error_type, const lit_utf8_byte_t *msg_p);
54+
#ifdef JERRY_ENABLE_ERROR_MESSAGES
55+
ecma_value_t ecma_raise_standard_error_with_format (ecma_standard_error_t error_type, const char *msg_p, ...);
56+
#endif /* JERRY_ENABLE_ERROR_MESSAGES */
5457
ecma_value_t ecma_raise_common_error (const char *msg_p);
5558
ecma_value_t ecma_raise_eval_error (const char *msg_p);
5659
ecma_value_t ecma_raise_range_error (const char *msg_p);

jerry-core/ecma/operations/ecma-get-put-value.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,15 @@ ecma_op_get_value_lex_env_base (ecma_object_t *ref_base_lex_env_p, /**< referenc
5252
/* 3. */
5353
if (unlikely (is_unresolvable_reference))
5454
{
55-
return ecma_raise_reference_error (ECMA_ERR_MSG ("Cannot resolve reference."));
55+
#ifdef JERRY_ENABLE_ERROR_MESSAGES
56+
ecma_value_t var_name_val = ecma_make_string_value (var_name_string_p);
57+
ecma_value_t error_value = ecma_raise_standard_error_with_format (ECMA_ERROR_REFERENCE,
58+
"% is not defined",
59+
var_name_val);
60+
#else /* !JERRY_ENABLE_ERROR_MESSAGES */
61+
ecma_value_t error_value = ecma_raise_reference_error (NULL);
62+
#endif /* JERRY_ENABLE_ERROR_MESSAGES */
63+
return error_value;
5664
}
5765

5866
/* 5. */
@@ -149,7 +157,15 @@ ecma_op_put_value_lex_env_base (ecma_object_t *ref_base_lex_env_p, /**< referenc
149157
/* 3.a. */
150158
if (is_strict)
151159
{
152-
return ecma_raise_reference_error (ECMA_ERR_MSG ("Cannot resolve reference."));
160+
#ifdef JERRY_ENABLE_ERROR_MESSAGES
161+
ecma_value_t var_name_val = ecma_make_string_value (var_name_string_p);
162+
ecma_value_t error_value = ecma_raise_standard_error_with_format (ECMA_ERROR_REFERENCE,
163+
"% is not defined",
164+
var_name_val);
165+
#else /* !JERRY_ENABLE_ERROR_MESSAGES */
166+
ecma_value_t error_value = ecma_raise_reference_error (NULL);
167+
#endif /* JERRY_ENABLE_ERROR_MESSAGES */
168+
return error_value;
153169
}
154170
else
155171
{

jerry-core/ecma/operations/ecma-reference.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,15 @@ ecma_op_resolve_reference_value (ecma_object_t *lex_env_p, /**< starting lexical
123123
lex_env_p = ecma_get_lex_env_outer_reference (lex_env_p);
124124
}
125125

126-
return ecma_raise_reference_error (ECMA_ERR_MSG ("Cannot resolve reference."));
126+
#ifdef JERRY_ENABLE_ERROR_MESSAGES
127+
ecma_value_t name_val = ecma_make_string_value (name_p);
128+
ecma_value_t error_value = ecma_raise_standard_error_with_format (ECMA_ERROR_REFERENCE,
129+
"% is not defined",
130+
name_val);
131+
#else /* !JERRY_ENABLE_ERROR_MESSAGES */
132+
ecma_value_t error_value = ecma_raise_reference_error (NULL);
133+
#endif /* JERRY_ENABLE_ERROR_MESSAGES */
134+
return error_value;
127135
} /* ecma_op_resolve_reference_value */
128136

129137
/**

jerry-core/parser/js/js-parser.c

Lines changed: 17 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2345,13 +2345,6 @@ parser_send_breakpoints (parser_context_t *context_p, /**< context */
23452345

23462346
#endif /* JERRY_DEBUGGER */
23472347

2348-
#define PARSE_ERR_POS_START " [line: "
2349-
#define PARSE_ERR_POS_START_SIZE ((uint32_t) sizeof (PARSE_ERR_POS_START) - 1)
2350-
#define PARSE_ERR_POS_MIDDLE ", column: "
2351-
#define PARSE_ERR_POS_MIDDLE_SIZE ((uint32_t) sizeof (PARSE_ERR_POS_MIDDLE) - 1)
2352-
#define PARSE_ERR_POS_END "]"
2353-
#define PARSE_ERR_POS_END_SIZE ((uint32_t) sizeof (PARSE_ERR_POS_END))
2354-
23552348
#endif /* JERRY_JS_PARSER */
23562349

23572350
/**
@@ -2397,50 +2390,23 @@ parser_parse_script (const uint8_t *source_p, /**< source code */
23972390
return ecma_make_error_value (ecma_make_simple_value (ECMA_SIMPLE_VALUE_NULL));
23982391
}
23992392
#ifdef JERRY_ENABLE_ERROR_MESSAGES
2400-
const char *err_str_p = parser_error_to_string (parser_error.error);
2401-
uint32_t err_str_size = lit_zt_utf8_string_size ((const lit_utf8_byte_t *) err_str_p);
2402-
2403-
char line_str_p[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32];
2404-
uint32_t line_len = ecma_uint32_to_utf8_string (parser_error.line,
2405-
(lit_utf8_byte_t *) line_str_p,
2406-
ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32);
2407-
2408-
char col_str_p[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32];
2409-
uint32_t col_len = ecma_uint32_to_utf8_string (parser_error.column,
2410-
(lit_utf8_byte_t *) col_str_p,
2411-
ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32);
2412-
2413-
uint32_t msg_size = (err_str_size
2414-
+ line_len
2415-
+ col_len
2416-
+ PARSE_ERR_POS_START_SIZE
2417-
+ PARSE_ERR_POS_MIDDLE_SIZE
2418-
+ PARSE_ERR_POS_END_SIZE);
2419-
2420-
ecma_value_t error_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
2421-
2422-
JMEM_DEFINE_LOCAL_ARRAY (error_msg_p, msg_size, char);
2423-
char *err_msg_pos_p = error_msg_p;
2424-
2425-
strncpy (err_msg_pos_p, err_str_p, err_str_size);
2426-
err_msg_pos_p += err_str_size;
2427-
2428-
strncpy (err_msg_pos_p, PARSE_ERR_POS_START, PARSE_ERR_POS_START_SIZE);
2429-
err_msg_pos_p += PARSE_ERR_POS_START_SIZE;
2430-
2431-
strncpy (err_msg_pos_p, line_str_p, line_len);
2432-
err_msg_pos_p += line_len;
2433-
2434-
strncpy (err_msg_pos_p, PARSE_ERR_POS_MIDDLE, PARSE_ERR_POS_MIDDLE_SIZE);
2435-
err_msg_pos_p += PARSE_ERR_POS_MIDDLE_SIZE;
2436-
2437-
strncpy (err_msg_pos_p, col_str_p, col_len);
2438-
err_msg_pos_p += col_len;
2439-
2440-
strncpy (err_msg_pos_p, PARSE_ERR_POS_END, PARSE_ERR_POS_END_SIZE);
2441-
2442-
error_value = ecma_raise_syntax_error (error_msg_p);
2443-
JMEM_FINALIZE_LOCAL_ARRAY (error_msg_p);
2393+
const lit_utf8_byte_t *err_bytes_p = (const lit_utf8_byte_t *) parser_error_to_string (parser_error.error);
2394+
lit_utf8_size_t err_bytes_size = lit_zt_utf8_string_size (err_bytes_p);
2395+
2396+
ecma_string_t *err_str_p = ecma_new_ecma_string_from_utf8 (err_bytes_p, err_bytes_size);
2397+
ecma_value_t err_str_val = ecma_make_string_value (err_str_p);
2398+
ecma_value_t line_str_val = ecma_make_uint32_value (parser_error.line);
2399+
ecma_value_t col_str_val = ecma_make_uint32_value (parser_error.column);
2400+
2401+
ecma_value_t error_value = ecma_raise_standard_error_with_format (ECMA_ERROR_SYNTAX,
2402+
"% [line: %, column: %]",
2403+
err_str_val,
2404+
line_str_val,
2405+
col_str_val);
2406+
2407+
ecma_free_value (col_str_val);
2408+
ecma_free_value (line_str_val);
2409+
ecma_free_value (err_str_val);
24442410

24452411
return error_value;
24462412
#else /* !JERRY_ENABLE_ERROR_MESSAGES */

jerry-core/vm/vm.c

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,15 @@ vm_op_get_value (ecma_value_t object, /**< base object */
9696

9797
if (unlikely (ecma_is_value_undefined (object) || ecma_is_value_null (object)))
9898
{
99-
return ecma_raise_type_error (ECMA_ERR_MSG ("Base object cannot be null or undefined."));
99+
#ifdef JERRY_ENABLE_ERROR_MESSAGES
100+
ecma_value_t error_value = ecma_raise_standard_error_with_format (ECMA_ERROR_TYPE,
101+
"Cannot read property '%' of %",
102+
property,
103+
object);
104+
#else /* !JERRY_ENABLE_ERROR_MESSAGES */
105+
ecma_value_t error_value = ecma_raise_type_error (NULL);
106+
#endif /* JERRY_ENABLE_ERROR_MESSAGES */
107+
return error_value;
100108
}
101109

102110
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 */
136144

137145
if (ECMA_IS_VALUE_ERROR (to_object))
138146
{
147+
#ifdef JERRY_ENABLE_ERROR_MESSAGES
148+
ecma_free_value (to_object);
149+
150+
ecma_value_t error_value = ecma_raise_standard_error_with_format (ECMA_ERROR_TYPE,
151+
"Cannot set property '%' of %",
152+
property,
153+
object);
154+
ecma_free_value (property);
155+
156+
return error_value;
157+
#else /* !JERRY_ENABLE_ERROR_MESSAGES */
139158
ecma_free_value (property);
140159
return to_object;
160+
#endif /* JERRY_ENABLE_ERROR_MESSAGES */
141161
}
142162

143163
object = to_object;
@@ -1082,16 +1102,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
10821102
ref_base_lex_env_p = ecma_op_resolve_reference_base (frame_ctx_p->lex_env_p,
10831103
name_p);
10841104

1085-
if (ref_base_lex_env_p != NULL)
1086-
{
1087-
result = ecma_op_get_value_lex_env_base (ref_base_lex_env_p,
1088-
name_p,
1089-
is_strict);
1090-
}
1091-
else
1092-
{
1093-
result = ecma_raise_reference_error (ECMA_ERR_MSG ("Cannot resolve reference."));
1094-
}
1105+
result = ecma_op_get_value_lex_env_base (ref_base_lex_env_p,
1106+
name_p,
1107+
is_strict);
10951108

10961109
if (ECMA_IS_VALUE_ERROR (result))
10971110
{

0 commit comments

Comments
 (0)