ecma-objects.c 80.6 KB
Newer Older
1
/* Copyright JS Foundation and other contributors, http://js.foundation
2 3 4 5 6 7 8 9 10 11 12 13 14 15
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

16
#include "ecma-array-object.h"
17
#include "ecma-builtins.h"
18
#include "ecma-builtin-helpers.h"
19
#include "ecma-exceptions.h"
20
#include "ecma-gc.h"
21
#include "ecma-globals.h"
22
#include "ecma-function-object.h"
23
#include "ecma-lex-env.h"
24
#include "ecma-string-object.h"
25
#include "ecma-objects-arguments.h"
26
#include "ecma-objects-general.h"
27
#include "ecma-objects.h"
28
#include "jcontext.h"
29

30
#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
31
#include "ecma-typedarray-object.h"
32 33
#include "ecma-arraybuffer-object.h"
#include "ecma-try-catch-macro.h"
34
#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
35

36
/** \addtogroup ecma ECMA
37
 * @{
38
 *
39 40 41 42
 * \addtogroup ecmaobjectsinternalops ECMA objects' operations
 * @{
 */

Z
Zoltan Herczeg 已提交
43 44 45 46 47
/**
 * Hash bitmap size for ecma objects
 */
#define ECMA_OBJECT_HASH_BITMAP_SIZE 256

48 49
/**
 * Assert that specified object type value is valid
50
 *
51
 * @param type object's implementation-defined type
52
 */
53 54
#ifndef JERRY_NDEBUG
#define JERRY_ASSERT_OBJECT_TYPE_IS_VALID(type) \
55
  JERRY_ASSERT (type < ECMA_OBJECT_TYPE__MAX);
56 57 58
#else /* JERRY_NDEBUG */
#define JERRY_ASSERT_OBJECT_TYPE_IS_VALID(type)
#endif /* !JERRY_NDEBUG */
Z
Zoltan Herczeg 已提交
59

60
/**
61 62 63 64
 * [[GetOwnProperty]] ecma object's operation
 *
 * See also:
 *          ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
65 66
 *
 * @return pointer to a property - if it exists,
67
 *         NULL (i.e. ecma-undefined) - otherwise.
68
 */
69 70 71 72 73
ecma_property_t
ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */
                                 ecma_string_t *property_name_p, /**< property name */
                                 ecma_property_ref_t *property_ref_p, /**< property reference */
                                 uint32_t options) /**< option bits */
74
{
75 76 77
  JERRY_ASSERT (object_p != NULL
                && !ecma_is_lexical_environment (object_p));
  JERRY_ASSERT (property_name_p != NULL);
78
  JERRY_ASSERT (options == ECMA_PROPERTY_GET_NO_OPTIONS || property_ref_p != NULL);
79

80
  ecma_object_type_t type = ecma_get_object_type (object_p);
81

82
  switch (type)
83
  {
84
    case ECMA_OBJECT_TYPE_CLASS:
85
    {
86 87 88
      ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;

      if (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_STRING_UL)
89
      {
90
        if (ecma_string_is_length (property_name_p))
91
        {
92 93
          if (options & ECMA_PROPERTY_GET_VALUE)
          {
94
            ecma_value_t prim_value_p = ext_object_p->u.class_prop.u.value;
95
            ecma_string_t *prim_value_str_p = ecma_get_string_from_value (prim_value_p);
96

97 98 99
            ecma_length_t length = ecma_string_get_length (prim_value_str_p);
            property_ref_p->virtual_value = ecma_make_uint32_value (length);
          }
100

101
          return ECMA_PROPERTY_TYPE_VIRTUAL;
102 103
        }

104
        uint32_t index = ecma_string_get_array_index (property_name_p);
105

106
        if (index != ECMA_STRING_NOT_ARRAY_INDEX)
107
        {
108
          ecma_value_t prim_value_p = ext_object_p->u.class_prop.u.value;
109 110 111
          ecma_string_t *prim_value_str_p = ecma_get_string_from_value (prim_value_p);

          if (index < ecma_string_get_length (prim_value_str_p))
112
          {
113 114 115 116 117 118
            if (options & ECMA_PROPERTY_GET_VALUE)
            {
              ecma_char_t char_at_idx = ecma_string_get_char_at_pos (prim_value_str_p, index);
              ecma_string_t *char_str_p = ecma_new_ecma_string_from_code_unit (char_at_idx);
              property_ref_p->virtual_value = ecma_make_string_value (char_str_p);
            }
119

120 121
            return ECMA_PROPERTY_FLAG_ENUMERABLE | ECMA_PROPERTY_TYPE_VIRTUAL;
          }
122 123
        }
      }
124
      break;
125
    }
126 127
    case ECMA_OBJECT_TYPE_ARRAY:
    {
128 129
      ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;

130 131 132 133 134 135
      if (ecma_string_is_length (property_name_p))
      {
        if (options & ECMA_PROPERTY_GET_VALUE)
        {
          property_ref_p->virtual_value = ecma_make_uint32_value (ext_object_p->u.array.length);
        }
136

137 138
        return ext_object_p->u.array.length_prop;
      }
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167

      if (ext_object_p->u.array.is_fast_mode)
      {
        uint32_t index = ecma_string_get_array_index (property_name_p);

        if (index != ECMA_STRING_NOT_ARRAY_INDEX)
        {
          if (JERRY_LIKELY (index < ext_object_p->u.array.length))
          {
            ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp);

            if (ecma_is_value_array_hole (values_p[index]))
            {
              return ECMA_PROPERTY_TYPE_NOT_FOUND;
            }

            if (options & ECMA_PROPERTY_GET_VALUE)
            {
              property_ref_p->virtual_value = ecma_fast_copy_value (values_p[index]);
            }

            return (ecma_property_t) (ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | ECMA_PROPERTY_TYPE_VIRTUAL);
          }
        }

        return ECMA_PROPERTY_TYPE_NOT_FOUND;
      }


168 169
      break;
    }
170
#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
171 172 173 174 175
    case ECMA_OBJECT_TYPE_PSEUDO_ARRAY:
    {
      /* ES2015 9.4.5.1 */
      if (ecma_is_typedarray (ecma_make_object_value (object_p)))
      {
176
#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
177 178 179 180
        if (ecma_prop_name_is_symbol (property_name_p))
        {
          break;
        }
181
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
182

183 184 185
        uint32_t array_index = ecma_string_get_array_index (property_name_p);

        if (array_index != ECMA_STRING_NOT_ARRAY_INDEX)
186
        {
187 188 189
          ecma_typedarray_info_t info = ecma_typedarray_get_info (object_p);
          ecma_value_t value = ECMA_VALUE_UNDEFINED;

190
          if (array_index < info.length)
191
          {
192 193
            ecma_length_t byte_pos = array_index << info.shift;
            ecma_number_t num = ecma_get_typedarray_element (info.buffer_p + byte_pos, info.id);
194 195
            value = ecma_make_number_value (num);
          }
196

197 198
          if (!ecma_is_value_undefined (value))
          {
199 200 201 202 203 204 205 206
            if (options & ECMA_PROPERTY_GET_VALUE)
            {
              property_ref_p->virtual_value = value;
            }
            else
            {
              ecma_fast_free_value (value);
            }
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228

            return ECMA_PROPERTY_ENUMERABLE_WRITABLE | ECMA_PROPERTY_TYPE_VIRTUAL;
          }

          return ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP;
        }

        ecma_number_t num = ecma_string_to_number (property_name_p);
        ecma_string_t *num_to_str = ecma_new_ecma_string_from_number (num);

        if (ecma_compare_ecma_strings (property_name_p, num_to_str))
        {
          ecma_deref_ecma_string (num_to_str);

          return ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP;
        }

        ecma_deref_ecma_string (num_to_str);
      }

      break;
    }
229
#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
230 231 232 233 234 235 236 237 238 239
    default:
    {
      break;
    }
  }

  ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p);

  if (property_p == NULL)
  {
240
    if (ecma_get_object_is_builtin (object_p))
241
    {
242
      property_p = ecma_builtin_try_to_instantiate_property (object_p, property_name_p);
243
    }
244
    else if (ecma_is_normal_or_arrow_function (type))
245
    {
246
      if (ecma_string_is_length (property_name_p))
247
      {
248 249 250 251
        if (options & ECMA_PROPERTY_GET_VALUE)
        {
          /* Get length virtual property. */
          const ecma_compiled_code_t *bytecode_data_p;
252

253
#if ENABLED (JERRY_ES2015_ARROW_FUNCTION)
254 255 256
          if (type != ECMA_OBJECT_TYPE_ARROW_FUNCTION)
          {
            ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
257
            bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
258 259 260 261
          }
          else
          {
            ecma_arrow_function_t *arrow_func_p = (ecma_arrow_function_t *) object_p;
262
            bytecode_data_p = ecma_op_arrow_function_get_compiled_code (arrow_func_p);
263
          }
264
#else /* !ENABLED (JERRY_ES2015_ARROW_FUNCTION) */
265
          ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
266
          bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
267
#endif /* ENABLED (JERRY_ES2015_ARROW_FUNCTION) */
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284

          uint32_t len;
          if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
          {
            cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p;
            len = args_p->argument_end;
          }
          else
          {
            cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p;
            len = args_p->argument_end;
          }

          property_ref_p->virtual_value = ecma_make_uint32_value (len);
        }

        return ECMA_PROPERTY_TYPE_VIRTUAL;
285
      }
286 287

      /* Get prototype physical property. */
288 289
      property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p);
    }
290 291 292 293
    else if (type == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION)
    {
      property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p);
    }
294 295 296
    else if (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION)
    {
      property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p);
297
    }
298

299
    if (property_p == NULL)
300
    {
301
      return ECMA_PROPERTY_TYPE_NOT_FOUND;
302
    }
303
  }
304
  else if (type == ECMA_OBJECT_TYPE_PSEUDO_ARRAY
Z
Zoltan Herczeg 已提交
305
           && property_ref_p != NULL)
306
  {
307
    ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
308

309
    if (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS)
310
    {
311
      uint32_t index = ecma_string_get_array_index (property_name_p);
Z
Zoltan Herczeg 已提交
312

313 314
      if (index != ECMA_STRING_NOT_ARRAY_INDEX
          && index < ext_object_p->u.pseudo_array.u1.length)
Z
Zoltan Herczeg 已提交
315
      {
316
        ecma_value_t *arg_Literal_p = (ecma_value_t *) (ext_object_p + 1);
317

318 319 320
        if (arg_Literal_p[index] != ECMA_VALUE_EMPTY)
        {
          ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_Literal_p[index]);
Z
Zoltan Herczeg 已提交
321

322 323
          ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
                                                                      ext_object_p->u.pseudo_array.u2.lex_env_cp);
324

325 326
          JERRY_ASSERT (lex_env_p != NULL
                        && ecma_is_lexical_environment (lex_env_p));
327

328
          ecma_value_t binding_value = ecma_op_get_binding_value (lex_env_p, arg_name_p, true);
329

330 331 332 333
          ecma_named_data_property_assign_value (object_p,
                                                 ECMA_PROPERTY_VALUE_PTR (property_p),
                                                 binding_value);
          ecma_free_value (binding_value);
Z
Zoltan Herczeg 已提交
334 335
        }
      }
