Skip to content

Commit d80063b

Browse files
Implementing [[Construct]] of built-in Function object.
JerryScript-DCO-1.0-Signed-off-by: Ruben Ayrapetyan [email protected]
1 parent 0644c5c commit d80063b

File tree

2 files changed

+209
-8
lines changed

2 files changed

+209
-8
lines changed

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

Lines changed: 128 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,13 @@
1414
*/
1515

1616
#include "ecma-alloc.h"
17-
#include "ecma-builtins.h"
1817
#include "ecma-conversion.h"
19-
#include "ecma-exceptions.h"
18+
#include "ecma-try-catch-macro.h"
2019
#include "ecma-gc.h"
21-
#include "ecma-globals.h"
22-
#include "ecma-helpers.h"
23-
#include "ecma-objects.h"
2420
#include "ecma-function-object.h"
25-
#include "ecma-try-catch-macro.h"
26-
#include "jrt.h"
21+
#include "ecma-lex-env.h"
22+
#include "serializer.h"
23+
#include "parser.h"
2724

2825
#define ECMA_BUILTINS_INTERNAL
2926
#include "ecma-builtins-internal.h"
@@ -59,6 +56,9 @@ ecma_builtin_function_dispatch_call (const ecma_value_t *arguments_list_p, /**<
5956
/**
6057
* Handle calling [[Construct]] of built-in Function object
6158
*
59+
* See also:
60+
* ECMA-262 v5, 15.3.
61+
*
6262
* @return completion-value
6363
*/
6464
ecma_completion_value_t
@@ -67,7 +67,127 @@ ecma_builtin_function_dispatch_construct (const ecma_value_t *arguments_list_p,
6767
{
6868
JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
6969

70-
ECMA_BUILTIN_CP_UNIMPLEMENTED (arguments_list_p, arguments_list_len);
70+
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
71+
72+
/* Last string, if any, is the function's body, and the rest, if any - are the function's parameter names */
73+
MEM_DEFINE_LOCAL_ARRAY (string_params_p,
74+
arguments_list_len == 0 ? 1 : arguments_list_len,
75+
ecma_string_t*);
76+
uint32_t params_count;
77+
78+
size_t zt_strings_buffer_size;
79+
80+
if (arguments_list_len == 0)
81+
{
82+
/* 3. */
83+
string_params_p[0] = ecma_new_ecma_string_from_magic_string_id (ECMA_MAGIC_STRING__EMPTY);
84+
zt_strings_buffer_size = sizeof (ecma_char_t);
85+
params_count = 1;
86+
}
87+
else
88+
{
89+
/* 4., 5., 6. */
90+
zt_strings_buffer_size = 0;
91+
92+
params_count = 0;
93+
while (params_count < arguments_list_len
94+
&& ecma_is_completion_value_empty (ret_value))
95+
{
96+
ECMA_TRY_CATCH (str_arg_value,
97+
ecma_op_to_string (arguments_list_p[params_count]),
98+
ret_value);
99+
100+
string_params_p[params_count] = ecma_copy_or_ref_ecma_string (ecma_get_string_from_value (str_arg_value));
101+
zt_strings_buffer_size += ((size_t) ecma_string_get_length (string_params_p[params_count]) +
102+
sizeof (ecma_char_t));
103+
params_count++;
104+
105+
ECMA_FINALIZE (str_arg_value);
106+
}
107+
}
108+
109+
if (ecma_is_completion_value_empty (ret_value))
110+
{
111+
JERRY_ASSERT (params_count >= 1);
112+
113+
MEM_DEFINE_LOCAL_ARRAY (zt_string_params_p,
114+
params_count,
115+
ecma_char_t*);
116+
MEM_DEFINE_LOCAL_ARRAY (zt_string_buffer_p,
117+
zt_strings_buffer_size,
118+
ecma_char_t);
119+
120+
ssize_t zt_string_buffer_pos = 0;
121+
for (uint32_t i = 0; i < params_count; i++)
122+
{
123+
ssize_t sz = ecma_string_to_zt_string (string_params_p[i],
124+
&zt_string_buffer_p[zt_string_buffer_pos],
125+
(ssize_t) zt_strings_buffer_size - zt_string_buffer_pos);
126+
JERRY_ASSERT (sz > 0);
127+
128+
zt_string_params_p[i] = zt_string_buffer_p + zt_string_buffer_pos;
129+
130+
zt_string_buffer_pos += sz;
131+
}
132+
133+
parser_init ();
134+
135+
/*
136+
* FIXME:
137+
* Handle syntax errors
138+
*/
139+
parser_parse_new_function ((const char **) zt_string_params_p, params_count);
140+
const opcode_t* opcodes_p = (const opcode_t*) serializer_get_bytecode ();
141+
serializer_print_opcodes ();
142+
parser_free ();
143+
144+
bool is_strict = false;
145+
bool do_instantiate_arguments_object = true;
146+
147+
opcode_scope_code_flags_t scope_flags = vm_get_scope_flags (opcodes_p,
148+
0);
149+
150+
if (scope_flags & OPCODE_SCOPE_CODE_FLAGS_STRICT)
151+
{
152+
is_strict = true;
153+
}
154+
155+
if ((scope_flags & OPCODE_SCOPE_CODE_FLAGS_NOT_REF_ARGUMENTS_IDENTIFIER)
156+
&& (scope_flags & OPCODE_SCOPE_CODE_FLAGS_NOT_REF_EVAL_IDENTIFIER))
157+
{
158+
/* the code doesn't use 'arguments' identifier
159+
* and doesn't perform direct call to eval,
160+
* so Arguments object can't be referenced */
161+
do_instantiate_arguments_object = false;
162+
}
163+
164+
// 11.
165+
ecma_object_t *glob_lex_env_p = ecma_get_global_environment ();
166+
167+
ecma_object_t *func_obj_p = ecma_op_create_function_object (params_count > 1u ? string_params_p : NULL,
168+
(ecma_length_t) (params_count - 1u),
169+
glob_lex_env_p,
170+
is_strict,
171+
do_instantiate_arguments_object,
172+
opcodes_p,
173+
1);
174+
175+
ecma_deref_object (glob_lex_env_p);
176+
177+
ret_value = ecma_make_normal_completion_value (ecma_make_object_value (func_obj_p));
178+
179+
MEM_FINALIZE_LOCAL_ARRAY (zt_string_buffer_p);
180+
MEM_FINALIZE_LOCAL_ARRAY (zt_string_params_p);
181+
}
182+
183+
for (uint32_t i = 0; i < params_count; i++)
184+
{
185+
ecma_deref_ecma_string (string_params_p[i]);
186+
}
187+
188+
MEM_FINALIZE_LOCAL_ARRAY (string_params_p);
189+
190+
return ret_value;
71191
} /* ecma_builtin_function_dispatch_construct */
72192

73193
/**

tests/jerry/function_construct.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Copyright 2015 Samsung Electronics Co., Ltd.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
var f = new Function ('');
16+
assert (f () === undefined);
17+
18+
var f = new Function ('"use strict"; f = undefined;');
19+
assert (f () === undefined && f === undefined);
20+
21+
var f = new Function ('"use strict"; q = undefined;');
22+
try
23+
{
24+
f ();
25+
assert (false);
26+
}
27+
catch (e)
28+
{
29+
assert (e instanceof ReferenceError);
30+
}
31+
32+
for (i = 1; i < 10; i ++)
33+
{
34+
var f = new Function ('a', 'b', 'var q = a; b++; function f (k) {return q + k + b++;}; return f;');
35+
36+
var fns = new Array ();
37+
38+
for (var n = 0; n < 10; n++)
39+
{
40+
var r = f (1, 7);
41+
fns[n] = r;
42+
43+
var check_value = 10;
44+
45+
for (var m = 0; m < 100; m++)
46+
{
47+
var value = r (1);
48+
assert (check_value++ === value);
49+
}
50+
}
51+
52+
var check_value = 109;
53+
for (var n = 0; n < 11; n++)
54+
{
55+
for (var m = 0; m < 10; m++)
56+
{
57+
var value = fns [m] (m * n);
58+
assert (value == check_value + m * n);
59+
}
60+
61+
check_value++;
62+
}
63+
}
64+
65+
try
66+
{
67+
new Function ({
68+
toString : function () {
69+
throw new TypeError();
70+
},
71+
valueOf : function () {
72+
throw new TypeError();
73+
}
74+
});
75+
76+
assert (false);
77+
}
78+
catch (e)
79+
{
80+
assert (e instanceof TypeError);
81+
}

0 commit comments

Comments
 (0)