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