336 337
    }
  }
338

339 340 341 342 343
  if (options & ECMA_PROPERTY_GET_EXT_REFERENCE)
  {
    ((ecma_extended_property_ref_t *) property_ref_p)->property_p = property_p;
  }

344
  if (property_ref_p != NULL)
345
  {
346
    property_ref_p->value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
347
  }
348

349
  return *property_p;
350 351 352 353 354 355 356 357 358
} /* ecma_op_object_get_own_property */

/**
 * [[GetProperty]] ecma object's operation
 *
 * See also:
 *          ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
 *
 * @return pointer to a property - if it exists,
359
 *         NULL (i.e. ecma-undefined) - otherwise.
360
 */
361
static ecma_property_t
362
ecma_op_object_get_property (ecma_object_t *object_p, /**< the object */
363 364 365
                             ecma_string_t *property_name_p, /**< property name */
                             ecma_property_ref_t *property_ref_p, /**< property reference */
                             uint32_t options) /**< option bits */
366
{
367
  while (true)
368
  {
369 370 371 372
    ecma_property_t property = ecma_op_object_get_own_property (object_p,
                                                                property_name_p,
                                                                property_ref_p,
                                                                options);
373

374
    if (property != ECMA_PROPERTY_TYPE_NOT_FOUND && property != ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP)
375
    {
376
      return property;
377 378
    }

379
    if (property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP)
380 381 382 383
    {
      break;
    }

384 385 386 387 388 389
    if (object_p->u2.prototype_cp == JMEM_CP_NULL)
    {
      break;
    }

    object_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, object_p->u2.prototype_cp);
390 391
  }

392
  return ECMA_PROPERTY_TYPE_NOT_FOUND;
393 394
} /* ecma_op_object_get_property */

395 396 397
/**
 * Checks whether an object (excluding prototypes) has a named property
 *
398 399
 * @return true - if property is found
 *         false - otherwise
400
 */
401
inline bool JERRY_ATTR_ALWAYS_INLINE
402 403 404
ecma_op_object_has_own_property (ecma_object_t *object_p, /**< the object */
                                 ecma_string_t *property_name_p) /**< property name */
{
405 406 407 408
  ecma_property_t property = ecma_op_object_get_own_property (object_p,
                                                              property_name_p,
                                                              NULL,
                                                              ECMA_PROPERTY_GET_NO_OPTIONS);
409 410

  return property != ECMA_PROPERTY_TYPE_NOT_FOUND && property != ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP;
411 412 413 414 415
} /* ecma_op_object_has_own_property */

/**
 * Checks whether an object (including prototypes) has a named property
 *
416 417
 * @return true - if property is found
 *         false - otherwise
418
 */
419
inline bool JERRY_ATTR_ALWAYS_INLINE
420 421 422
ecma_op_object_has_property (ecma_object_t *object_p, /**< the object */
                             ecma_string_t *property_name_p) /**< property name */
{
423 424 425 426 427
  ecma_property_t property = ecma_op_object_get_property (object_p,
                                                          property_name_p,
                                                          NULL,
                                                          ECMA_PROPERTY_GET_NO_OPTIONS);
  return property != ECMA_PROPERTY_TYPE_NOT_FOUND;
428 429 430 431 432 433 434 435
} /* ecma_op_object_has_property */

/**
 * Search the value corresponding to a property name
 *
 * Note: search includes prototypes
 *
 * @return ecma value if property is found
436
 *         ECMA_VALUE_NOT_FOUND if property is not found
437 438 439
 *         Returned value must be freed with ecma_free_value
 */
ecma_value_t
Y
Yanhui Shen 已提交
440 441
ecma_op_object_find_own (ecma_value_t base_value, /**< base value */
                         ecma_object_t *object_p, /**< target object */
442 443 444 445 446 447
                         ecma_string_t *property_name_p) /**< property name */
{
  JERRY_ASSERT (object_p != NULL
                && !ecma_is_lexical_environment (object_p));
  JERRY_ASSERT (property_name_p != NULL);

448 449
  ecma_object_type_t type = ecma_get_object_type (object_p);

450
  switch (type)
451
  {
452
    case ECMA_OBJECT_TYPE_CLASS:
453
    {
454 455 456
      ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;

      if (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_STRING_UL)
457
      {
458 459
        if (ecma_string_is_length (property_name_p))
        {
460
          ecma_value_t prim_value_p = ext_object_p->u.class_prop.u.value;
461

462 463
          ecma_string_t *prim_value_str_p = ecma_get_string_from_value (prim_value_p);
          ecma_length_t length = ecma_string_get_length (prim_value_str_p);
464

465 466
          return ecma_make_uint32_value (length);
        }
467

468
        uint32_t index = ecma_string_get_array_index (property_name_p);
469

470
        if (index != ECMA_STRING_NOT_ARRAY_INDEX)
471
        {
472
          ecma_value_t prim_value_p = ext_object_p->u.class_prop.u.value;
473

474
          ecma_string_t *prim_value_str_p = ecma_get_string_from_value (prim_value_p);
475

476 477 478 479 480
          if (index < ecma_string_get_length (prim_value_str_p))
          {
            ecma_char_t char_at_idx = ecma_string_get_char_at_pos (prim_value_str_p, index);
            return ecma_make_string_value (ecma_new_ecma_string_from_code_unit (char_at_idx));
          }
481 482
        }
      }
483

484 485 486 487
      break;
    }
    case ECMA_OBJECT_TYPE_ARRAY:
    {
488 489
      ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;

490 491 492 493
      if (ecma_string_is_length (property_name_p))
      {
        return ecma_make_uint32_value (ext_object_p->u.array.length);
      }
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511

      if (JERRY_LIKELY (ext_object_p->u.array.is_fast_mode))
      {
        uint32_t index = ecma_string_get_array_index (property_name_p);

        if (JERRY_LIKELY (index != ECMA_STRING_NOT_ARRAY_INDEX))
        {
          if (JERRY_LIKELY (index < ext_object_p->u.array.length))
          {
            ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp);

            return (ecma_is_value_array_hole (values_p[index]) ? ECMA_VALUE_NOT_FOUND
                                                               : ecma_fast_copy_value (values_p[index]));
          }
        }
        return ECMA_VALUE_NOT_FOUND;
      }

512
      break;
513
    }
514
    case ECMA_OBJECT_TYPE_PSEUDO_ARRAY:
515
    {
516
      ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
517

518
      if (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS)
519
      {
520
        uint32_t index = ecma_string_get_array_index (property_name_p);
521

522 523
        if (index != ECMA_STRING_NOT_ARRAY_INDEX
            && index < ext_object_p->u.pseudo_array.u1.length)
524
        {
525
          ecma_value_t *arg_Literal_p = (ecma_value_t *) (ext_object_p + 1);
526

527 528 529
          if (arg_Literal_p[index] != ECMA_VALUE_EMPTY)
          {
            ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_Literal_p[index]);
530

531 532
            ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
                                                                        ext_object_p->u.pseudo_array.u2.lex_env_cp);
533

534 535
            JERRY_ASSERT (lex_env_p != NULL
                          && ecma_is_lexical_environment (lex_env_p));
536

537
            return ecma_op_get_binding_value (lex_env_p, arg_name_p, true);
538 539 540
          }
        }
      }
541
#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
542 543 544
      /* ES2015 9.4.5.4 */
      if (ecma_is_typedarray (ecma_make_object_value (object_p)))
      {
545
#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
546 547 548 549
        if (ecma_prop_name_is_symbol (property_name_p))
        {
          break;
        }
550
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
551

552 553 554
        uint32_t array_index = ecma_string_get_array_index (property_name_p);

        if (array_index != ECMA_STRING_NOT_ARRAY_INDEX)
555
        {
556 557
          ecma_typedarray_info_t info = ecma_typedarray_get_info (object_p);

558
          if (array_index >= info.length)
559 560 561 562
          {
            return ECMA_VALUE_UNDEFINED;
          }

563 564
          ecma_length_t byte_pos = array_index << info.shift;
          ecma_number_t num = ecma_get_typedarray_element (info.buffer_p + byte_pos, info.id);
565
          return ecma_make_number_value (num);
566 567 568 569 570 571 572 573 574
        }

        ecma_number_t num = ecma_string_to_number (property_name_p);
        ecma_string_t *num_to_str = ecma_new_ecma_string_from_number (num);

        if (ecma_compare_ecma_strings (property_name_p, num_to_str))
        {
          ecma_deref_ecma_string (num_to_str);

575
          return ECMA_VALUE_UNDEFINED;
576 577 578 579
        }

        ecma_deref_ecma_string (num_to_str);
      }
580
#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
581

582 583 584 585 586 587 588 589 590 591 592 593
      break;
    }
    default:
    {
      break;
    }
  }

  ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p);

  if (property_p == NULL)
  {
594 595 596 597
    if (ecma_get_object_is_builtin (object_p))
    {
      property_p = ecma_builtin_try_to_instantiate_property (object_p, property_name_p);
    }
598
    else if (ecma_is_normal_or_arrow_function (type))
599 600 601 602 603
    {
      if (ecma_string_is_length (property_name_p))
      {
        /* Get length virtual property. */
        const ecma_compiled_code_t *bytecode_data_p;
604

605
#if ENABLED (JERRY_ES2015_ARROW_FUNCTION)
606 607 608
        if (type != ECMA_OBJECT_TYPE_ARROW_FUNCTION)
        {
          ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
609
          bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
610 611 612 613
        }
        else
        {
          ecma_arrow_function_t *arrow_func_p = (ecma_arrow_function_t *) object_p;
614
          bytecode_data_p = ecma_op_arrow_function_get_compiled_code (arrow_func_p);
615
        }
616
#else /* !ENABLED (JERRY_ES2015_ARROW_FUNCTION) */
617
        ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
618
        bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
619
#endif /* ENABLED (JERRY_ES2015_ARROW_FUNCTION) */
620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636

        uint32_t len;
        if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
        {
          cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p;
          len = args_p->argument_end;
        }
        else
        {
          cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p;
          len = args_p->argument_end;
        }

        return ecma_make_uint32_value (len);
      }

      /* Get prototype physical property. */
637 638
      property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p);
    }
639 640 641 642
    else if (type == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION)
    {
      property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p);
    }
643 644 645
    else if (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION)
    {
      property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p);
646 647 648 649
    }

    if (property_p == NULL)
    {
650
      return ECMA_VALUE_NOT_FOUND;
651
    }
652 653
  }

654 655 656
  ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p);

  if (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA)
657
  {
658
    return ecma_fast_copy_value (prop_value_p->value);
659 660
  }

661 662
  JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);

663
  ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (prop_value_p);
664

665
  if (get_set_pair_p->getter_cp == JMEM_CP_NULL)
666
  {
667
    return ECMA_VALUE_UNDEFINED;
668 669
  }

670 671
  ecma_object_t *getter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->getter_cp);

Y
Yanhui Shen 已提交
672
  return ecma_op_function_call (getter_p, base_value, NULL, 0);
