Skip to content

Commit 7952b1c

Browse files
Zsolt Borbélygalpeter
authored andcommitted
Implement Function.prototype.apply()
JerryScript-DCO-1.0-Signed-off-by: Zsolt Borbély [email protected]
1 parent 72eb14f commit 7952b1c

File tree

2 files changed

+165
-1
lines changed

2 files changed

+165
-1
lines changed

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

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/* Copyright 2014-2015 Samsung Electronics Co., Ltd.
2+
* Copyright 2015 University of Szeged.
23
*
34
* Licensed under the Apache License, Version 2.0 (the "License");
45
* you may not use this file except in compliance with the License.
@@ -21,6 +22,7 @@
2122
#include "ecma-globals.h"
2223
#include "ecma-helpers.h"
2324
#include "ecma-function-object.h"
25+
#include "ecma-objects.h"
2426
#include "ecma-try-catch-macro.h"
2527
#include "jrt.h"
2628

@@ -70,7 +72,94 @@ ecma_builtin_function_prototype_object_apply (ecma_value_t this_arg, /**< this a
7072
ecma_value_t arg1, /**< first argument */
7173
ecma_value_t arg2) /**< second argument */
7274
{
73-
ECMA_BUILTIN_CP_UNIMPLEMENTED (this_arg, arg1, arg2);
75+
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
76+
77+
/* 1. */
78+
if (!ecma_op_is_callable (this_arg))
79+
{
80+
ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
81+
}
82+
else
83+
{
84+
ecma_object_t *func_obj_p = ecma_get_object_from_value (this_arg);
85+
86+
/* 2. */
87+
if (ecma_is_value_null (arg2) || ecma_is_value_undefined (arg2))
88+
{
89+
ret_value = ecma_op_function_call (func_obj_p,
90+
arg1,
91+
NULL,
92+
0);
93+
}
94+
else
95+
{
96+
/* 3. */
97+
if (!ecma_is_value_object (arg2))
98+
{
99+
ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
100+
}
101+
else
102+
{
103+
ecma_object_t *obj_p = ecma_get_object_from_value (arg2);
104+
ecma_string_t *length_magic_string_p = ecma_get_magic_string (ECMA_MAGIC_STRING_LENGTH);
105+
106+
/* 4. */
107+
ECMA_TRY_CATCH (length_value,
108+
ecma_op_object_get (obj_p, length_magic_string_p),
109+
ret_value);
110+
111+
ECMA_OP_TO_NUMBER_TRY_CATCH (length_number,
112+
length_value,
113+
ret_value);
114+
115+
/* 5. */
116+
const uint32_t length = ecma_number_to_uint32 (length_number);
117+
118+
/* 6. */
119+
MEM_DEFINE_LOCAL_ARRAY (arg_list, length, ecma_value_t);
120+
121+
/* 7. */
122+
uint32_t appended_num = 0;
123+
for (uint32_t index = 0; index < length && ecma_is_completion_value_empty (ret_value); index++)
124+
{
125+
ecma_string_t *curr_idx_str_p = ecma_new_ecma_string_from_uint32 (index);
126+
127+
ECMA_TRY_CATCH (get_value,
128+
ecma_op_object_get (obj_p, curr_idx_str_p),
129+
ret_value);
130+
131+
arg_list[index] = ecma_copy_value (get_value, true);
132+
appended_num++;
133+
134+
ECMA_FINALIZE (get_value);
135+
ecma_deref_ecma_string (curr_idx_str_p);
136+
}
137+
138+
JERRY_ASSERT (appended_num == length || !ecma_is_completion_value_empty (ret_value));
139+
140+
if (ecma_is_completion_value_empty (ret_value))
141+
{
142+
ret_value = ecma_op_function_call (func_obj_p,
143+
arg1,
144+
arg_list,
145+
(ecma_length_t) appended_num);
146+
}
147+
148+
for (uint32_t index = 0; index < appended_num; index++)
149+
{
150+
ecma_free_value (arg_list[index], true);
151+
}
152+
153+
MEM_FINALIZE_LOCAL_ARRAY (arg_list);
154+
155+
ECMA_OP_TO_NUMBER_FINALIZE (length_number);
156+
ECMA_FINALIZE (length_value);
157+
ecma_deref_ecma_string (length_magic_string_p);
158+
}
159+
}
160+
}
161+
162+
return ret_value;
74163
} /* ecma_builtin_function_prototype_object_apply */
75164

76165
/**
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
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+
// See a general usage: number addition.
17+
function addNum ()
18+
{
19+
var sum = 0;
20+
for(var i = 0; i < arguments.length; i++)
21+
{
22+
sum += arguments[i];
23+
}
24+
return sum;
25+
}
26+
27+
var array = [6720, 4, 42];
28+
var obj;
29+
30+
obj = addNum.apply(obj, array);
31+
assert (obj === 6766);
32+
33+
// If the arguments are missing.
34+
obj = addNum.apply();
35+
assert (obj === 0);
36+
37+
obj = addNum.apply(obj);
38+
assert (obj === 0);
39+
40+
// If the function is a builtin.
41+
assert (Math.min.apply(null, array) === 4);
42+
assert (Math.max.apply(null, array) === 6720);
43+
44+
// If the function can't be used as caller.
45+
try {
46+
obj = new Function.prototype.apply();
47+
assert (false);
48+
} catch (e) {
49+
assert (e instanceof TypeError);
50+
}
51+
52+
// If the called function throws an error.
53+
function throwError ()
54+
{
55+
throw new ReferenceError ("foo");
56+
}
57+
58+
try {
59+
obj = throwError.apply(obj, array);
60+
assert (false);
61+
} catch (e) {
62+
assert (e.message === "foo");
63+
assert (e instanceof ReferenceError);
64+
}
65+
66+
// If the array access throws an error.
67+
Object.defineProperty(array, '0', { 'get' : function () { throw new ReferenceError ("foo"); } });
68+
69+
try {
70+
obj = addNum.apply(obj, array);
71+
assert (false);
72+
} catch (e) {
73+
assert (e.message === "foo");
74+
assert (e instanceof ReferenceError);
75+
}

0 commit comments

Comments
 (0)