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-builtins.h"
19#include "ecma-conversion.h"
20#include "ecma-exceptions.h"
21#include "ecma-gc.h"
22#include "ecma-globals.h"
23#include "ecma-helpers.h"
24#include "ecma-objects.h"
25#include "ecma-proxy-object.h"
26#include "ecma-objects-general.h"
27#include "jrt.h"
28#include "ecma-builtin-object.h"
29
30#define ECMA_BUILTINS_INTERNAL
31#include "ecma-builtins-internal.h"
32
33/**
34 * This object has a custom dispatch function.
35 */
36#define BUILTIN_CUSTOM_DISPATCH
37
38/**
39 * List of built-in routine identifiers.
40 */
41enum
42{
43  ECMA_OBJECT_ROUTINE_START = ECMA_BUILTIN_ID__COUNT - 1,
44
45  ECMA_OBJECT_ROUTINE_CREATE,
46  ECMA_OBJECT_ROUTINE_IS,
47  ECMA_OBJECT_ROUTINE_SET_PROTOTYPE_OF,
48
49  /* These should be in this order. */
50  ECMA_OBJECT_ROUTINE_DEFINE_PROPERTY,
51  ECMA_OBJECT_ROUTINE_DEFINE_PROPERTIES,
52
53  /* These should be in this order. */
54  ECMA_OBJECT_ROUTINE_ASSIGN,
55  ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_DESCRIPTOR,
56  ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_NAMES,
57  ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_SYMBOLS,
58  ECMA_OBJECT_ROUTINE_GET_PROTOTYPE_OF,
59  ECMA_OBJECT_ROUTINE_KEYS,
60
61  /* These should be in this order. */
62  ECMA_OBJECT_ROUTINE_FREEZE,
63  ECMA_OBJECT_ROUTINE_PREVENT_EXTENSIONS,
64  ECMA_OBJECT_ROUTINE_SEAL,
65
66  /* These should be in this order. */
67  ECMA_OBJECT_ROUTINE_IS_EXTENSIBLE,
68  ECMA_OBJECT_ROUTINE_IS_FROZEN,
69  ECMA_OBJECT_ROUTINE_IS_SEALED,
70};
71
72#define BUILTIN_INC_HEADER_NAME "ecma-builtin-object.inc.h"
73#define BUILTIN_UNDERSCORED_ID object
74#include "ecma-builtin-internal-routines-template.inc.h"
75
76/** \addtogroup ecma ECMA
77 * @{
78 *
79 * \addtogroup ecmabuiltins
80 * @{
81 *
82 * \addtogroup object ECMA Object object built-in
83 * @{
84 */
85
86/**
87 * Handle calling [[Call]] of built-in Object object
88 *
89 * @return ecma value
90 */
91ecma_value_t
92ecma_builtin_object_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */
93                                   ecma_length_t arguments_list_len) /**< number of arguments */
94{
95  JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
96
97  if (arguments_list_len == 0
98      || ecma_is_value_undefined (arguments_list_p[0])
99      || ecma_is_value_null (arguments_list_p[0]))
100  {
101    return ecma_builtin_object_dispatch_construct (arguments_list_p, arguments_list_len);
102  }
103
104  return ecma_op_to_object (arguments_list_p[0]);
105} /* ecma_builtin_object_dispatch_call */
106
107/**
108 * Handle calling [[Construct]] of built-in Object object
109 *
110 * @return ecma value
111 */
112ecma_value_t
113ecma_builtin_object_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */
114                                        ecma_length_t arguments_list_len) /**< number of arguments */
115{
116  JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
117
118  if (arguments_list_len == 0)
119  {
120    ecma_object_t *obj_p = ecma_op_create_object_object_noarg ();
121
122    return ecma_make_object_value (obj_p);
123  }
124
125  return ecma_op_create_object_object_arg (arguments_list_p[0]);
126} /* ecma_builtin_object_dispatch_construct */
127
128/**
129 * The Object object's 'getPrototypeOf' routine
130 *
131 * See also:
132 *          ECMA-262 v5, 15.2.3.2
133 *
134 * @return ecma value
135 *         Returned value must be freed with ecma_free_value.
136 */
137ecma_value_t
138ecma_builtin_object_object_get_prototype_of (ecma_object_t *obj_p) /**< routine's argument */
139{
140#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
141  if (ECMA_OBJECT_IS_PROXY (obj_p))
142  {
143    return ecma_proxy_object_get_prototype_of (obj_p);
144  }
145#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
146
147  jmem_cpointer_t proto_cp = ecma_op_ordinary_object_get_prototype_of (obj_p);
148
149  if (proto_cp != JMEM_CP_NULL)
150  {
151    ecma_object_t *prototype_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp);
152    ecma_ref_object (prototype_p);
153    return ecma_make_object_value (prototype_p);
154  }
155
156  return ECMA_VALUE_NULL;
157} /* ecma_builtin_object_object_get_prototype_of */
158
159#if ENABLED (JERRY_ES2015)
160/**
161 * The Object object's 'setPrototypeOf' routine
162 *
163 * See also:
164 *          ES2015 19.1.2.18
165 *
166 * @return ecma value
167 *         Returned value must be freed with ecma_free_value.
168 */
169ecma_value_t
170ecma_builtin_object_object_set_prototype_of (ecma_value_t arg1, /**< routine's first argument */
171                                             ecma_value_t arg2) /**< routine's second argument */
172{
173  /* 1., 2. */
174  if (ECMA_IS_VALUE_ERROR (ecma_op_check_object_coercible (arg1)))
175  {
176    return ECMA_VALUE_ERROR;
177  }
178
179  /* 3. */
180  if (!ecma_is_value_object (arg2) && !ecma_is_value_null (arg2))
181  {
182    return ecma_raise_type_error (ECMA_ERR_MSG ("proto is neither Object nor Null."));
183  }
184
185  /* 4. */
186  if (!ecma_is_value_object (arg1))
187  {
188    return ecma_copy_value (arg1);
189  }
190
191  ecma_object_t *obj_p = ecma_get_object_from_value (arg1);
192  ecma_value_t status;
193
194  /* 5. */
195#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
196  if (ECMA_OBJECT_IS_PROXY (obj_p))
197  {
198    status = ecma_proxy_object_set_prototype_of (obj_p, arg2);
199
200    if (ECMA_IS_VALUE_ERROR (status))
201    {
202      return status;
203    }
204  }
205  else
206  {
207#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
208    status = ecma_op_ordinary_object_set_prototype_of (obj_p, arg2);
209#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
210  }
211#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
212
213  if (ecma_is_value_false (status))
214  {
215    return ecma_raise_type_error (ECMA_ERR_MSG ("Cannot set [[Prototype]]."));
216  }
217
218  JERRY_ASSERT (ecma_is_value_true (status));
219  ecma_ref_object (obj_p);
220
221  return arg1;
222} /* ecma_builtin_object_object_set_prototype_of */
223
224/**
225 * The Object object's set __proto__ routine
226 *
227 * See also:
228 *          ECMA-262 v6, B.2.2.1.2
229 *
230 * @return ecma value
231 *         Returned value must be freed with ecma_free_value.
232 */
233ecma_value_t
234ecma_builtin_object_object_set_proto (ecma_value_t arg1, /**< routine's first argument */
235                                      ecma_value_t arg2) /**< routine's second argument */
236{
237  /* 1., 2. */
238  if (ECMA_IS_VALUE_ERROR (ecma_op_check_object_coercible (arg1)))
239  {
240    return ECMA_VALUE_ERROR;
241  }
242
243  /* 3. */
244  if (!ecma_is_value_object (arg2) && !ecma_is_value_null (arg2))
245  {
246    return ECMA_VALUE_UNDEFINED;
247  }
248
249  /* 4. */
250  if (!ecma_is_value_object (arg1))
251  {
252    return ECMA_VALUE_UNDEFINED;
253  }
254
255  ecma_object_t *obj_p = ecma_get_object_from_value (arg1);
256  ecma_value_t status;
257
258  /* 5. */
259#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
260  if (ECMA_OBJECT_IS_PROXY (obj_p))
261  {
262    status = ecma_proxy_object_set_prototype_of (obj_p, arg2);
263
264    if (ECMA_IS_VALUE_ERROR (status))
265    {
266      return status;
267    }
268  }
269  else
270  {
271#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
272    status = ecma_op_ordinary_object_set_prototype_of (obj_p, arg2);
273#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
274  }
275#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
276
277  if (ecma_is_value_false (status))
278  {
279    return ecma_raise_type_error (ECMA_ERR_MSG ("Cannot set [[Prototype]]."));
280  }
281
282  JERRY_ASSERT (ecma_is_value_true (status));
283
284  return ECMA_VALUE_UNDEFINED;
285} /* ecma_builtin_object_object_set_proto */
286#endif /* ENABLED (JERRY_ES2015) */
287
288/**
289 * The Object object's 'getOwnPropertyNames' routine
290 *
291 * See also:
292 *          ECMA-262 v5, 15.2.3.4
293 *
294 * @return ecma value
295 *         Returned value must be freed with ecma_free_value.
296 */
297static ecma_value_t
298ecma_builtin_object_object_get_own_property_names (ecma_object_t *obj_p) /**< routine's argument */
299{
300  return ecma_builtin_helper_object_get_properties (obj_p, ECMA_LIST_NO_OPTS);
301} /* ecma_builtin_object_object_get_own_property_names */
302
303#if ENABLED (JERRY_ES2015)
304
305/**
306 * The Object object's 'getOwnPropertySymbols' routine
307 *
308 * See also:
309 *          ECMA-262 v6, 19.1.2.7
310 *
311 * @return ecma value
312 *         Returned value must be freed with ecma_free_value.
313 */
314static ecma_value_t
315ecma_builtin_object_object_get_own_property_symbols (ecma_object_t *obj_p) /**< routine's argument */
316{
317  return ecma_builtin_helper_object_get_properties (obj_p, ECMA_LIST_SYMBOLS_ONLY);
318} /* ecma_builtin_object_object_get_own_property_symbols */
319
320#endif /* ENABLED (JERRY_ES2015) */
321
322/**
323 * SetIntegrityLevel operation
324 *
325 * See also:
326 *          ECMA-262 v6, 7.3.14
327 *
328 * @return ECMA_VALUE_ERROR - if the operation raised an error
329 *         ECMA_VALUE_{TRUE/FALSE} - depends on whether the integrity level has been set sucessfully
330 */
331static ecma_value_t
332ecma_builtin_object_set_integrity_level (ecma_object_t *obj_p, /**< object */
333                                         bool is_seal) /**< true - set "sealed"
334                                                        *   false - set "frozen" */
335{
336  /* 3. */
337#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
338  if (ECMA_OBJECT_IS_PROXY (obj_p))
339  {
340    ecma_value_t status = ecma_proxy_object_prevent_extensions (obj_p);
341
342    if (!ecma_is_value_true (status))
343    {
344      return status;
345    }
346  }
347  else
348  {
349#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
350    ecma_op_ordinary_object_prevent_extensions (obj_p);
351#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
352  }
353#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
354
355  /* 6. */
356  uint32_t opts = ECMA_LIST_CONVERT_FAST_ARRAYS;
357#if ENABLED (JERRY_ES2015)
358  opts |= ECMA_LIST_SYMBOLS;
359#endif /* ENABLED (JERRY_ES2015) */
360
361  ecma_collection_t *props_p = ecma_op_object_get_property_names (obj_p, opts);
362
363#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
364  if (props_p == NULL)
365  {
366    return ECMA_VALUE_ERROR;
367  }
368#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
369
370  ecma_value_t *buffer_p = props_p->buffer_p;
371
372  if (is_seal)
373  {
374    /* 8.a */
375    for (uint32_t i = 0; i < props_p->item_count; i++)
376    {
377      ecma_string_t *property_name_p = ecma_get_prop_name_from_value (buffer_p[i]);
378
379      ecma_property_descriptor_t prop_desc;
380      ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, property_name_p, &prop_desc);
381
382#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
383      if (ECMA_IS_VALUE_ERROR (status))
384      {
385        break;
386      }
387#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
388
389      if (ecma_is_value_false (status))
390      {
391        continue;
392      }
393
394      prop_desc.flags &= (uint16_t) ~ECMA_PROP_IS_CONFIGURABLE;
395      prop_desc.flags |= ECMA_PROP_IS_THROW;
396
397      /* 8.a.i */
398      ecma_value_t define_own_prop_ret = ecma_op_object_define_own_property (obj_p,
399                                                                             property_name_p,
400                                                                             &prop_desc);
401
402      ecma_free_property_descriptor (&prop_desc);
403
404      /* 8.a.ii */
405      if (ECMA_IS_VALUE_ERROR (define_own_prop_ret))
406      {
407        ecma_collection_free (props_p);
408        return define_own_prop_ret;
409      }
410
411      ecma_free_value (define_own_prop_ret);
412    }
413  }
414  else
415  {
416    /* 9.a */
417    for (uint32_t i = 0; i < props_p->item_count; i++)
418    {
419      ecma_string_t *property_name_p = ecma_get_prop_name_from_value (buffer_p[i]);
420
421      /* 9.1 */
422      ecma_property_descriptor_t prop_desc;
423      ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, property_name_p, &prop_desc);
424
425#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
426      if (ECMA_IS_VALUE_ERROR (status))
427      {
428        break;
429      }
430#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
431
432      if (ecma_is_value_false (status))
433      {
434        continue;
435      }
436
437      /* 9.2 */
438      if ((prop_desc.flags & (ECMA_PROP_IS_WRITABLE_DEFINED | ECMA_PROP_IS_WRITABLE))
439          == (ECMA_PROP_IS_WRITABLE_DEFINED | ECMA_PROP_IS_WRITABLE))
440      {
441        prop_desc.flags &= (uint16_t) ~ECMA_PROP_IS_WRITABLE;
442      }
443
444      prop_desc.flags &= (uint16_t) ~ECMA_PROP_IS_CONFIGURABLE;
445      prop_desc.flags |= ECMA_PROP_IS_THROW;
446
447      /* 9.3 */
448      ecma_value_t define_own_prop_ret = ecma_op_object_define_own_property (obj_p,
449                                                                             property_name_p,
450                                                                             &prop_desc);
451
452      ecma_free_property_descriptor (&prop_desc);
453
454      /* 9.4 */
455      if (ECMA_IS_VALUE_ERROR (define_own_prop_ret))
456      {
457        ecma_collection_free (props_p);
458        return define_own_prop_ret;
459      }
460
461      ecma_free_value (define_own_prop_ret);
462    }
463
464  }
465
466  ecma_collection_free (props_p);
467
468  return ECMA_VALUE_TRUE;
469} /* ecma_builtin_object_set_integrity_level */
470
471/**
472 * The Object object's 'seal' routine
473 *
474 * See also:
475 *          ECMA-262 v5, 15.2.3.8
476 *
477 * @return ecma value
478 *         Returned value must be freed with ecma_free_value.
479 */
480static ecma_value_t
481ecma_builtin_object_object_seal (ecma_object_t *obj_p) /**< routine's argument */
482{
483  ecma_value_t status = ecma_builtin_object_set_integrity_level (obj_p, true);
484
485  if (ECMA_IS_VALUE_ERROR (status))
486  {
487    return status;
488  }
489
490#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
491  if (ecma_is_value_false (status))
492  {
493    return ecma_raise_type_error (ECMA_ERR_MSG ("Object cannot be sealed."));
494  }
495#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
496
497  /* 4. */
498  ecma_ref_object (obj_p);
499  return ecma_make_object_value (obj_p);
500} /* ecma_builtin_object_object_seal */
501
502/**
503 * The Object object's 'freeze' routine
504 *
505 * See also:
506 *          ECMA-262 v5, 15.2.3.9
507 *
508 * @return ecma value
509 *         Returned value must be freed with ecma_free_value.
510 */
511static ecma_value_t
512ecma_builtin_object_object_freeze (ecma_object_t *obj_p) /**< routine's argument */
513{
514  ecma_value_t status = ecma_builtin_object_set_integrity_level (obj_p, false);
515
516  if (ECMA_IS_VALUE_ERROR (status))
517  {
518    return status;
519  }
520
521#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
522  if (ecma_is_value_false (status))
523  {
524    return ecma_raise_type_error (ECMA_ERR_MSG ("Object cannot be frozen."));
525  }
526#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
527
528  /* 4. */
529  ecma_ref_object (obj_p);
530  return ecma_make_object_value (obj_p);
531} /* ecma_builtin_object_object_freeze */
532
533/**
534 * The Object object's 'preventExtensions' routine
535 *
536 * See also:
537 *          ECMA-262 v5, 15.2.3.10
538 *
539 * @return ecma value
540 *         Returned value must be freed with ecma_free_value.
541 */
542ecma_value_t
543ecma_builtin_object_object_prevent_extensions (ecma_object_t *obj_p) /**< routine's argument */
544{
545#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
546  if (ECMA_OBJECT_IS_PROXY (obj_p))
547  {
548    ecma_value_t status = ecma_proxy_object_prevent_extensions (obj_p);
549
550    if (ECMA_IS_VALUE_ERROR (status))
551    {
552      return status;
553    }
554
555    if (ecma_is_value_false (status))
556    {
557      return ecma_raise_type_error (ECMA_ERR_MSG ("Cannot set [[Extensible]] property of the object."));
558    }
559
560    JERRY_ASSERT (ecma_is_value_true (status));
561  }
562  else
563  {
564#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
565    ecma_op_ordinary_object_prevent_extensions (obj_p);
566#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
567  }
568#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
569  ecma_ref_object (obj_p);
570
571  return ecma_make_object_value (obj_p);
572} /* ecma_builtin_object_object_prevent_extensions */
573
574/**
575 * The Object object's 'isSealed' and 'isFrozen' routines
576 *
577 * See also:
578 *         ECMA-262 v5, 15.2.3.11
579 *         ECMA-262 v5, 15.2.3.12
580 *
581 * @return ecma value
582 *         Returned value must be freed with ecma_free_value.
583 */
584static ecma_value_t
585ecma_builtin_object_test_integrity_level (ecma_object_t *obj_p, /**< routine's argument */
586                                          int mode) /**< routine mode */
587{
588  JERRY_ASSERT (mode == ECMA_OBJECT_ROUTINE_IS_FROZEN || mode == ECMA_OBJECT_ROUTINE_IS_SEALED);
589
590  /* 3. */
591  bool is_extensible;
592#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
593  if (ECMA_OBJECT_IS_PROXY (obj_p))
594  {
595    ecma_value_t status = ecma_proxy_object_is_extensible (obj_p);
596
597    if (ECMA_IS_VALUE_ERROR (status))
598    {
599      return status;
600    }
601
602    is_extensible = ecma_is_value_true (status);
603  }
604  else
605  {
606#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
607    is_extensible = ecma_op_ordinary_object_is_extensible (obj_p);
608#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
609  }
610#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
611
612  if (is_extensible)
613  {
614    return ECMA_VALUE_FALSE;
615  }
616
617  /* the value can be updated in the loop below */
618  ecma_value_t ret_value = ECMA_VALUE_TRUE;
619
620  /* 2. */
621  ecma_collection_t *props_p = ecma_op_object_get_property_names (obj_p, ECMA_LIST_NO_OPTS);
622
623#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
624  if (props_p == NULL)
625  {
626    return ECMA_VALUE_ERROR;
627  }
628#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
629
630  ecma_value_t *buffer_p = props_p->buffer_p;
631
632  for (uint32_t i = 0; i < props_p->item_count; i++)
633  {
634    ecma_string_t *property_name_p = ecma_get_string_from_value (buffer_p[i]);
635
636    /* 2.a */
637    ecma_property_descriptor_t prop_desc;
638    ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, property_name_p, &prop_desc);
639
640#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
641    if (ECMA_IS_VALUE_ERROR (status))
642    {
643      ret_value = status;
644      break;
645    }
646#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
647
648    if (ecma_is_value_false (status))
649    {
650      continue;
651    }
652
653    bool is_writable_data = ((prop_desc.flags & (ECMA_PROP_IS_VALUE_DEFINED | ECMA_PROP_IS_WRITABLE))
654                             == (ECMA_PROP_IS_VALUE_DEFINED | ECMA_PROP_IS_WRITABLE));
655    bool is_configurable = (prop_desc.flags & ECMA_PROP_IS_CONFIGURABLE);
656
657    ecma_free_property_descriptor (&prop_desc);
658
659    /* 2.b for isFrozen */
660    /* 2.b for isSealed, 2.c for isFrozen */
661    if ((mode == ECMA_OBJECT_ROUTINE_IS_FROZEN && is_writable_data)
662        || is_configurable)
663    {
664      ret_value = ECMA_VALUE_FALSE;
665      break;
666    }
667  }
668
669  ecma_collection_free (props_p);
670
671  return ret_value;
672} /* ecma_builtin_object_test_integrity_level */
673
674/**
675 * The Object object's 'isExtensible' routine
676 *
677 * See also:
678 *          ECMA-262 v5, 15.2.3.13
679 *
680 * @return ecma value
681 *         Returned value must be freed with ecma_free_value.
682 */
683ecma_value_t
684ecma_builtin_object_object_is_extensible (ecma_object_t *obj_p) /**< routine's argument */
685{
686#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
687  if (ECMA_OBJECT_IS_PROXY (obj_p))
688  {
689    return ecma_proxy_object_is_extensible (obj_p);
690  }
691#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
692
693  return ecma_make_boolean_value (ecma_op_ordinary_object_is_extensible (obj_p));
694} /* ecma_builtin_object_object_is_extensible */
695
696/**
697 * The Object object's 'keys' routine
698 *
699 * See also:
700 *          ECMA-262 v5, 15.2.3.14
701 *
702 * @return ecma value
703 *         Returned value must be freed with ecma_free_value.
704 */
705static ecma_value_t
706ecma_builtin_object_object_keys (ecma_object_t *obj_p) /**< routine's argument */
707{
708  return ecma_builtin_helper_object_get_properties (obj_p, ECMA_LIST_ENUMERABLE);
709} /* ecma_builtin_object_object_keys */
710
711/**
712 * The Object object's 'getOwnPropertyDescriptor' routine
713 *
714 * See also:
715 *          ECMA-262 v5, 15.2.3.3
716 *
717 * @return ecma value
718 *         Returned value must be freed with ecma_free_value.
719 */
720ecma_value_t
721ecma_builtin_object_object_get_own_property_descriptor (ecma_object_t *obj_p, /**< routine's first argument */
722                                                        ecma_string_t *name_str_p) /**< routine's second argument */
723{
724  /* 3. */
725  ecma_property_descriptor_t prop_desc;
726
727  ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, name_str_p, &prop_desc);
728
729#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
730  if (ECMA_IS_VALUE_ERROR (status))
731  {
732    return status;
733  }
734#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
735
736  if (ecma_is_value_true (status))
737  {
738    /* 4. */
739    ecma_object_t *desc_obj_p = ecma_op_from_property_descriptor (&prop_desc);
740
741    ecma_free_property_descriptor (&prop_desc);
742
743    return ecma_make_object_value (desc_obj_p);
744  }
745
746  return ECMA_VALUE_UNDEFINED;
747} /* ecma_builtin_object_object_get_own_property_descriptor */
748
749/**
750 * The Object object's 'defineProperties' routine
751 *
752 * See also:
753 *          ECMA-262 v5, 15.2.3.7
754 *
755 * @return ecma value
756 *         Returned value must be freed with ecma_free_value.
757 */
758static ecma_value_t
759ecma_builtin_object_object_define_properties (ecma_object_t *obj_p, /**< routine's first argument */
760                                              ecma_value_t arg2) /**< routine's second argument */
761{
762  /* 2. */
763  ecma_value_t props = ecma_op_to_object (arg2);
764
765  if (ECMA_IS_VALUE_ERROR (props))
766  {
767    return props;
768  }
769
770  ecma_object_t *props_p = ecma_get_object_from_value (props);
771  /* 3. */
772  ecma_collection_t *prop_names_p = ecma_op_object_get_property_names (props_p, ECMA_LIST_CONVERT_FAST_ARRAYS
773                                                                                | ECMA_LIST_ENUMERABLE);
774  ecma_value_t ret_value = ECMA_VALUE_ERROR;
775
776#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
777  if (prop_names_p == NULL)
778  {
779    ecma_deref_object (props_p);
780    return ret_value;
781  }
782#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
783
784  ecma_value_t *buffer_p = prop_names_p->buffer_p;
785
786  /* 4. */
787  JMEM_DEFINE_LOCAL_ARRAY (property_descriptors, prop_names_p->item_count, ecma_property_descriptor_t);
788  uint32_t property_descriptor_number = 0;
789
790  for (uint32_t i = 0; i < prop_names_p->item_count; i++)
791  {
792    /* 5.a */
793    ecma_value_t desc_obj = ecma_op_object_get (props_p, ecma_get_string_from_value (buffer_p[i]));
794
795    if (ECMA_IS_VALUE_ERROR (desc_obj))
796    {
797      goto cleanup;
798    }
799
800    /* 5.b */
801    ecma_value_t conv_result = ecma_op_to_property_descriptor (desc_obj,
802                                                               &property_descriptors[property_descriptor_number]);
803
804    property_descriptors[property_descriptor_number].flags |= ECMA_PROP_IS_THROW;
805
806    ecma_free_value (desc_obj);
807
808    if (ECMA_IS_VALUE_ERROR (conv_result))
809    {
810      goto cleanup;
811    }
812
813    property_descriptor_number++;
814
815    ecma_free_value (conv_result);
816  }
817
818  /* 6. */
819  buffer_p = prop_names_p->buffer_p;
820
821  for (uint32_t i = 0; i < prop_names_p->item_count; i++)
822  {
823    ecma_value_t define_own_prop_ret =  ecma_op_object_define_own_property (obj_p,
824                                                                            ecma_get_string_from_value (buffer_p[i]),
825                                                                            &property_descriptors[i]);
826    if (ECMA_IS_VALUE_ERROR (define_own_prop_ret))
827    {
828      goto cleanup;
829    }
830
831    ecma_free_value (define_own_prop_ret);
832  }
833
834  ecma_ref_object (obj_p);
835  ret_value = ecma_make_object_value (obj_p);
836
837cleanup:
838  /* Clean up. */
839  for (uint32_t index = 0;
840       index < property_descriptor_number;
841       index++)
842  {
843    ecma_free_property_descriptor (&property_descriptors[index]);
844  }
845
846  JMEM_FINALIZE_LOCAL_ARRAY (property_descriptors);
847
848  ecma_collection_free (prop_names_p);
849
850  ecma_deref_object (props_p);
851
852  return ret_value;
853} /* ecma_builtin_object_object_define_properties */
854
855/**
856 * The Object object's 'create' routine
857 *
858 * See also:
859 *          ECMA-262 v5, 15.2.3.5
860 *
861 * @return ecma value
862 *         Returned value must be freed with ecma_free_value.
863 */
864static ecma_value_t
865ecma_builtin_object_object_create (ecma_value_t arg1, /**< routine's first argument */
866                                   ecma_value_t arg2) /**< routine's second argument */
867{
868  /* 1. */
869  if (!ecma_is_value_object (arg1) && !ecma_is_value_null (arg1))
870  {
871    return ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an object."));
872  }
873
874  ecma_object_t *obj_p = NULL;
875
876  if (!ecma_is_value_null (arg1))
877  {
878    obj_p = ecma_get_object_from_value (arg1);
879  }
880  /* 2-3. */
881  ecma_object_t *result_obj_p = ecma_op_create_object_object_noarg_and_set_prototype (obj_p);
882
883  /* 4. */
884  if (!ecma_is_value_undefined (arg2))
885  {
886    ecma_value_t obj = ecma_builtin_object_object_define_properties (result_obj_p, arg2);
887
888    if (ECMA_IS_VALUE_ERROR (obj))
889    {
890      ecma_deref_object (result_obj_p);
891      return obj;
892    }
893
894    ecma_free_value (obj);
895  }
896
897  /* 5. */
898  return ecma_make_object_value (result_obj_p);
899} /* ecma_builtin_object_object_create */
900
901/**
902 * The Object object's 'defineProperty' routine
903 *
904 * See also:
905 *          ECMA-262 v5, 15.2.3.6
906 *
907 * @return ecma value
908 *         Returned value must be freed with ecma_free_value.
909 */
910ecma_value_t
911ecma_builtin_object_object_define_property (ecma_object_t *obj_p, /**< routine's first argument */
912                                            ecma_string_t *name_str_p, /**< routine's second argument */
913                                            ecma_value_t arg3) /**< routine's third argument */
914{
915  ecma_property_descriptor_t prop_desc;
916
917  ecma_value_t conv_result = ecma_op_to_property_descriptor (arg3, &prop_desc);
918
919  if (ECMA_IS_VALUE_ERROR (conv_result))
920  {
921    return conv_result;
922  }
923
924  prop_desc.flags |= ECMA_PROP_IS_THROW;
925
926  ecma_value_t define_own_prop_ret = ecma_op_object_define_own_property (obj_p,
927                                                                         name_str_p,
928                                                                         &prop_desc);
929
930  ecma_free_property_descriptor (&prop_desc);
931  ecma_free_value (conv_result);
932
933  if (ECMA_IS_VALUE_ERROR (define_own_prop_ret))
934  {
935    return define_own_prop_ret;
936  }
937
938  ecma_ref_object (obj_p);
939  ecma_free_value (define_own_prop_ret);
940
941  return ecma_make_object_value (obj_p);
942} /* ecma_builtin_object_object_define_property */
943
944#if ENABLED (JERRY_ES2015)
945
946/**
947 * The Object object's 'assign' routine
948 *
949 * See also:
950 *          ECMA-262 v6, 19.1.2.1
951 *
952 * @return ecma value
953 *         Returned value must be freed with ecma_free_value.
954 */
955static ecma_value_t
956ecma_builtin_object_object_assign (ecma_object_t *target_p, /**< target object */
957                                   const ecma_value_t arguments_list_p[], /**< arguments list */
958                                   ecma_length_t arguments_list_len) /**< number of arguments */
959{
960  ecma_value_t ret_value = ECMA_VALUE_EMPTY;
961
962  /* 4-5. */
963  for (uint32_t i = 0; i < arguments_list_len && ecma_is_value_empty (ret_value); i++)
964  {
965    ecma_value_t next_source = arguments_list_p[i];
966
967    /* 5.a */
968    if (ecma_is_value_undefined (next_source) || ecma_is_value_null (next_source))
969    {
970      continue;
971    }
972
973    /* 5.b.i */
974    ecma_value_t from_value = ecma_op_to_object (next_source);
975    /* null and undefied cases are handled above, so this must be a valid object */
976    JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (from_value));
977
978    ecma_object_t *from_obj_p = ecma_get_object_from_value (from_value);
979
980    /* 5.b.iii */
981    ecma_collection_t *props_p = ecma_op_object_get_property_names (from_obj_p, ECMA_LIST_CONVERT_FAST_ARRAYS
982                                                                                | ECMA_LIST_ENUMERABLE
983                                                                                | ECMA_LIST_SYMBOLS);
984#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
985    if (props_p == NULL)
986    {
987      ecma_deref_object (from_obj_p);
988      return ECMA_VALUE_ERROR;
989    }
990#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
991
992    ecma_value_t *buffer_p = props_p->buffer_p;
993
994    for (uint32_t j = 0; (j < props_p->item_count) && ecma_is_value_empty (ret_value); j++)
995    {
996      ecma_string_t *property_name_p = ecma_get_prop_name_from_value (buffer_p[j]);
997
998      /* 5.c.i-ii */
999      ecma_property_descriptor_t prop_desc;
1000      ecma_value_t desc_status = ecma_op_object_get_own_property_descriptor (from_obj_p, property_name_p, &prop_desc);
1001
1002#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
1003      if (ECMA_IS_VALUE_ERROR (desc_status))
1004      {
1005        ret_value = desc_status;
1006        break;
1007      }
1008#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
1009
1010      if (ecma_is_value_false (desc_status))
1011      {
1012        continue;
1013      }
1014
1015      /* 5.c.iii */
1016      if ((prop_desc.flags & ECMA_PROP_IS_ENUMERABLE)
1017          && (((prop_desc.flags & ECMA_PROP_IS_VALUE_DEFINED) && !ecma_is_value_undefined (prop_desc.value))
1018              || (prop_desc.flags & ECMA_PROP_IS_GET_DEFINED)))
1019      {
1020        /* 5.c.iii.1 */
1021        ecma_value_t prop_value = ecma_op_object_get (from_obj_p, property_name_p);
1022
1023        /* 5.c.iii.2 */
1024        if (ECMA_IS_VALUE_ERROR (prop_value))
1025        {
1026          ret_value = prop_value;
1027        }
1028        else
1029        {
1030          /* 5.c.iii.3 */
1031          ecma_value_t status = ecma_op_object_put (target_p, property_name_p, prop_value, true);
1032
1033          /* 5.c.iii.4 */
1034          if (ECMA_IS_VALUE_ERROR (status))
1035          {
1036            ret_value = status;
1037          }
1038        }
1039
1040        ecma_free_value (prop_value);
1041        ecma_free_property_descriptor (&prop_desc);
1042      }
1043    }
1044
1045    ecma_deref_object (from_obj_p);
1046    ecma_collection_free (props_p);
1047  }
1048
1049  /* 6. */
1050  if (ecma_is_value_empty (ret_value))
1051  {
1052    ecma_ref_object (target_p);
1053    return ecma_make_object_value (target_p);
1054  }
1055
1056  return ret_value;
1057} /* ecma_builtin_object_object_assign */
1058
1059/**
1060 * The Object object's 'is' routine
1061 *
1062 * See also:
1063 *          ECMA-262 v6, 19.1.2.10
1064 *
1065 * @return ecma value
1066 *         Returned value must be freed with ecma_free_value.
1067 */
1068static ecma_value_t
1069ecma_builtin_object_object_is (ecma_value_t arg1, /**< routine's first argument */
1070                               ecma_value_t arg2) /**< routine's second argument */
1071{
1072  return ecma_op_same_value (arg1, arg2) ? ECMA_VALUE_TRUE : ECMA_VALUE_FALSE;
1073} /* ecma_builtin_object_object_is */
1074
1075#endif /* ENABLED (JERRY_ES2015) */
1076
1077/**
1078 * Dispatcher of the built-in's routines
1079 *
1080 * @return ecma value
1081 *         Returned value must be freed with ecma_free_value.
1082 */
1083ecma_value_t
1084ecma_builtin_object_dispatch_routine (uint16_t builtin_routine_id, /**< built-in wide routine
1085                                                                    *   identifier */
1086                                      ecma_value_t this_arg, /**< 'this' argument value */
1087                                      const ecma_value_t arguments_list_p[], /**< list of arguments
1088                                                                              *   passed to routine */
1089                                      ecma_length_t arguments_number) /**< length of arguments' list */
1090{
1091  JERRY_UNUSED (this_arg);
1092  JERRY_UNUSED (arguments_list_p);
1093  JERRY_UNUSED (arguments_number);
1094
1095  ecma_value_t arg1 = arguments_list_p[0];
1096  ecma_value_t arg2 = arguments_list_p[1];
1097
1098  /* No specialization for the arguments */
1099  switch (builtin_routine_id)
1100  {
1101    case ECMA_OBJECT_ROUTINE_CREATE:
1102    {
1103      return ecma_builtin_object_object_create (arg1, arg2);
1104    }
1105#if ENABLED (JERRY_ES2015)
1106    case ECMA_OBJECT_ROUTINE_SET_PROTOTYPE_OF:
1107    {
1108      return ecma_builtin_object_object_set_prototype_of (arg1, arg2);
1109    }
1110    case ECMA_OBJECT_ROUTINE_IS:
1111    {
1112      return ecma_builtin_object_object_is (arg1, arg2);
1113    }
1114#endif /* ENABLED (JERRY_ES2015) */
1115    default:
1116    {
1117      break;
1118    }
1119  }
1120
1121  ecma_object_t *obj_p;
1122#if !ENABLED (JERRY_ES2015)
1123  if (!ecma_is_value_object (arg1))
1124  {
1125    return ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an object."));
1126  }
1127#endif /* !ENABLED (JERRY_ES2015) */
1128
1129  if (builtin_routine_id <= ECMA_OBJECT_ROUTINE_DEFINE_PROPERTIES)
1130  {
1131#if ENABLED (JERRY_ES2015)
1132    if (!ecma_is_value_object (arg1))
1133    {
1134      return ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an object."));
1135    }
1136#endif /* ENABLED (JERRY_ES2015) */
1137
1138    obj_p = ecma_get_object_from_value (arg1);
1139
1140    if (builtin_routine_id == ECMA_OBJECT_ROUTINE_DEFINE_PROPERTY)
1141    {
1142      ecma_string_t *prop_name_p = ecma_op_to_prop_name (arg2);
1143
1144      if (prop_name_p == NULL)
1145      {
1146        return ECMA_VALUE_ERROR;
1147      }
1148
1149      ecma_value_t result = ecma_builtin_object_object_define_property (obj_p, prop_name_p, arguments_list_p[2]);
1150
1151      ecma_deref_ecma_string (prop_name_p);
1152      return result;
1153    }
1154
1155    JERRY_ASSERT (builtin_routine_id == ECMA_OBJECT_ROUTINE_DEFINE_PROPERTIES);
1156    return ecma_builtin_object_object_define_properties (obj_p, arg2);
1157  }
1158  else if (builtin_routine_id <= ECMA_OBJECT_ROUTINE_KEYS)
1159  {
1160#if ENABLED (JERRY_ES2015)
1161    ecma_value_t object = ecma_op_to_object (arg1);
1162    if (ECMA_IS_VALUE_ERROR (object))
1163    {
1164      return object;
1165    }
1166
1167    obj_p = ecma_get_object_from_value (object);
1168#else /* !ENABLED (JERRY_ES2015) */
1169    obj_p = ecma_get_object_from_value (arg1);
1170#endif /* ENABLED (JERRY_ES2015) */
1171
1172    ecma_value_t result;
1173    switch (builtin_routine_id)
1174    {
1175      case ECMA_OBJECT_ROUTINE_GET_PROTOTYPE_OF:
1176      {
1177        result = ecma_builtin_object_object_get_prototype_of (obj_p);
1178        break;
1179      }
1180      case ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_NAMES:
1181      {
1182        result = ecma_builtin_object_object_get_own_property_names (obj_p);
1183        break;
1184      }
1185#if ENABLED (JERRY_ES2015)
1186      case ECMA_OBJECT_ROUTINE_ASSIGN:
1187      {
1188        result = ecma_builtin_object_object_assign (obj_p, arguments_list_p + 1, arguments_number - 1);
1189        break;
1190      }
1191      case ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_SYMBOLS:
1192      {
1193        result = ecma_builtin_object_object_get_own_property_symbols (obj_p);
1194        break;
1195      }
1196#endif /* ENABLED (JERRY_ES2015) */
1197      case ECMA_OBJECT_ROUTINE_KEYS:
1198      {
1199        result = ecma_builtin_object_object_keys (obj_p);
1200        break;
1201      }
1202      case ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_DESCRIPTOR:
1203      {
1204        ecma_string_t *prop_name_p = ecma_op_to_prop_name (arg2);
1205
1206        if (prop_name_p == NULL)
1207        {
1208          result = ECMA_VALUE_ERROR;
1209          break;
1210        }
1211
1212        result = ecma_builtin_object_object_get_own_property_descriptor (obj_p, prop_name_p);
1213        ecma_deref_ecma_string (prop_name_p);
1214        break;
1215      }
1216      default:
1217      {
1218        JERRY_UNREACHABLE ();
1219      }
1220    }
1221
1222#if ENABLED (JERRY_ES2015)
1223    ecma_deref_object (obj_p);
1224#endif /* ENABLED (JERRY_ES2015) */
1225    return result;
1226  }
1227  else if (builtin_routine_id <= ECMA_OBJECT_ROUTINE_SEAL)
1228  {
1229#if ENABLED (JERRY_ES2015)
1230    if (!ecma_is_value_object (arg1))
1231    {
1232      return ecma_copy_value (arg1);
1233    }
1234#endif /* ENABLED (JERRY_ES2015) */
1235
1236    obj_p = ecma_get_object_from_value (arg1);
1237    switch (builtin_routine_id)
1238    {
1239      case ECMA_OBJECT_ROUTINE_SEAL:
1240      {
1241        return ecma_builtin_object_object_seal (obj_p);
1242      }
1243      case ECMA_OBJECT_ROUTINE_FREEZE:
1244      {
1245        return ecma_builtin_object_object_freeze (obj_p);
1246      }
1247      case ECMA_OBJECT_ROUTINE_PREVENT_EXTENSIONS:
1248      {
1249        return ecma_builtin_object_object_prevent_extensions (obj_p);
1250      }
1251      default:
1252      {
1253        JERRY_UNREACHABLE ();
1254      }
1255    }
1256  }
1257  else
1258  {
1259    JERRY_ASSERT (builtin_routine_id <= ECMA_OBJECT_ROUTINE_IS_SEALED);
1260#if ENABLED (JERRY_ES2015)
1261    if (!ecma_is_value_object (arg1))
1262    {
1263      return ecma_make_boolean_value (builtin_routine_id != ECMA_OBJECT_ROUTINE_IS_EXTENSIBLE);
1264    }
1265#endif /* ENABLED (JERRY_ES2015) */
1266
1267    obj_p = ecma_get_object_from_value (arg1);
1268    switch (builtin_routine_id)
1269    {
1270      case ECMA_OBJECT_ROUTINE_IS_SEALED:
1271      case ECMA_OBJECT_ROUTINE_IS_FROZEN:
1272      {
1273        return ecma_builtin_object_test_integrity_level (obj_p, builtin_routine_id);
1274      }
1275      case ECMA_OBJECT_ROUTINE_IS_EXTENSIBLE:
1276      {
1277        return ecma_builtin_object_object_is_extensible (obj_p);
1278      }
1279      default:
1280      {
1281        JERRY_UNREACHABLE ();
1282      }
1283    }
1284  }
1285} /* ecma_builtin_object_dispatch_routine */
1286
1287/**
1288 * @}
1289 * @}
1290 * @}
1291 */
1292