673 674
} /* ecma_op_object_find_own */

675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719
/**
 * Search the value corresponding to an uint32_t property index
 *
 * Note: this method falls back to the general ecma_op_object_find
 *
 * @return ecma value if property is found
 *         ECMA_VALUE_NOT_FOUND if property is not found
 *         Returned value must be freed with ecma_free_value
 */
ecma_value_t
ecma_op_object_find_by_uint32_index (ecma_object_t *object_p, /**< the object */
                                     uint32_t index) /**< property index */
{
  if (JERRY_LIKELY (index <= ECMA_DIRECT_STRING_MAX_IMM))
  {
    return ecma_op_object_find (object_p, ECMA_CREATE_DIRECT_UINT32_STRING (index));
  }

  ecma_string_t *index_str_p = ecma_new_non_direct_string_from_uint32 (index);
  ecma_value_t ret_value = ecma_op_object_find (object_p, index_str_p);
  ecma_deref_ecma_string (index_str_p);

  return ret_value;
} /* ecma_op_object_find_by_uint32_index */

/**
 * Search the value corresponding to an ecma_number_t property index
 *
 * Note: this method falls back to the general ecma_op_object_find
 *
 * @return ecma value if property is found
 *         ECMA_VALUE_NOT_FOUND if property is not found
 *         Returned value must be freed with ecma_free_value
 */
ecma_value_t
ecma_op_object_find_by_number_index (ecma_object_t *object_p, /**< the object */
                                     ecma_number_t index) /**< property index */
{
  ecma_string_t *index_str_p = ecma_new_ecma_string_from_number (index);
  ecma_value_t ret_value = ecma_op_object_find (object_p, index_str_p);
  ecma_deref_ecma_string (index_str_p);

  return ret_value;
} /* ecma_op_object_find_by_number_index */

720 721 722 723 724 725
/**
 * Search the value corresponding to a property name
 *
 * Note: search includes prototypes
 *
 * @return ecma value if property is found
726
 *         ECMA_VALUE_NOT_FOUND if property is not found
727 728 729 730 731 732
 *         Returned value must be freed with ecma_free_value
 */
ecma_value_t
ecma_op_object_find (ecma_object_t *object_p, /**< the object */
                     ecma_string_t *property_name_p) /**< property name */
{
Y
Yanhui Shen 已提交
733
  ecma_value_t base_value = ecma_make_object_value (object_p);
734 735

  while (true)
736
  {
Y
Yanhui Shen 已提交
737
    ecma_value_t value = ecma_op_object_find_own (base_value, object_p, property_name_p);
738 739 740 741 742 743

    if (ecma_is_value_found (value))
    {
      return value;
    }

744
    if (object_p->u2.prototype_cp == JMEM_CP_NULL)
745 746 747 748
    {
      break;
    }

749
    object_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, object_p->u2.prototype_cp);
750 751
  }

752
  return ECMA_VALUE_NOT_FOUND;
753 754 755 756 757 758 759 760 761 762
} /* ecma_op_object_find */

/**
 * Get own property by name
 *
 * Note: property must be an existing data property
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value
 */
763
inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE
764 765 766
ecma_op_object_get_own_data_prop (ecma_object_t *object_p, /**< the object */
                                  ecma_string_t *property_name_p) /**< property name */
{
767 768 769 770
  JERRY_ASSERT (ecma_is_lexical_environment (object_p)
                || ecma_get_object_type (object_p) != ECMA_OBJECT_TYPE_ARRAY
                || !((ecma_extended_object_t *) object_p)->u.array.is_fast_mode);

771 772 773 774
  ecma_value_t result = ecma_op_object_find_own (ecma_make_object_value (object_p),
                                                 object_p,
                                                 property_name_p);

775
#ifndef JERRY_NDEBUG
776 777 778 779
  /* Because ecma_op_object_find_own might create a property
   * this check is executed after the function return. */
  ecma_property_t *property_p = ecma_find_named_property (object_p,
                                                          property_name_p);
780 781

  JERRY_ASSERT (property_p != NULL
782 783
                && ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA
                && !ecma_is_property_configurable (*property_p));
784 785
#endif /* !JERRY_NDEBUG */

786
  return result;
787 788 789
} /* ecma_op_object_get_own_data_prop */

/**
790 791 792 793 794 795
 * [[Get]] operation of ecma object
 *
 * This function returns the value of a named property, or undefined
 * if the property is not found in the prototype chain. If the property
 * is an accessor, it calls the "get" callback function and returns
 * with its result (including error throws).
796 797 798 799 800 801 802 803 804 805 806
 *
 * See also:
 *          ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value
 */
ecma_value_t
ecma_op_object_get (ecma_object_t *object_p, /**< the object */
                    ecma_string_t *property_name_p) /**< property name */
{
807
  ecma_value_t base_value = ecma_make_object_value (object_p);
808 809

  while (true)
810
  {
811 812 813 814 815 816 817
    ecma_value_t value = ecma_op_object_find_own (base_value, object_p, property_name_p);

    if (ecma_is_value_found (value))
    {
      return value;
    }

818
    if (object_p->u2.prototype_cp == JMEM_CP_NULL)
819 820 821 822
    {
      break;
    }

823
    object_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, object_p->u2.prototype_cp);
824 825
  }

826
  return ECMA_VALUE_UNDEFINED;
827 828
} /* ecma_op_object_get */

829 830 831 832 833 834 835 836 837 838 839 840 841 842
/**
 * [[Get]] operation of ecma object where the property name is a magic string
 *
 * This function returns the value of a named property, or undefined
 * if the property is not found in the prototype chain. If the property
 * is an accessor, it calls the "get" callback function and returns
 * with its result (including error throws).
 *
 * See also:
 *          ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value
 */
843
inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE
844 845 846
ecma_op_object_get_by_magic_id (ecma_object_t *object_p, /**< the object */
                                lit_magic_string_id_t property_id) /**< property magic string id */
{
847
  return ecma_op_object_get (object_p, ecma_get_magic_string (property_id));
848 849
} /* ecma_op_object_get_by_magic_id */

850
#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871
/**
 * [[Get]] operation of ecma object where the property is a well-known symbol
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value
 */
ecma_value_t
ecma_op_object_get_by_symbol_id (ecma_object_t *object_p, /**< the object */
                                 lit_magic_string_id_t property_id) /**< property symbol id */
{
  ecma_value_t symbol_value = ecma_op_object_get_by_magic_id (ecma_builtin_get (ECMA_BUILTIN_ID_SYMBOL),
                                                              property_id);
  JERRY_ASSERT (ecma_is_value_symbol (symbol_value));

  ecma_string_t *symbol_p = ecma_get_symbol_from_value (symbol_value);
  ecma_value_t ret_value = ecma_op_object_get (object_p, symbol_p);

  ecma_deref_ecma_string (symbol_p);

  return ret_value;
} /* ecma_op_object_get_by_symbol_id */
872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921

/**
 * GetMethod operation the property is a well-known symbol
 *
 * See also: ECMA-262 v6, 7.3.9
 *
 * Note:
 *      Returned value must be freed with ecma_free_value.
 *
 * @return iterator fucntion object - if success
 *         raised error - otherwise
 */
ecma_value_t
ecma_op_get_method_by_symbol_id (ecma_value_t value, /**< ecma value */
                                 lit_magic_string_id_t property_id) /**< property symbol id */
{
  /* 2. */
  ecma_value_t obj_value = ecma_op_to_object (value);

  if (ECMA_IS_VALUE_ERROR (obj_value))
  {
    return obj_value;
  }

  ecma_object_t *obj_p = ecma_get_object_from_value (obj_value);
  ecma_value_t func = ecma_op_object_get_by_symbol_id (obj_p, property_id);
  ecma_deref_object (obj_p);

  /* 3. */
  if (ECMA_IS_VALUE_ERROR (func))
  {
    return func;
  }

  /* 4. */
  if (ecma_is_value_undefined (func) || ecma_is_value_null (func))
  {
    return ECMA_VALUE_UNDEFINED;
  }

  /* 5. */
  if (!ecma_op_is_callable (func))
  {
    ecma_free_value (func);
    return ecma_raise_type_error (ECMA_ERR_MSG ("Iterator is not callable."));
  }

  /* 6. */
  return func;
} /* ecma_op_get_method_by_symbol_id */
922
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
923

924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973
/**
 * [[Put]] ecma general object's operation specialized for uint32_ property index
 *
 * Note: This function falls back to the general ecma_op_object_put
 *
 * @return ecma value
 *         The returned value must be freed with ecma_free_value.
 */
ecma_value_t
ecma_op_object_put_by_uint32_index (ecma_object_t *object_p, /**< the object */
                                    uint32_t index, /**< property index */
                                    ecma_value_t value, /**< ecma value */
                                    bool is_throw) /**< flag that controls failure handling */
{
  if (JERRY_LIKELY (index <= ECMA_DIRECT_STRING_MAX_IMM))
  {
    return ecma_op_object_put (object_p,
                               ECMA_CREATE_DIRECT_UINT32_STRING (index),
                               value,
                               is_throw);
  }

  ecma_string_t *index_str_p = ecma_new_non_direct_string_from_uint32 (index);
  ecma_value_t ret_value = ecma_op_object_put (object_p, index_str_p, value, is_throw);
  ecma_deref_ecma_string (index_str_p);

  return ret_value;
} /* ecma_op_object_put_by_uint32_index */

/**
 * [[Put]] ecma general object's operation specialized for ecma_number_ property index
 *
 * Note: This function falls back to the general ecma_op_object_put
 *
 * @return ecma value
 *         The returned value must be freed with ecma_free_value.
 */
ecma_value_t
ecma_op_object_put_by_number_index (ecma_object_t *object_p, /**< the object */
                                    ecma_number_t index, /**< property index */
                                    ecma_value_t value, /**< ecma value */
                                    bool is_throw) /**< flag that controls failure handling */
{
  ecma_string_t *index_str_p = ecma_new_ecma_string_from_number (index);
  ecma_value_t ret_value = ecma_op_object_put (object_p, index_str_p, value, is_throw);
  ecma_deref_ecma_string (index_str_p);

  return ret_value;
} /* ecma_op_object_put_by_number_index */

974
/**
975
 * [[Put]] ecma general object's operation
976 977 978
 *
 * See also:
 *          ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
979 980
 *          ECMA-262 v5, 8.12.5
 *          Also incorporates [[CanPut]] ECMA-262 v5, 8.12.4
981
 *
982
 * @return ecma value
983 984
 *         The returned value must be freed with ecma_free_value.
 *
985
 *         Returns with ECMA_VALUE_TRUE if the operation is
986
 *         successful. Otherwise it returns with an error object
987
 *         or ECMA_VALUE_FALSE.
988 989 990
 *
 *         Note: even if is_throw is false, the setter can throw an
 *         error, and this function returns with that error.
991
 */
