14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#include "ecmascript/builtins/builtins_dataview.h"
174514f5e3Sopenharmony_ci#include "ecmascript/builtins/builtins_arraybuffer.h"
184514f5e3Sopenharmony_ci#include "ecmascript/js_arraybuffer.h"
194514f5e3Sopenharmony_ci#include "ecmascript/js_tagged_value-inl.h"
204514f5e3Sopenharmony_ci
214514f5e3Sopenharmony_cinamespace panda::ecmascript::builtins {
224514f5e3Sopenharmony_ci// 24.2.2.1
234514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::DataViewConstructor(EcmaRuntimeCallInfo *argv)
244514f5e3Sopenharmony_ci{
254514f5e3Sopenharmony_ci    ASSERT(argv);
264514f5e3Sopenharmony_ci    JSThread *thread = argv->GetThread();
274514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, DataView, Constructor);
284514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
294514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> ctor = GetConstructor(argv);
304514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv);
314514f5e3Sopenharmony_ci    // 1. If NewTarget is undefined, throw a TypeError exception.
324514f5e3Sopenharmony_ci    if (newTarget->IsUndefined()) {
334514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "newtarget is undefined", JSTaggedValue::Exception());
344514f5e3Sopenharmony_ci    }
354514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> bufferHandle = GetCallArg(argv, 0);
364514f5e3Sopenharmony_ci    // 2. If Type(buffer) is not Object, throw a TypeError exception.
374514f5e3Sopenharmony_ci    if (!bufferHandle->IsECMAObject()) {
384514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "buffer is not Object", JSTaggedValue::Exception());
394514f5e3Sopenharmony_ci    }
404514f5e3Sopenharmony_ci    // 3. If buffer does not have an [[ArrayBufferData]] internal slot, throw a TypeError exception.
414514f5e3Sopenharmony_ci    if (!bufferHandle->IsArrayBuffer() && !bufferHandle->IsSharedArrayBuffer()) {
424514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "buffer is not ArrayBuffer", JSTaggedValue::Exception());
434514f5e3Sopenharmony_ci    }
444514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> offsetHandle = GetCallArg(argv, 1);
454514f5e3Sopenharmony_ci    // 4. Let numberOffset be ToNumber(byteOffset).
464514f5e3Sopenharmony_ci    JSTaggedNumber offsetNumber = JSTaggedValue::ToNumber(thread, offsetHandle);
474514f5e3Sopenharmony_ci    // 6. ReturnIfAbrupt(offset).
484514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
494514f5e3Sopenharmony_ci    int32_t offsetInt = base::NumberHelper::DoubleInRangeInt32(offsetNumber.GetNumber());
504514f5e3Sopenharmony_ci    // 7. If numberOffset ≠ offset or offset < 0, throw a RangeError exception.
514514f5e3Sopenharmony_ci    if (offsetInt < 0) {
524514f5e3Sopenharmony_ci        THROW_RANGE_ERROR_AND_RETURN(thread, "Offset out of range", JSTaggedValue::Exception());
534514f5e3Sopenharmony_ci    }
544514f5e3Sopenharmony_ci    uint32_t offset = static_cast<uint32_t>(offsetInt);
554514f5e3Sopenharmony_ci    // 8. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
564514f5e3Sopenharmony_ci    if (BuiltinsArrayBuffer::IsDetachedBuffer(bufferHandle.GetTaggedValue())) {
574514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "buffer is Detached Buffer", JSTaggedValue::Exception());
584514f5e3Sopenharmony_ci    }
594514f5e3Sopenharmony_ci    // 9. Let bufferByteLength be the value of buffer’s [[ArrayBufferByteLength]] internal slot.
604514f5e3Sopenharmony_ci    JSHandle<JSArrayBuffer> arrBufHandle(bufferHandle);
614514f5e3Sopenharmony_ci    uint32_t bufByteLen = arrBufHandle->GetArrayBufferByteLength();
624514f5e3Sopenharmony_ci    // 10. If offset > bufferByteLength, throw a RangeError exception.
634514f5e3Sopenharmony_ci    if (offset > bufByteLen) {
644514f5e3Sopenharmony_ci        THROW_RANGE_ERROR_AND_RETURN(thread, "offset > bufferByteLength", JSTaggedValue::Exception());
654514f5e3Sopenharmony_ci    }
664514f5e3Sopenharmony_ci    uint32_t viewByteLen = 0;
674514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> byteLenHandle = GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD);
684514f5e3Sopenharmony_ci    // 11. If byteLength is undefined, then Let viewByteLength be bufferByteLength – offset.
694514f5e3Sopenharmony_ci    if (byteLenHandle->IsUndefined()) {
704514f5e3Sopenharmony_ci        viewByteLen = bufByteLen - offset;
714514f5e3Sopenharmony_ci    } else {
724514f5e3Sopenharmony_ci        // Let viewByteLength be ToIndex(byteLength).
734514f5e3Sopenharmony_ci        JSTaggedNumber byteLen = JSTaggedValue::ToIndex(thread, byteLenHandle);
744514f5e3Sopenharmony_ci        // ReturnIfAbrupt(viewByteLength).
754514f5e3Sopenharmony_ci        RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
764514f5e3Sopenharmony_ci        viewByteLen = static_cast<uint32_t>(byteLen.ToInt32());
774514f5e3Sopenharmony_ci        // If offset+viewByteLength > bufferByteLength, throw a RangeError exception.
784514f5e3Sopenharmony_ci        if (offset + viewByteLen > bufByteLen) {
794514f5e3Sopenharmony_ci            THROW_RANGE_ERROR_AND_RETURN(thread, "offset + viewByteLen > bufByteLen", JSTaggedValue::Exception());
804514f5e3Sopenharmony_ci        }
814514f5e3Sopenharmony_ci    }
824514f5e3Sopenharmony_ci    // 13. Let O be OrdinaryCreateFromConstructor OrdinaryCreateFromConstructor(NewTarget, "%DataViewPrototype%",
834514f5e3Sopenharmony_ci    // «[[DataView]],[[ViewedArrayBuffer]], [[ByteLength]], [[ByteOffset]]» ).
844514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
854514f5e3Sopenharmony_ci    JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(ctor), newTarget);
864514f5e3Sopenharmony_ci    // 14. ReturnIfAbrupt(O).
874514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
884514f5e3Sopenharmony_ci    JSHandle<JSDataView> dataView(obj);
894514f5e3Sopenharmony_ci    // 15. Set O’s [[DataView]] internal slot to true.
904514f5e3Sopenharmony_ci    dataView->SetDataView(thread, JSTaggedValue::True());
914514f5e3Sopenharmony_ci    // 16. Set O’s [[ViewedArrayBuffer]] internal slot to buffer.
924514f5e3Sopenharmony_ci    dataView->SetViewedArrayBuffer(thread, bufferHandle.GetTaggedValue());
934514f5e3Sopenharmony_ci    // 17. Set O’s [[ByteLength]] internal slot to viewByteLength.
944514f5e3Sopenharmony_ci    dataView->SetByteLength(viewByteLen);
954514f5e3Sopenharmony_ci    // 18. Set O’s [[ByteOffset]] internal slot to offset.
964514f5e3Sopenharmony_ci    dataView->SetByteOffset(offset);
974514f5e3Sopenharmony_ci    // 19. Return O.
984514f5e3Sopenharmony_ci    return JSTaggedValue(dataView.GetTaggedValue());
994514f5e3Sopenharmony_ci}
1004514f5e3Sopenharmony_ci
1014514f5e3Sopenharmony_ci// 24.2.4.1
1024514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::GetBuffer(EcmaRuntimeCallInfo *argv)
1034514f5e3Sopenharmony_ci{
1044514f5e3Sopenharmony_ci    ASSERT(argv);
1054514f5e3Sopenharmony_ci    JSThread *thread = argv->GetThread();
1064514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, DataView, GetBuffer);
1074514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
1084514f5e3Sopenharmony_ci    // 1. Let O be the this value.
1094514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
1104514f5e3Sopenharmony_ci    // 2. f Type(O) is not Object, throw a TypeError exception.
1114514f5e3Sopenharmony_ci    if (!thisHandle->IsECMAObject()) {
1124514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "Type(O) is not Object", JSTaggedValue::Exception());
1134514f5e3Sopenharmony_ci    }
1144514f5e3Sopenharmony_ci    // 3. If O does not have a [[ViewedArrayBuffer]] internal slot, throw a TypeError exception.
1154514f5e3Sopenharmony_ci    if (!thisHandle->IsDataView()) {
1164514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "O does not have a [[ViewedArrayBuffer]]", JSTaggedValue::Exception());
1174514f5e3Sopenharmony_ci    }
1184514f5e3Sopenharmony_ci    JSHandle<JSDataView> dataView(thisHandle);
1194514f5e3Sopenharmony_ci    // 4. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot.
1204514f5e3Sopenharmony_ci    JSTaggedValue buffer = dataView->GetViewedArrayBuffer();
1214514f5e3Sopenharmony_ci    // 5. Return buffer.
1224514f5e3Sopenharmony_ci    return JSTaggedValue(buffer);
1234514f5e3Sopenharmony_ci}
1244514f5e3Sopenharmony_ci
1254514f5e3Sopenharmony_ci// 24.2.4.2
1264514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::GetByteLength(EcmaRuntimeCallInfo *argv)
1274514f5e3Sopenharmony_ci{
1284514f5e3Sopenharmony_ci    ASSERT(argv);
1294514f5e3Sopenharmony_ci    JSThread *thread = argv->GetThread();
1304514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, DataView, GetByteLength);
1314514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
1324514f5e3Sopenharmony_ci    // 1. Let O be the this value.
1334514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
1344514f5e3Sopenharmony_ci    // 2. If Type(O) is not Object, throw a TypeError exception.
1354514f5e3Sopenharmony_ci    if (!thisHandle->IsECMAObject()) {
1364514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "Type(O) is not Object", JSTaggedValue::Exception());
1374514f5e3Sopenharmony_ci    }
1384514f5e3Sopenharmony_ci    // 3. If O does not have a [[ViewedArrayBuffer]] internal slot, throw a TypeError exception.
1394514f5e3Sopenharmony_ci    if (!thisHandle->IsDataView()) {
1404514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "O does not have a [[ViewedArrayBuffer]]", JSTaggedValue::Exception());
1414514f5e3Sopenharmony_ci    }
1424514f5e3Sopenharmony_ci    JSHandle<JSDataView> dataView(thisHandle);
1434514f5e3Sopenharmony_ci    // 4. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot.
1444514f5e3Sopenharmony_ci    JSTaggedValue buffer = dataView->GetViewedArrayBuffer();
1454514f5e3Sopenharmony_ci    // 5. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
1464514f5e3Sopenharmony_ci    if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) {
1474514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer", JSTaggedValue::Exception());
1484514f5e3Sopenharmony_ci    }
1494514f5e3Sopenharmony_ci    // 6. Let size be the value of O’s [[ByteLength]] internal slot.
1504514f5e3Sopenharmony_ci    uint32_t size = dataView->GetByteLength();
1514514f5e3Sopenharmony_ci    // 7. Return size.
1524514f5e3Sopenharmony_ci    return JSTaggedValue(size);
1534514f5e3Sopenharmony_ci}
1544514f5e3Sopenharmony_ci
1554514f5e3Sopenharmony_ci// 24.2.4.3
1564514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::GetOffset(EcmaRuntimeCallInfo *argv)
1574514f5e3Sopenharmony_ci{
1584514f5e3Sopenharmony_ci    ASSERT(argv);
1594514f5e3Sopenharmony_ci    JSThread *thread = argv->GetThread();
1604514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, DataView, GetOffset);
1614514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
1624514f5e3Sopenharmony_ci    // 1. Let O be the this value.
1634514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
1644514f5e3Sopenharmony_ci    // 2. If Type(O) is not Object, throw a TypeError exception.
1654514f5e3Sopenharmony_ci    if (!thisHandle->IsECMAObject()) {
1664514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "Type(O) is not Object", JSTaggedValue::Exception());
1674514f5e3Sopenharmony_ci    }
1684514f5e3Sopenharmony_ci    // 3. If O does not have a [[ViewedArrayBuffer]] internal slot, throw a TypeError exception.
1694514f5e3Sopenharmony_ci    if (!thisHandle->IsDataView()) {
1704514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "O does not have a [[ViewedArrayBuffer]]", JSTaggedValue::Exception());
1714514f5e3Sopenharmony_ci    }
1724514f5e3Sopenharmony_ci    JSHandle<JSDataView> dataView(thisHandle);
1734514f5e3Sopenharmony_ci    // 4. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot.
1744514f5e3Sopenharmony_ci    JSTaggedValue buffer = dataView->GetViewedArrayBuffer();
1754514f5e3Sopenharmony_ci    // 5. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
1764514f5e3Sopenharmony_ci    if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) {
1774514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer", JSTaggedValue::Exception());
1784514f5e3Sopenharmony_ci    }
1794514f5e3Sopenharmony_ci    // 6. Let offset be the value of O’s [[ByteOffset]] internal slot.
1804514f5e3Sopenharmony_ci    uint32_t offset = dataView->GetByteOffset();
1814514f5e3Sopenharmony_ci    // 7. Return offset.
1824514f5e3Sopenharmony_ci    return JSTaggedValue(offset);
1834514f5e3Sopenharmony_ci}
1844514f5e3Sopenharmony_ci
1854514f5e3Sopenharmony_ci// 24.2.4.5
1864514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::GetFloat32(EcmaRuntimeCallInfo *argv)
1874514f5e3Sopenharmony_ci{
1884514f5e3Sopenharmony_ci    ASSERT(argv);
1894514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(argv->GetThread(), DataView, GetFloat32);
1904514f5e3Sopenharmony_ci    return GetTypedValue(argv, DataViewType::FLOAT32);
1914514f5e3Sopenharmony_ci}
1924514f5e3Sopenharmony_ci
1934514f5e3Sopenharmony_ci// 24.2.4.6
1944514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::GetFloat64(EcmaRuntimeCallInfo *argv)
1954514f5e3Sopenharmony_ci{
1964514f5e3Sopenharmony_ci    ASSERT(argv);
1974514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(argv->GetThread(), DataView, GetFloat64);
1984514f5e3Sopenharmony_ci    return GetTypedValue(argv, DataViewType::FLOAT64);
1994514f5e3Sopenharmony_ci}
2004514f5e3Sopenharmony_ci
2014514f5e3Sopenharmony_ci// 24.2.4.7
2024514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::GetInt8(EcmaRuntimeCallInfo *argv)
2034514f5e3Sopenharmony_ci{
2044514f5e3Sopenharmony_ci    ASSERT(argv);
2054514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(argv->GetThread(), DataView, GetInt8);
2064514f5e3Sopenharmony_ci    return GetTypedValue(argv, DataViewType::INT8);
2074514f5e3Sopenharmony_ci}
2084514f5e3Sopenharmony_ci
2094514f5e3Sopenharmony_ci// 24.2.4.8
2104514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::GetInt16(EcmaRuntimeCallInfo *argv)
2114514f5e3Sopenharmony_ci{
2124514f5e3Sopenharmony_ci    ASSERT(argv);
2134514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(argv->GetThread(), DataView, GetInt16);
2144514f5e3Sopenharmony_ci    return GetTypedValue(argv, DataViewType::INT16);
2154514f5e3Sopenharmony_ci}
2164514f5e3Sopenharmony_ci
2174514f5e3Sopenharmony_ci// 24.2.4.9
2184514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::GetInt32(EcmaRuntimeCallInfo *argv)
2194514f5e3Sopenharmony_ci{
2204514f5e3Sopenharmony_ci    ASSERT(argv);
2214514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(argv->GetThread(), DataView, GetInt32);
2224514f5e3Sopenharmony_ci    return GetTypedValue(argv, DataViewType::INT32);
2234514f5e3Sopenharmony_ci}
2244514f5e3Sopenharmony_ci
2254514f5e3Sopenharmony_ci// 24.2.4.10
2264514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::GetUint8(EcmaRuntimeCallInfo *argv)
2274514f5e3Sopenharmony_ci{
2284514f5e3Sopenharmony_ci    ASSERT(argv);
2294514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(argv->GetThread(), DataView, GetUint8);
2304514f5e3Sopenharmony_ci    return GetTypedValue(argv, DataViewType::UINT8);
2314514f5e3Sopenharmony_ci}
2324514f5e3Sopenharmony_ci
2334514f5e3Sopenharmony_ci// 24.2.4.11
2344514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::GetUint16(EcmaRuntimeCallInfo *argv)
2354514f5e3Sopenharmony_ci{
2364514f5e3Sopenharmony_ci    ASSERT(argv);
2374514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(argv->GetThread(), DataView, GetUint16);
2384514f5e3Sopenharmony_ci    return GetTypedValue(argv, DataViewType::UINT16);
2394514f5e3Sopenharmony_ci}
2404514f5e3Sopenharmony_ci
2414514f5e3Sopenharmony_ci// 24.2.4.12
2424514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::GetUint32(EcmaRuntimeCallInfo *argv)
2434514f5e3Sopenharmony_ci{
2444514f5e3Sopenharmony_ci    ASSERT(argv);
2454514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(argv->GetThread(), DataView, GetUint32);
2464514f5e3Sopenharmony_ci    return GetTypedValue(argv, DataViewType::UINT32);
2474514f5e3Sopenharmony_ci}
2484514f5e3Sopenharmony_ci// 25.3.4.5
2494514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::GetBigInt64(EcmaRuntimeCallInfo *argv)
2504514f5e3Sopenharmony_ci{
2514514f5e3Sopenharmony_ci    ASSERT(argv);
2524514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(argv->GetThread(), DataView, GetBigInt64);
2534514f5e3Sopenharmony_ci    return GetTypedValue(argv, DataViewType::BIGINT64);
2544514f5e3Sopenharmony_ci}
2554514f5e3Sopenharmony_ci// 25.3.4.6
2564514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::GetBigUint64(EcmaRuntimeCallInfo *argv)
2574514f5e3Sopenharmony_ci{
2584514f5e3Sopenharmony_ci    ASSERT(argv);
2594514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(argv->GetThread(), DataView, GetBigUint64);
2604514f5e3Sopenharmony_ci    return GetTypedValue(argv, DataViewType::BIGUINT64);
2614514f5e3Sopenharmony_ci}
2624514f5e3Sopenharmony_ci// 24.2.4.13
2634514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::SetFloat32(EcmaRuntimeCallInfo *argv)
2644514f5e3Sopenharmony_ci{
2654514f5e3Sopenharmony_ci    ASSERT(argv);
2664514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(argv->GetThread(), DataView, SetFloat32);
2674514f5e3Sopenharmony_ci    return SetTypedValue(argv, DataViewType::FLOAT32);
2684514f5e3Sopenharmony_ci}
2694514f5e3Sopenharmony_ci
2704514f5e3Sopenharmony_ci// 24.2.4.14
2714514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::SetFloat64(EcmaRuntimeCallInfo *argv)
2724514f5e3Sopenharmony_ci{
2734514f5e3Sopenharmony_ci    ASSERT(argv);
2744514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(argv->GetThread(), DataView, SetFloat64);
2754514f5e3Sopenharmony_ci    return SetTypedValue(argv, DataViewType::FLOAT64);
2764514f5e3Sopenharmony_ci}
2774514f5e3Sopenharmony_ci
2784514f5e3Sopenharmony_ci// 24.2.4.15
2794514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::SetInt8(EcmaRuntimeCallInfo *argv)
2804514f5e3Sopenharmony_ci{
2814514f5e3Sopenharmony_ci    ASSERT(argv);
2824514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(argv->GetThread(), DataView, SetInt8);
2834514f5e3Sopenharmony_ci    return SetTypedValue(argv, DataViewType::INT8);
2844514f5e3Sopenharmony_ci}
2854514f5e3Sopenharmony_ci
2864514f5e3Sopenharmony_ci// 24.2.4.16
2874514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::SetInt16(EcmaRuntimeCallInfo *argv)
2884514f5e3Sopenharmony_ci{
2894514f5e3Sopenharmony_ci    ASSERT(argv);
2904514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(argv->GetThread(), DataView, SetInt16);
2914514f5e3Sopenharmony_ci    return SetTypedValue(argv, DataViewType::INT16);
2924514f5e3Sopenharmony_ci}
2934514f5e3Sopenharmony_ci
2944514f5e3Sopenharmony_ci// 24.2.4.17
2954514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::SetInt32(EcmaRuntimeCallInfo *argv)
2964514f5e3Sopenharmony_ci{
2974514f5e3Sopenharmony_ci    ASSERT(argv);
2984514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(argv->GetThread(), DataView, SetInt32);
2994514f5e3Sopenharmony_ci    return SetTypedValue(argv, DataViewType::INT32);
3004514f5e3Sopenharmony_ci}
3014514f5e3Sopenharmony_ci
3024514f5e3Sopenharmony_ci// 24.2.4.18
3034514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::SetUint8(EcmaRuntimeCallInfo *argv)
3044514f5e3Sopenharmony_ci{
3054514f5e3Sopenharmony_ci    ASSERT(argv);
3064514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(argv->GetThread(), DataView, SetUint8);
3074514f5e3Sopenharmony_ci    return SetTypedValue(argv, DataViewType::UINT8);
3084514f5e3Sopenharmony_ci}
3094514f5e3Sopenharmony_ci
3104514f5e3Sopenharmony_ci// 24.2.4.19
3114514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::SetUint16(EcmaRuntimeCallInfo *argv)
3124514f5e3Sopenharmony_ci{
3134514f5e3Sopenharmony_ci    ASSERT(argv);
3144514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(argv->GetThread(), DataView, SetUint16);
3154514f5e3Sopenharmony_ci    return SetTypedValue(argv, DataViewType::UINT16);
3164514f5e3Sopenharmony_ci}
3174514f5e3Sopenharmony_ci
3184514f5e3Sopenharmony_ci// 24.2.4.20
3194514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::SetUint32(EcmaRuntimeCallInfo *argv)
3204514f5e3Sopenharmony_ci{
3214514f5e3Sopenharmony_ci    ASSERT(argv);
3224514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(argv->GetThread(), DataView, SetUint32);
3234514f5e3Sopenharmony_ci    return SetTypedValue(argv, DataViewType::UINT32);
3244514f5e3Sopenharmony_ci}
3254514f5e3Sopenharmony_ci
3264514f5e3Sopenharmony_ci// 25.3.4.15
3274514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::SetBigInt64(EcmaRuntimeCallInfo *argv)
3284514f5e3Sopenharmony_ci{
3294514f5e3Sopenharmony_ci    ASSERT(argv);
3304514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(argv->GetThread(), DataView, SetBigInt64);
3314514f5e3Sopenharmony_ci    return SetTypedValue(argv, DataViewType::BIGINT64);
3324514f5e3Sopenharmony_ci}
3334514f5e3Sopenharmony_ci
3344514f5e3Sopenharmony_ci// 25.3.4.16
3354514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::SetBigUint64(EcmaRuntimeCallInfo *argv)
3364514f5e3Sopenharmony_ci{
3374514f5e3Sopenharmony_ci    ASSERT(argv);
3384514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(argv->GetThread(), DataView, SetBigUint64);
3394514f5e3Sopenharmony_ci    return SetTypedValue(argv, DataViewType::BIGUINT64);
3404514f5e3Sopenharmony_ci}
3414514f5e3Sopenharmony_ci
3424514f5e3Sopenharmony_ci// 24.2.1.1
3434514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::GetViewValue(JSThread *thread, const JSHandle<JSTaggedValue> &view,
3444514f5e3Sopenharmony_ci                                             const JSHandle<JSTaggedValue> &requestIndex,
3454514f5e3Sopenharmony_ci                                             const JSHandle<JSTaggedValue> &littleEndian,
3464514f5e3Sopenharmony_ci                                             DataViewType type)
3474514f5e3Sopenharmony_ci{
3484514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, DataView, GetViewValue);
3494514f5e3Sopenharmony_ci    // 1. If Type(view) is not Object, throw a TypeError exception.
3504514f5e3Sopenharmony_ci    if (!view->IsECMAObject()) {
3514514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "Type(O) is not Object", JSTaggedValue::Exception());
3524514f5e3Sopenharmony_ci    }
3534514f5e3Sopenharmony_ci    // 2. If view does not have a [[DataView]] internal slot, throw a TypeError exception.
3544514f5e3Sopenharmony_ci    if (!view->IsDataView()) {
3554514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "view is not dataview", JSTaggedValue::Exception());
3564514f5e3Sopenharmony_ci    }
3574514f5e3Sopenharmony_ci
3584514f5e3Sopenharmony_ci    int32_t indexInt = 0;
3594514f5e3Sopenharmony_ci    if (requestIndex->IsInt()) {
3604514f5e3Sopenharmony_ci        // fast get index if requestIndex is int
3614514f5e3Sopenharmony_ci        indexInt = requestIndex->GetInt();
3624514f5e3Sopenharmony_ci    } else {
3634514f5e3Sopenharmony_ci        // 3. Let numberIndex be ToNumber(requestIndex).
3644514f5e3Sopenharmony_ci        JSTaggedNumber numberIndex = JSTaggedValue::ToNumber(thread, requestIndex);
3654514f5e3Sopenharmony_ci        // 5. ReturnIfAbrupt(getIndex).
3664514f5e3Sopenharmony_ci        RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
3674514f5e3Sopenharmony_ci        indexInt = base::NumberHelper::DoubleInRangeInt32(numberIndex.GetNumber());
3684514f5e3Sopenharmony_ci    }
3694514f5e3Sopenharmony_ci    // 6. If numberIndex ≠ getIndex or getIndex < 0, throw a RangeError exception.
3704514f5e3Sopenharmony_ci    if (indexInt < 0) {
3714514f5e3Sopenharmony_ci        THROW_RANGE_ERROR_AND_RETURN(thread, "getIndex < 0", JSTaggedValue::Exception());
3724514f5e3Sopenharmony_ci    }
3734514f5e3Sopenharmony_ci    uint32_t index = static_cast<uint32_t>(indexInt);
3744514f5e3Sopenharmony_ci    // 7. Let isLittleEndian be ToBoolean(isLittleEndian).
3754514f5e3Sopenharmony_ci    bool isLittleEndian = false;
3764514f5e3Sopenharmony_ci    if (littleEndian->IsUndefined()) {
3774514f5e3Sopenharmony_ci        isLittleEndian = false;
3784514f5e3Sopenharmony_ci    } else {
3794514f5e3Sopenharmony_ci        isLittleEndian = littleEndian->ToBoolean();
3804514f5e3Sopenharmony_ci    }
3814514f5e3Sopenharmony_ci    // 8. Let buffer be the value of view’s [[ViewedArrayBuffer]] internal slot.
3824514f5e3Sopenharmony_ci    JSHandle<JSDataView> dataView(view);
3834514f5e3Sopenharmony_ci    JSTaggedValue buffer = dataView->GetViewedArrayBuffer();
3844514f5e3Sopenharmony_ci    // 9. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
3854514f5e3Sopenharmony_ci    if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) {
3864514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer", JSTaggedValue::Exception());
3874514f5e3Sopenharmony_ci    }
3884514f5e3Sopenharmony_ci    // 10. Let viewOffset be the value of view’s [[ByteOffset]] internal slot.
3894514f5e3Sopenharmony_ci    uint32_t offset = dataView->GetByteOffset();
3904514f5e3Sopenharmony_ci    // 11. Let viewSize be the value of view’s [[ByteLength]] internal slot.
3914514f5e3Sopenharmony_ci    uint32_t size = dataView->GetByteLength();
3924514f5e3Sopenharmony_ci    // 12. Let elementSize be the Number value of the Element Size value specified in Table 49 for Element Type type.
3934514f5e3Sopenharmony_ci    uint32_t elementSize = JSDataView::GetElementSize(type);
3944514f5e3Sopenharmony_ci    // 13. If getIndex +elementSize > viewSize, throw a RangeError exception.
3954514f5e3Sopenharmony_ci    if (index + elementSize > size) {
3964514f5e3Sopenharmony_ci        THROW_RANGE_ERROR_AND_RETURN(thread, "getIndex +elementSize > viewSize", JSTaggedValue::Exception());
3974514f5e3Sopenharmony_ci    }
3984514f5e3Sopenharmony_ci    // 14. Let bufferIndex be getIndex + viewOffset.
3994514f5e3Sopenharmony_ci    uint32_t bufferIndex = index + offset;
4004514f5e3Sopenharmony_ci    // 15. Return GetValueFromBuffer(buffer, bufferIndex, type, isLittleEndian).
4014514f5e3Sopenharmony_ci    return BuiltinsArrayBuffer::GetValueFromBuffer(thread, buffer, bufferIndex, type, isLittleEndian);
4024514f5e3Sopenharmony_ci}
4034514f5e3Sopenharmony_ci
4044514f5e3Sopenharmony_ci// 24.2.1.2
4054514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::SetViewValue(JSThread *thread, const JSHandle<JSTaggedValue> &view,
4064514f5e3Sopenharmony_ci                                             const JSHandle<JSTaggedValue> &requestIndex,
4074514f5e3Sopenharmony_ci                                             const JSHandle<JSTaggedValue> &littleEndian,
4084514f5e3Sopenharmony_ci                                             DataViewType type, const JSHandle<JSTaggedValue> &value)
4094514f5e3Sopenharmony_ci{
4104514f5e3Sopenharmony_ci    // 1. If Type(view) is not Object, throw a TypeError exception.
4114514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, DataView, SetViewValue);
4124514f5e3Sopenharmony_ci    if (!view->IsECMAObject()) {
4134514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "Type(O) is not Object", JSTaggedValue::Exception());
4144514f5e3Sopenharmony_ci    }
4154514f5e3Sopenharmony_ci    // 2. If view does not have a [[DataView]] internal slot, throw a TypeError exception.
4164514f5e3Sopenharmony_ci    if (!view->IsDataView()) {
4174514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "view is not dataview", JSTaggedValue::Exception());
4184514f5e3Sopenharmony_ci    }
4194514f5e3Sopenharmony_ci    int64_t index = 0;
4204514f5e3Sopenharmony_ci    if (requestIndex->IsInt()) {
4214514f5e3Sopenharmony_ci        // fast get index if requestIndex is int
4224514f5e3Sopenharmony_ci        index = requestIndex->GetInt();
4234514f5e3Sopenharmony_ci    } else {
4244514f5e3Sopenharmony_ci        // 3. Let numberIndex be ToNumber(requestIndex).
4254514f5e3Sopenharmony_ci        JSTaggedNumber numberIndex = JSTaggedValue::ToIndex(thread, requestIndex);
4264514f5e3Sopenharmony_ci        // 5. ReturnIfAbrupt(getIndex).
4274514f5e3Sopenharmony_ci        RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
4284514f5e3Sopenharmony_ci        index = base::NumberHelper::DoubleInRangeInt32(numberIndex.GetNumber());
4294514f5e3Sopenharmony_ci    }
4304514f5e3Sopenharmony_ci    // 6. If numberIndex ≠ getIndex or getIndex < 0, throw a RangeError exception.
4314514f5e3Sopenharmony_ci    if (index < 0) {
4324514f5e3Sopenharmony_ci        THROW_RANGE_ERROR_AND_RETURN(thread, "getIndex < 0", JSTaggedValue::Exception());
4334514f5e3Sopenharmony_ci    }
4344514f5e3Sopenharmony_ci    JSMutableHandle<JSTaggedValue> numValueHandle = JSMutableHandle<JSTaggedValue>(thread, value);
4354514f5e3Sopenharmony_ci    if (!value->IsNumber()) {
4364514f5e3Sopenharmony_ci        numValueHandle.Update(JSTaggedValue::ToNumeric(thread, value));
4374514f5e3Sopenharmony_ci        RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
4384514f5e3Sopenharmony_ci    }
4394514f5e3Sopenharmony_ci    // 7. Let isLittleEndian be ToBoolean(isLittleEndian).
4404514f5e3Sopenharmony_ci    bool isLittleEndian = false;
4414514f5e3Sopenharmony_ci    if (littleEndian->IsUndefined()) {
4424514f5e3Sopenharmony_ci        isLittleEndian = false;
4434514f5e3Sopenharmony_ci    } else {
4444514f5e3Sopenharmony_ci        isLittleEndian = littleEndian->ToBoolean();
4454514f5e3Sopenharmony_ci    }
4464514f5e3Sopenharmony_ci    // 8. Let buffer be the value of view’s [[ViewedArrayBuffer]] internal slot.
4474514f5e3Sopenharmony_ci    JSHandle<JSDataView> dataView(view);
4484514f5e3Sopenharmony_ci    JSTaggedValue buffer = dataView->GetViewedArrayBuffer();
4494514f5e3Sopenharmony_ci    // 9. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
4504514f5e3Sopenharmony_ci    if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) {
4514514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer", JSTaggedValue::Exception());
4524514f5e3Sopenharmony_ci    }
4534514f5e3Sopenharmony_ci    // 10. Let viewOffset be the value of view’s [[ByteOffset]] internal slot.
4544514f5e3Sopenharmony_ci    uint32_t offset = dataView->GetByteOffset();
4554514f5e3Sopenharmony_ci    // 11. Let viewSize be the value of view’s [[ByteLength]] internal slot.
4564514f5e3Sopenharmony_ci    uint32_t size = dataView->GetByteLength();
4574514f5e3Sopenharmony_ci    // 12. Let elementSize be the Number value of the Element Size value specified in Table 49 for Element Type type.
4584514f5e3Sopenharmony_ci    uint32_t elementSize = JSDataView::GetElementSize(type);
4594514f5e3Sopenharmony_ci    // 13. If getIndex +elementSize > viewSize, throw a RangeError exception.
4604514f5e3Sopenharmony_ci    if (static_cast<uint32_t>(index) + elementSize > size) {
4614514f5e3Sopenharmony_ci        THROW_RANGE_ERROR_AND_RETURN(thread, "getIndex +elementSize > viewSize", JSTaggedValue::Exception());
4624514f5e3Sopenharmony_ci    }
4634514f5e3Sopenharmony_ci    // 14. Let bufferIndex be getIndex + viewOffset.
4644514f5e3Sopenharmony_ci    uint32_t bufferIndex = static_cast<uint32_t>(index) + offset;
4654514f5e3Sopenharmony_ci    // 15. Return SetValueFromBuffer(buffer, bufferIndex, type, value, isLittleEndian).
4664514f5e3Sopenharmony_ci    return BuiltinsArrayBuffer::SetValueInBuffer(thread, buffer, bufferIndex, type, numValueHandle, isLittleEndian);
4674514f5e3Sopenharmony_ci}
4684514f5e3Sopenharmony_ci
4694514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::GetTypedValue(EcmaRuntimeCallInfo *argv, DataViewType type)
4704514f5e3Sopenharmony_ci{
4714514f5e3Sopenharmony_ci    JSThread *thread = argv->GetThread();
4724514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, DataView, GetTypedValue);
4734514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
4744514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
4754514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> offsetHandle = GetCallArg(argv, 0);
4764514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> trueHandle(thread, JSTaggedValue::True());
4774514f5e3Sopenharmony_ci    if (type == DataViewType::UINT8 || type == DataViewType::INT8) {
4784514f5e3Sopenharmony_ci        return GetViewValue(thread, thisHandle, offsetHandle, trueHandle, type);
4794514f5e3Sopenharmony_ci    }
4804514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> littleEndianHandle = GetCallArg(argv, 1);
4814514f5e3Sopenharmony_ci    return GetViewValue(thread, thisHandle, offsetHandle, littleEndianHandle, type);
4824514f5e3Sopenharmony_ci}
4834514f5e3Sopenharmony_ci
4844514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDataView::SetTypedValue(EcmaRuntimeCallInfo *argv, DataViewType type)
4854514f5e3Sopenharmony_ci{
4864514f5e3Sopenharmony_ci    JSThread *thread = argv->GetThread();
4874514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, DataView, SetTypedValue);
4884514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
4894514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
4904514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> offsetHandle = GetCallArg(argv, 0);
4914514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> value = GetCallArg(argv, 1);
4924514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> trueHandle(thread, JSTaggedValue::True());
4934514f5e3Sopenharmony_ci    if (type == DataViewType::UINT8 || type == DataViewType::INT8) {
4944514f5e3Sopenharmony_ci        return SetViewValue(thread, thisHandle, offsetHandle, trueHandle, type, value);
4954514f5e3Sopenharmony_ci    }
4964514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> littleEndianHandle = GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD);
4974514f5e3Sopenharmony_ci    return SetViewValue(thread, thisHandle, offsetHandle, littleEndianHandle, type, value);
4984514f5e3Sopenharmony_ci}
4994514f5e3Sopenharmony_ci}  // namespace panda::ecmascript::builtins
500