• 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 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
GetBuffer(EcmaRuntimeCallInfo * argv)102 JSTaggedValue 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
GetByteLength(EcmaRuntimeCallInfo * argv)126 JSTaggedValue 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
GetOffset(EcmaRuntimeCallInfo * argv)156 JSTaggedValue 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
GetFloat32(EcmaRuntimeCallInfo * argv)186 JSTaggedValue 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
GetFloat64(EcmaRuntimeCallInfo * argv)194 JSTaggedValue 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
GetInt8(EcmaRuntimeCallInfo * argv)202 JSTaggedValue 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
GetInt16(EcmaRuntimeCallInfo * argv)210 JSTaggedValue 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
GetInt32(EcmaRuntimeCallInfo * argv)218 JSTaggedValue 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
GetUint8(EcmaRuntimeCallInfo * argv)226 JSTaggedValue 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
GetUint16(EcmaRuntimeCallInfo * argv)234 JSTaggedValue 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
GetUint32(EcmaRuntimeCallInfo * argv)242 JSTaggedValue 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
GetBigInt64(EcmaRuntimeCallInfo * argv)249 JSTaggedValue 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
GetBigUint64(EcmaRuntimeCallInfo * argv)256 JSTaggedValue 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
SetFloat32(EcmaRuntimeCallInfo * argv)263 JSTaggedValue 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
SetFloat64(EcmaRuntimeCallInfo * argv)271 JSTaggedValue 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
SetInt8(EcmaRuntimeCallInfo * argv)279 JSTaggedValue 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
SetInt16(EcmaRuntimeCallInfo * argv)287 JSTaggedValue 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
SetInt32(EcmaRuntimeCallInfo * argv)295 JSTaggedValue 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
SetUint8(EcmaRuntimeCallInfo * argv)303 JSTaggedValue 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
SetUint16(EcmaRuntimeCallInfo * argv)311 JSTaggedValue 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
SetUint32(EcmaRuntimeCallInfo * argv)319 JSTaggedValue 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
SetBigInt64(EcmaRuntimeCallInfo * argv)327 JSTaggedValue 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
SetBigUint64(EcmaRuntimeCallInfo * argv)335 JSTaggedValue 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
GetViewValue(JSThread * thread,const JSHandle<JSTaggedValue> & view,const JSHandle<JSTaggedValue> & requestIndex,const JSHandle<JSTaggedValue> & littleEndian,DataViewType type)343 JSTaggedValue 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
SetViewValue(JSThread * thread,const JSHandle<JSTaggedValue> & view,const JSHandle<JSTaggedValue> & requestIndex,const JSHandle<JSTaggedValue> & littleEndian,DataViewType type,const JSHandle<JSTaggedValue> & value)405 JSTaggedValue 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 
GetTypedValue(EcmaRuntimeCallInfo * argv,DataViewType type)469 JSTaggedValue 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 
SetTypedValue(EcmaRuntimeCallInfo * argv,DataViewType type)484 JSTaggedValue 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