/** * Handle calling [[Construct]] of built-in object * * @return ecma value */ ecma_value_t ecma_builtin_dispatch_construct (ecma_object_t *obj_p, /**< built-in object */ const ecma_value_t *arguments_list_p, /**< arguments list */ ecma_length_t arguments_list_len) /**< arguments list length */ { JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION); JERRY_ASSERT (ecma_get_object_is_builtin (obj_p)); ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ecma_property_t *built_in_id_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_BUILT_IN_ID); ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_id_prop_p->u.internal_property.value; JERRY_ASSERT (ecma_builtin_is (obj_p, builtin_id)); JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION); switch (builtin_id) { #define BUILTIN(builtin_id, \ object_type, \ object_prototype_builtin_id, \ is_extensible, \ is_static, \ lowercase_name) \ case builtin_id: \ { \ if (object_type == ECMA_OBJECT_TYPE_FUNCTION) \ { \ ret_value = ecma_builtin_ ## lowercase_name ## _dispatch_construct (arguments_list_p, \ arguments_list_len); \ } \ break; \ } #include "ecma-builtins.inc.h" case ECMA_BUILTIN_ID__COUNT: { JERRY_UNREACHABLE (); } default: { #ifdef CONFIG_ECMA_COMPACT_PROFILE JERRY_UNREACHABLE (); #else /* CONFIG_ECMA_COMPACT_PROFILE */ JERRY_UNIMPLEMENTED ("The built-in is not implemented."); #endif /* !CONFIG_ECMA_COMPACT_PROFILE */ } } JERRY_ASSERT (!ecma_is_value_empty (ret_value)); return ret_value; } /* ecma_builtin_dispatch_construct */
/** * Instantiate specified ECMA built-in object */ static void ecma_instantiate_builtin (ecma_builtin_id_t id) /**< built-in id */ { switch (id) { #define BUILTIN(builtin_id, \ object_type, \ object_prototype_builtin_id, \ is_extensible, \ is_static, \ lowercase_name) \ case builtin_id: \ { \ JERRY_ASSERT (ecma_builtin_objects[builtin_id] == NULL); \ if (is_static) \ { \ ecma_builtin_ ## lowercase_name ## _sort_property_names (); \ } \ \ ecma_object_t *prototype_obj_p; \ if (object_prototype_builtin_id == ECMA_BUILTIN_ID__COUNT) \ { \ prototype_obj_p = NULL; \ } \ else \ { \ if (ecma_builtin_objects[object_prototype_builtin_id] == NULL) \ { \ ecma_instantiate_builtin (object_prototype_builtin_id); \ } \ prototype_obj_p = ecma_builtin_objects[object_prototype_builtin_id]; \ JERRY_ASSERT (prototype_obj_p != NULL); \ } \ \ ecma_object_t *builtin_obj_p = ecma_builtin_init_object (builtin_id, \ prototype_obj_p, \ object_type, \ is_extensible); \ ecma_builtin_objects[builtin_id] = builtin_obj_p; \ \ break; \ } #include "ecma-builtins.inc.h" default: { JERRY_ASSERT (id < ECMA_BUILTIN_ID__COUNT); JERRY_UNIMPLEMENTED ("The built-in is not implemented."); } } } /* ecma_instantiate_builtin */
/** * If the property's name is one of built-in properties of the object * that is not instantiated yet, instantiate the property and * return pointer to the instantiated property. * * @return pointer property, if one was instantiated, * NULL - otherwise. */ ecma_property_t* ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object */ ecma_string_t *string_p) /**< property's name */ { JERRY_ASSERT (ecma_get_object_is_builtin (object_p)); ecma_property_t *built_in_id_prop_p = ecma_get_internal_property (object_p, ECMA_INTERNAL_PROPERTY_BUILT_IN_ID); ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_id_prop_p->u.internal_property.value; JERRY_ASSERT (ecma_builtin_is (object_p, builtin_id)); switch (builtin_id) { #define BUILTIN(builtin_id, \ object_type, \ object_prototype_builtin_id, \ is_extensible, \ is_static, \ lowercase_name) \ case builtin_id: \ { \ return ecma_builtin_ ## lowercase_name ## _try_to_instantiate_property (object_p, \ string_p); \ } #include "ecma-builtins.inc.h" case ECMA_BUILTIN_ID__COUNT: { JERRY_UNREACHABLE (); } default: { #ifdef CONFIG_ECMA_COMPACT_PROFILE JERRY_UNREACHABLE (); #else /* CONFIG_ECMA_COMPACT_PROFILE */ JERRY_UNIMPLEMENTED ("The built-in is not implemented."); #endif /* !CONFIG_ECMA_COMPACT_PROFILE */ } } JERRY_UNREACHABLE (); } /* ecma_builtin_try_to_instantiate_property */
/** * Dispatcher of built-in routines * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_dispatch_routine (ecma_builtin_id_t builtin_object_id, /**< built-in object' identifier */ uint16_t builtin_routine_id, /**< builtin-wide identifier * of the built-in object's * routine property */ ecma_value_t this_arg_value, /**< 'this' argument value */ const ecma_value_t arguments_list[], /**< list of arguments passed to routine */ ecma_length_t arguments_number) /**< length of arguments' list */ { switch (builtin_object_id) { #define BUILTIN(builtin_id, \ object_type, \ object_prototype_builtin_id, \ is_extensible, \ is_static, \ lowercase_name) \ case builtin_id: \ { \ return ecma_builtin_ ## lowercase_name ## _dispatch_routine (builtin_routine_id, \ this_arg_value, \ arguments_list, \ arguments_number); \ } #include "ecma-builtins.inc.h" case ECMA_BUILTIN_ID__COUNT: { JERRY_UNREACHABLE (); } default: { #ifdef CONFIG_ECMA_COMPACT_PROFILE JERRY_UNREACHABLE (); #else /* CONFIG_ECMA_COMPACT_PROFILE */ JERRY_UNIMPLEMENTED ("The built-in is not implemented."); #endif /* !CONFIG_ECMA_COMPACT_PROFILE */ } } JERRY_UNREACHABLE (); } /* ecma_builtin_dispatch_routine */
/** * Mark objects as visited starting from specified object as root */ void ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ { JERRY_ASSERT (object_p != NULL); JERRY_ASSERT (ecma_gc_is_object_visited (object_p)); bool traverse_properties = true; if (ecma_is_lexical_environment (object_p)) { ecma_object_t *lex_env_p = ecma_get_lex_env_outer_reference (object_p); if (lex_env_p != NULL) { ecma_gc_set_object_visited (lex_env_p, true); } if (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_OBJECTBOUND) { ecma_object_t *binding_object_p = ecma_get_lex_env_binding_object (object_p); ecma_gc_set_object_visited (binding_object_p, true); traverse_properties = false; } } else { ecma_object_t *proto_p = ecma_get_object_prototype (object_p); if (proto_p != NULL) { ecma_gc_set_object_visited (proto_p, true); } } if (traverse_properties) { for (ecma_property_t *property_p = ecma_get_property_list (object_p), *next_property_p; property_p != NULL; property_p = next_property_p) { next_property_p = ECMA_GET_POINTER (ecma_property_t, property_p->next_property_p); switch ((ecma_property_type_t) property_p->type) { case ECMA_PROPERTY_NAMEDDATA: { ecma_value_t value = ecma_get_named_data_property_value (property_p); if (ecma_is_value_object (value)) { ecma_object_t *value_obj_p = ecma_get_object_from_value (value); ecma_gc_set_object_visited (value_obj_p, true); } break; } case ECMA_PROPERTY_NAMEDACCESSOR: { ecma_object_t *getter_obj_p = ecma_get_named_accessor_property_getter (property_p); ecma_object_t *setter_obj_p = ecma_get_named_accessor_property_setter (property_p); if (getter_obj_p != NULL) { ecma_gc_set_object_visited (getter_obj_p, true); } if (setter_obj_p != NULL) { ecma_gc_set_object_visited (setter_obj_p, true); } break; } case ECMA_PROPERTY_INTERNAL: { ecma_internal_property_id_t property_id = (ecma_internal_property_id_t) property_p->u.internal_property.type; uint32_t property_value = property_p->u.internal_property.value; switch (property_id) { case ECMA_INTERNAL_PROPERTY_NUMBER_INDEXED_ARRAY_VALUES: /* a collection of ecma-values */ case ECMA_INTERNAL_PROPERTY_STRING_INDEXED_ARRAY_VALUES: /* a collection of ecma-values */ { JERRY_UNIMPLEMENTED ("Indexed array storage is not implemented yet."); } case ECMA_INTERNAL_PROPERTY_PROTOTYPE: /* the property's value is located in ecma_object_t (see above in the routine) */ case ECMA_INTERNAL_PROPERTY_EXTENSIBLE: /* the property's value is located in ecma_object_t (see above in the routine) */ case ECMA_INTERNAL_PROPERTY__COUNT: /* not a real internal property type, * but number of the real internal property types */ { JERRY_UNREACHABLE (); } case ECMA_INTERNAL_PROPERTY_FORMAL_PARAMETERS: /* a collection of strings */ case ECMA_INTERNAL_PROPERTY_PRIMITIVE_STRING_VALUE: /* compressed pointer to a ecma_string_t */ case ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE: /* compressed pointer to a ecma_number_t */ case ECMA_INTERNAL_PROPERTY_PRIMITIVE_BOOLEAN_VALUE: /* a simple boolean value */ case ECMA_INTERNAL_PROPERTY_CLASS: /* an enum */ case ECMA_INTERNAL_PROPERTY_CODE_BYTECODE: /* compressed pointer to a bytecode array */ case ECMA_INTERNAL_PROPERTY_CODE_FLAGS_AND_OFFSET: /* an integer */ case ECMA_INTERNAL_PROPERTY_NATIVE_CODE: /* an external pointer */ case ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE: /* an external pointer */ case ECMA_INTERNAL_PROPERTY_FREE_CALLBACK: /* an object's native free callback */ case ECMA_INTERNAL_PROPERTY_BUILT_IN_ID: /* an integer */ case ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_DESC: /* an integer */ case ECMA_INTERNAL_PROPERTY_EXTENSION_ID: /* an integer */ case ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_0_31: /* an integer (bit-mask) */ case ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_32_63: /* an integer (bit-mask) */ case ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE: case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION: case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_THIS: case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_ARGS: { break; } case ECMA_INTERNAL_PROPERTY_SCOPE: /* a lexical environment */ case ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP: /* an object */ { ecma_object_t *obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, property_value); ecma_gc_set_object_visited (obj_p, true); break; } } break; } } } } } /* ecma_gc_mark */
/** * Convert specified string to token of specified type, transforming escape sequences * * @return token descriptor */ static token convert_string_to_token_transform_escape_seq (token_type tok_type, /**< type of token to produce */ const jerry_api_char_t *source_str_p, /**< string to convert, * located in source buffer */ size_t source_str_size) /**< size of the string */ { token ret; if (source_str_size == 0) { return convert_string_to_token (tok_type, lit_get_magic_string_utf8 (LIT_MAGIC_STRING__EMPTY), 0); } else { JERRY_ASSERT (source_str_p != NULL); } lit_utf8_byte_t *str_buf_p = (lit_utf8_byte_t*) jsp_mm_alloc (source_str_size); const lit_utf8_byte_t *source_str_iter_p = source_str_p; lit_utf8_byte_t *str_buf_iter_p = str_buf_p; bool is_correct_sequence = true; bool every_char_islower = true; bool every_char_allowed_in_identifier = true; while (source_str_iter_p < source_str_p + source_str_size) { ecma_char_t converted_char; if (*source_str_iter_p != '\\') { converted_char = (lit_utf8_byte_t) *source_str_iter_p++; JERRY_ASSERT (str_buf_iter_p <= str_buf_p + source_str_size); JERRY_ASSERT (source_str_iter_p <= source_str_p + source_str_size); } else { source_str_iter_p++; const lit_utf8_byte_t escape_character = (lit_utf8_byte_t) *source_str_iter_p++; JERRY_ASSERT (source_str_iter_p <= source_str_p + source_str_size); if (isdigit (escape_character)) { if (escape_character == '0') { JERRY_UNIMPLEMENTED ("<NUL> character is not currently supported.\n"); } else { /* Implementation-defined (ECMA-262 v5, B.1.2): octal escape sequences are not implemented */ is_correct_sequence = false; break; } } else if (escape_character == 'u' || escape_character == 'x') { const uint32_t hex_chars_num = (escape_character == 'u' ? 4u : 2u); if (source_str_iter_p + hex_chars_num > source_str_p + source_str_size) { is_correct_sequence = false; break; } bool chars_are_hex = true; uint16_t char_code = 0; for (uint32_t i = 0; i < hex_chars_num; i++) { const lit_utf8_byte_t byte = (lit_utf8_byte_t) *source_str_iter_p++; if (!isxdigit (byte)) { chars_are_hex = false; break; } else { /* * Check that highest 4 bits are zero, so the value would not overflow. */ JERRY_ASSERT ((char_code & 0xF000u) == 0); char_code = (uint16_t) (char_code << 4u); char_code = (uint16_t) (char_code + ecma_char_hex_to_int (byte)); } } JERRY_ASSERT (str_buf_iter_p <= str_buf_p + source_str_size); JERRY_ASSERT (source_str_iter_p <= source_str_p + source_str_size); if (!chars_are_hex) { is_correct_sequence = false; break; } /* * In CONFIG_ECMA_CHAR_ASCII mode size of ecma_char_t is 1 byte, so the conversion * would ignore highest part of 2-byte value, and in CONFIG_ECMA_CHAR_UTF16 mode this * would be just an assignment of 2-byte value. */ converted_char = (ecma_char_t) char_code; } else if (ecma_char_is_line_terminator (escape_character)) { if (source_str_iter_p + 1 <= source_str_p + source_str_size) { lit_utf8_byte_t byte = *source_str_iter_p; if (escape_character == '\x0D' && byte == '\x0A') { source_str_iter_p++; } } continue; } else { convert_single_escape_character ((ecma_char_t) escape_character, &converted_char); } } TODO ("Support surrogate paris.") str_buf_iter_p += lit_code_unit_to_utf8 (converted_char, str_buf_iter_p); JERRY_ASSERT (str_buf_iter_p <= str_buf_p + source_str_size); if (!islower (converted_char)) { every_char_islower = false; if (!isalpha (converted_char) && !isdigit (converted_char) && converted_char != '$' && converted_char != '_') { every_char_allowed_in_identifier = false; } } } if (is_correct_sequence) { lit_utf8_size_t length = (lit_utf8_size_t) (str_buf_iter_p - str_buf_p); ret = empty_token; if (tok_type == TOK_NAME) { if (every_char_islower) { ret = decode_keyword (str_buf_p, length); } else if (!every_char_allowed_in_identifier) { PARSE_ERROR ("Malformed identifier name", source_str_p - buffer_start); } } if (is_empty (ret)) { ret = convert_string_to_token (tok_type, str_buf_p, length); } } else { PARSE_ERROR ("Malformed escape sequence", source_str_p - buffer_start); } jsp_mm_free (str_buf_p); return ret; } /* convert_string_to_token_transform_escape_seq */
/** * 'Native call' opcode handler. */ ecma_completion_value_t opfunc_native_call (opcode_t opdata, /**< operation data */ int_data_t *int_data) /**< interpreter context */ { const idx_t dst_var_idx = opdata.data.native_call.lhs; const idx_t native_call_id_idx = opdata.data.native_call.name; const idx_t args_number = opdata.data.native_call.arg_list; const opcode_counter_t lit_oc = int_data->pos; JERRY_ASSERT (native_call_id_idx < OPCODE_NATIVE_CALL__COUNT); int_data->pos++; JERRY_STATIC_ASSERT (OPCODE_NATIVE_CALL__COUNT < (1u << (sizeof (native_call_id_idx) * JERRY_BITSINBYTE))); ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); MEM_DEFINE_LOCAL_ARRAY (arg_values, args_number, ecma_value_t); ecma_length_t args_read; ecma_completion_value_t get_arg_completion = fill_varg_list (int_data, args_number, arg_values, &args_read); if (ecma_is_completion_value_empty (get_arg_completion)) { JERRY_ASSERT (args_read == args_number); switch ((opcode_native_call_t)native_call_id_idx) { case OPCODE_NATIVE_CALL_LED_TOGGLE: case OPCODE_NATIVE_CALL_LED_ON: case OPCODE_NATIVE_CALL_LED_OFF: case OPCODE_NATIVE_CALL_LED_ONCE: case OPCODE_NATIVE_CALL_WAIT: { JERRY_UNIMPLEMENTED ("Device operations are not implemented."); } case OPCODE_NATIVE_CALL_PRINT: { for (ecma_length_t arg_index = 0; ecma_is_completion_value_empty (ret_value) && arg_index < args_read; arg_index++) { ECMA_TRY_CATCH (str_value, ecma_op_to_string (arg_values[arg_index]), ret_value); ecma_string_t *str_p = ecma_get_string_from_value (str_value); lit_utf8_size_t bytes = ecma_string_get_size (str_p); ssize_t utf8_str_size = (ssize_t) (bytes + 1); lit_utf8_byte_t *utf8_str_p = (lit_utf8_byte_t*) mem_heap_alloc_block ((size_t) utf8_str_size, MEM_HEAP_ALLOC_SHORT_TERM); if (utf8_str_p == NULL) { jerry_fatal (ERR_OUT_OF_MEMORY); } ecma_string_to_utf8_string (str_p, utf8_str_p, utf8_str_size); utf8_str_p[utf8_str_size - 1] = 0; FIXME ("Support unicode in printf."); if (arg_index < args_read - 1) { printf ("%s ", (char*) utf8_str_p); } else { printf ("%s", (char*) utf8_str_p); } mem_heap_free_block (utf8_str_p); ret_value = set_variable_value (int_data, lit_oc, dst_var_idx, ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED)); ECMA_FINALIZE (str_value); } printf ("\n"); break; } case OPCODE_NATIVE_CALL__COUNT: { JERRY_UNREACHABLE (); } } } else { JERRY_ASSERT (!ecma_is_completion_value_normal (get_arg_completion)); ret_value = get_arg_completion; } for (ecma_length_t arg_index = 0; arg_index < args_read; arg_index++) { ecma_free_value (arg_values[arg_index], true); } MEM_FINALIZE_LOCAL_ARRAY (arg_values); return ret_value; } /* opfunc_native_call */
/** * Handle calling [[Call]] of built-in object * * @return ecma value */ ecma_value_t ecma_builtin_dispatch_call (ecma_object_t *obj_p, /**< built-in object */ ecma_value_t this_arg_value, /**< 'this' argument value */ const ecma_value_t *arguments_list_p, /**< arguments list */ ecma_length_t arguments_list_len) /**< arguments list length */ { JERRY_ASSERT (ecma_get_object_is_builtin (obj_p)); ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION) { ecma_property_t *desc_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_DESC); uint64_t builtin_routine_desc = desc_prop_p->u.internal_property.value; uint64_t built_in_id_field = jrt_extract_bit_field (builtin_routine_desc, ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_OBJECT_ID_POS, ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_OBJECT_ID_WIDTH); JERRY_ASSERT (built_in_id_field < ECMA_BUILTIN_ID__COUNT); uint64_t routine_id_field = jrt_extract_bit_field (builtin_routine_desc, ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_ROUTINE_ID_POS, ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_ROUTINE_ID_WIDTH); JERRY_ASSERT ((uint16_t) routine_id_field == routine_id_field); ecma_builtin_id_t built_in_id = (ecma_builtin_id_t) built_in_id_field; uint16_t routine_id = (uint16_t) routine_id_field; ret_value = ecma_builtin_dispatch_routine (built_in_id, routine_id, this_arg_value, arguments_list_p, arguments_list_len); } else { JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION); ecma_property_t *built_in_id_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_BUILT_IN_ID); ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_id_prop_p->u.internal_property.value; JERRY_ASSERT (ecma_builtin_is (obj_p, builtin_id)); switch (builtin_id) { #define BUILTIN(builtin_id, \ object_type, \ object_prototype_builtin_id, \ is_extensible, \ is_static, \ lowercase_name) \ case builtin_id: \ { \ if (object_type == ECMA_OBJECT_TYPE_FUNCTION) \ { \ ret_value = ecma_builtin_ ## lowercase_name ## _dispatch_call (arguments_list_p, \ arguments_list_len); \ } \ break; \ } #include "ecma-builtins.inc.h" case ECMA_BUILTIN_ID__COUNT: { JERRY_UNREACHABLE (); } default: { #ifdef CONFIG_ECMA_COMPACT_PROFILE JERRY_UNREACHABLE (); #else /* CONFIG_ECMA_COMPACT_PROFILE */ JERRY_UNIMPLEMENTED ("The built-in is not implemented."); #endif /* !CONFIG_ECMA_COMPACT_PROFILE */ } } } JERRY_ASSERT (!ecma_is_value_empty (ret_value)); return ret_value; } /* ecma_builtin_dispatch_call */
/** * List names of a built-in object's lazy instantiated properties * * See also: * ecma_builtin_try_to_instantiate_property */ void ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in 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 */ { const ecma_object_type_t type = ecma_get_object_type (object_p); if (type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION) { ecma_collection_header_t *for_enumerable_p = main_collection_p; (void) for_enumerable_p; ecma_collection_header_t *for_non_enumerable_p = separate_enumerable ? non_enum_collection_p : main_collection_p; /* 'length' property is non-enumerable (ECMA-262 v5, 15) */ ecma_string_t *name_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_append_to_values_collection (for_non_enumerable_p, ecma_make_string_value (name_p), true); ecma_deref_ecma_string (name_p); } else { ecma_property_t *built_in_id_prop_p = ecma_get_internal_property (object_p, ECMA_INTERNAL_PROPERTY_BUILT_IN_ID); ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_id_prop_p->u.internal_property.value; JERRY_ASSERT (ecma_builtin_is (object_p, builtin_id)); switch (builtin_id) { #define BUILTIN(builtin_id, \ object_type, \ object_prototype_builtin_id, \ is_extensible, \ is_static, \ lowercase_name) \ case builtin_id: \ { \ ecma_builtin_ ## lowercase_name ## _list_lazy_property_names (object_p, \ separate_enumerable, \ main_collection_p, \ non_enum_collection_p); \ return; \ } #include "ecma-builtins.inc.h" case ECMA_BUILTIN_ID__COUNT: { JERRY_UNREACHABLE (); } default: { #ifdef CONFIG_ECMA_COMPACT_PROFILE JERRY_UNREACHABLE (); #else /* CONFIG_ECMA_COMPACT_PROFILE */ JERRY_UNIMPLEMENTED ("The built-in is not implemented."); #endif /* !CONFIG_ECMA_COMPACT_PROFILE */ } } JERRY_UNREACHABLE (); } } /* ecma_builtin_list_lazy_property_names */
/** * If the property's name is one of built-in properties of the object * that is not instantiated yet, instantiate the property and * return pointer to the instantiated property. * * @return pointer property, if one was instantiated, * NULL - otherwise. */ ecma_property_t * ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object */ ecma_string_t *string_p) /**< property's name */ { JERRY_ASSERT (ecma_get_object_is_builtin (object_p)); const ecma_object_type_t type = ecma_get_object_type (object_p); if (type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION) { ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); bool is_length_property = ecma_compare_ecma_strings (string_p, magic_string_length_p); ecma_deref_ecma_string (magic_string_length_p); if (is_length_property) { /* * Lazy instantiation of 'length' property * * Note: * We don't need to mark that the property was already lazy instantiated, * as it is non-configurable and so can't be deleted */ ecma_property_t *desc_prop_p = ecma_get_internal_property (object_p, ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_DESC); uint64_t builtin_routine_desc = desc_prop_p->u.internal_property.value; JERRY_STATIC_ASSERT (sizeof (uint8_t) * JERRY_BITSINBYTE == ECMA_BUILTIN_ROUTINE_ID_LENGTH_VALUE_WIDTH, bits_in_uint8_t_must_be_equal_to_ECMA_BUILTIN_ROUTINE_ID_LENGTH_VALUE_WIDTH); uint8_t length_prop_value = (uint8_t) jrt_extract_bit_field (builtin_routine_desc, ECMA_BUILTIN_ROUTINE_ID_LENGTH_VALUE_POS, ECMA_BUILTIN_ROUTINE_ID_LENGTH_VALUE_WIDTH); ecma_property_t *len_prop_p = ecma_create_named_data_property (object_p, string_p, false, false, false); ecma_number_t *len_p = ecma_alloc_number (); *len_p = length_prop_value; ecma_set_named_data_property_value (len_prop_p, ecma_make_number_value (len_p)); JERRY_ASSERT (!ecma_is_property_configurable (len_prop_p)); return len_prop_p; } return NULL; } else { ecma_property_t *built_in_id_prop_p = ecma_get_internal_property (object_p, ECMA_INTERNAL_PROPERTY_BUILT_IN_ID); ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_id_prop_p->u.internal_property.value; JERRY_ASSERT (ecma_builtin_is (object_p, builtin_id)); switch (builtin_id) { #define BUILTIN(builtin_id, \ object_type, \ object_prototype_builtin_id, \ is_extensible, \ is_static, \ lowercase_name) \ case builtin_id: \ { \ return ecma_builtin_ ## lowercase_name ## _try_to_instantiate_property (object_p, \ string_p); \ } #include "ecma-builtins.inc.h" case ECMA_BUILTIN_ID__COUNT: { JERRY_UNREACHABLE (); } default: { #ifdef CONFIG_ECMA_COMPACT_PROFILE JERRY_UNREACHABLE (); #else /* CONFIG_ECMA_COMPACT_PROFILE */ JERRY_UNIMPLEMENTED ("The built-in is not implemented."); #endif /* !CONFIG_ECMA_COMPACT_PROFILE */ } } JERRY_UNREACHABLE (); } } /* ecma_builtin_try_to_instantiate_property */
/** * Handle calling [[Call]] of built-in object * * @return ecma value */ ecma_value_t ecma_builtin_dispatch_call (ecma_object_t *obj_p, /**< built-in object */ ecma_value_t this_arg_value, /**< 'this' argument value */ const ecma_value_t *arguments_list_p, /**< arguments list */ ecma_length_t arguments_list_len) /**< arguments list length */ { JERRY_ASSERT (ecma_get_object_is_builtin (obj_p)); ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; if (ecma_builtin_function_is_routine (obj_p)) { ret_value = ecma_builtin_dispatch_routine (ext_obj_p->u.built_in.id, ext_obj_p->u.built_in.routine_id, this_arg_value, arguments_list_p, arguments_list_len); } else { JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION); switch ((ecma_builtin_id_t) ext_obj_p->u.built_in.id) { #define BUILTIN(builtin_id, \ object_type, \ object_prototype_builtin_id, \ is_extensible, \ is_static, \ lowercase_name) \ case builtin_id: \ { \ if (object_type == ECMA_OBJECT_TYPE_FUNCTION) \ { \ ret_value = ecma_builtin_ ## lowercase_name ## _dispatch_call (arguments_list_p, \ arguments_list_len); \ } \ break; \ } #include "ecma-builtins.inc.h" case ECMA_BUILTIN_ID__COUNT: { JERRY_UNREACHABLE (); } default: { #ifdef CONFIG_ECMA_COMPACT_PROFILE JERRY_UNREACHABLE (); #else /* !CONFIG_ECMA_COMPACT_PROFILE */ JERRY_UNIMPLEMENTED ("The built-in is not implemented."); #endif /* CONFIG_ECMA_COMPACT_PROFILE */ } } } JERRY_ASSERT (!ecma_is_value_empty (ret_value)); return ret_value; } /* ecma_builtin_dispatch_call */
/** * Mark referenced object from property */ static void ecma_gc_mark_property (ecma_property_t *property_p) /**< property */ { switch (ECMA_PROPERTY_GET_TYPE (property_p)) { case ECMA_PROPERTY_TYPE_NAMEDDATA: { ecma_value_t value = ecma_get_named_data_property_value (property_p); if (ecma_is_value_object (value)) { ecma_object_t *value_obj_p = ecma_get_object_from_value (value); ecma_gc_set_object_visited (value_obj_p, true); } break; } case ECMA_PROPERTY_TYPE_NAMEDACCESSOR: { ecma_object_t *getter_obj_p = ecma_get_named_accessor_property_getter (property_p); ecma_object_t *setter_obj_p = ecma_get_named_accessor_property_setter (property_p); if (getter_obj_p != NULL) { ecma_gc_set_object_visited (getter_obj_p, true); } if (setter_obj_p != NULL) { ecma_gc_set_object_visited (setter_obj_p, true); } break; } case ECMA_PROPERTY_TYPE_INTERNAL: { uint32_t property_value = ECMA_PROPERTY_VALUE_PTR (property_p)->value; switch (ECMA_PROPERTY_GET_INTERNAL_PROPERTY_TYPE (property_p)) { case ECMA_INTERNAL_PROPERTY_NUMBER_INDEXED_ARRAY_VALUES: /* a collection of ecma values */ case ECMA_INTERNAL_PROPERTY_STRING_INDEXED_ARRAY_VALUES: /* a collection of ecma values */ { JERRY_UNIMPLEMENTED ("Indexed array storage is not implemented yet."); } case ECMA_INTERNAL_PROPERTY_PROTOTYPE: /* the property's value is located in ecma_object_t * (see above in the routine) */ case ECMA_INTERNAL_PROPERTY_EXTENSIBLE: /* the property's value is located in ecma_object_t * (see above in the routine) */ case ECMA_INTERNAL_PROPERTY__COUNT: /* not a real internal property type, * but number of the real internal property types */ { JERRY_UNREACHABLE (); } case ECMA_INTERNAL_PROPERTY_PRIMITIVE_STRING_VALUE: /* compressed pointer to a ecma_string_t */ case ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE: /* compressed pointer to a ecma_number_t */ case ECMA_INTERNAL_PROPERTY_PRIMITIVE_BOOLEAN_VALUE: /* a simple boolean value */ case ECMA_INTERNAL_PROPERTY_CLASS: /* an enum */ case ECMA_INTERNAL_PROPERTY_CODE_BYTECODE: /* compressed pointer to a bytecode array */ case ECMA_INTERNAL_PROPERTY_NATIVE_CODE: /* an external pointer */ case ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE: /* an external pointer */ case ECMA_INTERNAL_PROPERTY_FREE_CALLBACK: /* an object's native free callback */ case ECMA_INTERNAL_PROPERTY_BUILT_IN_ID: /* an integer */ case ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_DESC: /* an integer */ case ECMA_INTERNAL_PROPERTY_EXTENSION_ID: /* an integer */ case ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_0_31: /* an integer (bit-mask) */ case ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_32_63: /* an integer (bit-mask) */ case ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE: { break; } case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_THIS: /* an ecma value */ { if (ecma_is_value_object (property_value)) { ecma_object_t *obj_p = ecma_get_object_from_value (property_value); ecma_gc_set_object_visited (obj_p, true); } break; } case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_ARGS: /* a collection of ecma values */ { ecma_collection_header_t *bound_arg_list_p = ECMA_GET_NON_NULL_POINTER (ecma_collection_header_t, property_value); ecma_collection_iterator_t bound_args_iterator; ecma_collection_iterator_init (&bound_args_iterator, bound_arg_list_p); for (ecma_length_t i = 0; i < bound_arg_list_p->unit_number; i++) { bool is_moved = ecma_collection_iterator_next (&bound_args_iterator); JERRY_ASSERT (is_moved); if (ecma_is_value_object (*bound_args_iterator.current_value_p)) { ecma_object_t *obj_p = ecma_get_object_from_value (*bound_args_iterator.current_value_p); ecma_gc_set_object_visited (obj_p, true); } } break; } case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION: /* an object */ case ECMA_INTERNAL_PROPERTY_SCOPE: /* a lexical environment */ case ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP: /* an object */ { ecma_object_t *obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, property_value); ecma_gc_set_object_visited (obj_p, true); break; } } break; } default: { JERRY_UNREACHABLE (); break; } } } /* ecma_gc_mark_property */
/** * Handle calling [[Construct]] of built-in object * * @return completion-value */ ecma_completion_value_t ecma_builtin_dispatch_construct (ecma_object_t *obj_p, /**< built-in object */ ecma_collection_header_t* arg_collection_p) /**< arguments collection */ { JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION); JERRY_ASSERT (ecma_get_object_is_builtin (obj_p)); ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); const ecma_length_t arguments_list_len = arg_collection_p != NULL ? arg_collection_p->unit_number : 0; MEM_DEFINE_LOCAL_ARRAY (arguments_list_p, arguments_list_len, ecma_value_t); ecma_collection_iterator_t arg_collection_iter; ecma_collection_iterator_init (&arg_collection_iter, arg_collection_p); for (ecma_length_t arg_index = 0; ecma_collection_iterator_next (&arg_collection_iter); arg_index++) { arguments_list_p[arg_index] = *arg_collection_iter.current_value_p; } ecma_property_t *built_in_id_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_BUILT_IN_ID); ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_id_prop_p->u.internal_property.value; JERRY_ASSERT (ecma_builtin_is (obj_p, builtin_id)); JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION); switch (builtin_id) { #define BUILTIN(builtin_id, \ object_type, \ object_prototype_builtin_id, \ is_extensible, \ is_static, \ lowercase_name) \ case builtin_id: \ { \ if (object_type == ECMA_OBJECT_TYPE_FUNCTION) \ { \ ret_value = ecma_builtin_ ## lowercase_name ## _dispatch_construct (arguments_list_p, \ arguments_list_len); \ } \ break; \ } #include "ecma-builtins.inc.h" case ECMA_BUILTIN_ID__COUNT: { JERRY_UNREACHABLE (); } default: { #ifdef CONFIG_ECMA_COMPACT_PROFILE JERRY_UNREACHABLE (); #else /* CONFIG_ECMA_COMPACT_PROFILE */ JERRY_UNIMPLEMENTED ("The built-in is not implemented."); #endif /* !CONFIG_ECMA_COMPACT_PROFILE */ } } MEM_FINALIZE_LOCAL_ARRAY (arguments_list_p); JERRY_ASSERT (!ecma_is_completion_value_empty (ret_value)); return ret_value; } /* ecma_builtin_dispatch_construct */