1/*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "ecmascript/builtins/builtins_dataview.h"
17#include "ecmascript/builtins/builtins_arraybuffer.h"
18#include "ecmascript/js_arraybuffer.h"
19#include "ecmascript/js_tagged_value-inl.h"
20
21namespace panda::ecmascript::builtins {
22// 24.2.2.1
23JSTaggedValue BuiltinsDataView::DataViewConstructor(EcmaRuntimeCallInfo *argv)
24{
25    ASSERT(argv);
26    JSThread *thread = argv->GetThread();
27    BUILTINS_API_TRACE(thread, DataView, Constructor);
28    [[maybe_unused]] EcmaHandleScope handleScope(thread);
29    JSHandle<JSTaggedValue> ctor = GetConstructor(argv);
30    JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv);
31    // 1. If NewTarget is undefined, throw a TypeError exception.
32    if (newTarget->IsUndefined()) {
33        THROW_TYPE_ERROR_AND_RETURN(thread, "newtarget is undefined", JSTaggedValue::Exception());
34    }
35    JSHandle<JSTaggedValue> bufferHandle = GetCallArg(argv, 0);
36    // 2. If Type(buffer) is not Object, throw a TypeError exception.
37    if (!bufferHandle->IsECMAObject()) {
38        THROW_TYPE_ERROR_AND_RETURN(thread, "buffer is not Object", JSTaggedValue::Exception());
39    }
40    // 3. If buffer does not have an [[ArrayBufferData]] internal slot, throw a TypeError exception.
41    if (!bufferHandle->IsArrayBuffer() && !bufferHandle->IsSharedArrayBuffer()) {
42        THROW_TYPE_ERROR_AND_RETURN(thread, "buffer is not ArrayBuffer", JSTaggedValue::Exception());
43    }
44    JSHandle<JSTaggedValue> offsetHandle = GetCallArg(argv, 1);
45    // 4. Let numberOffset be ToNumber(byteOffset).
46    JSTaggedNumber offsetNumber = JSTaggedValue::ToNumber(thread, offsetHandle);
47    // 6. ReturnIfAbrupt(offset).
48    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
49    int32_t offsetInt = base::NumberHelper::DoubleInRangeInt32(offsetNumber.GetNumber());
50    // 7. If numberOffset ≠ offset or offset < 0, throw a RangeError exception.
51    if (offsetInt < 0) {
52        THROW_RANGE_ERROR_AND_RETURN(thread, "Offset out of range", JSTaggedValue::Exception());
53    }
54    uint32_t offset = static_cast<uint32_t>(offsetInt);
55    // 8. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
56    if (BuiltinsArrayBuffer::IsDetachedBuffer(bufferHandle.GetTaggedValue())) {
57        THROW_TYPE_ERROR_AND_RETURN(thread, "buffer is Detached Buffer", JSTaggedValue::Exception());
58    }
59    // 9. Let bufferByteLength be the value of buffer’s [[ArrayBufferByteLength]] internal slot.
60    JSHandle<JSArrayBuffer> arrBufHandle(bufferHandle);
61    uint32_t bufByteLen = arrBufHandle->GetArrayBufferByteLength();
62    // 10. If offset > bufferByteLength, throw a RangeError exception.
63    if (offset > bufByteLen) {
64        THROW_RANGE_ERROR_AND_RETURN(thread, "offset > bufferByteLength", JSTaggedValue::Exception());
65    }
66    uint32_t viewByteLen = 0;
67    JSHandle<JSTaggedValue> byteLenHandle = GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD);
68    // 11. If byteLength is undefined, then Let viewByteLength be bufferByteLength – offset.
69    if (byteLenHandle->IsUndefined()) {
70        viewByteLen = bufByteLen - offset;
71    } else {
72        // Let viewByteLength be ToIndex(byteLength).
73        JSTaggedNumber byteLen = JSTaggedValue::ToIndex(thread, byteLenHandle);
74        // ReturnIfAbrupt(viewByteLength).
75        RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
76        viewByteLen = static_cast<uint32_t>(byteLen.ToInt32());
77        // If offset+viewByteLength > bufferByteLength, throw a RangeError exception.
78        if (offset + viewByteLen > bufByteLen) {
79            THROW_RANGE_ERROR_AND_RETURN(thread, "offset + viewByteLen > bufByteLen", JSTaggedValue::Exception());
80        }
81    }
82    // 13. Let O be OrdinaryCreateFromConstructor OrdinaryCreateFromConstructor(NewTarget, "%DataViewPrototype%",
83    // «[[DataView]],[[ViewedArrayBuffer]], [[ByteLength]], [[ByteOffset]]» ).
84    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
85    JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(ctor), newTarget);
86    // 14. ReturnIfAbrupt(O).
87    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
88    JSHandle<JSDataView> dataView(obj);
89    // 15. Set O’s [[DataView]] internal slot to true.
90    dataView->SetDataView(thread, JSTaggedValue::True());
91    // 16. Set O’s [[ViewedArrayBuffer]] internal slot to buffer.
92    dataView->SetViewedArrayBuffer(thread, bufferHandle.GetTaggedValue());
93    // 17. Set O’s [[ByteLength]] internal slot to viewByteLength.
94    dataView->SetByteLength(viewByteLen);
95    // 18. Set O’s [[ByteOffset]] internal slot to offset.
96    dataView->SetByteOffset(offset);
97    // 19. Return O.
98    return JSTaggedValue(dataView.GetTaggedValue());
99}
100
101// 24.2.4.1
102JSTaggedValue BuiltinsDataView::GetBuffer(EcmaRuntimeCallInfo *argv)
103{
104    ASSERT(argv);
105    JSThread *thread = argv->GetThread();
106    BUILTINS_API_TRACE(thread, DataView, GetBuffer);
107    [[maybe_unused]] EcmaHandleScope handleScope(thread);
108    // 1. Let O be the this value.
109    JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
110    // 2. f Type(O) is not Object, throw a TypeError exception.
111    if (!thisHandle->IsECMAObject()) {
112        THROW_TYPE_ERROR_AND_RETURN(thread, "Type(O) is not Object", JSTaggedValue::Exception());
113    }
114    // 3. If O does not have a [[ViewedArrayBuffer]] internal slot, throw a TypeError exception.
115    if (!thisHandle->IsDataView()) {
116        THROW_TYPE_ERROR_AND_RETURN(thread, "O does not have a [[ViewedArrayBuffer]]", JSTaggedValue::Exception());
117    }
118    JSHandle<JSDataView> dataView(thisHandle);
119    // 4. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot.
120    JSTaggedValue buffer = dataView->GetViewedArrayBuffer();
121    // 5. Return buffer.
122    return JSTaggedValue(buffer);
123}
124
125// 24.2.4.2
126JSTaggedValue BuiltinsDataView::GetByteLength(EcmaRuntimeCallInfo *argv)
127{
128    ASSERT(argv);
129    JSThread *thread = argv->GetThread();
130    BUILTINS_API_TRACE(thread, DataView, GetByteLength);
131    [[maybe_unused]] EcmaHandleScope handleScope(thread);
132    // 1. Let O be the this value.
133    JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
134    // 2. If Type(O) is not Object, throw a TypeError exception.
135    if (!thisHandle->IsECMAObject()) {
136        THROW_TYPE_ERROR_AND_RETURN(thread, "Type(O) is not Object", JSTaggedValue::Exception());
137    }
138    // 3. If O does not have a [[ViewedArrayBuffer]] internal slot, throw a TypeError exception.
139    if (!thisHandle->IsDataView()) {
140        THROW_TYPE_ERROR_AND_RETURN(thread, "O does not have a [[ViewedArrayBuffer]]", JSTaggedValue::Exception());
141    }
142    JSHandle<JSDataView> dataView(thisHandle);
143    // 4. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot.
144    JSTaggedValue buffer = dataView->GetViewedArrayBuffer();
145    // 5. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
146    if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) {
147        THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer", JSTaggedValue::Exception());
148    }
149    // 6. Let size be the value of O’s [[ByteLength]] internal slot.
150    uint32_t size = dataView->GetByteLength();
151    // 7. Return size.
152    return JSTaggedValue(size);
153}
154
155// 24.2.4.3
156JSTaggedValue BuiltinsDataView::GetOffset(EcmaRuntimeCallInfo *argv)
157{
158    ASSERT(argv);
159    JSThread *thread = argv->GetThread();
160    BUILTINS_API_TRACE(thread, DataView, GetOffset);
161    [[maybe_unused]] EcmaHandleScope handleScope(thread);
162    // 1. Let O be the this value.
163    JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
164    // 2. If Type(O) is not Object, throw a TypeError exception.
165    if (!thisHandle->IsECMAObject()) {
166        THROW_TYPE_ERROR_AND_RETURN(thread, "Type(O) is not Object", JSTaggedValue::Exception());
167    }
168    // 3. If O does not have a [[ViewedArrayBuffer]] internal slot, throw a TypeError exception.
169    if (!thisHandle->IsDataView()) {
170        THROW_TYPE_ERROR_AND_RETURN(thread, "O does not have a [[ViewedArrayBuffer]]", JSTaggedValue::Exception());
171    }
172    JSHandle<JSDataView> dataView(thisHandle);
173    // 4. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot.
174    JSTaggedValue buffer = dataView->GetViewedArrayBuffer();
175    // 5. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
176    if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) {
177        THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer", JSTaggedValue::Exception());
178    }
179    // 6. Let offset be the value of O’s [[ByteOffset]] internal slot.
180    uint32_t offset = dataView->GetByteOffset();
181    // 7. Return offset.
182    return JSTaggedValue(offset);
183}
184
185// 24.2.4.5
186JSTaggedValue BuiltinsDataView::GetFloat32(EcmaRuntimeCallInfo *argv)
187{
188    ASSERT(argv);
189    BUILTINS_API_TRACE(argv->GetThread(), DataView, GetFloat32);
190    return GetTypedValue(argv, DataViewType::FLOAT32);
191}
192
193// 24.2.4.6
194JSTaggedValue BuiltinsDataView::GetFloat64(EcmaRuntimeCallInfo *argv)
195{
196    ASSERT(argv);
197    BUILTINS_API_TRACE(argv->GetThread(), DataView, GetFloat64);
198    return GetTypedValue(argv, DataViewType::FLOAT64);
199}
200
201// 24.2.4.7
202JSTaggedValue BuiltinsDataView::GetInt8(EcmaRuntimeCallInfo *argv)
203{
204    ASSERT(argv);
205    BUILTINS_API_TRACE(argv->GetThread(), DataView, GetInt8);
206    return GetTypedValue(argv, DataViewType::INT8);
207}
208
209// 24.2.4.8
210JSTaggedValue BuiltinsDataView::GetInt16(EcmaRuntimeCallInfo *argv)
211{
212    ASSERT(argv);
213    BUILTINS_API_TRACE(argv->GetThread(), DataView, GetInt16);
214    return GetTypedValue(argv, DataViewType::INT16);
215}
216
217// 24.2.4.9
218JSTaggedValue BuiltinsDataView::GetInt32(EcmaRuntimeCallInfo *argv)
219{
220    ASSERT(argv);
221    BUILTINS_API_TRACE(argv->GetThread(), DataView, GetInt32);
222    return GetTypedValue(argv, DataViewType::INT32);
223}
224
225// 24.2.4.10
226JSTaggedValue BuiltinsDataView::GetUint8(EcmaRuntimeCallInfo *argv)
227{
228    ASSERT(argv);
229    BUILTINS_API_TRACE(argv->GetThread(), DataView, GetUint8);
230    return GetTypedValue(argv, DataViewType::UINT8);
231}
232
233// 24.2.4.11
234JSTaggedValue BuiltinsDataView::GetUint16(EcmaRuntimeCallInfo *argv)
235{
236    ASSERT(argv);
237    BUILTINS_API_TRACE(argv->GetThread(), DataView, GetUint16);
238    return GetTypedValue(argv, DataViewType::UINT16);
239}
240
241// 24.2.4.12
242JSTaggedValue BuiltinsDataView::GetUint32(EcmaRuntimeCallInfo *argv)
243{
244    ASSERT(argv);
245    BUILTINS_API_TRACE(argv->GetThread(), DataView, GetUint32);
246    return GetTypedValue(argv, DataViewType::UINT32);
247}
248// 25.3.4.5
249JSTaggedValue BuiltinsDataView::GetBigInt64(EcmaRuntimeCallInfo *argv)
250{
251    ASSERT(argv);
252    BUILTINS_API_TRACE(argv->GetThread(), DataView, GetBigInt64);
253    return GetTypedValue(argv, DataViewType::BIGINT64);
254}
255// 25.3.4.6
256JSTaggedValue BuiltinsDataView::GetBigUint64(EcmaRuntimeCallInfo *argv)
257{
258    ASSERT(argv);
259    BUILTINS_API_TRACE(argv->GetThread(), DataView, GetBigUint64);
260    return GetTypedValue(argv, DataViewType::BIGUINT64);
261}
262// 24.2.4.13
263JSTaggedValue BuiltinsDataView::SetFloat32(EcmaRuntimeCallInfo *argv)
264{
265    ASSERT(argv);
266    BUILTINS_API_TRACE(argv->GetThread(), DataView, SetFloat32);
267    return SetTypedValue(argv, DataViewType::FLOAT32);
268}
269
270// 24.2.4.14
271JSTaggedValue BuiltinsDataView::SetFloat64(EcmaRuntimeCallInfo *argv)
272{
273    ASSERT(argv);
274    BUILTINS_API_TRACE(argv->GetThread(), DataView, SetFloat64);
275    return SetTypedValue(argv, DataViewType::FLOAT64);
276}
277
278// 24.2.4.15
279JSTaggedValue BuiltinsDataView::SetInt8(EcmaRuntimeCallInfo *argv)
280{
281    ASSERT(argv);
282    BUILTINS_API_TRACE(argv->GetThread(), DataView, SetInt8);
283    return SetTypedValue(argv, DataViewType::INT8);
284}
285
286// 24.2.4.16
287JSTaggedValue BuiltinsDataView::SetInt16(EcmaRuntimeCallInfo *argv)
288{
289    ASSERT(argv);
290    BUILTINS_API_TRACE(argv->GetThread(), DataView, SetInt16);
291    return SetTypedValue(argv, DataViewType::INT16);
292}
293
294// 24.2.4.17
295JSTaggedValue BuiltinsDataView::SetInt32(EcmaRuntimeCallInfo *argv)
296{
297    ASSERT(argv);
298    BUILTINS_API_TRACE(argv->GetThread(), DataView, SetInt32);
299    return SetTypedValue(argv, DataViewType::INT32);
300}
301
302// 24.2.4.18
303JSTaggedValue BuiltinsDataView::SetUint8(EcmaRuntimeCallInfo *argv)
304{
305    ASSERT(argv);
306    BUILTINS_API_TRACE(argv->GetThread(), DataView, SetUint8);
307    return SetTypedValue(argv, DataViewType::UINT8);
308}
309
310// 24.2.4.19
311JSTaggedValue BuiltinsDataView::SetUint16(EcmaRuntimeCallInfo *argv)
312{
313    ASSERT(argv);
314    BUILTINS_API_TRACE(argv->GetThread(), DataView, SetUint16);
315    return SetTypedValue(argv, DataViewType::UINT16);
316}
317
318// 24.2.4.20
319JSTaggedValue BuiltinsDataView::SetUint32(EcmaRuntimeCallInfo *argv)
320{
321    ASSERT(argv);
322    BUILTINS_API_TRACE(argv->GetThread(), DataView, SetUint32);
323    return SetTypedValue(argv, DataViewType::UINT32);
324}
325
326// 25.3.4.15
327JSTaggedValue BuiltinsDataView::SetBigInt64(EcmaRuntimeCallInfo *argv)
328{
329    ASSERT(argv);
330    BUILTINS_API_TRACE(argv->GetThread(), DataView, SetBigInt64);
331    return SetTypedValue(argv, DataViewType::BIGINT64);
332}
333
334// 25.3.4.16
335JSTaggedValue BuiltinsDataView::SetBigUint64(EcmaRuntimeCallInfo *argv)
336{
337    ASSERT(argv);
338    BUILTINS_API_TRACE(argv->GetThread(), DataView, SetBigUint64);
339    return SetTypedValue(argv, DataViewType::BIGUINT64);
340}
341
342// 24.2.1.1
343JSTaggedValue BuiltinsDataView::GetViewValue(JSThread *thread, const JSHandle<JSTaggedValue> &view,
344                                             const JSHandle<JSTaggedValue> &requestIndex,
345                                             const JSHandle<JSTaggedValue> &littleEndian,
346                                             DataViewType type)
347{
348    BUILTINS_API_TRACE(thread, DataView, GetViewValue);
349    // 1. If Type(view) is not Object, throw a TypeError exception.
350    if (!view->IsECMAObject()) {
351        THROW_TYPE_ERROR_AND_RETURN(thread, "Type(O) is not Object", JSTaggedValue::Exception());
352    }
353    // 2. If view does not have a [[DataView]] internal slot, throw a TypeError exception.
354    if (!view->IsDataView()) {
355        THROW_TYPE_ERROR_AND_RETURN(thread, "view is not dataview", JSTaggedValue::Exception());
356    }
357
358    int32_t indexInt = 0;
359    if (requestIndex->IsInt()) {
360        // fast get index if requestIndex is int
361        indexInt = requestIndex->GetInt();
362    } else {
363        // 3. Let numberIndex be ToNumber(requestIndex).
364        JSTaggedNumber numberIndex = JSTaggedValue::ToNumber(thread, requestIndex);
365        // 5. ReturnIfAbrupt(getIndex).
366        RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
367        indexInt = base::NumberHelper::DoubleInRangeInt32(numberIndex.GetNumber());
368    }
369    // 6. If numberIndex ≠ getIndex or getIndex < 0, throw a RangeError exception.
370    if (indexInt < 0) {
371        THROW_RANGE_ERROR_AND_RETURN(thread, "getIndex < 0", JSTaggedValue::Exception());
372    }
373    uint32_t index = static_cast<uint32_t>(indexInt);
374    // 7. Let isLittleEndian be ToBoolean(isLittleEndian).
375    bool isLittleEndian = false;
376    if (littleEndian->IsUndefined()) {
377        isLittleEndian = false;
378    } else {
379        isLittleEndian = littleEndian->ToBoolean();
380    }
381    // 8. Let buffer be the value of view’s [[ViewedArrayBuffer]] internal slot.
382    JSHandle<JSDataView> dataView(view);
383    JSTaggedValue buffer = dataView->GetViewedArrayBuffer();
384    // 9. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
385    if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) {
386        THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer", JSTaggedValue::Exception());
387    }
388    // 10. Let viewOffset be the value of view’s [[ByteOffset]] internal slot.
389    uint32_t offset = dataView->GetByteOffset();
390    // 11. Let viewSize be the value of view’s [[ByteLength]] internal slot.
391    uint32_t size = dataView->GetByteLength();
392    // 12. Let elementSize be the Number value of the Element Size value specified in Table 49 for Element Type type.
393    uint32_t elementSize = JSDataView::GetElementSize(type);
394    // 13. If getIndex +elementSize > viewSize, throw a RangeError exception.
395    if (index + elementSize > size) {
396        THROW_RANGE_ERROR_AND_RETURN(thread, "getIndex +elementSize > viewSize", JSTaggedValue::Exception());
397    }
398    // 14. Let bufferIndex be getIndex + viewOffset.
399    uint32_t bufferIndex = index + offset;
400    // 15. Return GetValueFromBuffer(buffer, bufferIndex, type, isLittleEndian).
401    return BuiltinsArrayBuffer::GetValueFromBuffer(thread, buffer, bufferIndex, type, isLittleEndian);
402}
403
404// 24.2.1.2
405JSTaggedValue BuiltinsDataView::SetViewValue(JSThread *thread, const JSHandle<JSTaggedValue> &view,
406                                             const JSHandle<JSTaggedValue> &requestIndex,
407                                             const JSHandle<JSTaggedValue> &littleEndian,
408                                             DataViewType type, const JSHandle<JSTaggedValue> &value)
409{
410    // 1. If Type(view) is not Object, throw a TypeError exception.
411    BUILTINS_API_TRACE(thread, DataView, SetViewValue);
412    if (!view->IsECMAObject()) {
413        THROW_TYPE_ERROR_AND_RETURN(thread, "Type(O) is not Object", JSTaggedValue::Exception());
414    }
415    // 2. If view does not have a [[DataView]] internal slot, throw a TypeError exception.
416    if (!view->IsDataView()) {
417        THROW_TYPE_ERROR_AND_RETURN(thread, "view is not dataview", JSTaggedValue::Exception());
418    }
419    int64_t index = 0;
420    if (requestIndex->IsInt()) {
421        // fast get index if requestIndex is int
422        index = requestIndex->GetInt();
423    } else {
424        // 3. Let numberIndex be ToNumber(requestIndex).
425        JSTaggedNumber numberIndex = JSTaggedValue::ToIndex(thread, requestIndex);
426        // 5. ReturnIfAbrupt(getIndex).
427        RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
428        index = base::NumberHelper::DoubleInRangeInt32(numberIndex.GetNumber());
429    }
430    // 6. If numberIndex ≠ getIndex or getIndex < 0, throw a RangeError exception.
431    if (index < 0) {
432        THROW_RANGE_ERROR_AND_RETURN(thread, "getIndex < 0", JSTaggedValue::Exception());
433    }
434    JSMutableHandle<JSTaggedValue> numValueHandle = JSMutableHandle<JSTaggedValue>(thread, value);
435    if (!value->IsNumber()) {
436        numValueHandle.Update(JSTaggedValue::ToNumeric(thread, value));
437        RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
438    }
439    // 7. Let isLittleEndian be ToBoolean(isLittleEndian).
440    bool isLittleEndian = false;
441    if (littleEndian->IsUndefined()) {
442        isLittleEndian = false;
443    } else {
444        isLittleEndian = littleEndian->ToBoolean();
445    }
446    // 8. Let buffer be the value of view’s [[ViewedArrayBuffer]] internal slot.
447    JSHandle<JSDataView> dataView(view);
448    JSTaggedValue buffer = dataView->GetViewedArrayBuffer();
449    // 9. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
450    if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) {
451        THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer", JSTaggedValue::Exception());
452    }
453    // 10. Let viewOffset be the value of view’s [[ByteOffset]] internal slot.
454    uint32_t offset = dataView->GetByteOffset();
455    // 11. Let viewSize be the value of view’s [[ByteLength]] internal slot.
456    uint32_t size = dataView->GetByteLength();
457    // 12. Let elementSize be the Number value of the Element Size value specified in Table 49 for Element Type type.
458    uint32_t elementSize = JSDataView::GetElementSize(type);
459    // 13. If getIndex +elementSize > viewSize, throw a RangeError exception.
460    if (static_cast<uint32_t>(index) + elementSize > size) {
461        THROW_RANGE_ERROR_AND_RETURN(thread, "getIndex +elementSize > viewSize", JSTaggedValue::Exception());
462    }
463    // 14. Let bufferIndex be getIndex + viewOffset.
464    uint32_t bufferIndex = static_cast<uint32_t>(index) + offset;
465    // 15. Return SetValueFromBuffer(buffer, bufferIndex, type, value, isLittleEndian).
466    return BuiltinsArrayBuffer::SetValueInBuffer(thread, buffer, bufferIndex, type, numValueHandle, isLittleEndian);
467}
468
469JSTaggedValue BuiltinsDataView::GetTypedValue(EcmaRuntimeCallInfo *argv, DataViewType type)
470{
471    JSThread *thread = argv->GetThread();
472    BUILTINS_API_TRACE(thread, DataView, GetTypedValue);
473    [[maybe_unused]] EcmaHandleScope handleScope(thread);
474    JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
475    JSHandle<JSTaggedValue> offsetHandle = GetCallArg(argv, 0);
476    JSHandle<JSTaggedValue> trueHandle(thread, JSTaggedValue::True());
477    if (type == DataViewType::UINT8 || type == DataViewType::INT8) {
478        return GetViewValue(thread, thisHandle, offsetHandle, trueHandle, type);
479    }
480    JSHandle<JSTaggedValue> littleEndianHandle = GetCallArg(argv, 1);
481    return GetViewValue(thread, thisHandle, offsetHandle, littleEndianHandle, type);
482}
483
484JSTaggedValue BuiltinsDataView::SetTypedValue(EcmaRuntimeCallInfo *argv, DataViewType type)
485{
486    JSThread *thread = argv->GetThread();
487    BUILTINS_API_TRACE(thread, DataView, SetTypedValue);
488    [[maybe_unused]] EcmaHandleScope handleScope(thread);
489    JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
490    JSHandle<JSTaggedValue> offsetHandle = GetCallArg(argv, 0);
491    JSHandle<JSTaggedValue> value = GetCallArg(argv, 1);
492    JSHandle<JSTaggedValue> trueHandle(thread, JSTaggedValue::True());
493    if (type == DataViewType::UINT8 || type == DataViewType::INT8) {
494        return SetViewValue(thread, thisHandle, offsetHandle, trueHandle, type, value);
495    }
496    JSHandle<JSTaggedValue> littleEndianHandle = GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD);
497    return SetViewValue(thread, thisHandle, offsetHandle, littleEndianHandle, type, value);
498}
499}  // namespace panda::ecmascript::builtins
500