/** * ECMA-reference constructor. * * @return ECMA-reference * Returned value must be freed through ecma_free_reference. */ ecma_reference_t ecma_make_reference (ecma_value_t base, /**< base value */ ecma_string_t *name_p, /**< referenced name */ bool is_strict) /**< strict reference flag */ { ecma_ref_ecma_string (name_p); ecma_reference_t ref; ref.base = ecma_copy_value (base); ref.is_strict = (is_strict != 0); ECMA_SET_POINTER (ref.referenced_name_cp, name_p); return ref; } /* ecma_make_reference */
/** * Standard ecma-error object constructor. * * @return pointer to ecma-object representing specified error * with reference counter set to one. */ ecma_object_t * ecma_new_standard_error_with_message (ecma_standard_error_t error_type, /**< native error type */ ecma_string_t *message_string_p) /**< message string */ { ecma_object_t *new_error_obj_p = ecma_new_standard_error (error_type); ecma_string_t *message_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_MESSAGE); ecma_property_t *prop_p = ecma_create_named_data_property (new_error_obj_p, message_magic_string_p, ECMA_PROPERTY_CONFIGURABLE_WRITABLE); ecma_ref_ecma_string (message_string_p); ecma_set_named_data_property_value (prop_p, ecma_make_string_value (message_string_p)); ecma_deref_ecma_string (message_magic_string_p); return new_error_obj_p; } /* ecma_new_standard_error_with_message */
/** * Send string representation of exception to the client. * * @return true - if the data sent successfully to the debugger client, * false - otherwise */ bool jerry_debugger_send_exception_string (void) { ecma_string_t *string_p = NULL; ecma_value_t exception_value = JERRY_CONTEXT (error_value); if (ecma_is_value_object (exception_value)) { string_p = jerry_debugger_exception_object_to_string (exception_value); if (string_p == NULL) { string_p = ecma_get_string_from_value (ecma_builtin_helper_object_to_string (exception_value)); } } else if (ecma_is_value_string (exception_value)) { string_p = ecma_get_string_from_value (exception_value); ecma_ref_ecma_string (string_p); } else { exception_value = ecma_op_to_string (exception_value); string_p = ecma_get_string_from_value (exception_value); } ECMA_STRING_TO_UTF8_STRING (string_p, string_data_p, string_size); bool result = jerry_debugger_send_string (JERRY_DEBUGGER_EXCEPTION_STR, JERRY_DEBUGGER_NO_SUBTYPE, string_data_p, string_size); ECMA_FINALIZE_UTF8_STRING (string_data_p, string_size); ecma_deref_ecma_string (string_p); return result; } /* jerry_debugger_send_exception_string */
/** * [[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 RegExp.prototype object's 'compile' routine * * See also: * ECMA-262 v5, B.2.5.1 * * @return undefined - if compiled successfully * error ecma value - otherwise * * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_regexp_prototype_compile (ecma_value_t this_arg, /**< this argument */ ecma_value_t pattern_arg, /**< pattern or RegExp object */ ecma_value_t flags_arg) /**< flags */ { 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_string_t *pattern_string_p = NULL; uint16_t flags = 0; if (ecma_is_value_object (pattern_arg) && ecma_object_get_class_name (ecma_get_object_from_value (pattern_arg)) == LIT_MAGIC_STRING_REGEXP_UL) { if (!ecma_is_value_undefined (flags_arg)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Invalid argument of RegExp compile.")); } else { /* Compile from existing RegExp pbject. */ ecma_object_t *target_p = ecma_get_object_from_value (pattern_arg); /* Get source. */ ecma_string_t *magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_SOURCE); ecma_property_t *prop_p = ecma_op_object_get_property (target_p, magic_string_p); pattern_string_p = ecma_get_string_from_value (ecma_get_named_data_property_value (prop_p)); ecma_deref_ecma_string (magic_string_p); /* Get flags. */ magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_GLOBAL); prop_p = ecma_op_object_get_property (target_p, magic_string_p); if (ecma_is_value_true (ecma_get_named_data_property_value (prop_p))) { flags |= RE_FLAG_GLOBAL; } ecma_deref_ecma_string (magic_string_p); magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_IGNORECASE_UL); prop_p = ecma_op_object_get_property (target_p, magic_string_p); if (ecma_is_value_true (ecma_get_named_data_property_value (prop_p))) { flags |= RE_FLAG_IGNORE_CASE; } ecma_deref_ecma_string (magic_string_p); magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_MULTILINE); prop_p = ecma_op_object_get_property (target_p, magic_string_p); if (ecma_is_value_true (ecma_get_named_data_property_value (prop_p))) { flags |= RE_FLAG_MULTILINE; } ecma_deref_ecma_string (magic_string_p); ECMA_TRY_CATCH (obj_this, ecma_op_to_object (this_arg), ret_value); ecma_object_t *this_obj_p = ecma_get_object_from_value (obj_this); /* Get bytecode property. */ ecma_property_t *bc_prop_p = ecma_get_internal_property (this_obj_p, ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE); /* TODO: We currently have to re-compile the bytecode, because * we can't copy it without knowing its length. */ const re_compiled_code_t *new_bc_p = NULL; ecma_value_t bc_comp = re_compile_bytecode (&new_bc_p, pattern_string_p, flags); /* Should always succeed, since we're compiling from a source that has been compiled previously. */ JERRY_ASSERT (ecma_is_value_empty (bc_comp)); re_compiled_code_t *old_bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t, ecma_get_internal_property_value (bc_prop_p)); if (old_bc_p != NULL) { /* Free the old bytecode */ ecma_bytecode_deref ((ecma_compiled_code_t *) old_bc_p); } ECMA_SET_INTERNAL_VALUE_POINTER (ECMA_PROPERTY_VALUE_PTR (bc_prop_p)->value, new_bc_p); re_initialize_props (this_obj_p, pattern_string_p, flags); ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); ECMA_FINALIZE (obj_this); } } else { /* Get source string. */ if (!ecma_is_value_undefined (pattern_arg)) { ECMA_TRY_CATCH (regexp_str_value, ecma_op_to_string (pattern_arg), ret_value); if (ecma_string_is_empty (ecma_get_string_from_value (regexp_str_value))) { pattern_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP); } else { pattern_string_p = ecma_get_string_from_value (regexp_str_value); ecma_ref_ecma_string (pattern_string_p); } ECMA_FINALIZE (regexp_str_value); } else { pattern_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP); } /* Parse flags. */ if (ecma_is_value_empty (ret_value) && !ecma_is_value_undefined (flags_arg)) { ECMA_TRY_CATCH (flags_str_value, ecma_op_to_string (flags_arg), ret_value); ECMA_TRY_CATCH (flags_dummy, re_parse_regexp_flags (ecma_get_string_from_value (flags_str_value), &flags), ret_value); ECMA_FINALIZE (flags_dummy); ECMA_FINALIZE (flags_str_value); } if (ecma_is_value_empty (ret_value)) { ECMA_TRY_CATCH (obj_this, ecma_op_to_object (this_arg), ret_value); ecma_object_t *this_obj_p = ecma_get_object_from_value (obj_this); ecma_property_t *bc_prop_p = ecma_get_internal_property (this_obj_p, ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE); /* Try to compile bytecode from new source. */ const re_compiled_code_t *new_bc_p = NULL; ECMA_TRY_CATCH (bc_dummy, re_compile_bytecode (&new_bc_p, pattern_string_p, flags), ret_value); re_compiled_code_t *old_bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t, ecma_get_internal_property_value (bc_prop_p)); if (old_bc_p != NULL) { /* Free the old bytecode */ ecma_bytecode_deref ((ecma_compiled_code_t *) old_bc_p); } ECMA_SET_INTERNAL_VALUE_POINTER (ECMA_PROPERTY_VALUE_PTR (bc_prop_p)->value, new_bc_p); re_initialize_props (this_obj_p, pattern_string_p, flags); ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); ECMA_FINALIZE (bc_dummy); ECMA_FINALIZE (obj_this); } if (pattern_string_p != NULL) { ecma_deref_ecma_string (pattern_string_p); } } } return ret_value; } /* ecma_builtin_regexp_prototype_compile */
/** * 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); ecma_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 */
/** * Concatenate ecma-strings * * @return concatenation of two ecma-strings */ ecma_string_t * ecma_concat_ecma_strings (ecma_string_t *string1_p, /**< first ecma-string */ ecma_string_t *string2_p) /**< second ecma-string */ { JERRY_ASSERT (string1_p != NULL && string2_p != NULL); if (ecma_string_is_empty (string1_p)) { ecma_ref_ecma_string (string2_p); return string2_p; } else if (ecma_string_is_empty (string2_p)) { ecma_ref_ecma_string (string1_p); return string1_p; } const lit_utf8_byte_t *utf8_string1_p, *utf8_string2_p; lit_utf8_size_t utf8_string1_size, utf8_string2_size; lit_utf8_size_t utf8_string1_length, utf8_string2_length; lit_utf8_byte_t uint32_to_string_buffer1[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; lit_utf8_byte_t uint32_to_string_buffer2[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; switch (ECMA_STRING_GET_CONTAINER (string1_p)) { case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: { utf8_string1_p = (lit_utf8_byte_t *) (string1_p + 1); utf8_string1_size = string1_p->u.utf8_string.size; utf8_string1_length = string1_p->u.utf8_string.length; break; } case ECMA_STRING_CONTAINER_UINT32_IN_DESC: { utf8_string1_size = ecma_uint32_to_utf8_string (string1_p->u.uint32_number, uint32_to_string_buffer1, ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); utf8_string1_p = uint32_to_string_buffer1; utf8_string1_length = utf8_string1_size; break; } case ECMA_STRING_CONTAINER_MAGIC_STRING: { utf8_string1_p = lit_get_magic_string_utf8 (string1_p->u.magic_string_id); utf8_string1_size = lit_get_magic_string_size (string1_p->u.magic_string_id); utf8_string1_length = utf8_string1_size; break; } default: { JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); utf8_string1_p = lit_get_magic_string_ex_utf8 (string1_p->u.magic_string_id); utf8_string1_size = lit_get_magic_string_ex_size (string1_p->u.magic_string_id); utf8_string1_length = utf8_string1_size; break; } } switch (ECMA_STRING_GET_CONTAINER (string2_p)) { case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: { utf8_string2_p = (lit_utf8_byte_t *) (string2_p + 1); utf8_string2_size = string2_p->u.utf8_string.size; utf8_string2_length = string2_p->u.utf8_string.length; break; } case ECMA_STRING_CONTAINER_UINT32_IN_DESC: { utf8_string2_size = ecma_uint32_to_utf8_string (string2_p->u.uint32_number, uint32_to_string_buffer2, ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); utf8_string2_p = uint32_to_string_buffer2; utf8_string2_length = utf8_string2_size; break; } case ECMA_STRING_CONTAINER_MAGIC_STRING: { utf8_string2_p = lit_get_magic_string_utf8 (string2_p->u.magic_string_id); utf8_string2_size = lit_get_magic_string_size (string2_p->u.magic_string_id); utf8_string2_length = utf8_string2_size; break; } default: { JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string2_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); utf8_string2_p = lit_get_magic_string_ex_utf8 (string2_p->u.magic_string_id); utf8_string2_size = lit_get_magic_string_ex_size (string2_p->u.magic_string_id); utf8_string2_length = utf8_string2_size; break; } } JERRY_ASSERT (utf8_string1_size > 0); JERRY_ASSERT (utf8_string2_size > 0); JERRY_ASSERT (utf8_string1_length <= utf8_string1_size); JERRY_ASSERT (utf8_string2_length <= utf8_string2_size); lit_utf8_size_t new_size = utf8_string1_size + utf8_string2_size; JERRY_ASSERT (new_size <= UINT16_MAX); ecma_string_t *string_desc_p = jmem_heap_alloc_block (sizeof (ecma_string_t) + new_size); string_desc_p->refs_and_container = ECMA_STRING_CONTAINER_HEAP_UTF8_STRING | ECMA_STRING_REF_ONE; string_desc_p->hash = lit_utf8_string_hash_combine (string1_p->hash, utf8_string2_p, utf8_string2_size); string_desc_p->u.common_field = 0; string_desc_p->u.utf8_string.size = (uint16_t) new_size; string_desc_p->u.utf8_string.length = (uint16_t) (utf8_string1_length + utf8_string2_length); lit_utf8_byte_t *data_p = (lit_utf8_byte_t *) (string_desc_p + 1); memcpy (data_p, utf8_string1_p, utf8_string1_size); memcpy (data_p + utf8_string1_size, utf8_string2_p, utf8_string2_size); return string_desc_p; } /* ecma_concat_ecma_strings */
/** * Handle calling [[Construct]] of built-in RegExp object * * @return ecma value * Returned value must be freed with ecma_free_value. */ ecma_value_t ecma_builtin_regexp_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ ecma_length_t arguments_list_len) /**< number of arguments */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ecma_value_t pattern_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); ecma_value_t flags_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); if (arguments_list_len > 0) { /* pattern string or RegExp object */ pattern_value = arguments_list_p[0]; if (arguments_list_len > 1) { flags_value = arguments_list_p[1]; } } if (ecma_is_value_object (pattern_value) && ecma_object_get_class_name (ecma_get_object_from_value (pattern_value)) == LIT_MAGIC_STRING_REGEXP_UL) { if (ecma_is_value_undefined (flags_value)) { ret_value = ecma_copy_value (pattern_value); } else { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Invalid argument of RegExp call.")); } } else { ecma_string_t *pattern_string_p = NULL; ecma_string_t *flags_string_p = NULL; if (!ecma_is_value_undefined (pattern_value)) { ECMA_TRY_CATCH (regexp_str_value, ecma_op_to_string (pattern_value), ret_value); if (ecma_string_is_empty (ecma_get_string_from_value (regexp_str_value))) { pattern_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP); } else { pattern_string_p = ecma_get_string_from_value (regexp_str_value); ecma_ref_ecma_string (pattern_string_p); } ECMA_FINALIZE (regexp_str_value); } else { pattern_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP); } if (ecma_is_value_empty (ret_value) && !ecma_is_value_undefined (flags_value)) { ECMA_TRY_CATCH (flags_str_value, ecma_op_to_string (flags_value), ret_value); flags_string_p = ecma_get_string_from_value (flags_str_value); ecma_ref_ecma_string (flags_string_p); ECMA_FINALIZE (flags_str_value); } if (ecma_is_value_empty (ret_value)) { ret_value = ecma_op_create_regexp_object (pattern_string_p, flags_string_p); } if (pattern_string_p != NULL) { ecma_deref_ecma_string (pattern_string_p); } if (flags_string_p != NULL) { ecma_deref_ecma_string (flags_string_p); } } return ret_value; } /* ecma_builtin_regexp_dispatch_construct */
/** * Get backtrace. The backtrace is an array of strings where * each string contains the position of the corresponding frame. * The array length is zero if the backtrace is not available. * * @return array ecma value */ ecma_value_t vm_get_backtrace (uint32_t max_depth) /**< maximum backtrace depth, 0 = unlimited */ { #ifdef JERRY_ENABLE_LINE_INFO ecma_value_t result_array = ecma_op_create_array_object (NULL, 0, false); if (max_depth == 0) { max_depth = UINT32_MAX; } vm_frame_ctx_t *context_p = JERRY_CONTEXT (vm_top_context_p); ecma_object_t *array_p = ecma_get_object_from_value (result_array); uint32_t index = 0; while (context_p != NULL) { if (context_p->resource_name == ECMA_VALUE_UNDEFINED) { context_p = context_p->prev_context_p; continue; } ecma_string_t *str_p = ecma_get_string_from_value (context_p->resource_name); if (ecma_string_is_empty (str_p)) { const char *unknown_str_p = "<unknown>:"; str_p = ecma_new_ecma_string_from_utf8 ((const lit_utf8_byte_t *) unknown_str_p, (lit_utf8_size_t) strlen (unknown_str_p)); } else { ecma_ref_ecma_string (str_p); str_p = ecma_append_magic_string_to_string (str_p, LIT_MAGIC_STRING_COLON_CHAR); } ecma_string_t *line_str_p = ecma_new_ecma_string_from_uint32 (context_p->current_line); str_p = ecma_concat_ecma_strings (str_p, line_str_p); ecma_deref_ecma_string (line_str_p); ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index); ecma_property_value_t *prop_value_p; prop_value_p = ecma_create_named_data_property (array_p, index_str_p, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, NULL); ecma_deref_ecma_string (index_str_p); prop_value_p->value = ecma_make_string_value (str_p); context_p = context_p->prev_context_p; index++; if (index >= max_depth) { break; } } if (index > 0) { JERRY_ASSERT (ecma_get_object_type (array_p) == ECMA_OBJECT_TYPE_ARRAY); ((ecma_extended_object_t *) array_p)->u.array.length = index; } return result_array; #else /* !JERRY_ENABLE_LINE_INFO */ JERRY_UNUSED (max_depth); return ecma_op_create_array_object (NULL, 0, false); #endif /* JERRY_ENABLE_LINE_INFO */ } /* vm_get_backtrace */