992
ecma_value_t
993
ecma_op_object_put (ecma_object_t *object_p, /**< the object */
994
                    ecma_string_t *property_name_p, /**< property name */
995
                    ecma_value_t value, /**< ecma value */
996 997
                    bool is_throw) /**< flag that controls failure handling */
{
998 999
  JERRY_ASSERT (object_p != NULL
                && !ecma_is_lexical_environment (object_p));
1000
  JERRY_ASSERT (property_name_p != NULL);
1001

M
mamingshuai 已提交
1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019
#if defined(JERRY_FUNCTION_NAME) && !defined(__APPLE__)
  if (ecma_is_value_object(value)) {
    ecma_object_t* obj = ecma_get_object_from_value(value);
    if (ecma_get_object_type(obj) == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION) {
      ecma_string_t* property_name = ecma_get_magic_string (LIT_MAGIC_STRING_NAME);
      if (ecma_find_named_property (obj, property_name) == NULL) {
        ecma_property_value_t* prop_val = ecma_create_named_data_property(obj,
                                            property_name,
                                            ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE,
                                            NULL);
        prop_val->value = ecma_copy_value(ecma_make_string_value(property_name_p));
      } else {
        ecma_deref_ecma_string (property_name);
      }
    }
  }
#endif

1020 1021
  ecma_object_type_t type = ecma_get_object_type (object_p);

1022
  switch (type)
1023
  {
1024 1025
    case ECMA_OBJECT_TYPE_ARRAY:
    {
1026 1027
      ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;

1028 1029 1030 1031 1032 1033 1034 1035 1036
      if (ecma_string_is_length (property_name_p))
      {
        if (ecma_is_property_writable (ext_object_p->u.array.length_prop))
        {
          return ecma_op_array_object_set_length (object_p, value, 0);
        }

        return ecma_reject (is_throw);
      }
1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052

      if (JERRY_LIKELY (ext_object_p->u.array.is_fast_mode))
      {
        if (JERRY_UNLIKELY (!ecma_get_object_extensible (object_p)))
        {
          return ecma_reject (is_throw);
        }

        if (ecma_fast_array_set_property (object_p, property_name_p, value))
        {
          return ECMA_VALUE_TRUE;
        }
      }

      JERRY_ASSERT (!(ext_object_p->u.array.is_fast_mode));

1053 1054
      break;
    }
1055
    case ECMA_OBJECT_TYPE_PSEUDO_ARRAY:
1056
    {
1057
      ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
1058

1059
      if (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS)
Z
Zoltan Herczeg 已提交
1060
      {
1061
        uint32_t index = ecma_string_get_array_index (property_name_p);
1062

1063 1064
        if (index != ECMA_STRING_NOT_ARRAY_INDEX
            && index < ext_object_p->u.pseudo_array.u1.length)
Z
Zoltan Herczeg 已提交
1065
        {
1066
          ecma_value_t *arg_Literal_p = (ecma_value_t *) (ext_object_p + 1);
Z
Zoltan Herczeg 已提交
1067

1068 1069 1070
          if (arg_Literal_p[index] != ECMA_VALUE_EMPTY)
          {
            ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_Literal_p[index]);
1071

1072 1073
            ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
                                                                        ext_object_p->u.pseudo_array.u2.lex_env_cp);
1074

1075 1076
            JERRY_ASSERT (lex_env_p != NULL
                          && ecma_is_lexical_environment (lex_env_p));
1077

1078 1079
            ecma_op_set_mutable_binding (lex_env_p, arg_name_p, value, true);
            return ECMA_VALUE_TRUE;
1080 1081 1082
          }
        }
      }
1083
#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
1084 1085 1086
      /* ES2015 9.4.5.5 */
      if (ecma_is_typedarray (ecma_make_object_value (object_p)))
      {
1087
#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
1088 1089 1090 1091
        if (ecma_prop_name_is_symbol (property_name_p))
        {
          break;
        }
1092
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
1093

1094 1095 1096
        uint32_t array_index = ecma_string_get_array_index (property_name_p);

        if (array_index != ECMA_STRING_NOT_ARRAY_INDEX)
1097
        {
1098 1099
          ecma_number_t num_var;
          ecma_value_t error = ecma_get_number (value, &num_var);
Z
Zoltan Herczeg 已提交
1100

1101
          if (ECMA_IS_VALUE_ERROR (error))
1102
          {
1103 1104
            ecma_free_value (JERRY_CONTEXT (error_value));
            return ecma_reject (is_throw);
1105
          }
1106

1107 1108
          ecma_typedarray_info_t info = ecma_typedarray_get_info (object_p);

1109
          if (array_index >= info.length)
1110 1111 1112 1113
          {
            return ecma_reject (is_throw);
          }

1114 1115
          ecma_length_t byte_pos = array_index << info.shift;
          ecma_set_typedarray_element (info.buffer_p + byte_pos, num_var, info.id);
1116 1117

          return ECMA_VALUE_TRUE;
1118 1119 1120 1121 1122 1123 1124 1125 1126 1127
        }

        ecma_number_t num = ecma_string_to_number (property_name_p);
        ecma_string_t *num_to_str = ecma_new_ecma_string_from_number (num);

        if (ecma_compare_ecma_strings (property_name_p, num_to_str))
        {
          ecma_deref_ecma_string (num_to_str);

          return ecma_reject (is_throw);
Z
Zoltan Herczeg 已提交
1128
        }
1129 1130

        ecma_deref_ecma_string (num_to_str);
Z
Zoltan Herczeg 已提交
1131
      }
1132
#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
1133 1134 1135 1136 1137
      break;
    }
    default:
    {
      break;
1138 1139 1140 1141 1142 1143 1144
    }
  }

  ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p);

  if (property_p == NULL)
  {
1145
    if (type == ECMA_OBJECT_TYPE_CLASS)
1146
    {
1147
      ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
1148

1149
      if (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_STRING_UL)
1150
      {
1151
        uint32_t index = ecma_string_get_array_index (property_name_p);
1152

1153
        if (index != ECMA_STRING_NOT_ARRAY_INDEX)
1154
        {
1155
          ecma_value_t prim_value_p = ext_object_p->u.class_prop.u.value;
1156 1157 1158 1159 1160 1161
          ecma_string_t *prim_value_str_p = ecma_get_string_from_value (prim_value_p);

          if (index < ecma_string_get_length (prim_value_str_p))
          {
            return ecma_reject (is_throw);
          }
1162 1163 1164 1165 1166 1167 1168 1169
        }
      }
    }

    if (ecma_get_object_is_builtin (object_p))
    {
      property_p = ecma_builtin_try_to_instantiate_property (object_p, property_name_p);
    }
1170
    else if (ecma_is_normal_or_arrow_function (type))
1171 1172 1173 1174 1175 1176 1177
    {
      if (ecma_string_is_length (property_name_p))
      {
        return ecma_reject (is_throw);
      }

      /* Get prototype physical property. */
1178 1179
      property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p);
    }
1180 1181 1182 1183
    else if (type == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION)
    {
      property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p);
    }
1184 1185 1186
    else if (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION)
    {
      property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p);
1187 1188 1189
    }
  }

1190 1191
  jmem_cpointer_t setter_cp = JMEM_CP_NULL;

1192 1193
  if (property_p != NULL)
  {
1194
    if (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA)
1195
    {
1196
      if (ecma_is_property_writable (*property_p))
1197 1198 1199
      {
        /* There is no need for special casing arrays here because changing the
         * value of an existing property never changes the length of an array. */
1200 1201 1202
        ecma_named_data_property_assign_value (object_p,
                                               ECMA_PROPERTY_VALUE_PTR (property_p),
                                               value);
1203
        return ECMA_VALUE_TRUE;
1204 1205 1206 1207
      }
    }
    else
    {
1208
      JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
1209

1210 1211 1212
      ecma_getter_setter_pointers_t *get_set_pair_p;
      get_set_pair_p = ecma_get_named_accessor_property (ECMA_PROPERTY_VALUE_PTR (property_p));
      setter_cp = get_set_pair_p->setter_cp;
1213 1214 1215 1216 1217 1218
    }
  }
  else
  {
    bool create_new_property = true;

1219
    if (object_p->u2.prototype_cp != JMEM_CP_NULL)
1220
    {
1221
      ecma_property_ref_t property_ref = { NULL };
1222
      ecma_object_t *proto_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, object_p->u2.prototype_cp);
1223 1224 1225 1226 1227

      ecma_property_t inherited_property = ecma_op_object_get_property (proto_p,
                                                                        property_name_p,
                                                                        &property_ref,
                                                                        ECMA_PROPERTY_GET_NO_OPTIONS);
1228

1229
      if (inherited_property != ECMA_PROPERTY_TYPE_NOT_FOUND)
1230
      {
1231
        if (ECMA_PROPERTY_GET_TYPE (inherited_property) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR)
1232
        {
1233
          setter_cp = ecma_get_named_accessor_property (property_ref.value_p)->setter_cp;
1234 1235 1236 1237
          create_new_property = false;
        }
        else
        {
1238
          create_new_property = ecma_is_property_writable (inherited_property);
1239 1240 1241 1242 1243 1244 1245
        }
      }
    }

    if (create_new_property
        && ecma_get_object_extensible (object_p))
    {
1246
      const ecma_object_type_t obj_type = ecma_get_object_type (object_p);
1247

1248
      if (obj_type == ECMA_OBJECT_TYPE_PSEUDO_ARRAY)
1249
      {
1250 1251 1252 1253 1254 1255 1256
        ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;

        if (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS)
        {
          return ecma_builtin_helper_def_prop (object_p,
                                               property_name_p,
                                               value,
1257
                                               ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | ECMA_IS_THROW);
1258
        }
1259 1260
      }

1261
      uint32_t index = ecma_string_get_array_index (property_name_p);
1262

1263
      if (obj_type == ECMA_OBJECT_TYPE_ARRAY
1264
          && index != ECMA_STRING_NOT_ARRAY_INDEX)
1265
      {
1266
        ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
1267 1268

        if (index < UINT32_MAX
1269
            && index >= ext_object_p->u.array.length)
1270
        {
1271
          if (!ecma_is_property_writable (ext_object_p->u.array.length_prop))
1272 1273 1274 1275
          {
            return ecma_reject (is_throw);
          }

1276
          ext_object_p->u.array.length = index + 1;
1277 1278 1279
        }
      }

1280 1281 1282 1283 1284
      ecma_property_value_t *new_prop_value_p;
      new_prop_value_p = ecma_create_named_data_property (object_p,
                                                          property_name_p,
                                                          ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE,
                                                          NULL);
1285

1286 1287
      JERRY_ASSERT (ecma_is_value_undefined (new_prop_value_p->value));
      new_prop_value_p->value = ecma_copy_value_if_not_object (value);
1288
      return ECMA_VALUE_TRUE;
1289 1290 1291
    }
  }

1292
  if (setter_cp == JMEM_CP_NULL)
1293 1294 1295 1296
  {
    return ecma_reject (is_throw);
  }

1297
  ecma_value_t ret_value = ecma_op_function_call (ECMA_GET_NON_NULL_POINTER (ecma_object_t, setter_cp),
1298 1299 1300 1301 1302 1303 1304
                                                  ecma_make_object_value (object_p),
                                                  &value,
                                                  1);

  if (!ECMA_IS_VALUE_ERROR (ret_value))
  {
    ecma_fast_free_value (ret_value);
1305
    ret_value = ECMA_VALUE_TRUE;
1306 1307 1308
  }

  return ret_value;
