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