Skip to content

Commit 137c5f3

Browse files
Zsolt Borbélygalpeter
authored andcommitted
Implemented Array.prototype.slice().
JerryScript-DCO-1.0-Signed-off-by: Zsolt Borbély zsborbely.u-szeged@partner.samsung.com
1 parent fc309ca commit 137c5f3

File tree

3 files changed

+228
-0
lines changed

3 files changed

+228
-0
lines changed

jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.cpp

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
*/
1515

1616
#include "ecma-alloc.h"
17+
#include "ecma-array-object.h"
1718
#include "ecma-builtins.h"
1819
#include "ecma-comparison.h"
1920
#include "ecma-conversion.h"
@@ -702,6 +703,162 @@ ecma_builtin_array_prototype_object_unshift (ecma_value_t this_arg, /**< this ar
702703
return ret_value;
703704
} /* ecma_builtin_array_prototype_object_unshift */
704705

706+
/**
707+
* The Array.prototype object's 'slice' routine
708+
*
709+
* See also:
710+
* ECMA-262 v5, 15.4.4.10
711+
*
712+
* @return completion value
713+
* Returned value must be freed with ecma_free_completion_value.
714+
*/
715+
static ecma_completion_value_t
716+
ecma_builtin_array_prototype_object_slice (ecma_value_t this_arg, /**< 'this' argument */
717+
ecma_value_t arg1, /**< start */
718+
ecma_value_t arg2) /**< end */
719+
{
720+
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
721+
722+
/* 1. */
723+
ECMA_TRY_CATCH (obj_this,
724+
ecma_op_to_object (this_arg),
725+
ret_value);
726+
727+
ecma_object_t* obj_p = ecma_get_object_from_value (obj_this);
728+
ecma_string_t* length_magic_string_p = ecma_get_magic_string (ECMA_MAGIC_STRING_LENGTH);
729+
730+
ECMA_TRY_CATCH (len_value,
731+
ecma_op_object_get (obj_p, length_magic_string_p),
732+
ret_value);
733+
734+
/* 3. */
735+
ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, len_value, ret_value);
736+
737+
/* 4. */
738+
const uint32_t len = ecma_number_to_uint32 (len_number);
739+
740+
uint32_t start = 0, end = len;
741+
742+
/* 5. */
743+
ECMA_OP_TO_NUMBER_TRY_CATCH (start_num, arg1, ret_value);
744+
int32_t relative_start = ecma_number_to_int32 (start_num);
745+
746+
/* 6. */
747+
if (relative_start < 0)
748+
{
749+
uint32_t start_abs = (uint32_t) -relative_start;
750+
751+
if (start_abs > len)
752+
{
753+
start = 0;
754+
}
755+
else
756+
{
757+
start = len - start_abs;
758+
}
759+
}
760+
else
761+
{
762+
start = (uint32_t) relative_start;
763+
if (start > len)
764+
{
765+
start = len;
766+
}
767+
}
768+
769+
/* 7. */
770+
if (ecma_is_value_undefined (arg2))
771+
{
772+
end = len;
773+
}
774+
else
775+
{
776+
/* 7. part 2*/
777+
ECMA_OP_TO_NUMBER_TRY_CATCH (end_num, arg2, ret_value)
778+
int32_t relative_end = ecma_number_to_int32 (end_num);
779+
780+
if (relative_end < 0)
781+
{
782+
uint32_t end_abs = (uint32_t) -relative_end;
783+
784+
if (end_abs > len)
785+
{
786+
end = 0;
787+
}
788+
else
789+
{
790+
end = len - end_abs;
791+
}
792+
}
793+
else
794+
{
795+
end = (uint32_t) relative_end;
796+
if (end > len)
797+
{
798+
end = len;
799+
}
800+
}
801+
802+
ECMA_OP_TO_NUMBER_FINALIZE (end_num);
803+
}
804+
805+
ECMA_OP_TO_NUMBER_FINALIZE (start_num);
806+
807+
JERRY_ASSERT (start <= len && end <= len);
808+
809+
ecma_completion_value_t new_array = ecma_op_create_array_object (0, 0, false);
810+
ecma_object_t *new_array_p = ecma_get_object_from_completion_value (new_array);
811+
812+
/* 9. */
813+
uint32_t n = 0;
814+
815+
/* 10. */
816+
for (uint32_t k = start; k < end && ecma_is_completion_value_empty (ret_value); k++, n++)
817+
{
818+
/* 10.a */
819+
ecma_string_t *curr_idx_str_p = ecma_new_ecma_string_from_uint32 (k);
820+
821+
/* 10.c */
822+
if (ecma_op_object_get_property (obj_p, curr_idx_str_p) != NULL)
823+
{
824+
/* 10.c.i */
825+
ECMA_TRY_CATCH (get_value, ecma_op_object_get (obj_p, curr_idx_str_p), ret_value);
826+
827+
ecma_string_t *to_idx_str_p = ecma_new_ecma_string_from_uint32 (n);
828+
/*
829+
* 10.c.ii
830+
* Using [[Put]] is equivalent to using [[DefineOwnProperty]] as specified the standard,
831+
* so we use [[Put]] instead for simplicity. No need for a try-catch block since it is called
832+
* with is_throw = false.
833+
*/
834+
ecma_completion_value_t put_comp_value = ecma_op_object_put (new_array_p, to_idx_str_p, get_value, false);
835+
JERRY_ASSERT (ecma_is_completion_value_normal (put_comp_value));
836+
ecma_free_completion_value (put_comp_value);
837+
ecma_deref_ecma_string (to_idx_str_p);
838+
839+
ECMA_FINALIZE (get_value);
840+
}
841+
842+
ecma_deref_ecma_string (curr_idx_str_p);
843+
}
844+
845+
if (ecma_is_completion_value_empty (ret_value))
846+
{
847+
ret_value = new_array;
848+
}
849+
else
850+
{
851+
ecma_free_completion_value (new_array);
852+
}
853+
854+
ECMA_OP_TO_NUMBER_FINALIZE (len_number);
855+
ECMA_FINALIZE (len_value);
856+
ecma_deref_ecma_string (length_magic_string_p);
857+
ECMA_FINALIZE (obj_this);
858+
859+
return ret_value;
860+
} /* ecma_builtin_array_prototype_object_slice */
861+
705862
/**
706863
* @}
707864
* @}

jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.inc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ ROUTINE (ECMA_MAGIC_STRING_PUSH, ecma_builtin_array_prototype_object_push, NON_F
6565
ROUTINE (ECMA_MAGIC_STRING_INDEX_OF_UL, ecma_builtin_array_prototype_object_index_of, 2, 1)
6666
ROUTINE (ECMA_MAGIC_STRING_SHIFT, ecma_builtin_array_prototype_object_shift, 0, 0)
6767
ROUTINE (ECMA_MAGIC_STRING_UNSHIFT, ecma_builtin_array_prototype_object_unshift, NON_FIXED, 1)
68+
ROUTINE (ECMA_MAGIC_STRING_SLICE, ecma_builtin_array_prototype_object_slice, 2, 2)
6869

6970
#undef OBJECT_ID
7071
#undef SIMPLE_VALUE

tests/jerry/array_prototype_slice.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Copyright 2015 Samsung Electronics Co., Ltd.
2+
// Copyright 2015 University of Szeged.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
var array = [54, undefined, "Lemon", -127];
17+
18+
var array1 = array.slice();
19+
var array2 = array.slice("a", "3");
20+
var array3 = array.slice(-2);
21+
var array4 = array.slice(-12, undefined);
22+
var array5 = array.slice(undefined, -3);
23+
24+
assert (array1.length == 4);
25+
assert (array1[0] == 54);
26+
assert (array1[1] == undefined);
27+
assert (array1[2] == "Lemon");
28+
assert (array1[3] == -127);
29+
30+
assert (array2.length == 3);
31+
assert (array2[0] == 54);
32+
assert (array2[1] == undefined);
33+
assert (array2[2] == "Lemon");
34+
35+
assert (array3.length == 2);
36+
assert (array3[0] == "Lemon");
37+
assert (array3[1] == -127);
38+
39+
assert (array4.length == 4);
40+
assert (array4[0] == 54);
41+
assert (array4[1] == undefined);
42+
assert (array4[2] == "Lemon");
43+
assert (array4[3] == -127);
44+
45+
assert (array5.length == 1);
46+
assert (array5[0] == 54);
47+
48+
// Checking behavior when unable to get length
49+
var obj = { slice : Array.prototype.slice };
50+
Object.defineProperty(obj, 'length', { 'get' : function () { throw new ReferenceError ("foo"); } });
51+
52+
try {
53+
obj.slice(1, 2);
54+
assert (false);
55+
} catch (e) {
56+
assert (e.message === "foo");
57+
assert (e instanceof ReferenceError);
58+
}
59+
60+
// Checking behavior when unable to get element
61+
var obj = { length : 1, slice : Array.prototype.slice };
62+
Object.defineProperty(obj, '0', { 'get' : function () { throw new ReferenceError ("foo"); } });
63+
64+
try {
65+
obj.slice(0, 1);
66+
assert (false);
67+
} catch (e) {
68+
assert (e.message === "foo");
69+
assert (e instanceof ReferenceError);
70+
}

0 commit comments

Comments
 (0)