Skip to content

Commit 3c1563a

Browse files
committed
Implemented Array.prototype.unshift().
JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai [email protected]
1 parent 1f8772d commit 3c1563a

File tree

3 files changed

+202
-0
lines changed

3 files changed

+202
-0
lines changed

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

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,103 @@ ecma_builtin_array_prototype_object_shift (ecma_value_t this_arg) /**< this argu
510510
return ret_value;
511511
} /* ecma_builtin_array_prototype_object_shift */
512512

513+
/**
514+
* The Array.prototype object's 'unshift' routine
515+
*
516+
* See also:
517+
* ECMA-262 v5, 15.4.4.13
518+
*
519+
* @return completion value
520+
* Returned value must be freed with ecma_free_completion_value.
521+
*/
522+
static ecma_completion_value_t
523+
ecma_builtin_array_prototype_object_unshift (ecma_value_t this_arg, /**< this argument */
524+
const ecma_value_t args[], /**< arguments list */
525+
ecma_length_t args_number) /**< number of arguments */
526+
{
527+
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
528+
529+
/* 1. */
530+
ECMA_TRY_CATCH (obj_this,
531+
ecma_op_to_object (this_arg),
532+
ret_value);
533+
534+
ecma_object_t *obj_p = ecma_get_object_from_value (obj_this);
535+
ecma_string_t *magic_string_length_p = ecma_get_magic_string (ECMA_MAGIC_STRING_LENGTH);
536+
537+
/* 2. */
538+
ECMA_TRY_CATCH (len_value,
539+
ecma_op_object_get (obj_p, magic_string_length_p),
540+
ret_value);
541+
542+
ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, len_value, ret_value);
543+
544+
/* 3. */
545+
uint32_t len = ecma_number_to_uint32 (len_number);
546+
547+
/* 5. and 6. */
548+
for (uint32_t k = len; k > 0 && ecma_is_completion_value_empty (ret_value); k--)
549+
{
550+
/* 6.a */
551+
ecma_string_t *from_str_p = ecma_new_ecma_string_from_uint32 (k - 1);
552+
/* 6.b */
553+
ecma_string_t *to_str_p = ecma_new_ecma_string_from_uint32 (k + args_number - 1);
554+
555+
/* 6.c */
556+
if (ecma_op_object_get_property (obj_p, from_str_p) != NULL)
557+
{
558+
/* 6.d.i */
559+
ECMA_TRY_CATCH (get_value, ecma_op_object_get (obj_p, from_str_p), ret_value);
560+
/* 6.d.ii */
561+
ECMA_TRY_CATCH (put_value, ecma_op_object_put (obj_p, to_str_p, get_value, true), ret_value);
562+
563+
ECMA_FINALIZE (put_value);
564+
ECMA_FINALIZE (get_value);
565+
}
566+
else
567+
{
568+
/* 6.e.i */
569+
ECMA_TRY_CATCH (del_value, ecma_op_object_delete (obj_p, to_str_p, true), ret_value);
570+
ECMA_FINALIZE (del_value);
571+
}
572+
573+
ecma_deref_ecma_string (to_str_p);
574+
ecma_deref_ecma_string (from_str_p);
575+
}
576+
577+
for (uint32_t arg_index = 0;
578+
arg_index < args_number && ecma_is_completion_value_empty (ret_value);
579+
arg_index++)
580+
{
581+
ecma_string_t *to_str_p = ecma_new_ecma_string_from_uint32 (arg_index);
582+
/* 9.b */
583+
ECMA_TRY_CATCH (put_value, ecma_op_object_put (obj_p, to_str_p, args[arg_index], true), ret_value);
584+
ECMA_FINALIZE (put_value);
585+
ecma_deref_ecma_string (to_str_p);
586+
}
587+
588+
if (ecma_is_completion_value_empty (ret_value))
589+
{
590+
/* 10. */
591+
ECMA_TRY_CATCH (set_length_value,
592+
ecma_builtin_array_prototype_helper_set_length (obj_p, len + args_number),
593+
ret_value);
594+
595+
ecma_number_t *num_p = ecma_alloc_number ();
596+
*num_p = ecma_uint32_to_number (len + args_number);
597+
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (num_p));
598+
599+
ECMA_FINALIZE (set_length_value);
600+
}
601+
602+
ECMA_OP_TO_NUMBER_FINALIZE (len_number);
603+
ECMA_FINALIZE (len_value);
604+
ecma_deref_ecma_string (magic_string_length_p);
605+
ECMA_FINALIZE (obj_this);
606+
607+
return ret_value;
608+
} /* ecma_builtin_array_prototype_object_unshift */
609+
513610
/**
514611
* @}
515612
* @}

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
@@ -63,6 +63,7 @@ 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)
6464
ROUTINE (ECMA_MAGIC_STRING_INDEX_OF_UL, ecma_builtin_array_prototype_object_index_of, 2, 1)
6565
ROUTINE (ECMA_MAGIC_STRING_SHIFT, ecma_builtin_array_prototype_object_shift, 0, 0)
66+
ROUTINE (ECMA_MAGIC_STRING_UNSHIFT, ecma_builtin_array_prototype_object_unshift, NON_FIXED, 1)
6667

6768
#undef OBJECT_ID
6869
#undef SIMPLE_VALUE
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
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 = []
17+
18+
assert(array.length === 0);
19+
20+
array.unshift("foo");
21+
assert(array.length === 1);
22+
assert(array[0] === "foo");
23+
24+
array.unshift(new Array())
25+
assert(array.length === 2);
26+
assert(array[0] instanceof Array);
27+
assert(array[1] === "foo")
28+
29+
array.unshift(Infinity);
30+
assert(array.length === 3);
31+
assert(array[0] === Infinity);
32+
assert(array[1] instanceof Array);
33+
assert(array[2] === "foo")
34+
35+
array.unshift("bar", 0);
36+
assert(array.length === 5);
37+
assert(array[0] === "bar");
38+
assert(array[1] === 0);
39+
assert(array[2] === Infinity);
40+
assert(array[3] instanceof Array);
41+
assert(array[4] === "foo")
42+
43+
44+
// Checking behavior when no length property defined
45+
var obj = { unshift : Array.prototype.unshift };
46+
47+
assert(obj.length === undefined);
48+
obj.unshift(1,2,3);
49+
assert(obj.length === 3);
50+
51+
// Checking behavior when unable to get length
52+
var obj = { unshift : Array.prototype.unshift };
53+
Object.defineProperty(obj, 'length', { 'get' : function () {throw new ReferenceError ("foo"); } });
54+
55+
try {
56+
obj.unshift(1);
57+
assert(false)
58+
} catch (e) {
59+
assert(e.message === "foo");
60+
assert(e instanceof ReferenceError);
61+
}
62+
63+
// Checking behavior when unable to set length
64+
var obj = { unshift : Array.prototype.unshift };
65+
Object.defineProperty(obj, 'length', { 'set' : function () {throw new ReferenceError ("foo"); } });
66+
67+
try {
68+
obj.unshift(2);
69+
assert(false)
70+
} catch (e) {
71+
assert(e.message === "foo");
72+
assert(e instanceof ReferenceError);
73+
}
74+
75+
// Checking behavior when unable shift elements
76+
var obj = { unshift : Array.prototype.unshift, length : 1 };
77+
Object.defineProperty(obj, '0', { 'get' : function () {throw new ReferenceError ("foo"); } });
78+
79+
try {
80+
obj.unshift(3);
81+
assert(false);
82+
} catch (e) {
83+
assert(e.message === "foo");
84+
assert(e instanceof ReferenceError);
85+
}
86+
87+
var obj = { unshift : Array.prototype.unshift, length : 1 };
88+
Object.defineProperty(obj, '0', { 'set' : function () {throw new ReferenceError ("foo"); } });
89+
90+
try {
91+
obj.unshift(4);
92+
assert(false);
93+
} catch (e) {
94+
assert(e.message === "foo");
95+
assert(e instanceof ReferenceError);
96+
}
97+
98+
// Checking behavior when a property is not defined
99+
var obj = { '0' : "foo", '2' : "bar", length : 3, unshift : Array.prototype.unshift };
100+
assert(obj.unshift("baz") === 4);
101+
assert(obj[0] === "baz");
102+
assert(obj[1] === "foo");
103+
assert(obj[2] === undefined);
104+
assert(obj[3] === "bar");

0 commit comments

Comments
 (0)