1309 1310
} /* ecma_op_object_put */

1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357
/**
 * [[Delete]] ecma object's operation specialized for uint32_t property index
 *
 * Note:
 *      This method falls back to the general ecma_op_object_delete
 *
 * @return true - if deleted successfully
 *         false - or type error otherwise (based in 'is_throw')
 */
ecma_value_t
ecma_op_object_delete_by_uint32_index (ecma_object_t *obj_p, /**< the object */
                                       uint32_t index, /**< property index */
                                       bool is_throw) /**< flag that controls failure handling */
{
  if (JERRY_LIKELY (index <= ECMA_DIRECT_STRING_MAX_IMM))
  {
    return ecma_op_object_delete (obj_p, ECMA_CREATE_DIRECT_UINT32_STRING (index), is_throw);
  }

  ecma_string_t *index_str_p = ecma_new_non_direct_string_from_uint32 (index);
  ecma_value_t ret_value = ecma_op_object_delete (obj_p, index_str_p, is_throw);
  ecma_deref_ecma_string (index_str_p);

  return ret_value;
} /* ecma_op_object_delete_by_uint32_index */

/**
 * [[Delete]] ecma object's operation specialized for ecma_number_t property index
 *
 * Note:
 *      This method falls back to the general ecma_op_object_delete
 *
 * @return true - if deleted successfully
 *         false - or type error otherwise (based in 'is_throw')
 */
ecma_value_t
ecma_op_object_delete_by_number_index (ecma_object_t *obj_p, /**< the object */
                                       ecma_number_t index, /**< property index */
                                       bool is_throw) /**< flag that controls failure handling */
{
  ecma_string_t *index_str_p = ecma_new_ecma_string_from_number (index);
  ecma_value_t ret_value = ecma_op_object_delete (obj_p, index_str_p, is_throw);
  ecma_deref_ecma_string (index_str_p);

  return ret_value;
} /* ecma_op_object_delete_by_number_index */

1358 1359 1360 1361 1362 1363
/**
 * [[Delete]] ecma object's operation
 *
 * See also:
 *          ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
 *
L
László Langó 已提交
1364 1365 1366
 * Note:
 *      returned value must be freed with ecma_free_value
 *
1367 1368
 * @return true - if deleted successfully
 *         false - or type error otherwise (based in 'is_throw')
1369
 */
1370
ecma_value_t
1371
ecma_op_object_delete (ecma_object_t *obj_p, /**< the object */
1372
                       ecma_string_t *property_name_p, /**< property name */
1373 1374
                       bool is_throw) /**< flag that controls failure handling */
{
1375 1376 1377
  JERRY_ASSERT (obj_p != NULL
                && !ecma_is_lexical_environment (obj_p));
  JERRY_ASSERT (property_name_p != NULL);
1378

1379
  if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_PSEUDO_ARRAY)
1380
  {
1381
    ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
1382

1383
    if (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS)
1384
    {
1385
      return ecma_op_arguments_object_delete (obj_p,
1386 1387
                                              property_name_p,
                                              is_throw);
1388 1389
    }
  }
1390 1391 1392 1393 1394 1395

  JERRY_ASSERT_OBJECT_TYPE_IS_VALID (ecma_get_object_type (obj_p));

  return ecma_op_general_object_delete (obj_p,
                                        property_name_p,
                                        is_throw);
1396 1397 1398 1399 1400 1401 1402 1403
} /* ecma_op_object_delete */

/**
 * [[DefaultValue]] ecma object's operation
 *
 * See also:
 *          ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
 *
1404 1405
 * @return ecma value
 *         Returned value must be freed with ecma_free_value
1406
 */
1407
ecma_value_t
1408
ecma_op_object_default_value (ecma_object_t *obj_p, /**< the object */
1409 1410
                              ecma_preferred_type_hint_t hint) /**< hint on preferred result type */
{
1411 1412
  JERRY_ASSERT (obj_p != NULL
                && !ecma_is_lexical_environment (obj_p));
1413

1414
  JERRY_ASSERT_OBJECT_TYPE_IS_VALID (ecma_get_object_type (obj_p));
1415 1416

  /*
1417
   * typedef ecma_property_t * (*default_value_ptr_t) (ecma_object_t *, ecma_string_t *);
1418 1419 1420
   * static const default_value_ptr_t default_value [ECMA_OBJECT_TYPE__COUNT] =
   * {
   *   [ECMA_OBJECT_TYPE_GENERAL]           = &ecma_op_general_object_default_value,
1421
   *   [ECMA_OBJECT_TYPE_CLASS]             = &ecma_op_general_object_default_value,
1422
   *   [ECMA_OBJECT_TYPE_FUNCTION]          = &ecma_op_general_object_default_value,
1423
   *   [ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION] = &ecma_op_general_object_default_value,
1424 1425
   *   [ECMA_OBJECT_TYPE_ARRAY]             = &ecma_op_general_object_default_value,
   *   [ECMA_OBJECT_TYPE_BOUND_FUNCTION]    = &ecma_op_general_object_default_value,
1426
   *   [ECMA_OBJECT_TYPE_PSEUDO_ARRAY]      = &ecma_op_general_object_default_value
1427
   *   [ECMA_OBJECT_TYPE_ARROW_FUNCTION]    = &ecma_op_general_object_default_value
1428 1429 1430 1431 1432
   * };
   *
   * return default_value[type] (obj_p, property_name_p);
   */

1433
  return ecma_op_general_object_default_value (obj_p, hint);
1434 1435 1436 1437 1438 1439 1440 1441
} /* ecma_op_object_default_value */

/**
 * [[DefineOwnProperty]] ecma object's operation
 *
 * See also:
 *          ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
 *
1442 1443
 * @return ecma value
 *         Returned value must be freed with ecma_free_value
1444
 */
1445
ecma_value_t
1446
ecma_op_object_define_own_property (ecma_object_t *obj_p, /**< the object */
1447
                                    ecma_string_t *property_name_p, /**< property name */
1448
                                    const ecma_property_descriptor_t *property_desc_p) /**< property
1449
                                                                                        *   descriptor */
1450
{
1451 1452 1453
  JERRY_ASSERT (obj_p != NULL
                && !ecma_is_lexical_environment (obj_p));
  JERRY_ASSERT (property_name_p != NULL);
1454

1455
  const ecma_object_type_t type = ecma_get_object_type (obj_p);
1456

1457
  switch (type)
1458
  {
1459
    case ECMA_OBJECT_TYPE_GENERAL:
1460
    case ECMA_OBJECT_TYPE_CLASS:
1461
    case ECMA_OBJECT_TYPE_FUNCTION:
1462
#if ENABLED (JERRY_ES2015_ARROW_FUNCTION)
1463
    case ECMA_OBJECT_TYPE_ARROW_FUNCTION:
1464
#endif /* ENABLED (JERRY_ES2015_ARROW_FUNCTION) */
1465
    case ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION:
1466
    case ECMA_OBJECT_TYPE_BOUND_FUNCTION:
1467
    {
1468 1469
      return ecma_op_general_object_define_own_property (obj_p,
                                                         property_name_p,
1470
                                                         property_desc_p);
1471 1472 1473 1474
    }

    case ECMA_OBJECT_TYPE_ARRAY:
    {
1475 1476
      return ecma_op_array_object_define_own_property (obj_p,
                                                       property_name_p,
1477
                                                       property_desc_p);
1478 1479
    }

1480
    default:
1481
    {
1482 1483
      JERRY_ASSERT (type == ECMA_OBJECT_TYPE_PSEUDO_ARRAY);

1484 1485
      ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;

1486
#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
1487 1488
      if (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS)
      {
1489
#else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
1490
        JERRY_ASSERT (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS);
1491
#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
1492 1493
        return ecma_op_arguments_object_define_own_property (obj_p,
                                                             property_name_p,
1494
                                                             property_desc_p);
1495
#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
1496
      }
1497 1498 1499
      /* ES2015 9.4.5.3 */
      if (ecma_is_typedarray (ecma_make_object_value (obj_p)))
      {
1500
#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
1501 1502 1503 1504
        if (ecma_prop_name_is_symbol (property_name_p))
        {
          return ecma_op_general_object_define_own_property (obj_p,
                                                             property_name_p,
1505
                                                             property_desc_p);
1506
        }
1507
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
1508 1509 1510
        uint32_t array_index = ecma_string_get_array_index (property_name_p);

        if (array_index != ECMA_STRING_NOT_ARRAY_INDEX)
1511 1512
        {
          bool define_status = ecma_op_typedarray_define_index_prop (obj_p,
1513
                                                                     array_index,
1514 1515 1516 1517
                                                                     property_desc_p);

          if (define_status)
          {
1518
            return ECMA_VALUE_TRUE;
1519 1520
          }

1521
          return ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW);
1522 1523 1524 1525 1526 1527 1528 1529 1530
        }

        ecma_number_t num = ecma_string_to_number (property_name_p);
        ecma_string_t *num_to_str = ecma_new_ecma_string_from_number (num);

        if (ecma_compare_ecma_strings (property_name_p, num_to_str))
        {
          ecma_deref_ecma_string (num_to_str);

1531
          return ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW);
1532 1533 1534 1535 1536 1537 1538
        }

        ecma_deref_ecma_string (num_to_str);
      }

      return ecma_op_general_object_define_own_property (obj_p,
                                                         property_name_p,
1539
                                                         property_desc_p);
1540
#else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
1541
      break;
1542
#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
1543
    }
1544
  }
1545 1546
} /* ecma_op_object_define_own_property */

1547 1548 1549 1550 1551 1552 1553 1554 1555 1556
/**
 * Get property descriptor from specified property
 *
 * depending on the property type the following fields are set:
 *   - for named data properties: { [Value], [Writable], [Enumerable], [Configurable] };
 *   - for named accessor properties: { [Get] - if defined,
 *                                      [Set] - if defined,
 *                                      [Enumerable], [Configurable]
 *                                    }.
 *
1557 1558
 * @return true - if property found
 *         false - otherwise
1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571
 */
