Implementing Array construction routine; adding unit test on array operations.

This commit is contained in:
Ruben Ayrapetyan
2014-09-03 17:30:03 +04:00
parent 76de0e9a06
commit 50371ddf20
7 changed files with 330 additions and 20 deletions
+1 -1
View File
@@ -42,7 +42,7 @@ fill_varg_list (int_data_t *int_data, /**< interpreter context */
{
ecma_completion_value_t evaluate_arg_completion = run_int_loop (int_data);
if (ecma_is_completion_value_meta (evaluate_arg_completion))
if (ecma_is_completion_value_normal (evaluate_arg_completion))
{
opcode_t next_opcode = read_opcode (int_data->pos);
JERRY_ASSERT (next_opcode.op_idx == __op__idx_meta);
+13 -7
View File
@@ -902,15 +902,17 @@ opfunc_array_decl (opcode_t opdata, /**< operation data */
{
JERRY_ASSERT (args_read == args_number);
ecma_object_t *array_obj_p = ecma_op_create_array_object (arg_values,
args_number,
false);
ECMA_TRY_CATCH (array_obj_value,
ecma_op_create_array_object (arg_values,
args_number,
false),
ret_value);
ret_value = set_variable_value (int_data,
lhs_var_idx,
ecma_make_object_value (array_obj_p));
array_obj_value.u.value);
ecma_deref_object (array_obj_p);
ECMA_FINALIZE (array_obj_value);
}
else
{
@@ -957,8 +959,10 @@ opfunc_obj_decl (opcode_t opdata, /**< operation data */
{
ecma_completion_value_t evaluate_prop_completion = run_int_loop (int_data);
if (ecma_is_completion_value_meta (evaluate_prop_completion))
if (ecma_is_completion_value_normal (evaluate_prop_completion))
{
JERRY_ASSERT (ecma_is_completion_value_empty (evaluate_prop_completion));
opcode_t next_opcode = read_opcode (int_data->pos);
JERRY_ASSERT (next_opcode.op_idx == __op__idx_meta);
@@ -1423,8 +1427,10 @@ opfunc_with (opcode_t opdata, /**< operation data */
ecma_completion_value_t evaluation_completion = run_int_loop (int_data);
if (ecma_is_completion_value_meta (evaluation_completion))
if (ecma_is_completion_value_normal (evaluation_completion))
{
JERRY_ASSERT (ecma_is_completion_value_empty (evaluation_completion));
opcode_t meta_opcode = read_opcode (int_data->pos);
JERRY_ASSERT (meta_opcode.op_idx == __op__idx_meta);
JERRY_ASSERT (meta_opcode.data.meta.type == OPCODE_META_TYPE_END_WITH);
+104 -10
View File
@@ -55,9 +55,10 @@ ecma_reject (bool is_throw) /**< Throw flag */
* See also: ECMA-262 v5, 15.4.2.1
* ECMA-262 v5, 15.4.2.2
*
* @return pointer to newly created Array object
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_object_t*
ecma_completion_value_t
ecma_op_create_array_object (ecma_value_t *arguments_list_p, /**< list of arguments that
are passed to Array constructor */
ecma_length_t arguments_list_len, /**< length of the arguments' list */
@@ -71,7 +72,83 @@ ecma_op_create_array_object (ecma_value_t *arguments_list_p, /**< list of argume
JERRY_ASSERT (arguments_list_len == 0
|| arguments_list_p != NULL);
JERRY_UNIMPLEMENTED_REF_UNUSED_VARS (arguments_list_p, arguments_list_len, is_treat_single_arg_as_length);
uint32_t length;
ecma_value_t *array_items_p;
ecma_length_t array_items_count;
if (is_treat_single_arg_as_length
&& arguments_list_len == 1
&& arguments_list_p[0].value_type == ECMA_TYPE_NUMBER)
{
ecma_number_t *num_p = ECMA_GET_POINTER (arguments_list_p[0].value);
uint32_t num_uint32 = ecma_number_to_uint32 (*num_p);
if (*num_p != ecma_uint32_to_number (num_uint32))
{
return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_RANGE));
}
else
{
length = num_uint32;
array_items_p = NULL;
array_items_count = 0;
}
}
else
{
length = arguments_list_len;
array_items_p = arguments_list_p;
array_items_count = arguments_list_len;
}
FIXME (/* Set prototype to built-in Array prototype (15.4.3.1) */);
ecma_object_t *obj_p = ecma_create_object (NULL, true, ECMA_OBJECT_TYPE_ARRAY);
ecma_property_t *class_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_CLASS);
class_prop_p->u.internal_property.value = ECMA_OBJECT_CLASS_ARRAY;
ecma_string_t *length_magic_string_p = ecma_get_magic_string (ECMA_MAGIC_STRING_LENGTH);
ecma_number_t *length_num_p = ecma_alloc_number ();
*length_num_p = ecma_uint32_to_number (length);
ecma_property_t *length_prop_p = ecma_create_named_data_property (obj_p,
length_magic_string_p,
true,
false,
false);
length_prop_p->u.named_data_property.value = ecma_make_number_value (length_num_p);
ecma_deref_ecma_string (length_magic_string_p);
for (uint32_t index = 0;
index < array_items_count;
index++)
{
ecma_string_t* item_name_string_p = ecma_new_ecma_string_from_uint32 (index);
ecma_property_descriptor_t item_prop_desc = ecma_make_empty_property_descriptor ();
{
item_prop_desc.is_value_defined = true;
item_prop_desc.value = array_items_p [index];
item_prop_desc.is_writable_defined = true;
item_prop_desc.writable = ECMA_PROPERTY_WRITABLE;
item_prop_desc.is_enumerable_defined = true;
item_prop_desc.enumerable = ECMA_PROPERTY_ENUMERABLE;
item_prop_desc.is_configurable_defined = true;
item_prop_desc.configurable = ECMA_PROPERTY_CONFIGURABLE;
}
ecma_op_object_define_own_property (obj_p,
item_name_string_p,
item_prop_desc,
false);
ecma_deref_ecma_string (item_name_string_p);
}
return ecma_make_normal_completion_value (ecma_make_object_value (obj_p));
} /* ecma_op_create_array_object */
/**
@@ -177,8 +254,8 @@ ecma_op_array_object_define_own_property (ecma_object_t *obj_p, /**< the array o
uint32_t old_len_uint32 = ecma_number_to_uint32 (*num_p);
// 3.
bool is_property_name_equal_length = (ecma_compare_ecma_strings (property_name_p,
magic_string_length_p) == 0);
bool is_property_name_equal_length = ecma_compare_ecma_strings (property_name_p,
magic_string_length_p);
ecma_deref_ecma_string (magic_string_length_p);
@@ -332,13 +409,30 @@ ecma_op_array_object_define_own_property (ecma_object_t *obj_p, /**< the array o
else
{
// 4.a.
ecma_number_t number = ecma_string_to_number (property_name_p);
uint32_t index = ecma_number_to_uint32 (number);
uint32_t index;
bool is_index;
TODO (Check if array index recognition is done according to ECMA);
if (property_name_p->container == ECMA_STRING_CONTAINER_UINT32_IN_DESC)
{
index = property_name_p->u.uint32_number;
is_index = true;
}
else
{
ecma_number_t number = ecma_string_to_number (property_name_p);
index = ecma_number_to_uint32 (number);
if (index >= ECMA_MAX_VALUE_OF_VALID_ARRAY_INDEX
|| ecma_uint32_to_number (index) != number)
ecma_string_t *to_uint32_to_string_p = ecma_new_ecma_string_from_uint32 (index);
is_index = ecma_compare_ecma_strings (property_name_p,
to_uint32_to_string_p);
ecma_deref_ecma_string (to_uint32_to_string_p);
}
is_index = is_index && (index != ECMA_MAX_VALUE_OF_VALID_ARRAY_INDEX);
if (!is_index)
{
// 5.
return ecma_op_general_object_define_own_property (obj_p,
+1 -1
View File
@@ -25,7 +25,7 @@
* @{
*/
extern ecma_object_t*
extern ecma_completion_value_t
ecma_op_create_array_object (ecma_value_t *arguments_list_p,
ecma_length_t arguments_list_len,
bool is_treat_single_arg_as_length);
+14 -1
View File
@@ -183,7 +183,20 @@ ecma_op_put_value (ecma_reference_t ref, /**< ECMA-reference */
JERRY_ASSERT (obj_p != NULL
&& !ecma_is_lexical_environment (obj_p));
return ecma_op_object_put (obj_p, ref.referenced_name_p, value, ref.is_strict);
ecma_completion_value_t ret_value;
ECMA_TRY_CATCH (put_completion,
ecma_op_object_put (obj_p,
ref.referenced_name_p,
value,
ref.is_strict),
ret_value);
ret_value = ecma_make_empty_completion_value ();
ECMA_FINALIZE (put_completion);
return ret_value;
}
else
{
+5
View File
@@ -15,6 +15,7 @@
#include "ecma-exceptions.h"
#include "ecma-globals.h"
#include "ecma-array-object.h"
#include "ecma-function-object.h"
#include "ecma-objects-arguments.h"
#include "ecma-objects-general.h"
@@ -402,6 +403,10 @@ ecma_op_object_define_own_property (ecma_object_t *obj_p, /**< the object */
}
case ECMA_OBJECT_TYPE_ARRAY:
{
return ecma_op_array_object_define_own_property (obj_p, property_name_p, property_desc, is_throw);
}
case ECMA_OBJECT_TYPE_HOST:
{
JERRY_UNIMPLEMENTED();
+192
View File
@@ -0,0 +1,192 @@
/* Copyright 2014 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "globals.h"
#include "interpreter.h"
#include "mem-allocator.h"
#include "opcodes.h"
#include "serializer.h"
/**
* Unit test's main function.
*/
int
main( int __unused argc,
char __unused **argv)
{
const opcode_t test_program[] = {
[ 0] = getop_reg_var_decl (240, 255),
[ 1] = getop_jmp_down (2),
[ 2] = getop_exitval (1),
/* var a, b; */
[ 3] = getop_var_decl (0),
[ 4] = getop_var_decl (1),
/* b = null; */
[ 5] = getop_assignment (1, OPCODE_ARG_TYPE_SIMPLE, ECMA_SIMPLE_VALUE_NULL),
/* a = [12, 'length', b]; */
[ 6] = getop_array_decl (0, 3),
[ 7] = getop_assignment (240, OPCODE_ARG_TYPE_SMALLINT, 12),
[ 8] = getop_meta (OPCODE_META_TYPE_VARG, 240, 255),
[ 9] = getop_assignment (240, OPCODE_ARG_TYPE_STRING, 2),
[10] = getop_meta (OPCODE_META_TYPE_VARG, 240, 255),
[11] = getop_assignment (240, OPCODE_ARG_TYPE_VARIABLE, 1),
[12] = getop_meta (OPCODE_META_TYPE_VARG, 240, 255),
/* assert (a.length === 3); */
[13] = getop_assignment (240, OPCODE_ARG_TYPE_STRING, 2),
[14] = getop_prop_getter (240, 0, 240),
[15] = getop_assignment (241, OPCODE_ARG_TYPE_SMALLINT, 3),
[16] = getop_equal_value_type (240, 240, 241),
[17] = getop_is_false_jmp (240, 2),
/* assert (a[0] === 12.0); */
[18] = getop_assignment (240, OPCODE_ARG_TYPE_SMALLINT, 0),
[19] = getop_prop_getter (240, 0, 240),
[20] = getop_assignment (241, OPCODE_ARG_TYPE_NUMBER, 5),
[21] = getop_equal_value_type (240, 240, 241),
[22] = getop_is_false_jmp (240, 2),
/* assert (a['1'] === 'length'); */
[23] = getop_assignment (240, OPCODE_ARG_TYPE_STRING, 3),
[24] = getop_prop_getter (240, 0, 240),
[25] = getop_assignment (241, OPCODE_ARG_TYPE_STRING, 2),
[26] = getop_equal_value_type (240, 240, 241),
[27] = getop_is_false_jmp (240, 2),
/* assert (a[2.0] === null); */
[28] = getop_assignment (240, OPCODE_ARG_TYPE_NUMBER, 4),
[29] = getop_prop_getter (240, 0, 240),
[30] = getop_assignment (241, OPCODE_ARG_TYPE_SIMPLE, ECMA_SIMPLE_VALUE_NULL),
[31] = getop_equal_value_type (240, 240, 241),
[32] = getop_is_false_jmp (240, 2),
/* assert (a[2.5] === undefined); */
[33] = getop_assignment (240, OPCODE_ARG_TYPE_NUMBER, 6),
[34] = getop_prop_getter (240, 0, 240),
[35] = getop_assignment (241, OPCODE_ARG_TYPE_SIMPLE, ECMA_SIMPLE_VALUE_UNDEFINED),
[36] = getop_equal_value_type (240, 240, 241),
[37] = getop_is_false_jmp (240, 2),
/* a.length = 1; */
[38] = getop_assignment (240, OPCODE_ARG_TYPE_STRING, 2),
[39] = getop_assignment (241, OPCODE_ARG_TYPE_SMALLINT, 1),
[40] = getop_prop_setter (0, 240, 241),
/* assert (a.length === 1); */
[41] = getop_assignment (240, OPCODE_ARG_TYPE_STRING, 2),
[42] = getop_prop_getter (240, 0, 240),
[43] = getop_assignment (241, OPCODE_ARG_TYPE_SMALLINT, 1),
[44] = getop_equal_value_type (240, 240, 241),
[45] = getop_is_false_jmp (240, 2),
/* assert (a[0] === 12.0); */
[46] = getop_assignment (240, OPCODE_ARG_TYPE_SMALLINT, 0),
[47] = getop_prop_getter (240, 0, 240),
[48] = getop_assignment (241, OPCODE_ARG_TYPE_NUMBER, 5),
[49] = getop_equal_value_type (240, 240, 241),
[50] = getop_is_false_jmp (240, 2),
/* assert (a['1'] === undefined); */
[51] = getop_assignment (240, OPCODE_ARG_TYPE_STRING, 3),
[52] = getop_prop_getter (240, 0, 240),
[53] = getop_assignment (241, OPCODE_ARG_TYPE_SIMPLE, ECMA_SIMPLE_VALUE_UNDEFINED),
[54] = getop_equal_value_type (240, 240, 241),
[55] = getop_is_false_jmp (240, 2),
/* assert (a[2.0] === undefined); */
[56] = getop_assignment (240, OPCODE_ARG_TYPE_NUMBER, 4),
[57] = getop_prop_getter (240, 0, 240),
[58] = getop_equal_value_type (240, 240, 241),
[59] = getop_is_false_jmp (240, 2),
/* a.length = 8; */
[60] = getop_assignment (240, OPCODE_ARG_TYPE_STRING, 2),
[61] = getop_assignment (241, OPCODE_ARG_TYPE_SMALLINT, 8),
[62] = getop_prop_setter (0, 240, 241),
/* assert (a.length === 8); */
[63] = getop_assignment (240, OPCODE_ARG_TYPE_STRING, 2),
[64] = getop_prop_getter (240, 0, 240),
[65] = getop_assignment (241, OPCODE_ARG_TYPE_SMALLINT, 8),
[66] = getop_equal_value_type (240, 240, 241),
[67] = getop_is_false_jmp (240, 2),
/* a[10] = true; */
[68] = getop_assignment (240, OPCODE_ARG_TYPE_SMALLINT, 10),
[69] = getop_assignment (241, OPCODE_ARG_TYPE_SIMPLE, ECMA_SIMPLE_VALUE_TRUE),
[70] = getop_prop_setter (0, 240, 241),
/* assert (a.length === 11); */
[71] = getop_assignment (240, OPCODE_ARG_TYPE_STRING, 2),
[72] = getop_prop_getter (240, 0, 240),
[73] = getop_assignment (241, OPCODE_ARG_TYPE_SMALLINT, 11),
[74] = getop_equal_value_type (240, 240, 241),
[75] = getop_is_false_jmp (240, 2),
/* assert (a[0] === 12.0); */
[76] = getop_assignment (240, OPCODE_ARG_TYPE_SMALLINT, 0),
[77] = getop_prop_getter (240, 0, 240),
[78] = getop_assignment (241, OPCODE_ARG_TYPE_NUMBER, 5),
[79] = getop_equal_value_type (240, 240, 241),
[80] = getop_is_false_jmp (240, 2),
/* assert (a['1'] === undefined); */
[81] = getop_assignment (240, OPCODE_ARG_TYPE_STRING, 3),
[82] = getop_prop_getter (240, 0, 240),
[83] = getop_assignment (241, OPCODE_ARG_TYPE_SIMPLE, ECMA_SIMPLE_VALUE_UNDEFINED),
[84] = getop_equal_value_type (240, 240, 241),
[85] = getop_is_false_jmp (240, 2),
/* assert (a[2.0] === undefined); */
[86] = getop_assignment (240, OPCODE_ARG_TYPE_NUMBER, 4),
[87] = getop_prop_getter (240, 0, 240),
[88] = getop_equal_value_type (240, 240, 241),
[89] = getop_is_false_jmp (240, 2),
/* assert (a[17] === true); */
[90] = getop_assignment (240, OPCODE_ARG_TYPE_SMALLINT, 10),
[91] = getop_prop_getter (240, 0, 240),
[92] = getop_assignment (241, OPCODE_ARG_TYPE_SIMPLE, ECMA_SIMPLE_VALUE_TRUE),
[93] = getop_equal_value_type (240, 240, 241),
[94] = getop_is_false_jmp (240, 2),
[95] = getop_exitval (0),
};
mem_init();
serializer_init (false);
const char *strings[] = { "a",
"b",
"length",
"1" };
ecma_number_t nums [] = { 2.0,
12.0,
2.5 };
uint16_t offset = serializer_dump_strings( strings, 4);
serializer_dump_nums( nums, 3, offset, 4);
init_int( test_program);
bool status = run_int();
serializer_free ();
mem_finalize (false);
return (status ? 0 : 1);
} /* main */