• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright JS Foundation and other contributors, http://js.foundation
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecma-array-object.h"
17 #include "ecma-builtins.h"
18 #include "ecma-exceptions.h"
19 #include "ecma-function-object.h"
20 #include "ecma-gc.h"
21 #include "ecma-globals.h"
22 #include "ecma-helpers.h"
23 #include "ecma-objects.h"
24 #include "ecma-objects-general.h"
25 #include "ecma-proxy-object.h"
26 #include "ecma-try-catch-macro.h"
27 
28 /** \addtogroup ecma ECMA
29  * @{
30  *
31  * \addtogroup ecmaobjectsinternalops ECMA objects' operations
32  * @{
33  */
34 
35 /**
36  * Reject sequence
37  *
38  * @return ecma value
39  *         Returned value must be freed with ecma_free_value
40  */
41 ecma_value_t
ecma_reject(bool is_throw)42 ecma_reject (bool is_throw) /**< Throw flag */
43 {
44   if (is_throw)
45   {
46     return ecma_raise_type_error (ECMA_ERR_MSG ("Invalid argument type."));
47   }
48   else
49   {
50     return ECMA_VALUE_FALSE;
51   }
52 } /* ecma_reject */
53 
54 /**
55  * 'Object' object creation operation with no arguments.
56  *
57  * See also: ECMA-262 v5, 15.2.2.1
58  *
59  * @return pointer to newly created 'Object' object
60  */
61 ecma_object_t *
ecma_op_create_object_object_noarg(void)62 ecma_op_create_object_object_noarg (void)
63 {
64   ecma_object_t *object_prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE);
65 
66   /* 3., 4., 6., 7. */
67   return ecma_op_create_object_object_noarg_and_set_prototype (object_prototype_p);
68 } /* ecma_op_create_object_object_noarg */
69 
70 /**
71  * 'Object' object creation operation with one argument.
72  *
73  * See also: ECMA-262 v5, 15.2.2.1
74  *
75  * @return pointer to newly created 'Object' object
76  */
77 ecma_value_t
ecma_op_create_object_object_arg(ecma_value_t value)78 ecma_op_create_object_object_arg (ecma_value_t value) /**< argument of constructor */
79 {
80   ecma_check_value_type_is_spec_defined (value);
81 
82   if (ecma_is_value_object (value)
83       || ecma_is_value_number (value)
84       || ecma_is_value_prop_name (value)
85       || ecma_is_value_boolean (value))
86   {
87     /* 1.b, 1.c, 1.d */
88     return ecma_op_to_object (value);
89   }
90   else
91   {
92     /* 2. */
93     JERRY_ASSERT (ecma_is_value_undefined (value)
94                   || ecma_is_value_null (value));
95 
96     ecma_object_t *obj_p = ecma_op_create_object_object_noarg ();
97 
98     return ecma_make_object_value (obj_p);
99   }
100 } /* ecma_op_create_object_object_arg */
101 
102 /**
103  * Object creation operation with no arguments.
104  * It sets the given prototype to the newly created object.
105  *
106  * See also: ECMA-262 v5, 15.2.2.1, 15.2.3.5
107  *
108  * @return pointer to newly created object
109  */
110 ecma_object_t *
ecma_op_create_object_object_noarg_and_set_prototype(ecma_object_t * object_prototype_p)111 ecma_op_create_object_object_noarg_and_set_prototype (ecma_object_t *object_prototype_p) /**< pointer to prototype of
112                                                                                               the object
113                                                                                               (can be NULL) */
114 {
115   ecma_object_t *obj_p = ecma_create_object (object_prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL);
116 
117   /*
118    * [[Class]] property of ECMA_OBJECT_TYPE_GENERAL type objects
119    * without ECMA_INTERNAL_PROPERTY_CLASS internal property
120    * is "Object".
121    *
122    * See also: ecma_object_get_class_name
123    */
124 
125   return obj_p;
126 } /* ecma_op_create_object_object_noarg_and_set_prototype */
127 
128 /**
129  * [[Delete]] ecma general object's operation
130  *
131  * See also:
132  *          ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
133  *          ECMA-262 v5, 8.12.7
134  *
135  * @return ecma value
136  *         Returned value must be freed with ecma_free_value
137  */
138 ecma_value_t
ecma_op_general_object_delete(ecma_object_t * obj_p,ecma_string_t * property_name_p,bool is_throw)139 ecma_op_general_object_delete (ecma_object_t *obj_p, /**< the object */
140                                ecma_string_t *property_name_p, /**< property name */
141                                bool is_throw) /**< flag that controls failure handling */
142 {
143   JERRY_ASSERT (obj_p != NULL
144                 && !ecma_is_lexical_environment (obj_p));
145   JERRY_ASSERT (property_name_p != NULL);
146 
147   /* 1. */
148   ecma_property_ref_t property_ref;
149 
150   ecma_property_t property = ecma_op_object_get_own_property (obj_p,
151                                                               property_name_p,
152                                                               &property_ref,
153                                                               ECMA_PROPERTY_GET_NO_OPTIONS);
154 
155   /* 2. */
156   if (property == ECMA_PROPERTY_TYPE_NOT_FOUND || property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP)
157   {
158     return ECMA_VALUE_TRUE;
159   }
160 
161   /* 3. */
162   if (ecma_is_property_configurable (property))
163   {
164     if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY)
165     {
166       ecma_array_object_delete_property (obj_p, property_name_p, property_ref.value_p);
167     }
168     else
169     {
170       /* a. */
171       ecma_delete_property (obj_p, property_ref.value_p);
172     }
173 
174     /* b. */
175     return ECMA_VALUE_TRUE;
176   }
177 
178   /* 4. */
179   if (is_throw)
180   {
181     return ecma_raise_type_error (ECMA_ERR_MSG ("Expected a configurable property."));
182   }
183 
184   /* 5. */
185   return ECMA_VALUE_FALSE;
186 } /* ecma_op_general_object_delete */
187 
188 /**
189  * Property invocation order during [[DefaultValue]] operation with string hint
190  */
191 static const lit_magic_string_id_t to_primitive_string_hint_method_names[2] =
192 {
193   LIT_MAGIC_STRING_TO_STRING_UL, /**< toString operation */
194   LIT_MAGIC_STRING_VALUE_OF_UL, /**< valueOf operation */
195 };
196 
197 /**
198  * Property invocation order during [[DefaultValue]] operation with non string hint
199  */
200 static const lit_magic_string_id_t to_primitive_non_string_hint_method_names[2] =
201 {
202   LIT_MAGIC_STRING_VALUE_OF_UL, /**< valueOf operation */
203   LIT_MAGIC_STRING_TO_STRING_UL, /**< toString operation */
204 };
205 
206 #if ENABLED (JERRY_ES2015)
207 /**
208  * Hints for the ecma general object's toPrimitve operation
209  */
210 static const lit_magic_string_id_t hints[3] =
211 {
212   LIT_MAGIC_STRING_DEFAULT, /**< "default" hint */
213   LIT_MAGIC_STRING_NUMBER, /**< "number" hint */
214   LIT_MAGIC_STRING_STRING, /**< "string" hint */
215 };
216 #endif /* ENABLED (JERRY_ES2015) */
217 
218 /**
219  * [[DefaultValue]] ecma general object's operation
220  *
221  * See also:
222  *          ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
223  *          ECMA-262 v5, 8.12.8
224  *
225  * @return ecma value
226  *         Returned value must be freed with ecma_free_value
227  */
228 ecma_value_t
ecma_op_general_object_default_value(ecma_object_t * obj_p,ecma_preferred_type_hint_t hint)229 ecma_op_general_object_default_value (ecma_object_t *obj_p, /**< the object */
230                                       ecma_preferred_type_hint_t hint) /**< hint on preferred result type */
231 {
232   JERRY_ASSERT (obj_p != NULL
233                 && !ecma_is_lexical_environment (obj_p));
234 
235 #if ENABLED (JERRY_ES2015)
236   ecma_value_t obj_value = ecma_make_object_value (obj_p);
237 
238   ecma_value_t exotic_to_prim = ecma_op_get_method_by_symbol_id (obj_value,
239                                                                  LIT_GLOBAL_SYMBOL_TO_PRIMITIVE);
240 
241   if (ECMA_IS_VALUE_ERROR (exotic_to_prim))
242   {
243     return exotic_to_prim;
244   }
245 
246   if (!ecma_is_value_undefined (exotic_to_prim))
247   {
248     ecma_object_t *call_func_p = ecma_get_object_from_value (exotic_to_prim);
249     ecma_value_t argument = ecma_make_magic_string_value (hints[hint]);
250 
251     ecma_value_t result = ecma_op_function_call (call_func_p,
252                                                  obj_value,
253                                                  &argument,
254                                                  1);
255 
256     ecma_free_value (exotic_to_prim);
257 
258     if (ECMA_IS_VALUE_ERROR (result)
259         || !ecma_is_value_object (result))
260     {
261       return result;
262     }
263 
264     ecma_free_value (result);
265 
266     return ecma_raise_type_error (ECMA_ERR_MSG ("Invalid argument type in [[DefaultValue]]."));
267   }
268 
269   ecma_free_value (exotic_to_prim);
270 
271   if (hint == ECMA_PREFERRED_TYPE_NO)
272   {
273     hint = ECMA_PREFERRED_TYPE_NUMBER;
274   }
275 #else /* !ENABLED (JERRY_ES2015) */
276   if (hint == ECMA_PREFERRED_TYPE_NO)
277   {
278     if (ecma_object_class_is (obj_p, LIT_MAGIC_STRING_DATE_UL))
279     {
280       hint = ECMA_PREFERRED_TYPE_STRING;
281     }
282     else
283     {
284       hint = ECMA_PREFERRED_TYPE_NUMBER;
285     }
286   }
287 #endif /* ENABLED (JERRY_ES2015) */
288 
289   return ecma_op_general_object_ordinary_value (obj_p, hint);
290 } /* ecma_op_general_object_default_value */
291 
292 /**
293  * Ecma general object's OrdinaryToPrimitive operation
294  *
295  * See also:
296  *          ECMA-262 v6 7.1.1
297  *
298  * @return ecma value
299  *         Returned value must be freed with ecma_free_value
300  */
301 ecma_value_t
ecma_op_general_object_ordinary_value(ecma_object_t * obj_p,ecma_preferred_type_hint_t hint)302 ecma_op_general_object_ordinary_value (ecma_object_t *obj_p, /**< the object */
303                                        ecma_preferred_type_hint_t hint) /**< hint on preferred result type */
304 {
305   const lit_magic_string_id_t *function_name_ids_p = (hint == ECMA_PREFERRED_TYPE_STRING
306                                                       ? to_primitive_string_hint_method_names
307                                                       : to_primitive_non_string_hint_method_names);
308 
309   for (uint32_t i = 0; i < 2; i++)
310   {
311     ecma_value_t function_value = ecma_op_object_get_by_magic_id (obj_p, function_name_ids_p[i]);
312 
313     if (ECMA_IS_VALUE_ERROR (function_value))
314     {
315       return function_value;
316     }
317 
318     ecma_value_t call_completion = ECMA_VALUE_EMPTY;
319 
320     if (ecma_op_is_callable (function_value))
321     {
322       ecma_object_t *func_obj_p = ecma_get_object_from_value (function_value);
323 
324       call_completion = ecma_op_function_call (func_obj_p,
325                                                ecma_make_object_value (obj_p),
326                                                NULL,
327                                                0);
328     }
329 
330     ecma_free_value (function_value);
331 
332     if (ECMA_IS_VALUE_ERROR (call_completion)
333         || (!ecma_is_value_empty (call_completion)
334            && !ecma_is_value_object (call_completion)))
335     {
336       return call_completion;
337     }
338 
339     ecma_free_value (call_completion);
340   }
341 
342   return ecma_raise_type_error (ECMA_ERR_MSG ("Invalid argument type in [[DefaultValue]]."));
343 } /* ecma_op_general_object_ordinary_value */
344 
345 /**
346  * Special type for ecma_op_general_object_define_own_property.
347  */
348 #define ECMA_PROPERTY_TYPE_GENERIC ECMA_PROPERTY_TYPE_SPECIAL
349 
350 /**
351  * [[DefineOwnProperty]] ecma general object's operation
352  *
353  * See also:
354  *          ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
355  *          ECMA-262 v5, 8.12.9
356  *
357  * @return ecma value
358  *         Returned value must be freed with ecma_free_value
359  */
360 ecma_value_t
ecma_op_general_object_define_own_property(ecma_object_t * object_p,ecma_string_t * property_name_p,const ecma_property_descriptor_t * property_desc_p)361 ecma_op_general_object_define_own_property (ecma_object_t *object_p, /**< the object */
362                                             ecma_string_t *property_name_p, /**< property name */
363                                             const ecma_property_descriptor_t *property_desc_p) /**< property
364                                                                                                 *   descriptor */
365 {
366 #if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
367   if (ECMA_OBJECT_IS_PROXY (object_p))
368   {
369     return ecma_proxy_object_define_own_property (object_p, property_name_p, property_desc_p);
370   }
371 #endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
372 
373   JERRY_ASSERT (object_p != NULL
374                 && !ecma_is_lexical_environment (object_p));
375   JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p));
376   JERRY_ASSERT (property_name_p != NULL);
377 
378   ecma_property_types_t property_desc_type = ECMA_PROPERTY_TYPE_GENERIC;
379 
380   if (property_desc_p->flags & (ECMA_PROP_IS_VALUE_DEFINED | ECMA_PROP_IS_WRITABLE_DEFINED))
381   {
382     /* A property descriptor cannot be both named data and named accessor. */
383     JERRY_ASSERT ((property_desc_p->flags & (ECMA_PROP_IS_GET_DEFINED | ECMA_PROP_IS_SET_DEFINED))
384                    != (ECMA_PROP_IS_GET_DEFINED | ECMA_PROP_IS_SET_DEFINED));
385     property_desc_type = ECMA_PROPERTY_TYPE_NAMEDDATA;
386   }
387   else if (property_desc_p->flags & (ECMA_PROP_IS_GET_DEFINED | ECMA_PROP_IS_SET_DEFINED))
388   {
389     JERRY_ASSERT (!(property_desc_p->flags & ECMA_PROP_IS_WRITABLE_DEFINED));
390     property_desc_type = ECMA_PROPERTY_TYPE_NAMEDACCESSOR;
391   }
392 
393   /* These three asserts ensures that a new property is created with the appropriate default flags.
394    * E.g. if ECMA_PROP_IS_CONFIGURABLE_DEFINED is false, the newly created property must be non-configurable. */
395   JERRY_ASSERT ((property_desc_p->flags & ECMA_PROP_IS_CONFIGURABLE_DEFINED)
396                 || !(property_desc_p->flags & ECMA_PROP_IS_CONFIGURABLE));
397   JERRY_ASSERT ((property_desc_p->flags & ECMA_PROP_IS_ENUMERABLE_DEFINED)
398                 || !(property_desc_p->flags & ECMA_PROP_IS_ENUMERABLE));
399   JERRY_ASSERT ((property_desc_p->flags & ECMA_PROP_IS_WRITABLE_DEFINED)
400                 || !(property_desc_p->flags & ECMA_PROP_IS_WRITABLE));
401 
402   /* 1. */
403   ecma_extended_property_ref_t ext_property_ref = { .property_ref.value_p = NULL, .property_p = NULL };
404   ecma_property_t current_prop;
405 
406   current_prop = ecma_op_object_get_own_property (object_p,
407                                                   property_name_p,
408                                                   &ext_property_ref.property_ref,
409                                                   ECMA_PROPERTY_GET_VALUE | ECMA_PROPERTY_GET_EXT_REFERENCE);
410 
411   if (current_prop == ECMA_PROPERTY_TYPE_NOT_FOUND || current_prop == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP)
412   {
413     /* 3. */
414     if (!ecma_op_ordinary_object_is_extensible (object_p))
415     {
416       /* 2. */
417       return ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW);
418     }
419 
420     /* 4. */
421     uint8_t prop_attributes = (uint8_t) (property_desc_p->flags & ECMA_PROPERTY_FLAGS_MASK);
422 
423     if (property_desc_type != ECMA_PROPERTY_TYPE_NAMEDACCESSOR)
424     {
425       /* a. */
426       JERRY_ASSERT (property_desc_type == ECMA_PROPERTY_TYPE_GENERIC
427                     || property_desc_type == ECMA_PROPERTY_TYPE_NAMEDDATA);
428 
429       ecma_property_value_t *new_prop_value_p = ecma_create_named_data_property (object_p,
430                                                                                  property_name_p,
431                                                                                  prop_attributes,
432                                                                                  NULL);
433 
434       JERRY_ASSERT ((property_desc_p->flags & ECMA_PROP_IS_VALUE_DEFINED)
435                     || ecma_is_value_undefined (property_desc_p->value));
436 
437       new_prop_value_p->value = ecma_copy_value_if_not_object (property_desc_p->value);
438     }
439     else
440     {
441       /* b. */
442 
443       ecma_create_named_accessor_property (object_p,
444                                            property_name_p,
445                                            property_desc_p->get_p,
446                                            property_desc_p->set_p,
447                                            prop_attributes,
448                                            NULL);
449     }
450 
451     return ECMA_VALUE_TRUE;
452   }
453 
454   /* 6. */
455   ecma_property_types_t current_property_type = ECMA_PROPERTY_GET_TYPE (current_prop);
456   const bool is_current_configurable = ecma_is_property_configurable (current_prop);
457 
458   JERRY_ASSERT (current_property_type == ECMA_PROPERTY_TYPE_NAMEDDATA
459                 || current_property_type == ECMA_PROPERTY_TYPE_NAMEDACCESSOR
460                 || current_property_type == ECMA_PROPERTY_TYPE_VIRTUAL);
461 
462   /* 7. a., b. */
463   bool is_enumerable = (property_desc_p->flags & ECMA_PROP_IS_ENUMERABLE) != 0;
464   if (!is_current_configurable
465       && ((property_desc_p->flags & ECMA_PROP_IS_CONFIGURABLE)
466           || ((property_desc_p->flags & ECMA_PROP_IS_ENUMERABLE_DEFINED)
467               && (is_enumerable != ecma_is_property_enumerable (current_prop)))))
468   {
469     if (current_property_type == ECMA_PROPERTY_TYPE_VIRTUAL)
470     {
471       ecma_free_value (ext_property_ref.property_ref.virtual_value);
472     }
473     return ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW);
474   }
475 
476   if (current_property_type == ECMA_PROPERTY_TYPE_VIRTUAL)
477   {
478     JERRY_ASSERT (!is_current_configurable && !ecma_is_property_writable (current_prop));
479 
480     ecma_value_t result = ECMA_VALUE_TRUE;
481 
482     if (property_desc_type == ECMA_PROPERTY_TYPE_NAMEDACCESSOR
483         || (property_desc_p->flags & ECMA_PROP_IS_WRITABLE)
484         || ((property_desc_p->flags & ECMA_PROP_IS_VALUE_DEFINED)
485             && !ecma_op_same_value (property_desc_p->value,
486                                     ext_property_ref.property_ref.virtual_value)))
487     {
488       result = ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW);
489     }
490 
491     ecma_free_value (ext_property_ref.property_ref.virtual_value);
492     return result;
493   }
494 
495   /* 8. */
496   if (property_desc_type == ECMA_PROPERTY_TYPE_GENERIC)
497   {
498     /* No action required. */
499   }
500   else if (JERRY_LIKELY (property_desc_type == current_property_type))
501   {
502     /* If property is configurable, there is no need for checks. */
503     if (JERRY_UNLIKELY (!is_current_configurable))
504     {
505       if (property_desc_type == ECMA_PROPERTY_TYPE_NAMEDDATA)
506       {
507         /* 10. a. i. & ii. */
508         if (!ecma_is_property_writable (current_prop)
509             && ((property_desc_p->flags & ECMA_PROP_IS_WRITABLE)
510                 || ((property_desc_p->flags & ECMA_PROP_IS_VALUE_DEFINED)
511                     && !ecma_op_same_value (property_desc_p->value,
512                                             ext_property_ref.property_ref.value_p->value))))
513         {
514           return ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW);
515         }
516       }
517       else
518       {
519         /* 11. */
520 
521         /* a. */
522         ecma_property_value_t *value_p = ext_property_ref.property_ref.value_p;
523 
524         ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (value_p);
525         jmem_cpointer_t prop_desc_getter_cp, prop_desc_setter_cp;
526         ECMA_SET_POINTER (prop_desc_getter_cp, property_desc_p->get_p);
527         ECMA_SET_POINTER (prop_desc_setter_cp, property_desc_p->set_p);
528 
529         if (((property_desc_p->flags & ECMA_PROP_IS_GET_DEFINED)
530              && prop_desc_getter_cp != get_set_pair_p->getter_cp)
531             || ((property_desc_p->flags & ECMA_PROP_IS_SET_DEFINED)
532                 && prop_desc_setter_cp != get_set_pair_p->setter_cp))
533         {
534           /* i., ii. */
535           return ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW);
536         }
537       }
538     }
539   }
540   else
541   {
542     /* 9. */
543     if (!is_current_configurable)
544     {
545       /* a. */
546       return ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW);
547     }
548 
549     ecma_property_value_t *value_p = ext_property_ref.property_ref.value_p;
550 
551     if (property_desc_type == ECMA_PROPERTY_TYPE_NAMEDACCESSOR)
552     {
553       JERRY_ASSERT (current_property_type == ECMA_PROPERTY_TYPE_NAMEDDATA);
554       ecma_free_value_if_not_object (value_p->value);
555 
556 #if ENABLED (JERRY_CPOINTER_32_BIT)
557       ecma_getter_setter_pointers_t *getter_setter_pair_p;
558       getter_setter_pair_p = jmem_pools_alloc (sizeof (ecma_getter_setter_pointers_t));
559       getter_setter_pair_p->getter_cp = JMEM_CP_NULL;
560       getter_setter_pair_p->setter_cp = JMEM_CP_NULL;
561       ECMA_SET_NON_NULL_POINTER (value_p->getter_setter_pair_cp, getter_setter_pair_p);
562 #else /* !ENABLED (JERRY_CPOINTER_32_BIT) */
563       value_p->getter_setter_pair.getter_cp = JMEM_CP_NULL;
564       value_p->getter_setter_pair.setter_cp = JMEM_CP_NULL;
565 #endif /* ENABLED (JERRY_CPOINTER_32_BIT) */
566     }
567     else
568     {
569       JERRY_ASSERT (current_property_type == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
570 #if ENABLED (JERRY_CPOINTER_32_BIT)
571       ecma_getter_setter_pointers_t *getter_setter_pair_p;
572       getter_setter_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_getter_setter_pointers_t,
573                                                         value_p->getter_setter_pair_cp);
574       jmem_pools_free (getter_setter_pair_p, sizeof (ecma_getter_setter_pointers_t));
575 #endif /* ENABLED (JERRY_CPOINTER_32_BIT) */
576       value_p->value = ECMA_VALUE_UNDEFINED;
577     }
578 
579     /* Update flags */
580     ecma_property_t prop_flags = *(ext_property_ref.property_p);
581     prop_flags = (ecma_property_t) (prop_flags & ~(ECMA_PROPERTY_TYPE_MASK | ECMA_PROPERTY_FLAG_WRITABLE));
582     prop_flags = (ecma_property_t) (prop_flags | property_desc_type);
583     *(ext_property_ref.property_p) = prop_flags;
584   }
585 
586   /* 12. */
587   if (property_desc_type == ECMA_PROPERTY_TYPE_NAMEDDATA)
588   {
589     JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*ext_property_ref.property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA);
590 
591     if (property_desc_p->flags & ECMA_PROP_IS_VALUE_DEFINED)
592     {
593       ecma_named_data_property_assign_value (object_p,
594                                              ext_property_ref.property_ref.value_p,
595                                              property_desc_p->value);
596     }
597 
598     if (property_desc_p->flags & ECMA_PROP_IS_WRITABLE_DEFINED)
599     {
600       ecma_set_property_writable_attr (ext_property_ref.property_p, (property_desc_p->flags & ECMA_PROP_IS_WRITABLE));
601     }
602   }
603   else if (property_desc_type == ECMA_PROPERTY_TYPE_NAMEDACCESSOR)
604   {
605     JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*ext_property_ref.property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
606 
607     if (property_desc_p->flags & ECMA_PROP_IS_GET_DEFINED)
608     {
609       ecma_set_named_accessor_property_getter (object_p,
610                                                ext_property_ref.property_ref.value_p,
611                                                property_desc_p->get_p);
612     }
613 
614     if (property_desc_p->flags & ECMA_PROP_IS_SET_DEFINED)
615     {
616       ecma_set_named_accessor_property_setter (object_p,
617                                                ext_property_ref.property_ref.value_p,
618                                                property_desc_p->set_p);
619     }
620   }
621 
622   if (property_desc_p->flags & ECMA_PROP_IS_ENUMERABLE_DEFINED)
623   {
624     ecma_set_property_enumerable_attr (ext_property_ref.property_p,
625                                        (property_desc_p->flags & ECMA_PROP_IS_ENUMERABLE));
626   }
627 
628   if (property_desc_p->flags & ECMA_PROP_IS_CONFIGURABLE_DEFINED)
629   {
630     ecma_set_property_configurable_attr (ext_property_ref.property_p,
631                                          (property_desc_p->flags & ECMA_PROP_IS_CONFIGURABLE));
632   }
633 
634   return ECMA_VALUE_TRUE;
635 } /* ecma_op_general_object_define_own_property */
636 
637 #undef ECMA_PROPERTY_TYPE_GENERIC
638 
639 #if ENABLED (JERRY_ES2015)
640 /**
641  * The IsCompatiblePropertyDescriptor method for Proxy object internal methods
642  *
643  * See also:
644  *          ECMAScript v6, 9.1.6.2
645  *
646  * @return bool
647  */
648 bool
ecma_op_is_compatible_property_descriptor(const ecma_property_descriptor_t * desc_p,const ecma_property_descriptor_t * current_p,bool is_extensible)649 ecma_op_is_compatible_property_descriptor (const ecma_property_descriptor_t *desc_p, /**< target descriptor */
650                                            const ecma_property_descriptor_t *current_p, /**< current descriptor */
651                                            bool is_extensible) /**< true - if target object is extensible
652                                                                     false - otherwise */
653 {
654   JERRY_ASSERT (desc_p != NULL);
655 
656   /* 2. */
657   if (current_p == NULL)
658   {
659     return is_extensible;
660   }
661 
662   /* 3. */
663   if (desc_p->flags == 0)
664   {
665     return true;
666   }
667 
668   /* 4. */
669   if ((current_p->flags & desc_p->flags) == desc_p->flags)
670   {
671     if ((current_p->flags & ECMA_PROP_IS_VALUE_DEFINED)
672          && ecma_op_same_value (current_p->value, desc_p->value))
673     {
674       return true;
675     }
676 
677     if ((current_p->flags & (ECMA_PROP_IS_GET_DEFINED | ECMA_PROP_IS_SET_DEFINED)
678          && current_p->get_p == desc_p->get_p
679          && current_p->set_p == desc_p->set_p))
680     {
681       return true;
682     }
683   }
684 
685   /* 5. */
686   if (!(current_p->flags & ECMA_PROP_IS_CONFIGURABLE))
687   {
688     if (desc_p->flags & ECMA_PROP_IS_CONFIGURABLE)
689     {
690       return false;
691     }
692     if ((desc_p->flags & ECMA_PROP_IS_ENUMERABLE_DEFINED)
693         && ((current_p->flags & ECMA_PROP_IS_ENUMERABLE) != (desc_p->flags & ECMA_PROP_IS_ENUMERABLE)))
694     {
695       return false;
696     }
697   }
698 
699   const uint32_t accessor_desc_flags = (ECMA_PROP_IS_SET_DEFINED | ECMA_PROP_IS_GET_DEFINED);
700   const uint32_t data_desc_flags = (ECMA_PROP_IS_VALUE_DEFINED | ECMA_PROP_IS_WRITABLE_DEFINED);
701 
702   bool desc_is_accessor = (desc_p->flags & accessor_desc_flags) != 0;
703   bool desc_is_data = (desc_p->flags & data_desc_flags) != 0;
704   bool current_is_data = (current_p->flags & data_desc_flags) != 0;
705 
706   /* 6. */
707   if (!desc_is_accessor && !desc_is_data)
708   {
709     return true;
710   }
711 
712   /* 7. */
713   if (current_is_data != desc_is_data)
714   {
715     return (current_p->flags & ECMA_PROP_IS_CONFIGURABLE) != 0;
716   }
717 
718   /* 8. */
719   if (current_is_data)
720   {
721     if (!(current_p->flags & ECMA_PROP_IS_CONFIGURABLE))
722     {
723       if (!(current_p->flags & ECMA_PROP_IS_WRITABLE)
724            && (desc_p->flags & ECMA_PROP_IS_WRITABLE))
725       {
726         return false;
727       }
728 
729       if (!(current_p->flags & ECMA_PROP_IS_WRITABLE)
730            && (desc_p->flags & ECMA_PROP_IS_VALUE_DEFINED)
731            && !ecma_op_same_value (desc_p->value, current_p->value))
732       {
733         return false;
734       }
735     }
736 
737     return true;
738   }
739 
740   JERRY_ASSERT ((current_p->flags & (ECMA_PROP_IS_GET_DEFINED | ECMA_PROP_IS_SET_DEFINED)) != 0);
741   JERRY_ASSERT ((desc_p->flags & (ECMA_PROP_IS_GET_DEFINED | ECMA_PROP_IS_SET_DEFINED)) != 0);
742 
743   /* 9. */
744   if (!(current_p->flags & ECMA_PROP_IS_CONFIGURABLE))
745   {
746     if ((desc_p->flags & ECMA_PROP_IS_SET_DEFINED)
747          && desc_p->set_p != current_p->set_p)
748     {
749       return false;
750     }
751 
752     if ((desc_p->flags & ECMA_PROP_IS_GET_DEFINED)
753          && desc_p->get_p != current_p->get_p)
754     {
755       return false;
756     }
757   }
758 
759   return true;
760 } /* ecma_op_is_compatible_property_descriptor */
761 
762 /**
763  * CompletePropertyDescriptor method for proxy internal method
764  *
765  * See also:
766  *          ECMA-262 v6, 6.2.4.5
767  */
768 void
ecma_op_to_complete_property_descriptor(ecma_property_descriptor_t * desc_p)769 ecma_op_to_complete_property_descriptor (ecma_property_descriptor_t *desc_p) /**< target descriptor */
770 {
771   /* 4. */
772   if (!(desc_p->flags & (ECMA_PROP_IS_GET_DEFINED | ECMA_PROP_IS_SET_DEFINED)))
773   {
774     /* a. */
775     desc_p->flags |= ECMA_PROP_IS_VALUE_DEFINED;
776   }
777   /* 5. */
778   else
779   {
780     desc_p->flags |= (ECMA_PROP_IS_GET_DEFINED | ECMA_PROP_IS_SET_DEFINED);
781   }
782 } /* ecma_op_to_complete_property_descriptor */
783 #endif /* ENABLED (JERRY_ES2015) */
784 
785 /**
786  * @}
787  * @}
788  */
789