diff --git a/ecmascript/containers/containers_buffer.cpp b/ecmascript/containers/containers_buffer.cpp index 3010f12ba656ebb7ecfe00c8f92f3bb17be9089d..01033f38399d780c3dbcc3cdec1ebc0f9e6df843 100644 --- a/ecmascript/containers/containers_buffer.cpp +++ b/ecmascript/containers/containers_buffer.cpp @@ -32,22 +32,22 @@ namespace panda::ecmascript::containers { +#define NEW_BUSINESS_ERROR_AND_THROW(thread, errorType, message) \ + JSTaggedValue error = ContainerError::BusinessError(thread, errorType, message); \ + THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()) + #define RANGE_ERROR_CHECK(value, name, left, right) \ double(num##name) = (value)->GetNumber(); \ if ((num##name) < (left) || (num##name) > (right)) { \ std::ostringstream oss; \ oss << "The value of \"" << (#name) << "\" is out of range. It must be >= " << (left) << " and <= " << (right) \ << ". Received value is: " << (num##name); \ - JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str()); \ - THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); \ + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str()); \ } -#define CHECK_NULL_OR_UNDEFINED(value) \ - if ((value)->IsUndefined() || (value)->IsNull()) { \ - std::ostringstream oss; \ - oss << "The parameter should not be null or undefined."; \ - JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, oss.str().c_str()); \ - THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); \ +#define CHECK_NULL_OR_UNDEFINED(value) \ + if ((value)->IsUndefined() || (value)->IsNull()) { \ + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::TYPE_ERROR, "The parameter should not be null or undefined."); \ } int32_t GetValueInt32(JSHandle valueHandle) @@ -105,9 +105,8 @@ JSTaggedValue ContainersBuffer::BufferConstructor(EcmaRuntimeCallInfo *argv) JSHandle newTarget = GetNewTarget(argv); JSHandle constructor = GetConstructor(argv); if (newTarget->IsUndefined()) { - JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::IS_NULL_ERROR, - "The Buffer's constructor cannot be directly invoked."); - THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::IS_NULL_ERROR, + "The Buffer's constructor cannot be directly invoked."); } ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); @@ -122,16 +121,15 @@ JSTaggedValue ContainersBuffer::BufferConstructor(EcmaRuntimeCallInfo *argv) RANGE_ERROR_CHECK(value, value, 0, UINT32_MAX); JSAPIFastBuffer::AllocateFastBuffer(thread, bufferObj, GetValueUInt32(value)); } else if (value->IsString()) { - if (byteOffsetOrEncoding->IsString() && !IsValidEncoding(thread, byteOffsetOrEncoding)) { - JSTaggedValue error = ContainerError::BusinessError( - thread, ErrorFlag::TYPE_ERROR, - "Parameter error. The type of \"encoding\" must be BufferEncoding. the encoding code is unknown"); - THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); + if (!byteOffsetOrEncoding->IsString()) { + JSAPIFastBuffer::FromString(thread, bufferObj, value); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + return bufferObj.GetTaggedValue(); } JSAPIFastBuffer::FromString(thread, bufferObj, value, byteOffsetOrEncoding); } else if (value->IsJSAPIBuffer()) { if (byteOffsetOrEncoding->IsNumber() && length->IsNumber()) { - // share memory with another buffer(eg: create from pool) + // share memory with another buffer(create from pool) JSAPIFastBuffer::AllocateFromBufferObject(thread, bufferObj, value, GetValueUInt32(length), GetValueUInt32(byteOffsetOrEncoding)); } else { @@ -142,6 +140,10 @@ JSTaggedValue ContainersBuffer::BufferConstructor(EcmaRuntimeCallInfo *argv) JSAPIFastBuffer::Copy(thread, bufferHandle, value, 0, 0, bufferLength); } } else if (value->IsArrayBuffer() || value->IsSharedArrayBuffer()) { + if (BuiltinsArrayBuffer::IsDetachedBuffer(thread, value.GetTaggedValue())) { + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::ARRAY_BUFFER_IS_NULL_OR_DETACHED, + "The underlying ArrayBuffer is null or detached."); + } uint32_t index = 0; uint32_t byteLength = JSHandle(value)->GetArrayBufferByteLength(); if (byteOffsetOrEncoding->IsNumber()) { @@ -159,7 +161,7 @@ JSTaggedValue ContainersBuffer::BufferConstructor(EcmaRuntimeCallInfo *argv) } else if (value->IsJSArray()) { JSAPIFastBuffer::CreateBufferFromArrayLike(thread, bufferObj, value); } - + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return bufferObj.GetTaggedValue(); } @@ -205,6 +207,10 @@ JSTaggedValue ContainersBuffer::Compare(EcmaRuntimeCallInfo *argv) CONTAINER_BUFFER_CHECK(Compare); auto value = GetCallArg(argv, 0); // 0 means the first arg CHECK_NULL_OR_UNDEFINED(value); + if (!value->IsJSAPIBuffer() && !value->IsTypedArray()) { + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::TYPE_ERROR, + "The type of \"target\" must be [FastBuffer, Uint8Array]."); + } auto src = JSHandle::Cast(self); uint32_t tStart = 0; uint32_t tEnd = (value->IsJSAPIBuffer() ? JSHandle::Cast(value)->GetLength() @@ -233,12 +239,6 @@ JSTaggedValue ContainersBuffer::Compare(EcmaRuntimeCallInfo *argv) RANGE_ERROR_CHECK(sourceEnd, sourceEnd, 0, srcLength); sEnd = GetValueUInt32(sourceEnd); } - if (sStart >= sEnd) { - return JSTaggedValue(tStart >= tEnd ? 0 : -1); - } - if (tStart >= tEnd) { - return JSTaggedValue(1); - } auto ret = JSAPIFastBuffer::Compare(thread, src, value, sStart, sEnd, tStart, tEnd); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return ret; @@ -253,6 +253,10 @@ JSTaggedValue ContainersBuffer::Equals(EcmaRuntimeCallInfo *argv) CONTAINER_BUFFER_CHECK(Equals); auto value = GetCallArg(argv, 0); // 0 means the first arg CHECK_NULL_OR_UNDEFINED(value); + if (!value->IsJSAPIBuffer() && !value->IsTypedArray()) { + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::TYPE_ERROR, + "The type of \"target\" must be [FastBuffer, Uint8Array]."); + } auto src = JSHandle::Cast(self); uint32_t tEnd; if (value->IsJSAPIBuffer()) { @@ -279,6 +283,10 @@ JSTaggedValue ContainersBuffer::IndexOf(EcmaRuntimeCallInfo *argv) JSHandle value = GetCallArg(argv, 0); // 0 means the first arg JSHandle offset = GetCallArg(argv, 1); // 1 means the second arg CHECK_NULL_OR_UNDEFINED(value); + if (!value->IsString() && !value->IsJSAPIBuffer() && !value->IsTypedArray() && !value->IsNumber()) { + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::TYPE_ERROR, + "The type of \"value\" must be [string, FastBuffer, Uint8Array, number]."); + } int32_t offsetIndex = 0; int32_t length = static_cast(buffer->GetLength()); if (offset->IsNumber()) { @@ -297,10 +305,8 @@ JSTaggedValue ContainersBuffer::IndexOf(EcmaRuntimeCallInfo *argv) JSAPIFastBuffer::EncodingType encodingType = JSAPIFastBuffer::UTF8; if (encoding->IsString()) { if (!IsValidEncoding(thread, encoding)) { - JSTaggedValue error = ContainerError::BusinessError( - thread, ErrorFlag::TYPE_ERROR, + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::TYPE_ERROR, "Parameter error. The type of \"encoding\" must be BufferEncoding. the encoding code is unknown"); - THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } encodingType = JSAPIFastBuffer::GetEncodingType(JSAPIFastBuffer::GetString(thread, encoding)); } @@ -336,10 +342,8 @@ JSTaggedValue ContainersBuffer::Includes(EcmaRuntimeCallInfo *argv) JSAPIFastBuffer::EncodingType encodingType = JSAPIFastBuffer::UTF8; if (encoding->IsString()) { if (!IsValidEncoding(thread, encoding)) { - JSTaggedValue error = ContainerError::BusinessError( - thread, ErrorFlag::TYPE_ERROR, + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::TYPE_ERROR, "Parameter error. The type of \"encoding\" must be BufferEncoding. the encoding code is unknown"); - THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } encodingType = JSAPIFastBuffer::GetEncodingType(JSAPIFastBuffer::GetString(thread, encoding)); } @@ -356,6 +360,10 @@ JSTaggedValue ContainersBuffer::LastIndexOf(EcmaRuntimeCallInfo *argv) JSHandle buffer = JSHandle::Cast(self); JSHandle value = GetCallArg(argv, 0); // 0 means the first arg CHECK_NULL_OR_UNDEFINED(value); + if (!value->IsString() && !value->IsJSAPIBuffer() && !value->IsTypedArray() && !value->IsNumber()) { + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::TYPE_ERROR, + "The type of \"value\" must be [string, FastBuffer, Uint8Array, number]."); + } JSHandle offset = GetCallArg(argv, 1); // 1 means the second arg int64_t length = static_cast(buffer->GetLength()); int64_t offsetIndex = length - 1; @@ -376,10 +384,8 @@ JSTaggedValue ContainersBuffer::LastIndexOf(EcmaRuntimeCallInfo *argv) JSAPIFastBuffer::EncodingType encodingType = JSAPIFastBuffer::UTF8; if (encoding->IsString()) { if (!IsValidEncoding(thread, encoding)) { - JSTaggedValue error = ContainerError::BusinessError( - thread, ErrorFlag::TYPE_ERROR, + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::TYPE_ERROR, "Parameter error. The type of \"encoding\" must be BufferEncoding. the encoding code is unknown"); - THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } encodingType = JSAPIFastBuffer::GetEncodingType(JSAPIFastBuffer::GetString(thread, encoding)); } @@ -427,19 +433,21 @@ JSTaggedValue ContainersBuffer::Fill(EcmaRuntimeCallInfo *argv) [[maybe_unused]] EcmaHandleScope handleScope(thread); CONTAINER_BUFFER_CHECK(Fill); JSHandle buffer = JSHandle::Cast(self); + JSHandle value = GetCallArg(argv, 0); // 0 means the first arg uint32_t length = buffer->GetLength(); - if (length == 0) { + if (length == 0 || value->IsUndefinedOrNull()) { return buffer.GetTaggedValue(); } - JSHandle value = GetCallArg(argv, 0); // 0 means the first arg + if (!value->IsString() && !value->IsJSAPIBuffer() && !value->IsTypedArray() && !value->IsNumber()) { + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::TYPE_ERROR, + "The type of \"value\" must be [string, FastBuffer, Uint8Array, number]."); + } JSHandle start = GetCallArg(argv, 1); // 1 means the second arg if (start->IsString()) { JSAPIFastBuffer::EncodingType encodingType = JSAPIFastBuffer::UTF8; if (!IsValidEncoding(thread, start)) { - JSTaggedValue error = ContainerError::BusinessError( - thread, ErrorFlag::TYPE_ERROR, + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::TYPE_ERROR, "Parameter error. The type of \"encoding\" must be BufferEncoding. the encoding code is unknown"); - THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } encodingType = JSAPIFastBuffer::GetEncodingType(JSAPIFastBuffer::GetString(thread, start)); return JSAPIFastBuffer::Fill(thread, buffer, value, encodingType, 0, length); @@ -462,10 +470,8 @@ JSTaggedValue ContainersBuffer::Fill(EcmaRuntimeCallInfo *argv) JSAPIFastBuffer::EncodingType encodingType = JSAPIFastBuffer::UTF8; if (encoding->IsString()) { if (!IsValidEncoding(thread, encoding)) { - JSTaggedValue error = ContainerError::BusinessError( - thread, ErrorFlag::TYPE_ERROR, + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::TYPE_ERROR, "Parameter error. The type of \"encoding\" must be BufferEncoding. the encoding code is unknown"); - THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } encodingType = JSAPIFastBuffer::GetEncodingType(JSAPIFastBuffer::GetString(thread, encoding)); } @@ -491,10 +497,8 @@ JSTaggedValue ContainersBuffer::Write(EcmaRuntimeCallInfo *argv) } if (secondArg->IsString()) { if (!IsValidEncoding(thread, secondArg)) { - JSTaggedValue error = ContainerError::BusinessError( - thread, ErrorFlag::TYPE_ERROR, + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::TYPE_ERROR, "Parameter error. The type of \"encoding\" must be BufferEncoding. the encoding code is unknown"); - THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } encodingType = JSAPIFastBuffer::GetEncodingType(JSAPIFastBuffer::GetString(thread, secondArg)); return JSAPIFastBuffer::WriteString(thread, buffer, firstArg, 0, buffer->GetLength(), encodingType); @@ -513,10 +517,8 @@ JSTaggedValue ContainersBuffer::Write(EcmaRuntimeCallInfo *argv) JSHandle encoding = GetCallArg(argv, 3); // 3 means the fourth arg if (encoding->IsString()) { if (!IsValidEncoding(thread, encoding)) { - JSTaggedValue error = ContainerError::BusinessError( - thread, ErrorFlag::TYPE_ERROR, + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::TYPE_ERROR, "Parameter error. The type of \"encoding\" must be BufferEncoding. the encoding code is unknown"); - THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } encodingType = JSAPIFastBuffer::GetEncodingType(JSAPIFastBuffer::GetString(thread, encoding)); } @@ -539,10 +541,8 @@ JSTaggedValue ContainersBuffer::ToString(EcmaRuntimeCallInfo *argv) JSAPIFastBuffer::EncodingType encodingType = JSAPIFastBuffer::UTF8; if (firstArg->IsString()) { if (!IsValidEncoding(thread, firstArg)) { - JSTaggedValue error = ContainerError::BusinessError( - thread, ErrorFlag::TYPE_ERROR, + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::TYPE_ERROR, "Parameter error. The type of \"encoding\" must be BufferEncoding. the encoding code is unknown"); - THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } encodingType = JSAPIFastBuffer::GetEncodingType(thread, firstArg); } @@ -580,6 +580,10 @@ JSTaggedValue ContainersBuffer::Copy(EcmaRuntimeCallInfo *argv) JSHandle src = JSHandle::Cast(self); JSHandle dst = GetCallArg(argv, 0); // 0 means the first arg CHECK_NULL_OR_UNDEFINED(dst); + if (!dst->IsJSAPIBuffer() && !dst->IsTypedArray()) { + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::TYPE_ERROR, + "The type of \"target\" must be [FastBuffer, Uint8Array]."); + } uint32_t srcLength = src->GetLength(); uint32_t dstLength = dst->IsJSAPIBuffer() ? JSHandle(dst)->GetLength() : JSHandle(dst)->GetArrayLength(); @@ -619,11 +623,10 @@ JSTaggedValue ContainersBuffer::WriteUIntBE(EcmaRuntimeCallInfo *argv) JSHandle offset = GetCallArg(argv, 1); // 1 means the second arg JSHandle byteLengthHandle = GetCallArg(argv, 2); // 2 means the third arg CHECK_NULL_OR_UNDEFINED(value); - if (!byteLengthHandle->IsNumber()) { - JSTaggedValue error = - ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, "The byteLength should be number."); - THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); + if (!value->IsNumber() || !byteLengthHandle->IsNumber()) { + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::TYPE_ERROR, "The parameter should be number."); } + RANGE_ERROR_CHECK(byteLengthHandle, byteLength, 0, buffer->GetLength()); uint32_t byteLength = GetValueUInt32(byteLengthHandle); uint32_t offsetIndex = 0; if (offset->IsNumber()) { @@ -646,11 +649,10 @@ JSTaggedValue ContainersBuffer::WriteUIntLE(EcmaRuntimeCallInfo *argv) JSHandle value = GetCallArg(argv, 0); // 0 means the first arg JSHandle offset = GetCallArg(argv, 1); // 1 means the second arg JSHandle byteLengthHandle = GetCallArg(argv, 2); // 2 means the third arg - if (!byteLengthHandle->IsNumber()) { - JSTaggedValue error = - ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, "The byteLength should be number."); - THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); + if (!value->IsNumber() || !byteLengthHandle->IsNumber()) { + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::TYPE_ERROR, "The parameter should be number."); } + RANGE_ERROR_CHECK(byteLengthHandle, byteLength, 0, buffer->GetLength()); uint32_t byteLength = GetValueUInt32(byteLengthHandle); CHECK_NULL_OR_UNDEFINED(value); uint32_t offsetIndex = 0; @@ -675,10 +677,9 @@ JSTaggedValue ContainersBuffer::ReadUIntBE(EcmaRuntimeCallInfo *argv) JSHandle byteLengthHandle = GetCallArg(argv, 1); // 1 means the second arg CHECK_NULL_OR_UNDEFINED(offset); if (!byteLengthHandle->IsNumber()) { - JSTaggedValue error = - ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, "The byteLength should be number."); - THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::TYPE_ERROR, "The byteLength should be number."); } + RANGE_ERROR_CHECK(byteLengthHandle, byteLength, 0, buffer->GetLength()); uint32_t byteLength = GetValueUInt32(byteLengthHandle); uint32_t offsetIndex = 0; if (offset->IsNumber()) { @@ -702,10 +703,9 @@ JSTaggedValue ContainersBuffer::ReadUIntLE(EcmaRuntimeCallInfo *argv) JSHandle byteLengthHandle = GetCallArg(argv, 1); // 1 means the second arg CHECK_NULL_OR_UNDEFINED(offset); if (!byteLengthHandle->IsNumber()) { - JSTaggedValue error = - ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, "The byteLength should be number."); - THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::TYPE_ERROR, "The byteLength should be number."); } + RANGE_ERROR_CHECK(byteLengthHandle, byteLength, 0, buffer->GetLength()); uint32_t byteLength = GetValueUInt32(byteLengthHandle); uint32_t offsetIndex = 0; if (offset->IsNumber()) { @@ -730,11 +730,10 @@ JSTaggedValue ContainersBuffer::WriteIntBE(EcmaRuntimeCallInfo *argv) JSHandle offset = GetCallArg(argv, 1); // 1 means the second arg JSHandle byteLengthHandle = GetCallArg(argv, 2); // 2 means the third arg CHECK_NULL_OR_UNDEFINED(value); - if (!byteLengthHandle->IsNumber()) { - JSTaggedValue error = - ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, "The byteLength should be number."); - THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); + if (!value->IsNumber() || !byteLengthHandle->IsNumber()) { + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::TYPE_ERROR, "The parameter should be number."); } + RANGE_ERROR_CHECK(byteLengthHandle, byteLength, 0, buffer->GetLength()); uint32_t byteLength = GetValueUInt32(byteLengthHandle); uint32_t offsetIndex = 0; if (offset->IsNumber()) { @@ -758,11 +757,10 @@ JSTaggedValue ContainersBuffer::WriteIntLE(EcmaRuntimeCallInfo *argv) JSHandle offset = GetCallArg(argv, 1); // 1 means the second arg JSHandle byteLengthHandle = GetCallArg(argv, 2); // 2 means the third arg CHECK_NULL_OR_UNDEFINED(value); - if (!byteLengthHandle->IsNumber()) { - JSTaggedValue error = - ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, "The byteLength should be number."); - THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); + if (!value->IsNumber() || !byteLengthHandle->IsNumber()) { + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::TYPE_ERROR, "The parameter should be number."); } + RANGE_ERROR_CHECK(byteLengthHandle, byteLength, 0, buffer->GetLength()); uint32_t byteLength = GetValueUInt32(byteLengthHandle); uint32_t offsetIndex = 0; if (offset->IsNumber()) { @@ -786,10 +784,9 @@ JSTaggedValue ContainersBuffer::ReadIntBE(EcmaRuntimeCallInfo *argv) JSHandle byteLengthHandle = GetCallArg(argv, 1); // 1 means the second arg CHECK_NULL_OR_UNDEFINED(offset); if (!byteLengthHandle->IsNumber()) { - JSTaggedValue error = - ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, "The byteLength should be number."); - THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::TYPE_ERROR, "The byteLength should be number."); } + RANGE_ERROR_CHECK(byteLengthHandle, byteLength, 0, buffer->GetLength()); uint32_t byteLength = GetValueUInt32(byteLengthHandle); uint32_t offsetIndex = 0; if (offset->IsNumber()) { @@ -813,10 +810,9 @@ JSTaggedValue ContainersBuffer::ReadIntLE(EcmaRuntimeCallInfo *argv) JSHandle byteLengthHandle = GetCallArg(argv, 1); // 1 means the second arg CHECK_NULL_OR_UNDEFINED(offset); if (!byteLengthHandle->IsNumber()) { - JSTaggedValue error = - ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, "The byteLength should be number."); - THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); + NEW_BUSINESS_ERROR_AND_THROW(thread, ErrorFlag::TYPE_ERROR, "The byteLength should be number."); } + RANGE_ERROR_CHECK(byteLengthHandle, byteLength, 0, buffer->GetLength()); uint32_t byteLength = GetValueUInt32(byteLengthHandle); uint32_t offsetIndex = 0; if (offset->IsNumber()) { diff --git a/ecmascript/containers/tests/containers_buffer_test.cpp b/ecmascript/containers/tests/containers_buffer_test.cpp index 5aacac3beab18258ed11c9b3d183e47a2484e6e6..de59ab5265da3d258f5a57814fdbb82a32128e96 100644 --- a/ecmascript/containers/tests/containers_buffer_test.cpp +++ b/ecmascript/containers/tests/containers_buffer_test.cpp @@ -83,10 +83,9 @@ protected: { JSHandle newTarget(thread, InitializeBufferConstructor()); auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), - ContainersBufferTest::GetArgvCount(4)); + ContainersBufferTest::GetArgvCount(3)); objCallInfo->SetFunction(newTarget.GetTaggedValue()); objCallInfo->SetNewTarget(newTarget.GetTaggedValue()); - objCallInfo->SetThis(JSTaggedValue::Undefined()); objCallInfo->SetCallArg(0, JSTaggedValue(length)); [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo); JSTaggedValue result = ContainersBuffer::BufferConstructor(objCallInfo); @@ -101,12 +100,13 @@ HWTEST_F_L0(ContainersBufferTest, BufferConstructor) InitializeBufferConstructor(); JSHandle newTarget(thread, InitializeBufferConstructor()); auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), - ContainersBufferTest::GetArgvCount(4)); + 6); objCallInfo->SetFunction(newTarget.GetTaggedValue()); objCallInfo->SetNewTarget(newTarget.GetTaggedValue()); - objCallInfo->SetThis(JSTaggedValue::Undefined()); objCallInfo->SetCallArg(0, JSTaggedValue(JSAPIFastBuffer::DEFAULT_CAPACITY_LENGTH)); + EXPECT_EQ(objCallInfo->GetArgsNumber(), 1); [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo); + EXPECT_EQ(objCallInfo->GetArgsNumber(), 1); JSTaggedValue result = ContainersBuffer::BufferConstructor(objCallInfo); TestHelper::TearDownFrame(thread, prev); ASSERT_TRUE(result.IsJSAPIBuffer()); @@ -715,7 +715,6 @@ HWTEST_F_L0(ContainersBufferTest, CreateFromArrayTest001) ContainersBufferTest::GetArgvCount(4)); objCallInfo->SetFunction(newTarget.GetTaggedValue()); objCallInfo->SetNewTarget(newTarget.GetTaggedValue()); - objCallInfo->SetThis(JSTaggedValue::Undefined()); objCallInfo->SetCallArg(0, arr.GetTaggedValue()); [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo); JSTaggedValue result = ContainersBuffer::BufferConstructor(objCallInfo); diff --git a/ecmascript/js_api/js_api_buffer.cpp b/ecmascript/js_api/js_api_buffer.cpp index 9226c7d5630538d43969cc38dde2b516175f19c6..9c0359065ea145ee9c2eb4fe32cf9d6b3bf888e3 100644 --- a/ecmascript/js_api/js_api_buffer.cpp +++ b/ecmascript/js_api/js_api_buffer.cpp @@ -201,7 +201,15 @@ JSHandle JSAPIFastBuffer::NewUint8Array(JSThread *thread, uint32_t factory->NewJSObjectByConstructor(JSHandle(handleTagValFunc), handleTagValFunc); DataViewType arrayType = DataViewType::UINT8; JSTypedArray::Cast(*obj)->SetTypedArrayName(thread, thread->GlobalConstants()->GetUint8ArrayString()); - TypedArrayHelper::AllocateTypedArrayBuffer(thread, obj, length, arrayType); + if (length > 0) { + TypedArrayHelper::AllocateTypedArrayBuffer(thread, obj, length, arrayType); + } else { + auto jsTypedArray = JSTypedArray::Cast(*obj); + jsTypedArray->SetContentType(ContentType::Number); + jsTypedArray->SetByteLength(0); + jsTypedArray->SetByteOffset(0); + jsTypedArray->SetArrayLength(0); + } return JSHandle(obj); } @@ -262,11 +270,7 @@ JSTaggedValue JSAPIFastBuffer::CreateBufferFromArrayLike(JSThread *thread, const JSTaggedValue JSAPIFastBuffer::FromArrayBuffer(JSThread *thread, const JSHandle &buffer, const JSHandle &src, uint32_t byteOffset, uint32_t length) { - if (BuiltinsArrayBuffer::IsDetachedBuffer(thread, src.GetTaggedValue())) { - JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::ARRAY_BUFFER_IS_NULL_OR_DETACHED, - "The underlying ArrayBuffer is null or detached."); - THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); - } + // src must be an arraybuffer without detached. auto srcBuffer = JSHandle(src); uint32_t srcLength = srcBuffer->GetArrayBufferByteLength(); if (srcLength <= byteOffset) { @@ -274,11 +278,12 @@ JSTaggedValue JSAPIFastBuffer::FromArrayBuffer(JSThread *thread, const JSHandle< "byteOffset must less than length."); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } - auto len = std::min(length, srcLength); - auto array = NewUint8Array(thread, len); + auto len = std::min(length, srcLength - byteOffset); + auto array = NewUint8Array(thread, 0); array->SetViewedArrayBufferOrByteArray(thread, srcBuffer); array->SetByteLength(len); array->SetArrayLength(len); + array->SetByteOffset(byteOffset); buffer->SetFastBufferData(thread, array); buffer->SetLength(len); buffer->SetOffset(byteOffset); @@ -448,10 +453,15 @@ string JSAPIFastBuffer::GetString(JSThread *thread, const JSHandle &buffer, const JSHandle &str, const JSHandle &encoding) { - if (encoding->IsUndefined() || encoding->IsNull()) { + if (encoding->IsUndefinedOrNull()) { return FromString(thread, buffer, str); } - EncodingType encodingType = GetEncodingType(thread, encoding); + EncodingType encodingType; + if (!encoding->IsString() || (encodingType = GetEncodingType(thread, encoding)) == EncodingType::INVALID) { + JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, + "Parameter error. The type of \"encoding\" must be BufferEncoding. the encoding code is unknown"); + THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); + } return FromString(thread, buffer, str, encodingType); } @@ -612,10 +622,11 @@ JSTaggedValue JSAPIFastBuffer::AllocateFromBufferObject(JSThread *thread, const const JSHandle &src, uint32_t byteLength, uint32_t byteOffset) { - auto handleUint8Array = JSTaggedValue(GetUInt8ArrayFromBufferObject(thread, src)); - buffer->SetFastBufferData(thread, handleUint8Array); - buffer->SetLength(byteLength); - buffer->SetOffset(byteOffset); + auto uint8Array = GetUInt8ArrayFromBufferObject(thread, src); + uint32_t maxLength = std::min(uint8Array->GetByteLength(), byteLength); + buffer->SetFastBufferData(thread, JSTaggedValue(uint8Array)); + buffer->SetLength(maxLength); + buffer->SetOffset(std::min(maxLength, byteOffset)); return buffer.GetTaggedValue(); } @@ -736,6 +747,12 @@ JSTaggedValue JSAPIFastBuffer::Fill(JSThread *thread, JSHandle JSTaggedValue JSAPIFastBuffer::Compare(JSThread *thread, JSHandle &a, JSHandle &bObj, uint32_t sStart, uint32_t sEnd, uint32_t tStart, uint32_t tEnd) { + if (sStart >= sEnd) { + return JSTaggedValue(tStart >= tEnd ? 0 : -1); + } + if (tStart >= tEnd) { + return JSTaggedValue(1); + } JSTypedArray *typedArrayA = GetUInt8ArrayFromBufferObject(thread, a.GetTaggedValue()); JSTypedArray *typedArrayB = GetUInt8ArrayFromBufferObject(thread, bObj); uint32_t aCmpLength = sEnd - sStart; diff --git a/ecmascript/js_api/js_api_lightweightset.cpp b/ecmascript/js_api/js_api_lightweightset.cpp index ca89ccf0334c258185b64a958aa1f9b2da5d3846..e57c99de6e559fe884ca0e5db9152b4b2a0fc11a 100644 --- a/ecmascript/js_api/js_api_lightweightset.cpp +++ b/ecmascript/js_api/js_api_lightweightset.cpp @@ -164,8 +164,8 @@ void JSAPILightWeightSet::SizeCopy(const JSThread *thread, const JSHandleGetEcmaVM()->GetFactory()->CopyArray(hashArray, capacity, newCapacity); valueArray = thread->GetEcmaVM()->GetFactory()->CopyArray(valueArray, capacity, newCapacity); - obj->SetValues(thread, hashArray); - obj->SetHashes(thread, valueArray); + obj->SetValues(thread, valueArray); + obj->SetHashes(thread, hashArray); } bool JSAPILightWeightSet::IsEmpty() @@ -301,10 +301,15 @@ void JSAPILightWeightSet::IncreaseCapacityTo(JSThread *thread, const JSHandle hashArray(thread, obj->GetHashes(thread)); + JSHandle valueArray(thread, obj->GetValues(thread)); JSHandle newElements = thread->GetEcmaVM()->GetFactory()->NewAndCopyTaggedArray(hashArray, static_cast(minCapacity), capacity); + JSHandle newValues = + thread->GetEcmaVM()->GetFactory()->NewAndCopyTaggedArray(valueArray, + static_cast(minCapacity), capacity); obj->SetHashes(thread, newElements); + obj->SetValues(thread, newValues); } JSHandle JSAPILightWeightSet::GetIteratorObj(JSThread *thread, const JSHandle &obj, diff --git a/ecmascript/js_api/js_api_plain_array.cpp b/ecmascript/js_api/js_api_plain_array.cpp index e8d67752966828568e4e3648d330697fd8a46685..b42f0440b868057ed089705014f2d03199109f46 100644 --- a/ecmascript/js_api/js_api_plain_array.cpp +++ b/ecmascript/js_api/js_api_plain_array.cpp @@ -42,7 +42,7 @@ void JSAPIPlainArray::Add(JSThread *thread, const JSHandle &obj } uint32_t capacity = valueArray->GetLength(); if (size + 1 >= capacity) { - uint32_t newCapacity = capacity << 1U; + uint32_t newCapacity = std::max(uint32_t(DEFAULT_CAPACITY_LENGTH), capacity << 1U); keyArray = thread->GetEcmaVM()->GetFactory()->CopyArray(keyArray, capacity, newCapacity); valueArray =