bool
ecma_op_object_get_own_property_descriptor (ecma_object_t *object_p, /**< the object */
                                            ecma_string_t *property_name_p, /**< property name */
                                            ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */
{
  ecma_property_ref_t property_ref;

  ecma_property_t property = ecma_op_object_get_own_property (object_p,
                                                              property_name_p,
                                                              &property_ref,
                                                              ECMA_PROPERTY_GET_VALUE);

1572
  if (property == ECMA_PROPERTY_TYPE_NOT_FOUND || property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP)
1573 1574 1575 1576 1577 1578
  {
    return false;
  }

  *prop_desc_p = ecma_make_empty_property_descriptor ();

1579 1580 1581 1582
  uint32_t flags = ecma_is_property_enumerable (property) ? ECMA_PROP_IS_ENUMERABLE : ECMA_PROP_NO_OPTS;
  flags |= ecma_is_property_configurable (property) ? ECMA_PROP_IS_CONFIGURABLE: ECMA_PROP_NO_OPTS;

  prop_desc_p->flags = (uint16_t) (ECMA_PROP_IS_ENUMERABLE_DEFINED | ECMA_PROP_IS_CONFIGURABLE_DEFINED | flags);
1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597

  ecma_property_types_t type = ECMA_PROPERTY_GET_TYPE (property);

  if (type != ECMA_PROPERTY_TYPE_NAMEDACCESSOR)
  {
    if (type == ECMA_PROPERTY_TYPE_NAMEDDATA)
    {
      prop_desc_p->value = ecma_copy_value (property_ref.value_p->value);
    }
    else
    {
      JERRY_ASSERT (type == ECMA_PROPERTY_TYPE_VIRTUAL);
      prop_desc_p->value = property_ref.virtual_value;
    }

1598 1599 1600
    prop_desc_p->flags |= (ECMA_PROP_IS_VALUE_DEFINED | ECMA_PROP_IS_WRITABLE_DEFINED);
    prop_desc_p->flags = (uint16_t) (prop_desc_p->flags | (ecma_is_property_writable (property) ? ECMA_PROP_IS_WRITABLE
                                                                                                : ECMA_PROP_NO_OPTS));
1601 1602 1603
  }
  else
  {
1604

1605
    ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (property_ref.value_p);
1606
    prop_desc_p->flags |= (ECMA_PROP_IS_GET_DEFINED | ECMA_PROP_IS_SET_DEFINED);
1607

1608 1609 1610 1611 1612
    if (get_set_pair_p->getter_cp == JMEM_CP_NULL)
    {
      prop_desc_p->get_p = NULL;
    }
    else
1613
    {
1614
      prop_desc_p->get_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->getter_cp);
1615 1616 1617
      ecma_ref_object (prop_desc_p->get_p);
    }

1618 1619 1620 1621 1622
    if (get_set_pair_p->setter_cp == JMEM_CP_NULL)
    {
      prop_desc_p->set_p = NULL;
    }
    else
1623
    {
1624
      prop_desc_p->set_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->setter_cp);
1625 1626 1627 1628 1629 1630 1631
      ecma_ref_object (prop_desc_p->set_p);
    }
  }

  return true;
} /* ecma_op_object_get_own_property_descriptor */

1632 1633 1634 1635 1636
/**
 * [[HasInstance]] ecma object's operation
 *
 * See also:
 *          ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 9
1637 1638 1639
 *
 * @return ecma value containing a boolean value or an error
 *         Returned value must be freed with ecma_free_value
1640
 */
1641
ecma_value_t
1642
ecma_op_object_has_instance (ecma_object_t *obj_p, /**< the object */
1643
                             ecma_value_t value) /**< argument 'V' */
1644
{
1645 1646
  JERRY_ASSERT (obj_p != NULL
                && !ecma_is_lexical_environment (obj_p));
1647

1648
  const ecma_object_type_t type = ecma_get_object_type (obj_p);
1649

1650 1651 1652
  if (ecma_is_normal_or_arrow_function (type)
      || type == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION
      || type == ECMA_OBJECT_TYPE_BOUND_FUNCTION)
1653
  {
1654 1655
    return ecma_op_function_has_instance (obj_p, value);
  }
1656

1657
  JERRY_ASSERT_OBJECT_TYPE_IS_VALID (type);
1658

1659
  return ecma_raise_type_error (ECMA_ERR_MSG ("Expected a function object."));
1660 1661
} /* ecma_op_object_has_instance */

1662 1663 1664 1665 1666 1667
/**
 * Object's isPrototypeOf operation
 *
 * See also:
 *          ECMA-262 v5, 15.2.4.6; 3
 *
1668 1669
 * @return true - if the target object is prototype of the base object
 *         false - if the target object is not prototype of the base object
1670 1671
 */
bool
1672 1673
ecma_op_object_is_prototype_of (ecma_object_t *base_p, /**< base object */
                                ecma_object_t *target_p) /**< target object */
1674 1675 1676
{
  do
  {
1677 1678 1679
    jmem_cpointer_t target_cp = target_p->u2.prototype_cp;

    if (target_cp == JMEM_CP_NULL)
1680 1681 1682
    {
      return false;
    }
1683 1684 1685 1686

    target_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, target_cp);

    if (target_p == base_p)
1687 1688 1689 1690 1691 1692
    {
      return true;
    }
  } while (true);
} /* ecma_op_object_is_prototype_of */

1693 1694 1695 1696 1697
/**
 * Get collection of property names
 *
 * Order of names in the collection:
 *  - integer indices in ascending order
Z
Zoltan Herczeg 已提交
1698
 *  - other indices in creation order (for built-ins: the order of the properties are listed in specification).
1699 1700 1701 1702 1703 1704 1705 1706
 *
 * Note:
 *      Implementation of the routine assumes that new properties are appended to beginning of corresponding object's
 *      property list, and the list is not reordered (in other words, properties are stored in order that is reversed
 *      to the properties' addition order).
 *
 * @return collection of strings - property names
 */
R
Robert Fancsik 已提交
1707
ecma_collection_t *
1708
ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
1709
                                   uint32_t opts) /**< any combination of ecma_list_properties_options_t values  */
1710
{
1711 1712 1713
  JERRY_ASSERT (obj_p != NULL
                && !ecma_is_lexical_environment (obj_p));

1714 1715 1716 1717 1718 1719 1720 1721 1722 1723
  if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY)
  {
    ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;

    if (ext_object_p->u.array.is_fast_mode)
    {
      return ecma_fast_array_get_property_names (obj_p, opts);
    }
  }

R
Robert Fancsik 已提交
1724 1725
  ecma_collection_t *ret_p = ecma_new_collection ();
  ecma_collection_t *skipped_non_enumerable_p = ecma_new_collection ();
1726

1727
  const ecma_object_type_t type = ecma_get_object_type (obj_p);
1728
  const bool obj_is_builtin = ecma_get_object_is_builtin (obj_p);
1729 1730 1731
  const bool is_enumerable_only = (opts & ECMA_LIST_ENUMERABLE) != 0;
  const bool is_array_indices_only = (opts & ECMA_LIST_ARRAY_INDICES) != 0;
  const bool is_with_prototype_chain = (opts & ECMA_LIST_PROTOTYPE) != 0;
1732
#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
1733
  const bool is_symbols_only = (opts & ECMA_LIST_SYMBOLS) != 0;
1734
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
1735

1736
  const size_t bitmap_row_size = sizeof (uint32_t) * JERRY_BITSINBYTE;
Y
Yonggang Luo 已提交
1737 1738
  const size_t names_hashes_bitmap_size = ECMA_OBJECT_HASH_BITMAP_SIZE / bitmap_row_size;
  JERRY_VLA (uint32_t, names_hashes_bitmap, names_hashes_bitmap_size);
1739

Y
Yonggang Luo 已提交
1740
  memset (names_hashes_bitmap, 0, names_hashes_bitmap_size * sizeof (names_hashes_bitmap[0]));
1741

1742 1743 1744
  ecma_object_t *prototype_chain_iter_p = obj_p;

  while (true)
1745 1746 1747 1748
  {
    ecma_length_t string_named_properties_count = 0;
    ecma_length_t array_index_named_properties_count = 0;

R
Robert Fancsik 已提交
1749
    ecma_collection_t *prop_names_p = ecma_new_collection ();
1750

1751
#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
1752
    if (JERRY_LIKELY (!is_symbols_only))
1753
    {
1754
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
1755 1756 1757 1758 1759 1760 1761 1762 1763

      if (obj_is_builtin)
      {
        ecma_builtin_list_lazy_property_names (obj_p,
                                               is_enumerable_only,
                                               prop_names_p,
                                               skipped_non_enumerable_p);
      }
      else
1764
      {
1765
        switch (type)
1766
        {
1767
          case ECMA_OBJECT_TYPE_PSEUDO_ARRAY:
1768
          {
1769
  #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
1770 1771 1772 1773
            if (ecma_is_typedarray (ecma_make_object_value (obj_p)))
            {
              ecma_op_typedarray_list_lazy_property_names (obj_p, prop_names_p);
            }
1774
  #endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
1775
            break;
1776
          }
1777
          case ECMA_OBJECT_TYPE_FUNCTION:
1778
  #if ENABLED (JERRY_ES2015_ARROW_FUNCTION)
1779
          case ECMA_OBJECT_TYPE_ARROW_FUNCTION:
1780
  #endif /* ENABLED (JERRY_ES2015_ARROW_FUNCTION) */
1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795
          {
            ecma_op_function_list_lazy_property_names (obj_p,
                                                       is_enumerable_only,
                                                       prop_names_p,
                                                       skipped_non_enumerable_p);
            break;
          }
          case ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION:
          {
            ecma_op_external_function_list_lazy_property_names (is_enumerable_only,
                                                                prop_names_p,
                                                                skipped_non_enumerable_p);
            break;
          }
          case ECMA_OBJECT_TYPE_BOUND_FUNCTION:
1796
          {
1797 1798 1799 1800
            ecma_op_bound_function_list_lazy_property_names (is_enumerable_only,
                                                             prop_names_p,
                                                             skipped_non_enumerable_p);
            break;
1801
          }
1802 1803 1804
          case ECMA_OBJECT_TYPE_CLASS:
          {
            ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
1805

1806 1807 1808 1809 1810 1811 1812
            if (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_STRING_UL)
            {
              ecma_op_string_list_lazy_property_names (obj_p,
                                                       is_enumerable_only,
                                                       prop_names_p,
                                                       skipped_non_enumerable_p);
            }
1813

1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829
            break;
          }
          case ECMA_OBJECT_TYPE_ARRAY:
          {
            ecma_op_array_list_lazy_property_names (obj_p,
                                                    is_enumerable_only,
                                                    prop_names_p,
                                                    skipped_non_enumerable_p);
            break;
          }
          default:
          {
            JERRY_ASSERT (type == ECMA_OBJECT_TYPE_GENERAL);

            break;
          }
1830
        }
1831
      }
1832
#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
1833
    }
1834
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
1835

R
Robert Fancsik 已提交
1836
    ecma_value_t *buffer_p = prop_names_p->buffer_p;
1837

Y
Yonggang Luo 已提交
1838 1839 1840
    const size_t own_names_hashes_bitmap_size = ECMA_OBJECT_HASH_BITMAP_SIZE / bitmap_row_size;
    JERRY_VLA (uint32_t, own_names_hashes_bitmap, own_names_hashes_bitmap_size);
    memset (own_names_hashes_bitmap, 0, own_names_hashes_bitmap_size * sizeof (own_names_hashes_bitmap[0]));
1841

R
Robert Fancsik 已提交
1842
    for (uint32_t i = 0; i < prop_names_p->item_count; i++)
1843
    {
R
Robert Fancsik 已提交
1844
      ecma_string_t *name_p = ecma_get_string_from_value (buffer_p[i]);
1845

1846
#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
1847 1848
      /* Symbols are never lazy listed */
      JERRY_ASSERT (!ecma_prop_name_is_symbol (name_p));
1849
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
1850

1851
      uint8_t hash = (uint8_t) ecma_string_hash (name_p);
1852
      uint32_t bitmap_row = (uint32_t) (hash / bitmap_row_size);
1853
      uint32_t bitmap_column = (uint32_t) (hash % bitmap_row_size);
1854 1855 1856 1857 1858 1859

      if ((own_names_hashes_bitmap[bitmap_row] & (1u << bitmap_column)) == 0)
      {
        own_names_hashes_bitmap[bitmap_row] |= (1u << bitmap_column);
      }
    }
1860

1861
    jmem_cpointer_t prop_iter_cp = prototype_chain_iter_p->u1.property_list_cp;
1862

1863 1864 1865
    if (ecma_get_object_type (prototype_chain_iter_p) == ECMA_OBJECT_TYPE_ARRAY
        && ((ecma_extended_object_t *) prototype_chain_iter_p)->u.array.is_fast_mode
        && prop_iter_cp != JMEM_CP_NULL)
1866
    {
1867
      ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) prototype_chain_iter_p;
1868

1869
      uint32_t length = ext_obj_p->u.array.length;
1870

1871
      ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, prop_iter_cp);
