• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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/containers/containers_buffer.h"
17 #include <cstdint>
18 
19 #include "ecmascript/base/typed_array_helper.h"
20 #include "ecmascript/base/typed_array_helper-inl.h"
21 #include "ecmascript/containers/containers_errors.h"
22 #include "ecmascript/ecma_string.h"
23 #include "ecmascript/ecma_string-inl.h"
24 #include "ecmascript/global_env.h"
25 #include "ecmascript/js_api/js_api_buffer.h"
26 #include "ecmascript/js_handle.h"
27 #include "ecmascript/js_hclass.h"
28 #include "ecmascript/js_tagged_number.h"
29 #include "ecmascript/js_tagged_value.h"
30 #include "ecmascript/js_typed_array.h"
31 #include "macros.h"
32 
33 namespace panda::ecmascript::containers {
34 
35 #define RANGE_ERROR_CHECK(value, name, left, right)                                                                    \
36     double(num##name) = (value)->GetNumber();                                                                          \
37     if ((num##name) < (left) || (num##name) > (right)) {                                                               \
38         std::ostringstream oss;                                                                                        \
39         oss << "The value of \"" << (#name) << "\" is out of range. It must be >= " << (left) << " and <= " << (right) \
40             << ". Received value is: " << (num##name);                                                                 \
41         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str());        \
42         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());                                   \
43     }
44 
45 #define CHECK_NULL_OR_UNDEFINED(value)                                                                         \
46     if ((value)->IsUndefined() || (value)->IsNull()) {                                                             \
47         std::ostringstream oss;                                                                                \
48         oss << "The parameter should not be null or undefined.";                                               \
49         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, oss.str().c_str()); \
50         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());                           \
51     }
52 
GetValueInt32(JSHandle<JSTaggedValue> valueHandle)53 int32_t GetValueInt32(JSHandle<JSTaggedValue> valueHandle)
54 {
55     JSTaggedValue value = valueHandle.GetTaggedValue();
56     if (UNLIKELY(value.IsDouble())) {
57         return static_cast<int32_t>(
58             ecmascript::base::NumberHelper::DoubleToInt(value.GetDouble(), ecmascript::base::INT32_BITS));
59     }
60     return value.GetInt();
61 }
62 
GetValueUInt32(JSHandle<JSTaggedValue> valueHandle)63 uint32_t GetValueUInt32(JSHandle<JSTaggedValue> valueHandle)
64 {
65     return static_cast<uint32_t>(GetValueInt32(valueHandle));
66 }
67 
GetUInt8ArrayFromBufferObject(JSThread * thread,JSTaggedValue buffer)68 JSTypedArray *GetUInt8ArrayFromBufferObject(JSThread *thread, JSTaggedValue buffer)
69 {
70     if (buffer.IsJSUint8Array()) {
71         return JSTypedArray::Cast(buffer.GetTaggedObject());
72     }
73     ASSERT(buffer.IsJSAPIBuffer());
74     return JSTypedArray::Cast(
75         JSAPIFastBuffer::Cast(buffer.GetTaggedObject())->GetFastBufferData(thread).GetTaggedObject());
76 }
77 
GetUInt8ArrayFromBufferObject(JSThread * thread,JSHandle<JSTaggedValue> buffer)78 JSTypedArray *GetUInt8ArrayFromBufferObject(JSThread *thread, JSHandle<JSTaggedValue> buffer)
79 {
80     return GetUInt8ArrayFromBufferObject(thread, buffer.GetTaggedValue());
81 }
82 
IsNegetiveNumber(JSHandle<JSTaggedValue> & v)83 bool IsNegetiveNumber(JSHandle<JSTaggedValue> &v)
84 {
85     ASSERT(v->IsNumber());
86     return v->GetNumber() < 0;
87 }
88 
IsValidEncoding(JSThread * thread,JSHandle<JSTaggedValue> & str)89 bool IsValidEncoding(JSThread *thread, JSHandle<JSTaggedValue> &str)
90 {
91     if (!str->IsString()) {
92         return false;
93     }
94     auto strAccessor = EcmaStringAccessor(JSHandle<EcmaString>(str));
95     auto res = strAccessor.ToStdString(thread);
96     return JSAPIFastBuffer::GetEncodingType(res) != JSAPIFastBuffer::EncodingType::INVALID;
97 }
98 
BufferConstructor(EcmaRuntimeCallInfo * argv)99 JSTaggedValue ContainersBuffer::BufferConstructor(EcmaRuntimeCallInfo *argv)
100 {
101     ASSERT(argv);
102     BUILTINS_API_TRACE(argv->GetThread(), Buffer, Constructor);
103     JSThread *thread = argv->GetThread();
104     [[maybe_unused]] EcmaHandleScope handleScope(thread);
105     JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv);
106     JSHandle<JSTaggedValue> constructor = GetConstructor(argv);
107     if (newTarget->IsUndefined()) {
108         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::IS_NULL_ERROR,
109                                                             "The Buffer's constructor cannot be directly invoked.");
110         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
111     }
112 
113     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
114     JSHandle<JSAPIFastBuffer> bufferObj = JSHandle<JSAPIFastBuffer>::Cast(
115         factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget));
116     // parameter preprocess
117     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);                 // 0 means the first arg
118     JSHandle<JSTaggedValue> byteOffsetOrEncoding = GetCallArg(argv, 1);  // 1 means the second arg
119     JSHandle<JSTaggedValue> length = GetCallArg(argv, 2);                // 2 means the third arg
120     CHECK_NULL_OR_UNDEFINED(value);
121     if (value->IsNumber()) {
122         RANGE_ERROR_CHECK(value, value, 0, UINT32_MAX);
123         JSAPIFastBuffer::AllocateFastBuffer(thread, bufferObj, GetValueUInt32(value));
124     } else if (value->IsString()) {
125         if (byteOffsetOrEncoding->IsString() && !IsValidEncoding(thread, byteOffsetOrEncoding)) {
126             JSTaggedValue error = ContainerError::BusinessError(
127                 thread, ErrorFlag::TYPE_ERROR,
128                 "Parameter error. The type of \"encoding\" must be BufferEncoding. the encoding code is unknown");
129             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
130         }
131         JSAPIFastBuffer::FromString(thread, bufferObj, value, byteOffsetOrEncoding);
132     } else if (value->IsJSAPIBuffer()) {
133         if (byteOffsetOrEncoding->IsNumber() && length->IsNumber()) {
134             // share memory with another buffer(eg: create from pool)
135             JSAPIFastBuffer::AllocateFromBufferObject(thread, bufferObj, value, GetValueUInt32(length),
136                                                       GetValueUInt32(byteOffsetOrEncoding));
137         } else {
138             uint32_t bufferLength = JSAPIFastBuffer::Cast(value->GetTaggedObject())->GetLength();
139             JSAPIFastBuffer::AllocateFastBuffer(thread, bufferObj, bufferLength);
140             bufferObj->SetLength(bufferLength);
141             auto bufferHandle = JSHandle<JSTaggedValue>::Cast(bufferObj);
142             JSAPIFastBuffer::Copy(thread, bufferHandle, value, 0, 0, bufferLength);
143         }
144     } else if (value->IsArrayBuffer() || value->IsSharedArrayBuffer()) {
145         uint32_t index = 0;
146         uint32_t byteLength = JSHandle<JSArrayBuffer>(value)->GetArrayBufferByteLength();
147         if (byteOffsetOrEncoding->IsNumber()) {
148             RANGE_ERROR_CHECK(byteOffsetOrEncoding, byteOffsetOrEncoding, 0, UINT32_MAX);
149             index = GetValueUInt32(byteOffsetOrEncoding);
150         }
151         if (length->IsNumber()) {
152             RANGE_ERROR_CHECK(length, length, 0, UINT32_MAX);
153             byteLength = GetValueUInt32(length);
154         }
155         JSAPIFastBuffer::FromArrayBuffer(thread, bufferObj, value, index, byteLength);
156     } else if (value->IsJSUint8Array()) {
157         bufferObj->SetFastBufferData(thread, value);
158         bufferObj->SetLength(JSTypedArray::Cast(value->GetTaggedObject())->GetByteLength());
159     } else if (value->IsJSArray()) {
160         JSAPIFastBuffer::CreateBufferFromArrayLike(thread, bufferObj, value);
161     }
162 
163     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
164     return bufferObj.GetTaggedValue();
165 }
166 
GetSize(EcmaRuntimeCallInfo * argv)167 JSTaggedValue ContainersBuffer::GetSize(EcmaRuntimeCallInfo *argv)
168 {
169     ASSERT(argv);
170     BUILTINS_API_TRACE(argv->GetThread(), Buffer, GetSize);
171     JSThread *thread = argv->GetThread();
172     [[maybe_unused]] EcmaHandleScope handleScope(thread);
173     CONTAINER_BUFFER_CHECK(GetSize);
174 
175     return JSTaggedValue(JSHandle<JSAPIFastBuffer>::Cast(self)->GetLength());
176 }
177 
GetByteOffset(EcmaRuntimeCallInfo * argv)178 JSTaggedValue ContainersBuffer::GetByteOffset(EcmaRuntimeCallInfo *argv)
179 {
180     ASSERT(argv);
181     BUILTINS_API_TRACE(argv->GetThread(), Buffer, GetByteOffset);
182     JSThread *thread = argv->GetThread();
183     [[maybe_unused]] EcmaHandleScope handleScope(thread);
184     CONTAINER_BUFFER_CHECK(GetByteOffset);
185     return JSTaggedValue(JSHandle<JSAPIFastBuffer>::Cast(self)->GetOffset());
186 }
187 
GetArrayBuffer(EcmaRuntimeCallInfo * argv)188 JSTaggedValue ContainersBuffer::GetArrayBuffer(EcmaRuntimeCallInfo *argv)
189 {
190     ASSERT(argv);
191     BUILTINS_API_TRACE(argv->GetThread(), Buffer, GetArrayBuffer);
192     JSThread *thread = argv->GetThread();
193     [[maybe_unused]] EcmaHandleScope handleScope(thread);
194     CONTAINER_BUFFER_CHECK(GetArrayBuffer);
195     JSHandle<JSAPIFastBuffer> buffer = JSHandle<JSAPIFastBuffer>::Cast(self);
196     return JSAPIFastBuffer::GetArrayBuffer(thread, buffer);
197 }
198 
Compare(EcmaRuntimeCallInfo * argv)199 JSTaggedValue ContainersBuffer::Compare(EcmaRuntimeCallInfo *argv)
200 {
201     ASSERT(argv);
202     BUILTINS_API_TRACE(argv->GetThread(), Buffer, Compare);
203     JSThread *thread = argv->GetThread();
204     [[maybe_unused]] EcmaHandleScope handleScope(thread);
205     CONTAINER_BUFFER_CHECK(Compare);
206     auto value = GetCallArg(argv, 0);  // 0 means the first arg
207     CHECK_NULL_OR_UNDEFINED(value);
208     auto src = JSHandle<JSAPIFastBuffer>::Cast(self);
209     uint32_t tStart = 0;
210     uint32_t tEnd = (value->IsJSAPIBuffer() ? JSHandle<JSAPIFastBuffer>::Cast(value)->GetLength()
211                                             : JSHandle<JSTypedArray>::Cast(value)->GetByteLength());
212     uint32_t srcLength = src->GetLength();
213     uint32_t dstLength = tEnd;
214     auto targetStart = GetCallArg(argv, 1);  // 1 means the second arg
215     auto targetEnd = GetCallArg(argv, 2);    // 2 means the third arg
216     auto sourceStart = GetCallArg(argv, 3);  // 3 means the fourth arg
217     auto sourceEnd = GetCallArg(argv, 4);    // 4 means the fifth arg
218     if (targetStart->IsNumber()) {
219         RANGE_ERROR_CHECK(targetStart, targetStart, 0, dstLength);
220         tStart = GetValueUInt32(targetStart);
221     }
222     if (targetEnd->IsNumber()) {
223         RANGE_ERROR_CHECK(targetEnd, targetEnd, 0, dstLength);
224         tEnd = GetValueUInt32(targetEnd);
225     }
226     uint32_t sStart = 0;
227     if (sourceStart->IsNumber()) {
228         RANGE_ERROR_CHECK(sourceStart, sourceStart, 0, srcLength);
229         sStart = GetValueUInt32(sourceStart);
230     }
231     uint32_t sEnd = src->GetLength();
232     if (sourceEnd->IsNumber()) {
233         RANGE_ERROR_CHECK(sourceEnd, sourceEnd, 0, srcLength);
234         sEnd = GetValueUInt32(sourceEnd);
235     }
236     if (sStart >= sEnd) {
237         return JSTaggedValue(tStart >= tEnd ? 0 : -1);
238     }
239     if (tStart >= tEnd) {
240         return JSTaggedValue(1);
241     }
242     auto ret = JSAPIFastBuffer::Compare(thread, src, value, sStart, sEnd, tStart, tEnd);
243     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
244     return ret;
245 }
246 
Equals(EcmaRuntimeCallInfo * argv)247 JSTaggedValue ContainersBuffer::Equals(EcmaRuntimeCallInfo *argv)
248 {
249     ASSERT(argv);
250     BUILTINS_API_TRACE(argv->GetThread(), Buffer, Equals);
251     JSThread *thread = argv->GetThread();
252     [[maybe_unused]] EcmaHandleScope handleScope(thread);
253     CONTAINER_BUFFER_CHECK(Equals);
254     auto value = GetCallArg(argv, 0);  // 0 means the first arg
255     CHECK_NULL_OR_UNDEFINED(value);
256     auto src = JSHandle<JSAPIFastBuffer>::Cast(self);
257     uint32_t tEnd;
258     if (value->IsJSAPIBuffer()) {
259         tEnd = JSHandle<JSAPIFastBuffer>::Cast(value)->GetLength();
260     } else if (value->IsJSUint8Array()) {
261         tEnd = JSHandle<JSTypedArray>::Cast(value)->GetByteLength();
262     } else {
263         JSTaggedValue error = ContainerError::ParamError(thread, "unexpect value type, expect buffer | Uint8Array");
264         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
265     }
266     auto res = JSAPIFastBuffer::Compare(thread, src, value, 0, src->GetLength(), 0, tEnd);
267     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
268     return res.GetInt() == 0 ? JSTaggedValue(true) : JSTaggedValue(false);
269 }
270 
IndexOf(EcmaRuntimeCallInfo * argv)271 JSTaggedValue ContainersBuffer::IndexOf(EcmaRuntimeCallInfo *argv)
272 {
273     ASSERT(argv);
274     BUILTINS_API_TRACE(argv->GetThread(), Buffer, IndexOf);
275     JSThread *thread = argv->GetThread();
276     [[maybe_unused]] EcmaHandleScope handleScope(thread);
277     CONTAINER_BUFFER_CHECK(IndexOf);
278     JSHandle<JSAPIFastBuffer> buffer = JSHandle<JSAPIFastBuffer>::Cast(self);
279     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);   // 0 means the first arg
280     JSHandle<JSTaggedValue> offset = GetCallArg(argv, 1);  // 1 means the second arg
281     CHECK_NULL_OR_UNDEFINED(value);
282     int32_t offsetIndex = 0;
283     int32_t length = static_cast<int32_t>(buffer->GetLength());
284     if (offset->IsNumber()) {
285         if (offset->GetNumber() > length) {
286             return JSTaggedValue(-1);
287         } else {
288             offsetIndex = GetValueInt32(offset);
289             if (offsetIndex < 0) {
290                 offsetIndex = -offsetIndex;
291                 offsetIndex = length - offsetIndex;
292                 offsetIndex = std::max(offsetIndex, 0);
293             }
294         }
295     }
296     JSHandle<JSTaggedValue> encoding = GetCallArg(argv, 2);  // 2 means the third arg
297     JSAPIFastBuffer::EncodingType encodingType = JSAPIFastBuffer::UTF8;
298     if (encoding->IsString()) {
299         if (!IsValidEncoding(thread, encoding)) {
300             JSTaggedValue error = ContainerError::BusinessError(
301                 thread, ErrorFlag::TYPE_ERROR,
302                 "Parameter error. The type of \"encoding\" must be BufferEncoding. the encoding code is unknown");
303             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
304         }
305         encodingType = JSAPIFastBuffer::GetEncodingType(JSAPIFastBuffer::GetString(thread, encoding));
306     }
307     return JSAPIFastBuffer::IndexOf(thread, buffer, value, offsetIndex, encodingType);
308 }
309 
Includes(EcmaRuntimeCallInfo * argv)310 JSTaggedValue ContainersBuffer::Includes(EcmaRuntimeCallInfo *argv)
311 {
312     ASSERT(argv);
313     BUILTINS_API_TRACE(argv->GetThread(), Buffer, Includes);
314     JSThread *thread = argv->GetThread();
315     [[maybe_unused]] EcmaHandleScope handleScope(thread);
316     CONTAINER_BUFFER_CHECK(Includes);
317     JSHandle<JSAPIFastBuffer> buffer = JSHandle<JSAPIFastBuffer>::Cast(self);
318     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);  // 0 means the first arg
319     CHECK_NULL_OR_UNDEFINED(value);
320     JSHandle<JSTaggedValue> offset = GetCallArg(argv, 1);  // 1 means the second arg
321     int32_t length = static_cast<int32_t>(buffer->GetLength());
322     int32_t offsetIndex = 0;
323     if (offset->IsNumber()) {
324         if (offset->GetNumber() > length) {
325             return JSTaggedValue(false);
326         } else {
327             offsetIndex = GetValueInt32(offset);
328             if (offsetIndex < 0) {
329                 offsetIndex = -offsetIndex;
330                 offsetIndex = length - offsetIndex;
331                 offsetIndex = std::max(offsetIndex, 0);
332             }
333         }
334     }
335     JSHandle<JSTaggedValue> encoding = GetCallArg(argv, 2);  // 2 means the third arg
336     JSAPIFastBuffer::EncodingType encodingType = JSAPIFastBuffer::UTF8;
337     if (encoding->IsString()) {
338         if (!IsValidEncoding(thread, encoding)) {
339             JSTaggedValue error = ContainerError::BusinessError(
340                 thread, ErrorFlag::TYPE_ERROR,
341                 "Parameter error. The type of \"encoding\" must be BufferEncoding. the encoding code is unknown");
342             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
343         }
344         encodingType = JSAPIFastBuffer::GetEncodingType(JSAPIFastBuffer::GetString(thread, encoding));
345     }
346     return JSAPIFastBuffer::Includes(thread, buffer, value, offsetIndex, encodingType);
347 }
348 
LastIndexOf(EcmaRuntimeCallInfo * argv)349 JSTaggedValue ContainersBuffer::LastIndexOf(EcmaRuntimeCallInfo *argv)
350 {
351     ASSERT(argv);
352     BUILTINS_API_TRACE(argv->GetThread(), Buffer, LastIndexOf);
353     JSThread *thread = argv->GetThread();
354     [[maybe_unused]] EcmaHandleScope handleScope(thread);
355     CONTAINER_BUFFER_CHECK(LastIndexOf);
356     JSHandle<JSAPIFastBuffer> buffer = JSHandle<JSAPIFastBuffer>::Cast(self);
357     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);  // 0 means the first arg
358     CHECK_NULL_OR_UNDEFINED(value);
359     JSHandle<JSTaggedValue> offset = GetCallArg(argv, 1);  // 1 means the second arg
360     int64_t length = static_cast<int64_t>(buffer->GetLength());
361     int64_t offsetIndex = length - 1;
362     if (offset->IsNumber()) {
363         if (offset->GetNumber() < -length) {
364             return JSTaggedValue(-1);
365         }
366         if (offset->GetNumber() < length) {
367             offsetIndex = GetValueInt32(offset);
368             if (offsetIndex < 0) {
369                 offsetIndex = -offsetIndex;
370                 offsetIndex = length - offsetIndex;
371             }
372         }
373     }
374     offsetIndex = std::min(offsetIndex, length);
375     JSHandle<JSTaggedValue> encoding = GetCallArg(argv, 2);  // 2 means the third arg
376     JSAPIFastBuffer::EncodingType encodingType = JSAPIFastBuffer::UTF8;
377     if (encoding->IsString()) {
378         if (!IsValidEncoding(thread, encoding)) {
379             JSTaggedValue error = ContainerError::BusinessError(
380                 thread, ErrorFlag::TYPE_ERROR,
381                 "Parameter error. The type of \"encoding\" must be BufferEncoding. the encoding code is unknown");
382             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
383         }
384         encodingType = JSAPIFastBuffer::GetEncodingType(JSAPIFastBuffer::GetString(thread, encoding));
385     }
386     return JSAPIFastBuffer::IndexOf(thread, buffer, value, static_cast<uint32_t>(offsetIndex), encodingType, true);
387 }
388 
Entries(EcmaRuntimeCallInfo * argv)389 JSTaggedValue ContainersBuffer::Entries(EcmaRuntimeCallInfo *argv)
390 {
391     ASSERT(argv);
392     BUILTINS_API_TRACE(argv->GetThread(), Buffer, Entries);
393     JSThread *thread = argv->GetThread();
394     [[maybe_unused]] EcmaHandleScope handleScope(thread);
395     CONTAINER_BUFFER_CHECK(Entries);
396     JSHandle<JSAPIFastBuffer> buffer = JSHandle<JSAPIFastBuffer>::Cast(self);
397     return JSAPIFastBuffer::Entries(thread, buffer);
398 }
399 
Keys(EcmaRuntimeCallInfo * argv)400 JSTaggedValue ContainersBuffer::Keys(EcmaRuntimeCallInfo *argv)
401 {
402     ASSERT(argv);
403     BUILTINS_API_TRACE(argv->GetThread(), Buffer, Keys);
404     JSThread *thread = argv->GetThread();
405     [[maybe_unused]] EcmaHandleScope handleScope(thread);
406     CONTAINER_BUFFER_CHECK(Keys);
407     JSHandle<JSAPIFastBuffer> buffer = JSHandle<JSAPIFastBuffer>::Cast(self);
408     return JSAPIFastBuffer::Keys(thread, buffer);
409 }
410 
Values(EcmaRuntimeCallInfo * argv)411 JSTaggedValue ContainersBuffer::Values(EcmaRuntimeCallInfo *argv)
412 {
413     ASSERT(argv);
414     BUILTINS_API_TRACE(argv->GetThread(), Buffer, Values);
415     JSThread *thread = argv->GetThread();
416     [[maybe_unused]] EcmaHandleScope handleScope(thread);
417     CONTAINER_BUFFER_CHECK(Values);
418     JSHandle<JSAPIFastBuffer> buffer = JSHandle<JSAPIFastBuffer>::Cast(self);
419     return JSAPIFastBuffer::Values(thread, buffer);
420 }
421 
Fill(EcmaRuntimeCallInfo * argv)422 JSTaggedValue ContainersBuffer::Fill(EcmaRuntimeCallInfo *argv)
423 {
424     ASSERT(argv);
425     BUILTINS_API_TRACE(argv->GetThread(), Buffer, Fill);
426     JSThread *thread = argv->GetThread();
427     [[maybe_unused]] EcmaHandleScope handleScope(thread);
428     CONTAINER_BUFFER_CHECK(Fill);
429     JSHandle<JSAPIFastBuffer> buffer = JSHandle<JSAPIFastBuffer>::Cast(self);
430     uint32_t length = buffer->GetLength();
431     if (length == 0) {
432         return buffer.GetTaggedValue();
433     }
434     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);  // 0 means the first arg
435     JSHandle<JSTaggedValue> start = GetCallArg(argv, 1);  // 1 means the second arg
436     if (start->IsString()) {
437         JSAPIFastBuffer::EncodingType encodingType = JSAPIFastBuffer::UTF8;
438         if (!IsValidEncoding(thread, start)) {
439             JSTaggedValue error = ContainerError::BusinessError(
440                 thread, ErrorFlag::TYPE_ERROR,
441                 "Parameter error. The type of \"encoding\" must be BufferEncoding. the encoding code is unknown");
442             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
443         }
444         encodingType = JSAPIFastBuffer::GetEncodingType(JSAPIFastBuffer::GetString(thread, start));
445         return JSAPIFastBuffer::Fill(thread, buffer, value, encodingType, 0, length);
446     }
447     JSHandle<JSTaggedValue> end = GetCallArg(argv, 2);       // 2 means the third arg
448     JSHandle<JSTaggedValue> encoding = GetCallArg(argv, 3);  // 3 means the fourth arg
449     uint32_t startIndex = 0;
450     if (start->IsNumber()) {
451         RANGE_ERROR_CHECK(start, offset, 0, length);
452         startIndex = GetValueUInt32(start);
453     }
454     uint32_t endIndex = length;
455     if (end->IsNumber()) {
456         RANGE_ERROR_CHECK(end, end, 0, length);
457         endIndex = GetValueUInt32(end);
458     }
459     if (endIndex <= startIndex) {
460         return buffer.GetTaggedValue();
461     }
462     JSAPIFastBuffer::EncodingType encodingType = JSAPIFastBuffer::UTF8;
463     if (encoding->IsString()) {
464         if (!IsValidEncoding(thread, encoding)) {
465             JSTaggedValue error = ContainerError::BusinessError(
466                 thread, ErrorFlag::TYPE_ERROR,
467                 "Parameter error. The type of \"encoding\" must be BufferEncoding. the encoding code is unknown");
468             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
469         }
470         encodingType = JSAPIFastBuffer::GetEncodingType(JSAPIFastBuffer::GetString(thread, encoding));
471     }
472     return JSAPIFastBuffer::Fill(thread, buffer, value, encodingType, startIndex, endIndex);
473 }
474 
Write(EcmaRuntimeCallInfo * argv)475 JSTaggedValue ContainersBuffer::Write(EcmaRuntimeCallInfo *argv)
476 {
477     ASSERT(argv);
478     BUILTINS_API_TRACE(argv->GetThread(), Buffer, Write);
479     JSThread *thread = argv->GetThread();
480     [[maybe_unused]] EcmaHandleScope handleScope(thread);
481     CONTAINER_BUFFER_CHECK(Write);
482     JSAPIFastBuffer::EncodingType encodingType = JSAPIFastBuffer::UTF8;
483     JSHandle<JSAPIFastBuffer> buffer = JSHandle<JSAPIFastBuffer>::Cast(self);
484     JSHandle<JSTaggedValue> firstArg = GetCallArg(argv, 0);  // 0 means the first arg
485     CHECK_NULL_OR_UNDEFINED(firstArg);
486     if (firstArg->IsString()) {
487         JSHandle<JSTaggedValue> secondArg = GetCallArg(argv, 1);  // 1 means the second arg
488         if (secondArg->IsUndefined() || secondArg->IsNull()) {
489             return JSAPIFastBuffer::WriteString(thread, buffer, firstArg, 0, buffer->GetLength(),
490                                                 JSAPIFastBuffer::UTF8);
491         }
492         if (secondArg->IsString()) {
493             if (!IsValidEncoding(thread, secondArg)) {
494                 JSTaggedValue error = ContainerError::BusinessError(
495                     thread, ErrorFlag::TYPE_ERROR,
496                     "Parameter error. The type of \"encoding\" must be BufferEncoding. the encoding code is unknown");
497                 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
498             }
499             encodingType = JSAPIFastBuffer::GetEncodingType(JSAPIFastBuffer::GetString(thread, secondArg));
500             return JSAPIFastBuffer::WriteString(thread, buffer, firstArg, 0, buffer->GetLength(), encodingType);
501         }
502         uint32_t offset = 0;
503         if (secondArg->IsNumber()) {
504             RANGE_ERROR_CHECK(secondArg, offset, 0, buffer->GetLength() - 1);
505             offset = GetValueUInt32(secondArg);
506         }
507         uint32_t maxLength = buffer->GetLength() - offset;
508         JSHandle<JSTaggedValue> thirdArg = GetCallArg(argv, 2);  // 2 means the third arg
509         if (thirdArg->IsNumber()) {
510             RANGE_ERROR_CHECK(thirdArg, length, 0, maxLength);
511             maxLength = std::min(GetValueUInt32(thirdArg), maxLength);
512         }
513         JSHandle<JSTaggedValue> encoding = GetCallArg(argv, 3);  // 3 means the fourth arg
514         if (encoding->IsString()) {
515             if (!IsValidEncoding(thread, encoding)) {
516                 JSTaggedValue error = ContainerError::BusinessError(
517                     thread, ErrorFlag::TYPE_ERROR,
518                     "Parameter error. The type of \"encoding\" must be BufferEncoding. the encoding code is unknown");
519                 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
520             }
521             encodingType = JSAPIFastBuffer::GetEncodingType(JSAPIFastBuffer::GetString(thread, encoding));
522         }
523         return JSAPIFastBuffer::WriteString(thread, buffer, firstArg, offset, maxLength, encodingType);
524     }
525     return JSTaggedValue(0);
526 }
527 
ToString(EcmaRuntimeCallInfo * argv)528 JSTaggedValue ContainersBuffer::ToString(EcmaRuntimeCallInfo *argv)
529 {
530     ASSERT(argv);
531     BUILTINS_API_TRACE(argv->GetThread(), Buffer, ToString);
532     JSThread *thread = argv->GetThread();
533     [[maybe_unused]] EcmaHandleScope handleScope(thread);
534     CONTAINER_BUFFER_CHECK(ToString);
535     JSHandle<JSAPIFastBuffer> buffer = JSHandle<JSAPIFastBuffer>::Cast(self);
536     JSHandle<JSTaggedValue> firstArg = GetCallArg(argv, 0);  // 0 means the first arg
537     JSHandle<JSTaggedValue> start = GetCallArg(argv, 1);     // 1 means the second arg
538     JSHandle<JSTaggedValue> end = GetCallArg(argv, 2);       // 2 means the third arg
539     JSAPIFastBuffer::EncodingType encodingType = JSAPIFastBuffer::UTF8;
540     if (firstArg->IsString()) {
541         if (!IsValidEncoding(thread, firstArg)) {
542             JSTaggedValue error = ContainerError::BusinessError(
543                 thread, ErrorFlag::TYPE_ERROR,
544                 "Parameter error. The type of \"encoding\" must be BufferEncoding. the encoding code is unknown");
545             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
546         }
547         encodingType = JSAPIFastBuffer::GetEncodingType(thread, firstArg);
548     }
549     uint32_t startIndex = 0;
550     if (start->IsNumber()) {
551         if (start->GetNumber() < 0) {
552             startIndex = 0;
553         } else {
554             startIndex = GetValueUInt32(start);
555         }
556     }
557     uint32_t endIndex = buffer->GetLength();
558     if (startIndex >= endIndex) {
559         return thread->GlobalConstants()->GetHandledEmptyString().GetTaggedValue();
560     }
561     if (end->IsNumber()) {
562         if (end->GetNumber() <= startIndex) {
563             return thread->GlobalConstants()->GetHandledEmptyString().GetTaggedValue();
564         }
565         if (end->GetNumber() < endIndex) {
566             endIndex = GetValueUInt32(end);
567         }
568     }
569     auto ret = JSAPIFastBuffer::ToString(thread, buffer, encodingType, startIndex, endIndex);
570     return ret;
571 }
572 
Copy(EcmaRuntimeCallInfo * argv)573 JSTaggedValue ContainersBuffer::Copy(EcmaRuntimeCallInfo *argv)
574 {
575     ASSERT(argv);
576     BUILTINS_API_TRACE(argv->GetThread(), Buffer, Copy);
577     JSThread *thread = argv->GetThread();
578     [[maybe_unused]] EcmaHandleScope handleScope(thread);
579     CONTAINER_BUFFER_CHECK(Copy);
580     JSHandle<JSAPIFastBuffer> src = JSHandle<JSAPIFastBuffer>::Cast(self);
581     JSHandle<JSTaggedValue> dst = GetCallArg(argv, 0);  // 0 means the first arg
582     CHECK_NULL_OR_UNDEFINED(dst);
583     uint32_t srcLength = src->GetLength();
584     uint32_t dstLength = dst->IsJSAPIBuffer() ? JSHandle<JSAPIFastBuffer>(dst)->GetLength()
585                                               : JSHandle<JSTypedArray>(dst)->GetArrayLength();
586     auto targetStart = GetCallArg(argv, 1);  // 1 means the second arg
587     auto sourceStart = GetCallArg(argv, 2);  // 2 means the third arg
588     auto sourceEnd = GetCallArg(argv, 3);    // 3 means the fourth arg
589     uint32_t tStart = 0;
590     if (targetStart->IsNumber()) {
591         RANGE_ERROR_CHECK(targetStart, targetStart, 0, UINT32_MAX);
592         tStart = GetValueUInt32(targetStart);
593     }
594     uint32_t sStart = 0;
595     if (sourceStart->IsNumber()) {
596         RANGE_ERROR_CHECK(sourceStart, sourceStart, 0, UINT32_MAX);
597         sStart = GetValueUInt32(sourceStart);
598     }
599     uint32_t sEnd = srcLength;
600     if (sourceEnd->IsNumber()) {
601         RANGE_ERROR_CHECK(sourceEnd, sourceEnd, 0, srcLength);
602         sEnd = GetValueUInt32(sourceEnd);
603     }
604     if (sEnd <= sStart || sStart >= srcLength || tStart >= dstLength) {
605         return JSTaggedValue(0);
606     }
607     return JSAPIFastBuffer::Copy(thread, dst, self, tStart, sStart, sEnd);
608 }
609 
WriteUIntBE(EcmaRuntimeCallInfo * argv)610 JSTaggedValue ContainersBuffer::WriteUIntBE(EcmaRuntimeCallInfo *argv)
611 {
612     ASSERT(argv != nullptr);
613     JSThread *thread = argv->GetThread();
614     BUILTINS_API_TRACE(thread, Buffer, WriteUIntBE);
615     [[maybe_unused]] EcmaHandleScope handleScope(thread);
616     CONTAINER_BUFFER_CHECK(WriteUIntBE);
617     JSHandle<JSAPIFastBuffer> buffer = JSHandle<JSAPIFastBuffer>::Cast(self);
618     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);             // 0 means the first arg
619     JSHandle<JSTaggedValue> offset = GetCallArg(argv, 1);            // 1 means the second arg
620     JSHandle<JSTaggedValue> byteLengthHandle = GetCallArg(argv, 2);  // 2 means the third arg
621     CHECK_NULL_OR_UNDEFINED(value);
622     if (!byteLengthHandle->IsNumber()) {
623         JSTaggedValue error =
624             ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, "The byteLength should be number.");
625         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
626     }
627     uint32_t byteLength = GetValueUInt32(byteLengthHandle);
628     uint32_t offsetIndex = 0;
629     if (offset->IsNumber()) {
630         RANGE_ERROR_CHECK(offset, offset, 0, buffer->GetLength() - byteLength);
631         offsetIndex = GetValueUInt32(offset);
632     }
633     auto ret = JSAPIFastBuffer::WriteBytesValue(thread, buffer, value, offsetIndex,
634                                                 static_cast<JSAPIFastBuffer::ByteLength>(byteLength));
635     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
636     return ret;
637 }
WriteUIntLE(EcmaRuntimeCallInfo * argv)638 JSTaggedValue ContainersBuffer::WriteUIntLE(EcmaRuntimeCallInfo *argv)
639 {
640     ASSERT(argv != nullptr);
641     JSThread *thread = argv->GetThread();
642     BUILTINS_API_TRACE(thread, Buffer, WriteUIntLE);
643     [[maybe_unused]] EcmaHandleScope handleScope(thread);
644     CONTAINER_BUFFER_CHECK(WriteUIntLE)
645     JSHandle<JSAPIFastBuffer> buffer = JSHandle<JSAPIFastBuffer>::Cast(self);
646     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);             // 0 means the first arg
647     JSHandle<JSTaggedValue> offset = GetCallArg(argv, 1);            // 1 means the second arg
648     JSHandle<JSTaggedValue> byteLengthHandle = GetCallArg(argv, 2);  // 2 means the third arg
649     if (!byteLengthHandle->IsNumber()) {
650         JSTaggedValue error =
651             ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, "The byteLength should be number.");
652         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
653     }
654     uint32_t byteLength = GetValueUInt32(byteLengthHandle);
655     CHECK_NULL_OR_UNDEFINED(value);
656     uint32_t offsetIndex = 0;
657     if (offset->IsInt()) {
658         RANGE_ERROR_CHECK(offset, offset, 0, buffer->GetLength() - byteLength);
659         offsetIndex = GetValueUInt32(offset);
660     }
661     auto ret = JSAPIFastBuffer::WriteBytesValue(thread, buffer, value, offsetIndex,
662                                                 static_cast<JSAPIFastBuffer::ByteLength>(byteLength), true);
663     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
664     return ret;
665 }
ReadUIntBE(EcmaRuntimeCallInfo * argv)666 JSTaggedValue ContainersBuffer::ReadUIntBE(EcmaRuntimeCallInfo *argv)
667 {
668     ASSERT(argv != nullptr);
669     JSThread *thread = argv->GetThread();
670     BUILTINS_API_TRACE(thread, Buffer, ReadUIntBE);
671     [[maybe_unused]] EcmaHandleScope handleScope(thread);
672     CONTAINER_BUFFER_CHECK(ReadUIntBE)
673     JSHandle<JSAPIFastBuffer> buffer = JSHandle<JSAPIFastBuffer>::Cast(self);
674     JSHandle<JSTaggedValue> offset = GetCallArg(argv, 0);            // 0 means the first arg
675     JSHandle<JSTaggedValue> byteLengthHandle = GetCallArg(argv, 1);  // 1 means the second arg
676     CHECK_NULL_OR_UNDEFINED(offset);
677     if (!byteLengthHandle->IsNumber()) {
678         JSTaggedValue error =
679             ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, "The byteLength should be number.");
680         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
681     }
682     uint32_t byteLength = GetValueUInt32(byteLengthHandle);
683     uint32_t offsetIndex = 0;
684     if (offset->IsNumber()) {
685         RANGE_ERROR_CHECK(offset, offset, 0, buffer->GetLength() - byteLength);
686         offsetIndex = GetValueUInt32(offset);
687     }
688     auto ret =
689         JSAPIFastBuffer::ReadBytes(thread, buffer, offsetIndex, static_cast<JSAPIFastBuffer::ByteLength>(byteLength));
690     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
691     return ret;
692 }
ReadUIntLE(EcmaRuntimeCallInfo * argv)693 JSTaggedValue ContainersBuffer::ReadUIntLE(EcmaRuntimeCallInfo *argv)
694 {
695     ASSERT(argv != nullptr);
696     JSThread *thread = argv->GetThread();
697     BUILTINS_API_TRACE(thread, Buffer, ReadUIntLE);
698     [[maybe_unused]] EcmaHandleScope handleScope(thread);
699     CONTAINER_BUFFER_CHECK(ReadUIntLE)
700     JSHandle<JSAPIFastBuffer> buffer = JSHandle<JSAPIFastBuffer>::Cast(self);
701     JSHandle<JSTaggedValue> offset = GetCallArg(argv, 0);            // 0 means the first arg
702     JSHandle<JSTaggedValue> byteLengthHandle = GetCallArg(argv, 1);  // 1 means the second arg
703     CHECK_NULL_OR_UNDEFINED(offset);
704     if (!byteLengthHandle->IsNumber()) {
705         JSTaggedValue error =
706             ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, "The byteLength should be number.");
707         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
708     }
709     uint32_t byteLength = GetValueUInt32(byteLengthHandle);
710     uint32_t offsetIndex = 0;
711     if (offset->IsNumber()) {
712         RANGE_ERROR_CHECK(offset, offset, 0, buffer->GetLength() - byteLength);
713         offsetIndex = GetValueUInt32(offset);
714     }
715     auto ret = JSAPIFastBuffer::ReadBytes(thread, buffer, offsetIndex,
716                                           static_cast<JSAPIFastBuffer::ByteLength>(byteLength), true);
717     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
718     return ret;
719 }
720 
WriteIntBE(EcmaRuntimeCallInfo * argv)721 JSTaggedValue ContainersBuffer::WriteIntBE(EcmaRuntimeCallInfo *argv)
722 {
723     ASSERT(argv != nullptr);
724     JSThread *thread = argv->GetThread();
725     BUILTINS_API_TRACE(thread, Buffer, WriteIntBE);
726     [[maybe_unused]] EcmaHandleScope handleScope(thread);
727     CONTAINER_BUFFER_CHECK(WriteIntBE)
728     JSHandle<JSAPIFastBuffer> buffer = JSHandle<JSAPIFastBuffer>::Cast(self);
729     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);             // 0 means the first arg
730     JSHandle<JSTaggedValue> offset = GetCallArg(argv, 1);            // 1 means the second arg
731     JSHandle<JSTaggedValue> byteLengthHandle = GetCallArg(argv, 2);  // 2 means the third arg
732     CHECK_NULL_OR_UNDEFINED(value);
733     if (!byteLengthHandle->IsNumber()) {
734         JSTaggedValue error =
735             ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, "The byteLength should be number.");
736         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
737     }
738     uint32_t byteLength = GetValueUInt32(byteLengthHandle);
739     uint32_t offsetIndex = 0;
740     if (offset->IsNumber()) {
741         RANGE_ERROR_CHECK(offset, offset, 0, buffer->GetLength() - byteLength);
742         offsetIndex = GetValueUInt32(offset);
743     }
744     auto ret = JSAPIFastBuffer::WriteBytesValue(thread, buffer, value, offsetIndex,
745                                                 static_cast<JSAPIFastBuffer::ByteLength>(byteLength));
746     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
747     return ret;
748 }
WriteIntLE(EcmaRuntimeCallInfo * argv)749 JSTaggedValue ContainersBuffer::WriteIntLE(EcmaRuntimeCallInfo *argv)
750 {
751     ASSERT(argv != nullptr);
752     JSThread *thread = argv->GetThread();
753     BUILTINS_API_TRACE(thread, Buffer, WriteIntLE);
754     [[maybe_unused]] EcmaHandleScope handleScope(thread);
755     CONTAINER_BUFFER_CHECK(WriteIntLE)
756     JSHandle<JSAPIFastBuffer> buffer = JSHandle<JSAPIFastBuffer>::Cast(self);
757     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);             // 0 means the first arg
758     JSHandle<JSTaggedValue> offset = GetCallArg(argv, 1);            // 1 means the second arg
759     JSHandle<JSTaggedValue> byteLengthHandle = GetCallArg(argv, 2);  // 2 means the third arg
760     CHECK_NULL_OR_UNDEFINED(value);
761     if (!byteLengthHandle->IsNumber()) {
762         JSTaggedValue error =
763             ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, "The byteLength should be number.");
764         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
765     }
766     uint32_t byteLength = GetValueUInt32(byteLengthHandle);
767     uint32_t offsetIndex = 0;
768     if (offset->IsNumber()) {
769         RANGE_ERROR_CHECK(offset, offset, 0, buffer->GetLength() - byteLength);
770         offsetIndex = GetValueUInt32(offset);
771     }
772     auto ret = JSAPIFastBuffer::WriteBytesValue(thread, buffer, value, offsetIndex,
773                                                 static_cast<JSAPIFastBuffer::ByteLength>(byteLength), true);
774     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
775     return ret;
776 }
ReadIntBE(EcmaRuntimeCallInfo * argv)777 JSTaggedValue ContainersBuffer::ReadIntBE(EcmaRuntimeCallInfo *argv)
778 {
779     ASSERT(argv != nullptr);
780     JSThread *thread = argv->GetThread();
781     BUILTINS_API_TRACE(thread, Buffer, ReadIntBE);
782     [[maybe_unused]] EcmaHandleScope handleScope(thread);
783     CONTAINER_BUFFER_CHECK(ReadIntBE)
784     JSHandle<JSAPIFastBuffer> buffer = JSHandle<JSAPIFastBuffer>::Cast(self);
785     JSHandle<JSTaggedValue> offset = GetCallArg(argv, 0);            // 0 means the first arg
786     JSHandle<JSTaggedValue> byteLengthHandle = GetCallArg(argv, 1);  // 1 means the second arg
787     CHECK_NULL_OR_UNDEFINED(offset);
788     if (!byteLengthHandle->IsNumber()) {
789         JSTaggedValue error =
790             ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, "The byteLength should be number.");
791         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
792     }
793     uint32_t byteLength = GetValueUInt32(byteLengthHandle);
794     uint32_t offsetIndex = 0;
795     if (offset->IsNumber()) {
796         RANGE_ERROR_CHECK(offset, offset, 0, buffer->GetLength() - byteLength);
797         offsetIndex = GetValueUInt32(offset);
798     }
799     auto ret =
800         JSAPIFastBuffer::ReadInt(thread, buffer, offsetIndex, static_cast<JSAPIFastBuffer::ByteLength>(byteLength));
801     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
802     return ret;
803 }
ReadIntLE(EcmaRuntimeCallInfo * argv)804 JSTaggedValue ContainersBuffer::ReadIntLE(EcmaRuntimeCallInfo *argv)
805 {
806     ASSERT(argv != nullptr);
807     JSThread *thread = argv->GetThread();
808     BUILTINS_API_TRACE(thread, Buffer, ReadIntLE);
809     [[maybe_unused]] EcmaHandleScope handleScope(thread);
810     CONTAINER_BUFFER_CHECK(ReadIntLE)
811     JSHandle<JSAPIFastBuffer> buffer = JSHandle<JSAPIFastBuffer>::Cast(self);
812     JSHandle<JSTaggedValue> offset = GetCallArg(argv, 0);            // 0 means the first arg
813     JSHandle<JSTaggedValue> byteLengthHandle = GetCallArg(argv, 1);  // 1 means the second arg
814     CHECK_NULL_OR_UNDEFINED(offset);
815     if (!byteLengthHandle->IsNumber()) {
816         JSTaggedValue error =
817             ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, "The byteLength should be number.");
818         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
819     }
820     uint32_t byteLength = GetValueUInt32(byteLengthHandle);
821     uint32_t offsetIndex = 0;
822     if (offset->IsNumber()) {
823         RANGE_ERROR_CHECK(offset, offset, 0, buffer->GetLength() - byteLength);
824         offsetIndex = GetValueUInt32(offset);
825     }
826     auto ret = JSAPIFastBuffer::ReadInt(thread, buffer, offsetIndex,
827                                         static_cast<JSAPIFastBuffer::ByteLength>(byteLength), true);
828     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
829     return ret;
830 }
831 
WriteUInt8(EcmaRuntimeCallInfo * argv)832 JSTaggedValue ContainersBuffer::WriteUInt8(EcmaRuntimeCallInfo *argv)
833 {
834     return ContainersBuffer::WriteUInt8LE(argv);
835 }
836 
WriteInt8(EcmaRuntimeCallInfo * argv)837 JSTaggedValue ContainersBuffer::WriteInt8(EcmaRuntimeCallInfo *argv)
838 {
839     return ContainersBuffer::WriteInt8LE(argv);
840 }
841 
ReadUInt8(EcmaRuntimeCallInfo * argv)842 JSTaggedValue ContainersBuffer::ReadUInt8(EcmaRuntimeCallInfo *argv)
843 {
844     return ContainersBuffer::ReadUInt8LE(argv);
845 }
846 
ReadInt8(EcmaRuntimeCallInfo * argv)847 JSTaggedValue ContainersBuffer::ReadInt8(EcmaRuntimeCallInfo *argv)
848 {
849     return ContainersBuffer::ReadInt8LE(argv);
850 }
851 
852 CONTAINER_BUFFER_ACCESSORS(UInt8)
853 CONTAINER_BUFFER_ACCESSORS(UInt16)
854 CONTAINER_BUFFER_ACCESSORS(UInt32)
855 CONTAINER_BUFFER_ACCESSORS(BigUInt64)
856 CONTAINER_BUFFER_ACCESSORS(Int8)
857 CONTAINER_BUFFER_ACCESSORS(Int16)
858 CONTAINER_BUFFER_ACCESSORS(Int32)
859 CONTAINER_BUFFER_ACCESSORS(BigInt64)
860 CONTAINER_BUFFER_ACCESSORS(Float32)
861 CONTAINER_BUFFER_ACCESSORS(Float64)
862 
863 }  // namespace panda::ecmascript::containers
864