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