blob: 44a7324bde800b4d75f2a5cf46581727ed7f191b [file] [log] [blame]
// 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);
}
}