Skip to content

Commit fd0c943

Browse files
committed
Implemented Array.prototype.indexOf().
JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai dbatyai.u-szeged@partner.samsung.com
1 parent 6c4e988 commit fd0c943

File tree

3 files changed

+198
-0
lines changed

3 files changed

+198
-0
lines changed

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

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "ecma-alloc.h"
1717
#include "ecma-builtins.h"
18+
#include "ecma-comparison.h"
1819
#include "ecma-conversion.h"
1920
#include "ecma-exceptions.h"
2021
#include "ecma-gc.h"
@@ -266,6 +267,136 @@ ecma_builtin_array_prototype_object_push (ecma_value_t this_arg, /**< this argum
266267
return ret_value;
267268
} /* ecma_builtin_array_prototype_object_push */
268269

270+
/**
271+
* The Array.prototype object's 'indexOf' routine
272+
*
273+
* See also:
274+
* ECMA-262 v5, 15.4.4.14
275+
*
276+
* @return completion value
277+
* Returned value must be freed with ecma_free_completion_value.
278+
*/
279+
static ecma_completion_value_t
280+
ecma_builtin_array_prototype_object_index_of (ecma_value_t this_arg, /**< this argument */
281+
ecma_value_t arg1, /**< searchElement */
282+
ecma_value_t arg2) /**< fromIndex */
283+
{
284+
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
285+
286+
/* 1. */
287+
ECMA_TRY_CATCH (obj_this,
288+
ecma_op_to_object (this_arg),
289+
ret_value);
290+
291+
ecma_object_t *obj_p = ecma_get_object_from_value (obj_this);
292+
ecma_string_t *magic_string_length_p = ecma_get_magic_string (ECMA_MAGIC_STRING_LENGTH);
293+
294+
/* 2. */
295+
ECMA_TRY_CATCH (len_value,
296+
ecma_op_object_get (obj_p, magic_string_length_p),
297+
ret_value);
298+
299+
ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, len_value, ret_value);
300+
301+
/* 3. */
302+
uint32_t len = ecma_number_to_uint32 (len_number);
303+
304+
ecma_number_t* num_p = ecma_alloc_number ();
305+
*num_p = ecma_int32_to_number (-1);
306+
307+
/* 4. */
308+
if (len == 0)
309+
{
310+
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (num_p));
311+
}
312+
else
313+
{
314+
/* 5. */
315+
ECMA_OP_TO_NUMBER_TRY_CATCH (arg_from_idx, arg2, ret_value);
316+
317+
int32_t from_idx_int = ecma_number_to_int32 (arg_from_idx);
318+
319+
/* 6. */
320+
if (from_idx_int > 0 && (uint32_t) from_idx_int >= len)
321+
{
322+
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (num_p));
323+
}
324+
else
325+
{
326+
uint32_t k;
327+
328+
/* 7 */
329+
if (from_idx_int >= 0)
330+
{
331+
k = (uint32_t) from_idx_int;
332+
}
333+
/* 8. */
334+
else
335+
{
336+
from_idx_int = -from_idx_int;
337+
338+
/* As opposed to the standard, we prevent k from being negative, so that we can use an uint32 */
339+
if ((uint32_t) from_idx_int < len)
340+
{
341+
/* 8.a */
342+
k = len - (uint32_t) from_idx_int;
343+
}
344+
/* If k would've been negative */
345+
else
346+
{
347+
/* 8.b */
348+
k = 0;
349+
}
350+
351+
}
352+
JERRY_ASSERT (k < len);
353+
354+
for (; k < len && *num_p < 0 && ecma_is_completion_value_empty (ret_value); k++)
355+
{
356+
ecma_string_t *idx_str_p = ecma_new_ecma_string_from_uint32 (k);
357+
358+
/* 9.a */
359+
if (ecma_op_object_get_property (obj_p, idx_str_p) != NULL)
360+
{
361+
/* 9.b.i */
362+
ECMA_TRY_CATCH (get_value, ecma_op_object_get (obj_p, idx_str_p), ret_value);
363+
364+
/* 9.b.ii */
365+
if (ecma_op_strict_equality_compare (arg1, get_value))
366+
{
367+
*num_p = ecma_uint32_to_number (k);
368+
}
369+
370+
ECMA_FINALIZE (get_value);
371+
}
372+
373+
ecma_deref_ecma_string (idx_str_p);
374+
}
375+
376+
if (ecma_is_completion_value_empty (ret_value))
377+
{
378+
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (num_p));
379+
}
380+
else
381+
{
382+
ecma_dealloc_number (num_p);
383+
}
384+
}
385+
386+
ECMA_OP_TO_NUMBER_FINALIZE (arg_from_idx);
387+
}
388+
389+
ECMA_OP_TO_NUMBER_FINALIZE (len_number);
390+
391+
ECMA_FINALIZE (len_value);
392+
393+
ecma_deref_ecma_string (magic_string_length_p);
394+
395+
ECMA_FINALIZE (obj_this);
396+
397+
return ret_value;
398+
} /* ecma_builtin_array_prototype_object_index_of */
399+
269400
/**
270401
* @}
271402
* @}

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
@@ -61,6 +61,7 @@ NUMBER_VALUE (ECMA_MAGIC_STRING_LENGTH,
6161
ROUTINE (ECMA_MAGIC_STRING_TO_STRING_UL, ecma_builtin_array_prototype_object_to_string, 0, 0)
6262
ROUTINE (ECMA_MAGIC_STRING_POP, ecma_builtin_array_prototype_object_pop, 0, 0)
6363
ROUTINE (ECMA_MAGIC_STRING_PUSH, ecma_builtin_array_prototype_object_push, NON_FIXED, 1)
64+
ROUTINE (ECMA_MAGIC_STRING_INDEX_OF_UL, ecma_builtin_array_prototype_object_index_of, 2, 1)
6465

6566
#undef OBJECT_ID
6667
#undef SIMPLE_VALUE
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
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 obj = {};
17+
var array = ["foo", 19, "bar", obj, "foo", 29, "baz"];
18+
19+
var index = array.indexOf("foo");
20+
assert(index === 0);
21+
assert(array[index] === "foo");
22+
23+
assert(array.indexOf("foo", 1) === 4);
24+
assert(array.indexOf("foo", 5) === -1);
25+
26+
var index = array.indexOf("baz");
27+
assert(index === 6);
28+
assert(array[index] === "baz");
29+
30+
assert(array.indexOf("baz", 7) === -1);
31+
32+
var index = array.indexOf(obj);
33+
assert(index === 3);
34+
assert(array[index] === obj);
35+
36+
// Checking behavior when length is zero
37+
var obj = { indexOf : Array.prototype.indexOf, length : 0 };
38+
assert(obj.indexOf("foo") === -1);
39+
40+
// Checking behavior when start index >= length
41+
var arr = [11, 22, 33, 44];
42+
assert(arr.indexOf(44, 4) === -1);
43+
44+
// Checking behavior when unable to get length
45+
var obj = { indexOf : Array.prototype.indexOf}
46+
Object.defineProperty(obj, 'length', { 'get' : function () { throw new ReferenceError ("foo"); } });
47+
48+
try {
49+
obj.indexOf("bar");
50+
assert(false);
51+
} catch (e) {
52+
assert(e.message === "foo");
53+
assert(e instanceof ReferenceError);
54+
}
55+
56+
// Checking behavior when unable to get element
57+
var obj = { indexOf : Array.prototype.indexOf, length : 1}
58+
Object.defineProperty(obj, '0', { 'get' : function () { throw new ReferenceError ("foo"); } });
59+
60+
try {
61+
obj.indexOf("bar");
62+
assert(false);
63+
} catch (e) {
64+
assert(e.message === "foo");
65+
assert(e instanceof ReferenceError);
66+
}

0 commit comments

Comments
 (0)