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