| // Copyright 2019 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| namespace typed_array { |
| // ES %TypedArray%.prototype.subarray |
| transitioning javascript builtin TypedArrayPrototypeSubArray( |
| js-implicit context: NativeContext, receiver: JSAny)( |
| ...arguments): JSTypedArray { |
| const methodName: constexpr string = '%TypedArray%.prototype.subarray'; |
| |
| // 1. Let O be the this value. |
| // 2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]). |
| const source = Cast<JSTypedArray>(receiver) |
| otherwise ThrowTypeError( |
| MessageTemplate::kIncompatibleMethodReceiver, methodName, receiver); |
| |
| // 3. Assert: O has a [[ViewedArrayBuffer]] internal slot. |
| // 4. Let buffer be O.[[ViewedArrayBuffer]]. |
| const buffer = typed_array::GetTypedArrayBuffer(source); |
| |
| // 5. Let getSrcBufferByteLength be |
| // MakeIdempotentArrayBufferByteLengthGetter(SeqCst). |
| // 6. Let srcLength be IntegerIndexedObjectLength(O, getSrcBufferByteLength). |
| let srcLength: uintptr; |
| try { |
| srcLength = LoadJSTypedArrayLengthAndCheckDetached(source) |
| otherwise DetachedOrOutOfBounds; |
| } label DetachedOrOutOfBounds { |
| // 7. If srcLength is out-of-bounds, set srcLength to 0. |
| srcLength = 0; |
| } |
| |
| // 8. Let relativeBegin be ? ToIntegerOrInfinity(begin). |
| // 9. If relativeBegin is -∞, let beginIndex be 0. |
| // 10. Else if relativeBegin < 0, let beginIndex be max(srcLength + |
| // relativeBegin, 0). |
| // 11. Else, let beginIndex be min(relativeBegin, srcLength). |
| const arg0 = arguments[0]; |
| const begin: uintptr = |
| arg0 != Undefined ? ConvertAndClampRelativeIndex(arg0, srcLength) : 0; |
| |
| // 12. If O.[[ArrayLength]] is auto and end is undefined, then |
| const arg1 = arguments[1]; |
| const endIsDefined = arg1 != Undefined; |
| |
| let newLength: NumberOrUndefined; |
| if (IsLengthTrackingJSArrayBufferView(source) && !endIsDefined) { |
| // a. Let newLength be undefined. |
| newLength = Undefined; |
| } else { |
| // 13. Else, |
| // a. If end is undefined, let relativeEnd be srcLength; else let |
| // relativeEnd be ? ToIntegerOrInfinity(end). |
| // b. If relativeEnd is -∞, let endIndex be 0. |
| // c. Else if relativeEnd < 0, let endIndex be max(srcLength + |
| // relativeEnd, 0). |
| // d. Else, let endIndex be min(relativeEnd, srcLength). |
| const end: uintptr = endIsDefined ? |
| ConvertAndClampRelativeIndex(arg1, srcLength) : |
| srcLength; |
| |
| // e. Let newLength be max(endIndex - beginIndex, 0). |
| newLength = Convert<Number>(Unsigned(IntPtrMax(Signed(end - begin), 0))); |
| } |
| |
| // 14. Let constructorName be the String value of O.[[TypedArrayName]]. |
| // 15. Let elementSize be the Number value of the Element Size value |
| // specified in Table 52 for constructorName. |
| const elementsInfo = typed_array::GetTypedArrayElementsInfo(source); |
| |
| // 16. Let srcByteOffset be O.[[ByteOffset]]. |
| const srcByteOffset: uintptr = source.byte_offset; |
| |
| // 17. Let beginByteOffset be srcByteOffset + beginIndex × elementSize. |
| // The subarray can only be too big if the API limits the size of typed |
| // arrays, but doesn't put a similar limit on the size of wasm byte arrays. |
| const beginByteOffset = |
| srcByteOffset + elementsInfo.CalculateByteLength(begin) |
| otherwise ThrowRangeError(MessageTemplate::kInvalidArrayBufferLength); |
| |
| // 18. If newLength is undefined, then |
| // a. Let argumentsList be « buffer, 𝔽(beginByteOffset) ». |
| // 19. Else, |
| // a. Let argumentsList be « buffer, 𝔽(beginByteOffset), 𝔽(newLength) ». |
| // 20. Return ? TypedArraySpeciesCreate(O, argumentsList). |
| return TypedArraySpeciesCreateByBuffer( |
| methodName, source, buffer, beginByteOffset, newLength); |
| } |
| } |