/** * The Date.prototype object's 'setMinutes' routine * * See also: * ECMA-262 v5, 15.9.5.32 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_date_prototype_set_minutes (ecma_value_t this_arg, /**< this argument */ const ecma_value_t args[], /**< arguments list */ ecma_length_t args_number) /**< number of arguments */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 1. */ ECMA_TRY_CATCH (this_time_value, ecma_builtin_date_prototype_get_time (this_arg), ret_value); ecma_number_t t = ecma_date_local_time (*ecma_get_number_from_value (this_time_value)); /* 2. */ ecma_number_t m = ecma_number_make_nan (); ecma_number_t s = ecma_date_sec_from_time (t); ecma_number_t milli = ecma_date_ms_from_time (t); if (args_number > 0 && !ecma_is_value_undefined (args[0])) { ECMA_OP_TO_NUMBER_TRY_CATCH (min, args[0], ret_value); m = min; /* 3. */ if (args_number > 1 && !ecma_is_value_undefined (args[1])) { ECMA_OP_TO_NUMBER_TRY_CATCH (sec, args[1], ret_value); s = sec; /* 4. */ if (args_number > 2 && !ecma_is_value_undefined (args[2])) { ECMA_OP_TO_NUMBER_TRY_CATCH (ms, args[2], ret_value); milli = ms; ECMA_OP_TO_NUMBER_FINALIZE (ms); } ECMA_OP_TO_NUMBER_FINALIZE (sec); } ECMA_OP_TO_NUMBER_FINALIZE (min); } if (ecma_is_value_empty (ret_value)) { /* 5-8. */ ecma_number_t hour = ecma_date_hour_from_time (t); ret_value = ecma_date_set_internal_property (this_arg, ecma_date_day (t), ecma_date_make_time (hour, m, s, milli), ECMA_DATE_LOCAL); } ECMA_FINALIZE (this_time_value); return ret_value; } /* ecma_builtin_date_prototype_set_minutes */
/** * ToObject operation. * * See also: * ECMA-262 v5, 9.9 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_to_object (ecma_value_t value) /**< ecma value */ { ecma_check_value_type_is_spec_defined (value); if (ecma_is_value_number (value)) { return ecma_op_create_number_object (value); } else if (ecma_is_value_string (value)) { return ecma_op_create_string_object (&value, 1); } else if (ecma_is_value_object (value)) { return ecma_copy_value (value); } else { if (ecma_is_value_undefined (value) || ecma_is_value_null (value)) { return ecma_raise_type_error (ECMA_ERR_MSG ("")); } else { JERRY_ASSERT (ecma_is_value_boolean (value)); return ecma_op_create_boolean_object (value); } } } /* ecma_op_to_object */
/** * The Date.prototype object's 'setUTCSeconds' routine * * See also: * ECMA-262 v5, 15.9.5.31 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_date_prototype_set_utc_seconds (ecma_value_t this_arg, /**< this argument */ ecma_value_t sec, /**< second */ ecma_value_t ms) /**< millisecond */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 1. */ ECMA_TRY_CATCH (this_time_value, ecma_builtin_date_prototype_get_time (this_arg), ret_value); ecma_number_t t = *ecma_get_number_from_value (this_time_value); /* 2. */ ECMA_OP_TO_NUMBER_TRY_CATCH (s, sec, ret_value); /* 3. */ ECMA_OP_TO_NUMBER_TRY_CATCH (milli, ms, ret_value); if (ecma_is_value_undefined (ms)) { milli = ecma_date_ms_from_time (t); } /* 4-7. */ ecma_number_t hour = ecma_date_hour_from_time (t); ecma_number_t min = ecma_date_min_from_time (t); ret_value = ecma_date_set_internal_property (this_arg, ecma_date_day (t), ecma_date_make_time (hour, min, s, milli), ECMA_DATE_UTC); ECMA_OP_TO_NUMBER_FINALIZE (milli); ECMA_OP_TO_NUMBER_FINALIZE (s); ECMA_FINALIZE (this_time_value); return ret_value; } /* ecma_builtin_date_prototype_set_utc_seconds */
/** * Relation opcode handler. * * See also: ECMA-262 v5, 11.8.1, 11.8.2, 11.8.3, 11.8.4 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t opfunc_relation (ecma_value_t left_value, /**< left value */ ecma_value_t right_value, /**< right value */ bool left_first, /**< 'LeftFirst' flag */ bool is_invert) /**< is invert */ { JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); ecma_value_t ret_value = ecma_op_abstract_relational_compare (left_value, right_value, left_first); if (ECMA_IS_VALUE_ERROR (ret_value)) { return ret_value; } if (ecma_is_value_undefined (ret_value)) { ret_value = ECMA_VALUE_FALSE; } else { JERRY_ASSERT (ecma_is_value_boolean (ret_value)); if (is_invert) { ret_value = ecma_invert_boolean_value (ret_value); } } return ret_value; } /* opfunc_relation */
/** * The Date.prototype object's 'setUTCMonth' routine * * See also: * ECMA-262 v5, 15.9.5.39 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_date_prototype_set_utc_month (ecma_value_t this_arg, /**< this argument */ ecma_value_t month, /**< month */ ecma_value_t date) /**< date */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 1. */ ECMA_TRY_CATCH (this_time_value, ecma_builtin_date_prototype_get_time (this_arg), ret_value); ecma_number_t t = *ecma_get_number_from_value (this_time_value); /* 2. */ ECMA_OP_TO_NUMBER_TRY_CATCH (m, month, ret_value); /* 3. */ ECMA_OP_TO_NUMBER_TRY_CATCH (dt, date, ret_value); if (ecma_is_value_undefined (date)) { dt = ecma_date_date_from_time (t); } /* 4-7. */ ecma_number_t year = ecma_date_year_from_time (t); ret_value = ecma_date_set_internal_property (this_arg, ecma_date_make_day (year, m, dt), ecma_date_time_within_day (t), ECMA_DATE_UTC); ECMA_OP_TO_NUMBER_FINALIZE (dt); ECMA_OP_TO_NUMBER_FINALIZE (m); ECMA_FINALIZE (this_time_value); return ret_value; } /* ecma_builtin_date_prototype_set_utc_month */
/** * 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 */
/** * 'Greater-than' opcode handler. * * See also: ECMA-262 v5, 11.8.2 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t opfunc_greater_than (ecma_value_t left_value, /**< left value */ ecma_value_t right_value) /**< right value */ { JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); ecma_value_t ret_value = ecma_op_abstract_relational_compare (left_value, right_value, false); if (ECMA_IS_VALUE_ERROR (ret_value)) { return ret_value; } if (ecma_is_value_undefined (ret_value)) { ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE); } else { JERRY_ASSERT (ecma_is_value_boolean (ret_value)); } return ret_value; } /* opfunc_greater_than */
/** * ToObject operation. * * See also: * ECMA-262 v5, 9.9 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_to_object (ecma_value_t value) /**< ecma-value */ { ecma_check_value_type_is_spec_defined (value); if (ecma_is_value_number (value)) { return ecma_op_create_number_object (value); } else if (ecma_is_value_string (value)) { return ecma_op_create_string_object (&value, 1); } else if (ecma_is_value_object (value)) { return ecma_make_normal_completion_value (ecma_copy_value (value, true)); } else { if (ecma_is_value_undefined (value) || ecma_is_value_null (value)) { return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } else { JERRY_ASSERT (ecma_is_value_boolean (value)); return ecma_op_create_boolean_object (value); } } } /* ecma_op_to_object */
/** * Handle calling [[Call]] of built-in SyntaxError object * * @return ecma value */ ecma_value_t ecma_builtin_syntax_error_dispatch_call (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_is_value_undefined (arguments_list_p[0])) { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ECMA_TRY_CATCH (msg_str_value, ecma_op_to_string (arguments_list_p[0]), ret_value); ecma_string_t *message_string_p = ecma_get_string_from_value (msg_str_value); ecma_object_t *new_error_object_p = ecma_new_standard_error_with_message (ECMA_ERROR_SYNTAX, message_string_p); ret_value = ecma_make_object_value (new_error_object_p); ECMA_FINALIZE (msg_str_value); return ret_value; } else { ecma_object_t *new_error_object_p = ecma_new_standard_error (ECMA_ERROR_SYNTAX); return ecma_make_object_value (new_error_object_p); } } /* ecma_builtin_syntax_error_dispatch_call */
/** * Handle calling [[Call]] of a built-in error object * * @return ecma value */ ecma_value_t ecma_builtin_helper_error_dispatch_call (ecma_standard_error_t error_type, /**< native error type */ 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_is_value_undefined (arguments_list_p[0])) { ecma_value_t ret_value = ECMA_VALUE_EMPTY; ECMA_TRY_CATCH (msg_str_value, ecma_op_to_string (arguments_list_p[0]), ret_value); ecma_string_t *message_string_p = ecma_get_string_from_value (msg_str_value); ecma_object_t *new_error_object_p = ecma_new_standard_error_with_message (error_type, message_string_p); ret_value = ecma_make_object_value (new_error_object_p); ECMA_FINALIZE (msg_str_value); return ret_value; } else { ecma_object_t *new_error_object_p = ecma_new_standard_error (error_type); return ecma_make_object_value (new_error_object_p); } } /* ecma_builtin_helper_error_dispatch_call */
/** * ToString operation. * * See also: * ECMA-262 v5, 9.8 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_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_completion_value_t ret_value = ecma_make_empty_completion_value (); 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_number (value)) { ecma_number_t *num_p = ecma_get_number_from_value (value); res_p = ecma_new_ecma_string_from_number (*num_p); } 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_normal_completion_value (ecma_make_string_value (res_p)); } } /* ecma_op_to_string */
/** * Debug assertion that specified value's type is one of ECMA-defined * script-visible types, i.e.: undefined, null, boolean, number, string, object. */ void ecma_check_value_type_is_spec_defined (ecma_value_t value) /**< ecma value */ { JERRY_ASSERT (ecma_is_value_undefined (value) || ecma_is_value_null (value) || ecma_is_value_boolean (value) || ecma_is_value_number (value) || ecma_is_value_string (value) || ecma_is_value_object (value)); } /* ecma_check_value_type_is_spec_defined */
/** * Run global code */ jerry_completion_code_t vm_run_global (void) { JERRY_ASSERT (__program != NULL); JERRY_ASSERT (vm_top_context_p == NULL); #ifdef MEM_STATS interp_mem_stats_print_legend (); #endif /* MEM_STATS */ bool is_strict = false; vm_instr_counter_t start_pos = 0; opcode_scope_code_flags_t scope_flags = vm_get_scope_flags (__program, start_pos++); if (scope_flags & OPCODE_SCOPE_CODE_FLAGS_STRICT) { is_strict = true; } ecma_object_t *glob_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_GLOBAL); ecma_object_t *lex_env_p = ecma_get_global_environment (); ecma_completion_value_t completion = vm_run_from_pos (__program, start_pos, ecma_make_object_value (glob_obj_p), lex_env_p, is_strict, false); jerry_completion_code_t ret_code; if (ecma_is_completion_value_return (completion)) { JERRY_ASSERT (ecma_is_value_undefined (ecma_get_completion_value_value (completion))); ret_code = JERRY_COMPLETION_CODE_OK; } else { JERRY_ASSERT (ecma_is_completion_value_throw (completion)); ret_code = JERRY_COMPLETION_CODE_UNHANDLED_EXCEPTION; } ecma_free_completion_value (completion); ecma_deref_object (glob_obj_p); ecma_deref_object (lex_env_p); JERRY_ASSERT (vm_top_context_p == NULL); return ret_code; } /* vm_run_global */
/** * ToBoolean operation. * * See also: * ECMA-262 v5, 9.2 * * @return completion value * Returned value is simple and so need not be freed. * However, ecma_free_completion_value may be called for it, but it is a no-op. */ ecma_completion_value_t ecma_op_to_boolean (ecma_value_t value) /**< ecma-value */ { ecma_check_value_type_is_spec_defined (value); ecma_simple_value_t ret_value; if (ecma_is_value_boolean (value)) { ret_value = (ecma_is_value_true (value) ? ECMA_SIMPLE_VALUE_TRUE : ECMA_SIMPLE_VALUE_FALSE); } else if (ecma_is_value_undefined (value) || ecma_is_value_null (value)) { ret_value = ECMA_SIMPLE_VALUE_FALSE; } else if (ecma_is_value_number (value)) { ecma_number_t *num_p = ecma_get_number_from_value (value); if (ecma_number_is_nan (*num_p) || ecma_number_is_zero (*num_p)) { ret_value = ECMA_SIMPLE_VALUE_FALSE; } else { ret_value = ECMA_SIMPLE_VALUE_TRUE; } } else if (ecma_is_value_string (value)) { ecma_string_t *str_p = ecma_get_string_from_value (value); if (ecma_string_get_length (str_p) == 0) { ret_value = ECMA_SIMPLE_VALUE_FALSE; } else { ret_value = ECMA_SIMPLE_VALUE_TRUE; } } else { JERRY_ASSERT (ecma_is_value_object (value)); ret_value = ECMA_SIMPLE_VALUE_TRUE; } return ecma_make_simple_completion_value (ret_value); } /* ecma_op_to_boolean */
/** * CheckObjectCoercible operation. * * See also: * ECMA-262 v5, 9.10 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_check_object_coercible (ecma_value_t value) /**< ecma-value */ { ecma_check_value_type_is_spec_defined (value); if (ecma_is_value_undefined (value) || ecma_is_value_null (value)) { return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } else { return ecma_make_empty_completion_value (); } } /* ecma_op_check_object_coercible */
/** * CheckObjectCoercible operation. * * See also: * ECMA-262 v5, 9.10 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_check_object_coercible (ecma_value_t value) /**< ecma value */ { ecma_check_value_type_is_spec_defined (value); if (ecma_is_value_undefined (value) || ecma_is_value_null (value)) { return ecma_raise_type_error (ECMA_ERR_MSG ("")); } else { return ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); } } /* ecma_op_check_object_coercible */
/** * 'Greater-than-or-equal' opcode handler. * * See also: ECMA-262 v5, 11.8.4 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t opfunc_greater_or_equal_than (vm_instr_t instr, /**< instruction */ vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */ { const idx_t dst_var_idx = instr.data.greater_or_equal_than.dst; const idx_t left_var_idx = instr.data.greater_or_equal_than.var_left; const idx_t right_var_idx = instr.data.greater_or_equal_than.var_right; //ilyushin printf("greater_or_equal_than,"); //ilyushin ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); ECMA_TRY_CATCH (left_value, get_variable_value (frame_ctx_p, left_var_idx, false), ret_value); ECMA_TRY_CATCH (right_value, get_variable_value (frame_ctx_p, right_var_idx, false), ret_value); ECMA_TRY_CATCH (compare_result, ecma_op_abstract_relational_compare (left_value, right_value, true), ret_value); ecma_simple_value_t res; if (ecma_is_value_undefined (compare_result)) { res = ECMA_SIMPLE_VALUE_FALSE; } else { JERRY_ASSERT (ecma_is_value_boolean (compare_result)); if (ecma_is_value_true (compare_result)) { res = ECMA_SIMPLE_VALUE_FALSE; } else { res = ECMA_SIMPLE_VALUE_TRUE; } } ret_value = set_variable_value (frame_ctx_p, frame_ctx_p->pos, dst_var_idx, ecma_make_simple_value (res)); ECMA_FINALIZE (compare_result); ECMA_FINALIZE (right_value); ECMA_FINALIZE (left_value); frame_ctx_p->pos++; return ret_value; } /* opfunc_greater_or_equal_than */
/** * The Object object's 'create' routine * * See also: * ECMA-262 v5, 15.2.3.5 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_object_object_create (ecma_value_t this_arg, /**< 'this' argument */ ecma_value_t arg1, /**< routine's first argument */ ecma_value_t arg2) /**< routine's second argument */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); // 1. if (!ecma_is_value_object (arg1) && !ecma_is_value_null (arg1)) { ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } else { ecma_object_t *obj_p = NULL; if (!ecma_is_value_null (arg1)) { obj_p = ecma_get_object_from_value (arg1); } // 2-3. ecma_object_t *result_obj_p = ecma_op_create_object_object_noarg_and_set_prototype (obj_p); // 4. if (!ecma_is_value_undefined (arg2)) { ECMA_TRY_CATCH (obj, ecma_builtin_object_object_define_properties (this_arg, ecma_make_object_value (result_obj_p), arg2), ret_value); ECMA_FINALIZE (obj); } // 5. if (ecma_is_completion_value_empty (ret_value)) { ret_value = ecma_make_normal_completion_value (ecma_copy_value (ecma_make_object_value (result_obj_p), true)); } ecma_deref_object (result_obj_p); } return ret_value; } /* ecma_builtin_object_object_create */
/** * 'Greater-than-or-equal' opcode handler. * * See also: ECMA-262 v5, 11.8.4 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t opfunc_greater_or_equal_than (opcode_t opdata, /**< operation data */ int_data_t *int_data) /**< interpreter context */ { const idx_t dst_var_idx = opdata.data.greater_or_equal_than.dst; const idx_t left_var_idx = opdata.data.greater_or_equal_than.var_left; const idx_t right_var_idx = opdata.data.greater_or_equal_than.var_right; ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value); ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value); ECMA_TRY_CATCH (compare_result, ecma_op_abstract_relational_compare (left_value, right_value, true), ret_value); ecma_simple_value_t res; if (ecma_is_value_undefined (compare_result)) { res = ECMA_SIMPLE_VALUE_FALSE; } else { JERRY_ASSERT (ecma_is_value_boolean (compare_result)); if (ecma_is_value_true (compare_result)) { res = ECMA_SIMPLE_VALUE_FALSE; } else { res = ECMA_SIMPLE_VALUE_TRUE; } } ret_value = set_variable_value (int_data, int_data->pos, dst_var_idx, ecma_make_simple_value (res)); ECMA_FINALIZE (compare_result); ECMA_FINALIZE (right_value); ECMA_FINALIZE (left_value); int_data->pos++; return ret_value; } /* opfunc_greater_or_equal_than */
/** * 'typeof' opcode handler. * * See also: ECMA-262 v5, 11.4.3 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t opfunc_typeof (ecma_value_t left_value) /**< left value */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ecma_string_t *type_str_p = NULL; if (ecma_is_value_undefined (left_value)) { type_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_UNDEFINED); } else if (ecma_is_value_null (left_value)) { type_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_OBJECT); } else if (ecma_is_value_boolean (left_value)) { type_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_BOOLEAN); } else if (ecma_is_value_number (left_value)) { type_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_NUMBER); } else if (ecma_is_value_string (left_value)) { type_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_STRING); } else { JERRY_ASSERT (ecma_is_value_object (left_value)); if (ecma_op_is_callable (left_value)) { type_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_FUNCTION); } else { type_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_OBJECT); } } ret_value = ecma_make_string_value (type_str_p); return ret_value; } /* opfunc_typeof */
/** * Deletes an object property. * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t vm_op_delete_prop (ecma_value_t object, /**< base object */ ecma_value_t property, /**< property name */ bool is_strict) /**< strict mode */ { ecma_value_t completion_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); if (ecma_is_value_undefined (object)) { completion_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } else { completion_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ECMA_TRY_CATCH (check_coercible_ret, ecma_op_check_object_coercible (object), completion_value); ECMA_TRY_CATCH (str_name_value, ecma_op_to_string (property), completion_value); JERRY_ASSERT (ecma_is_value_string (str_name_value)); ecma_string_t *name_string_p = ecma_get_string_from_value (str_name_value); ECMA_TRY_CATCH (obj_value, ecma_op_to_object (object), completion_value); JERRY_ASSERT (ecma_is_value_object (obj_value)); ecma_object_t *obj_p = ecma_get_object_from_value (obj_value); JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); ECMA_TRY_CATCH (delete_op_ret_val, ecma_op_object_delete (obj_p, name_string_p, is_strict), completion_value); completion_value = delete_op_ret_val; ECMA_FINALIZE (delete_op_ret_val); ECMA_FINALIZE (obj_value); ECMA_FINALIZE (str_name_value); ECMA_FINALIZE (check_coercible_ret); } return completion_value; } /* vm_op_delete_prop */
/** * Deletes a variable. * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t vm_op_delete_var (lit_cpointer_t name_literal, /**< name literal */ ecma_object_t *lex_env_p, /**< lexical environment */ bool is_strict) /**< strict mode */ { ecma_value_t completion_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ecma_string_t *var_name_str_p; var_name_str_p = ecma_new_ecma_string_from_lit_cp (name_literal); ecma_reference_t ref = ecma_op_get_identifier_reference (lex_env_p, var_name_str_p, is_strict); JERRY_ASSERT (!ref.is_strict); if (ecma_is_value_undefined (ref.base)) { completion_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } else { ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (lex_env_p, var_name_str_p); JERRY_ASSERT (ecma_is_lexical_environment (ref_base_lex_env_p)); ECMA_TRY_CATCH (delete_op_ret_val, ecma_op_delete_binding (ref_base_lex_env_p, ECMA_GET_NON_NULL_POINTER (ecma_string_t, ref.referenced_name_cp)), completion_value); completion_value = delete_op_ret_val; ECMA_FINALIZE (delete_op_ret_val); } ecma_free_reference (ref); ecma_deref_ecma_string (var_name_str_p); return completion_value; } /* vm_op_delete_var */
/** * CreateImmutableBinding operation. * * See also: ECMA-262 v5, 10.2.1 */ void ecma_op_create_immutable_binding (ecma_object_t *lex_env_p, /**< lexical environment */ ecma_string_t *name_p) /**< argument N */ { JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); /* * Warning: * Whether immutable bindings are deletable seems not to be defined by ECMA v5. */ ecma_property_t *prop_p = ecma_create_named_data_property (lex_env_p, name_p, false, false, false); JERRY_ASSERT (ecma_is_value_undefined (ecma_get_named_data_property_value (prop_p))); ecma_set_named_data_property_value (prop_p, ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY)); } /* ecma_op_create_immutable_binding */
/** * Handle calling [[Call]] of built-in Object object * * @return completion-value */ ecma_completion_value_t ecma_builtin_object_dispatch_call (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); ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); if (arguments_list_len == 0 || ecma_is_value_undefined (arguments_list_p[0]) || ecma_is_value_null (arguments_list_p[0])) { ret_value = ecma_builtin_object_dispatch_construct (arguments_list_p, arguments_list_len); } else { ret_value = ecma_op_to_object (arguments_list_p[0]); } return ret_value; } /* ecma_builtin_object_dispatch_call */
/** * 'Variable declaration' opcode handler. * * See also: ECMA-262 v5, 10.5 - Declaration binding instantiation (block 8). * * @return ecma value * Returned value is simple and so need not be freed. * However, ecma_free_value may be called for it, but it is a no-op. */ ecma_value_t vm_var_decl (vm_frame_ctx_t *frame_ctx_p, /**< interpreter context */ ecma_string_t *var_name_str_p) /**< variable name */ { if (!ecma_op_has_binding (frame_ctx_p->lex_env_p, var_name_str_p)) { const bool is_configurable_bindings = frame_ctx_p->is_eval_code; ecma_value_t completion_value = ecma_op_create_mutable_binding (frame_ctx_p->lex_env_p, var_name_str_p, is_configurable_bindings); JERRY_ASSERT (ecma_is_value_empty (completion_value)); /* Skipping SetMutableBinding as we have already checked that there were not * any binding with specified name in current lexical environment * and CreateMutableBinding sets the created binding's value to undefined */ JERRY_ASSERT (ecma_is_value_undefined (ecma_op_get_binding_value (frame_ctx_p->lex_env_p, var_name_str_p, true))); } return ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); } /* vm_var_decl */
/** * 'for-in' opcode handler * * See also: * ECMA-262 v5, 12.6.4 * * @return completion value * Returned value must be freed with ecma_free_value */ ecma_collection_header_t * opfunc_for_in (ecma_value_t left_value, /**< left value */ ecma_value_t *result_obj_p) /**< expression object */ { ecma_value_t compl_val = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ecma_collection_header_t *prop_names_p = NULL; /* 3. */ if (!ecma_is_value_undefined (left_value) && !ecma_is_value_null (left_value)) { /* 4. */ ECMA_TRY_CATCH (obj_expr_value, ecma_op_to_object (left_value), compl_val); ecma_object_t *obj_p = ecma_get_object_from_value (obj_expr_value); prop_names_p = ecma_op_object_get_property_names (obj_p, false, true, true); if (prop_names_p->unit_number != 0) { ecma_ref_object (obj_p); *result_obj_p = ecma_make_object_value (obj_p); } else { ecma_dealloc_collection_header (prop_names_p); prop_names_p = NULL; } ECMA_FINALIZE (obj_expr_value); } JERRY_ASSERT (ecma_is_value_empty (compl_val)); return prop_names_p; } /* opfunc_for_in */
/** * ToBoolean operation. Cannot throw an exception. * * See also: * ECMA-262 v5, 9.2 * * @return true if the logical value is true * false otherwise */ bool ecma_op_to_boolean (ecma_value_t value) /**< ecma value */ { ecma_check_value_type_is_spec_defined (value); if (ecma_is_value_simple (value)) { JERRY_ASSERT (ecma_is_value_boolean (value) || ecma_is_value_undefined (value) || ecma_is_value_null (value)); return ecma_is_value_true (value); } if (ecma_is_value_integer_number (value)) { return (value != ecma_make_integer_value (0)); } if (ecma_is_value_float_number (value)) { ecma_number_t num = ecma_get_float_from_value (value); return (!ecma_number_is_nan (num) && !ecma_number_is_zero (num)); } if (ecma_is_value_string (value)) { ecma_string_t *str_p = ecma_get_string_from_value (value); return ecma_string_get_length (str_p) != 0; } JERRY_ASSERT (ecma_is_value_object (value)); return true; } /* ecma_op_to_boolean */
/** * '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 */
ecma_completion_value_t ecma_builtin_helper_object_to_string (const ecma_value_t this_arg) /**< this argument */ { lit_magic_string_id_t type_string; if (ecma_is_value_undefined (this_arg)) { type_string = LIT_MAGIC_STRING_UNDEFINED_UL; } else if (ecma_is_value_null (this_arg)) { type_string = LIT_MAGIC_STRING_NULL_UL; } else { ecma_completion_value_t obj_this = ecma_op_to_object (this_arg); if (!ecma_is_completion_value_normal (obj_this)) { return obj_this; } JERRY_ASSERT (ecma_is_value_object (ecma_get_completion_value_value (obj_this))); ecma_object_t *obj_p = ecma_get_object_from_completion_value (obj_this); type_string = ecma_object_get_class_name (obj_p); ecma_free_completion_value (obj_this); } ecma_string_t *ret_string_p; /* Building string "[object #type#]" where type is 'Undefined', 'Null' or one of possible object's classes. The string with null character is maximum 19 characters long. */ const ssize_t buffer_size = 19; MEM_DEFINE_LOCAL_ARRAY (str_buffer, buffer_size, lit_utf8_byte_t); lit_utf8_byte_t *buffer_ptr = str_buffer; ssize_t buffer_size_left = buffer_size; const lit_magic_string_id_t magic_string_ids[] = { LIT_MAGIC_STRING_LEFT_SQUARE_CHAR, LIT_MAGIC_STRING_OBJECT, LIT_MAGIC_STRING_SPACE_CHAR, type_string, LIT_MAGIC_STRING_RIGHT_SQUARE_CHAR }; for (uint32_t i = 0; i < sizeof (magic_string_ids) / sizeof (lit_magic_string_id_t); ++i) { buffer_ptr = lit_copy_magic_string_to_buffer (magic_string_ids[i], buffer_ptr, buffer_size_left); buffer_size_left = buffer_size - (buffer_ptr - str_buffer); } JERRY_ASSERT (buffer_size_left >= 0); ret_string_p = ecma_new_ecma_string_from_utf8 (str_buffer, (lit_utf8_size_t) (buffer_size - buffer_size_left)); MEM_FINALIZE_LOCAL_ARRAY (str_buffer); return ecma_make_normal_completion_value (ecma_make_string_value (ret_string_p)); } /* ecma_builtin_helper_object_to_string */
/** * 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 */