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