/** * Reject the promise if the value is error. * * See also: * ES2015 25.4.1.1.1 * * @return ecma value of the new promise. * Returned value must be freed with ecma_free_value. */ inline static ecma_value_t ecma_builtin_promise_reject_abrupt (ecma_value_t capability) /**< reject description */ { ecma_value_t reason = JERRY_CONTEXT (error_value); ecma_string_t *str_reject = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_REJECT); ecma_value_t reject = ecma_op_object_get (ecma_get_object_from_value (capability), str_reject); ecma_deref_ecma_string (str_reject); ecma_value_t call_ret = ecma_op_function_call (ecma_get_object_from_value (reject), ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED), &reason, 1); ecma_free_value (reject); if (ECMA_IS_VALUE_ERROR (call_ret)) { return call_ret; } ecma_free_value (call_ret); ecma_string_t *str_promise = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_PROMISE); ecma_value_t promise_new = ecma_op_object_get (ecma_get_object_from_value (capability), str_promise); ecma_deref_ecma_string (str_promise); return promise_new; } /* ecma_builtin_promise_reject_abrupt */
/** * The Array.prototype's 'toLocaleString' single element operation routine * * See also: * ECMA-262 v5, 15.4.4.3 steps 6-8 and 10.b-d * * @return ecma value * Returned value must be freed with ecma_free_value. */ ecma_value_t ecma_builtin_helper_get_to_locale_string_at_index (ecma_object_t *obj_p, /**< this object */ uint32_t index) /**< array index */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); ECMA_TRY_CATCH (index_value, ecma_op_object_get (obj_p, index_string_p), ret_value); if (ecma_is_value_undefined (index_value) || ecma_is_value_null (index_value)) { ecma_string_t *return_string_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); ret_value = ecma_make_string_value (return_string_p); } else { ECMA_TRY_CATCH (index_obj_value, ecma_op_to_object (index_value), ret_value); ecma_object_t *index_obj_p = ecma_get_object_from_value (index_obj_value); ecma_string_t *locale_string_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL); ECMA_TRY_CATCH (to_locale_value, ecma_op_object_get (index_obj_p, locale_string_magic_string_p), ret_value); if (ecma_op_is_callable (to_locale_value)) { ecma_object_t *locale_func_obj_p = ecma_get_object_from_value (to_locale_value); ECMA_TRY_CATCH (call_value, ecma_op_function_call (locale_func_obj_p, ecma_make_object_value (index_obj_p), NULL, 0), ret_value); ret_value = ecma_op_to_string (call_value); ECMA_FINALIZE (call_value); } else { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("")); } ECMA_FINALIZE (to_locale_value); ecma_deref_ecma_string (locale_string_magic_string_p); ECMA_FINALIZE (index_obj_value); } ECMA_FINALIZE (index_value); ecma_deref_ecma_string (index_string_p); return ret_value; } /* ecma_builtin_helper_get_to_locale_string_at_index */
/** * 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 */
/** * Allocate new ecma-string and fill it with ecma-number * * @return pointer to ecma-string descriptor */ ecma_string_t * ecma_new_ecma_string_from_number (ecma_number_t num) /**< ecma-number */ { uint32_t uint32_num = ecma_number_to_uint32 (num); if (num == ((ecma_number_t) uint32_num)) { return ecma_new_ecma_string_from_uint32 (uint32_num); } if (ecma_number_is_nan (num)) { return ecma_get_magic_string (LIT_MAGIC_STRING_NAN); } if (ecma_number_is_infinity (num)) { lit_magic_string_id_t id = (ecma_number_is_negative (num) ? LIT_MAGIC_STRING_NEGATIVE_INFINITY_UL : LIT_MAGIC_STRING_INFINITY_UL); return ecma_get_magic_string (id); } lit_utf8_byte_t str_buf[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER]; lit_utf8_size_t str_size = ecma_number_to_utf8_string (num, str_buf, sizeof (str_buf)); JERRY_ASSERT (str_size > 0); #ifndef JERRY_NDEBUG lit_magic_string_id_t magic_string_id; lit_magic_string_ex_id_t magic_string_ex_id; JERRY_ASSERT (!lit_is_utf8_string_magic (str_buf, str_size, &magic_string_id) && !lit_is_ex_utf8_string_magic (str_buf, str_size, &magic_string_ex_id)); #endif /* !JERRY_NDEBUG */ ecma_string_t *string_desc_p = jmem_heap_alloc_block (sizeof (ecma_string_t) + str_size); string_desc_p->refs_and_container = ECMA_STRING_CONTAINER_HEAP_UTF8_STRING | ECMA_STRING_REF_ONE; string_desc_p->hash = lit_utf8_string_calc_hash (str_buf, str_size); string_desc_p->u.common_field = 0; string_desc_p->u.utf8_string.size = (uint16_t) str_size; string_desc_p->u.utf8_string.length = (uint16_t) str_size; lit_utf8_byte_t *data_p = (lit_utf8_byte_t *) (string_desc_p + 1); memcpy (data_p, str_buf, str_size); return string_desc_p; } /* ecma_new_ecma_string_from_number */
/** * 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 */
/** * List names of a String object's lazy instantiated properties * * @return string values collection */ void ecma_op_string_list_lazy_property_names (ecma_object_t *obj_p, /**< a String object */ bool separate_enumerable, /**< true - list enumerable properties * into main collection, * and non-enumerable to collection of * 'skipped non-enumerable' properties, * false - list all properties into main * collection. */ ecma_collection_header_t *main_collection_p, /**< 'main' * collection */ ecma_collection_header_t *non_enum_collection_p) /**< skipped * 'non-enumerable' * collection */ { JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_CLASS); ecma_collection_header_t *for_enumerable_p = main_collection_p; ecma_collection_header_t *for_non_enumerable_p = separate_enumerable ? non_enum_collection_p : main_collection_p; ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; JERRY_ASSERT (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_STRING_UL); ecma_string_t *prim_value_str_p = ecma_get_string_from_value (ext_object_p->u.class_prop.u.value); ecma_length_t length = ecma_string_get_length (prim_value_str_p); for (ecma_length_t i = 0; i < length; i++) { ecma_string_t *name_p = ecma_new_ecma_string_from_uint32 (i); /* the properties are enumerable (ECMA-262 v5, 15.5.5.2.9) */ ecma_append_to_values_collection (for_enumerable_p, ecma_make_string_value (name_p), 0); ecma_deref_ecma_string (name_p); } ecma_append_to_values_collection (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH), 0); } /* ecma_op_string_list_lazy_property_names */
/** * List names of a String object's lazy instantiated properties * * See also: * ecma_op_string_object_get_own_property * * @return string values collection */ void ecma_op_string_list_lazy_property_names (ecma_object_t *obj_p, /**< a String object */ bool separate_enumerable, /**< true - list enumerable properties * into main collection, * and non-enumerable to collection of * 'skipped non-enumerable' properties, * false - list all properties into main * collection. */ ecma_collection_header_t *main_collection_p, /**< 'main' * collection */ ecma_collection_header_t *non_enum_collection_p) /**< skipped * 'non-enumerable' * collection */ { JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_STRING); ecma_collection_header_t *for_enumerable_p = main_collection_p; ecma_collection_header_t *for_non_enumerable_p = separate_enumerable ? main_collection_p : non_enum_collection_p; JERRY_UNUSED (for_non_enumerable_p); ecma_property_t *prim_value_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_ECMA_VALUE); ecma_string_t *prim_value_str_p; prim_value_str_p = ecma_get_string_from_value (ecma_get_internal_property_value (prim_value_prop_p)); ecma_length_t length = ecma_string_get_length (prim_value_str_p); for (ecma_length_t i = 0; i < length; i++) { ecma_string_t *name_p = ecma_new_ecma_string_from_uint32 (i); /* the properties are enumerable (ECMA-262 v5, 15.5.5.2.9) */ ecma_append_to_values_collection (for_enumerable_p, ecma_make_string_value (name_p), true); ecma_deref_ecma_string (name_p); } } /* ecma_op_string_list_lazy_property_names */
/** * 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_value_t result_array = ecma_op_create_array_object (0, 0, false); ecma_object_t *result_array_obj_p = ecma_get_object_from_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 */
* * @return ecma value of undefined. */ static ecma_value_t ecma_builtin_promise_all_handler (const ecma_value_t function, /**< the function itself */ const ecma_value_t this, /**< this_arg of the function */ const ecma_value_t argv[], /**< argument list */ const ecma_length_t argc) /**< argument number */ { JERRY_UNUSED (this); JERRY_UNUSED (argc); ecma_value_t ret = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); /* 1. */ ecma_object_t *function_p = ecma_get_object_from_value (function); ecma_string_t *str_already_called = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_ALREADY_CALLED); ecma_value_t already_called = ecma_op_object_get (function_p, str_already_called); JERRY_ASSERT (ecma_is_value_boolean (already_called)); /* 2. */ if (ecma_is_value_true (already_called)) { ecma_fast_free_value (already_called); ecma_deref_ecma_string (str_already_called); return ret; } /* 3. */ ecma_op_object_put (function_p,
/** * [[DefineOwnProperty]] ecma array object's operation * * See also: * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 * ECMA-262 v5, 15.4.5.1 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_array_object_define_own_property (ecma_object_t *obj_p, /**< the array object */ ecma_string_t *property_name_p, /**< property name */ const ecma_property_descriptor_t* property_desc_p, /**< property descriptor */ bool is_throw) /**< flag that controls failure handling */ { JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY); // 1. ecma_string_t* magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_property_t *len_prop_p = ecma_op_object_get_own_property (obj_p, magic_string_length_p); JERRY_ASSERT (len_prop_p != NULL && len_prop_p->type == ECMA_PROPERTY_NAMEDDATA); // 2. ecma_value_t old_len_value = ecma_get_named_data_property_value (len_prop_p); ecma_number_t *num_p = ecma_get_number_from_value (old_len_value); uint32_t old_len_uint32 = ecma_number_to_uint32 (*num_p); // 3. bool is_property_name_equal_length = ecma_compare_ecma_strings (property_name_p, magic_string_length_p); ecma_deref_ecma_string (magic_string_length_p); if (is_property_name_equal_length) { // a. if (!property_desc_p->is_value_defined) { // i. return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p, is_throw); } ecma_number_t new_len_num; // c. ecma_completion_value_t completion = ecma_op_to_number (property_desc_p->value); if (ecma_is_completion_value_throw (completion)) { return completion; } JERRY_ASSERT (ecma_is_completion_value_normal (completion) && ecma_is_value_number (ecma_get_completion_value_value (completion))); new_len_num = *ecma_get_number_from_completion_value (completion); ecma_free_completion_value (completion); uint32_t new_len_uint32 = ecma_number_to_uint32 (new_len_num); // d. if (ecma_uint32_to_number (new_len_uint32) != new_len_num) { return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_RANGE)); } else { // b., e. ecma_number_t *new_len_num_p = ecma_alloc_number (); *new_len_num_p = new_len_num; ecma_property_descriptor_t new_len_property_desc = *property_desc_p; new_len_property_desc.value = ecma_make_number_value (new_len_num_p); ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); // f. if (new_len_uint32 >= old_len_uint32) { // i. magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ret_value = ecma_op_general_object_define_own_property (obj_p, magic_string_length_p, &new_len_property_desc, is_throw); ecma_deref_ecma_string (magic_string_length_p); } else { // g. if (!ecma_is_property_writable (len_prop_p)) { ret_value = ecma_reject (is_throw); } else { // h. bool new_writable; if (!new_len_property_desc.is_writable_defined || new_len_property_desc.is_writable) { new_writable = true; } else { // ii. new_writable = false; // iii. new_len_property_desc.is_writable_defined = true; new_len_property_desc.is_writable = true; } // j. magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_completion_value_t succeeded = ecma_op_general_object_define_own_property (obj_p, magic_string_length_p, &new_len_property_desc, is_throw); ecma_deref_ecma_string (magic_string_length_p); /* Handling normal false and throw values */ if (!ecma_is_completion_value_normal_true (succeeded)) { JERRY_ASSERT (ecma_is_completion_value_normal_false (succeeded) || ecma_is_completion_value_throw (succeeded)); // k. ret_value = succeeded; } else { // l JERRY_ASSERT (new_len_uint32 < old_len_uint32); bool reduce_succeeded = true; while (new_len_uint32 < old_len_uint32) { // i old_len_uint32--; // ii ecma_string_t *old_length_string_p = ecma_new_ecma_string_from_uint32 (old_len_uint32); ecma_completion_value_t delete_succeeded = ecma_op_object_delete (obj_p, old_length_string_p, false); ecma_deref_ecma_string (old_length_string_p); // iii if (ecma_is_completion_value_normal_false (delete_succeeded)) { JERRY_ASSERT (ecma_is_value_number (new_len_property_desc.value)); ecma_number_t *new_len_num_p = ecma_get_number_from_value (new_len_property_desc.value); // 1. *new_len_num_p = ecma_uint32_to_number (old_len_uint32 + 1); // 2. if (!new_writable) { new_len_property_desc.is_writable_defined = true; new_len_property_desc.is_writable = false; } // 3. ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_completion_value_t completion = ecma_op_general_object_define_own_property (obj_p, magic_string_length_p, &new_len_property_desc, false); ecma_deref_ecma_string (magic_string_length_p); JERRY_ASSERT (ecma_is_completion_value_normal_true (completion) || ecma_is_completion_value_normal_false (completion)); reduce_succeeded = false; break; } } if (!reduce_succeeded) { ret_value = ecma_reject (is_throw); } else { // m. if (!new_writable) { ecma_property_descriptor_t prop_desc_not_writable = ecma_make_empty_property_descriptor (); prop_desc_not_writable.is_writable_defined = true; prop_desc_not_writable.is_writable = false; ecma_completion_value_t completion_set_not_writable; magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); completion_set_not_writable = ecma_op_general_object_define_own_property (obj_p, magic_string_length_p, &prop_desc_not_writable, false); ecma_deref_ecma_string (magic_string_length_p); JERRY_ASSERT (ecma_is_completion_value_normal_true (completion_set_not_writable)); } ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE); } } } } ecma_dealloc_number (new_len_num_p); return ret_value; } JERRY_UNREACHABLE (); } else { // 4.a. uint32_t index; if (!ecma_string_get_array_index (property_name_p, &index)) { // 5. return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p, is_throw); } // 4. // b. if (index >= old_len_uint32 && !ecma_is_property_writable (len_prop_p)) { return ecma_reject (is_throw); } // c. ecma_completion_value_t succeeded = ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p, false); // d. JERRY_ASSERT (ecma_is_completion_value_normal_true (succeeded) || ecma_is_completion_value_normal_false (succeeded)); if (ecma_is_completion_value_normal_false (succeeded)) { return ecma_reject (is_throw); } // e. if (index >= old_len_uint32) { // i., ii. ecma_number_t *num_p = ecma_alloc_number (); *num_p = ecma_number_add (ecma_uint32_to_number (index), ECMA_NUMBER_ONE); ecma_named_data_property_assign_value (obj_p, len_prop_p, ecma_make_number_value (num_p)); ecma_dealloc_number (num_p); } // f. return ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE); } JERRY_UNREACHABLE (); } /* ecma_op_array_object_define_own_property */
/** * The processor for PromiseReactionJob. * * See also: ES2015 25.4.2.1 * * @return ecma value * Returned value must be freed with ecma_free_value */ static ecma_value_t ecma_process_promise_reaction_job (void *obj_p) /**< the job to be operated */ { ecma_job_promise_reaction_t *job_p = (ecma_job_promise_reaction_t *) obj_p; ecma_object_t *reaction_p = ecma_get_object_from_value (job_p->reaction); ecma_string_t *str_capability = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_CAPABILITY); ecma_string_t *str_handler = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_HANDLER); ecma_string_t *str_resolve = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_RESOLVE); ecma_string_t *str_reject = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_REJECT); /* 2. */ ecma_value_t capability = ecma_op_object_get (reaction_p, str_capability); /* 3. */ ecma_value_t handler = ecma_op_object_get (reaction_p, str_handler); JERRY_ASSERT (ecma_is_value_boolean (handler) || ecma_op_is_callable (handler)); ecma_value_t handler_result; if (ecma_is_value_boolean (handler)) { /* 4-5. True indicates "identity" and false indicates "thrower" */ handler_result = ecma_copy_value (job_p->argument); } else { /* 6. */ handler_result = ecma_op_function_call (ecma_get_object_from_value (handler), ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED), &(job_p->argument), 1); } ecma_value_t status; if (ecma_is_value_false (handler) || ECMA_IS_VALUE_ERROR (handler_result)) { if (ECMA_IS_VALUE_ERROR (handler_result)) { handler_result = ecma_get_value_from_error_value (handler_result); } /* 7. */ ecma_value_t reject = ecma_op_object_get (ecma_get_object_from_value (capability), str_reject); JERRY_ASSERT (ecma_op_is_callable (reject)); status = ecma_op_function_call (ecma_get_object_from_value (reject), ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED), &handler_result, 1); ecma_free_value (reject); } else { /* 8. */ ecma_value_t resolve = ecma_op_object_get (ecma_get_object_from_value (capability), str_resolve); JERRY_ASSERT (ecma_op_is_callable (resolve)); status = ecma_op_function_call (ecma_get_object_from_value (resolve), ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED), &handler_result, 1); ecma_free_value (resolve); } ecma_free_value (handler_result); ecma_free_value (handler); ecma_free_value (capability); ecma_deref_ecma_string (str_capability); ecma_deref_ecma_string (str_handler); ecma_deref_ecma_string (str_resolve); ecma_deref_ecma_string (str_reject); ecma_free_promise_reaction_job (job_p); return status; } /* ecma_process_promise_reaction_job */
/** * Array object creation operation. * * See also: ECMA-262 v5, 15.4.2.1 * ECMA-262 v5, 15.4.2.2 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_create_array_object (const ecma_value_t *arguments_list_p, /**< list of arguments that are passed to Array constructor */ ecma_length_t arguments_list_len, /**< length of the arguments' list */ bool is_treat_single_arg_as_length) /**< if the value is true, arguments_list_len is 1 and single argument is Number, then treat the single argument as new Array's length rather than as single item of the Array */ { JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); uint32_t length; const ecma_value_t *array_items_p; ecma_length_t array_items_count; if (is_treat_single_arg_as_length && arguments_list_len == 1 && ecma_is_value_number (arguments_list_p[0])) { ecma_number_t num = ecma_get_number_from_value (arguments_list_p[0]); uint32_t num_uint32 = ecma_number_to_uint32 (num); if (num != ((ecma_number_t) num_uint32)) { return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid array length.")); } else { length = num_uint32; array_items_p = NULL; array_items_count = 0; } } else { length = arguments_list_len; array_items_p = arguments_list_p; array_items_count = arguments_list_len; } #ifndef CONFIG_DISABLE_ARRAY_BUILTIN ecma_object_t *array_prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_ARRAY_PROTOTYPE); #else /* CONFIG_DISABLE_ARRAY_BUILTIN */ ecma_object_t *array_prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); #endif /* !CONFIG_DISABLE_ARRAY_BUILTIN */ ecma_object_t *obj_p = ecma_create_object (array_prototype_obj_p, 0, ECMA_OBJECT_TYPE_ARRAY); ecma_deref_object (array_prototype_obj_p); /* * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_ARRAY type. * * See also: ecma_object_get_class_name */ ecma_string_t *length_magic_string_p = ecma_new_ecma_length_string (); ecma_property_value_t *length_prop_value_p; length_prop_value_p = ecma_create_named_data_property (obj_p, length_magic_string_p, ECMA_PROPERTY_FLAG_WRITABLE, NULL); length_prop_value_p->value = ecma_make_number_value ((ecma_number_t) length); ecma_deref_ecma_string (length_magic_string_p); for (uint32_t index = 0; index < array_items_count; index++) { if (ecma_is_value_array_hole (array_items_p[index])) { continue; } ecma_string_t *item_name_string_p = ecma_new_ecma_string_from_uint32 (index); ecma_builtin_helper_def_prop (obj_p, item_name_string_p, array_items_p[index], true, /* Writable */ true, /* Enumerable */ true, /* Configurable */ false); /* Failure handling */ ecma_deref_ecma_string (item_name_string_p); } return ecma_make_object_value (obj_p); } /* ecma_op_create_array_object */
/** * 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 */
/** * 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 */
/** * [[DefineOwnProperty]] ecma array object's operation * * See also: * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 * ECMA-262 v5, 15.4.5.1 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_array_object_define_own_property (ecma_object_t *obj_p, /**< the array object */ ecma_string_t *property_name_p, /**< property name */ const ecma_property_descriptor_t *property_desc_p, /**< property descriptor */ bool is_throw) /**< flag that controls failure handling */ { JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY); // 1. ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_property_t *len_prop_p = ecma_op_object_get_own_property (obj_p, magic_string_length_p); JERRY_ASSERT (len_prop_p != NULL && len_prop_p->type == ECMA_PROPERTY_NAMEDDATA); // 2. ecma_value_t old_len_value = ecma_get_named_data_property_value (len_prop_p); ecma_number_t *num_p = ecma_get_number_from_value (old_len_value); uint32_t old_len_uint32 = ecma_number_to_uint32 (*num_p); // 3. bool is_property_name_equal_length = ecma_compare_ecma_strings (property_name_p, magic_string_length_p); ecma_deref_ecma_string (magic_string_length_p); if (is_property_name_equal_length) { // a. if (!property_desc_p->is_value_defined) { // i. return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p, is_throw); } ecma_number_t new_len_num; // c. ecma_completion_value_t completion = ecma_op_to_number (property_desc_p->value); if (ecma_is_completion_value_throw (completion)) { return completion; } JERRY_ASSERT (ecma_is_completion_value_normal (completion) && ecma_is_value_number (ecma_get_completion_value_value (completion))); new_len_num = *ecma_get_number_from_completion_value (completion); ecma_free_completion_value (completion); uint32_t new_len_uint32 = ecma_number_to_uint32 (new_len_num); // d. if (ecma_uint32_to_number (new_len_uint32) != new_len_num) { return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_RANGE)); } else { // b., e. ecma_number_t *new_len_num_p = ecma_alloc_number (); *new_len_num_p = new_len_num; ecma_property_descriptor_t new_len_property_desc = *property_desc_p; new_len_property_desc.value = ecma_make_number_value (new_len_num_p); ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); // f. if (new_len_uint32 >= old_len_uint32) { // i. magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ret_value = ecma_op_general_object_define_own_property (obj_p, magic_string_length_p, &new_len_property_desc, is_throw); ecma_deref_ecma_string (magic_string_length_p); } else { // g. if (!ecma_is_property_writable (len_prop_p)) { ret_value = ecma_reject (is_throw); } else { // h. bool new_writable; if (!new_len_property_desc.is_writable_defined || new_len_property_desc.is_writable) { new_writable = true; } else { // ii. new_writable = false; // iii. new_len_property_desc.is_writable_defined = true; new_len_property_desc.is_writable = true; } // j. magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_completion_value_t succeeded = ecma_op_general_object_define_own_property (obj_p, magic_string_length_p, &new_len_property_desc, is_throw); ecma_deref_ecma_string (magic_string_length_p); /* Handling normal false and throw values */ if (!ecma_is_completion_value_normal_true (succeeded)) { JERRY_ASSERT (ecma_is_completion_value_normal_false (succeeded) || ecma_is_completion_value_throw (succeeded)); // k. ret_value = succeeded; } else { // l JERRY_ASSERT (new_len_uint32 < old_len_uint32); /* * Item i. is replaced with faster iteration: only indices that actually exist in the array, are iterated */ bool is_reduce_succeeded = true; ecma_collection_header_t *array_index_props_p = ecma_op_object_get_property_names (obj_p, true, false, false); ecma_length_t array_index_props_num = array_index_props_p->unit_number; MEM_DEFINE_LOCAL_ARRAY (array_index_values_p, array_index_props_num, uint32_t); ecma_collection_iterator_t iter; ecma_collection_iterator_init (&iter, array_index_props_p); uint32_t array_index_values_pos = 0; while (ecma_collection_iterator_next (&iter)) { ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p); uint32_t index; bool is_index = ecma_string_get_array_index (property_name_p, &index); JERRY_ASSERT (is_index); JERRY_ASSERT (index < old_len_uint32); array_index_values_p[array_index_values_pos++] = index; } JERRY_ASSERT (array_index_values_pos == array_index_props_num); while (array_index_values_pos != 0 && array_index_values_p[--array_index_values_pos] >= new_len_uint32) { uint32_t index = array_index_values_p[array_index_values_pos]; // ii. ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); ecma_completion_value_t delete_succeeded = ecma_op_object_delete (obj_p, index_string_p, false); ecma_deref_ecma_string (index_string_p); if (ecma_is_completion_value_normal_false (delete_succeeded)) { // iii. new_len_uint32 = (index + 1u); ecma_number_t *new_len_num_p = ecma_get_number_from_value (new_len_property_desc.value); // 1. *new_len_num_p = ecma_uint32_to_number (index + 1u); // 2. if (!new_writable) { new_len_property_desc.is_writable_defined = true; new_len_property_desc.is_writable = false; } // 3. ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_completion_value_t completion = ecma_op_general_object_define_own_property (obj_p, magic_string_length_p, &new_len_property_desc, false); ecma_deref_ecma_string (magic_string_length_p); JERRY_ASSERT (ecma_is_completion_value_normal_true (completion) || ecma_is_completion_value_normal_false (completion)); is_reduce_succeeded = false; break; } } MEM_FINALIZE_LOCAL_ARRAY (array_index_values_p); ecma_free_values_collection (array_index_props_p, true); if (!is_reduce_succeeded) { ret_value = ecma_reject (is_throw); } else { // m. if (!new_writable) { ecma_property_descriptor_t prop_desc_not_writable = ecma_make_empty_property_descriptor (); prop_desc_not_writable.is_writable_defined = true; prop_desc_not_writable.is_writable = false; ecma_completion_value_t completion_set_not_writable; magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); completion_set_not_writable = ecma_op_general_object_define_own_property (obj_p, magic_string_length_p, &prop_desc_not_writable, false); ecma_deref_ecma_string (magic_string_length_p); JERRY_ASSERT (ecma_is_completion_value_normal_true (completion_set_not_writable)); } ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE); } } } } ecma_dealloc_number (new_len_num_p); return ret_value; } JERRY_UNREACHABLE (); } else { // 4.a. uint32_t index; if (!ecma_string_get_array_index (property_name_p, &index)) { // 5. return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p, is_throw); } // 4. // b. if (index >= old_len_uint32 && !ecma_is_property_writable (len_prop_p)) { return ecma_reject (is_throw); } // c. ecma_completion_value_t succeeded = ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p, false); // d. JERRY_ASSERT (ecma_is_completion_value_normal_true (succeeded) || ecma_is_completion_value_normal_false (succeeded)); if (ecma_is_completion_value_normal_false (succeeded)) { return ecma_reject (is_throw); } // e. if (index >= old_len_uint32) { // i., ii. ecma_number_t *num_p = ecma_alloc_number (); *num_p = ecma_number_add (ecma_uint32_to_number (index), ECMA_NUMBER_ONE); ecma_named_data_property_assign_value (obj_p, len_prop_p, ecma_make_number_value (num_p)); ecma_dealloc_number (num_p); } // f. return ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE); } JERRY_UNREACHABLE (); } /* ecma_op_array_object_define_own_property */
/** * 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 */
/** * Runtime Semantics: PerformPromiseRace. * * See also: * ES2015 25.4.4.3.1 * * @return ecma value of the new promise. * Returned value must be freed with ecma_free_value. */ inline static ecma_value_t ecma_builtin_promise_do_race (ecma_value_t array, /**< the array for race */ ecma_value_t capability, /**< PromiseCapability record */ ecma_value_t ctor) /**< the caller of Promise.race */ { JERRY_ASSERT (ecma_is_value_object (capability) && ecma_is_value_object (array) && ecma_is_value_object (ctor)); JERRY_ASSERT (ecma_get_object_builtin_id (ecma_get_object_from_value (ctor)) == ECMA_BUILTIN_ID_PROMISE); JERRY_ASSERT (ecma_get_object_type (ecma_get_object_from_value (array)) == ECMA_OBJECT_TYPE_ARRAY); ecma_value_t ret = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ecma_string_t *magic_string_length_p = ecma_new_ecma_length_string (); ecma_object_t *array_p = ecma_get_object_from_value (array); ecma_value_t len_value = ecma_op_object_get (array_p, magic_string_length_p); ecma_deref_ecma_string (magic_string_length_p); ecma_length_t len = (ecma_length_t) ecma_get_integer_from_value (len_value); ecma_fast_free_value (len_value); ecma_string_t *str_promise = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_PROMISE); ecma_string_t *str_resolve = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_RESOLVE); ecma_string_t *str_reject = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_REJECT); ecma_value_t resolve = ecma_op_object_get (ecma_get_object_from_value (capability), str_resolve); ecma_value_t reject = ecma_op_object_get (ecma_get_object_from_value (capability), str_reject); for (ecma_length_t index = 0; index <= len; index++) { /* b-d. */ if (index == len) { ret = ecma_op_object_get (ecma_get_object_from_value (capability), str_promise); break; } /* e. */ ecma_string_t *str_index = ecma_new_ecma_string_from_uint32 (index); ecma_value_t array_item = ecma_op_object_get (array_p, str_index); ecma_deref_ecma_string (str_index); /* h. */ ecma_value_t next_promise = ecma_builtin_promise_resolve (ctor, array_item); ecma_free_value (array_item); /* i. */ if (ECMA_IS_VALUE_ERROR (next_promise)) { ret = next_promise; break; } /* j. */ ecma_value_t then_result = ecma_promise_then (next_promise, resolve, reject); ecma_free_value (next_promise); /* k. */ if (ECMA_IS_VALUE_ERROR (then_result)) { ret = then_result; break; } ecma_free_value (then_result); } ecma_free_value (reject); ecma_free_value (resolve); ecma_deref_ecma_string (str_promise); ecma_deref_ecma_string (str_resolve); ecma_deref_ecma_string (str_reject); JERRY_ASSERT (!ecma_is_value_empty (ret)); return ret; } /* ecma_builtin_promise_do_race */
/** * The Function.prototype object's 'apply' routine * * See also: * ECMA-262 v5, 15.3.4.3 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_function_prototype_object_apply (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg1, /**< first argument */ ecma_value_t arg2) /**< second argument */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); /* 1. */ if (!ecma_op_is_callable (this_arg)) { ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } else { ecma_object_t *func_obj_p = ecma_get_object_from_value (this_arg); /* 2. */ if (ecma_is_value_null (arg2) || ecma_is_value_undefined (arg2)) { ret_value = ecma_op_function_call (func_obj_p, arg1, NULL); } else { /* 3. */ if (!ecma_is_value_object (arg2)) { ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } else { ecma_object_t *obj_p = ecma_get_object_from_value (arg2); ecma_string_t *length_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); /* 4. */ ECMA_TRY_CATCH (length_value, ecma_op_object_get (obj_p, length_magic_string_p), ret_value); ECMA_OP_TO_NUMBER_TRY_CATCH (length_number, length_value, ret_value); /* 5. */ const uint32_t length = ecma_number_to_uint32 (length_number); /* 6. */ ecma_collection_header_t *arg_collection_p = ecma_new_values_collection (NULL, 0, true); /* 7. */ for (uint32_t index = 0; index < length && ecma_is_completion_value_empty (ret_value); index++) { ecma_string_t *curr_idx_str_p = ecma_new_ecma_string_from_uint32 (index); ECMA_TRY_CATCH (get_value, ecma_op_object_get (obj_p, curr_idx_str_p), ret_value); ecma_append_to_values_collection (arg_collection_p, get_value, true); ECMA_FINALIZE (get_value); ecma_deref_ecma_string (curr_idx_str_p); } JERRY_ASSERT (arg_collection_p->unit_number == length || !ecma_is_completion_value_empty (ret_value)); if (ecma_is_completion_value_empty (ret_value)) { ret_value = ecma_op_function_call (func_obj_p, arg1, arg_collection_p); } ecma_free_values_collection (arg_collection_p, true); ECMA_OP_TO_NUMBER_FINALIZE (length_number); ECMA_FINALIZE (length_value); ecma_deref_ecma_string (length_magic_string_p); } } } return ret_value; } /* ecma_builtin_function_prototype_object_apply */
/** * 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 */
/** * The common function for 'reject' and 'resolve'. * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_promise_reject_or_resolve (ecma_value_t this_arg, /**< "this" argument */ ecma_value_t argument, /**< argument for reject or resolve */ bool is_resolve) /**< whether it is for resolve routine */ { if (!ecma_is_value_object (this_arg)) { return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not an object.")); } uint8_t builtin_id = ecma_get_object_builtin_id (ecma_get_object_from_value (this_arg)); if (builtin_id != ECMA_BUILTIN_ID_PROMISE) { return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not the Promise constructor.")); } if (is_resolve && ecma_is_value_object (argument) && ecma_is_promise (ecma_get_object_from_value (argument))) { return ecma_copy_value (argument); } ecma_value_t capability = ecma_promise_new_capability (); if (ECMA_IS_VALUE_ERROR (capability)) { return capability; } ecma_string_t *str; if (is_resolve) { str = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_RESOLVE); } else { str = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_REJECT); } ecma_value_t func = ecma_op_object_get (ecma_get_object_from_value (capability), str); ecma_deref_ecma_string (str); ecma_value_t call_ret = ecma_op_function_call (ecma_get_object_from_value (func), ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED), &argument, 1); ecma_free_value (func); if (ECMA_IS_VALUE_ERROR (call_ret)) { return call_ret; } ecma_free_value (call_ret); ecma_string_t *str_promise = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_PROMISE); ecma_value_t promise_new = ecma_op_object_get (ecma_get_object_from_value (capability), str_promise); ecma_deref_ecma_string (str_promise); ecma_free_value (capability); return promise_new; } /* ecma_builtin_promise_reject_or_resolve */
/** * The JSON object's 'stringify' routine * * See also: * ECMA-262 v5, 15.12.3 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_json_stringify (ecma_value_t this_arg __attr_unused___, /**< 'this' argument */ ecma_value_t arg1, /**< value */ ecma_value_t arg2, /**< replacer */ ecma_value_t arg3) /**< space */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ecma_json_stringify_context_t context; /* 1. */ context.occurence_stack_p = ecma_new_values_collection (NULL, 0, false); /* 2. */ context.indent_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); /* 3. */ context.property_list_p = ecma_new_values_collection (NULL, 0, false); context.replacer_function_p = NULL; /* 4. */ if (ecma_is_value_object (arg2)) { ecma_object_t *obj_p = ecma_get_object_from_value (arg2); /* 4.a */ if (ecma_op_is_callable (arg2)) { context.replacer_function_p = obj_p; } /* 4.b */ else if (ecma_object_get_class_name (obj_p) == LIT_MAGIC_STRING_ARRAY_UL) { ecma_string_t *length_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ECMA_TRY_CATCH (array_length, ecma_op_object_get (obj_p, length_str_p), ret_value); ECMA_OP_TO_NUMBER_TRY_CATCH (array_length_num, array_length, ret_value); uint32_t array_length = ecma_number_to_uint32 (array_length_num); uint32_t index = 0; /* 4.b.ii */ while ((index < array_length) && ecma_is_value_empty (ret_value)) { ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index); ECMA_TRY_CATCH (value, ecma_op_object_get (obj_p, index_str_p), ret_value); /* 4.b.ii.1 */ ecma_value_t item = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); /* 4.b.ii.2 */ if (ecma_is_value_string (value)) { item = ecma_copy_value (value, true); } /* 4.b.ii.3 */ else if (ecma_is_value_number (value)) { ECMA_TRY_CATCH (str_val, ecma_op_to_string (value), ret_value); item = ecma_copy_value (str_val, true); ECMA_FINALIZE (str_val); } /* 4.b.ii.4 */ else if (ecma_is_value_object (value)) { ecma_object_t *obj_val_p = ecma_get_object_from_value (value); lit_magic_string_id_t class_name = ecma_object_get_class_name (obj_val_p); /* 4.b.ii.4.a */ if (class_name == LIT_MAGIC_STRING_NUMBER_UL || class_name == LIT_MAGIC_STRING_STRING_UL) { ECMA_TRY_CATCH (val, ecma_op_to_string (value), ret_value); item = ecma_copy_value (val, true); ECMA_FINALIZE (val); } } /* 4.b.ii.5 */ if (!ecma_is_value_undefined (item)) { if (!ecma_has_string_value_in_collection (context.property_list_p, item)) { ecma_append_to_values_collection (context.property_list_p, item, true); ecma_deref_ecma_string (ecma_get_string_from_value (item)); } else { ecma_free_value (item); } } ECMA_FINALIZE (value); ecma_deref_ecma_string (index_str_p); index++; } ECMA_OP_TO_NUMBER_FINALIZE (array_length_num); ECMA_FINALIZE (array_length); ecma_deref_ecma_string (length_str_p); } } if (ecma_is_value_empty (ret_value)) { ecma_value_t space = ecma_copy_value (arg3, true); /* 5. */ if (ecma_is_value_object (arg3)) { ecma_object_t *obj_p = ecma_get_object_from_value (arg3); lit_magic_string_id_t class_name = ecma_object_get_class_name (obj_p); /* 5.a */ if (class_name == LIT_MAGIC_STRING_NUMBER_UL) { ECMA_TRY_CATCH (val, ecma_op_to_number (arg3), ret_value); ecma_free_value (space); space = ecma_copy_value (val, true); ECMA_FINALIZE (val); } /* 5.b */ else if (class_name == LIT_MAGIC_STRING_STRING_UL) { ECMA_TRY_CATCH (val, ecma_op_to_string (arg3), ret_value); ecma_free_value (space); space = ecma_copy_value (val, true); ECMA_FINALIZE (val); } } if (ecma_is_value_empty (ret_value)) { /* 6. */ if (ecma_is_value_number (space)) { ECMA_OP_TO_NUMBER_TRY_CATCH (array_length_num, arg3, ret_value); /* 6.a */ int32_t num_of_spaces = ecma_number_to_int32 (array_length_num); int32_t space = (num_of_spaces > 10) ? 10 : num_of_spaces; /* 6.b */ if (space < 1) { context.gap_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); } else { MEM_DEFINE_LOCAL_ARRAY (space_buff, space, char); for (int32_t i = 0; i < space; i++) { space_buff[i] = LIT_CHAR_SP; } context.gap_str_p = ecma_new_ecma_string_from_utf8 ((lit_utf8_byte_t *) space_buff, (lit_utf8_size_t) space); MEM_FINALIZE_LOCAL_ARRAY (space_buff); } ECMA_OP_TO_NUMBER_FINALIZE (array_length_num); } /* 7. */ else if (ecma_is_value_string (space)) { ecma_string_t *space_str_p = ecma_get_string_from_value (space); ecma_length_t num_of_chars = ecma_string_get_length (space_str_p); if (num_of_chars < 10) { context.gap_str_p = ecma_copy_or_ref_ecma_string (space_str_p); } else { context.gap_str_p = ecma_string_substr (space_str_p, 0, 10); } } /* 8. */ else { context.gap_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); } } ecma_free_value (space); if (ecma_is_value_empty (ret_value)) { /* 9. */ ecma_object_t *obj_wrapper_p = ecma_op_create_object_object_noarg (); ecma_string_t *empty_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); /* 10. */ ecma_value_t put_comp_val = ecma_op_object_put (obj_wrapper_p, empty_str_p, arg1, false); JERRY_ASSERT (ecma_is_value_true (put_comp_val)); ecma_free_value (put_comp_val); /* 11. */ ECMA_TRY_CATCH (str_val, ecma_builtin_json_str (empty_str_p, obj_wrapper_p, &context), ret_value); ret_value = ecma_copy_value (str_val, true); ECMA_FINALIZE (str_val); ecma_deref_object (obj_wrapper_p); ecma_deref_ecma_string (empty_str_p); } ecma_deref_ecma_string (context.gap_str_p); } ecma_deref_ecma_string (context.indent_str_p); ecma_free_values_collection (context.property_list_p, true); ecma_free_values_collection (context.occurence_stack_p, true); return ret_value; } /* ecma_builtin_json_stringify */
/** * [[GetOwnProperty]] ecma String object's operation * * See also: * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 * ECMA-262 v5, 15.5.5.2 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_property_t * ecma_op_string_object_get_own_property (ecma_object_t *obj_p, /**< a String object */ ecma_string_t *property_name_p) /**< property name */ { JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_STRING); // 1. ecma_property_t *prop_p = ecma_op_general_object_get_own_property (obj_p, property_name_p); // 2. if (prop_p != NULL) { return prop_p; } // 3., 5. uint32_t uint32_index; ecma_string_t *new_prop_name_p; if (ECMA_STRING_GET_CONTAINER (property_name_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC) { uint32_index = property_name_p->u.uint32_number; new_prop_name_p = property_name_p; ecma_ref_ecma_string (new_prop_name_p); } else { ecma_number_t index = ecma_string_to_number (property_name_p); uint32_index = ecma_number_to_uint32 (index); ecma_string_t *to_str_p = ecma_new_ecma_string_from_uint32 (uint32_index); bool are_equal = ecma_compare_ecma_strings (to_str_p, property_name_p); if (!are_equal) { ecma_deref_ecma_string (to_str_p); return NULL; } else { new_prop_name_p = to_str_p; } } // 4. ecma_property_t *prim_value_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_ECMA_VALUE); ecma_string_t *prim_value_str_p; prim_value_str_p = ecma_get_string_from_value (ecma_get_internal_property_value (prim_value_prop_p)); // 6. ecma_length_t length = ecma_string_get_length (prim_value_str_p); ecma_property_t *new_prop_p; if (uint32_index >= (uint32_t) length) { // 7. new_prop_p = NULL; } else { // 8. ecma_char_t c = ecma_string_get_char_at_pos (prim_value_str_p, uint32_index); // 9. ecma_string_t *new_prop_str_value_p = ecma_new_ecma_string_from_code_unit (c); new_prop_p = ecma_create_named_data_property (obj_p, new_prop_name_p, ECMA_PROPERTY_FLAG_ENUMERABLE); ecma_set_named_data_property_value (new_prop_p, ecma_make_string_value (new_prop_str_value_p)); } ecma_deref_ecma_string (new_prop_name_p); return new_prop_p; } /* ecma_op_string_object_get_own_property */
/** * The Function.prototype object's 'apply' routine * * See also: * ECMA-262 v5, 15.3.4.3 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_function_prototype_object_apply (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg1, /**< first argument */ ecma_value_t arg2) /**< second argument */ { ecma_value_t ret_value = ECMA_VALUE_EMPTY; /* 1. */ if (!ecma_op_is_callable (this_arg)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not a function.")); } else { ecma_object_t *func_obj_p = ecma_get_object_from_value (this_arg); /* 2. */ if (ecma_is_value_null (arg2) || ecma_is_value_undefined (arg2)) { ret_value = ecma_op_function_call (func_obj_p, arg1, NULL, 0); } else { /* 3. */ if (!ecma_is_value_object (arg2)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an object.")); } else { ecma_object_t *obj_p = ecma_get_object_from_value (arg2); /* 4. */ ecma_value_t length_value = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH); if (ECMA_IS_VALUE_ERROR (length_value)) { return length_value; } ecma_number_t length_number; ecma_value_t get_result = ecma_get_number (length_value, &length_number); ecma_free_value (length_value); if (ECMA_IS_VALUE_ERROR (get_result)) { return get_result; } JERRY_ASSERT (ecma_is_value_empty (get_result)); /* 5. */ const uint32_t length = ecma_number_to_uint32 (length_number); if (length >= ECMA_FUNCTION_APPLY_ARGUMENT_COUNT_LIMIT) { ret_value = ecma_raise_range_error (ECMA_ERR_MSG ("Too many arguments declared for Function.apply().")); } else { /* 6. */ JMEM_DEFINE_LOCAL_ARRAY (arguments_list_p, length, ecma_value_t); uint32_t index = 0; /* 7. */ for (index = 0; index < length; index++) { ecma_string_t *curr_idx_str_p = ecma_new_ecma_string_from_uint32 (index); ecma_value_t get_value = ecma_op_object_get (obj_p, curr_idx_str_p); ecma_deref_ecma_string (curr_idx_str_p); if (ECMA_IS_VALUE_ERROR (get_value)) { ret_value = get_value; break; } arguments_list_p[index] = get_value; } if (ecma_is_value_empty (ret_value)) { JERRY_ASSERT (index == length); ret_value = ecma_op_function_call (func_obj_p, arg1, arguments_list_p, length); } for (uint32_t remove_index = 0; remove_index < index; remove_index++) { ecma_free_value (arguments_list_p[remove_index]); } JMEM_FINALIZE_LOCAL_ARRAY (arguments_list_p); } } } } return ret_value; } /* ecma_builtin_function_prototype_object_apply */
/** * Arguments object creation operation. * * See also: ECMA-262 v5, 10.6 */ void ecma_op_create_arguments_object (ecma_object_t *func_obj_p, /**< callee function */ ecma_object_t *lex_env_p, /**< lexical environment the Arguments object is created for */ const ecma_value_t *arguments_list_p, /**< arguments list */ ecma_length_t arguments_number, /**< length of arguments list */ const ecma_compiled_code_t *bytecode_data_p) /**< byte code */ { // 2., 3., 6. ecma_object_t *prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); ecma_object_t *obj_p = ecma_create_object (prototype_p, false, true, ECMA_OBJECT_TYPE_GENERAL); ecma_deref_object (prototype_p); // 11.a, 11.b for (ecma_length_t indx = 0; indx < arguments_number; indx++) { ecma_value_t completion; ecma_string_t *indx_string_p = ecma_new_ecma_string_from_uint32 (indx); completion = ecma_builtin_helper_def_prop (obj_p, indx_string_p, arguments_list_p[indx], true, /* Writable */ true, /* Enumerable */ true, /* Configurable */ false); /* Failure handling */ JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (indx_string_p); } bool is_strict = (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0; // 1. // 4. ecma_property_t *class_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_CLASS); ECMA_PROPERTY_VALUE_PTR (class_prop_p)->value = LIT_MAGIC_STRING_ARGUMENTS_UL; // 7. ecma_string_t *length_magic_string_p = ecma_new_ecma_length_string (); ecma_value_t completion = ecma_builtin_helper_def_prop (obj_p, length_magic_string_p, ecma_make_uint32_value (arguments_number), true, /* Writable */ false, /* Enumerable */ true, /* Configurable */ false); /* Failure handling */ JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (length_magic_string_p); ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); if (bytecode_data_p != NULL) { ecma_length_t formal_params_number; jmem_cpointer_t *literal_p; if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) { cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p; uint8_t *byte_p = (uint8_t *) bytecode_data_p; formal_params_number = args_p->argument_end; literal_p = (jmem_cpointer_t *) (byte_p + sizeof (cbc_uint16_arguments_t)); } else { cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p; uint8_t *byte_p = (uint8_t *) bytecode_data_p; formal_params_number = args_p->argument_end; literal_p = (jmem_cpointer_t *) (byte_p + sizeof (cbc_uint8_arguments_t)); } if (!is_strict && arguments_number > 0 && formal_params_number > 0) { // 8. ecma_object_t *map_p = ecma_op_create_object_object_noarg (); // 11.c for (uint32_t indx = 0; indx < formal_params_number; indx++) { // i. if (literal_p[indx] == JMEM_CP_NULL) { continue; } ecma_string_t *name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, literal_p[indx]); ecma_string_t *indx_string_p = ecma_new_ecma_string_from_uint32 ((uint32_t) indx); prop_desc.is_value_defined = true; prop_desc.value = ecma_make_string_value (name_p); prop_desc.is_configurable_defined = true; prop_desc.is_configurable = true; completion = ecma_op_object_define_own_property (map_p, indx_string_p, &prop_desc, false); JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (indx_string_p); } // 12. ecma_set_object_type (obj_p, ECMA_OBJECT_TYPE_ARGUMENTS); /* * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_ARGUMENTS type. * * See also: ecma_object_get_class_name */ ecma_delete_property (obj_p, class_prop_p); ecma_property_t *parameters_map_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP); ECMA_SET_INTERNAL_VALUE_POINTER (ECMA_PROPERTY_VALUE_PTR (parameters_map_prop_p)->value, map_p); ecma_property_t *scope_prop_p = ecma_create_internal_property (map_p, ECMA_INTERNAL_PROPERTY_SCOPE); ECMA_SET_INTERNAL_VALUE_POINTER (ECMA_PROPERTY_VALUE_PTR (scope_prop_p)->value, lex_env_p); ecma_deref_object (map_p); } } // 13. if (!is_strict) { ecma_string_t *callee_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_CALLEE); completion = ecma_builtin_helper_def_prop (obj_p, callee_magic_string_p, ecma_make_object_value (func_obj_p), true, /* Writable */ false, /* Enumerable */ true, /* Configurable */ false); /* Failure handling */ JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (callee_magic_string_p); } else { ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER); // 14. prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_get_defined = true; prop_desc.get_p = thrower_p; prop_desc.is_set_defined = true; prop_desc.set_p = thrower_p; prop_desc.is_enumerable_defined = true; prop_desc.is_enumerable = false; prop_desc.is_configurable_defined = true; prop_desc.is_configurable = false; } ecma_string_t *callee_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_CALLEE); completion = ecma_op_object_define_own_property (obj_p, callee_magic_string_p, &prop_desc, false); JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (callee_magic_string_p); ecma_string_t *caller_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_CALLER); completion = ecma_op_object_define_own_property (obj_p, caller_magic_string_p, &prop_desc, false); JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (caller_magic_string_p); ecma_deref_object (thrower_p); } ecma_string_t *arguments_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_ARGUMENTS); if (is_strict) { ecma_op_create_immutable_binding (lex_env_p, arguments_string_p); ecma_op_initialize_immutable_binding (lex_env_p, arguments_string_p, ecma_make_object_value (obj_p)); } else { ecma_value_t completion = ecma_op_create_mutable_binding (lex_env_p, arguments_string_p, false); JERRY_ASSERT (ecma_is_value_empty (completion)); completion = ecma_op_set_mutable_binding (lex_env_p, arguments_string_p, ecma_make_object_value (obj_p), false); JERRY_ASSERT (ecma_is_value_empty (completion)); } ecma_deref_ecma_string (arguments_string_p); ecma_deref_object (obj_p); } /* ecma_op_create_arguments_object */
/** * The Function.prototype object's 'apply' routine * * See also: * ECMA-262 v5, 15.3.4.3 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_function_prototype_object_apply (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg1, /**< first argument */ ecma_value_t arg2) /**< second argument */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 1. */ if (!ecma_op_is_callable (this_arg)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("")); } else { ecma_object_t *func_obj_p = ecma_get_object_from_value (this_arg); /* 2. */ if (ecma_is_value_null (arg2) || ecma_is_value_undefined (arg2)) { ret_value = ecma_op_function_call (func_obj_p, arg1, NULL, 0); } else { /* 3. */ if (!ecma_is_value_object (arg2)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("")); } else { ecma_object_t *obj_p = ecma_get_object_from_value (arg2); ecma_string_t *length_magic_string_p = ecma_new_ecma_length_string (); /* 4. */ ECMA_TRY_CATCH (length_value, ecma_op_object_get (obj_p, length_magic_string_p), ret_value); ECMA_OP_TO_NUMBER_TRY_CATCH (length_number, length_value, ret_value); /* 5. */ const uint32_t length = ecma_number_to_uint32 (length_number); /* 6. */ JMEM_DEFINE_LOCAL_ARRAY (arguments_list_p, length, ecma_value_t); uint32_t last_index = 0; /* 7. */ for (uint32_t index = 0; index < length && ecma_is_value_empty (ret_value); index++) { ecma_string_t *curr_idx_str_p = ecma_new_ecma_string_from_uint32 (index); ECMA_TRY_CATCH (get_value, ecma_op_object_get (obj_p, curr_idx_str_p), ret_value); arguments_list_p[index] = ecma_copy_value (get_value); last_index = index + 1; ECMA_FINALIZE (get_value); ecma_deref_ecma_string (curr_idx_str_p); } if (ecma_is_value_empty (ret_value)) { JERRY_ASSERT (last_index == length); ret_value = ecma_op_function_call (func_obj_p, arg1, arguments_list_p, length); } for (uint32_t index = 0; index < last_index; index++) { ecma_free_value (arguments_list_p[index]); } JMEM_FINALIZE_LOCAL_ARRAY (arguments_list_p); ECMA_OP_TO_NUMBER_FINALIZE (length_number); ECMA_FINALIZE (length_value); ecma_deref_ecma_string (length_magic_string_p); } } } return ret_value; } /* ecma_builtin_function_prototype_object_apply */
/** * Abstract operation 'JA' defined in 15.12.3 * * See also: * ECMA-262 v5, 15.12.3 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_json_array (ecma_object_t *obj_p, /**< the array object*/ ecma_json_stringify_context_t *context_p) /**< context*/ { ecma_value_t obj_value = ecma_make_object_value (obj_p); /* 1. */ if (ecma_has_object_value_in_collection (context_p->occurence_stack_p, obj_value)) { return ecma_raise_type_error (""); } ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 2. */ ecma_append_to_values_collection (context_p->occurence_stack_p, obj_value, true); /* 3. */ ecma_string_t *stepback_p = context_p->indent_str_p; /* 4. */ context_p->indent_str_p = ecma_concat_ecma_strings (context_p->indent_str_p, context_p->gap_str_p); /* 5. */ ecma_collection_header_t *partial_p = ecma_new_values_collection (NULL, 0, true); ecma_string_t *length_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); /* 6. */ ECMA_TRY_CATCH (array_length, ecma_op_object_get (obj_p, length_str_p), ret_value); ECMA_OP_TO_NUMBER_TRY_CATCH (array_length_num, array_length, ret_value); uint32_t array_length = ecma_number_to_uint32 (array_length_num); /* 7. - 8. */ for (uint32_t index = 0; index < array_length && ecma_is_value_empty (ret_value); index++) { /* 8.a */ ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index); ECMA_TRY_CATCH (str_val, ecma_builtin_json_str (index_str_p, obj_p, context_p), ret_value); /* 8.b */ if (ecma_is_value_undefined (str_val)) { ecma_string_t *null_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_NULL); ecma_append_to_values_collection (partial_p, ecma_make_string_value (null_str_p), true); ecma_deref_ecma_string (null_str_p); } /* 8.c */ else { ecma_append_to_values_collection (partial_p, str_val, true); } ECMA_FINALIZE (str_val); ecma_deref_ecma_string (index_str_p); } if (ecma_is_value_empty (ret_value)) { /* 9. */ if (partial_p->unit_number == 0) { ecma_string_t *left_square_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LEFT_SQUARE_CHAR); ecma_string_t *right_square_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_RIGHT_SQUARE_CHAR); ecma_string_t *final_str_p = ecma_concat_ecma_strings (left_square_str_p, right_square_str_p); ret_value = ecma_make_string_value (final_str_p); ecma_deref_ecma_string (left_square_str_p); ecma_deref_ecma_string (right_square_str_p); } /* 10. */ else { bool is_gap_empty = (ecma_string_get_length (context_p->gap_str_p) == 0); /* 10.a */ if (is_gap_empty) { ecma_string_t *left_square_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LEFT_SQUARE_CHAR); ecma_string_t *right_square_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_RIGHT_SQUARE_CHAR); ret_value = ecma_builtin_helper_json_create_non_formatted_json (left_square_str_p, right_square_str_p, partial_p); ecma_deref_ecma_string (left_square_str_p); ecma_deref_ecma_string (right_square_str_p); } /* 10.b */ else { ecma_string_t *left_square_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LEFT_SQUARE_CHAR); ecma_string_t *right_square_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_RIGHT_SQUARE_CHAR); ret_value = ecma_builtin_helper_json_create_formatted_json (left_square_str_p, right_square_str_p, stepback_p, partial_p, context_p); ecma_deref_ecma_string (left_square_str_p); ecma_deref_ecma_string (right_square_str_p); } } } ECMA_OP_TO_NUMBER_FINALIZE (array_length_num); ECMA_FINALIZE (array_length); ecma_deref_ecma_string (length_str_p); ecma_free_values_collection (partial_p, true); /* 11. */ ecma_remove_last_value_from_values_collection (context_p->occurence_stack_p); /* 12. */ ecma_deref_ecma_string (context_p->indent_str_p); context_p->indent_str_p = stepback_p; /* 13. */ return ret_value; } /* ecma_builtin_json_array */
/** * Helper function for concatenating an ecma_value_t to an Array. * * See also: * ECMA-262 v5, 15.4.4.4 steps 5.b - 5.c * * Used by: * - The Array.prototype.concat routine. * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ ecma_completion_value_t ecma_builtin_helper_array_concat_value (ecma_object_t *obj_p, /**< array */ uint32_t *length_p, /**< in-out: array's length */ ecma_value_t value) /**< value to concat */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); /* 5.b */ if (ecma_is_value_object (value) && (ecma_object_get_class_name (ecma_get_object_from_value (value)) == LIT_MAGIC_STRING_ARRAY_UL)) { ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); /* 5.b.ii */ ECMA_TRY_CATCH (arg_len_value, ecma_op_object_get (ecma_get_object_from_value (value), magic_string_length_p), ret_value); ECMA_OP_TO_NUMBER_TRY_CATCH (arg_len_number, arg_len_value, ret_value); uint32_t arg_len = ecma_number_to_uint32 (arg_len_number); /* 5.b.iii */ for (uint32_t array_index = 0; array_index < arg_len && ecma_is_completion_value_empty (ret_value); array_index++) { ecma_string_t *array_index_string_p = ecma_new_ecma_string_from_uint32 (array_index); /* 5.b.iii.2 */ if (ecma_op_object_get_property (ecma_get_object_from_value (value), array_index_string_p) != NULL) { ecma_string_t *new_array_index_string_p = ecma_new_ecma_string_from_uint32 (*length_p + array_index); /* 5.b.iii.3.a */ ECMA_TRY_CATCH (get_value, ecma_op_object_get (ecma_get_object_from_value (value), array_index_string_p), ret_value); ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_value_defined = true; prop_desc.value = get_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; } /* 5.b.iii.3.b */ /* This will always be a simple value since 'is_throw' is false, so no need to free. */ ecma_completion_value_t put_comp = ecma_op_object_define_own_property (obj_p, new_array_index_string_p, &prop_desc, false); JERRY_ASSERT (ecma_is_completion_value_normal_true (put_comp)); ECMA_FINALIZE (get_value); ecma_deref_ecma_string (new_array_index_string_p); } ecma_deref_ecma_string (array_index_string_p); } *length_p += arg_len; ECMA_OP_TO_NUMBER_FINALIZE (arg_len_number); ECMA_FINALIZE (arg_len_value); ecma_deref_ecma_string (magic_string_length_p); } else { ecma_string_t *new_array_index_string_p = ecma_new_ecma_string_from_uint32 ((*length_p)++); ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_value_defined = true; prop_desc.value = 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; } /* 5.c.i */ /* This will always be a simple value since 'is_throw' is false, so no need to free. */ ecma_completion_value_t put_comp = ecma_op_object_define_own_property (obj_p, new_array_index_string_p, &prop_desc, false); JERRY_ASSERT (ecma_is_completion_value_normal_true (put_comp)); ecma_deref_ecma_string (new_array_index_string_p); } if (ecma_is_completion_value_empty (ret_value)) { ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE); } return ret_value; } /* ecma_builtin_helper_array_concat_value */
/** * Helper function for concatenating an ecma_value_t to an Array. * * See also: * ECMA-262 v5, 15.4.4.4 steps 5.b - 5.c * * Used by: * - The Array.prototype.concat routine. * * @return ecma value * Returned value must be freed with ecma_free_value. */ ecma_value_t ecma_builtin_helper_array_concat_value (ecma_object_t *obj_p, /**< array */ uint32_t *length_p, /**< [in,out] array's length */ ecma_value_t value) /**< value to concat */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 5.b */ if (ecma_is_value_object (value) && (ecma_object_get_class_name (ecma_get_object_from_value (value)) == LIT_MAGIC_STRING_ARRAY_UL)) { ecma_string_t *magic_string_length_p = ecma_new_ecma_length_string (); /* 5.b.ii */ ECMA_TRY_CATCH (arg_len_value, ecma_op_object_get (ecma_get_object_from_value (value), magic_string_length_p), ret_value); ECMA_OP_TO_NUMBER_TRY_CATCH (arg_len_number, arg_len_value, ret_value); uint32_t arg_len = ecma_number_to_uint32 (arg_len_number); /* 5.b.iii */ for (uint32_t array_index = 0; array_index < arg_len && ecma_is_value_empty (ret_value); array_index++) { ecma_string_t *array_index_string_p = ecma_new_ecma_string_from_uint32 (array_index); /* 5.b.iii.2 */ if (ecma_op_object_get_property (ecma_get_object_from_value (value), array_index_string_p) != NULL) { ecma_string_t *new_array_index_string_p = ecma_new_ecma_string_from_uint32 (*length_p + array_index); /* 5.b.iii.3.a */ ECMA_TRY_CATCH (get_value, ecma_op_object_get (ecma_get_object_from_value (value), array_index_string_p), ret_value); /* 5.b.iii.3.b */ /* This will always be a simple value since 'is_throw' is false, so no need to free. */ ecma_value_t put_comp = ecma_builtin_helper_def_prop (obj_p, new_array_index_string_p, get_value, true, /* Writable */ true, /* Enumerable */ true, /* Configurable */ false); /* Failure handling */ JERRY_ASSERT (ecma_is_value_true (put_comp)); ECMA_FINALIZE (get_value); ecma_deref_ecma_string (new_array_index_string_p); } ecma_deref_ecma_string (array_index_string_p); } *length_p += arg_len; ECMA_OP_TO_NUMBER_FINALIZE (arg_len_number); ECMA_FINALIZE (arg_len_value); ecma_deref_ecma_string (magic_string_length_p); } else { ecma_string_t *new_array_index_string_p = ecma_new_ecma_string_from_uint32 ((*length_p)++); /* 5.c.i */ /* This will always be a simple value since 'is_throw' is false, so no need to free. */ ecma_value_t put_comp = ecma_builtin_helper_def_prop (obj_p, new_array_index_string_p, value, true, /* Writable */ true, /* Enumerable */ true, /* Configurable */ false); /* Failure handling */ JERRY_ASSERT (ecma_is_value_true (put_comp)); ecma_deref_ecma_string (new_array_index_string_p); } if (ecma_is_value_empty (ret_value)) { ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } return ret_value; } /* ecma_builtin_helper_array_concat_value */
/** * Array object creation operation. * * See also: ECMA-262 v5, 15.4.2.1 * ECMA-262 v5, 15.4.2.2 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_create_array_object (const ecma_value_t *arguments_list_p, /**< list of arguments that are passed to Array constructor */ ecma_length_t arguments_list_len, /**< length of the arguments' list */ bool is_treat_single_arg_as_length) /**< if the value is true, arguments_list_len is 1 and single argument is Number, then treat the single argument as new Array's length rather than as single item of the Array */ { JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); uint32_t length; const ecma_value_t *array_items_p; ecma_length_t array_items_count; if (is_treat_single_arg_as_length && arguments_list_len == 1 && ecma_is_value_number (arguments_list_p[0])) { ecma_number_t *num_p = ecma_get_number_from_value (arguments_list_p[0]); uint32_t num_uint32 = ecma_number_to_uint32 (*num_p); if (*num_p != ecma_uint32_to_number (num_uint32)) { return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_RANGE)); } else { length = num_uint32; array_items_p = NULL; array_items_count = 0; } } else { length = arguments_list_len; array_items_p = arguments_list_p; array_items_count = arguments_list_len; } #ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_ARRAY_BUILTIN ecma_object_t *array_prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_ARRAY_PROTOTYPE); #else /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_ARRAY_BUILTIN */ ecma_object_t *array_prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); #endif /* CONFIG_ECMA_COMPACT_PROFILE_DISABLE_ARRAY_BUILTIN */ ecma_object_t *obj_p = ecma_create_object (array_prototype_obj_p, true, ECMA_OBJECT_TYPE_ARRAY); ecma_deref_object (array_prototype_obj_p); /* * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_ARRAY type. * * See also: ecma_object_get_class_name */ ecma_string_t *length_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_number_t *length_num_p = ecma_alloc_number (); *length_num_p = ecma_uint32_to_number (length); ecma_property_t *length_prop_p = ecma_create_named_data_property (obj_p, length_magic_string_p, true, false, false); ecma_set_named_data_property_value (length_prop_p, ecma_make_number_value (length_num_p)); ecma_deref_ecma_string (length_magic_string_p); for (uint32_t index = 0; index < array_items_count; index++) { if (ecma_is_value_array_hole (array_items_p[index])) { continue; } ecma_string_t *item_name_string_p = ecma_new_ecma_string_from_uint32 (index); ecma_builtin_helper_def_prop (obj_p, item_name_string_p, array_items_p[index], true, /* Writable */ true, /* Enumerable */ true, /* Configurable */ false); /* Failure handling */ ecma_deref_ecma_string (item_name_string_p); } return ecma_make_normal_completion_value (ecma_make_object_value (obj_p)); } /* ecma_op_create_array_object */
/** * ToString operation. * * See also: * ECMA-262 v5, 9.8 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_to_string (ecma_value_t value) /**< ecma value */ { ecma_check_value_type_is_spec_defined (value); if (unlikely (ecma_is_value_object (value))) { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ECMA_TRY_CATCH (prim_value, ecma_op_to_primitive (value, ECMA_PREFERRED_TYPE_STRING), ret_value); ret_value = ecma_op_to_string (prim_value); ECMA_FINALIZE (prim_value); return ret_value; } else { ecma_string_t *res_p = NULL; if (ecma_is_value_string (value)) { res_p = ecma_get_string_from_value (value); res_p = ecma_copy_or_ref_ecma_string (res_p); } else if (ecma_is_value_integer_number (value)) { ecma_integer_value_t num = ecma_get_integer_from_value (value); if (num < 0) { res_p = ecma_new_ecma_string_from_number ((ecma_number_t) num); } else { res_p = ecma_new_ecma_string_from_uint32 ((uint32_t) num); } } else if (ecma_is_value_float_number (value)) { ecma_number_t num = ecma_get_float_from_value (value); res_p = ecma_new_ecma_string_from_number (num); } else if (ecma_is_value_undefined (value)) { res_p = ecma_get_magic_string (LIT_MAGIC_STRING_UNDEFINED); } else if (ecma_is_value_null (value)) { res_p = ecma_get_magic_string (LIT_MAGIC_STRING_NULL); } else { JERRY_ASSERT (ecma_is_value_boolean (value)); if (ecma_is_value_true (value)) { res_p = ecma_get_magic_string (LIT_MAGIC_STRING_TRUE); } else { res_p = ecma_get_magic_string (LIT_MAGIC_STRING_FALSE); } } return ecma_make_string_value (res_p); } } /* ecma_op_to_string */