• 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 <math.h>
17 
18 #include "ecma-iterator-object.h"
19 #include "ecma-typedarray-object.h"
20 #include "ecma-arraybuffer-object.h"
21 #include "ecma-function-object.h"
22 #include "ecma-builtin-helpers.h"
23 #include "ecma-try-catch-macro.h"
24 #include "ecma-objects.h"
25 #include "ecma-builtins.h"
26 #include "ecma-exceptions.h"
27 #include "ecma-gc.h"
28 #include "ecma-globals.h"
29 #include "ecma-helpers.h"
30 #include "jcontext.h"
31 
32 #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
33 
34 /** \addtogroup ecma ECMA
35  * @{
36  *
37  * \addtogroup ecmatypedarrayobject ECMA TypedArray object related routines
38  * @{
39  */
40 
41 /**
42  * Read an int8_t value from the given arraybuffer
43  */
44 static ecma_number_t
ecma_typedarray_get_int8_element(lit_utf8_byte_t * src)45 ecma_typedarray_get_int8_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */
46 {
47   int8_t num = (int8_t) *src;
48   return (ecma_number_t) num;
49 } /* ecma_typedarray_get_int8_element */
50 
51 /**
52  * Read an uint8_t value from the given arraybuffer
53  */
54 static ecma_number_t
ecma_typedarray_get_uint8_element(lit_utf8_byte_t * src)55 ecma_typedarray_get_uint8_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */
56 {
57   uint8_t num = (uint8_t) *src;
58   return (ecma_number_t) num;
59 } /* ecma_typedarray_get_uint8_element */
60 
61 /**
62  * Read an int16_t value from the given arraybuffer
63  */
64 static ecma_number_t
ecma_typedarray_get_int16_element(lit_utf8_byte_t * src)65 ecma_typedarray_get_int16_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */
66 {
67   int16_t num;
68   memcpy (&num, src, sizeof (int16_t));
69   return (ecma_number_t) num;
70 } /* ecma_typedarray_get_int16_element */
71 
72 /**
73  * Read an uint16_t value from the given arraybuffer
74  */
75 static ecma_number_t
ecma_typedarray_get_uint16_element(lit_utf8_byte_t * src)76 ecma_typedarray_get_uint16_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */
77 {
78   uint16_t num;
79   memcpy (&num, src, sizeof (uint16_t));
80   return (ecma_number_t) num;
81 } /* ecma_typedarray_get_uint16_element */
82 
83 /**
84  * Read an int32_t value from the given arraybuffer
85  */
86 static ecma_number_t
ecma_typedarray_get_int32_element(lit_utf8_byte_t * src)87 ecma_typedarray_get_int32_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */
88 {
89   int32_t num;
90   memcpy (&num, src, sizeof (int32_t));
91   return (ecma_number_t) num;
92 } /* ecma_typedarray_get_int32_element */
93 
94 /**
95  * Read an uint32_t value from the given arraybuffer
96  */
97 static ecma_number_t
ecma_typedarray_get_uint32_element(lit_utf8_byte_t * src)98 ecma_typedarray_get_uint32_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */
99 {
100   uint32_t num;
101   memcpy (&num, src, sizeof (uint32_t));
102   return (ecma_number_t) num;
103 } /* ecma_typedarray_get_uint32_element */
104 
105 /**
106  * Read a float value from the given arraybuffer
107  */
108 static ecma_number_t
ecma_typedarray_get_float_element(lit_utf8_byte_t * src)109 ecma_typedarray_get_float_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */
110 {
111   float num;
112   memcpy (&num, src, sizeof (float));
113   return (ecma_number_t) num;
114 } /* ecma_typedarray_get_float_element */
115 
116 /**
117  * Read a double value from the given arraybuffer
118  */
119 static ecma_number_t
ecma_typedarray_get_double_element(lit_utf8_byte_t * src)120 ecma_typedarray_get_double_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */
121 {
122   double num;
123   memcpy (&num, src, sizeof (double));
124   return (ecma_number_t) num;
125 } /* ecma_typedarray_get_double_element */
126 
127 /**
128  * Normalize the given ecma_number_t to an uint32_t value
129  */
130 static uint32_t
ecma_typedarray_setter_number_to_uint32(ecma_number_t value)131 ecma_typedarray_setter_number_to_uint32 (ecma_number_t value) /**< the number value to normalize */
132 {
133   uint32_t uint32_value = 0;
134 
135   if (!ecma_number_is_nan (value) && !ecma_number_is_infinity (value))
136   {
137     bool is_negative = false;
138 
139     if (value < 0)
140     {
141       is_negative = true;
142       value = -value;
143     }
144 
145     if (value > ((ecma_number_t) 0xffffffff))
146     {
147       value = (ecma_number_t) (fmod (value, (ecma_number_t) 0x100000000));
148     }
149 
150     uint32_value = (uint32_t) value;
151 
152     if (is_negative)
153     {
154       uint32_value = (uint32_t) (-(int32_t) uint32_value);
155     }
156   }
157 
158   return uint32_value;
159 } /* ecma_typedarray_setter_number_to_uint32 */
160 
161 /**
162  * Write an int8_t value into the given arraybuffer
163  */
164 static void
ecma_typedarray_set_int8_element(lit_utf8_byte_t * dst_p,ecma_number_t value)165 ecma_typedarray_set_int8_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */
166                                   ecma_number_t value) /**< the number value to set */
167 {
168   int8_t num = (int8_t) ecma_typedarray_setter_number_to_uint32 (value);
169   *dst_p = (lit_utf8_byte_t) num;
170 } /* ecma_typedarray_set_int8_element */
171 
172 /**
173  * Write an uint8_t value into the given arraybuffer
174  */
175 static void
ecma_typedarray_set_uint8_element(lit_utf8_byte_t * dst_p,ecma_number_t value)176 ecma_typedarray_set_uint8_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */
177                                    ecma_number_t value) /**< the number value to set */
178 {
179   uint8_t num = (uint8_t) ecma_typedarray_setter_number_to_uint32 (value);
180   *dst_p = (lit_utf8_byte_t) num;
181 } /* ecma_typedarray_set_uint8_element */
182 
183 /**
184  * Write an uint8_t clamped value into the given arraybuffer
185  */
186 static void
ecma_typedarray_set_uint8_clamped_element(lit_utf8_byte_t * dst_p,ecma_number_t value)187 ecma_typedarray_set_uint8_clamped_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */
188                                            ecma_number_t value) /**< the number value to set */
189 {
190   uint8_t clamped;
191 
192   if (value > 255)
193   {
194     clamped = 255;
195   }
196   else if (value <= 0)
197   {
198     clamped = 0;
199   }
200   else
201   {
202     clamped = (uint8_t) value;
203 
204     if (clamped + 0.5 < value
205         || (clamped + 0.5 == value && (clamped % 2) == 1))
206     {
207       clamped ++;
208     }
209   }
210 
211   *dst_p = (lit_utf8_byte_t) clamped;
212 } /* ecma_typedarray_set_uint8_clamped_element */
213 
214 /**
215  * Write an int16_t value into the given arraybuffer
216  */
217 static void
ecma_typedarray_set_int16_element(lit_utf8_byte_t * dst_p,ecma_number_t value)218 ecma_typedarray_set_int16_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */
219                                    ecma_number_t value) /**< the number value to set */
220 {
221   int16_t num = (int16_t) ecma_typedarray_setter_number_to_uint32 (value);
222   memcpy (dst_p, &num, sizeof (int16_t));
223 } /* ecma_typedarray_set_int16_element */
224 
225 /**
226  * Write an uint8_t value into the given arraybuffer
227  */
228 static void
ecma_typedarray_set_uint16_element(lit_utf8_byte_t * dst_p,ecma_number_t value)229 ecma_typedarray_set_uint16_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */
230                                     ecma_number_t value) /**< the number value to set */
231 {
232   uint16_t num = (uint16_t) ecma_typedarray_setter_number_to_uint32 (value);
233   memcpy (dst_p, &num, sizeof (uint16_t));
234 } /* ecma_typedarray_set_uint16_element */
235 
236 /**
237  * Write an int32_t value into the given arraybuffer
238  */
239 static void
ecma_typedarray_set_int32_element(lit_utf8_byte_t * dst_p,ecma_number_t value)240 ecma_typedarray_set_int32_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */
241                                    ecma_number_t value) /**< the number value to set */
242 {
243   int32_t num = (int32_t) ecma_typedarray_setter_number_to_uint32 (value);
244   memcpy (dst_p, &num, sizeof (int32_t));
245 } /* ecma_typedarray_set_int32_element */
246 
247 /**
248  * Write an uint32_t value into the given arraybuffer
249  */
250 static void
ecma_typedarray_set_uint32_element(lit_utf8_byte_t * dst_p,ecma_number_t value)251 ecma_typedarray_set_uint32_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */
252                                     ecma_number_t value) /**< the number value to set */
253 {
254   uint32_t num = (uint32_t) ecma_typedarray_setter_number_to_uint32 (value);
255   memcpy (dst_p, &num, sizeof (uint32_t));
256 } /* ecma_typedarray_set_uint32_element */
257 
258 /**
259  * Write a float value into the given arraybuffer
260  */
261 static void
ecma_typedarray_set_float_element(lit_utf8_byte_t * dst_p,ecma_number_t value)262 ecma_typedarray_set_float_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */
263                                    ecma_number_t value) /**< the number value to set */
264 {
265   float num = (float) value;
266   memcpy (dst_p, &num, sizeof (float));
267 } /* ecma_typedarray_set_float_element */
268 
269 #if ENABLED (JERRY_NUMBER_TYPE_FLOAT64)
270 /**
271  * Write a double value into the given arraybuffer
272  */
273 static void
ecma_typedarray_set_double_element(lit_utf8_byte_t * dst_p,ecma_number_t value)274 ecma_typedarray_set_double_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */
275                                     ecma_number_t value) /**< the number value to set */
276 {
277   double num = (double) value;
278   memcpy (dst_p, &num, sizeof (double));
279 } /* ecma_typedarray_set_double_element */
280 #endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */
281 
282 /**
283  * Builtin id of the first %TypedArray% builtin routine intrinsic object
284  */
285 #define ECMA_FIRST_TYPEDARRAY_BUILTIN_ROUTINE_ID ECMA_BUILTIN_ID_INT8ARRAY
286 
287 #if ENABLED (JERRY_NUMBER_TYPE_FLOAT64)
288 /**
289  * Builtin id of the last %TypedArray% builtin routine intrinsic object
290  */
291 #define ECMA_LAST_TYPEDARRAY_BUILTIN_ROUTINE_ID ECMA_BUILTIN_ID_FLOAT64ARRAY
292 #else /* !ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */
293 /**
294  * Builtin id of the last %TypedArray% builtin routine intrinsic object
295  */
296 #define ECMA_LAST_TYPEDARRAY_BUILTIN_ROUTINE_ID ECMA_BUILTIN_ID_FLOAT32ARRAY
297 #endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */
298 
299 /**
300  * Builtin id of the first %TypedArray% builtin prototype intrinsic object
301  */
302 #define ECMA_FIRST_TYPEDARRAY_BUILTIN_PROTOTYPE_ID ECMA_BUILTIN_ID_INT8ARRAY_PROTOTYPE
303 
304 /**
305  * List of typedarray getters based on their builtin id
306  */
307 static const ecma_typedarray_getter_fn_t ecma_typedarray_getters[] =
308 {
309   ecma_typedarray_get_int8_element,   /**< Int8Array */
310   ecma_typedarray_get_uint8_element,  /**< Uint8Array */
311   ecma_typedarray_get_uint8_element,  /**< Uint8ClampedArray */
312   ecma_typedarray_get_int16_element,  /**< Int16Array */
313   ecma_typedarray_get_uint16_element, /**< Int32Array */
314   ecma_typedarray_get_int32_element,  /**< Uint32Array */
315   ecma_typedarray_get_uint32_element, /**< Uint32Array */
316   ecma_typedarray_get_float_element,  /**< Float32Array */
317 #if ENABLED (JERRY_NUMBER_TYPE_FLOAT64)
318   ecma_typedarray_get_double_element, /**< Float64Array */
319 #endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */
320 };
321 
322 /**
323  * List of typedarray setters based on their builtin id
324  */
325 static const ecma_typedarray_setter_fn_t ecma_typedarray_setters[] =
326 {
327   ecma_typedarray_set_int8_element,          /**< Int8Array */
328   ecma_typedarray_set_uint8_element,         /**< Uint8Array */
329   ecma_typedarray_set_uint8_clamped_element, /**< Uint8ClampedArray */
330   ecma_typedarray_set_int16_element,         /**< Int16Array */
331   ecma_typedarray_set_uint16_element,        /**< Int32Array */
332   ecma_typedarray_set_int32_element,         /**< Uint32Array */
333   ecma_typedarray_set_uint32_element,        /**< Uint32Array */
334   ecma_typedarray_set_float_element,         /**< Float32Array */
335 #if ENABLED (JERRY_NUMBER_TYPE_FLOAT64)
336   ecma_typedarray_set_double_element,        /**< Float64Array */
337 #endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */
338 };
339 
340 /**
341  * List of typedarray element shift sizes based on their builtin id
342  */
343 static const uint8_t ecma_typedarray_element_shift_sizes[] =
344 {
345   0, /**< Int8Array */
346   0, /**< Uint8Array */
347   0, /**< Uint8ClampedArray */
348   1, /**< Int16Array */
349   1, /**< Uint16Array */
350   2, /**< Int32Array */
351   2, /**< Uint32Array */
352   2, /**< Float32Array */
353 #if ENABLED (JERRY_NUMBER_TYPE_FLOAT64)
354   3, /**< Float64Array */
355 #endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */
356 };
357 
358 /**
359  * List of typedarray class magic strings based on their builtin id
360  */
361 static const uint16_t ecma_typedarray_magic_string_list[] =
362 {
363   (uint16_t) LIT_MAGIC_STRING_INT8_ARRAY_UL,          /**< Int8Array */
364   (uint16_t) LIT_MAGIC_STRING_UINT8_ARRAY_UL,         /**< Uint8Array */
365   (uint16_t) LIT_MAGIC_STRING_UINT8_CLAMPED_ARRAY_UL, /**< Uint8ClampedArray */
366   (uint16_t) LIT_MAGIC_STRING_INT16_ARRAY_UL,         /**< Int16Array */
367   (uint16_t) LIT_MAGIC_STRING_UINT16_ARRAY_UL,        /**< Uint16Array */
368   (uint16_t) LIT_MAGIC_STRING_INT32_ARRAY_UL,         /**< Int32Array */
369   (uint16_t) LIT_MAGIC_STRING_UINT32_ARRAY_UL,        /**< Uint32Array */
370   (uint16_t) LIT_MAGIC_STRING_FLOAT32_ARRAY_UL,       /**< Float32Array */
371 #if ENABLED (JERRY_NUMBER_TYPE_FLOAT64)
372   (uint16_t) LIT_MAGIC_STRING_FLOAT64_ARRAY_UL,       /**< Float64Array */
373 #endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */
374 };
375 
376 /**
377  * Get typedarray's getter function callback
378  *
379  * @return ecma_typedarray_getter_fn_t: the getter function for the given builtin TypedArray id
380  */
381 inline ecma_typedarray_getter_fn_t JERRY_ATTR_ALWAYS_INLINE
ecma_get_typedarray_getter_fn(ecma_typedarray_type_t typedarray_id)382 ecma_get_typedarray_getter_fn (ecma_typedarray_type_t typedarray_id)
383 {
384   return ecma_typedarray_getters[typedarray_id];
385 } /* ecma_get_typedarray_getter_fn */
386 
387 /**
388  * get typedarray's element value
389  *
390  * @return ecma_number_t: the value of the element
391  */
392 inline ecma_number_t JERRY_ATTR_ALWAYS_INLINE
ecma_get_typedarray_element(lit_utf8_byte_t * src_p,ecma_typedarray_type_t typedarray_id)393 ecma_get_typedarray_element (lit_utf8_byte_t *src_p,
394                              ecma_typedarray_type_t typedarray_id)
395 {
396   return ecma_typedarray_getters[typedarray_id](src_p);
397 } /* ecma_get_typedarray_element */
398 
399 /**
400  * Get typedarray's setter function callback
401  *
402  * @return ecma_typedarray_setter_fn_t: the setter function for the given builtin TypedArray id
403  */
404 inline ecma_typedarray_setter_fn_t JERRY_ATTR_ALWAYS_INLINE
ecma_get_typedarray_setter_fn(ecma_typedarray_type_t typedarray_id)405 ecma_get_typedarray_setter_fn (ecma_typedarray_type_t typedarray_id)
406 {
407   return ecma_typedarray_setters[typedarray_id];
408 } /* ecma_get_typedarray_setter_fn */
409 
410 /**
411  * set typedarray's element value
412  */
413 inline void JERRY_ATTR_ALWAYS_INLINE
ecma_set_typedarray_element(lit_utf8_byte_t * dst_p,ecma_number_t value,ecma_typedarray_type_t typedarray_id)414 ecma_set_typedarray_element (lit_utf8_byte_t *dst_p,
415                              ecma_number_t value,
416                              ecma_typedarray_type_t typedarray_id)
417 {
418   ecma_typedarray_setters[typedarray_id](dst_p, value);
419 } /* ecma_set_typedarray_element */
420 
421 /**
422  * Get the element shift size of a TypedArray type.
423  *
424  * @return uint8_t
425  */
426 inline uint8_t JERRY_ATTR_ALWAYS_INLINE
ecma_typedarray_helper_get_shift_size(ecma_typedarray_type_t typedarray_id)427 ecma_typedarray_helper_get_shift_size (ecma_typedarray_type_t typedarray_id)
428 {
429   return ecma_typedarray_element_shift_sizes[typedarray_id];
430 } /* ecma_typedarray_helper_get_shift_size */
431 
432 /**
433  * Check if the builtin is a TypedArray type.
434  *
435  * @return bool: - true if based on the given id it is a TypedArray
436  *               - false if based on the given id it is not a TypedArray
437  */
438 bool
ecma_typedarray_helper_is_typedarray(ecma_builtin_id_t builtin_id)439 ecma_typedarray_helper_is_typedarray (ecma_builtin_id_t builtin_id) /**< the builtin id of a type **/
440 {
441   return ((builtin_id >= ECMA_FIRST_TYPEDARRAY_BUILTIN_ROUTINE_ID)
442           && (builtin_id <= ECMA_LAST_TYPEDARRAY_BUILTIN_ROUTINE_ID));
443 } /* ecma_typedarray_helper_is_typedarray */
444 
445 /**
446  * Get the prototype ID of a TypedArray type.
447  *
448  * @return ecma_builtin_id_t
449  */
450 ecma_builtin_id_t
ecma_typedarray_helper_get_prototype_id(ecma_typedarray_type_t typedarray_id)451 ecma_typedarray_helper_get_prototype_id (ecma_typedarray_type_t typedarray_id) /**< the id of the typedarray **/
452 {
453   return (ecma_builtin_id_t) (ECMA_FIRST_TYPEDARRAY_BUILTIN_PROTOTYPE_ID + typedarray_id);
454 } /* ecma_typedarray_helper_get_prototype_id */
455 
456 /**
457  * Get the constructor ID of a TypedArray type.
458  *
459  * @return ecma_builtin_id_t
460  */
461 ecma_builtin_id_t
ecma_typedarray_helper_get_constructor_id(ecma_typedarray_type_t typedarray_id)462 ecma_typedarray_helper_get_constructor_id (ecma_typedarray_type_t typedarray_id) /**< the id of the typedarray **/
463 {
464   return (ecma_builtin_id_t) (ECMA_FIRST_TYPEDARRAY_BUILTIN_ROUTINE_ID + typedarray_id);
465 } /* ecma_typedarray_helper_get_constructor_id */
466 
467 /**
468  * Get the built-in TypedArray type of the given object.
469  *
470  * @return ecma_typedarray_type_t
471  */
472 ecma_typedarray_type_t
ecma_get_typedarray_id(ecma_object_t * obj_p)473 ecma_get_typedarray_id (ecma_object_t *obj_p) /**< typedarray object **/
474 {
475   JERRY_ASSERT (ecma_object_is_typedarray (obj_p));
476 
477   ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
478 
479   return (ecma_typedarray_type_t) ext_object_p->u.pseudo_array.extra_info;
480 } /* ecma_get_typedarray_id */
481 
482 /**
483  * Get the built-in TypedArray type of the given object.
484  *
485  * @return ecma_typedarray_type_t
486  */
487 ecma_typedarray_type_t
ecma_typedarray_helper_builtin_to_typedarray_id(ecma_builtin_id_t builtin_id)488 ecma_typedarray_helper_builtin_to_typedarray_id (ecma_builtin_id_t builtin_id)
489 {
490   JERRY_ASSERT (ecma_typedarray_helper_is_typedarray (builtin_id));
491 
492   return (ecma_typedarray_type_t) (builtin_id - ECMA_FIRST_TYPEDARRAY_BUILTIN_ROUTINE_ID);
493 } /* ecma_typedarray_helper_builtin_to_typedarray_id */
494 
495 /**
496  * Create a TypedArray object by given array_length
497  *
498  * See also: ES2015 22.2.1.2.1
499  *
500  * @return ecma value of the new typedarray object
501  *         Returned value must be freed with ecma_free_value
502  */
503 ecma_value_t
ecma_typedarray_create_object_with_length(ecma_length_t array_length,ecma_object_t * src_buffer_p,ecma_object_t * proto_p,uint8_t element_size_shift,ecma_typedarray_type_t typedarray_id)504 ecma_typedarray_create_object_with_length (ecma_length_t array_length, /**< length of the typedarray */
505                                            ecma_object_t *src_buffer_p, /**< source buffer */
506                                            ecma_object_t *proto_p, /**< prototype object */
507                                            uint8_t element_size_shift, /**< the size shift of the element length */
508                                            ecma_typedarray_type_t typedarray_id) /**< id of the typedarray */
509 {
510   if (array_length > (UINT32_MAX >> element_size_shift))
511   {
512     return ecma_raise_range_error (ECMA_ERR_MSG ("Maximum typedarray size is reached."));
513   }
514 
515   ecma_length_t byte_length = array_length << element_size_shift;
516 
517   if (byte_length > UINT32_MAX - sizeof (ecma_extended_object_t) - JMEM_ALIGNMENT + 1)
518   {
519     return ecma_raise_range_error (ECMA_ERR_MSG ("Maximum typedarray size is reached."));
520   }
521 
522   ecma_object_t *new_arraybuffer_p = NULL;
523   if (src_buffer_p == NULL)
524   {
525     new_arraybuffer_p = ecma_arraybuffer_new_object (byte_length);
526   }
527   else
528   {
529 #if ENABLED (JERRY_ES2015)
530     ecma_value_t ctor_proto = ecma_op_species_constructor (src_buffer_p, ECMA_BUILTIN_ID_ARRAYBUFFER);
531 #else
532     ecma_value_t ctor_proto = ECMA_VALUE_ERROR;
533 #endif /* ENABLED (JERRY_ES2015) */
534     if (ECMA_IS_VALUE_ERROR (ctor_proto))
535     {
536       return ctor_proto;
537     }
538 
539     ecma_object_t *ctor_proto_p = ecma_get_object_from_value (ctor_proto);
540 
541     ecma_object_t *prototype_p = ecma_op_get_prototype_from_constructor (ctor_proto_p,
542                                                                          ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE);
543 
544     ecma_deref_object (ctor_proto_p);
545 
546     if (JERRY_UNLIKELY (prototype_p == NULL))
547     {
548       return ECMA_VALUE_ERROR;
549     }
550 
551     new_arraybuffer_p = ecma_arraybuffer_new_object (byte_length);
552 
553     ECMA_SET_NON_NULL_POINTER (new_arraybuffer_p->u2.prototype_cp, prototype_p);
554 
555     ecma_deref_object (prototype_p);
556   }
557 
558   ecma_object_t *object_p = ecma_create_object (proto_p,
559                                                 sizeof (ecma_extended_object_t),
560                                                 ECMA_OBJECT_TYPE_PSEUDO_ARRAY);
561 
562   ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
563   ext_object_p->u.pseudo_array.u1.class_id = ecma_typedarray_magic_string_list[typedarray_id];
564   ext_object_p->u.pseudo_array.type = ECMA_PSEUDO_ARRAY_TYPEDARRAY;
565   ext_object_p->u.pseudo_array.extra_info = (uint8_t) typedarray_id;
566   ext_object_p->u.pseudo_array.u2.arraybuffer = ecma_make_object_value (new_arraybuffer_p);
567 
568   ecma_deref_object (new_arraybuffer_p);
569 
570   return ecma_make_object_value (object_p);
571 } /* ecma_typedarray_create_object_with_length */
572 
573 /**
574  * Create a TypedArray object by given buffer, offset, and array_length
575  *
576  * See also: ES2015 22.2.1.5
577  *
578  * @return ecma value of the new typedarray object
579  *         Returned value must be freed with ecma_free_value
580  */
581 static ecma_value_t
ecma_typedarray_create_object_with_buffer(ecma_object_t * arraybuffer_p,ecma_length_t byte_offset,ecma_length_t array_length,ecma_object_t * proto_p,uint8_t element_size_shift,ecma_typedarray_type_t typedarray_id)582 ecma_typedarray_create_object_with_buffer (ecma_object_t *arraybuffer_p, /**< the arraybuffer inside */
583                                            ecma_length_t byte_offset, /**< the byte offset of the arraybuffer */
584                                            ecma_length_t array_length, /**< length of the typedarray */
585                                            ecma_object_t *proto_p, /**< prototype object */
586                                            uint8_t element_size_shift, /**< the size shift of the element length */
587                                            ecma_typedarray_type_t typedarray_id) /**< id of the typedarray */
588 {
589   if (ecma_arraybuffer_is_detached (arraybuffer_p))
590   {
591     return ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer has been detached."));
592   }
593   ecma_length_t expected_length = (ecma_arraybuffer_get_length (arraybuffer_p) >> element_size_shift);
594 
595   bool needs_ext_typedarray_obj = (byte_offset != 0 || array_length != expected_length);
596 
597   size_t object_size = (needs_ext_typedarray_obj ? sizeof (ecma_extended_typedarray_object_t)
598                                                  : sizeof (ecma_extended_object_t));
599 
600   ecma_object_t *object_p = ecma_create_object (proto_p, object_size, ECMA_OBJECT_TYPE_PSEUDO_ARRAY);
601 
602   ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
603   ext_object_p->u.pseudo_array.u1.class_id = ecma_typedarray_magic_string_list[typedarray_id];
604   ext_object_p->u.pseudo_array.type = ECMA_PSEUDO_ARRAY_TYPEDARRAY;
605   ext_object_p->u.pseudo_array.extra_info = (uint8_t) typedarray_id;
606   ext_object_p->u.pseudo_array.u2.arraybuffer = ecma_make_object_value (arraybuffer_p);
607 
608   if (needs_ext_typedarray_obj)
609   {
610     ext_object_p->u.pseudo_array.type = ECMA_PSEUDO_ARRAY_TYPEDARRAY_WITH_INFO;
611 
612     ecma_extended_typedarray_object_t *typedarray_info_p = (ecma_extended_typedarray_object_t *) object_p;
613     typedarray_info_p->array_length = array_length;
614     typedarray_info_p->byte_offset = byte_offset;
615   }
616 
617   return ecma_make_object_value (object_p);
618 } /* ecma_typedarray_create_object_with_buffer */
619 
620 /**
621  * Create a TypedArray object by given another TypedArray object
622  *
623  * See also: ES2015 22.2.1.3
624  *
625  * @return ecma value of the new typedarray object
626  *         Returned value must be freed with ecma_free_value
627  */
628 static ecma_value_t
ecma_typedarray_create_object_with_typedarray(ecma_object_t * typedarray_p,ecma_object_t * proto_p,uint8_t element_size_shift,ecma_typedarray_type_t typedarray_id)629 ecma_typedarray_create_object_with_typedarray (ecma_object_t *typedarray_p, /**< a typedarray object */
630                                                ecma_object_t *proto_p, /**< prototype object */
631                                                uint8_t element_size_shift, /**< the size shift of the element length */
632                                                ecma_typedarray_type_t typedarray_id) /**< id of the typedarray */
633 {
634   ecma_length_t array_length = ecma_typedarray_get_length (typedarray_p);
635   ecma_object_t *src_arraybuffer_p = ecma_typedarray_get_arraybuffer (typedarray_p);
636   if (ecma_arraybuffer_is_detached (src_arraybuffer_p))
637   {
638     return ecma_raise_type_error (ECMA_ERR_MSG ("Invalid detached ArrayBuffer."));
639   }
640 
641   ecma_value_t new_typedarray = ecma_typedarray_create_object_with_length (array_length,
642                                                                            src_arraybuffer_p,
643                                                                            proto_p,
644                                                                            element_size_shift,
645                                                                            typedarray_id);
646 
647   if (ECMA_IS_VALUE_ERROR (new_typedarray))
648   {
649     return new_typedarray;
650   }
651 
652   ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray);
653 
654   lit_utf8_byte_t *src_buf_p = ecma_arraybuffer_get_buffer (src_arraybuffer_p);
655 
656   ecma_object_t *dst_arraybuffer_p = ecma_typedarray_get_arraybuffer (new_typedarray_p);
657   lit_utf8_byte_t *dst_buf_p = ecma_arraybuffer_get_buffer (dst_arraybuffer_p);
658 
659   src_buf_p += ecma_typedarray_get_offset (typedarray_p);
660 
661   ecma_typedarray_type_t src_id = ecma_get_typedarray_id (typedarray_p);
662 
663   if (src_id == typedarray_id)
664   {
665     memcpy (dst_buf_p, src_buf_p, array_length << element_size_shift);
666   }
667   else
668   {
669     uint32_t src_element_size = 1u << ecma_typedarray_get_element_size_shift (typedarray_p);
670     uint32_t dst_element_size = 1u << element_size_shift;
671     ecma_typedarray_getter_fn_t src_typedarray_getter_cb = ecma_get_typedarray_getter_fn (src_id);
672     ecma_typedarray_setter_fn_t target_typedarray_setter_cb = ecma_get_typedarray_setter_fn (typedarray_id);
673 
674     for (uint32_t i = 0; i < array_length; i++)
675     {
676       /* Convert values from source to destination format. */
677       ecma_number_t tmp = src_typedarray_getter_cb (src_buf_p);
678       target_typedarray_setter_cb (dst_buf_p, tmp);
679 
680       src_buf_p += src_element_size;
681       dst_buf_p += dst_element_size;
682     }
683   }
684 
685   return new_typedarray;
686 } /* ecma_typedarray_create_object_with_typedarray */
687 
688 /**
689  * Helper method for ecma_op_typedarray_from
690  *
691  * @return ECMA_VALUE_TRUE - if setting the given value to the new typedarray was successful
692  *         ECMA_VALUE_ERROR - otherwise
693  */
694 static ecma_value_t
ecma_op_typedarray_from_helper(ecma_value_t this_val,ecma_value_t current_value,uint32_t index,ecma_object_t * func_object_p,ecma_typedarray_info_t * info_p,ecma_typedarray_setter_fn_t setter_cb)695 ecma_op_typedarray_from_helper (ecma_value_t this_val, /**< this_arg for the above from function */
696                                 ecma_value_t current_value, /**< given value to set */
697                                 uint32_t index, /**< currrent index */
698                                 ecma_object_t *func_object_p, /**< map function object */
699                                 ecma_typedarray_info_t *info_p, /**< typedarray info */
700                                 ecma_typedarray_setter_fn_t setter_cb) /**< setter callback function */
701 {
702   ecma_value_t mapped_value;
703   if (func_object_p != NULL)
704   {
705     /* 17.d 17.f */
706     ecma_value_t current_index = ecma_make_uint32_value (index);
707     ecma_value_t call_args[] = { current_value, current_index };
708 
709     ecma_value_t cb_value = ecma_op_function_call (func_object_p, this_val, call_args, 2);
710 
711     ecma_free_value (current_index);
712     ecma_free_value (current_value);
713 
714     if (ECMA_IS_VALUE_ERROR (cb_value))
715     {
716       return cb_value;
717     }
718 
719     mapped_value = cb_value;
720   }
721   else
722   {
723     mapped_value = current_value;
724   }
725 
726   ecma_number_t num_var;
727   ecma_value_t mapped_number = ecma_get_number (mapped_value, &num_var);
728   ecma_free_value (mapped_value);
729 
730   if (ECMA_IS_VALUE_ERROR (mapped_number))
731   {
732     return mapped_number;
733   }
734 
735   if (index >= info_p->length)
736   {
737     return ecma_raise_type_error (ECMA_ERR_MSG ("Invalid argument type."));
738   }
739 
740   setter_cb (info_p->buffer_p + (index << info_p->shift), num_var);
741 
742   return ECMA_VALUE_TRUE;
743 } /* ecma_op_typedarray_from_helper */
744 
745 /**
746  * Create a TypedArray object by transforming from an array-like object or iterable object
747  *
748  * See also: ES2015 22.2.2.1
749  *
750  * @return ecma value of the new typedarray object
751  *         Returned value must be freed with ecma_free_value
752  */
753 ecma_value_t
ecma_op_typedarray_from(ecma_value_t items_val,ecma_value_t map_fn_val,ecma_value_t this_val,ecma_object_t * proto_p,uint8_t element_size_shift,ecma_typedarray_type_t typedarray_id)754 ecma_op_typedarray_from (ecma_value_t items_val, /**< the source array-like object */
755                          ecma_value_t map_fn_val, /**< map function */
756                          ecma_value_t this_val, /**< this_arg for the above map function */
757                          ecma_object_t *proto_p, /**< prototype object */
758                          uint8_t element_size_shift, /**< the size shift of the element length */
759                          ecma_typedarray_type_t typedarray_id) /**< id of the typedarray */
760 {
761   /* 3 */
762   JERRY_ASSERT (ecma_op_is_callable (map_fn_val) || ecma_is_value_undefined (map_fn_val));
763 
764   /* 4-5 */
765   ecma_object_t *func_object_p = NULL;
766   if (!ecma_is_value_undefined (map_fn_val))
767   {
768     func_object_p = ecma_get_object_from_value (map_fn_val);
769   }
770 
771 #if ENABLED (JERRY_ES2015)
772   /* 6 */
773   ecma_value_t using_iterator = ecma_op_get_method_by_symbol_id (items_val, LIT_GLOBAL_SYMBOL_ITERATOR);
774 
775   /* 7 */
776   if (ECMA_IS_VALUE_ERROR (using_iterator))
777   {
778     return using_iterator;
779   }
780 
781   /* 8 */
782   if (!ecma_is_value_undefined (using_iterator))
783   {
784     /* 8.a */
785     ecma_value_t iterator = ecma_op_get_iterator (items_val, using_iterator);
786     ecma_free_value (using_iterator);
787 
788     /* 8.b */
789     if (ECMA_IS_VALUE_ERROR (iterator))
790     {
791       return iterator;
792     }
793 
794     /* 8.c */
795     ecma_collection_t *values_p = ecma_new_collection ();
796     ecma_value_t ret_value = ECMA_VALUE_EMPTY;
797 
798     /* 8.e */
799     while (true)
800     {
801       /* 8.e.i */
802       ecma_value_t next = ecma_op_iterator_step (iterator);
803 
804       /* 8.e.ii */
805       if (ECMA_IS_VALUE_ERROR (next))
806       {
807         ret_value = next;
808         break;
809       }
810 
811       if (next == ECMA_VALUE_FALSE)
812       {
813         break;
814       }
815 
816       /* 8.e.iii */
817       ecma_value_t next_value = ecma_op_iterator_value (next);
818       ecma_free_value (next);
819 
820       if (ECMA_IS_VALUE_ERROR (next_value))
821       {
822         ret_value = next_value;
823         break;
824       }
825 
826       ecma_collection_push_back (values_p, next_value);
827     }
828 
829     ecma_free_value (iterator);
830 
831     if (ECMA_IS_VALUE_ERROR (ret_value))
832     {
833       ecma_collection_free (values_p);
834       return ret_value;
835     }
836 
837     /* 8.g */
838     ecma_value_t new_typedarray = ecma_typedarray_create_object_with_length (values_p->item_count,
839                                                                              NULL,
840                                                                              proto_p,
841                                                                              element_size_shift,
842                                                                              typedarray_id);
843 
844     /* 8.h */
845     if (ECMA_IS_VALUE_ERROR (new_typedarray))
846     {
847       ecma_collection_free (values_p);
848       return new_typedarray;
849     }
850 
851     ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray);
852     ecma_typedarray_info_t info = ecma_typedarray_get_info (new_typedarray_p);
853     ecma_typedarray_setter_fn_t setter_cb = ecma_get_typedarray_setter_fn (info.id);
854 
855     ret_value = ecma_make_object_value (new_typedarray_p);
856 
857     /* 8.j */
858     for (uint32_t index = 0; index < values_p->item_count; index++)
859     {
860       ecma_value_t set_value = ecma_op_typedarray_from_helper (this_val,
861                                                                values_p->buffer_p[index],
862                                                                index,
863                                                                func_object_p,
864                                                                &info,
865                                                                setter_cb);
866 
867       if (ECMA_IS_VALUE_ERROR (set_value))
868       {
869         for (uint32_t j = index + 1; j < values_p->item_count; j++)
870         {
871           ecma_free_value (values_p->buffer_p[j]);
872         }
873 
874         ret_value = set_value;
875         break;
876       }
877     }
878 
879     ecma_collection_destroy (values_p);
880 
881     if (ECMA_IS_VALUE_ERROR (ret_value))
882     {
883       ecma_deref_object (new_typedarray_p);
884     }
885 
886     return ret_value;
887   }
888 #endif /* ENABLED (JERRY_ES2015) */
889 
890   /* 10 */
891   ecma_value_t arraylike_object_val = ecma_op_to_object (items_val);
892 
893   if (ECMA_IS_VALUE_ERROR (arraylike_object_val))
894   {
895     return arraylike_object_val;
896   }
897 
898   ecma_object_t *arraylike_object_p = ecma_get_object_from_value (arraylike_object_val);
899 
900   /* 12 */
901   uint32_t len;
902   ecma_value_t len_value = ecma_op_object_get_length (arraylike_object_p, &len);
903 
904   if (ECMA_IS_VALUE_ERROR (len_value))
905   {
906     ecma_deref_object (arraylike_object_p);
907     return len_value;
908   }
909 
910   /* 14 */
911   ecma_value_t new_typedarray = ecma_typedarray_create_object_with_length (len,
912                                                                            NULL,
913                                                                            proto_p,
914                                                                            element_size_shift,
915                                                                            typedarray_id);
916 
917   if (ECMA_IS_VALUE_ERROR (new_typedarray))
918   {
919     ecma_deref_object (arraylike_object_p);
920     return new_typedarray;
921   }
922 
923   ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray);
924   ecma_typedarray_info_t info = ecma_typedarray_get_info (new_typedarray_p);
925   ecma_typedarray_setter_fn_t setter_cb = ecma_get_typedarray_setter_fn (info.id);
926   ecma_value_t ret_value = ecma_make_object_value (new_typedarray_p);
927 
928   /* 17 */
929   for (uint32_t index = 0; index < len; index++)
930   {
931     ecma_value_t current_value = ecma_op_object_find_by_uint32_index (arraylike_object_p, index);
932 
933     if (ECMA_IS_VALUE_ERROR (current_value))
934     {
935       ret_value = current_value;
936       break;
937     }
938 
939     if (ecma_is_value_found (current_value))
940     {
941       ecma_value_t set_value = ecma_op_typedarray_from_helper (this_val,
942                                                                current_value,
943                                                                index,
944                                                                func_object_p,
945                                                                &info,
946                                                                setter_cb);
947 
948       if (ECMA_IS_VALUE_ERROR (set_value))
949       {
950         ret_value = set_value;
951         break;
952       }
953     }
954   }
955 
956   ecma_deref_object (arraylike_object_p);
957 
958   if (ECMA_IS_VALUE_ERROR (ret_value))
959   {
960     ecma_deref_object (new_typedarray_p);
961   }
962 
963   return ret_value;
964 } /* ecma_op_typedarray_from */
965 
966 /**
967  * Get the arraybuffer of the typedarray object
968  *
969  * @return the pointer to the internal arraybuffer
970  */
971 inline ecma_object_t * JERRY_ATTR_ALWAYS_INLINE
ecma_typedarray_get_arraybuffer(ecma_object_t * typedarray_p)972 ecma_typedarray_get_arraybuffer (ecma_object_t *typedarray_p) /**< the pointer to the typedarray object */
973 {
974   JERRY_ASSERT (ecma_object_is_typedarray (typedarray_p));
975 
976   ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) typedarray_p;
977 
978   return ecma_get_object_from_value (ext_object_p->u.pseudo_array.u2.arraybuffer);
979 } /* ecma_typedarray_get_arraybuffer */
980 
981 /**
982  * Get the element size shift in the typedarray object
983  *
984  * @return the size shift of the element, size is 1 << shift
985  */
986 uint8_t
ecma_typedarray_get_element_size_shift(ecma_object_t * typedarray_p)987 ecma_typedarray_get_element_size_shift (ecma_object_t *typedarray_p) /**< the pointer to the typedarray object */
988 {
989   JERRY_ASSERT (ecma_object_is_typedarray (typedarray_p));
990 
991   return ecma_typedarray_helper_get_shift_size (ecma_get_typedarray_id (typedarray_p));
992 } /* ecma_typedarray_get_element_size_shift */
993 
994 /**
995  * Get the array length of the typedarray object
996  *
997  * @return the array length
998  */
999 ecma_length_t
ecma_typedarray_get_length(ecma_object_t * typedarray_p)1000 ecma_typedarray_get_length (ecma_object_t *typedarray_p) /**< the pointer to the typedarray object */
1001 {
1002   JERRY_ASSERT (ecma_object_is_typedarray (typedarray_p));
1003 
1004   ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) typedarray_p;
1005 
1006   if (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_TYPEDARRAY)
1007   {
1008     ecma_object_t *arraybuffer_p = ecma_get_object_from_value (ext_object_p->u.pseudo_array.u2.arraybuffer);
1009     ecma_length_t buffer_length = ecma_arraybuffer_get_length (arraybuffer_p);
1010     uint8_t shift = ecma_typedarray_get_element_size_shift (typedarray_p);
1011 
1012     return buffer_length >> shift;
1013   }
1014 
1015   ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (typedarray_p);
1016   if (ecma_arraybuffer_is_detached (arraybuffer_p))
1017   {
1018     return 0;
1019   }
1020 
1021   ecma_extended_typedarray_object_t *info_p = (ecma_extended_typedarray_object_t *) ext_object_p;
1022 
1023   return info_p->array_length;
1024 } /* ecma_typedarray_get_length */
1025 
1026 /**
1027  * Get the offset of the internal arraybuffer
1028  *
1029  * @return the offset
1030  */
1031 ecma_length_t
ecma_typedarray_get_offset(ecma_object_t * typedarray_p)1032 ecma_typedarray_get_offset (ecma_object_t *typedarray_p) /**< the pointer to the typedarray object */
1033 {
1034   JERRY_ASSERT (ecma_object_is_typedarray (typedarray_p));
1035 
1036   ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) typedarray_p;
1037 
1038   if (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_TYPEDARRAY)
1039   {
1040     return 0;
1041   }
1042 
1043   ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (typedarray_p);
1044   if (ecma_arraybuffer_is_detached (arraybuffer_p))
1045   {
1046     return 0;
1047   }
1048 
1049   ecma_extended_typedarray_object_t *info_p = (ecma_extended_typedarray_object_t *) ext_object_p;
1050 
1051   return info_p->byte_offset;
1052 } /* ecma_typedarray_get_offset */
1053 
1054 /**
1055  * Utility function: return the pointer of the data buffer referenced by the typed array
1056  *
1057  * @return pointer to the data buffer
1058  */
1059 lit_utf8_byte_t *
ecma_typedarray_get_buffer(ecma_object_t * typedarray_p)1060 ecma_typedarray_get_buffer (ecma_object_t *typedarray_p) /**< the pointer to the typed array object */
1061 {
1062   ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (typedarray_p);
1063 
1064   return ecma_arraybuffer_get_buffer (arraybuffer_p) + ecma_typedarray_get_offset (typedarray_p);
1065 } /* ecma_typedarray_get_buffer */
1066 
1067 /**
1068  * Create a new typedarray object.
1069  *
1070  * The struct of the typedarray object
1071  *   ecma_object_t
1072  *   extend_part
1073  *   typedarray_info
1074  *
1075  * @return ecma value of the new typedarray object
1076  *         Returned value must be freed with ecma_free_value
1077  */
1078 ecma_value_t
ecma_op_create_typedarray(const ecma_value_t * arguments_list_p,ecma_length_t arguments_list_len,ecma_object_t * proto_p,uint8_t element_size_shift,ecma_typedarray_type_t typedarray_id)1079 ecma_op_create_typedarray (const ecma_value_t *arguments_list_p, /**< the arg list passed to typedarray construct */
1080                            ecma_length_t arguments_list_len, /**< the length of the arguments_list_p */
1081                            ecma_object_t *proto_p, /**< prototype object */
1082                            uint8_t element_size_shift, /**< the size shift of the element length */
1083                            ecma_typedarray_type_t typedarray_id) /**< id of the typedarray */
1084 {
1085   JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
1086 
1087   ecma_value_t ret = ECMA_VALUE_EMPTY;
1088 
1089   if (arguments_list_len == 0)
1090   {
1091     /* 22.2.1.1 */
1092     ret = ecma_typedarray_create_object_with_length (0, NULL, proto_p, element_size_shift, typedarray_id);
1093   }
1094   else if (!ecma_is_value_object (arguments_list_p[0]))
1095   {
1096     /* 22.2.1.2 */
1097     if (ecma_is_value_undefined (arguments_list_p[0]))
1098     {
1099       return ecma_raise_type_error (ECMA_ERR_MSG ("length argument is undefined"));
1100     }
1101 
1102     ECMA_OP_TO_NUMBER_TRY_CATCH (num, arguments_list_p[0], ret);
1103 
1104     uint32_t length = ecma_number_to_uint32 (num);
1105 
1106     if (num != ((ecma_number_t) length))
1107     {
1108       ret = ecma_raise_range_error (ECMA_ERR_MSG ("Invalid typedarray length."));
1109     }
1110     else
1111     {
1112       ret = ecma_typedarray_create_object_with_length (length,
1113                                                        NULL,
1114                                                        proto_p,
1115                                                        element_size_shift,
1116                                                        typedarray_id);
1117     }
1118 
1119     ECMA_OP_TO_NUMBER_FINALIZE (num);
1120   }
1121   else if (ecma_is_value_object (arguments_list_p[0]))
1122   {
1123     ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list_p[0]);
1124     if (ecma_object_is_typedarray (obj_p))
1125     {
1126       /* 22.2.1.3 */
1127       ecma_object_t *typedarray_p = obj_p;
1128       ret = ecma_typedarray_create_object_with_typedarray (typedarray_p,
1129                                                            proto_p,
1130                                                            element_size_shift,
1131                                                            typedarray_id);
1132     }
1133     else if (ecma_object_class_is (obj_p, LIT_MAGIC_STRING_ARRAY_BUFFER_UL))
1134     {
1135       /* 22.2.1.5 */
1136       ecma_object_t *arraybuffer_p = obj_p;
1137       ecma_value_t arg2 = ((arguments_list_len > 1) ? arguments_list_p[1]
1138                                                     : ECMA_VALUE_UNDEFINED);
1139 
1140       ecma_value_t arg3 = ((arguments_list_len > 2) ? arguments_list_p[2]
1141                                                     : ECMA_VALUE_UNDEFINED);
1142 
1143       ecma_number_t offset;
1144       if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (arg2, &offset)))
1145       {
1146         return ECMA_VALUE_ERROR;
1147       }
1148 
1149       if (ecma_number_is_negative (offset))
1150       {
1151         ret = ecma_raise_range_error (ECMA_ERR_MSG ("Invalid offset."));
1152       }
1153       else if (ecma_arraybuffer_is_detached (arraybuffer_p))
1154       {
1155         ret = ecma_raise_type_error (ECMA_ERR_MSG ("Invalid detached ArrayBuffer."));
1156       }
1157       else
1158       {
1159         ecma_length_t buf_byte_length = ecma_arraybuffer_get_length (arraybuffer_p);
1160         ecma_length_t new_byte_length = 0;
1161 
1162         if (ecma_is_value_undefined (arg3))
1163         {
1164           if (buf_byte_length % (uint32_t) (1 << element_size_shift) != 0)
1165           {
1166             ret = ecma_raise_range_error (ECMA_ERR_MSG ("Invalid length."));
1167           }
1168           else if (buf_byte_length < offset)
1169           {
1170             ret = ecma_raise_range_error (ECMA_ERR_MSG ("Invalid length."));
1171           }
1172           else
1173           {
1174             new_byte_length = (ecma_length_t) (buf_byte_length - offset);
1175           }
1176         }
1177         else
1178         {
1179           uint32_t new_length;
1180           if (ECMA_IS_VALUE_ERROR (ecma_op_to_length (arg3, &new_length)))
1181           {
1182             return ECMA_VALUE_ERROR;
1183           }
1184 
1185           if (new_length > (UINT32_MAX >> element_size_shift))
1186           {
1187             ret = ecma_raise_range_error (ECMA_ERR_MSG ("Maximum typedarray size is reached."));
1188           }
1189           else
1190           {
1191             new_byte_length = (ecma_length_t) new_length << element_size_shift;
1192 
1193             if (((ecma_number_t) new_byte_length + offset) > buf_byte_length)
1194             {
1195               ret = ecma_raise_range_error (ECMA_ERR_MSG ("Invalid length."));
1196             }
1197           }
1198         }
1199 
1200         if (ecma_is_value_empty (ret))
1201         {
1202           ecma_length_t array_length = new_byte_length >> element_size_shift;
1203           ret = ecma_typedarray_create_object_with_buffer (arraybuffer_p,
1204                                                            (ecma_length_t) offset,
1205                                                            array_length,
1206                                                            proto_p,
1207                                                            element_size_shift,
1208                                                            typedarray_id);
1209         }
1210       }
1211     }
1212     else
1213     {
1214       /* 22.2.1.4 */
1215       ecma_value_t undef = ECMA_VALUE_UNDEFINED;
1216       ret = ecma_op_typedarray_from (arguments_list_p[0],
1217                                      undef,
1218                                      undef,
1219                                      proto_p,
1220                                      element_size_shift,
1221                                      typedarray_id);
1222     }
1223   }
1224 
1225   return ret;
1226 } /* ecma_op_create_typedarray */
1227 
1228 /**
1229  * Check if the object is typedarray
1230  *
1231  * @return true - if object is a TypedArray object
1232  *         false - otherwise
1233  */
1234 bool
ecma_object_is_typedarray(ecma_object_t * obj_p)1235 ecma_object_is_typedarray (ecma_object_t *obj_p) /**< the target object need to be checked */
1236 {
1237   JERRY_ASSERT (!ecma_is_lexical_environment (obj_p));
1238 
1239   if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_PSEUDO_ARRAY)
1240   {
1241     ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
1242 
1243     return ((ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_TYPEDARRAY)
1244             || (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_TYPEDARRAY_WITH_INFO));
1245   }
1246 
1247   return false;
1248 } /* ecma_object_is_typedarray */
1249 
1250 /**
1251  * Check if the value is typedarray
1252  *
1253  * @return true - if value is a TypedArray object
1254  *         false - otherwise
1255  */
1256 bool
ecma_is_typedarray(ecma_value_t value)1257 ecma_is_typedarray (ecma_value_t value) /**< the target need to be checked */
1258 {
1259   if (!ecma_is_value_object (value))
1260   {
1261     return false;
1262   }
1263 
1264   return ecma_object_is_typedarray (ecma_get_object_from_value (value));
1265 } /* ecma_is_typedarray */
1266 
1267 /**
1268  * List names of a TypedArray object's integer indexed properties
1269  *
1270  * @return void
1271  */
1272 void
ecma_op_typedarray_list_lazy_property_names(ecma_object_t * obj_p,ecma_collection_t * main_collection_p)1273 ecma_op_typedarray_list_lazy_property_names (ecma_object_t *obj_p, /**< a TypedArray object */
1274                                              ecma_collection_t *main_collection_p) /**< 'main' collection */
1275 {
1276   JERRY_ASSERT (ecma_object_is_typedarray (obj_p));
1277 
1278   ecma_length_t array_length = ecma_typedarray_get_length (obj_p);
1279 
1280   for (ecma_length_t i = 0; i < array_length; i++)
1281   {
1282     ecma_string_t *name_p = ecma_new_ecma_string_from_uint32 (i);
1283 
1284     ecma_collection_push_back (main_collection_p, ecma_make_string_value (name_p));
1285   }
1286 } /* ecma_op_typedarray_list_lazy_property_names */
1287 
1288 /**
1289  * Define the integer number property value of the typedarray
1290  *
1291  * See also: ES2015 9.4.5.3: 3.c
1292  *
1293  * @return boolean, false if failed
1294  */
1295 bool
ecma_op_typedarray_define_index_prop(ecma_object_t * obj_p,uint32_t index,const ecma_property_descriptor_t * property_desc_p)1296 ecma_op_typedarray_define_index_prop (ecma_object_t *obj_p, /**< a TypedArray object */
1297                                       uint32_t index, /**< the index number */
1298                                       const ecma_property_descriptor_t *property_desc_p) /**< the description of
1299                                                                                                the prop */
1300 {
1301   JERRY_ASSERT (ecma_object_is_typedarray (obj_p));
1302 
1303   ecma_length_t array_length = ecma_typedarray_get_length (obj_p);
1304 
1305   if ((index >= array_length)
1306       || (property_desc_p->flags & (ECMA_PROP_IS_GET_DEFINED | ECMA_PROP_IS_SET_DEFINED))
1307       || ((property_desc_p->flags & (ECMA_PROP_IS_CONFIGURABLE_DEFINED | ECMA_PROP_IS_CONFIGURABLE))
1308            == (ECMA_PROP_IS_CONFIGURABLE_DEFINED | ECMA_PROP_IS_CONFIGURABLE))
1309       || ((property_desc_p->flags & ECMA_PROP_IS_ENUMERABLE_DEFINED)
1310           && !(property_desc_p->flags & ECMA_PROP_IS_ENUMERABLE))
1311       || ((property_desc_p->flags & ECMA_PROP_IS_WRITABLE_DEFINED)
1312           && !(property_desc_p->flags & ECMA_PROP_IS_WRITABLE)))
1313   {
1314     return false;
1315   }
1316 
1317   if (property_desc_p->flags & ECMA_PROP_IS_VALUE_DEFINED)
1318   {
1319     ecma_number_t num_var;
1320     ecma_value_t error = ecma_get_number (property_desc_p->value, &num_var);
1321 
1322     if (ECMA_IS_VALUE_ERROR (error))
1323     {
1324       jcontext_release_exception ();
1325       return false;
1326     }
1327     ecma_typedarray_info_t info = ecma_typedarray_get_info (obj_p);
1328 
1329     if (index >= info.length)
1330     {
1331       return false;
1332     }
1333 
1334     lit_utf8_byte_t *src_buffer = info.buffer_p + (index << info.shift);
1335     ecma_set_typedarray_element (src_buffer, num_var, info.id);
1336   }
1337 
1338   return true;
1339 } /* ecma_op_typedarray_define_index_prop */
1340 
1341 /**
1342  * Create a typedarray object based on the "type" and arraylength
1343  * The "type" is same with arg1
1344  *
1345  * @return ecma_value_t
1346  */
1347 ecma_value_t
ecma_op_create_typedarray_with_type_and_length(ecma_typedarray_type_t typedarray_id,ecma_length_t array_length)1348 ecma_op_create_typedarray_with_type_and_length (ecma_typedarray_type_t typedarray_id, /** TypedArray id  */
1349                                                 ecma_length_t array_length) /**< length of the typedarray */
1350 {
1351   // TODO: assert validate typedarray_id
1352   ecma_object_t *proto_p = ecma_builtin_get (ecma_typedarray_helper_get_prototype_id (typedarray_id));
1353   uint8_t element_size_shift = ecma_typedarray_helper_get_shift_size (typedarray_id);
1354 
1355   ecma_value_t new_obj = ecma_typedarray_create_object_with_length (array_length,
1356                                                                     NULL,
1357                                                                     proto_p,
1358                                                                     element_size_shift,
1359                                                                     typedarray_id);
1360 
1361   return new_obj;
1362 } /* ecma_op_create_typedarray_with_type_and_length */
1363 
1364 /**
1365  * Method for getting the additional typedArray informations.
1366  */
1367 ecma_typedarray_info_t
ecma_typedarray_get_info(ecma_object_t * typedarray_p)1368 ecma_typedarray_get_info (ecma_object_t *typedarray_p)
1369 {
1370   ecma_typedarray_info_t info;
1371 
1372   info.id = ecma_get_typedarray_id (typedarray_p);
1373   info.length = ecma_typedarray_get_length (typedarray_p);
1374   info.shift = ecma_typedarray_get_element_size_shift (typedarray_p);
1375   info.element_size = (uint8_t) (1 << info.shift);
1376   info.offset = ecma_typedarray_get_offset (typedarray_p);
1377   info.array_buffer_p = ecma_typedarray_get_arraybuffer (typedarray_p);
1378   info.buffer_p = ecma_arraybuffer_get_buffer (info.array_buffer_p) + info.offset;
1379 
1380   return info;
1381 } /* ecma_typedarray_get_info */
1382 
1383 /**
1384  * @}
1385  * @}
1386  */
1387 #endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
1388