1872

1873
      for (uint32_t i = 0; i < length; i++)
1874
      {
1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886
        if (ecma_is_value_array_hole (values_p[i]))
        {
          continue;
        }

        ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (i);

        uint8_t hash = (uint8_t) ecma_string_hash (index_str_p);
        uint32_t bitmap_row = (uint32_t) (hash / bitmap_row_size);
        uint32_t bitmap_column = (uint32_t) (hash % bitmap_row_size);

        bool is_add = true;
1887

1888
        if ((own_names_hashes_bitmap[bitmap_row] & (1u << bitmap_column)) != 0)
1889
        {
R
Robert Fancsik 已提交
1890
          buffer_p = prop_names_p->buffer_p;
1891

R
Robert Fancsik 已提交
1892
          for (uint32_t j = 0; j < prop_names_p->item_count; j++)
1893
          {
R
Robert Fancsik 已提交
1894
            ecma_string_t *current_name_p = ecma_get_prop_name_from_value (buffer_p[j]);
1895 1896 1897 1898 1899 1900

            if (ecma_compare_ecma_strings (index_str_p, current_name_p))
            {
              is_add = false;
              break;
            }
1901
          }
1902
        }
1903

1904 1905 1906
        if (is_add)
        {
          own_names_hashes_bitmap[bitmap_row] |= (1u << bitmap_column);
1907

R
Robert Fancsik 已提交
1908
          ecma_collection_push_back (prop_names_p, ecma_make_string_value (index_str_p));
1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936
        }
      }
    }
    else
    {
#if ENABLED (JERRY_PROPRETY_HASHMAP)
      if (prop_iter_cp != JMEM_CP_NULL)
      {
        ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp);

        if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP)
        {
          prop_iter_cp = prop_iter_p->next_property_cp;
        }
      }
  #endif /* ENABLED (JERRY_PROPRETY_HASHMAP) */

      while (prop_iter_cp != JMEM_CP_NULL)
      {
        ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp);
        JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p));

        for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
        {
          ecma_property_t *property_p = prop_iter_p->types + i;

          if (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA
              || ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR)
1937
          {
1938
            ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p;
1939

1940 1941 1942
            if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_MAGIC
                && prop_pair_p->names_cp[i] >= LIT_NON_INTERNAL_MAGIC_STRING__COUNT
                && prop_pair_p->names_cp[i] < LIT_MAGIC_STRING__COUNT)
1943
            {
1944
              /* Internal properties are never enumerated. */
1945 1946 1947
              continue;
            }

1948 1949
            ecma_string_t *name_p = ecma_string_from_property_name (*property_p,
                                                                    prop_pair_p->names_cp[i]);
1950

1951
            if (!(is_enumerable_only && !ecma_is_property_enumerable (*property_p)))
1952
            {
1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970
  #if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
              /* If is_symbols_only is false and prop_name is symbol
                 we should skip the current property e.g. for-in.

                 Also if is_symbols_only is true and prop_name is not symbol
                 we should skip the current property e.g. Object.getOwnPropertySymbols. */
              if (JERRY_UNLIKELY (is_symbols_only != ecma_prop_name_is_symbol (name_p)))
              {
                ecma_deref_ecma_string (name_p);
                continue;
              }
  #endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */

              uint8_t hash = (uint8_t) ecma_string_hash (name_p);
              uint32_t bitmap_row = (uint32_t) (hash / bitmap_row_size);
              uint32_t bitmap_column = (uint32_t) (hash % bitmap_row_size);

              bool is_add = true;
1971

1972
              if ((own_names_hashes_bitmap[bitmap_row] & (1u << bitmap_column)) != 0)
1973
              {
R
Robert Fancsik 已提交
1974
                buffer_p = prop_names_p->buffer_p;
1975

R
Robert Fancsik 已提交
1976
                for (uint32_t j = 0; j < prop_names_p->item_count; j++)
1977
                {
R
Robert Fancsik 已提交
1978
                  ecma_string_t *current_name_p = ecma_get_prop_name_from_value (buffer_p[j]);
1979 1980 1981 1982 1983 1984

                  if (ecma_compare_ecma_strings (name_p, current_name_p))
                  {
                    is_add = false;
                    break;
                  }
1985
                }
1986
              }
1987

1988 1989 1990 1991
              if (is_add)
              {
                own_names_hashes_bitmap[bitmap_row] |= (1u << bitmap_column);

R
Robert Fancsik 已提交
1992 1993 1994 1995 1996
                ecma_collection_push_back (prop_names_p, ecma_make_prop_name_value (name_p));
              }
              else
              {
                ecma_deref_ecma_string (name_p);
1997 1998 1999
              }
            }
            else
2000
            {
2001
              JERRY_ASSERT (is_enumerable_only && !ecma_is_property_enumerable (*property_p));
2002

R
Robert Fancsik 已提交
2003
              ecma_collection_push_back (skipped_non_enumerable_p, ecma_make_prop_name_value (name_p));
2004
            }
2005 2006
          }
        }
2007

2008 2009
        prop_iter_cp = prop_iter_p->next_property_cp;
      }
2010 2011
    }

R
Robert Fancsik 已提交
2012
    buffer_p = prop_names_p->buffer_p;
Z
Zoltan Herczeg 已提交
2013

R
Robert Fancsik 已提交
2014
    for (uint32_t i = 0; i < prop_names_p->item_count; i++)
2015
    {
R
Robert Fancsik 已提交
2016
      ecma_string_t *name_p = ecma_get_prop_name_from_value (buffer_p[i]);
2017

2018
      uint32_t index = ecma_string_get_array_index (name_p);
2019

2020
      if (index != ECMA_STRING_NOT_ARRAY_INDEX)
2021
      {
2022
        /* The name is a valid array index. */
2023 2024 2025 2026 2027 2028 2029 2030
        array_index_named_properties_count++;
      }
      else if (!is_array_indices_only)
      {
        string_named_properties_count++;
      }
    }

2031
    /* Second pass: collecting property names into arrays. */
2032 2033 2034 2035
    JMEM_DEFINE_LOCAL_ARRAY (names_p,
                             array_index_named_properties_count + string_named_properties_count,
                             ecma_string_t *);
    JMEM_DEFINE_LOCAL_ARRAY (array_index_names_p, array_index_named_properties_count, uint32_t);
2036 2037 2038 2039

    uint32_t name_pos = array_index_named_properties_count + string_named_properties_count;
    uint32_t array_index_name_pos = 0;

R
Robert Fancsik 已提交
2040
    buffer_p = prop_names_p->buffer_p;
Z
Zoltan Herczeg 已提交
2041

R
Robert Fancsik 已提交
2042
    for (uint32_t i = 0; i < prop_names_p->item_count; i++)
2043
    {
R
Robert Fancsik 已提交
2044
      ecma_string_t *name_p = ecma_get_prop_name_from_value (buffer_p[i]);
2045

2046
      uint32_t index = ecma_string_get_array_index (name_p);
2047

2048
      if (index != ECMA_STRING_NOT_ARRAY_INDEX)
2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067
      {
        JERRY_ASSERT (array_index_name_pos < array_index_named_properties_count);

        uint32_t insertion_pos = 0;
        while (insertion_pos < array_index_name_pos
               && index < array_index_names_p[insertion_pos])
        {
          insertion_pos++;
        }

        if (insertion_pos == array_index_name_pos)
        {
          array_index_names_p[array_index_name_pos++] = index;
        }
        else
        {
          JERRY_ASSERT (insertion_pos < array_index_name_pos);
          JERRY_ASSERT (index >= array_index_names_p[insertion_pos]);

2068
          uint32_t move_pos = array_index_name_pos++;
2069

2070
          while (move_pos > insertion_pos)
2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088
          {
            array_index_names_p[move_pos] = array_index_names_p[move_pos - 1u];

            move_pos--;
          }

          array_index_names_p[insertion_pos] = index;
        }
      }
      else if (!is_array_indices_only)
      {
        /*
         * Filling from end to begin, as list of object's properties is sorted
         * in order that is reverse to properties creation order
         */

        JERRY_ASSERT (name_pos > 0
                      && name_pos <= array_index_named_properties_count + string_named_properties_count);
2089 2090
        ecma_ref_ecma_string (name_p);
        names_p[--name_pos] = name_p;
2091 2092 2093
      }
    }

2094 2095 2096 2097 2098 2099 2100 2101 2102
    for (uint32_t i = 0; i < array_index_named_properties_count; i++)
    {
      JERRY_ASSERT (name_pos > 0
                    && name_pos <= array_index_named_properties_count + string_named_properties_count);
      names_p[--name_pos] = ecma_new_ecma_string_from_uint32 (array_index_names_p[i]);
    }

    JERRY_ASSERT (name_pos == 0);

2103
    JMEM_FINALIZE_LOCAL_ARRAY (array_index_names_p);
2104

R
Robert Fancsik 已提交
2105
    ecma_collection_free (prop_names_p);
2106 2107 2108

    /* Third pass:
     *   embedding own property names of current object of prototype chain to aggregate property names collection */
