// Copyright 2018 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. #include 'src/builtins/builtins-data-view-gen.h' namespace data_view { macro MakeDataViewGetterNameString(kind: constexpr ElementsKind): String { if constexpr (kind == UINT8_ELEMENTS) { return 'DataView.prototype.getUint8'; } else if constexpr (kind == INT8_ELEMENTS) { return 'DataView.prototype.getInt8'; } else if constexpr (kind == UINT16_ELEMENTS) { return 'DataView.prototype.getUint16'; } else if constexpr (kind == INT16_ELEMENTS) { return 'DataView.prototype.getInt16'; } else if constexpr (kind == UINT32_ELEMENTS) { return 'DataView.prototype.getUint32'; } else if constexpr (kind == INT32_ELEMENTS) { return 'DataView.prototype.getInt32'; } else if constexpr (kind == FLOAT32_ELEMENTS) { return 'DataView.prototype.getFloat32'; } else if constexpr (kind == FLOAT64_ELEMENTS) { return 'DataView.prototype.getFloat64'; } else if constexpr (kind == BIGINT64_ELEMENTS) { return 'DataView.prototype.getBigInt64'; } else if constexpr (kind == BIGUINT64_ELEMENTS) { return 'DataView.prototype.getBigUint64'; } else { unreachable; } } macro MakeDataViewSetterNameString(kind: constexpr ElementsKind): String { if constexpr (kind == UINT8_ELEMENTS) { return 'DataView.prototype.setUint8'; } else if constexpr (kind == INT8_ELEMENTS) { return 'DataView.prototype.setInt8'; } else if constexpr (kind == UINT16_ELEMENTS) { return 'DataView.prototype.setUint16'; } else if constexpr (kind == INT16_ELEMENTS) { return 'DataView.prototype.setInt16'; } else if constexpr (kind == UINT32_ELEMENTS) { return 'DataView.prototype.setUint32'; } else if constexpr (kind == INT32_ELEMENTS) { return 'DataView.prototype.setInt32'; } else if constexpr (kind == FLOAT32_ELEMENTS) { return 'DataView.prototype.setFloat32'; } else if constexpr (kind == FLOAT64_ELEMENTS) { return 'DataView.prototype.setFloat64'; } else if constexpr (kind == BIGINT64_ELEMENTS) { return 'DataView.prototype.setBigInt64'; } else if constexpr (kind == BIGUINT64_ELEMENTS) { return 'DataView.prototype.setBigUint64'; } else { unreachable; } } macro WasDetached(view: JSArrayBufferView): bool { return IsDetachedBuffer(view.buffer); } macro ValidateDataView(context: Context, o: JSAny, method: String): JSDataView { try { return Cast(o) otherwise CastError; } label CastError { ThrowTypeError(kIncompatibleMethodReceiver, method); } } // ES6 section 24.2.4.1 get DataView.prototype.buffer javascript builtin DataViewPrototypeGetBuffer( js-implicit context: Context, receiver: JSAny)(...arguments): JSArrayBuffer { const dataView: JSDataView = ValidateDataView(context, receiver, 'get DataView.prototype.buffer'); return dataView.buffer; } // ES6 section 24.2.4.2 get DataView.prototype.byteLength javascript builtin DataViewPrototypeGetByteLength( js-implicit context: Context, receiver: JSAny)(...arguments): Number { const dataView: JSDataView = ValidateDataView( context, receiver, 'get DataView.prototype.byte_length'); if (WasDetached(dataView)) { // TODO(bmeurer): According to the ES6 spec, we should throw a TypeError // here if the JSArrayBuffer of the {dataView} was detached. return 0; } return Convert(dataView.byte_length); } // ES6 section 24.2.4.3 get DataView.prototype.byteOffset javascript builtin DataViewPrototypeGetByteOffset( js-implicit context: Context, receiver: JSAny)(...arguments): Number { const dataView: JSDataView = ValidateDataView( context, receiver, 'get DataView.prototype.byte_offset'); if (WasDetached(dataView)) { // TODO(bmeurer): According to the ES6 spec, we should throw a TypeError // here if the JSArrayBuffer of the {dataView} was detached. return 0; } return Convert(dataView.byte_offset); } extern macro BitcastInt32ToFloat32(uint32): float32; extern macro BitcastFloat32ToInt32(float32): uint32; extern macro Float64ExtractLowWord32(float64): uint32; extern macro Float64ExtractHighWord32(float64): uint32; extern macro Float64InsertLowWord32(float64, uint32): float64; extern macro Float64InsertHighWord32(float64, uint32): float64; extern macro DataViewBuiltinsAssembler::LoadUint8(RawPtr, uintptr): uint32; extern macro DataViewBuiltinsAssembler::LoadInt8(RawPtr, uintptr): int32; macro LoadDataView8( buffer: JSArrayBuffer, offset: uintptr, signed: constexpr bool): Smi { if constexpr (signed) { return Convert(LoadInt8(buffer.backing_store, offset)); } else { return Convert(LoadUint8(buffer.backing_store, offset)); } } macro LoadDataView16( buffer: JSArrayBuffer, offset: uintptr, requestedLittleEndian: bool, signed: constexpr bool): Number { const dataPointer: RawPtr = buffer.backing_store; let b0: int32; let b1: int32; let result: int32; // Sign-extend the most significant byte by loading it as an Int8. if (requestedLittleEndian) { b0 = Signed(LoadUint8(dataPointer, offset)); b1 = LoadInt8(dataPointer, offset + 1); result = (b1 << 8) + b0; } else { b0 = LoadInt8(dataPointer, offset); b1 = Signed(LoadUint8(dataPointer, offset + 1)); result = (b0 << 8) + b1; } if constexpr (signed) { return Convert(result); } else { // Bit-mask the higher bits to prevent sign extension if we're unsigned. return Convert(result & 0xFFFF); } } macro LoadDataView32( buffer: JSArrayBuffer, offset: uintptr, requestedLittleEndian: bool, kind: constexpr ElementsKind): Number { const dataPointer: RawPtr = buffer.backing_store; const b0: uint32 = LoadUint8(dataPointer, offset); const b1: uint32 = LoadUint8(dataPointer, offset + 1); const b2: uint32 = LoadUint8(dataPointer, offset + 2); const b3: uint32 = LoadUint8(dataPointer, offset + 3); let result: uint32; if (requestedLittleEndian) { result = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0; } else { result = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3; } if constexpr (kind == INT32_ELEMENTS) { return Convert(Signed(result)); } else if constexpr (kind == UINT32_ELEMENTS) { return Convert(result); } else if constexpr (kind == FLOAT32_ELEMENTS) { const floatRes: float64 = Convert(BitcastInt32ToFloat32(result)); return Convert(floatRes); } else { unreachable; } } macro LoadDataViewFloat64( buffer: JSArrayBuffer, offset: uintptr, requestedLittleEndian: bool): Number { const dataPointer: RawPtr = buffer.backing_store; const b0: uint32 = LoadUint8(dataPointer, offset); const b1: uint32 = LoadUint8(dataPointer, offset + 1); const b2: uint32 = LoadUint8(dataPointer, offset + 2); const b3: uint32 = LoadUint8(dataPointer, offset + 3); const b4: uint32 = LoadUint8(dataPointer, offset + 4); const b5: uint32 = LoadUint8(dataPointer, offset + 5); const b6: uint32 = LoadUint8(dataPointer, offset + 6); const b7: uint32 = LoadUint8(dataPointer, offset + 7); let lowWord: uint32; let highWord: uint32; if (requestedLittleEndian) { lowWord = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0; highWord = (b7 << 24) | (b6 << 16) | (b5 << 8) | b4; } else { highWord = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3; lowWord = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7; } let result: float64 = 0; result = Float64InsertLowWord32(result, lowWord); result = Float64InsertHighWord32(result, highWord); return Convert(result); } const kZeroDigitBigInt: constexpr int31 = 0; const kOneDigitBigInt: constexpr int31 = 1; const kTwoDigitBigInt: constexpr int31 = 2; // Create a BigInt on a 64-bit architecture from two 32-bit values. macro MakeBigIntOn64Bit(implicit context: Context)( lowWord: uint32, highWord: uint32, signed: constexpr bool): BigInt { // 0n is represented by a zero-length BigInt. if (lowWord == 0 && highWord == 0) { return Convert(bigint::AllocateBigInt(kZeroDigitBigInt)); } let sign: uint32 = bigint::kPositiveSign; const highPart: intptr = Signed(Convert(highWord)); const lowPart: intptr = Signed(Convert(lowWord)); let rawValue: intptr = (highPart << 32) + lowPart; if constexpr (signed) { if (rawValue < 0) { sign = bigint::kNegativeSign; // We have to store the absolute value of rawValue in the digit. rawValue = 0 - rawValue; } } // Allocate the BigInt and store the absolute value. const result: MutableBigInt = bigint::AllocateEmptyBigInt(sign, kOneDigitBigInt); bigint::StoreBigIntDigit(result, 0, Unsigned(rawValue)); return Convert(result); } // Create a BigInt on a 32-bit architecture from two 32-bit values. macro MakeBigIntOn32Bit(implicit context: Context)( lowWord: uint32, highWord: uint32, signed: constexpr bool): BigInt { // 0n is represented by a zero-length BigInt. if (lowWord == 0 && highWord == 0) { return Convert(bigint::AllocateBigInt(kZeroDigitBigInt)); } // On a 32-bit platform, we might need 1 or 2 digits to store the number. let needTwoDigits: bool = false; let sign: uint32 = bigint::kPositiveSign; // We need to do some math on lowWord and highWord, // so Convert them to int32. let lowPart: int32 = Signed(lowWord); let highPart: int32 = Signed(highWord); // If highWord == 0, the number is positive, and we only need 1 digit, // so we don't have anything to do. // Otherwise, all cases are possible. if (highWord != 0) { if constexpr (signed) { // If highPart < 0, the number is always negative. if (highPart < 0) { sign = bigint::kNegativeSign; // We have to compute the absolute value by hand. // There will be a negative carry from the low word // to the high word iff low != 0. highPart = 0 - highPart; if (lowPart != 0) { highPart = highPart - 1; } lowPart = 0 - lowPart; // Here, highPart could be 0 again so we might have 1 or 2 digits. if (highPart != 0) { needTwoDigits = true; } } else { // In this case, the number is positive, and we need 2 digits. needTwoDigits = true; } } else { // In this case, the number is positive (unsigned), // and we need 2 digits. needTwoDigits = true; } } // Allocate the BigInt with the right sign and length. let result: MutableBigInt; if (needTwoDigits) { result = bigint::AllocateEmptyBigInt(sign, kTwoDigitBigInt); } else { result = bigint::AllocateEmptyBigInt(sign, kOneDigitBigInt); } // Finally, write the digit(s) to the BigInt. bigint::StoreBigIntDigit(result, 0, Unsigned(Convert(lowPart))); if (needTwoDigits) { bigint::StoreBigIntDigit(result, 1, Unsigned(Convert(highPart))); } return Convert(result); } macro MakeBigInt(implicit context: Context)( lowWord: uint32, highWord: uint32, signed: constexpr bool): BigInt { // A BigInt digit has the platform word size, so we only need one digit // on 64-bit platforms but may need two on 32-bit. if constexpr (Is64()) { return MakeBigIntOn64Bit(lowWord, highWord, signed); } else { return MakeBigIntOn32Bit(lowWord, highWord, signed); } } macro LoadDataViewBigInt(implicit context: Context)( buffer: JSArrayBuffer, offset: uintptr, requestedLittleEndian: bool, signed: constexpr bool): BigInt { const dataPointer: RawPtr = buffer.backing_store; const b0: uint32 = LoadUint8(dataPointer, offset); const b1: uint32 = LoadUint8(dataPointer, offset + 1); const b2: uint32 = LoadUint8(dataPointer, offset + 2); const b3: uint32 = LoadUint8(dataPointer, offset + 3); const b4: uint32 = LoadUint8(dataPointer, offset + 4); const b5: uint32 = LoadUint8(dataPointer, offset + 5); const b6: uint32 = LoadUint8(dataPointer, offset + 6); const b7: uint32 = LoadUint8(dataPointer, offset + 7); let lowWord: uint32; let highWord: uint32; if (requestedLittleEndian) { lowWord = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0; highWord = (b7 << 24) | (b6 << 16) | (b5 << 8) | b4; } else { highWord = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3; lowWord = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7; } return MakeBigInt(lowWord, highWord, signed); } extern macro ToSmiIndex(JSAny, Context): Smi labels RangeError; extern macro DataViewBuiltinsAssembler::DataViewElementSize( constexpr ElementsKind): constexpr int31; transitioning macro DataViewGet( context: Context, receiver: JSAny, offset: JSAny, requestedLittleEndian: JSAny, kind: constexpr ElementsKind): Numeric { const dataView: JSDataView = ValidateDataView(context, receiver, MakeDataViewGetterNameString(kind)); let getIndex: Number; try { getIndex = ToIndex(offset, context) otherwise RangeError; } label RangeError { ThrowRangeError(kInvalidDataViewAccessorOffset); } const littleEndian: bool = ToBoolean(requestedLittleEndian); const buffer: JSArrayBuffer = dataView.buffer; if (IsDetachedBuffer(buffer)) { ThrowTypeError(kDetachedOperation, MakeDataViewGetterNameString(kind)); } const getIndexFloat: float64 = Convert(getIndex); const getIndexWord: uintptr = Convert(getIndexFloat); const viewOffsetWord: uintptr = dataView.byte_offset; const viewSizeFloat: float64 = Convert(dataView.byte_length); const elementSizeFloat: float64 = DataViewElementSize(kind); if (getIndexFloat + elementSizeFloat > viewSizeFloat) { ThrowRangeError(kInvalidDataViewAccessorOffset); } const bufferIndex: uintptr = getIndexWord + viewOffsetWord; if constexpr (kind == UINT8_ELEMENTS) { return LoadDataView8(buffer, bufferIndex, false); } else if constexpr (kind == INT8_ELEMENTS) { return LoadDataView8(buffer, bufferIndex, true); } else if constexpr (kind == UINT16_ELEMENTS) { return LoadDataView16(buffer, bufferIndex, littleEndian, false); } else if constexpr (kind == INT16_ELEMENTS) { return LoadDataView16(buffer, bufferIndex, littleEndian, true); } else if constexpr (kind == UINT32_ELEMENTS) { return LoadDataView32(buffer, bufferIndex, littleEndian, kind); } else if constexpr (kind == INT32_ELEMENTS) { return LoadDataView32(buffer, bufferIndex, littleEndian, kind); } else if constexpr (kind == FLOAT32_ELEMENTS) { return LoadDataView32(buffer, bufferIndex, littleEndian, kind); } else if constexpr (kind == FLOAT64_ELEMENTS) { return LoadDataViewFloat64(buffer, bufferIndex, littleEndian); } else if constexpr (kind == BIGUINT64_ELEMENTS) { return LoadDataViewBigInt(buffer, bufferIndex, littleEndian, false); } else if constexpr (kind == BIGINT64_ELEMENTS) { return LoadDataViewBigInt(buffer, bufferIndex, littleEndian, true); } else { unreachable; } } transitioning javascript builtin DataViewPrototypeGetUint8( js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; return DataViewGet(context, receiver, offset, Undefined, UINT8_ELEMENTS); } transitioning javascript builtin DataViewPrototypeGetInt8( js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; return DataViewGet(context, receiver, offset, Undefined, INT8_ELEMENTS); } transitioning javascript builtin DataViewPrototypeGetUint16( js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; const isLittleEndian: JSAny = arguments.length > 1 ? arguments[1] : Undefined; return DataViewGet( context, receiver, offset, isLittleEndian, UINT16_ELEMENTS); } transitioning javascript builtin DataViewPrototypeGetInt16( js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; const isLittleEndian: JSAny = arguments.length > 1 ? arguments[1] : Undefined; return DataViewGet( context, receiver, offset, isLittleEndian, INT16_ELEMENTS); } transitioning javascript builtin DataViewPrototypeGetUint32( js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; const isLittleEndian: JSAny = arguments.length > 1 ? arguments[1] : Undefined; return DataViewGet( context, receiver, offset, isLittleEndian, UINT32_ELEMENTS); } transitioning javascript builtin DataViewPrototypeGetInt32( js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; const isLittleEndian: JSAny = arguments.length > 1 ? arguments[1] : Undefined; return DataViewGet( context, receiver, offset, isLittleEndian, INT32_ELEMENTS); } transitioning javascript builtin DataViewPrototypeGetFloat32( js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; const isLittleEndian: JSAny = arguments.length > 1 ? arguments[1] : Undefined; return DataViewGet( context, receiver, offset, isLittleEndian, FLOAT32_ELEMENTS); } transitioning javascript builtin DataViewPrototypeGetFloat64( js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; const isLittleEndian: JSAny = arguments.length > 1 ? arguments[1] : Undefined; return DataViewGet( context, receiver, offset, isLittleEndian, FLOAT64_ELEMENTS); } transitioning javascript builtin DataViewPrototypeGetBigUint64( js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; const isLittleEndian: JSAny = arguments.length > 1 ? arguments[1] : Undefined; return DataViewGet( context, receiver, offset, isLittleEndian, BIGUINT64_ELEMENTS); } transitioning javascript builtin DataViewPrototypeGetBigInt64( js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; const isLittleEndian: JSAny = arguments.length > 1 ? arguments[1] : Undefined; return DataViewGet( context, receiver, offset, isLittleEndian, BIGINT64_ELEMENTS); } extern macro ToNumber(Context, JSAny): Number; extern macro ToBigInt(Context, JSAny): BigInt; extern macro TruncateFloat64ToWord32(float64): uint32; extern macro DataViewBuiltinsAssembler::StoreWord8(RawPtr, uintptr, uint32): void; macro StoreDataView8(buffer: JSArrayBuffer, offset: uintptr, value: uint32) { StoreWord8(buffer.backing_store, offset, value & 0xFF); } macro StoreDataView16( buffer: JSArrayBuffer, offset: uintptr, value: uint32, requestedLittleEndian: bool) { const dataPointer: RawPtr = buffer.backing_store; const b0: uint32 = value & 0xFF; const b1: uint32 = (value >>> 8) & 0xFF; if (requestedLittleEndian) { StoreWord8(dataPointer, offset, b0); StoreWord8(dataPointer, offset + 1, b1); } else { StoreWord8(dataPointer, offset, b1); StoreWord8(dataPointer, offset + 1, b0); } } macro StoreDataView32( buffer: JSArrayBuffer, offset: uintptr, value: uint32, requestedLittleEndian: bool) { const dataPointer: RawPtr = buffer.backing_store; const b0: uint32 = value & 0xFF; const b1: uint32 = (value >>> 8) & 0xFF; const b2: uint32 = (value >>> 16) & 0xFF; const b3: uint32 = value >>> 24; // We don't need to mask here. if (requestedLittleEndian) { StoreWord8(dataPointer, offset, b0); StoreWord8(dataPointer, offset + 1, b1); StoreWord8(dataPointer, offset + 2, b2); StoreWord8(dataPointer, offset + 3, b3); } else { StoreWord8(dataPointer, offset, b3); StoreWord8(dataPointer, offset + 1, b2); StoreWord8(dataPointer, offset + 2, b1); StoreWord8(dataPointer, offset + 3, b0); } } macro StoreDataView64( buffer: JSArrayBuffer, offset: uintptr, lowWord: uint32, highWord: uint32, requestedLittleEndian: bool) { const dataPointer: RawPtr = buffer.backing_store; const b0: uint32 = lowWord & 0xFF; const b1: uint32 = (lowWord >>> 8) & 0xFF; const b2: uint32 = (lowWord >>> 16) & 0xFF; const b3: uint32 = lowWord >>> 24; const b4: uint32 = highWord & 0xFF; const b5: uint32 = (highWord >>> 8) & 0xFF; const b6: uint32 = (highWord >>> 16) & 0xFF; const b7: uint32 = highWord >>> 24; if (requestedLittleEndian) { StoreWord8(dataPointer, offset, b0); StoreWord8(dataPointer, offset + 1, b1); StoreWord8(dataPointer, offset + 2, b2); StoreWord8(dataPointer, offset + 3, b3); StoreWord8(dataPointer, offset + 4, b4); StoreWord8(dataPointer, offset + 5, b5); StoreWord8(dataPointer, offset + 6, b6); StoreWord8(dataPointer, offset + 7, b7); } else { StoreWord8(dataPointer, offset, b7); StoreWord8(dataPointer, offset + 1, b6); StoreWord8(dataPointer, offset + 2, b5); StoreWord8(dataPointer, offset + 3, b4); StoreWord8(dataPointer, offset + 4, b3); StoreWord8(dataPointer, offset + 5, b2); StoreWord8(dataPointer, offset + 6, b1); StoreWord8(dataPointer, offset + 7, b0); } } extern macro DataViewBuiltinsAssembler::DataViewDecodeBigIntLength( BigIntBase): uint32; extern macro DataViewBuiltinsAssembler::DataViewDecodeBigIntSign(BigIntBase): uint32; // We might get here a BigInt that is bigger than 64 bits, but we're only // interested in the 64 lowest ones. This means the lowest BigInt digit // on 64-bit platforms, and the 2 lowest BigInt digits on 32-bit ones. macro StoreDataViewBigInt( buffer: JSArrayBuffer, offset: uintptr, bigIntValue: BigInt, requestedLittleEndian: bool) { const length: uint32 = DataViewDecodeBigIntLength(bigIntValue); const sign: uint32 = DataViewDecodeBigIntSign(bigIntValue); // The 32-bit words that will hold the BigInt's value in // two's complement representation. let lowWord: uint32 = 0; let highWord: uint32 = 0; // The length is nonzero if and only if the BigInt's value is nonzero. if (length != 0) { if constexpr (Is64()) { // There is always exactly 1 BigInt digit to load in this case. const value: uintptr = bigint::LoadBigIntDigit(bigIntValue, 0); lowWord = Convert(value); // Truncates value to 32 bits. highWord = Convert(value >>> 32); } else { // There might be either 1 or 2 BigInt digits we need to load. lowWord = Convert(bigint::LoadBigIntDigit(bigIntValue, 0)); if (length >= 2) { // Only load the second digit if there is one. highWord = Convert(bigint::LoadBigIntDigit(bigIntValue, 1)); } } } if (sign != 0) { // The number is negative, Convert it. highWord = Unsigned(0 - Signed(highWord)); if (lowWord != 0) { highWord = Unsigned(Signed(highWord) - 1); } lowWord = Unsigned(0 - Signed(lowWord)); } StoreDataView64(buffer, offset, lowWord, highWord, requestedLittleEndian); } transitioning macro DataViewSet( context: Context, receiver: JSAny, offset: JSAny, value: JSAny, requestedLittleEndian: JSAny, kind: constexpr ElementsKind): JSAny { const dataView: JSDataView = ValidateDataView(context, receiver, MakeDataViewSetterNameString(kind)); let getIndex: Number; try { getIndex = ToIndex(offset, context) otherwise RangeError; } label RangeError { ThrowRangeError(kInvalidDataViewAccessorOffset); } const littleEndian: bool = ToBoolean(requestedLittleEndian); const buffer: JSArrayBuffer = dataView.buffer; // According to ES6 section 24.2.1.2 SetViewValue, we must perform // the conversion before doing the bounds check. if constexpr (kind == BIGUINT64_ELEMENTS || kind == BIGINT64_ELEMENTS) { const bigIntValue: BigInt = ToBigInt(context, value); if (IsDetachedBuffer(buffer)) { ThrowTypeError(kDetachedOperation, MakeDataViewSetterNameString(kind)); } const getIndexFloat: float64 = Convert(getIndex); const getIndexWord: uintptr = Convert(getIndexFloat); const viewOffsetWord: uintptr = dataView.byte_offset; const viewSizeFloat: float64 = Convert(dataView.byte_length); const elementSizeFloat: float64 = DataViewElementSize(kind); if (getIndexFloat + elementSizeFloat > viewSizeFloat) { ThrowRangeError(kInvalidDataViewAccessorOffset); } const bufferIndex: uintptr = getIndexWord + viewOffsetWord; StoreDataViewBigInt(buffer, bufferIndex, bigIntValue, littleEndian); } else { const numValue: Number = ToNumber(context, value); if (IsDetachedBuffer(buffer)) { ThrowTypeError(kDetachedOperation, MakeDataViewSetterNameString(kind)); } const getIndexFloat: float64 = Convert(getIndex); const getIndexWord: uintptr = Convert(getIndexFloat); const viewOffsetWord: uintptr = dataView.byte_offset; const viewSizeFloat: float64 = Convert(dataView.byte_length); const elementSizeFloat: float64 = DataViewElementSize(kind); if (getIndexFloat + elementSizeFloat > viewSizeFloat) { ThrowRangeError(kInvalidDataViewAccessorOffset); } const bufferIndex: uintptr = getIndexWord + viewOffsetWord; const doubleValue: float64 = ChangeNumberToFloat64(numValue); if constexpr (kind == UINT8_ELEMENTS || kind == INT8_ELEMENTS) { StoreDataView8( buffer, bufferIndex, TruncateFloat64ToWord32(doubleValue)); } else if constexpr (kind == UINT16_ELEMENTS || kind == INT16_ELEMENTS) { StoreDataView16( buffer, bufferIndex, TruncateFloat64ToWord32(doubleValue), littleEndian); } else if constexpr (kind == UINT32_ELEMENTS || kind == INT32_ELEMENTS) { StoreDataView32( buffer, bufferIndex, TruncateFloat64ToWord32(doubleValue), littleEndian); } else if constexpr (kind == FLOAT32_ELEMENTS) { const floatValue: float32 = TruncateFloat64ToFloat32(doubleValue); StoreDataView32( buffer, bufferIndex, BitcastFloat32ToInt32(floatValue), littleEndian); } else if constexpr (kind == FLOAT64_ELEMENTS) { const lowWord: uint32 = Float64ExtractLowWord32(doubleValue); const highWord: uint32 = Float64ExtractHighWord32(doubleValue); StoreDataView64(buffer, bufferIndex, lowWord, highWord, littleEndian); } } return Undefined; } transitioning javascript builtin DataViewPrototypeSetUint8( js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; const value: JSAny = arguments.length > 1 ? arguments[1] : Undefined; return DataViewSet( context, receiver, offset, value, Undefined, UINT8_ELEMENTS); } transitioning javascript builtin DataViewPrototypeSetInt8( js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; const value: JSAny = arguments.length > 1 ? arguments[1] : Undefined; return DataViewSet( context, receiver, offset, value, Undefined, INT8_ELEMENTS); } transitioning javascript builtin DataViewPrototypeSetUint16( js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; const value: JSAny = arguments.length > 1 ? arguments[1] : Undefined; const isLittleEndian: JSAny = arguments.length > 2 ? arguments[2] : Undefined; return DataViewSet( context, receiver, offset, value, isLittleEndian, UINT16_ELEMENTS); } transitioning javascript builtin DataViewPrototypeSetInt16( js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; const value: JSAny = arguments.length > 1 ? arguments[1] : Undefined; const isLittleEndian: JSAny = arguments.length > 2 ? arguments[2] : Undefined; return DataViewSet( context, receiver, offset, value, isLittleEndian, INT16_ELEMENTS); } transitioning javascript builtin DataViewPrototypeSetUint32( js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; const value: JSAny = arguments.length > 1 ? arguments[1] : Undefined; const isLittleEndian: JSAny = arguments.length > 2 ? arguments[2] : Undefined; return DataViewSet( context, receiver, offset, value, isLittleEndian, UINT32_ELEMENTS); } transitioning javascript builtin DataViewPrototypeSetInt32( js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; const value: JSAny = arguments.length > 1 ? arguments[1] : Undefined; const isLittleEndian: JSAny = arguments.length > 2 ? arguments[2] : Undefined; return DataViewSet( context, receiver, offset, value, isLittleEndian, INT32_ELEMENTS); } transitioning javascript builtin DataViewPrototypeSetFloat32( js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; const value: JSAny = arguments.length > 1 ? arguments[1] : Undefined; const isLittleEndian: JSAny = arguments.length > 2 ? arguments[2] : Undefined; return DataViewSet( context, receiver, offset, value, isLittleEndian, FLOAT32_ELEMENTS); } transitioning javascript builtin DataViewPrototypeSetFloat64( js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; const value: JSAny = arguments.length > 1 ? arguments[1] : Undefined; const isLittleEndian: JSAny = arguments.length > 2 ? arguments[2] : Undefined; return DataViewSet( context, receiver, offset, value, isLittleEndian, FLOAT64_ELEMENTS); } transitioning javascript builtin DataViewPrototypeSetBigUint64( js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; const value: JSAny = arguments.length > 1 ? arguments[1] : Undefined; const isLittleEndian: JSAny = arguments.length > 2 ? arguments[2] : Undefined; return DataViewSet( context, receiver, offset, value, isLittleEndian, BIGUINT64_ELEMENTS); } transitioning javascript builtin DataViewPrototypeSetBigInt64( js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; const value: JSAny = arguments.length > 1 ? arguments[1] : Undefined; const isLittleEndian: JSAny = arguments.length > 2 ? arguments[2] : Undefined; return DataViewSet( context, receiver, offset, value, isLittleEndian, BIGINT64_ELEMENTS); } }