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