Skip to content

Commit a80282a

Browse files
dbatyaiszledan
authored andcommitted
Implemented Array.prototype.filter()
JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai dbatyai.u-szeged@partner.samsung.com
1 parent aaeec7f commit a80282a

File tree

3 files changed

+197
-0
lines changed

3 files changed

+197
-0
lines changed

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

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1521,6 +1521,130 @@ ecma_builtin_array_prototype_object_some (ecma_value_t this_arg, /**< this argum
15211521
return ret_value;
15221522
} /* ecma_builtin_array_prototype_object_some */
15231523

1524+
/**
1525+
* The Array.prototype object's 'filter' routine
1526+
*
1527+
* See also:
1528+
* ECMA-262 v5, 15.4.4.20
1529+
*
1530+
* @return completion value
1531+
* Returned value must be freed with ecma_free_completion_value.
1532+
*/
1533+
static ecma_completion_value_t
1534+
ecma_builtin_array_prototype_object_filter (ecma_value_t this_arg, /**< this argument */
1535+
ecma_value_t arg1, /**< callbackfn */
1536+
ecma_value_t arg2) /**< thisArg */
1537+
{
1538+
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
1539+
1540+
/* 1. */
1541+
ECMA_TRY_CATCH (obj_this,
1542+
ecma_op_to_object (this_arg),
1543+
ret_value);
1544+
1545+
ecma_object_t *obj_p = ecma_get_object_from_value (obj_this);
1546+
ecma_string_t *magic_string_length_p = ecma_get_magic_string (ECMA_MAGIC_STRING_LENGTH);
1547+
1548+
/* 2. */
1549+
ECMA_TRY_CATCH (len_value,
1550+
ecma_op_object_get (obj_p, magic_string_length_p),
1551+
ret_value);
1552+
1553+
/* 3. */
1554+
ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, len_value, ret_value);
1555+
1556+
uint32_t len = ecma_number_to_uint32 (len_number);
1557+
1558+
/* 4. */
1559+
if (!ecma_op_is_callable (arg1))
1560+
{
1561+
ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
1562+
}
1563+
else
1564+
{
1565+
ecma_value_t current_index;
1566+
ecma_number_t *num_p = ecma_alloc_number ();
1567+
ecma_object_t *func_object_p;
1568+
1569+
/* 6. */
1570+
ecma_completion_value_t new_array = ecma_op_create_array_object (NULL, 0, false);
1571+
JERRY_ASSERT (ecma_is_completion_value_normal (new_array));
1572+
ecma_object_t *new_array_p = ecma_get_object_from_completion_value (new_array);
1573+
1574+
/* We already checked that arg1 is callable, so it will always be an object. */
1575+
JERRY_ASSERT (ecma_is_value_object (arg1));
1576+
func_object_p = ecma_get_object_from_value (arg1);
1577+
1578+
/* 8. */
1579+
uint32_t new_array_index = 0;
1580+
1581+
/* 9. */
1582+
for (uint32_t index = 0; index < len && ecma_is_completion_value_empty (ret_value); index++)
1583+
{
1584+
/* 9.a */
1585+
ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index);
1586+
1587+
/* 9.c */
1588+
if (ecma_op_object_get_property (obj_p, index_str_p) != NULL)
1589+
{
1590+
/* 9.c.i */
1591+
ECMA_TRY_CATCH (get_value, ecma_op_object_get (obj_p, index_str_p), ret_value);
1592+
1593+
*num_p = ecma_uint32_to_number (index);
1594+
current_index = ecma_make_number_value (num_p);
1595+
1596+
ecma_value_t call_args[] = { get_value, current_index, obj_this };
1597+
/* 9.c.ii */
1598+
ECMA_TRY_CATCH (call_value, ecma_op_function_call (func_object_p, arg2, call_args, 3), ret_value);
1599+
1600+
/* 9.c.iii, ecma_op_to_boolean always returns a simple value, so no need to free. */
1601+
if (ecma_is_value_true (ecma_op_to_boolean (call_value)))
1602+
{
1603+
ecma_string_t* to_index_string_p = ecma_new_ecma_string_from_uint32 (new_array_index);
1604+
/*
1605+
* By definition we should use [[DefineOwnProperty]] here, but since [[Put]] will create the
1606+
* same property that we need, we can use it for simplicity. No need for a try-catch block
1607+
* since it is called with is_throw = false.
1608+
*/
1609+
ecma_completion_value_t put_comp_value = ecma_op_object_put (new_array_p,
1610+
to_index_string_p,
1611+
get_value,
1612+
false);
1613+
JERRY_ASSERT (ecma_is_completion_value_normal_true (put_comp_value));
1614+
ecma_free_completion_value (put_comp_value);
1615+
1616+
ecma_deref_ecma_string (to_index_string_p);
1617+
new_array_index++;
1618+
}
1619+
1620+
ECMA_FINALIZE (call_value);
1621+
ECMA_FINALIZE (get_value);
1622+
}
1623+
1624+
ecma_deref_ecma_string (index_str_p);
1625+
}
1626+
1627+
ecma_dealloc_number (num_p);
1628+
1629+
if (ecma_is_completion_value_empty (ret_value))
1630+
{
1631+
/* 10. */
1632+
ret_value = new_array;
1633+
}
1634+
else
1635+
{
1636+
ecma_free_completion_value (new_array);
1637+
}
1638+
}
1639+
1640+
ECMA_OP_TO_NUMBER_FINALIZE (len_number);
1641+
ECMA_FINALIZE (len_value);
1642+
ecma_deref_ecma_string (magic_string_length_p);
1643+
ECMA_FINALIZE (obj_this);
1644+
1645+
return ret_value;
1646+
} /* ecma_builtin_array_prototype_object_filter */
1647+
15241648
/**
15251649
* The Array.prototype object's 'slice' routine
15261650
*

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
@@ -74,6 +74,7 @@ ROUTINE (ECMA_MAGIC_STRING_EVERY, ecma_builtin_array_prototype_object_every, 2,
7474
ROUTINE (ECMA_MAGIC_STRING_SOME, ecma_builtin_array_prototype_object_some, 2, 1)
7575
ROUTINE (ECMA_MAGIC_STRING_SLICE, ecma_builtin_array_prototype_object_slice, 2, 2)
7676
ROUTINE (ECMA_MAGIC_STRING_SPLICE, ecma_builtin_array_prototype_object_splice, NON_FIXED, 2)
77+
ROUTINE (ECMA_MAGIC_STRING_FILTER, ecma_builtin_array_prototype_object_filter, 2, 1)
7778

7879
#undef OBJECT_ID
7980
#undef SIMPLE_VALUE

tests/jerry/array_prototype_filter.js

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
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 = ["foo", [], Infinity, 4]
17+
18+
function f(arg1, arg2, arg3) {
19+
assert(arg1 === array[arg2]);
20+
assert(arg3 === array);
21+
return true;
22+
}
23+
24+
var filtered = array.filter(f);
25+
assert(filtered.length === array.length);
26+
for (i = 0; i < filtered.length; i++) {
27+
assert(filtered[i] === array[i]);
28+
}
29+
30+
var array = [1, 2, 3, 4, 5, 6, 7, 8];
31+
32+
function g (arg1, arg2, arg3) {
33+
if (arg2 % 2 === 0) {
34+
return true;
35+
} else {
36+
return false;
37+
}
38+
}
39+
40+
filtered = array.filter(g)
41+
assert(filtered.length === 4);
42+
assert(filtered[0] === 1);
43+
assert(filtered[1] === 3);
44+
assert(filtered[2] === 5);
45+
assert(filtered[3] === 7);
46+
47+
// Checking behavior when unable to get length
48+
var obj = {};
49+
Object.defineProperty(obj, 'length', { 'get' : function () {throw new ReferenceError ("foo"); } });
50+
obj.filter = Array.prototype.filter;
51+
52+
try {
53+
obj.filter(f);
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 = {}
62+
obj.length = 1;
63+
Object.defineProperty(obj, '0', { 'get' : function () {throw new ReferenceError ("foo"); } });
64+
obj.filter = Array.prototype.filter
65+
66+
try {
67+
obj.filter(f);
68+
assert(false);
69+
} catch (e) {
70+
assert(e.message === "foo");
71+
assert(e instanceof ReferenceError);
72+
}

0 commit comments

Comments
 (0)