/** * Implementation of 'CreateArrayFromList' specialized for iterators * * See also: * ECMA-262 v6, 7.3.16. * * Note: * Returned value must be freed with ecma_free_value. * * @return new array object */ ecma_value_t ecma_create_array_from_iter_element (ecma_value_t value, /**< value */ ecma_value_t index_value) /**< iterator index */ { /* 2. */ ecma_value_t new_array = ecma_op_create_array_object (NULL, 0, false); JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_array)); ecma_object_t *new_array_p = ecma_get_object_from_value (new_array); /* 3 - 4. */ for (uint32_t index = 0; index < 2; index++) { ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); /* 4.a */ ecma_value_t completion = ecma_builtin_helper_def_prop (new_array_p, index_string_p, (index == 0) ? index_value : value, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, false); /* Failure handling */ /* 4.b */ JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (index_string_p); } /* 5. */ return new_array; } /* ecma_create_array_from_iter_element */
/** * Handle calling [[Construct]] of built-in Array object * * @return ecma value */ ecma_value_t ecma_builtin_array_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ ecma_length_t arguments_list_len) /**< number of arguments */ { JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); return ecma_op_create_array_object (arguments_list_p, arguments_list_len, true); } /* ecma_builtin_array_dispatch_construct */
/** * The RegExp.prototype object's 'exec' routine * * See also: * ECMA-262 v5, 15.10.6.2 * * @return array object containing the results - if the matched * null - otherwise * * May raise error, so returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_regexp_prototype_exec (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg) /**< routine's argument */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); if (!ecma_is_value_object (this_arg) || ecma_object_get_class_name (ecma_get_object_from_value (this_arg)) != LIT_MAGIC_STRING_REGEXP_UL) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Incomplete RegExp type")); } else { ECMA_TRY_CATCH (obj_this, ecma_op_to_object (this_arg), ret_value); ECMA_TRY_CATCH (input_str_value, ecma_op_to_string (arg), ret_value); ecma_property_t *bytecode_prop_p; ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); bytecode_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE); void *bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (void, ecma_get_internal_property_value (bytecode_prop_p)); if (bytecode_p == NULL) { /* Missing bytecode means empty RegExp: '/(?:)/', so always return empty string. */ ecma_string_t *capture_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); ecma_value_t arguments_list[1]; arguments_list[0] = ecma_make_string_value (capture_str_p); ret_value = ecma_op_create_array_object (arguments_list, 1, false); ecma_deref_ecma_string (capture_str_p); re_set_result_array_properties (ecma_get_object_from_value (ret_value), ecma_get_string_from_value (input_str_value), 1, 0); } else { ret_value = ecma_regexp_exec_helper (obj_this, input_str_value, false); } ECMA_FINALIZE (input_str_value); ECMA_FINALIZE (obj_this); } return ret_value; } /* ecma_builtin_regexp_prototype_exec */
/** * The Object.keys and Object.getOwnPropertyNames routine's common part. * * See also: * ECMA-262 v5, 15.2.3.4 steps 2-5 * ECMA-262 v5, 15.2.3.14 steps 3-6 * * @return ecma value - Array of property names. * Returned value must be freed with ecma_free_value. */ ecma_value_t ecma_builtin_helper_object_get_properties (ecma_object_t *obj_p, /**< object */ bool only_enumerable_properties) /**< list enumerable properties? */ { JERRY_ASSERT (obj_p != NULL); ecma_value_t new_array = ecma_op_create_array_object (NULL, 0, false); JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_array)); ecma_object_t *new_array_p = ecma_get_object_from_value (new_array); uint32_t index = 0; ecma_collection_header_t *props_p = ecma_op_object_get_property_names (obj_p, false, only_enumerable_properties, false); ecma_collection_iterator_t iter; ecma_collection_iterator_init (&iter, props_p); while (ecma_collection_iterator_next (&iter)) { ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); ecma_value_t completion = ecma_builtin_helper_def_prop (new_array_p, index_string_p, *iter.current_value_p, true, /* Writable */ true, /* Enumerable */ true, /* Configurable */ false); /* Failure handling */ JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (index_string_p); index++; } ecma_free_values_collection (props_p, true); return new_array; } /* ecma_builtin_helper_object_get_properties */
/** * The Object.keys and Object.getOwnPropertyName routine's common part. * * See also: * ECMA-262 v5, 15.2.3.4 steps 2-5 * ECMA-262 v5, 15.2.3.14 steps 3-6 * * @return completion value - Array of property names. * Returned value must be freed with ecma_free_completion_value. */ ecma_completion_value_t ecma_builtin_helper_object_get_properties (ecma_object_t *obj_p, /** < object */ bool only_enumerable_properties) /** < list enumerable properties? */ { JERRY_ASSERT (obj_p != NULL); ecma_completion_value_t new_array = ecma_op_create_array_object (NULL, 0, false); JERRY_ASSERT (ecma_is_completion_value_normal (new_array)); ecma_object_t *new_array_p = ecma_get_object_from_completion_value (new_array); uint32_t index = 0; for (ecma_property_t *property_p = ecma_get_property_list (obj_p); property_p != NULL; property_p = ECMA_GET_POINTER (ecma_property_t, property_p->next_property_p)) { ecma_string_t *property_name_p; if (property_p->type == ECMA_PROPERTY_NAMEDDATA) { property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, property_p->u.named_data_property.name_p); } else if (property_p->type == ECMA_PROPERTY_NAMEDACCESSOR) { property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, property_p->u.named_accessor_property.name_p); } else { continue; } if (only_enumerable_properties && !ecma_is_property_enumerable (property_p)) { continue; } JERRY_ASSERT (property_name_p != NULL); ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); ecma_property_descriptor_t item_prop_desc = ecma_make_empty_property_descriptor (); { item_prop_desc.is_value_defined = true; item_prop_desc.value = ecma_make_string_value (property_name_p); item_prop_desc.is_writable_defined = true; item_prop_desc.is_writable = true; item_prop_desc.is_enumerable_defined = true; item_prop_desc.is_enumerable = true; item_prop_desc.is_configurable_defined = true; item_prop_desc.is_configurable = true; } ecma_completion_value_t completion = ecma_op_object_define_own_property (new_array_p, index_string_p, &item_prop_desc, false); JERRY_ASSERT (ecma_is_completion_value_normal_true (completion)); ecma_free_completion_value (completion); ecma_deref_ecma_string (index_string_p); index++; } return new_array; } /* ecma_builtin_helper_object_get_properties */
/** * RegExp helper function to start the recursive matching algorithm * and create the result Array object * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_regexp_exec_helper (ecma_value_t regexp_value, /**< RegExp object */ ecma_value_t input_string, /**< input string */ bool ignore_global) /**< ignore global flag */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); JERRY_ASSERT (ecma_is_value_object (regexp_value)); JERRY_ASSERT (ecma_is_value_string (input_string)); ecma_object_t *regexp_object_p = ecma_get_object_from_value (regexp_value); JERRY_ASSERT (ecma_object_get_class_name (regexp_object_p) == LIT_MAGIC_STRING_REGEXP_UL); ecma_property_t *bytecode_prop_p = ecma_get_internal_property (regexp_object_p, ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE); re_bytecode_t *bc_p = ECMA_GET_POINTER (re_bytecode_t, bytecode_prop_p->u.internal_property.value); ecma_string_t *input_string_p = ecma_get_string_from_value (input_string); lit_utf8_size_t input_string_size = ecma_string_get_size (input_string_p); MEM_DEFINE_LOCAL_ARRAY (input_utf8_buffer_p, input_string_size, lit_utf8_byte_t); ecma_string_to_utf8_string (input_string_p, input_utf8_buffer_p, (ssize_t) input_string_size); lit_utf8_iterator_t iterator = lit_utf8_iterator_create (input_utf8_buffer_p, input_string_size); re_matcher_ctx_t re_ctx; re_ctx.input_start_p = iterator.buf_p; re_ctx.input_end_p = iterator.buf_p + iterator.buf_size; /* 1. Read bytecode header and init regexp matcher context. */ re_ctx.flags = (uint8_t) re_get_value (&bc_p); if (ignore_global) { re_ctx.flags &= (uint8_t) ~RE_FLAG_GLOBAL; } JERRY_DDLOG ("Exec with flags [global: %d, ignoreCase: %d, multiline: %d]\n", re_ctx.flags & RE_FLAG_GLOBAL, re_ctx.flags & RE_FLAG_IGNORE_CASE, re_ctx.flags & RE_FLAG_MULTILINE); re_ctx.num_of_captures = re_get_value (&bc_p); JERRY_ASSERT (re_ctx.num_of_captures % 2 == 0); re_ctx.num_of_non_captures = re_get_value (&bc_p); /* We create an invalid iterator, that will be used to identify unused result values. */ lit_utf8_iterator_t unused_iter = lit_utf8_iterator_create (NULL, 0); unused_iter.buf_p = (lit_utf8_byte_t *) 1; MEM_DEFINE_LOCAL_ARRAY (saved_p, re_ctx.num_of_captures + re_ctx.num_of_non_captures, lit_utf8_iterator_t); for (uint32_t i = 0; i < re_ctx.num_of_captures + re_ctx.num_of_non_captures; i++) { saved_p[i] = unused_iter; } re_ctx.saved_p = saved_p; uint32_t num_of_iter_length = (re_ctx.num_of_captures / 2) + (re_ctx.num_of_non_captures - 1); MEM_DEFINE_LOCAL_ARRAY (num_of_iter_p, num_of_iter_length, uint32_t); for (uint32_t i = 0; i < num_of_iter_length; i++) { num_of_iter_p[i] = 0u; } bool is_match = false; re_ctx.num_of_iterations_p = num_of_iter_p; int32_t index = 0; ecma_length_t input_str_len = lit_utf8_string_length (iterator.buf_p, iterator.buf_size); if (iterator.buf_p && (re_ctx.flags & RE_FLAG_GLOBAL)) { ecma_string_t *magic_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL); ecma_property_t *lastindex_prop_p = ecma_op_object_get_property (regexp_object_p, magic_str_p); ECMA_OP_TO_NUMBER_TRY_CATCH (lastindex_num, lastindex_prop_p->u.named_data_property.value, ret_value) index = ecma_number_to_int32 (lastindex_num); JERRY_ASSERT (iterator.buf_pos.offset == 0 && !iterator.buf_pos.is_non_bmp_middle); if (!lit_utf8_iterator_is_eos (&iterator) && index <= (int32_t) input_str_len && index > 0) { lit_utf8_iterator_advance (&iterator, (ecma_length_t) index); } ECMA_OP_TO_NUMBER_FINALIZE (lastindex_num); ecma_deref_ecma_string (magic_str_p); } /* 2. Try to match */ lit_utf8_iterator_t sub_iter = lit_utf8_iterator_create (NULL, 0); while (ecma_is_completion_value_empty (ret_value)) { if (index < 0 || index > (int32_t) input_str_len) { if (re_ctx.flags & RE_FLAG_GLOBAL) { ecma_string_t *magic_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL); ecma_number_t *lastindex_num_p = ecma_alloc_number (); *lastindex_num_p = ECMA_NUMBER_ZERO; ecma_op_object_put (regexp_object_p, magic_str_p, ecma_make_number_value (lastindex_num_p), true); ecma_dealloc_number (lastindex_num_p); ecma_deref_ecma_string (magic_str_p); } is_match = false; break; } else { ECMA_TRY_CATCH (match_value, re_match_regexp (&re_ctx, bc_p, iterator, &sub_iter), ret_value); if (ecma_is_value_true (match_value)) { is_match = true; break; } if (!lit_utf8_iterator_is_eos (&iterator)) { lit_utf8_iterator_advance (&iterator, 1); } index++; ECMA_FINALIZE (match_value); } } if (iterator.buf_p && (re_ctx.flags & RE_FLAG_GLOBAL)) { ecma_string_t *magic_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL); ecma_number_t *lastindex_num_p = ecma_alloc_number (); *lastindex_num_p = sub_iter.buf_pos.offset; ecma_op_object_put (regexp_object_p, magic_str_p, ecma_make_number_value (lastindex_num_p), true); ecma_dealloc_number (lastindex_num_p); ecma_deref_ecma_string (magic_str_p); } /* 3. Fill the result array or return with 'undefiend' */ if (ecma_is_completion_value_empty (ret_value)) { if (is_match) { ecma_completion_value_t result_array = ecma_op_create_array_object (0, 0, false); ecma_object_t *result_array_obj_p = ecma_get_object_from_completion_value (result_array); ecma_string_t *input_str_p = ecma_new_ecma_string_from_utf8 (iterator.buf_p, iterator.buf_size); re_set_result_array_properties (result_array_obj_p, input_str_p, re_ctx.num_of_captures / 2, index); ecma_deref_ecma_string (input_str_p); for (uint32_t i = 0; i < re_ctx.num_of_captures; i += 2) { ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (i / 2); /* Note: 'iter_p->buf_p == NULL' means the input is empty string */ if ((re_ctx.saved_p[i].buf_p != unused_iter.buf_p && re_ctx.saved_p[i + 1].buf_p != unused_iter.buf_p) && re_ctx.saved_p[i + 1].buf_pos.offset >= re_ctx.saved_p[i].buf_pos.offset) { ecma_length_t capture_str_len; capture_str_len = (ecma_length_t) re_ctx.saved_p[i + 1].buf_pos.offset - re_ctx.saved_p[i].buf_pos.offset; ecma_string_t *capture_str_p; if (capture_str_len > 0) { const lit_utf8_byte_t *utf8_str_p = re_ctx.saved_p[i].buf_p + re_ctx.saved_p[i].buf_pos.offset; capture_str_p = ecma_new_ecma_string_from_utf8 (utf8_str_p, capture_str_len); } else { capture_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); } ecma_op_object_put (result_array_obj_p, index_str_p, ecma_make_string_value (capture_str_p), true); ecma_deref_ecma_string (capture_str_p); } else { ecma_op_object_put (result_array_obj_p, index_str_p, ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED), true); } ecma_deref_ecma_string (index_str_p); } ret_value = result_array; } else { ret_value = ecma_make_normal_completion_value (ecma_make_simple_value (ECMA_SIMPLE_VALUE_NULL)); } } MEM_FINALIZE_LOCAL_ARRAY (num_of_iter_p); MEM_FINALIZE_LOCAL_ARRAY (saved_p); MEM_FINALIZE_LOCAL_ARRAY (input_utf8_buffer_p); return ret_value; } /* ecma_regexp_exec_helper */
/** * The RegExp.prototype object's 'exec' routine * * See also: * ECMA-262 v5, 15.10.6.2 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_regexp_prototype_exec (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg) /**< routine's argument */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); if (!ecma_is_value_object (this_arg) || ecma_object_get_class_name (ecma_get_object_from_value (this_arg)) != LIT_MAGIC_STRING_REGEXP_UL) { ret_value = ecma_raise_type_error ("Incomplete RegExp type"); } else { ECMA_TRY_CATCH (obj_this, ecma_op_to_object (this_arg), ret_value); ECMA_TRY_CATCH (input_str_value, ecma_op_to_string (arg), ret_value); ecma_property_t *bytecode_prop_p; ecma_object_t *obj_p = ecma_get_object_from_completion_value (obj_this); bytecode_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE); void *bytecode_p = ECMA_GET_POINTER (void, bytecode_prop_p->u.internal_property.value); if (bytecode_p == NULL) { /* Missing bytecode means empty RegExp: '/(?:)/', so always return empty string. */ ecma_completion_value_t result_array = ecma_op_create_array_object (0, 0, false); ecma_object_t *result_array_obj_p = ecma_get_object_from_completion_value (result_array); ecma_string_t *input_str_p = ecma_get_string_from_value (input_str_value); re_set_result_array_properties (result_array_obj_p, input_str_p, 1, 0); ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (0); ecma_string_t *capture_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); ECMA_TRY_CATCH (put_res_value, ecma_op_object_put (result_array_obj_p, index_str_p, ecma_make_string_value (capture_str_p), true), ret_value); ret_value = result_array; ECMA_FINALIZE (put_res_value) ecma_deref_ecma_string (capture_str_p); ecma_deref_ecma_string (index_str_p); } else { ret_value = ecma_regexp_exec_helper (obj_this, input_str_value, false); } ECMA_FINALIZE (input_str_value); ECMA_FINALIZE (obj_this); } return ret_value; } /* ecma_builtin_regexp_prototype_exec */
/** * The String.prototype object's 'match' routine * * See also: * ECMA-262 v5, 15.5.4.10 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_string_prototype_object_match (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg) /**< routine's argument */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); /* 1. */ ECMA_TRY_CATCH (this_check_coercible_value, ecma_op_check_object_coercible (this_arg), ret_value); /* 2. */ ECMA_TRY_CATCH (this_to_string_value, ecma_op_to_string (this_arg), ret_value); ecma_value_t regexp_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 3. */ if (ecma_is_value_object (arg) && ecma_object_get_class_name (ecma_get_object_from_value (arg)) == LIT_MAGIC_STRING_REGEXP_UL) { regexp_value = ecma_copy_value (arg, true); } else { /* 4. */ ecma_value_t regexp_arguments[1] = { arg }; ECMA_TRY_CATCH (new_regexp_value, ecma_builtin_regexp_dispatch_construct (regexp_arguments, 1), ret_value); regexp_value = ecma_copy_value (new_regexp_value, true); ECMA_FINALIZE (new_regexp_value); } if (ecma_is_completion_value_empty (ret_value)) { JERRY_ASSERT (!ecma_is_value_empty (regexp_value)); ecma_object_t *regexp_obj_p = ecma_get_object_from_value (regexp_value); ecma_string_t *global_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_GLOBAL); /* 5. */ ECMA_TRY_CATCH (global_value, ecma_op_object_get (regexp_obj_p, global_string_p), ret_value); JERRY_ASSERT (ecma_is_value_boolean (global_value)); ecma_value_t exec_arguments[1] = { this_to_string_value }; if (!ecma_is_value_true (global_value)) { /* 7. */ ret_value = ecma_builtin_regexp_prototype_dispatch_routine (LIT_MAGIC_STRING_EXEC, regexp_value, exec_arguments, 1); } else { /* 8.a. */ ecma_number_t *zero_number_p = ecma_alloc_number (); *zero_number_p = 0; ecma_string_t *index_zero_string_p = ecma_new_ecma_string_from_uint32 (0); ecma_string_t *last_index_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL); ECMA_TRY_CATCH (put_value, ecma_op_object_put (regexp_obj_p, last_index_string_p, ecma_make_number_value (zero_number_p), true), ret_value); /* 8.b. */ ECMA_TRY_CATCH (new_array_value, ecma_op_create_array_object (NULL, 0, false), ret_value); ecma_object_t *new_array_obj_p = ecma_get_object_from_value (new_array_value); /* 8.c. */ ecma_number_t previous_last_index = 0; /* 8.d. */ uint32_t n = 0; /* 8.e. */ bool last_match = true; //ecma_completion_value_t exec_result = ecma_make_empty_completion_value (); /* 8.f. */ while (last_match && ecma_is_completion_value_empty (ret_value)) { /* 8.f.i. */ ECMA_TRY_CATCH (exec_value, ecma_builtin_regexp_prototype_dispatch_routine (LIT_MAGIC_STRING_EXEC, regexp_value, exec_arguments, 1), ret_value); if (ecma_is_value_null (exec_value)) { /* 8.f.ii. */ last_match = false; } else { /* 8.f.iii. */ ECMA_TRY_CATCH (this_index_value, ecma_op_object_get (regexp_obj_p, last_index_string_p), ret_value); ECMA_TRY_CATCH (this_index_number, ecma_op_to_number (this_index_value), ret_value); ecma_number_t this_index = *ecma_get_number_from_value (this_index_number); /* 8.f.iii.2. */ if (this_index == previous_last_index) { ecma_number_t *new_last_index_p = ecma_alloc_number (); *new_last_index_p = this_index + 1; /* 8.f.iii.2.a. */ ECMA_TRY_CATCH (index_put_value, ecma_op_object_put (regexp_obj_p, last_index_string_p, ecma_make_number_value (new_last_index_p), true), ret_value); /* 8.f.iii.2.b. */ previous_last_index = this_index + 1; ECMA_FINALIZE (index_put_value); ecma_dealloc_number (new_last_index_p); } else { /* 8.f.iii.3. */ previous_last_index = this_index; } if (ecma_is_completion_value_empty (ret_value)) { /* 8.f.iii.4. */ JERRY_ASSERT (ecma_is_value_object (exec_value)); ecma_object_t *exec_obj_p = ecma_get_object_from_value (exec_value); ECMA_TRY_CATCH (match_string_value, ecma_op_object_get (exec_obj_p, index_zero_string_p), ret_value); /* 8.f.iii.5. */ ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_value_defined = true; prop_desc.value = match_string_value; prop_desc.is_writable_defined = true; prop_desc.is_writable = true; prop_desc.is_enumerable_defined = true; prop_desc.is_enumerable = true; prop_desc.is_configurable_defined = true; prop_desc.is_configurable = true; } ecma_string_t *current_index_str_p = ecma_new_ecma_string_from_uint32 (n); ecma_completion_value_t completion = ecma_op_object_define_own_property (new_array_obj_p, current_index_str_p, &prop_desc, false); JERRY_ASSERT (ecma_is_completion_value_normal_true (completion)); ecma_deref_ecma_string (current_index_str_p); /* 8.f.iii.6. */ n++; ECMA_FINALIZE (match_string_value); } ECMA_FINALIZE (this_index_number); ECMA_FINALIZE (this_index_value); } ECMA_FINALIZE (exec_value); } if (ecma_is_completion_value_empty (ret_value)) { if (n == 0) { /* 8.g. */ ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_NULL); } else { /* 8.h. */ ret_value = ecma_make_normal_completion_value (ecma_copy_value (new_array_value, true)); } } ECMA_FINALIZE (new_array_value); ECMA_FINALIZE (put_value); ecma_deref_ecma_string (last_index_string_p); ecma_deref_ecma_string (index_zero_string_p); ecma_dealloc_number (zero_number_p); } ECMA_FINALIZE (global_value); ecma_deref_ecma_string (global_string_p); ecma_free_value (regexp_value, true); } ECMA_FINALIZE (this_to_string_value); ECMA_FINALIZE (this_check_coercible_value); return ret_value; } /* ecma_builtin_string_prototype_object_match */
/** * Parse next value. * * The function fills the fields of the ecma_json_token_t * argument and advances the string pointer. * * @return ecma_value with the property value */ static ecma_value_t ecma_builtin_json_parse_value (ecma_json_token_t *token_p) /**< token argument */ { ecma_builtin_json_parse_next_token (token_p); switch (token_p->type) { case number_token: { ecma_number_t *number_p = ecma_alloc_number (); *number_p = token_p->u.number; return ecma_make_number_value (number_p); } case string_token: { ecma_string_t *string_p = ecma_new_ecma_string_from_utf8 (token_p->u.string.start_p, token_p->u.string.size); return ecma_make_string_value (string_p); } case null_token: { return ecma_make_simple_value (ECMA_SIMPLE_VALUE_NULL); } case true_token: { return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } case false_token: { return ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE); } case left_brace_token: { bool parse_comma = false; ecma_object_t *object_p = ecma_op_create_object_object_noarg (); while (true) { ecma_builtin_json_parse_next_token (token_p); if (token_p->type == right_brace_token) { return ecma_make_object_value (object_p); } if (parse_comma) { if (token_p->type != comma_token) { break; } ecma_builtin_json_parse_next_token (token_p); } if (token_p->type != string_token) { break; } lit_utf8_byte_t *string_start_p = token_p->u.string.start_p; lit_utf8_size_t string_size = token_p->u.string.size; ecma_builtin_json_parse_next_token (token_p); if (token_p->type != colon_token) { break; } ecma_value_t value = ecma_builtin_json_parse_value (token_p); if (ecma_is_value_undefined (value)) { break; } ecma_string_t *name_p = ecma_new_ecma_string_from_utf8 (string_start_p, string_size); ecma_builtin_json_define_value_property (object_p, name_p, value); ecma_deref_ecma_string (name_p); ecma_free_value (value); parse_comma = true; } /* * Parse error occured. */ ecma_deref_object (object_p); return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } case left_square_token: { bool parse_comma = false; uint32_t length = 0; ecma_value_t array_construction = ecma_op_create_array_object (NULL, 0, false); JERRY_ASSERT (!ecma_is_value_error (array_construction)); ecma_object_t *array_p = ecma_get_object_from_value (array_construction); while (true) { if (ecma_builtin_json_check_right_square_token (token_p)) { return ecma_make_object_value (array_p); } if (parse_comma) { ecma_builtin_json_parse_next_token (token_p); if (token_p->type != comma_token) { break; } } ecma_value_t value = ecma_builtin_json_parse_value (token_p); if (ecma_is_value_undefined (value)) { break; } ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (length); ecma_value_t completion = ecma_builtin_helper_def_prop (array_p, index_str_p, value, true, /* Writable */ true, /* Enumerable */ true, /* Configurable */ false); /* Failure handling */ JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (index_str_p); ecma_free_value (value); length++; parse_comma = true; } /* * Parse error occured. */ ecma_deref_object (array_p); return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } default: { return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } } } /* ecma_builtin_json_parse_value */
/** * Get backtrace. The backtrace is an array of strings where * each string contains the position of the corresponding frame. * The array length is zero if the backtrace is not available. * * @return array ecma value */ ecma_value_t vm_get_backtrace (uint32_t max_depth) /**< maximum backtrace depth, 0 = unlimited */ { #ifdef JERRY_ENABLE_LINE_INFO ecma_value_t result_array = ecma_op_create_array_object (NULL, 0, false); if (max_depth == 0) { max_depth = UINT32_MAX; } vm_frame_ctx_t *context_p = JERRY_CONTEXT (vm_top_context_p); ecma_object_t *array_p = ecma_get_object_from_value (result_array); uint32_t index = 0; while (context_p != NULL) { if (context_p->resource_name == ECMA_VALUE_UNDEFINED) { context_p = context_p->prev_context_p; continue; } ecma_string_t *str_p = ecma_get_string_from_value (context_p->resource_name); if (ecma_string_is_empty (str_p)) { const char *unknown_str_p = "<unknown>:"; str_p = ecma_new_ecma_string_from_utf8 ((const lit_utf8_byte_t *) unknown_str_p, (lit_utf8_size_t) strlen (unknown_str_p)); } else { ecma_ref_ecma_string (str_p); str_p = ecma_append_magic_string_to_string (str_p, LIT_MAGIC_STRING_COLON_CHAR); } ecma_string_t *line_str_p = ecma_new_ecma_string_from_uint32 (context_p->current_line); str_p = ecma_concat_ecma_strings (str_p, line_str_p); ecma_deref_ecma_string (line_str_p); ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index); ecma_property_value_t *prop_value_p; prop_value_p = ecma_create_named_data_property (array_p, index_str_p, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, NULL); ecma_deref_ecma_string (index_str_p); prop_value_p->value = ecma_make_string_value (str_p); context_p = context_p->prev_context_p; index++; if (index >= max_depth) { break; } } if (index > 0) { JERRY_ASSERT (ecma_get_object_type (array_p) == ECMA_OBJECT_TYPE_ARRAY); ((ecma_extended_object_t *) array_p)->u.array.length = index; } return result_array; #else /* !JERRY_ENABLE_LINE_INFO */ JERRY_UNUSED (max_depth); return ecma_op_create_array_object (NULL, 0, false); #endif /* JERRY_ENABLE_LINE_INFO */ } /* vm_get_backtrace */