Repository: jerryscript-project/jerryscript
File: jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.c (C)

Code before:
  ecma_typedarray_info_t new_typedarray_info = ecma_typedarray_get_info (new_typedarray_p);

  if (ecma_arraybuffer_is_detached (info_p->array_buffer_p))
  {
    ecma_deref_object (new_typedarray_p);
    return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED);
  }

  uint8_t *dst_buffer_p = ecma_typedarray_get_buffer (&new_typedarray_info);

  src_buffer_p += relative_start << info_p->shift;

  if (info_p->id == new_typedarray_info.id)
  {
    // 22.2.3.23. Step 22. h-i.

    if (JERRY_LIKELY (new_typedarray_info.offset == 0))
    {
      if (info_p->array_buffer_p == new_typedarray_info.array_buffer_p)
      {
        return new_typedarray;
      }

      memcpy (dst_buffer_p, src_buffer_p, count << info_p->shift);
    }
    else if (count >= new_typedarray_info.offset)
    {
      uint32_t byte_shift = (uint32_t) (1 << info_p->shift);

      while (count)
      {
        memmove (dst_buffer_p, src_buffer_p, byte_shift);

        dst_buffer_p += byte_shift;
        src_buffer_p += byte_shift;

        count--;
      }
    }
  }
  else
  {
    // 22.2.3.23. Step 21. b.
    ecma_typedarray_getter_fn_t src_typedarray_getter_cb = ecma_get_typedarray_getter_fn (info_p->id);
    ecma_typedarray_setter_fn_t new_typedarray_setter_cb = ecma_get_typedarray_setter_fn (new_typedarray_info.id);

    for (uint32_t idx = 0; idx < count; idx++)
    {
      ecma_value_t element = src_typedarray_getter_cb (src_buffer_p);
      ecma_value_t set_element = new_typedarray_setter_cb (dst_buffer_p, element);
      ecma_free_value (element);

Review comment (suggestion):
Just to be fair, there was a comment on the original PR which has not been answered yet. I paste it here.

> What if count is less than the target offset? I don't think this condition is correct.
> 
> ```
> var buf = new ArrayBuffer(10);
> var a1 = new Int8Array(buf, 0, 5);
> a1.fill(1);
> a1.constructor = {
>     [Symbol.species]: function (len) {
>         return new Int8Array(buf, 5, 5);
>     }
> };
> var a2 = a1.slice(2,4);
> res = new Int8Array(buf, 0, 10);
> ```
> 
> Also, I don't think checking the offset is the right way, we need to check whether the two typedarrays use the same arraybuffer instead, and only then fall back to copying element-by-element.

_Originally posted by @dbatyai in https://github.com/jerryscript-project/jerryscript/pull/4898#discussion_r766609489_

Code after:
  ecma_typedarray_info_t new_typedarray_info = ecma_typedarray_get_info (new_typedarray_p);

  if (ecma_arraybuffer_is_detached (info_p->array_buffer_p))
  {
    ecma_deref_object (new_typedarray_p);
    return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED);
  }

  uint8_t *dst_buffer_p = ecma_typedarray_get_buffer (&new_typedarray_info);

  src_buffer_p += relative_start << info_p->shift;

  if (info_p->id == new_typedarray_info.id)
  {
    // 22.2.3.23. Step 22. h-i.

    if (JERRY_LIKELY (new_typedarray_info.offset == 0))
    {
      if (info_p->array_buffer_p == new_typedarray_info.array_buffer_p)
      {
        return new_typedarray;
      }

      memcpy (dst_buffer_p, src_buffer_p, count << info_p->shift);
    }
    else
    {
      uint32_t byte_shift = (uint32_t) (1 << info_p->shift);

      while (count)
      {
        memmove (dst_buffer_p, src_buffer_p, byte_shift);

        dst_buffer_p += byte_shift;
        src_buffer_p += byte_shift;

        count--;
      }
    }
  }
  else
  {
    // 22.2.3.23. Step 21. b.
    ecma_typedarray_getter_fn_t src_typedarray_getter_cb = ecma_get_typedarray_getter_fn (info_p->id);
    ecma_typedarray_setter_fn_t new_typedarray_setter_cb = ecma_get_typedarray_setter_fn (new_typedarray_info.id);

    for (uint32_t idx = 0; idx < count; idx++)
    {
      ecma_value_t element = src_typedarray_getter_cb (src_buffer_p);
      ecma_value_t set_element = new_typedarray_setter_cb (dst_buffer_p, element);
      ecma_free_value (element);