2109 2110 2111 2112
    for (uint32_t i = 0;
         i < array_index_named_properties_count + string_named_properties_count;
         i++)
    {
2113
      bool is_append = true;
2114 2115 2116

      ecma_string_t *name_p = names_p[i];

2117
      uint8_t hash = (uint8_t) ecma_string_hash (name_p);
2118
      uint32_t bitmap_row = (uint32_t) (hash / bitmap_row_size);
2119
      uint32_t bitmap_column = (uint32_t) (hash % bitmap_row_size);
2120 2121 2122

      if ((names_hashes_bitmap[bitmap_row] & (1u << bitmap_column)) == 0)
      {
2123
        /* This hash has not been used before (for non-skipped). */
2124 2125 2126 2127
        names_hashes_bitmap[bitmap_row] |= (1u << bitmap_column);
      }
      else
      {
2128
        /* Name with same hash has already occured. */
R
Robert Fancsik 已提交
2129
        buffer_p = ret_p->buffer_p;
2130

R
Robert Fancsik 已提交
2131
        for (uint32_t j = 0; j < ret_p->item_count; j++)
2132
        {
R
Robert Fancsik 已提交
2133
          ecma_string_t *current_name_p = ecma_get_prop_name_from_value (buffer_p[j]);
2134

Z
Zoltan Herczeg 已提交
2135
          if (ecma_compare_ecma_strings (name_p, current_name_p))
2136
          {
2137 2138
            is_append = false;
            break;
2139 2140
          }
        }
2141
      }
2142

2143 2144
      if (is_append)
      {
R
Robert Fancsik 已提交
2145
        buffer_p = skipped_non_enumerable_p->buffer_p;
Z
Zoltan Herczeg 已提交
2146

R
Robert Fancsik 已提交
2147
        for (uint32_t j = 0; j < skipped_non_enumerable_p->item_count; j++)
2148
        {
R
Robert Fancsik 已提交
2149
          ecma_string_t *current_name_p = ecma_get_prop_name_from_value (buffer_p[j]);
2150

Z
Zoltan Herczeg 已提交
2151
          if (ecma_compare_ecma_strings (name_p, current_name_p))
2152
          {
2153 2154
            is_append = false;
            break;
2155 2156 2157 2158 2159 2160 2161 2162
          }
        }
      }

      if (is_append)
      {
        JERRY_ASSERT ((names_hashes_bitmap[bitmap_row] & (1u << bitmap_column)) != 0);

R
Robert Fancsik 已提交
2163 2164 2165 2166 2167
        ecma_collection_push_back (ret_p, ecma_make_prop_name_value (name_p));
      }
      else
      {
        ecma_deref_ecma_string (name_p);
2168 2169 2170 2171
      }

    }

2172
    JMEM_FINALIZE_LOCAL_ARRAY (names_p);
2173 2174 2175 2176 2177 2178 2179 2180 2181


    if (!is_with_prototype_chain || prototype_chain_iter_p->u2.prototype_cp == JMEM_CP_NULL)
    {
      break;
    }

    prototype_chain_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t,
                                                        prototype_chain_iter_p->u2.prototype_cp);
2182 2183
  }

R
Robert Fancsik 已提交
2184
  ecma_collection_free (skipped_non_enumerable_p);
2185 2186 2187 2188

  return ret_p;
} /* ecma_op_object_get_property_names */

2189 2190
/**
 * The function is used in the assert of ecma_object_get_class_name
2191 2192 2193
 *
 * @return true  - if class name is an object
 *         false - otherwise
2194 2195 2196 2197 2198 2199
 */
inline static bool
ecma_object_check_class_name_is_object (ecma_object_t *obj_p) /**< object */
{
#ifndef JERRY_NDEBUG
  return (ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_GLOBAL)
2200
#if ENABLED (JERRY_ES2015_BUILTIN_PROMISE)
2201
          || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_PROMISE_PROTOTYPE)
2202 2203
#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
2204
          || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE)
2205 2206 2207 2208 2209 2210 2211 2212 2213
          || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE)
          || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_INT8ARRAY_PROTOTYPE)
          || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_UINT8ARRAY_PROTOTYPE)
          || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_INT16ARRAY_PROTOTYPE)
          || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_UINT16ARRAY_PROTOTYPE)
          || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_INT32ARRAY_PROTOTYPE)
          || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_UINT32ARRAY_PROTOTYPE)
          || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_FLOAT32ARRAY_PROTOTYPE)
          || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_UINT8CLAMPEDARRAY_PROTOTYPE)
2214
#if ENABLED (JERRY_NUMBER_TYPE_FLOAT64)
2215
          || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_FLOAT64ARRAY_PROTOTYPE)
2216 2217 2218
#endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */
#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
#if ENABLED (JERRY_ES2015_BUILTIN_ITERATOR)
2219 2220
          || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_ARRAY_ITERATOR_PROTOTYPE)
          || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_ITERATOR_PROTOTYPE)
2221
          || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_STRING_ITERATOR_PROTOTYPE)
2222 2223
#endif /* ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) */
#if ENABLED (JERRY_ES2015_BUILTIN_MAP)
2224
          || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_MAP_PROTOTYPE)
2225 2226 2227
#if ENABLED (JERRY_ES2015_BUILTIN_ITERATOR)
          || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_MAP_ITERATOR_PROTOTYPE)
#endif /* ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) */
2228
#endif /* ENABLED (JERRY_ES2015_BUILTIN_MAP) */
2229 2230
#if ENABLED (JERRY_ES2015_BUILTIN_SET)
          || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_SET_PROTOTYPE)
2231 2232 2233
#if ENABLED (JERRY_ES2015_BUILTIN_ITERATOR)
          || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_SET_ITERATOR_PROTOTYPE)
#endif /* ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) */
2234
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SET) */
2235
#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
2236
          || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_SYMBOL_PROTOTYPE)
2237
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
2238 2239 2240
#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW)
          || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_DATAVIEW_PROTOTYPE)
#endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) */
2241 2242 2243 2244 2245 2246 2247
          || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE));
#else /* JERRY_NDEBUG */
  JERRY_UNUSED (obj_p);
  return true;
#endif /* !JERRY_NDEBUG */
} /* ecma_object_check_class_name_is_object */

2248 2249 2250 2251 2252
/**
 * Get [[Class]] string of specified object
 *
 * @return class name magic string
 */
2253
lit_magic_string_id_t
2254 2255 2256 2257 2258 2259 2260 2261
ecma_object_get_class_name (ecma_object_t *obj_p) /**< object */
{
  ecma_object_type_t type = ecma_get_object_type (obj_p);

  switch (type)
  {
    case ECMA_OBJECT_TYPE_ARRAY:
    {
2262
      return LIT_MAGIC_STRING_ARRAY_UL;
2263
    }
2264
    case ECMA_OBJECT_TYPE_CLASS:
2265
    {
2266
      ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
2267
      return (lit_magic_string_id_t) ext_object_p->u.class_prop.class_id;
2268
    }
2269
    case ECMA_OBJECT_TYPE_PSEUDO_ARRAY:
2270
    {
2271 2272 2273 2274
      ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p;

      switch (ext_obj_p->u.pseudo_array.type)
      {
2275
#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
2276 2277 2278
        case ECMA_PSEUDO_ARRAY_TYPEDARRAY:
        case ECMA_PSEUDO_ARRAY_TYPEDARRAY_WITH_INFO:
        {
2279
          return (lit_magic_string_id_t) ext_obj_p->u.pseudo_array.u1.class_id;
2280
        }
2281 2282
#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
#if ENABLED (JERRY_ES2015_BUILTIN_ITERATOR)
2283 2284 2285 2286
        case ECMA_PSEUDO_ARRAY_ITERATOR:
        {
          return LIT_MAGIC_STRING_ARRAY_ITERATOR_UL;
        }
2287 2288 2289 2290 2291 2292 2293 2294
        case ECMA_PSEUDO_SET_ITERATOR:
        {
          return LIT_MAGIC_STRING_SET_ITERATOR_UL;
        }
        case ECMA_PSEUDO_MAP_ITERATOR:
        {
          return LIT_MAGIC_STRING_MAP_ITERATOR_UL;
        }
2295 2296 2297 2298 2299 2300
#endif /* ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) */
#if ENABLED (JERRY_ES2015_BUILTIN_ITERATOR)
        case ECMA_PSEUDO_STRING_ITERATOR:
        {
          return LIT_MAGIC_STRING_STRING_ITERATOR_UL;
        }
2301
#endif /* ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) */
2302 2303
        default:
        {
2304 2305 2306
          JERRY_ASSERT (ext_obj_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS);

          return LIT_MAGIC_STRING_ARGUMENTS_UL;
2307 2308 2309 2310
        }
      }

      break;
2311 2312
    }
    case ECMA_OBJECT_TYPE_FUNCTION:
2313
#if ENABLED (JERRY_ES2015_ARROW_FUNCTION)
2314
    case ECMA_OBJECT_TYPE_ARROW_FUNCTION:
2315
#endif /* ENABLED (JERRY_ES2015_ARROW_FUNCTION) */
2316
    case ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION:
2317
    case ECMA_OBJECT_TYPE_BOUND_FUNCTION:
2318
    {
2319
      return LIT_MAGIC_STRING_FUNCTION_UL;
2320 2321 2322 2323 2324 2325 2326
    }
    default:
    {
      JERRY_ASSERT (type == ECMA_OBJECT_TYPE_GENERAL);

      if (ecma_get_object_is_builtin (obj_p))
      {
2327
        ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p;
2328

2329
        switch (ext_obj_p->u.built_in.id)
2330
        {
2331
#if ENABLED (JERRY_BUILTIN_MATH)
2332 2333
          case ECMA_BUILTIN_ID_MATH:
          {
2334
            return LIT_MAGIC_STRING_MATH_UL;
2335
          }
2336 2337
#endif /* ENABLED (JERRY_BUILTIN_MATH) */
#if ENABLED (JERRY_BUILTIN_JSON)
Z
Zoltan Herczeg 已提交
2338 2339 2340 2341
          case ECMA_BUILTIN_ID_JSON:
          {
            return LIT_MAGIC_STRING_JSON_U;
          }
2342 2343
#endif /* ENABLED (JERRY_BUILTIN_JSON) */
#if ENABLED (JERRY_BUILTIN_ERRORS)
2344 2345 2346 2347 2348 2349
          case ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE:
          case ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE:
          case ECMA_BUILTIN_ID_REFERENCE_ERROR_PROTOTYPE:
          case ECMA_BUILTIN_ID_SYNTAX_ERROR_PROTOTYPE:
          case ECMA_BUILTIN_ID_TYPE_ERROR_PROTOTYPE:
          case ECMA_BUILTIN_ID_URI_ERROR_PROTOTYPE:
2350
#endif /* ENABLED (JERRY_BUILTIN_ERRORS) */
R
Robert Sipka 已提交
2351
          case ECMA_BUILTIN_ID_ERROR_PROTOTYPE:
2352
          {
2353
            return LIT_MAGIC_STRING_ERROR_UL;
2354 2355 2356
          }
          default:
          {
2357
            JERRY_ASSERT (ecma_object_check_class_name_is_object (obj_p));
2358

2359
            return LIT_MAGIC_STRING_OBJECT_UL;
2360 2361 2362 2363 2364
          }
        }
      }
      else
      {
2365
        return LIT_MAGIC_STRING_OBJECT_UL;
2366 2367 2368 2369
      }
    }
  }
} /* ecma_object_get_class_name */
2370

2371 2372 2373 2374
/**
 * Get value of an object if the class matches
 *
 * @return value of the object if the class matches
2375
 *         ECMA_VALUE_NOT_FOUND otherwise
2376
 */
2377
inline bool JERRY_ATTR_ALWAYS_INLINE
2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393
ecma_object_class_is (ecma_object_t *object_p, /**< object */
                      uint32_t class_id) /**< class id */
{
  if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_CLASS)
  {
    ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;

    if (ext_object_p->u.class_prop.class_id == class_id)
    {
      return true;
    }
  }

  return false;
} /* ecma_object_class_is */

2394 2395 2396 2397
/**
 * @}
 * @}
 */