• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright JS Foundation and other contributors, http://js.foundation
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 
16 #include "ecma-alloc.h"
17 #include "ecma-builtin-helpers.h"
18 #include "ecma-exceptions.h"
19 #include "ecma-function-object.h"
20 #include "ecma-gc.h"
21 #include "ecma-helpers.h"
22 #include "lit-char-helpers.h"
23 #include "ecma-lex-env.h"
24 #include "ecma-objects.h"
25 #include "ecma-objects-general.h"
26 #include "ecma-objects-arguments.h"
27 #include "ecma-proxy-object.h"
28 #include "ecma-try-catch-macro.h"
29 #include "jcontext.h"
30 
31 /** \addtogroup ecma ECMA
32  * @{
33  *
34  * \addtogroup ecmafunctionobject ECMA Function object related routines
35  * @{
36  */
37 
38 #if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM)
39 /**
40  * Get the resource name from the compiled code header
41  *
42  * @return resource name as ecma-string
43  */
44 ecma_value_t
ecma_op_resource_name(const ecma_compiled_code_t * bytecode_header_p)45 ecma_op_resource_name (const ecma_compiled_code_t *bytecode_header_p)
46 {
47   JERRY_ASSERT (bytecode_header_p != NULL);
48 
49   uint8_t *byte_p = (uint8_t *) bytecode_header_p;
50   byte_p += ((size_t) bytecode_header_p->size) << JMEM_ALIGNMENT_LOG;
51 
52   ecma_value_t *resource_name_p = (ecma_value_t *) byte_p;
53   resource_name_p -= ecma_compiled_code_get_formal_params (bytecode_header_p);
54 
55 #if ENABLED (JERRY_ES2015)
56   if (bytecode_header_p->status_flags & CBC_CODE_FLAG_HAS_TAGGED_LITERALS)
57   {
58     resource_name_p--;
59   }
60 #endif /* ENABLED (JERRY_ES2015) */
61 
62   return resource_name_p[-1];
63 } /* ecma_op_resource_name */
64 #endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
65 
66 /**
67  * IsCallable operation.
68  *
69  * See also: ECMA-262 v5, 9.11
70  *
71  * @return true - if the given object is callable;
72  *         false - otherwise
73  */
74 inline bool JERRY_ATTR_ALWAYS_INLINE
ecma_op_object_is_callable(ecma_object_t * obj_p)75 ecma_op_object_is_callable (ecma_object_t *obj_p) /**< ecma object */
76 {
77   JERRY_ASSERT (!ecma_is_lexical_environment (obj_p));
78 
79   const ecma_object_type_t type = ecma_get_object_type (obj_p);
80 
81 #if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
82   if (ECMA_OBJECT_TYPE_IS_PROXY (type))
83   {
84     return ecma_op_is_callable (((ecma_proxy_object_t *) obj_p)->target);
85   }
86 #endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
87 
88   return type >= ECMA_OBJECT_TYPE_FUNCTION;
89 } /* ecma_op_object_is_callable */
90 
91 /**
92  * IsCallable operation.
93  *
94  * See also: ECMA-262 v5, 9.11
95  *
96  * @return true - if value is callable object;
97  *         false - otherwise
98  */
99 bool
ecma_op_is_callable(ecma_value_t value)100 ecma_op_is_callable (ecma_value_t value) /**< ecma value */
101 {
102   return (ecma_is_value_object (value)
103           && ecma_op_object_is_callable (ecma_get_object_from_value (value)));
104 } /* ecma_op_is_callable */
105 
106 /**
107  * Checks whether the given object implements [[Construct]].
108  *
109  * @return true - if the given object is constructor;
110  *         false - otherwise
111  */
112 inline bool JERRY_ATTR_ALWAYS_INLINE
ecma_object_is_constructor(ecma_object_t * obj_p)113 ecma_object_is_constructor (ecma_object_t *obj_p) /**< ecma object */
114 {
115   JERRY_ASSERT (!ecma_is_lexical_environment (obj_p));
116 
117   ecma_object_type_t type = ecma_get_object_type (obj_p);
118 
119   while (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION)
120   {
121     ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) obj_p;
122 
123     obj_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t,
124                                                         bound_func_p->header.u.bound_function.target_function);
125 
126     type = ecma_get_object_type (obj_p);
127   }
128 
129 #if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
130   if (ECMA_OBJECT_TYPE_IS_PROXY (type))
131   {
132     return ecma_is_constructor (((ecma_proxy_object_t *) obj_p)->target);
133   }
134 #endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
135 
136   if (type == ECMA_OBJECT_TYPE_FUNCTION)
137   {
138     return (!ecma_get_object_is_builtin (obj_p) || !ecma_builtin_function_is_routine (obj_p));
139   }
140 
141   return (type >= ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION);
142 } /* ecma_object_is_constructor */
143 
144 /**
145  * Checks whether the value is Object that implements [[Construct]].
146  *
147  * @return true - if value is constructor object;
148  *         false - otherwise
149  */
150 bool
ecma_is_constructor(ecma_value_t value)151 ecma_is_constructor (ecma_value_t value) /**< ecma value */
152 {
153   return (ecma_is_value_object (value)
154           && ecma_object_is_constructor (ecma_get_object_from_value (value)));
155 } /* ecma_is_constructor */
156 
157 /**
158  * Helper method to count and convert the arguments for the Function/GeneratorFunction constructor call.
159  *
160  * See also:
161  *          ECMA 262 v5.1 15.3.2.1 steps 5.a-d
162  *          ECMA 262 v6 19.2.1.1.1 steps 8
163  *
164  * @return ecma value - concatenated arguments as a string.
165  *         Returned value must be freed with ecma_free_value.
166  */
167 static ecma_string_t *
ecma_op_create_dynamic_function_arguments_helper(const ecma_value_t * arguments_list_p,ecma_length_t arguments_list_len)168 ecma_op_create_dynamic_function_arguments_helper (const ecma_value_t *arguments_list_p, /**< arguments list */
169                                                   ecma_length_t arguments_list_len) /**< number of arguments */
170 {
171   JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
172 
173   if (arguments_list_len <= 1)
174   {
175     return ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY);
176   }
177 
178   ecma_string_t *str_p = ecma_op_to_string (arguments_list_p[0]);
179 
180   if (JERRY_UNLIKELY (str_p == NULL))
181   {
182     return str_p;
183   }
184 
185   if (arguments_list_len == 2)
186   {
187     return str_p;
188   }
189 
190   ecma_stringbuilder_t builder = ecma_stringbuilder_create_from (str_p);
191   ecma_deref_ecma_string (str_p);
192 
193   for (ecma_length_t idx = 1; idx < arguments_list_len - 1; idx++)
194   {
195     str_p = ecma_op_to_string (arguments_list_p[idx]);
196 
197     if (JERRY_UNLIKELY (str_p == NULL))
198     {
199       ecma_stringbuilder_destroy (&builder);
200       return str_p;
201     }
202 
203     ecma_stringbuilder_append_char (&builder, LIT_CHAR_COMMA);
204     ecma_stringbuilder_append (&builder, str_p);
205     ecma_deref_ecma_string (str_p);
206   }
207 
208   return ecma_stringbuilder_finalize (&builder);
209 } /* ecma_op_create_dynamic_function_arguments_helper */
210 
211 /**
212  * Function object creation operation.
213  *
214  * See also: ECMA-262 v5, 13.2
215  *
216  * @return pointer to newly created Function object
217  */
218 static ecma_object_t *
ecma_op_create_function_object(ecma_object_t * scope_p,const ecma_compiled_code_t * bytecode_data_p,ecma_builtin_id_t proto_id)219 ecma_op_create_function_object (ecma_object_t *scope_p, /**< function's scope */
220                                 const ecma_compiled_code_t *bytecode_data_p, /**< byte-code array */
221                                 ecma_builtin_id_t proto_id) /**< builtin id of the prototype object */
222 {
223   JERRY_ASSERT (ecma_is_lexical_environment (scope_p));
224 
225   /* 1., 4., 13. */
226   ecma_object_t *prototype_obj_p = ecma_builtin_get (proto_id);
227 
228   size_t function_object_size = sizeof (ecma_extended_object_t);
229 
230 #if ENABLED (JERRY_SNAPSHOT_EXEC)
231   if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)
232   {
233     function_object_size = sizeof (ecma_static_function_t);
234   }
235 #endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
236 
237   ecma_object_t *func_p = ecma_create_object (prototype_obj_p,
238                                               function_object_size,
239                                               ECMA_OBJECT_TYPE_FUNCTION);
240 
241   /* 2., 6., 7., 8. */
242   /*
243    * We don't setup [[Get]], [[Call]], [[Construct]], [[HasInstance]] for each function object.
244    * Instead we set the object's type to ECMA_OBJECT_TYPE_FUNCTION
245    * that defines which version of the routine should be used on demand.
246    */
247 
248   /* 3. */
249   /*
250    * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_FUNCTION type.
251    *
252    * See also: ecma_object_get_class_name
253    */
254 
255   ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_p;
256 
257   /* 9. */
258   ECMA_SET_NON_NULL_POINTER_TAG (ext_func_p->u.function.scope_cp, scope_p, 0);
259 
260   /* 10., 11., 12. */
261 
262 #if ENABLED (JERRY_SNAPSHOT_EXEC)
263   if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)
264   {
265     ext_func_p->u.function.bytecode_cp = ECMA_NULL_POINTER;
266     ((ecma_static_function_t *) func_p)->bytecode_p = bytecode_data_p;
267   }
268   else
269 #endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
270   {
271     ECMA_SET_INTERNAL_VALUE_POINTER (ext_func_p->u.function.bytecode_cp, bytecode_data_p);
272     ecma_bytecode_ref ((ecma_compiled_code_t *) bytecode_data_p);
273   }
274 
275   /* 14., 15., 16., 17., 18. */
276   /*
277    * 'length' and 'prototype' properties are instantiated lazily
278    *
279    * See also: ecma_op_function_try_to_lazy_instantiate_property
280    */
281 
282   return func_p;
283 } /* ecma_op_create_function_object */
284 
285 /**
286  * CreateDynamicFunction operation
287  *
288  * See also:
289  *          ECMA-262 v5, 15.3.
290  *          ECMA-262 v6, 19.2.1.1
291  *
292  * @return ECMA_VALUE_ERROR - if the operation fails
293  *         constructed function object - otherwise
294  */
295 ecma_value_t
ecma_op_create_dynamic_function(const ecma_value_t * arguments_list_p,ecma_length_t arguments_list_len,ecma_parse_opts_t parse_opts)296 ecma_op_create_dynamic_function (const ecma_value_t *arguments_list_p, /**< arguments list */
297                                  ecma_length_t arguments_list_len, /**< number of arguments */
298                                  ecma_parse_opts_t parse_opts) /**< parse options */
299 {
300   JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
301 
302   ecma_string_t *arguments_str_p = ecma_op_create_dynamic_function_arguments_helper (arguments_list_p,
303                                                                                      arguments_list_len);
304 
305   if (JERRY_UNLIKELY (arguments_str_p == NULL))
306   {
307     return ECMA_VALUE_ERROR;
308   }
309 
310   ecma_string_t *function_body_str_p;
311 
312   if (arguments_list_len > 0)
313   {
314     function_body_str_p = ecma_op_to_string (arguments_list_p[arguments_list_len - 1]);
315 
316     if (JERRY_UNLIKELY (function_body_str_p == NULL))
317     {
318       ecma_deref_ecma_string (arguments_str_p);
319       return ECMA_VALUE_ERROR;
320     }
321   }
322   else
323   {
324     /* Very unlikely code path, not optimized. */
325     function_body_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY);
326   }
327 
328   ECMA_STRING_TO_UTF8_STRING (arguments_str_p, arguments_buffer_p, arguments_buffer_size);
329   ECMA_STRING_TO_UTF8_STRING (function_body_str_p, function_body_buffer_p, function_body_buffer_size);
330 
331 #if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM)
332   JERRY_CONTEXT (resource_name) = ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_ANON);
333 #endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
334 
335   ecma_compiled_code_t *bytecode_data_p = NULL;
336 
337   ecma_value_t ret_value = parser_parse_script (arguments_buffer_p,
338                                                 arguments_buffer_size,
339                                                 function_body_buffer_p,
340                                                 function_body_buffer_size,
341                                                 parse_opts,
342                                                 &bytecode_data_p);
343 
344   if (!ECMA_IS_VALUE_ERROR (ret_value))
345   {
346     JERRY_ASSERT (ecma_is_value_true (ret_value));
347 
348     ecma_object_t *global_env_p = ecma_get_global_environment ();
349     ecma_builtin_id_t fallback_proto = ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE;
350 
351 #if ENABLED (JERRY_ES2015)
352     ecma_object_t *new_target_p = JERRY_CONTEXT (current_new_target);
353     bool is_generator_func = parse_opts & ECMA_PARSE_GENERATOR_FUNCTION;
354 
355     if (is_generator_func)
356     {
357       fallback_proto = ECMA_BUILTIN_ID_GENERATOR;
358     }
359 
360     if (new_target_p == NULL)
361     {
362       if (is_generator_func)
363       {
364         new_target_p = ecma_builtin_get (ECMA_BUILTIN_ID_GENERATOR_FUNCTION);
365       }
366       else
367       {
368         new_target_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION);
369       }
370     }
371 
372     ecma_object_t *proto = ecma_op_get_prototype_from_constructor (new_target_p, fallback_proto);
373 
374     if (JERRY_UNLIKELY (proto == NULL))
375     {
376       ecma_bytecode_deref (bytecode_data_p);
377       ecma_deref_ecma_string (arguments_str_p);
378       ecma_deref_ecma_string (function_body_str_p);
379       return ECMA_VALUE_ERROR;
380     }
381 #endif /* ENABLED (JERRY_ES2015) */
382 
383     ecma_object_t *func_obj_p = ecma_op_create_function_object (global_env_p, bytecode_data_p, fallback_proto);
384 
385 #if ENABLED (JERRY_ES2015)
386     ECMA_SET_NON_NULL_POINTER (func_obj_p->u2.prototype_cp, proto);
387     ecma_deref_object (proto);
388 #endif /* ENABLED (JERRY_ES2015) */
389 
390     ecma_bytecode_deref (bytecode_data_p);
391     ret_value = ecma_make_object_value (func_obj_p);
392   }
393 
394   ECMA_FINALIZE_UTF8_STRING (function_body_buffer_p, function_body_buffer_size);
395   ECMA_FINALIZE_UTF8_STRING (arguments_buffer_p, arguments_buffer_size);
396 
397   ecma_deref_ecma_string (arguments_str_p);
398   ecma_deref_ecma_string (function_body_str_p);
399 
400   return ret_value;
401 } /* ecma_op_create_dynamic_function */
402 
403 /**
404  * Function object creation operation.
405  *
406  * See also: ECMA-262 v5, 13.2
407  *
408  * @return pointer to newly created Function object
409  */
410 ecma_object_t *
ecma_op_create_simple_function_object(ecma_object_t * scope_p,const ecma_compiled_code_t * bytecode_data_p)411 ecma_op_create_simple_function_object (ecma_object_t *scope_p, /**< function's scope */
412                                        const ecma_compiled_code_t *bytecode_data_p) /**< byte-code array */
413 {
414   return ecma_op_create_function_object (scope_p, bytecode_data_p, ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE);
415 } /* ecma_op_create_simple_function_object */
416 
417 #if ENABLED (JERRY_ES2015)
418 
419 /**
420  * GeneratorFunction object creation operation.
421  *
422  * See also: ECMA-262 v5, 13.2
423  *
424  * @return pointer to newly created Function object
425  */
426 ecma_object_t *
ecma_op_create_generator_function_object(ecma_object_t * scope_p,const ecma_compiled_code_t * bytecode_data_p)427 ecma_op_create_generator_function_object (ecma_object_t *scope_p, /**< function's scope */
428                                           const ecma_compiled_code_t *bytecode_data_p) /**< byte-code array */
429 {
430   return ecma_op_create_function_object (scope_p, bytecode_data_p, ECMA_BUILTIN_ID_GENERATOR);
431 } /* ecma_op_create_generator_function_object */
432 
433 /**
434  * Arrow function object creation operation.
435  *
436  * See also: ES2015, 9.2.12
437  *
438  * @return pointer to newly created Function object
439  */
440 ecma_object_t *
ecma_op_create_arrow_function_object(ecma_object_t * scope_p,const ecma_compiled_code_t * bytecode_data_p,ecma_value_t this_binding)441 ecma_op_create_arrow_function_object (ecma_object_t *scope_p, /**< function's scope */
442                                       const ecma_compiled_code_t *bytecode_data_p, /**< byte-code array */
443                                       ecma_value_t this_binding) /**< value of 'this' binding */
444 {
445   ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE);
446 
447   size_t arrow_function_object_size = sizeof (ecma_arrow_function_t);
448 
449 #if ENABLED (JERRY_SNAPSHOT_EXEC)
450   if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)
451   {
452     arrow_function_object_size = sizeof (ecma_static_arrow_function_t);
453   }
454 #endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
455 
456   ecma_object_t *func_p = ecma_create_object (prototype_obj_p,
457                                               arrow_function_object_size,
458                                               ECMA_OBJECT_TYPE_FUNCTION);
459 
460   ecma_arrow_function_t *arrow_func_p = (ecma_arrow_function_t *) func_p;
461 
462   ECMA_SET_NON_NULL_POINTER_TAG (arrow_func_p->header.u.function.scope_cp, scope_p, 0);
463 
464 #if ENABLED (JERRY_SNAPSHOT_EXEC)
465   if ((bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION))
466   {
467     arrow_func_p->header.u.function.bytecode_cp = ECMA_NULL_POINTER;
468     ((ecma_static_arrow_function_t *) func_p)->bytecode_p = bytecode_data_p;
469   }
470   else
471   {
472 #endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
473     ECMA_SET_INTERNAL_VALUE_POINTER (arrow_func_p->header.u.function.bytecode_cp, bytecode_data_p);
474     ecma_bytecode_ref ((ecma_compiled_code_t *) bytecode_data_p);
475 #if ENABLED (JERRY_SNAPSHOT_EXEC)
476   }
477 #endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
478 
479   arrow_func_p->this_binding = ecma_copy_value_if_not_object (this_binding);
480   arrow_func_p->new_target = ECMA_VALUE_UNDEFINED;
481 
482   if (JERRY_CONTEXT (current_new_target) != NULL)
483   {
484     arrow_func_p->new_target = ecma_make_object_value (JERRY_CONTEXT (current_new_target));
485   }
486   return func_p;
487 } /* ecma_op_create_arrow_function_object */
488 
489 #endif /* ENABLED (JERRY_ES2015) */
490 
491 /**
492  * External function object creation operation.
493  *
494  * Note:
495  *      external function object is implementation-defined object type
496  *      that represent functions implemented in native code, using Embedding API
497  *
498  * @return pointer to newly created external function object
499  */
500 ecma_object_t *
ecma_op_create_external_function_object(ecma_external_handler_t handler_cb)501 ecma_op_create_external_function_object (ecma_external_handler_t handler_cb) /**< pointer to external native handler */
502 {
503   ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE);
504 
505   ecma_object_t *function_obj_p;
506   function_obj_p = ecma_create_object (prototype_obj_p,
507                                        sizeof (ecma_extended_object_t),
508                                        ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION);
509 
510   /*
511    * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION type.
512    *
513    * See also: ecma_object_get_class_name
514    */
515 
516   ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) function_obj_p;
517   ext_func_obj_p->u.external_handler_cb = handler_cb;
518 
519   return function_obj_p;
520 } /* ecma_op_create_external_function_object */
521 
522 /**
523  * Get compiled code of a function object.
524  *
525  * @return compiled code
526  */
527 inline const ecma_compiled_code_t * JERRY_ATTR_ALWAYS_INLINE
ecma_op_function_get_compiled_code(ecma_extended_object_t * function_p)528 ecma_op_function_get_compiled_code (ecma_extended_object_t *function_p) /**< function pointer */
529 {
530 #if ENABLED (JERRY_SNAPSHOT_EXEC)
531   if (function_p->u.function.bytecode_cp != ECMA_NULL_POINTER)
532   {
533     return ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t,
534                                             function_p->u.function.bytecode_cp);
535   }
536   else
537   {
538     return ((ecma_static_function_t *) function_p)->bytecode_p;
539   }
540 #else /* !ENABLED (JERRY_SNAPSHOT_EXEC) */
541   return ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t,
542                                           function_p->u.function.bytecode_cp);
543 #endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
544 } /* ecma_op_function_get_compiled_code */
545 
546 #if ENABLED (JERRY_ES2015)
547 /**
548  * Check whether the given object [[FunctionKind]] internal slot value is "generator".
549  *
550  * @return true - if the given object is a generator function
551  *         false - otherwise
552  */
553 bool
ecma_op_function_is_generator(ecma_object_t * obj_p)554 ecma_op_function_is_generator (ecma_object_t *obj_p) /**< object */
555 {
556   if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION
557       && !ecma_get_object_is_builtin (obj_p))
558   {
559     ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) obj_p;
560     const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_obj_p);
561 
562     return (bytecode_data_p->status_flags & CBC_CODE_FLAGS_GENERATOR) != 0;
563   }
564 
565   return false;
566 } /* ecma_op_function_is_generator */
567 
568 #endif /* ENABLED (JERRY_ES2015) */
569 
570 /**
571  * 15.3.5.3 implementation of [[HasInstance]] for Function objects
572  *
573  * @return true/false - if arguments are valid
574  *         error - otherwise
575  *         Returned value must be freed with ecma_free_value
576  */
577 ecma_value_t
ecma_op_function_has_instance(ecma_object_t * func_obj_p,ecma_value_t value)578 ecma_op_function_has_instance (ecma_object_t *func_obj_p, /**< Function object */
579                                ecma_value_t value) /**< argument 'V' */
580 {
581   JERRY_ASSERT (func_obj_p != NULL
582                 && !ecma_is_lexical_environment (func_obj_p));
583 
584   if (!ecma_is_value_object (value))
585   {
586     return ECMA_VALUE_FALSE;
587   }
588 
589   while (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION)
590   {
591     JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION);
592 
593     /* 1. 3. */
594     ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) func_obj_p;
595 
596     func_obj_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t,
597                                                              bound_func_p->header.u.bound_function.target_function);
598   }
599 
600   JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION
601                 || ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION
602                 || ECMA_OBJECT_IS_PROXY (func_obj_p));
603 
604   ecma_object_t *v_obj_p = ecma_get_object_from_value (value);
605 
606   ecma_value_t prototype_obj_value = ecma_op_object_get_by_magic_id (func_obj_p,
607                                                                      LIT_MAGIC_STRING_PROTOTYPE);
608 
609   if (ECMA_IS_VALUE_ERROR (prototype_obj_value))
610   {
611     return prototype_obj_value;
612   }
613 
614   if (!ecma_is_value_object (prototype_obj_value))
615   {
616     ecma_free_value (prototype_obj_value);
617     return ecma_raise_type_error (ECMA_ERR_MSG ("Object expected."));
618   }
619 
620   ecma_object_t *prototype_obj_p = ecma_get_object_from_value (prototype_obj_value);
621   JERRY_ASSERT (prototype_obj_p != NULL);
622 
623 #if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
624   ecma_value_t result = ECMA_VALUE_ERROR;
625 #else /* !ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
626   ecma_value_t result = ECMA_VALUE_FALSE;
627 #endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
628 
629   while (true)
630   {
631     jmem_cpointer_t v_obj_cp;
632 #if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
633     if (ECMA_OBJECT_IS_PROXY (v_obj_p))
634     {
635       ecma_value_t parent = ecma_proxy_object_get_prototype_of (v_obj_p);
636 
637       if (ECMA_IS_VALUE_ERROR (parent))
638       {
639         break;
640       }
641 
642       v_obj_cp = ecma_proxy_object_prototype_to_cp (parent);
643     }
644     else
645     {
646 #endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
647       v_obj_cp = ecma_op_ordinary_object_get_prototype_of (v_obj_p);
648 #if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
649     }
650 #endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
651 
652     if (v_obj_cp == JMEM_CP_NULL)
653     {
654 #if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
655       result = ECMA_VALUE_FALSE;
656 #endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
657       break;
658     }
659 
660     v_obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, v_obj_cp);
661 
662     if (v_obj_p == prototype_obj_p)
663     {
664       result = ECMA_VALUE_TRUE;
665       break;
666     }
667   }
668 
669   ecma_deref_object (prototype_obj_p);
670   return result;
671 } /* ecma_op_function_has_instance */
672 
673 #if ENABLED (JERRY_ES2015)
674 
675 /**
676  * GetSuperConstructor operation for class methods
677  *
678  * See also: ECMAScript v6, 12.3.5.2
679  *
680  * @return ECMA_VALUE_ERROR - if the operation fails
681  *         super constructor - otherwise
682  */
683 ecma_value_t
ecma_op_function_get_super_constructor(ecma_object_t * func_obj_p)684 ecma_op_function_get_super_constructor (ecma_object_t *func_obj_p) /**< function object */
685 {
686   ecma_object_t *super_ctor_p;
687 
688 #if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
689   if (ECMA_OBJECT_IS_PROXY (func_obj_p))
690   {
691     ecma_value_t super_ctor = ecma_proxy_object_get_prototype_of (func_obj_p);
692 
693     if (ECMA_IS_VALUE_ERROR (super_ctor))
694     {
695       return super_ctor;
696     }
697 
698     super_ctor_p = ecma_is_value_null (super_ctor) ? NULL : ecma_get_object_from_value (super_ctor);
699   }
700   else
701   {
702 #endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
703     jmem_cpointer_t proto_cp = ecma_op_ordinary_object_get_prototype_of (func_obj_p);
704     if (proto_cp == JMEM_CP_NULL)
705     {
706       super_ctor_p = NULL;
707     }
708     else
709     {
710       super_ctor_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp);
711       ecma_ref_object (super_ctor_p);
712     }
713 #if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
714   }
715 #endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
716 
717   if (super_ctor_p == NULL || !ecma_object_is_constructor (super_ctor_p))
718   {
719     if (super_ctor_p != NULL)
720     {
721       ecma_deref_object (super_ctor_p);
722     }
723     return ecma_raise_type_error (ECMA_ERR_MSG ("Super binding must be a constructor."));
724   }
725 
726   return ecma_make_object_value (super_ctor_p);
727 } /* ecma_op_function_get_super_constructor */
728 #endif /* ENABLED (JERRY_ES2015) */
729 
730 /**
731  * Ordinary internal method: GetPrototypeFromConstructor (constructor, intrinsicDefaultProto)
732  *
733  * See also: ECMAScript v6, 9.1.15
734  *
735  * @return NULL - if the operation fail (exception on the global context is raised)
736  *         pointer to the prototype object - otherwise
737  */
738 ecma_object_t *
ecma_op_get_prototype_from_constructor(ecma_object_t * ctor_obj_p,ecma_builtin_id_t default_proto_id)739 ecma_op_get_prototype_from_constructor (ecma_object_t *ctor_obj_p, /**< constructor to get prototype from  */
740                                         ecma_builtin_id_t default_proto_id) /**< intrinsicDefaultProto */
741 {
742   JERRY_ASSERT (ecma_object_is_constructor (ctor_obj_p));
743   JERRY_ASSERT (default_proto_id < ECMA_BUILTIN_ID__COUNT);
744 
745   ecma_value_t proto = ecma_op_object_get_by_magic_id (ctor_obj_p, LIT_MAGIC_STRING_PROTOTYPE);
746 
747   if (ECMA_IS_VALUE_ERROR (proto))
748   {
749     return NULL;
750   }
751 
752   ecma_object_t *proto_obj_p;
753 
754   if (!ecma_is_value_object (proto))
755   {
756     ecma_free_value (proto);
757     proto_obj_p = ecma_builtin_get (default_proto_id);
758     ecma_ref_object (proto_obj_p);
759   }
760   else
761   {
762     proto_obj_p = ecma_get_object_from_value (proto);
763   }
764 
765   return proto_obj_p;
766 } /* ecma_op_get_prototype_from_constructor */
767 
768 /**
769  * Perform a JavaScript function object method call.
770  *
771  * The input function object should be a pure JavaScript method
772  *
773  * @return the result of the function call.
774  */
775 static ecma_value_t
ecma_op_function_call_simple(ecma_object_t * func_obj_p,ecma_value_t this_arg_value,const ecma_value_t * arguments_list_p,ecma_length_t arguments_list_len)776 ecma_op_function_call_simple (ecma_object_t *func_obj_p, /**< Function object */
777                               ecma_value_t this_arg_value, /**< 'this' argument's value */
778                               const ecma_value_t *arguments_list_p, /**< arguments list */
779                               ecma_length_t arguments_list_len) /**< length of arguments list */
780 {
781   JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION);
782 
783   if (JERRY_UNLIKELY (ecma_get_object_is_builtin (func_obj_p)))
784   {
785     return ecma_builtin_dispatch_call (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len);
786   }
787 
788   /* Entering Function Code (ECMA-262 v5, 10.4.3) */
789   ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_obj_p;
790 
791   ecma_object_t *scope_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t,
792                                                                        ext_func_p->u.function.scope_cp);
793 
794   /* 8. */
795   ecma_value_t this_binding = this_arg_value;
796   bool free_this_binding = false;
797 
798   const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
799   uint16_t status_flags = bytecode_data_p->status_flags;
800 
801 #if ENABLED (JERRY_ES2015)
802   bool is_construct_call = JERRY_CONTEXT (current_new_target) != NULL;
803   if (JERRY_UNLIKELY (status_flags & (CBC_CODE_FLAGS_CLASS_CONSTRUCTOR | CBC_CODE_FLAGS_GENERATOR)))
804   {
805     if (!is_construct_call && (status_flags & CBC_CODE_FLAGS_CLASS_CONSTRUCTOR))
806     {
807       return ecma_raise_type_error (ECMA_ERR_MSG ("Class constructor cannot be invoked without 'new'."));
808     }
809 
810     if ((status_flags & CBC_CODE_FLAGS_GENERATOR) && is_construct_call)
811     {
812       return ecma_raise_type_error (ECMA_ERR_MSG ("Generator functions cannot be invoked with 'new'."));
813     }
814   }
815 #endif /* ENABLED (JERRY_ES2015) */
816 
817   /* 1. */
818 #if ENABLED (JERRY_ES2015)
819   ecma_object_t *old_function_object_p = JERRY_CONTEXT (current_function_obj_p);
820 
821   if (JERRY_UNLIKELY (status_flags & CBC_CODE_FLAGS_ARROW_FUNCTION))
822   {
823     ecma_arrow_function_t *arrow_func_p = (ecma_arrow_function_t *) func_obj_p;
824 
825     if (ecma_is_value_undefined (arrow_func_p->new_target))
826     {
827       JERRY_CONTEXT (current_new_target) = NULL;
828     }
829     else
830     {
831       JERRY_CONTEXT (current_new_target) = ecma_get_object_from_value (arrow_func_p->new_target);
832     }
833     this_binding = arrow_func_p->this_binding;
834   }
835   else
836   {
837     JERRY_CONTEXT (current_function_obj_p) = func_obj_p;
838 #endif /* ENABLED (JERRY_ES2015) */
839     if (!(status_flags & CBC_CODE_FLAGS_STRICT_MODE))
840     {
841       if (ecma_is_value_undefined (this_binding)
842           || ecma_is_value_null (this_binding))
843       {
844         /* 2. */
845         this_binding = ecma_make_object_value (ecma_builtin_get_global ());
846       }
847       else if (!ecma_is_value_object (this_binding))
848       {
849         /* 3., 4. */
850         this_binding = ecma_op_to_object (this_binding);
851         free_this_binding = true;
852 
853         JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (this_binding));
854       }
855     }
856 #if ENABLED (JERRY_ES2015)
857   }
858 #endif /* ENABLED (JERRY_ES2015) */
859 
860   /* 5. */
861   ecma_object_t *local_env_p;
862   if (status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED)
863   {
864     local_env_p = scope_p;
865   }
866   else
867   {
868     local_env_p = ecma_create_decl_lex_env (scope_p);
869     if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_IS_ARGUMENTS_NEEDED)
870     {
871       ecma_op_create_arguments_object (func_obj_p,
872                                        local_env_p,
873                                        arguments_list_p,
874                                        arguments_list_len,
875                                        bytecode_data_p);
876     }
877 #if ENABLED (JERRY_ES2015)
878     // ECMAScript v6, 9.2.2.8
879     if (JERRY_UNLIKELY (status_flags & CBC_CODE_FLAGS_CLASS_CONSTRUCTOR))
880     {
881       ecma_value_t lexical_this;
882       lexical_this = (ECMA_GET_THIRD_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp) ? ECMA_VALUE_UNINITIALIZED
883                                                                                             : this_binding);
884       ecma_op_init_this_binding (local_env_p, lexical_this);
885     }
886 #endif /* ENABLED (JERRY_ES2015) */
887   }
888 
889   ecma_value_t ret_value = vm_run (bytecode_data_p,
890                                    this_binding,
891                                    local_env_p,
892                                    arguments_list_p,
893                                    arguments_list_len);
894 
895 #if ENABLED (JERRY_ES2015)
896   JERRY_CONTEXT (current_function_obj_p) = old_function_object_p;
897 
898   /* ECMAScript v6, 9.2.2.13 */
899   if (ECMA_GET_THIRD_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp))
900   {
901     if (!ECMA_IS_VALUE_ERROR (ret_value) && !ecma_is_value_object (ret_value))
902     {
903       if (!ecma_is_value_undefined (ret_value))
904       {
905         ecma_free_value (ret_value);
906         ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Derived constructors may only return object or undefined."));
907       }
908       else
909       {
910         ret_value = ecma_op_get_this_binding (local_env_p);
911       }
912     }
913   }
914 
915 #endif /* ENABLED (JERRY_ES2015) */
916 
917   if (!(status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED))
918   {
919     ecma_deref_object (local_env_p);
920   }
921 
922   if (JERRY_UNLIKELY (free_this_binding))
923   {
924     ecma_free_value (this_binding);
925   }
926 
927   return ret_value;
928 } /* ecma_op_function_call_simple */
929 
930 /**
931  * Perform a native C method call which was registered via the API.
932  *
933  * @return the result of the function call.
934  */
935 static ecma_value_t JERRY_ATTR_NOINLINE
ecma_op_function_call_external(ecma_object_t * func_obj_p,ecma_value_t this_arg_value,const ecma_value_t * arguments_list_p,ecma_length_t arguments_list_len)936 ecma_op_function_call_external (ecma_object_t *func_obj_p, /**< Function object */
937                                 ecma_value_t this_arg_value, /**< 'this' argument's value */
938                                 const ecma_value_t *arguments_list_p, /**< arguments list */
939                                 ecma_length_t arguments_list_len) /**< length of arguments list */
940 
941 {
942   JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION);
943   ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p;
944   JERRY_ASSERT (ext_func_obj_p->u.external_handler_cb != NULL);
945 
946   ecma_value_t ret_value = ext_func_obj_p->u.external_handler_cb (ecma_make_object_value (func_obj_p),
947                                                                   this_arg_value,
948                                                                   arguments_list_p,
949                                                                   arguments_list_len);
950   if (JERRY_UNLIKELY (ecma_is_value_error_reference (ret_value)))
951   {
952     ecma_raise_error_from_error_reference (ret_value);
953     return ECMA_VALUE_ERROR;
954   }
955 
956 #if ENABLED (JERRY_DEBUGGER)
957   JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_EXCEPTION_THROWN);
958 #endif /* ENABLED (JERRY_DEBUGGER) */
959   return ret_value;
960 } /* ecma_op_function_call_external */
961 
962 /**
963  * Append the bound arguments into the given collection
964  *
965  * Note:
966  *       - The whole bound chain is resolved
967  *       - The first element of the collection contains the bounded this value
968  *
969  * @return target function of the bound function
970  */
971 JERRY_ATTR_NOINLINE static ecma_object_t *
ecma_op_bound_function_get_argument_list(ecma_object_t * func_obj_p,ecma_collection_t * list_p)972 ecma_op_bound_function_get_argument_list (ecma_object_t *func_obj_p, /**< bound bunction object */
973                                           ecma_collection_t *list_p) /**< list of arguments */
974 {
975   JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION);
976 
977   ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) func_obj_p;
978 
979   func_obj_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t,
980                                                            bound_func_p->header.u.bound_function.target_function);
981 
982   ecma_value_t args_len_or_this = bound_func_p->header.u.bound_function.args_len_or_this;
983 
984   ecma_length_t args_length = 1;
985 
986   if (ecma_is_value_integer_number (args_len_or_this))
987   {
988     args_length = (ecma_length_t) ecma_get_integer_from_value (args_len_or_this);
989   }
990 
991   /* 5. */
992   if (args_length != 1)
993   {
994     const ecma_value_t *args_p = (const ecma_value_t *) (bound_func_p + 1);
995     list_p->buffer_p[0] = *args_p;
996 
997     if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION)
998     {
999       func_obj_p = ecma_op_bound_function_get_argument_list (func_obj_p, list_p);
1000     }
1001     ecma_collection_append (list_p, args_p + 1, args_length - 1);
1002   }
1003   else
1004   {
1005     list_p->buffer_p[0] = args_len_or_this;
1006   }
1007 
1008   return func_obj_p;
1009 } /* ecma_op_bound_function_get_argument_list */
1010 
1011 /**
1012  * [[Call]] internal method for bound function objects
1013  *
1014  * @return ecma value
1015  *         Returned value must be freed with ecma_free_value
1016  */
1017 static ecma_value_t JERRY_ATTR_NOINLINE
ecma_op_function_call_bound(ecma_object_t * func_obj_p,const ecma_value_t * arguments_list_p,ecma_length_t arguments_list_len)1018 ecma_op_function_call_bound (ecma_object_t *func_obj_p, /**< Function object */
1019                              const ecma_value_t *arguments_list_p, /**< arguments list */
1020                              ecma_length_t arguments_list_len) /**< length of arguments list */
1021 {
1022   JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION);
1023 
1024   JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_DIRECT_EVAL;
1025 
1026   ecma_collection_t *bound_arg_list_p = ecma_new_collection ();
1027   ecma_collection_push_back (bound_arg_list_p, ECMA_VALUE_EMPTY);
1028 
1029   ecma_object_t *target_obj_p = ecma_op_bound_function_get_argument_list (func_obj_p, bound_arg_list_p);
1030 
1031   ecma_collection_append (bound_arg_list_p, arguments_list_p, arguments_list_len);
1032 
1033   JERRY_ASSERT (!ecma_is_value_empty (bound_arg_list_p->buffer_p[0]));
1034 
1035   ecma_value_t ret_value = ecma_op_function_call (target_obj_p,
1036                                                   bound_arg_list_p->buffer_p[0],
1037                                                   bound_arg_list_p->buffer_p + 1,
1038                                                   (ecma_length_t) (bound_arg_list_p->item_count - 1));
1039 
1040   ecma_collection_destroy (bound_arg_list_p);
1041 
1042   return ret_value;
1043 } /* ecma_op_function_call_bound */
1044 
1045 /**
1046  * [[Call]] implementation for Function objects,
1047  * created through 13.2 (ECMA_OBJECT_TYPE_FUNCTION)
1048  * or 15.3.4.5 (ECMA_OBJECT_TYPE_BOUND_FUNCTION),
1049  * and for built-in Function objects
1050  * from section 15 (ECMA_OBJECT_TYPE_FUNCTION).
1051  *
1052  * @return ecma value
1053  *         Returned value must be freed with ecma_free_value
1054  */
1055 ecma_value_t
ecma_op_function_call(ecma_object_t * func_obj_p,ecma_value_t this_arg_value,const ecma_value_t * arguments_list_p,ecma_length_t arguments_list_len)1056 ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */
1057                        ecma_value_t this_arg_value, /**< 'this' argument's value */
1058                        const ecma_value_t *arguments_list_p, /**< arguments list */
1059                        ecma_length_t arguments_list_len) /**< length of arguments list */
1060 {
1061   JERRY_ASSERT (func_obj_p != NULL
1062                 && !ecma_is_lexical_environment (func_obj_p));
1063   JERRY_ASSERT (ecma_op_object_is_callable (func_obj_p));
1064 
1065   ECMA_CHECK_STACK_USAGE ();
1066 
1067   const ecma_object_type_t type = ecma_get_object_type (func_obj_p);
1068 
1069 #if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
1070   if (ECMA_OBJECT_TYPE_IS_PROXY (type))
1071   {
1072     return ecma_proxy_object_call (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len);
1073   }
1074 #endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
1075 
1076 #if ENABLED (JERRY_ES2015)
1077   ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target);
1078   if (JERRY_UNLIKELY (!(JERRY_CONTEXT (status_flags) & ECMA_STATUS_DIRECT_EVAL)))
1079   {
1080     JERRY_CONTEXT (current_new_target) = NULL;
1081   }
1082 #endif /* ENABLED (JERRY_ES2015) */
1083 
1084   ecma_value_t result;
1085 
1086   if (JERRY_LIKELY (type == ECMA_OBJECT_TYPE_FUNCTION))
1087   {
1088     result = ecma_op_function_call_simple (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len);
1089   }
1090   else if (type == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION)
1091   {
1092     result = ecma_op_function_call_external (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len);
1093   }
1094   else
1095   {
1096     result = ecma_op_function_call_bound (func_obj_p, arguments_list_p, arguments_list_len);
1097   }
1098 
1099 #if ENABLED (JERRY_ES2015)
1100   JERRY_CONTEXT (current_new_target) = old_new_target_p;
1101 #endif /* ENABLED (JERRY_ES2015) */
1102 
1103   return result;
1104 } /* ecma_op_function_call */
1105 
1106 /**
1107  * [[Construct]] internal method for bound function objects
1108  *
1109  * @return ecma value
1110  *         Returned value must be freed with ecma_free_value
1111  */
1112 static ecma_value_t JERRY_ATTR_NOINLINE
ecma_op_function_construct_bound(ecma_object_t * func_obj_p,ecma_object_t * new_target_p,const ecma_value_t * arguments_list_p,ecma_length_t arguments_list_len)1113 ecma_op_function_construct_bound (ecma_object_t *func_obj_p, /**< Function object */
1114                                   ecma_object_t *new_target_p, /**< new target */
1115                                   const ecma_value_t *arguments_list_p, /**< arguments list */
1116                                   ecma_length_t arguments_list_len) /**< length of arguments list */
1117 {
1118   JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION);
1119 
1120   ecma_collection_t *bound_arg_list_p = ecma_new_collection ();
1121   ecma_collection_push_back (bound_arg_list_p, ECMA_VALUE_EMPTY);
1122 
1123   ecma_object_t *target_obj_p = ecma_op_bound_function_get_argument_list (func_obj_p, bound_arg_list_p);
1124 
1125   ecma_collection_append (bound_arg_list_p, arguments_list_p, arguments_list_len);
1126 
1127   if (func_obj_p == new_target_p)
1128   {
1129     new_target_p = target_obj_p;
1130   }
1131 
1132   ecma_value_t ret_value = ecma_op_function_construct (target_obj_p,
1133                                                        new_target_p,
1134                                                        bound_arg_list_p->buffer_p + 1,
1135                                                        (ecma_length_t) (bound_arg_list_p->item_count - 1));
1136 
1137   ecma_collection_destroy (bound_arg_list_p);
1138 
1139   return ret_value;
1140 } /* ecma_op_function_construct_bound */
1141 
1142 /**
1143  * [[Construct]] internal method for external function objects
1144  *
1145  * @return ecma value
1146  *         Returned value must be freed with ecma_free_value
1147  */
1148 static ecma_value_t JERRY_ATTR_NOINLINE
ecma_op_function_construct_external(ecma_object_t * func_obj_p,ecma_object_t * new_target_p,const ecma_value_t * arguments_list_p,ecma_length_t arguments_list_len)1149 ecma_op_function_construct_external (ecma_object_t *func_obj_p, /**< Function object */
1150                                      ecma_object_t *new_target_p, /**< new target */
1151                                      const ecma_value_t *arguments_list_p, /**< arguments list */
1152                                      ecma_length_t arguments_list_len) /**< length of arguments list */
1153 {
1154   JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION);
1155 
1156   ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (new_target_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE);
1157 
1158   if (JERRY_UNLIKELY (proto_p == NULL))
1159   {
1160     return ECMA_VALUE_ERROR;
1161   }
1162 
1163   ecma_object_t *new_this_obj_p = ecma_create_object (proto_p, 0, ECMA_OBJECT_TYPE_GENERAL);
1164   ecma_value_t this_arg = ecma_make_object_value (new_this_obj_p);
1165   ecma_deref_object (proto_p);
1166 
1167 #if ENABLED (JERRY_ES2015)
1168   ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target);
1169   JERRY_CONTEXT (current_new_target) = new_target_p;
1170 #endif /* ENABLED (JERRY_ES2015) */
1171 
1172   ecma_value_t ret_value = ecma_op_function_call_external (func_obj_p, this_arg, arguments_list_p, arguments_list_len);
1173 
1174 #if ENABLED (JERRY_ES2015)
1175   JERRY_CONTEXT (current_new_target) = old_new_target_p;
1176 #endif /* ENABLED (JERRY_ES2015) */
1177 
1178   if (ECMA_IS_VALUE_ERROR (ret_value) || ecma_is_value_object (ret_value))
1179   {
1180     ecma_deref_object (new_this_obj_p);
1181     return ret_value;
1182   }
1183 
1184   ecma_free_value (ret_value);
1185 
1186   return this_arg;
1187 } /* ecma_op_function_construct_external */
1188 
1189 /**
1190  * General [[Construct]] implementation function objects
1191  *
1192  * See also: ECMAScript v6, 9.2.2
1193  *
1194  * @return ecma value
1195  *         Returned value must be freed with ecma_free_value
1196  */
1197 ecma_value_t
ecma_op_function_construct(ecma_object_t * func_obj_p,ecma_object_t * new_target_p,const ecma_value_t * arguments_list_p,ecma_length_t arguments_list_len)1198 ecma_op_function_construct (ecma_object_t *func_obj_p, /**< Function object */
1199                             ecma_object_t *new_target_p, /**< new target */
1200                             const ecma_value_t *arguments_list_p, /**< arguments list */
1201                             ecma_length_t arguments_list_len) /**< length of arguments list */
1202 {
1203   JERRY_ASSERT (func_obj_p != NULL
1204                 && !ecma_is_lexical_environment (func_obj_p));
1205 
1206   const ecma_object_type_t type = ecma_get_object_type (func_obj_p);
1207 
1208 #if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
1209   if (ECMA_OBJECT_TYPE_IS_PROXY (type))
1210   {
1211     return ecma_proxy_object_construct (func_obj_p,
1212                                         new_target_p,
1213                                         arguments_list_p,
1214                                         arguments_list_len);
1215   }
1216 #endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
1217 
1218   if (JERRY_UNLIKELY (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION))
1219   {
1220     return ecma_op_function_construct_bound (func_obj_p, new_target_p, arguments_list_p, arguments_list_len);
1221   }
1222 
1223   if (JERRY_UNLIKELY (type == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION))
1224   {
1225     return ecma_op_function_construct_external (func_obj_p, new_target_p, arguments_list_p, arguments_list_len);
1226   }
1227 
1228   JERRY_ASSERT (type == ECMA_OBJECT_TYPE_FUNCTION);
1229 
1230   if (JERRY_UNLIKELY (ecma_get_object_is_builtin (func_obj_p)))
1231   {
1232     return ecma_builtin_dispatch_construct (func_obj_p, new_target_p, arguments_list_p, arguments_list_len);
1233   }
1234 
1235   ecma_object_t *new_this_obj_p = NULL;
1236   ecma_value_t this_arg;
1237   ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p;
1238   const ecma_compiled_code_t *byte_code_p = ecma_op_function_get_compiled_code (ext_func_obj_p);
1239 
1240   if (byte_code_p->status_flags & (CBC_CODE_FLAGS_ARROW_FUNCTION | CBC_CODE_FLAGS_ACCESSOR))
1241   {
1242     if (byte_code_p->status_flags & CBC_CODE_FLAGS_ARROW_FUNCTION)
1243     {
1244       return ecma_raise_type_error (ECMA_ERR_MSG ("Arrow functions have no constructor."));
1245     }
1246 
1247     return ecma_raise_type_error (ECMA_ERR_MSG ("Expected a constructor."));
1248   }
1249 
1250 #if ENABLED (JERRY_ES2015)
1251   /* 6. */
1252   ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target);
1253   JERRY_CONTEXT (current_new_target) = new_target_p;
1254 
1255   /* 5. */
1256   if (!ECMA_GET_THIRD_BIT_FROM_POINTER_TAG (ext_func_obj_p->u.function.scope_cp))
1257   {
1258 #endif /* ENABLED (JERRY_ES2015) */
1259     /* 5.a */
1260     ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (new_target_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE);
1261 
1262     /* 5.b */
1263     if (JERRY_UNLIKELY (proto_p == NULL))
1264     {
1265       return ECMA_VALUE_ERROR;
1266     }
1267 
1268     new_this_obj_p = ecma_create_object (proto_p, 0, ECMA_OBJECT_TYPE_GENERAL);
1269     ecma_deref_object (proto_p);
1270     this_arg = ecma_make_object_value (new_this_obj_p);
1271 #if ENABLED (JERRY_ES2015)
1272   }
1273   else
1274   {
1275     this_arg = ECMA_VALUE_UNDEFINED;
1276   }
1277 #endif /* ENABLED (JERRY_ES2015) */
1278 
1279   ecma_value_t ret_value = ecma_op_function_call_simple (func_obj_p, this_arg, arguments_list_p, arguments_list_len);
1280 
1281 #if ENABLED (JERRY_ES2015)
1282   JERRY_CONTEXT (current_new_target) = old_new_target_p;
1283 #endif /* ENABLED (JERRY_ES2015) */
1284 
1285   /* 13.a */
1286   if (ECMA_IS_VALUE_ERROR (ret_value) || ecma_is_value_object (ret_value))
1287   {
1288 #if ENABLED (JERRY_ES2015)
1289     if (new_this_obj_p != NULL)
1290     {
1291       ecma_deref_object (new_this_obj_p);
1292     }
1293 #else /* !ENABLED (JERRY_ES2015) */
1294     ecma_deref_object (new_this_obj_p);
1295 #endif /* ENABLED (JERRY_ES2015) */
1296     return ret_value;
1297   }
1298 
1299   /* 13.b */
1300   ecma_free_value (ret_value);
1301   return this_arg;
1302 } /* ecma_op_function_construct */
1303 
1304 /**
1305  * Lazy instantiation of 'prototype' property for non-builtin and external functions
1306  *
1307  * @return pointer to newly instantiated property
1308  */
1309 static ecma_property_t *
ecma_op_lazy_instantiate_prototype_object(ecma_object_t * object_p)1310 ecma_op_lazy_instantiate_prototype_object (ecma_object_t *object_p) /**< the function object */
1311 {
1312   JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION
1313                 || ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION);
1314 
1315   /* ECMA-262 v5, 13.2, 16-18 */
1316 
1317   ecma_object_t *proto_object_p = NULL;
1318   bool init_constructor = true;
1319 
1320 #if ENABLED (JERRY_ES2015)
1321   if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION)
1322   {
1323     const ecma_compiled_code_t *byte_code_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) object_p);
1324 
1325     if (byte_code_p->status_flags & CBC_CODE_FLAGS_GENERATOR)
1326     {
1327       proto_object_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE),
1328                                            0,
1329                                            ECMA_OBJECT_TYPE_GENERAL);
1330       init_constructor = false;
1331     }
1332     else if (byte_code_p->status_flags & (CBC_CODE_FLAGS_ARROW_FUNCTION | CBC_CODE_FLAGS_ACCESSOR))
1333     {
1334       return NULL;
1335     }
1336   }
1337 #endif /* ENABLED (JERRY_ES2015) */
1338 
1339 #if ENABLED (JERRY_ES2015)
1340   if (proto_object_p == NULL)
1341 #endif /* ENABLED (JERRY_ES2015) */
1342   {
1343     proto_object_p = ecma_op_create_object_object_noarg ();
1344   }
1345 
1346   /* 17. */
1347   if (init_constructor)
1348   {
1349     ecma_property_value_t *constructor_prop_value_p;
1350     constructor_prop_value_p = ecma_create_named_data_property (proto_object_p,
1351                                                                 ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR),
1352                                                                 ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
1353                                                                 NULL);
1354 
1355     constructor_prop_value_p->value = ecma_make_object_value (object_p);
1356   }
1357 
1358   /* 18. */
1359   ecma_property_t *prototype_prop_p;
1360   ecma_property_value_t *prototype_prop_value_p;
1361   prototype_prop_value_p = ecma_create_named_data_property (object_p,
1362                                                             ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE),
1363                                                             ECMA_PROPERTY_FLAG_WRITABLE,
1364                                                             &prototype_prop_p);
1365 
1366   prototype_prop_value_p->value = ecma_make_object_value (proto_object_p);
1367 
1368   ecma_deref_object (proto_object_p);
1369 
1370   return prototype_prop_p;
1371 } /* ecma_op_lazy_instantiate_prototype_object */
1372 
1373 /**
1374  * Lazy instantiation of non-builtin ecma function object's properties
1375  *
1376  * Warning:
1377  *         Only non-configurable properties could be instantiated lazily in this function,
1378  *         as configurable properties could be deleted and it would be incorrect
1379  *         to reinstantiate them in the function in second time.
1380  *
1381  * @return pointer to newly instantiated property, if a property was instantiated,
1382  *         NULL - otherwise
1383  */
1384 ecma_property_t *
ecma_op_function_try_to_lazy_instantiate_property(ecma_object_t * object_p,ecma_string_t * property_name_p)1385 ecma_op_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**< the function object */
1386                                                    ecma_string_t *property_name_p) /**< property name */
1387 {
1388   JERRY_ASSERT (!ecma_get_object_is_builtin (object_p));
1389 
1390 #if ENABLED (JERRY_ES2015)
1391   if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH))
1392   {
1393     ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
1394     if (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp))
1395     {
1396       /* Initialize 'length' property */
1397       const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
1398       uint32_t len;
1399       if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
1400       {
1401         cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p;
1402         len = args_p->argument_end;
1403       }
1404       else
1405       {
1406         cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p;
1407         len = args_p->argument_end;
1408       }
1409 
1410       /* Set tag bit to represent initialized 'length' property */
1411       ECMA_SET_FIRST_BIT_TO_POINTER_TAG (ext_func_p->u.function.scope_cp);
1412       ecma_property_t *value_prop_p;
1413       ecma_property_value_t *value_p = ecma_create_named_data_property (object_p,
1414                                                                         property_name_p,
1415                                                                         ECMA_PROPERTY_FLAG_CONFIGURABLE,
1416                                                                         &value_prop_p);
1417       value_p->value = ecma_make_uint32_value (len);
1418       return value_prop_p;
1419     }
1420 
1421     return NULL;
1422   }
1423 #endif /* ENABLED (JERRY_ES2015) */
1424 
1425   if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_PROTOTYPE)
1426       && ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION)
1427   {
1428     return ecma_op_lazy_instantiate_prototype_object (object_p);
1429   }
1430 
1431   if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_CALLER)
1432       || ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_ARGUMENTS))
1433   {
1434     const ecma_compiled_code_t *bytecode_data_p;
1435     bytecode_data_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) object_p);
1436 
1437 #if ENABLED (JERRY_ES2015)
1438     if (!(bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE))
1439     {
1440       ecma_property_t *value_prop_p;
1441       /* The property_name_p argument contans the name. */
1442       ecma_property_value_t *value_p = ecma_create_named_data_property (object_p,
1443                                                                         property_name_p,
1444                                                                         ECMA_PROPERTY_FIXED,
1445                                                                         &value_prop_p);
1446       value_p->value = ECMA_VALUE_NULL;
1447       return value_prop_p;
1448     }
1449 #else /* !ENABLED (JERRY_ES2015) */
1450     if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE)
1451     {
1452       ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER);
1453 
1454       ecma_property_t *caller_prop_p;
1455       /* The property_name_p argument contans the name. */
1456       ecma_create_named_accessor_property (object_p,
1457                                            property_name_p,
1458                                            thrower_p,
1459                                            thrower_p,
1460                                            ECMA_PROPERTY_FIXED,
1461                                            &caller_prop_p);
1462       return caller_prop_p;
1463     }
1464 #endif /* ENABLED (JERRY_ES2015) */
1465 
1466   }
1467 
1468   return NULL;
1469 } /* ecma_op_function_try_to_lazy_instantiate_property */
1470 
1471 /**
1472  * Create specification defined non-configurable properties for external functions.
1473  *
1474  * See also:
1475  *          ECMA-262 v5, 15.3.4.5
1476  *
1477  * @return pointer property, if one was instantiated,
1478  *         NULL - otherwise.
1479  */
1480 ecma_property_t *
ecma_op_external_function_try_to_lazy_instantiate_property(ecma_object_t * object_p,ecma_string_t * property_name_p)1481 ecma_op_external_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**< object */
1482                                                             ecma_string_t *property_name_p) /**< property's name */
1483 {
1484   JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION);
1485 
1486   if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_PROTOTYPE))
1487   {
1488     return ecma_op_lazy_instantiate_prototype_object (object_p);
1489   }
1490 
1491   return NULL;
1492 } /* ecma_op_external_function_try_to_lazy_instantiate_property */
1493 
1494 /**
1495  * Create specification defined non-configurable properties for bound functions.
1496  *
1497  * See also:
1498  *          ECMA-262 v5, 15.3.4.5
1499  *
1500  * @return pointer property, if one was instantiated,
1501  *         NULL - otherwise.
1502  */
1503 ecma_property_t *
ecma_op_bound_function_try_to_lazy_instantiate_property(ecma_object_t * object_p,ecma_string_t * property_name_p)1504 ecma_op_bound_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**< object */
1505                                                          ecma_string_t *property_name_p) /**< property's name */
1506 {
1507   JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION);
1508 
1509   if (ecma_string_is_length (property_name_p))
1510   {
1511     ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) object_p;
1512     ecma_value_t args_len_or_this = bound_func_p->header.u.bound_function.args_len_or_this;
1513     ecma_integer_value_t length = 0;
1514     ecma_integer_value_t args_length = 1;
1515     uint8_t length_attributes;
1516 
1517     if (ecma_is_value_integer_number (args_len_or_this))
1518     {
1519       args_length = ecma_get_integer_from_value (args_len_or_this);
1520     }
1521 
1522 #if ENABLED (JERRY_ES2015)
1523     if (ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (bound_func_p->header.u.bound_function.target_function))
1524     {
1525       return NULL;
1526     }
1527 
1528     length_attributes = ECMA_PROPERTY_FLAG_CONFIGURABLE;
1529     length = bound_func_p->target_length - (args_length - 1);
1530 
1531     /* Set tag bit to represent initialized 'length' property */
1532     ECMA_SET_FIRST_BIT_TO_POINTER_TAG (bound_func_p->header.u.bound_function.target_function);
1533 #else /* !ENABLED (JERRY_ES2015) */
1534     length_attributes = ECMA_PROPERTY_FIXED;
1535 
1536     ecma_object_t *target_func_p;
1537     target_func_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t,
1538                                                                 bound_func_p->header.u.bound_function.target_function);
1539 
1540     if (ecma_object_get_class_name (target_func_p) == LIT_MAGIC_STRING_FUNCTION_UL)
1541     {
1542       /* The property_name_p argument contains the 'length' string. */
1543       ecma_value_t get_len_value = ecma_op_object_get (target_func_p, property_name_p);
1544 
1545       JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (get_len_value));
1546       JERRY_ASSERT (ecma_is_value_integer_number (get_len_value));
1547 
1548       length = ecma_get_integer_from_value (get_len_value) - (args_length - 1);
1549     }
1550 #endif /* ENABLED (JERRY_ES2015) */
1551 
1552     if (length < 0)
1553     {
1554       length = 0;
1555     }
1556 
1557     ecma_property_t *len_prop_p;
1558     ecma_property_value_t *len_prop_value_p = ecma_create_named_data_property (object_p,
1559                                                                                property_name_p,
1560                                                                                length_attributes,
1561                                                                                &len_prop_p);
1562 
1563     len_prop_value_p->value = ecma_make_integer_value (length);
1564     return len_prop_p;
1565   }
1566 
1567   if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_CALLER)
1568       || ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_ARGUMENTS))
1569   {
1570     ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER);
1571 
1572     ecma_property_t *caller_prop_p;
1573     /* The string_p argument contans the name. */
1574     ecma_create_named_accessor_property (object_p,
1575                                          property_name_p,
1576                                          thrower_p,
1577                                          thrower_p,
1578                                          ECMA_PROPERTY_FIXED,
1579                                          &caller_prop_p);
1580     return caller_prop_p;
1581   }
1582 
1583   return NULL;
1584 } /* ecma_op_bound_function_try_to_lazy_instantiate_property */
1585 
1586 /**
1587  * List names of a Function object's lazy instantiated properties,
1588  * adding them to corresponding string collections
1589  *
1590  * See also:
1591  *          ecma_op_function_try_to_lazy_instantiate_property
1592  */
1593 void
ecma_op_function_list_lazy_property_names(ecma_object_t * object_p,uint32_t opts,ecma_collection_t * main_collection_p,ecma_collection_t * non_enum_collection_p)1594 ecma_op_function_list_lazy_property_names (ecma_object_t *object_p, /**< functionobject */
1595                                            uint32_t opts, /**< listing options using flags
1596                                                            *   from ecma_list_properties_options_t */
1597                                            ecma_collection_t *main_collection_p, /**< 'main' collection */
1598                                            ecma_collection_t *non_enum_collection_p) /**< skipped
1599                                                                                       *   'non-enumerable'
1600                                                                                       *   collection */
1601 {
1602   JERRY_UNUSED (main_collection_p);
1603 
1604   ecma_collection_t *for_non_enumerable_p = (opts & ECMA_LIST_ENUMERABLE) ? non_enum_collection_p : main_collection_p;
1605 
1606 #if ENABLED (JERRY_ES2015)
1607   ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
1608   if (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp))
1609   {
1610     /* Unintialized 'length' property is non-enumerable (ECMA-262 v6, 19.2.4.1) */
1611     ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH));
1612   }
1613 #else /* !ENABLED (JERRY_ES2015) */
1614   /* 'length' property is non-enumerable (ECMA-262 v5, 13.2.5) */
1615   ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH));
1616 #endif /* ENABLED (JERRY_ES2015) */
1617 
1618   const ecma_compiled_code_t *bytecode_data_p;
1619   bytecode_data_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) object_p);
1620 
1621 #if ENABLED (JERRY_ES2015)
1622   if (bytecode_data_p->status_flags & (CBC_CODE_FLAGS_ARROW_FUNCTION | CBC_CODE_FLAGS_ACCESSOR))
1623   {
1624     return;
1625   }
1626 #endif /* ENABLED (JERRY_ES2015) */
1627 
1628   /* 'prototype' property is non-enumerable (ECMA-262 v5, 13.2.18) */
1629   ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_PROTOTYPE));
1630 
1631 #if ENABLED (JERRY_ES2015)
1632   bool append_caller_and_arguments = !(bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE);
1633 #else /* !ENABLED (JERRY_ES2015) */
1634   bool append_caller_and_arguments = (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE);
1635 #endif /* ENABLED (JERRY_ES2015) */
1636 
1637   if (append_caller_and_arguments)
1638   {
1639     /* 'caller' property is non-enumerable (ECMA-262 v5, 13.2.5) */
1640     ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_CALLER));
1641 
1642     /* 'arguments' property is non-enumerable (ECMA-262 v5, 13.2.5) */
1643     ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_ARGUMENTS));
1644   }
1645 } /* ecma_op_function_list_lazy_property_names */
1646 
1647 /**
1648  * List names of an External Function object's lazy instantiated properties,
1649  * adding them to corresponding string collections
1650  *
1651  * See also:
1652  *          ecma_op_external_function_try_to_lazy_instantiate_property
1653  */
1654 void
ecma_op_external_function_list_lazy_property_names(ecma_object_t * object_p,uint32_t opts,ecma_collection_t * main_collection_p,ecma_collection_t * non_enum_collection_p)1655 ecma_op_external_function_list_lazy_property_names (ecma_object_t *object_p, /**< function object */
1656                                                     uint32_t opts, /**< listing options using flags
1657                                                                     *   from ecma_list_properties_options_t */
1658                                                     ecma_collection_t *main_collection_p, /**< 'main' collection */
1659                                                     ecma_collection_t *non_enum_collection_p) /**< skipped
1660                                                                                                *   collection */
1661 {
1662   JERRY_UNUSED (main_collection_p);
1663 
1664   ecma_collection_t *for_non_enumerable_p = (opts & ECMA_LIST_ENUMERABLE) ? non_enum_collection_p : main_collection_p;
1665 
1666 #if !ENABLED (JERRY_ES2015)
1667   JERRY_UNUSED (object_p);
1668 #else /* ENABLED (JERRY_ES2015) */
1669   if (!ecma_op_ordinary_object_has_own_property (object_p, ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE)))
1670 #endif /* !ENABLED (JERRY_ES2015) */
1671   {
1672     /* 'prototype' property is non-enumerable (ECMA-262 v5, 13.2.18) */
1673     ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_PROTOTYPE));
1674   }
1675 } /* ecma_op_external_function_list_lazy_property_names */
1676 
1677 /**
1678  * List names of a Bound Function object's lazy instantiated properties,
1679  * adding them to corresponding string collections
1680  *
1681  * See also:
1682  *          ecma_op_bound_function_try_to_lazy_instantiate_property
1683  */
1684 void
ecma_op_bound_function_list_lazy_property_names(ecma_object_t * object_p,uint32_t opts,ecma_collection_t * main_collection_p,ecma_collection_t * non_enum_collection_p)1685 ecma_op_bound_function_list_lazy_property_names (ecma_object_t *object_p, /**< bound function object*/
1686                                                  uint32_t opts, /**< listing options using flags
1687                                                                  *   from ecma_list_properties_options_t */
1688                                                  ecma_collection_t *main_collection_p, /**< 'main' collection */
1689                                                  ecma_collection_t *non_enum_collection_p) /**< skipped
1690                                                                                             *   'non-enumerable'
1691                                                                                             *   collection */
1692 {
1693   JERRY_UNUSED (main_collection_p);
1694 
1695   ecma_collection_t *for_non_enumerable_p = (opts & ECMA_LIST_ENUMERABLE) ? non_enum_collection_p : main_collection_p;
1696 
1697 #if ENABLED (JERRY_ES2015)
1698   /* Unintialized 'length' property is non-enumerable (ECMA-262 v6, 19.2.4.1) */
1699   ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) object_p;
1700   if (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (bound_func_p->header.u.bound_function.target_function))
1701   {
1702     ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH));
1703   }
1704 #else /* !ENABLED (JERRY_ES2015) */
1705   JERRY_UNUSED (object_p);
1706   /* 'length' property is non-enumerable (ECMA-262 v5, 13.2.5) */
1707   ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH));
1708 #endif /* ENABLED (JERRY_ES2015) */
1709 
1710   /* 'caller' property is non-enumerable (ECMA-262 v5, 13.2.5) */
1711   ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_CALLER));
1712 
1713   /* 'arguments' property is non-enumerable (ECMA-262 v5, 13.2.5) */
1714   ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_ARGUMENTS));
1715 } /* ecma_op_bound_function_list_lazy_property_names */
1716 
1717 /**
1718  * @}
1719  * @}
1720  */
1721