diff --git a/jerry-core/parser/js/js-parser-util.c b/jerry-core/parser/js/js-parser-util.c index c3c1b2806..02d7757b6 100644 --- a/jerry-core/parser/js/js-parser-util.c +++ b/jerry-core/parser/js/js-parser-util.c @@ -639,8 +639,9 @@ parser_set_continues_to_current_position (parser_context_t *context_p, /**< cont } } /* parser_set_continues_to_current_position */ +#if JERRY_ENABLE_ERROR_MESSAGES /** - * Returns with the striong representation of the error + * Returns with the string representation of the error */ const char * parser_error_to_string (parser_error_t error) /**< error code */ @@ -925,13 +926,12 @@ parser_error_to_string (parser_error_t error) /**< error code */ } default: { - break; + JERRY_ASSERT (error == PARSER_ERR_NO_ERROR); + return "No error."; } } - - JERRY_ASSERT (error == PARSER_ERR_NO_ERROR); - return "No error."; } /* parser_error_to_string */ +#endif /* JERRY_ENABLE_ERROR_MESSAGES */ /** * @} diff --git a/jerry-core/parser/js/js-parser.c b/jerry-core/parser/js/js-parser.c index 7de4c122c..7dc6b08e0 100644 --- a/jerry-core/parser/js/js-parser.c +++ b/jerry-core/parser/js/js-parser.c @@ -1803,7 +1803,7 @@ static ecma_compiled_code_t * parser_parse_source (const uint8_t *source_p, /**< valid UTF-8 source code */ size_t size, /**< size of the source code */ int strict_mode, /**< strict mode */ - parser_error_location *error_location) /**< error location */ + parser_error_location_t *error_location_p) /**< error location */ { parser_context_t context; ecma_compiled_code_t *compiled_code; @@ -1811,9 +1811,9 @@ parser_parse_source (const uint8_t *source_p, /**< valid UTF-8 source code */ context.error = PARSER_ERR_NO_ERROR; context.allocated_buffer_p = NULL; - if (error_location != NULL) + if (error_location_p != NULL) { - error_location->error = PARSER_ERR_NO_ERROR; + error_location_p->error = PARSER_ERR_NO_ERROR; } context.status_flags = PARSER_NO_REG_STORE | PARSER_LEXICAL_ENV_NEEDED | PARSER_ARGUMENTS_NOT_NEEDED; @@ -1907,11 +1907,11 @@ parser_parse_source (const uint8_t *source_p, /**< valid UTF-8 source code */ context.allocated_buffer_size); } - if (error_location != NULL) + if (error_location_p != NULL) { - error_location->error = context.error; - error_location->line = context.token.line; - error_location->column = context.token.column; + error_location_p->error = context.error; + error_location_p->line = context.token.line; + error_location_p->column = context.token.column; } compiled_code = NULL; @@ -2221,6 +2221,13 @@ parser_raise_error (parser_context_t *context_p, /**< context */ JERRY_ASSERT (0); } /* parser_raise_error */ +#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)) + /** * Parse EcamScript source code * @@ -2236,19 +2243,67 @@ parser_parse_script (const uint8_t *source_p, /**< source code */ bool is_strict, /**< strict mode */ ecma_compiled_code_t **bytecode_data_p) /**< [out] JS bytecode */ { - parser_error_location parse_error; - *bytecode_data_p = parser_parse_source (source_p, size, is_strict, &parse_error); + parser_error_location_t parser_error; + *bytecode_data_p = parser_parse_source (source_p, size, is_strict, &parser_error); if (!*bytecode_data_p) { - if (parse_error.error == PARSER_ERR_OUT_OF_MEMORY) + if (parser_error.error == PARSER_ERR_OUT_OF_MEMORY) { /* 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)); } +#if 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); - return ecma_raise_syntax_error (parser_error_to_string (parse_error.error)); + 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); + + 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); + + 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); + + return error_value; +#else /* !JERRY_ENABLE_ERROR_MESSAGES */ + return ecma_raise_syntax_error (""); +#endif /* JERRY_ENABLE_ERROR_MESSAGES */ } return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); diff --git a/jerry-core/parser/js/js-parser.h b/jerry-core/parser/js/js-parser.h index aa63d1f38..e7886ba1b 100644 --- a/jerry-core/parser/js/js-parser.h +++ b/jerry-core/parser/js/js-parser.h @@ -126,7 +126,7 @@ typedef struct parser_error_t error; /**< error code */ parser_line_counter_t line; /**< line where the error occured */ parser_line_counter_t column; /**< column where the error occured */ -} parser_error_location; +} parser_error_location_t; /* Note: source must be a valid UTF-8 string */ extern ecma_value_t parser_parse_script (const uint8_t *, size_t, bool, ecma_compiled_code_t **); diff --git a/jerry-main/main-unix.c b/jerry-main/main-unix.c index aba0ae9f2..6172089da 100644 --- a/jerry-main/main-unix.c +++ b/jerry-main/main-unix.c @@ -85,7 +85,7 @@ assert_handler (const jerry_value_t func_obj_val __attribute__((unused)), /**< f } else { - jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Script error: assertion failed\n"); + jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Script Error: assertion failed\n"); exit (JERRY_STANDALONE_EXIT_CODE_FAIL); } } /* assert_handler */ @@ -144,7 +144,7 @@ print_unhandled_exception (jerry_value_t error_value) } err_str_buf[err_str_size] = 0; - jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Script Error: unhandled exception: %s\n", err_str_buf); + jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Script Error: %s\n", err_str_buf); jerry_release_value (err_str_val); } /* print_unhandled_exception */ diff --git a/tests/unit/test-api.c b/tests/unit/test-api.c index a6a86eaa5..b2aea32fc 100644 --- a/tests/unit/test-api.c +++ b/tests/unit/test-api.c @@ -724,6 +724,28 @@ main (void) TEST_ASSERT (test_api_is_free_callback_was_called); + // Test: parser error location + jerry_init (JERRY_INIT_SHOW_OPCODES); + + const char *parser_err_src_p = "b = 'hello';\nvar a = (;"; + parsed_code_val = jerry_parse ((jerry_char_t *) parser_err_src_p, + strlen (parser_err_src_p), + false); + TEST_ASSERT (jerry_value_has_error_flag (parsed_code_val)); + jerry_value_clear_error_flag (&parsed_code_val); + jerry_value_t err_str_val = jerry_value_to_string (parsed_code_val); + jerry_size_t err_str_size = jerry_get_string_size (err_str_val); + jerry_char_t err_str_buf[256]; + sz = jerry_string_to_char_buffer (err_str_val, err_str_buf, err_str_size); + err_str_buf[sz] = 0; + + jerry_release_value (err_str_val); + jerry_release_value (parsed_code_val); + + TEST_ASSERT (!strcmp ((char *) err_str_buf, + "SyntaxError: Primary expression expected. [line: 2, column: 10]")); + jerry_cleanup (); + // External Magic String jerry_init (JERRY_INIT_SHOW_OPCODES); diff --git a/tools/run-tests.py b/tools/run-tests.py index 946e531b2..c9cdee875 100755 --- a/tools/run-tests.py +++ b/tools/run-tests.py @@ -62,8 +62,8 @@ class Options: # Test options for unittests jerry_unittests_options = [ - Options('unittests', ['--unittests']), - Options('unittests-debug', ['--unittests', '--debug']), + Options('unittests', ['--unittests', '--error-messages=on']), + Options('unittests-debug', ['--unittests', '--debug', '--error-messages=on']), ] # Test options for jerry-tests