# TypedArray.subarray byteOffset with detached buffers

**URL:** <https://es.discourse.group/t/typedarray-subarray-byteoffset-with-detached-buffers/2381>\
**Category:** I have questions\
**Tags:** proposal\
**Created:** [June 10, 2025, 3:07pm UTC](https://es.discourse.group/t/typedarray-subarray-byteoffset-with-detached-buffers/2381 "2025-06-10T15:07:46Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![nickv](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/nickv/32/2478_2.png) [@nickv](https://es.discourse.group/u/nickv)\
**Post date:** [June 10, 2025, 3:07pm UTC](https://es.discourse.group/t/typedarray-subarray-byteoffset-with-detached-buffers/2381/1 "2025-06-10T15:07:46Z")

</div>

Wondering if not setting `byteOffset=0` in the `TypedArray.subarray` for detached buffers is a spec omission or a deliberate design decision.

I had noticed a new test262 for it in [built-ins/TypedArray/prototype/subarray/byteoffset-with-detached-buffer.js](https://github.com/tc39/test262/blob/823f4cfd2004cf410bc0344304e22e12d243e955/test/built-ins/TypedArray/prototype/subarray/byteoffset-with-detached-buffer.js) and indeed the [spec](https://tc39.es/ecma262/#sec-%25typedarray%25.prototype.subarray) seems to require reading the `byteOffset` even if the buffer is detached.

If the array is detached spec says `6. If IsTypedArrayOutOfBounds(srcRecord) is true, then Let srcLength be 0.`. `IsTypedArrayOutOfBounds()` considers a detached array out of bounds, so that takes effect and `srcLength=0`, however further below we don't do the same with the `srcByteOffset`. That seems inconsistent at first sight. Why does it make sense to preserve the `byteOffset` from a detached buffer; is it deliberate or it's a spec omission?

It would seem that `If IsTypedArrayOutOfBounds(srcRecord) is true, then Let srcByteOffset be 0` would be more reasonable to have.

---

<div class="post-metadata">

**Author:** ![nickv](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/nickv/32/2478_2.png) [@nickv](https://es.discourse.group/u/nickv)\
**Post date:** [June 26, 2025, 8:14pm UTC](https://es.discourse.group/t/typedarray-subarray-byteoffset-with-detached-buffers/2381/2 "2025-06-26T20:14:27Z")

</div>

Maybe a simple example can help. This assumes we run in a test environment which has the ability to detach a buffer. The example is from the linked test262 test but a bit shorter.

```javascript
const elementSize = Float64Array.BYTES_PER_ELEMENT; // 8
let buffer = new ArrayBuffer(2 * elementSize);
let typedArray = new Float64Array(buffer, elementSize, 1);

typedArray.constructor = {
    [Symbol.species]: function(_, offset, _) {
        print("elementSize: " + elementSize);
        print("offset: " + offset);
        return new Float64Array(1);
    }
};

let end = {valueOf() {$262.detachArrayBuffer(buffer); return 0;}};
typedArray.subarray(1, end);

```

Currently we print the offset = 16, but I wonder if we detached the buffer if it makes sense to still access the offset from it.

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [June 26, 2025, 8:27pm UTC](https://es.discourse.group/t/typedarray-subarray-byteoffset-with-detached-buffers/2381/3 "2025-06-26T20:27:54Z")

</div>

Once detached, there shouldn't be any information left in it, including the offset.

---

<div class="post-metadata">

**Author:** ![nickv](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/nickv/32/2478_2.png) [@nickv](https://es.discourse.group/u/nickv)\
**Post date:** [June 26, 2025, 8:51pm UTC](https://es.discourse.group/t/typedarray-subarray-byteoffset-with-detached-buffers/2381/4 "2025-06-26T20:51:35Z")

</div>

> Once detached, there shouldn't be any information left in it, including the offset.

That was my idea as well and figured it might be an issue with the spec [ECMAScript® 2026 Language&nbsp;Specification](https://tc39.es/ecma262/#sec-%25typedarray%25.prototype.subarray)

Maybe line `13. Let srcByteOffset be O.[[ByteOffset]].` should check if the buffer is detached and set `ByteOffset` to 0 or raise an error?

---

<div class="post-metadata">

**Author:** ![ptomato](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ptomato/32/214_2.png) [@ptomato](https://es.discourse.group/u/ptomato)\
**Post date:** [June 27, 2025, 11:33pm UTC](https://es.discourse.group/t/typedarray-subarray-byteoffset-with-detached-buffers/2381/5 "2025-06-27T23:33:03Z")

</div>

After reading your code sample I think the test is correct.

[According to the spec text for `subarray`](https://tc39.es/ecma262/#sec-%25typedarray%25.prototype.subarray) the buffer isn't yet detached in step 6, so it's fine to obtain the offset in step 13. The buffer only becomes detached in step 16.a, as a side effect of ToIntegerOrInfinity.

---

<div class="post-metadata">

**Author:** ![nickv](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/nickv/32/2478_2.png) [@nickv](https://es.discourse.group/u/nickv)\
**Post date:** [June 29, 2025, 5:30pm UTC](https://es.discourse.group/t/typedarray-subarray-byteoffset-with-detached-buffers/2381/6 "2025-06-29T17:30:47Z")

</div>

> [According to the spec text for `subarray`](https://tc39.es/ecma262/#sec-%25typedarray%25.prototype.subarray) the buffer isn't yet detached in step 6, so it's fine to obtain the offset in step 13. The buffer only becomes detached in step 16.a, as a side effect of ToIntegerOrInfinity.

Oh, now I see it! That makes perfect sense. Thank you for explaining, @ptomato

---

<div class="post-metadata">

**Author:** ![nickv](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/nickv/32/2478_2.png) [@nickv](https://es.discourse.group/u/nickv)\
**Post date:** [August 25, 2025, 6:26pm UTC](https://es.discourse.group/t/typedarray-subarray-byteoffset-with-detached-buffers/2381/7 "2025-08-25T18:26:03Z")

</div>

Sorry for reviving an old thread. It seems there is still a case when the spec allows reading `ByteOffset` from a detached buffer:

If instead of the `end` it’s the `start` that has the `valueOf() {$DETACHBUFFER(ab); return ...}` logic (like the test does), in `8. Let relativeStart be ? ToIntegerOrInfinity(start).` the buffer would be detached and in `13. Let srcByteOffset be O.[[ByteOffset]].`we’d be reading the offset from a detached buffer.

```javascript

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
4. Let buffer be O.[[ViewedArrayBuffer]].
5. Let srcRecord be MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
6. If IsTypedArrayOutOfBounds(srcRecord) is true, then
   a. Let srcLength be 0.
7. Else,
   a. Let srcLength be TypedArrayLength(srcRecord).
8. Let relativeStart be ? ToIntegerOrInfinity(start).
9. If relativeStart = -∞, let startIndex be 0.
10. Else if relativeStart < 0, let startIndex be max(srcLength + relativeStart, 0).
11. Else, let startIndex be min(relativeStart, srcLength).
12. Let elementSize be TypedArrayElementSize(O).
13. Let srcByteOffset be O.[[ByteOffset]].
14. Let beginByteOffset be srcByteOffset + (startIndex × elementSize).
15. If O.[[ArrayLength]] is auto and end is undefined, then
    a. Let argumentsList be « buffer, 𝔽(beginByteOffset) ».
16. Else,
    a. If end is undefined, let relativeEnd be srcLength; else let relativeEnd be ? ToIntegerOrInfinity(end).
    b. If relativeEnd = -∞, let endIndex be 0.
    c. Else if relativeEnd < 0, let endIndex be max(srcLength + relativeEnd, 0).
    d. Else, let endIndex be min(relativeEnd, srcLength).
    e. Let newLength be max(endIndex - startIndex, 0).
    f. Let argumentsList be « buffer, 𝔽(beginByteOffset), 𝔽(newLength) ».
17. Return ? TypedArraySpeciesCreate(O, argumentsList).

```

---

<div class="post-metadata">

**Author:** ![gibson042](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/gibson042/32/160_2.png) [@gibson042](https://es.discourse.group/u/gibson042)\
**Post date:** [September 2, 2025, 4:25pm UTC](https://es.discourse.group/t/typedarray-subarray-byteoffset-with-detached-buffers/2381/8 "2025-09-02T16:25:32Z")

</div>

In [%TypedArray%.prototype.subarray](https://tc39.es/ecma262/multipage/indexed-collections.html#sec-%25typedarray%25.prototype.subarray), _O_ is not an ArrayBuffer but rather a TypedArray, and reading its original-valued [[ByteOffset]] slot after detachment of its [[ViewedArrayBuffer]] doesn’t seem to incur any issues—_beginByteOffset_ will be derived from combining that base with the value from coercing _start_, and then « _buffer_, 𝔽(_beginByteOffset_), … » arguments for a [TypedArray constructor](https://tc39.es/ecma262/multipage/indexed-collections.html#sec-typedarray) (via [TypedArraySpeciesCreate](https://tc39.es/ecma262/multipage/indexed-collections.html#typedarray-species-create)) will be routed to [InitializeTypedArrayFromArrayBuffer](https://tc39.es/ecma262/multipage/indexed-collections.html#sec-initializetypedarrayfromarraybuffer), which detects when _buffer_ is already detached and throws a TypeError in that case.

---

<div class="post-metadata">

**Author:** ![nickv](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/nickv/32/2478_2.png) [@nickv](https://es.discourse.group/u/nickv)\
**Post date:** [September 3, 2025, 4:14am UTC](https://es.discourse.group/t/typedarray-subarray-byteoffset-with-detached-buffers/2381/9 "2025-09-03T04:14:28Z")

</div>

Thanks for the clarification. So there is nothing inherently wrong in accessing the ByteOffset from the TypedArray even if the buffer is detached. [`InitializeTypedArrayFromArrayBuffer`](https://tc39.es/ecma262/multipage/indexed-collections.html#sec-initializetypedarrayfromarraybuffer)would throw an exception anyway. In the test the constructor is overridden and instead returns a new TypeArray altogether.
