/** * Send string representation of exception to the client. * * @return true - if the data sent successfully to the debugger client, * false - otherwise */ bool 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)) { string_p = jerry_debugger_exception_object_to_string (exception_value); if (string_p == NULL) { string_p = ecma_get_string_from_value (ecma_builtin_helper_object_to_string (exception_value)); } } else if (ecma_is_value_string (exception_value)) { string_p = ecma_get_string_from_value (exception_value); ecma_ref_ecma_string (string_p); } else { exception_value = ecma_op_to_string (exception_value); string_p = ecma_get_string_from_value (exception_value); } ECMA_STRING_TO_UTF8_STRING (string_p, string_data_p, string_size); bool result = jerry_debugger_send_string (JERRY_DEBUGGER_EXCEPTION_STR, JERRY_DEBUGGER_NO_SUBTYPE, string_data_p, string_size); ECMA_FINALIZE_UTF8_STRING (string_data_p, string_size); ecma_deref_ecma_string (string_p); return result; } /* jerry_debugger_send_exception_string */
/** * Convert ecma-string to number */ ecma_number_t ecma_string_to_number (const ecma_string_t *str_p) /**< ecma-string */ { JERRY_ASSERT (str_p != NULL); switch (ECMA_STRING_GET_CONTAINER (str_p)) { case ECMA_STRING_CONTAINER_UINT32_IN_DESC: { return ((ecma_number_t) str_p->u.uint32_number); } case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: case ECMA_STRING_CONTAINER_MAGIC_STRING: case ECMA_STRING_CONTAINER_MAGIC_STRING_EX: { ecma_number_t num; ECMA_STRING_TO_UTF8_STRING (str_p, str_buffer_p, str_buffer_size); if (str_buffer_size == 0) { return ECMA_NUMBER_ZERO; } num = ecma_utf8_string_to_number (str_buffer_p, str_buffer_size); ECMA_FINALIZE_UTF8_STRING (str_buffer_p, str_buffer_size); return num; } default: { JERRY_UNREACHABLE (); } } } /* ecma_string_to_number */
/** * Send result of evaluated expression or throw an error. * * @return true - if execution should be resumed * false - otherwise */ static bool jerry_debugger_send_eval (const lit_utf8_byte_t *eval_string_p, /**< evaluated string */ size_t eval_string_size) /**< evaluated string size */ { JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED); JERRY_ASSERT (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_VM_IGNORE)); JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_IGNORE); ecma_value_t result = ecma_op_eval_chars_buffer (eval_string_p + 1, eval_string_size - 1, true, false); JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_IGNORE); if (!ECMA_IS_VALUE_ERROR (result)) { if (eval_string_p[0] != JERRY_DEBUGGER_EVAL_EVAL) { JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_EXCEPTION_THROWN); JERRY_CONTEXT (error_value) = result; /* Stop where the error is caught. */ JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_STOP); JERRY_CONTEXT (debugger_stop_context) = NULL; if (eval_string_p[0] == JERRY_DEBUGGER_EVAL_THROW) { JERRY_CONTEXT (status_flags) |= ECMA_STATUS_EXCEPTION; } else { JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_EXCEPTION; } return true; } if (!ecma_is_value_string (result)) { ecma_value_t to_string_value = ecma_op_to_string (result); ecma_free_value (result); result = to_string_value; } } ecma_value_t message = result; uint8_t type = JERRY_DEBUGGER_EVAL_OK; if (ECMA_IS_VALUE_ERROR (result)) { type = JERRY_DEBUGGER_EVAL_ERROR; result = JERRY_CONTEXT (error_value); if (ecma_is_value_object (result)) { message = ecma_op_object_find (ecma_get_object_from_value (result), ecma_get_magic_string (LIT_MAGIC_STRING_MESSAGE)); if (!ecma_is_value_string (message) || ecma_string_is_empty (ecma_get_string_from_value (message))) { ecma_free_value (message); lit_magic_string_id_t id = ecma_object_get_class_name (ecma_get_object_from_value (result)); ecma_free_value (result); const lit_utf8_byte_t *string_p = lit_get_magic_string_utf8 (id); jerry_debugger_send_string (JERRY_DEBUGGER_EVAL_RESULT, type, string_p, strlen ((const char *) string_p)); return false; } } else { /* Primitive type. */ message = ecma_op_to_string (result); JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (message)); } ecma_free_value (result); } ecma_string_t *string_p = ecma_get_string_from_value (message); ECMA_STRING_TO_UTF8_STRING (string_p, buffer_p, buffer_size); jerry_debugger_send_string (JERRY_DEBUGGER_EVAL_RESULT, type, buffer_p, buffer_size); ECMA_FINALIZE_UTF8_STRING (buffer_p, buffer_size); ecma_free_value (message); return false; } /* jerry_debugger_send_eval */
/** * The Date object's 'parse' routine * * See also: * ECMA-262 v5, 15.9.4.2 * ECMA-262 v5, 15.9.1.15 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_date_parse (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg) /**< string */ { JERRY_UNUSED (this_arg); ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ecma_number_t date_num = ecma_number_make_nan (); /* Date Time String fromat (ECMA-262 v5, 15.9.1.15) */ ECMA_TRY_CATCH (date_str_value, ecma_op_to_string (arg), ret_value); ecma_string_t *date_str_p = ecma_get_string_from_value (date_str_value); ECMA_STRING_TO_UTF8_STRING (date_str_p, date_start_p, date_start_size); const lit_utf8_byte_t *date_str_curr_p = date_start_p; const lit_utf8_byte_t *date_str_end_p = date_start_p + date_start_size; /* 1. read year */ ecma_number_t year = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 4); if (!ecma_number_is_nan (year) && year >= 0) { ecma_number_t month = ECMA_NUMBER_ONE; ecma_number_t day = ECMA_NUMBER_ONE; ecma_number_t time = ECMA_NUMBER_ZERO; /* 2. read month if any */ if (date_str_curr_p < date_str_end_p && *date_str_curr_p == '-') { /* eat up '-' */ date_str_curr_p++; month = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2); if (month > 12 || month < 1) { month = ecma_number_make_nan (); } } /* 3. read day if any */ if (date_str_curr_p < date_str_end_p && *date_str_curr_p == '-') { /* eat up '-' */ date_str_curr_p++; day = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2); if (day < 1 || day > 31) { day = ecma_number_make_nan (); } } /* 4. read time if any */ if (date_str_curr_p < date_str_end_p && *date_str_curr_p == 'T') { /* eat up 'T' */ date_str_curr_p++; ecma_number_t hours = ECMA_NUMBER_ZERO; ecma_number_t minutes = ECMA_NUMBER_ZERO; ecma_number_t seconds = ECMA_NUMBER_ZERO; ecma_number_t milliseconds = ECMA_NUMBER_ZERO; ecma_length_t remaining_length = lit_utf8_string_length (date_str_curr_p, (lit_utf8_size_t) (date_str_end_p - date_str_curr_p)); if (remaining_length >= 5) { /* 4.1 read hours and minutes */ hours = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2); if (hours < 0 || hours > 24) { hours = ecma_number_make_nan (); } else if (hours == 24) { hours = ECMA_NUMBER_ZERO; } /* eat up ':' */ date_str_curr_p++; minutes = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2); if (minutes < 0 || minutes > 59) { minutes = ecma_number_make_nan (); } /* 4.2 read seconds if any */ if (date_str_curr_p < date_str_end_p && *date_str_curr_p == ':') { /* eat up ':' */ date_str_curr_p++; seconds = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2); if (seconds < 0 || seconds > 59) { seconds = ecma_number_make_nan (); } /* 4.3 read milliseconds if any */ if (date_str_curr_p < date_str_end_p && *date_str_curr_p == '.') { /* eat up '.' */ date_str_curr_p++; milliseconds = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 3); if (milliseconds < 0) { milliseconds = ecma_number_make_nan (); } } } time = ecma_date_make_time (hours, minutes, seconds, milliseconds); } else { time = ecma_number_make_nan (); } /* 4.4 read timezone if any */ if (date_str_curr_p < date_str_end_p && *date_str_curr_p == 'Z' && !ecma_number_is_nan (time)) { date_str_curr_p++; time = ecma_date_make_time (hours, minutes, seconds, milliseconds); } else if (date_str_curr_p < date_str_end_p && (*date_str_curr_p == '+' || *date_str_curr_p == '-')) { ecma_length_t remaining_length; remaining_length = lit_utf8_string_length (date_str_curr_p, (lit_utf8_size_t) (date_str_end_p - date_str_curr_p)) - 1; if (remaining_length == 5) { bool is_negative = false; if (*date_str_curr_p == '-') { is_negative = true; } /* eat up '+/-' */ date_str_curr_p++; /* read hours and minutes */ hours = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2); if (hours < 0 || hours > 24) { hours = ecma_number_make_nan (); } else if (hours == 24) { hours = ECMA_NUMBER_ZERO; } /* eat up ':' */ date_str_curr_p++; minutes = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2); if (minutes < 0 || minutes > 59) { minutes = ecma_number_make_nan (); } if (is_negative) { time += ecma_date_make_time (hours, minutes, ECMA_NUMBER_ZERO, ECMA_NUMBER_ZERO); } else { time -= ecma_date_make_time (hours, minutes, ECMA_NUMBER_ZERO, ECMA_NUMBER_ZERO); } } } } if (date_str_curr_p >= date_str_end_p) { ecma_number_t date = ecma_date_make_day (year, month - 1, day); date_num = ecma_date_make_date (date, time); } } ret_value = ecma_make_number_value (date_num); ECMA_FINALIZE_UTF8_STRING (date_start_p, date_start_size); ECMA_FINALIZE (date_str_value); return ret_value; } /* ecma_builtin_date_parse */
/** * Helper function for finding index of a search string * * This function clamps the given index to the [0, length] range. * If the index is negative, 0 value is used. * If the index is greater than the length of the string, the normalized index will be the length of the string. * NaN is mapped to zero or length depending on the nan_to_zero parameter. * * See also: * ECMA-262 v5, 15.5.4.7,8,11 * * Used by: * - The ecma_builtin_helper_string_prototype_object_index_of helper routine. * - The ecma_builtin_string_prototype_object_replace_match helper routine. * * @return uint32_t - the normalized value of the index */ bool ecma_builtin_helper_string_find_index (ecma_string_t *original_str_p, /**< index */ ecma_string_t *search_str_p, /**< string's length */ bool first_index, /**< whether search for first (t) or last (f) index */ ecma_length_t start_pos, /**< start position */ ecma_length_t *ret_index_p) /**< position found in original string */ { bool match_found = false; const ecma_length_t original_len = ecma_string_get_length (original_str_p); const ecma_length_t search_len = ecma_string_get_length (search_str_p); if (search_len <= original_len) { if (!search_len) { match_found = true; *ret_index_p = first_index ? 0 : original_len; } else { /* create utf8 string from original string and advance to position */ ECMA_STRING_TO_UTF8_STRING (original_str_p, original_str_utf8_p, original_str_size); ecma_length_t index = start_pos; const lit_utf8_byte_t *original_str_curr_p = original_str_utf8_p; for (ecma_length_t idx = 0; idx < index; idx++) { lit_utf8_incr (&original_str_curr_p); } /* create utf8 string from search string */ ECMA_STRING_TO_UTF8_STRING (search_str_p, search_str_utf8_p, search_str_size); const lit_utf8_byte_t *search_str_curr_p = search_str_utf8_p; /* iterate original string and try to match at each position */ bool searching = true; ecma_char_t first_char = lit_utf8_read_next (&search_str_curr_p); while (searching) { /* match as long as possible */ ecma_length_t match_len = 0; const lit_utf8_byte_t *stored_original_str_curr_p = original_str_curr_p; if (match_len < search_len && index + match_len < original_len && lit_utf8_read_next (&original_str_curr_p) == first_char) { const lit_utf8_byte_t *nested_search_str_curr_p = search_str_curr_p; match_len++; while (match_len < search_len && index + match_len < original_len && lit_utf8_read_next (&original_str_curr_p) == lit_utf8_read_next (&nested_search_str_curr_p)) { match_len++; } } /* check for match */ if (match_len == search_len) { match_found = true; *ret_index_p = index; break; } else { /* inc/dec index and update iterators and search condition */ original_str_curr_p = stored_original_str_curr_p; if (first_index) { if ((searching = (index <= original_len - search_len))) { lit_utf8_incr (&original_str_curr_p); index++; } } else { if ((searching = (index > 0))) { lit_utf8_decr (&original_str_curr_p); index--; } } } } ECMA_FINALIZE_UTF8_STRING (search_str_utf8_p, search_str_size); ECMA_FINALIZE_UTF8_STRING (original_str_utf8_p, original_str_size); } } return match_found; } /* ecma_builtin_helper_string_find_index */
/** * Trim leading and trailing whitespace characters from string. * * @return trimmed ecma string */ ecma_string_t * ecma_string_trim (const ecma_string_t *string_p) /**< pointer to an ecma string */ { ecma_string_t *ret_string_p; ECMA_STRING_TO_UTF8_STRING (string_p, utf8_str_p, utf8_str_size); if (utf8_str_size > 0) { ecma_char_t ch; lit_utf8_size_t read_size; const lit_utf8_byte_t *nonws_start_p = utf8_str_p + utf8_str_size; const lit_utf8_byte_t *current_p = utf8_str_p; /* Trim front. */ while (current_p < nonws_start_p) { read_size = lit_read_code_unit_from_utf8 (current_p, &ch); if (!lit_char_is_white_space (ch) && !lit_char_is_line_terminator (ch)) { nonws_start_p = current_p; break; } current_p += read_size; } current_p = utf8_str_p + utf8_str_size; /* Trim back. */ while (current_p > utf8_str_p) { read_size = lit_read_prev_code_unit_from_utf8 (current_p, &ch); if (!lit_char_is_white_space (ch) && !lit_char_is_line_terminator (ch)) { break; } current_p -= read_size; } /* Construct new string. */ if (current_p > nonws_start_p) { ret_string_p = ecma_new_ecma_string_from_utf8 (nonws_start_p, (lit_utf8_size_t) (current_p - nonws_start_p)); } else { ret_string_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); } } else { ret_string_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); } ECMA_FINALIZE_UTF8_STRING (utf8_str_p, utf8_str_size); return ret_string_p; } /* ecma_string_trim */