/** * Handle calling [[Construct]] of built-in Object object * * @return completion-value */ ecma_completion_value_t ecma_builtin_object_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); if (arguments_list_len == 0) { ecma_object_t *obj_p = ecma_op_create_object_object_noarg (); return ecma_make_normal_completion_value (ecma_make_object_value (obj_p)); } else { ecma_completion_value_t new_obj_value = ecma_op_create_object_object_arg (arguments_list_p[0]); if (!ecma_is_completion_value_normal (new_obj_value)) { return new_obj_value; } else { return ecma_make_normal_completion_value (ecma_get_completion_value_value (new_obj_value)); } } } /* ecma_builtin_object_dispatch_construct */
/** * 'Object' object creation operation with one argument. * * See also: ECMA-262 v5, 15.2.2.1 * * @return pointer to newly created 'Object' object */ ecma_completion_value_t ecma_op_create_object_object_arg (ecma_value_t value) /**< argument of constructor */ { ecma_check_value_type_is_spec_defined (value); if (ecma_is_value_object (value) || ecma_is_value_number (value) || ecma_is_value_string (value) || ecma_is_value_boolean (value)) { // 1.b, 1.c, 1.d return ecma_op_to_object (value); } else { // 2. JERRY_ASSERT (ecma_is_value_undefined (value) || ecma_is_value_null (value)); ecma_object_t *obj_p = ecma_op_create_object_object_noarg (); return ecma_make_normal_completion_value (ecma_make_object_value (obj_p)); } } /* ecma_op_create_object_object_arg */
/** * Lazy instantation of non-builtin ecma function object's properties * * Warning: * Only non-configurable properties could be instantiated lazily in this function, * as configurable properties could be deleted and it would be incorrect * to reinstantiate them in the function in second time. * * @return pointer to newly instantiated property, if a property was instantiated, * NULL - otherwise */ ecma_property_t * ecma_op_function_try_lazy_instantiate_property (ecma_object_t *object_p, /**< the function object */ ecma_string_t *property_name_p) /**< property name */ { static const char prototype_str_p[] = "prototype"; JERRY_ASSERT (!ecma_get_object_is_builtin (object_p)); ecma_string_container_t container = ECMA_STRING_GET_CONTAINER (property_name_p); /* Check whether the property_name_p is prototype */ if (container == ECMA_STRING_CONTAINER_MAGIC_STRING) { if (property_name_p->u.magic_string_id != LIT_MAGIC_STRING_PROTOTYPE) { return NULL; } } else if (container != ECMA_STRING_CONTAINER_HEAP_UTF8_STRING || property_name_p->u.utf8_string.size != (sizeof (prototype_str_p) - 1)) { return NULL; } else { if (strncmp ((char *) (property_name_p + 1), prototype_str_p, (sizeof (prototype_str_p) - 1)) != 0) { return NULL; } } /* ECMA-262 v5, 13.2, 16-18 */ /* 16. */ ecma_object_t *proto_object_p = ecma_op_create_object_object_noarg (); /* 17. */ ecma_string_t *magic_string_constructor_p = ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR); ecma_property_value_t *constructor_prop_value_p; constructor_prop_value_p = ecma_create_named_data_property (proto_object_p, magic_string_constructor_p, ECMA_PROPERTY_CONFIGURABLE_WRITABLE, NULL); constructor_prop_value_p->value = ecma_make_object_value (object_p); ecma_deref_ecma_string (magic_string_constructor_p); /* 18. */ ecma_property_t *prototype_prop_p; ecma_property_value_t *prototype_prop_value_p; prototype_prop_value_p = ecma_create_named_data_property (object_p, property_name_p, ECMA_PROPERTY_FLAG_WRITABLE, &prototype_prop_p); prototype_prop_value_p->value = ecma_make_object_value (proto_object_p); ecma_deref_object (proto_object_p); return prototype_prop_p; } /* ecma_op_function_try_lazy_instantiate_property */
/** * 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 */
/** * FromPropertyDescriptor operation. * * See also: * ECMA-262 v5, 8.10.4 * * @return constructed object */ ecma_object_t * ecma_op_from_property_descriptor (const ecma_property_descriptor_t *src_prop_desc_p) /**< property descriptor */ { // 2. ecma_object_t *obj_p = ecma_op_create_object_object_noarg (); ecma_value_t completion; ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_value_defined = true; 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; } // 3. if (src_prop_desc_p->is_value_defined || src_prop_desc_p->is_writable_defined) { JERRY_ASSERT (prop_desc.is_value_defined && prop_desc.is_writable_defined); // a. prop_desc.value = src_prop_desc_p->value; ecma_string_t *value_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_VALUE); completion = ecma_op_object_define_own_property (obj_p, value_magic_string_p, &prop_desc, false); ecma_deref_ecma_string (value_magic_string_p); JERRY_ASSERT (ecma_is_value_true (completion)); // b. const bool is_writable = (src_prop_desc_p->is_writable); prop_desc.value = ecma_make_simple_value (is_writable ? ECMA_SIMPLE_VALUE_TRUE : ECMA_SIMPLE_VALUE_FALSE); ecma_string_t *writable_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_WRITABLE); completion = ecma_op_object_define_own_property (obj_p, writable_magic_string_p, &prop_desc, false); ecma_deref_ecma_string (writable_magic_string_p); JERRY_ASSERT (ecma_is_value_true (completion)); } else { // 4. JERRY_ASSERT (src_prop_desc_p->is_get_defined || src_prop_desc_p->is_set_defined); // a. if (src_prop_desc_p->get_p == NULL) { prop_desc.value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } else { prop_desc.value = ecma_make_object_value (src_prop_desc_p->get_p); } ecma_string_t *get_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_GET); completion = ecma_op_object_define_own_property (obj_p, get_magic_string_p, &prop_desc, false); ecma_deref_ecma_string (get_magic_string_p); JERRY_ASSERT (ecma_is_value_true (completion)); // b. if (src_prop_desc_p->set_p == NULL) { prop_desc.value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } else { prop_desc.value = ecma_make_object_value (src_prop_desc_p->set_p); } ecma_string_t *set_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_SET); completion = ecma_op_object_define_own_property (obj_p, set_magic_string_p, &prop_desc, false); ecma_deref_ecma_string (set_magic_string_p); JERRY_ASSERT (ecma_is_value_true (completion)); } const bool is_enumerable = src_prop_desc_p->is_enumerable; prop_desc.value = ecma_make_simple_value (is_enumerable ? ECMA_SIMPLE_VALUE_TRUE : ECMA_SIMPLE_VALUE_FALSE); ecma_string_t *enumerable_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_ENUMERABLE); completion = ecma_op_object_define_own_property (obj_p, enumerable_magic_string_p, &prop_desc, false); ecma_deref_ecma_string (enumerable_magic_string_p); JERRY_ASSERT (ecma_is_value_true (completion)); const bool is_configurable = src_prop_desc_p->is_configurable; prop_desc.value = ecma_make_simple_value (is_configurable ? ECMA_SIMPLE_VALUE_TRUE : ECMA_SIMPLE_VALUE_FALSE); ecma_string_t *configurable_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_CONFIGURABLE); completion = ecma_op_object_define_own_property (obj_p, configurable_magic_string_p, &prop_desc, false); ecma_deref_ecma_string (configurable_magic_string_p); JERRY_ASSERT (ecma_is_value_true (completion)); return obj_p; } /* ecma_op_from_property_descriptor */
/** * Function object creation operation. * * See also: ECMA-262 v5, 13.2 * * @return pointer to newly created Function object */ ecma_object_t* ecma_op_create_function_object (ecma_string_t* formal_parameter_list_p[], /**< formal parameters list */ ecma_length_t formal_parameters_number, /**< formal parameters list's length */ ecma_object_t *scope_p, /**< function's scope */ bool is_strict, /**< 'strict' flag */ bool do_instantiate_arguments_object, /**< should an Arguments object be instantiated * for the function object upon call */ const vm_instr_t *instrs_p, /**< byte-code array */ vm_instr_counter_t first_instr_pos) /**< position of first instruction * of function's body */ { // 1., 4., 13. ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); ecma_object_t *f = ecma_create_object (prototype_obj_p, true, ECMA_OBJECT_TYPE_FUNCTION); ecma_deref_object (prototype_obj_p); // 2., 6., 7., 8. /* * We don't setup [[Get]], [[Call]], [[Construct]], [[HasInstance]] for each function object. * Instead we set the object's type to ECMA_OBJECT_TYPE_FUNCTION * that defines which version of the routine should be used on demand. */ // 3. /* * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_FUNCTION type. * * See also: ecma_object_get_class_name */ // 9. ecma_property_t *scope_prop_p = ecma_create_internal_property (f, ECMA_INTERNAL_PROPERTY_SCOPE); ECMA_SET_POINTER (scope_prop_p->u.internal_property.value, scope_p); // 10., 11. ecma_property_t *formal_parameters_prop_p = ecma_create_internal_property (f, ECMA_INTERNAL_PROPERTY_FORMAL_PARAMETERS); if (formal_parameters_number != 0) { /* * Reverse formal parameter list */ for (ecma_length_t i = 0; i < formal_parameters_number / 2; i++) { ecma_string_t *tmp_p = formal_parameter_list_p[i]; formal_parameter_list_p[i] = formal_parameter_list_p[formal_parameters_number - 1u - i]; formal_parameter_list_p[formal_parameters_number - 1u - i] = tmp_p; } ecma_collection_header_t *formal_parameters_collection_p = ecma_new_strings_collection (formal_parameter_list_p, formal_parameters_number); ECMA_SET_POINTER (formal_parameters_prop_p->u.internal_property.value, formal_parameters_collection_p); } else { JERRY_ASSERT (formal_parameters_prop_p->u.internal_property.value == ECMA_NULL_POINTER); } // 12. ecma_property_t *bytecode_prop_p = ecma_create_internal_property (f, ECMA_INTERNAL_PROPERTY_CODE_BYTECODE); MEM_CP_SET_NON_NULL_POINTER (bytecode_prop_p->u.internal_property.value, instrs_p); ecma_property_t *code_prop_p = ecma_create_internal_property (f, ECMA_INTERNAL_PROPERTY_CODE_FLAGS_AND_OFFSET); code_prop_p->u.internal_property.value = ecma_pack_code_internal_property_value (is_strict, do_instantiate_arguments_object, first_instr_pos); // 14. ecma_number_t* len_p = ecma_alloc_number (); *len_p = ecma_uint32_to_number (formal_parameters_number); // 15. ecma_property_descriptor_t length_prop_desc = ecma_make_empty_property_descriptor (); length_prop_desc.is_value_defined = true; length_prop_desc.value = ecma_make_number_value (len_p); ecma_string_t* magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_completion_value_t completion = ecma_op_object_define_own_property (f, magic_string_length_p, &length_prop_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)); ecma_dealloc_number (len_p); len_p = NULL; // 16. ecma_object_t *proto_p = ecma_op_create_object_object_noarg (); // 17. ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_value_defined = true; prop_desc.value = ecma_make_object_value (f); prop_desc.is_writable_defined = true; prop_desc.is_writable = true; prop_desc.is_enumerable_defined = true; prop_desc.is_enumerable = false; prop_desc.is_configurable_defined = true; prop_desc.is_configurable = true; } ecma_string_t *magic_string_constructor_p = ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR); ecma_op_object_define_own_property (proto_p, magic_string_constructor_p, &prop_desc, false); ecma_deref_ecma_string (magic_string_constructor_p); // 18. prop_desc.value = ecma_make_object_value (proto_p); prop_desc.is_configurable = false; ecma_string_t *magic_string_prototype_p = ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE); ecma_op_object_define_own_property (f, magic_string_prototype_p, &prop_desc, false); ecma_deref_ecma_string (magic_string_prototype_p); ecma_deref_object (proto_p); // 19. if (is_strict) { ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER); prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_enumerable_defined = true; prop_desc.is_enumerable = false; prop_desc.is_configurable_defined = true; prop_desc.is_configurable = false; prop_desc.is_get_defined = true; prop_desc.get_p = thrower_p; prop_desc.is_set_defined = true; prop_desc.set_p = thrower_p; } ecma_string_t *magic_string_caller_p = ecma_get_magic_string (LIT_MAGIC_STRING_CALLER); ecma_op_object_define_own_property (f, magic_string_caller_p, &prop_desc, false); ecma_deref_ecma_string (magic_string_caller_p); ecma_string_t *magic_string_arguments_p = ecma_get_magic_string (LIT_MAGIC_STRING_ARGUMENTS); ecma_op_object_define_own_property (f, magic_string_arguments_p, &prop_desc, false); ecma_deref_ecma_string (magic_string_arguments_p); ecma_deref_object (thrower_p); } return f; } /* ecma_op_create_function_object */
/** * 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 */
/** * The JSON object's 'parse' routine * * See also: * ECMA-262 v5, 15.12.2 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_json_parse (ecma_value_t this_arg __attr_unused___, /**< 'this' argument */ ecma_value_t arg1, /**< string argument */ ecma_value_t arg2) /**< reviver argument */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ECMA_TRY_CATCH (string, ecma_op_to_string (arg1), ret_value); ecma_string_t *string_p = ecma_get_string_from_value (string); ecma_length_t string_size = (uint32_t) ecma_string_get_size (string_p); size_t buffer_size = sizeof (lit_utf8_byte_t) * (string_size + 1); MEM_DEFINE_LOCAL_ARRAY (str_start_p, buffer_size, lit_utf8_byte_t); ssize_t sz = ecma_string_to_utf8_string (string_p, str_start_p, (ssize_t) buffer_size); JERRY_ASSERT (sz == (ssize_t) string_size); str_start_p[string_size] = LIT_BYTE_NULL; ecma_json_token_t token; token.current_p = str_start_p; token.end_p = str_start_p + string_size; ecma_value_t final_result = ecma_builtin_json_parse_value (&token); if (!ecma_is_value_undefined (final_result)) { ecma_builtin_json_parse_next_token (&token); if (token.type != end_token) { ecma_free_value (final_result); final_result = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } } if (ecma_is_value_undefined (final_result)) { ret_value = ecma_raise_syntax_error (""); } else { if (ecma_op_is_callable (arg2)) { ecma_object_t *object_p = ecma_op_create_object_object_noarg (); ecma_string_t *name_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); ecma_property_t *property_p = ecma_create_named_data_property (object_p, name_p, true, true, true); ecma_named_data_property_assign_value (object_p, property_p, final_result); ecma_free_value (final_result); ret_value = ecma_builtin_json_walk (ecma_get_object_from_value (arg2), object_p, name_p); ecma_deref_object (object_p); ecma_deref_ecma_string (name_p); } else { ret_value = final_result; } } MEM_FINALIZE_LOCAL_ARRAY (str_start_p); ECMA_FINALIZE (string); return ret_value; } /* ecma_builtin_json_parse */
/** * 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 */