diff --git a/frameworks/native_engine/jsi/jsi.cpp b/frameworks/native_engine/jsi/jsi.cpp index 54a71591f8e2f8e94206b5bc6609b6777b67caed..b0a38344a54bdc74b5e5d204b446a085a01f6048 100644 --- a/frameworks/native_engine/jsi/jsi.cpp +++ b/frameworks/native_engine/jsi/jsi.cpp @@ -1171,5 +1171,33 @@ void JSI::SuccessCallback(const JSIValue thisVal, const JSIValue args, const JSI CallFunction(complete, thisVal, nullptr, 0); ReleaseValueList(success, complete); } + +JSIValue JSI::CreateErrorWithCode(uint32_t errCode, + const char * const errMsg, + const JSIValue extraErrData) +{ + if (errMsg == nullptr) { + HILOG_ERROR(HILOG_MODULE_ACE, "JSI:CreateErrorWithCode parameters invalid!"); + return CreateUndefined(); + } + const size_t maxErrMsgLength = 256; + if (strlen(errMsg) > maxErrMsgLength) { + HILOG_ERROR(HILOG_MODULE_ACE, "JSI:CreateErrorWithCode error message too long!"); + return CreateUndefined(); + } +#if (ENABLE_JERRY == 1) + JSIValue errObj = CreateObject(); + SetNumberProperty(errObj, "code", errCode); + SetStringProperty(errObj, "message", errMsg); + if (extraErrData != 0 && ValueIsObject(extraErrData)) { + SetNamedProperty(errObj, "data", extraErrData); + } + jerry_value_t errRef = jerry_create_error_from_value(AS_JERRY_VALUE(errObj), true); + return AS_JSI_VALUE(errRef); +#else + HILOG_ERROR(HILOG_MODULE_ACE, "JSI:CreateErrorWithCode has not been implemented in this js engine!"); + return CreateUndefined(); +#endif +} } // namespace ACELite } // namespace OHOS diff --git a/frameworks/native_engine/jsi/test/unittest/common/jsi_interface_tdd_test.cpp b/frameworks/native_engine/jsi/test/unittest/common/jsi_interface_tdd_test.cpp index 262f94ff46741025c3528648cf2df5fd94cf97b8..4571b3d4ebf609078920f345c2a5a4fdcf77505c 100644 --- a/frameworks/native_engine/jsi/test/unittest/common/jsi_interface_tdd_test.cpp +++ b/frameworks/native_engine/jsi/test/unittest/common/jsi_interface_tdd_test.cpp @@ -14,13 +14,18 @@ */ #include "jsi_interface_tdd_test.h" -#include -#include #include "acelite_config.h" +#include "jerryscript-core.h" #include "js_debugger_config.h" +#include "jsi_types.h" +#include +#include namespace OHOS { namespace ACELite { +#define TO_JERRY_VALUE(a) ((jerry_value_t)(uintptr_t)(a)) +#define TO_JSI_VALUE(a) ((JSIValue)(uintptr_t)(a)) + static int8_t g_descValue = 0; JsiInterfaceTddTest::JsiInterfaceTddTest() {} @@ -39,12 +44,17 @@ void JsiInterfaceTddTest::TearDown() JSIValue JsiInterfaceTddTest::Function(const JSIValue thisVal, const JSIValue args[], uint8_t argsNum) { + (void)thisVal; + (void)args; + (void)argsNum; printf("Function called\n"); return JSI::CreateUndefined(); } JSIValue JsiInterfaceTddTest::Setter(const JSIValue thisVal, const JSIValue args[], uint8_t argsNum) { + (void)thisVal; + (void)argsNum; double newValue = JSI::ValueToNumber(args[0]); g_descValue = (int8_t)newValue; @@ -54,6 +64,9 @@ JSIValue JsiInterfaceTddTest::Setter(const JSIValue thisVal, const JSIValue args JSIValue JsiInterfaceTddTest::Getter(const JSIValue thisVal, const JSIValue args[], uint8_t argsNum) { + (void)thisVal; + (void)args; + (void)argsNum; g_descValue++; printf("Getter called, returning: %d\n", g_descValue); return JSI::CreateNumber(g_descValue); @@ -1086,6 +1099,250 @@ void JsiInterfaceTddTest::JSIInterfaceTest029() TDD_CASE_END(); } +void JsiInterfaceTddTest::JSIInterfaceTest030() +{ + TDD_CASE_BEGIN(); + /** + * @tc.steps: step1. try to create one error with null msg + */ + JSIValue errRef = JSI::CreateErrorWithCode(JSI_ERR_CODE_PERMISSION_DENIED, nullptr); + /** + * @tc.expected: step1. errRef = undefined + */ + JSIValue undefinedValue = JSI::CreateUndefined(); + if (errRef == undefinedValue) { + printf("JSIInterfaceTest030 pass\n"); + } else { + printf("JSIInterfaceTest030 fail\n"); + } + EXPECT_TRUE(errRef == undefinedValue); + JSI::ReleaseValue(errRef); + TDD_CASE_END(); +} + +void JsiInterfaceTddTest::JSIInterfaceTest031() +{ + TDD_CASE_BEGIN(); + /** + * @tc.steps: step1. try to create one error with valid msg + */ + JSIValue errRef = JSI::CreateErrorWithCode(0, "this is error message"); + /** + * @tc.expected: step1. errRef is valid + */ + if (JSI::ValueIsError(errRef)) { + printf("JSIInterfaceTest031 pass\n"); + } else { + printf("JSIInterfaceTest031 fail\n"); + } + EXPECT_TRUE(JSI::ValueIsError(errRef)); + JSI::ReleaseValue(errRef); + TDD_CASE_END(); +} + +void JsiInterfaceTddTest::JSIInterfaceTest032() +{ + TDD_CASE_BEGIN(); + /** + * @tc.steps: step1. try to create one error with very long msg which is over 256 + */ + const char *veryLongMessage = + "this is one very long test message which is used to check if the length can be verified by the function, this " + "is one very long test message which is used to check if the length can be verified by the function, this is " + "one very long test message which is used to check if the length can be verified by the function."; + JSIValue errRef = JSI::CreateErrorWithCode(JSI_ERR_CODE_NOT_SUPPORTED, veryLongMessage); + /** + * @tc.expected: step1. errRef = undefined + */ + JSIValue undefValue = JSI::CreateUndefined(); + if (errRef == undefValue) { + printf("JSIInterfaceTest032 pass\n"); + } else { + printf("JSIInterfaceTest032 fail\n"); + } + EXPECT_TRUE(errRef == undefValue); + JSI::ReleaseValue(errRef); + TDD_CASE_END(); +} + +void JsiInterfaceTddTest::JSIInterfaceTest033() +{ + TDD_CASE_BEGIN(); + /** + * @tc.steps: step1. try to create one error with empty string + */ + JSIValue errResult = JSI::CreateErrorWithCode(JSI_ERR_CODE_PARAM_CHECK_FAILED, ""); + /** + * @tc.expected: step1. errRef is valid + */ + if (JSI::ValueIsError(errResult)) { + printf("JSIInterfaceTest033 pass\n"); + } else { + printf("JSIInterfaceTest033 fail\n"); + } + EXPECT_TRUE(JSI::ValueIsError(errResult)); + JSI::ReleaseValue(errResult); + TDD_CASE_END(); +} + +void JsiInterfaceTddTest::JSIInterfaceTest034() +{ + TDD_CASE_BEGIN(); + /** + * @tc.steps: step1. try to create one error with extra data + */ + JSIValue extraData = JSI::CreateObject(); + JSIValue errRef = JSI::CreateErrorWithCode(JSI_ERR_CODE_NOT_SUPPORTED, "error info", extraData); + /** + * @tc.expected: step1. errRef is valid + */ + bool result = JSI::ValueIsError(errRef); + if (result) { + printf("JSIInterfaceTest034 pass\n"); + } else { + printf("JSIInterfaceTest034 fail\n"); + } + EXPECT_TRUE(result); + JSI::ReleaseValue(extraData); + JSI::ReleaseValue(errRef); + TDD_CASE_END(); +} + +void JsiInterfaceTddTest::JSIInterfaceTest035() +{ + TDD_CASE_BEGIN(); + /** + * @tc.steps: step1. try to create one error with extra data + */ + JSIValue extraData = JSI::CreateObject(); + JSI::SetStringProperty(extraData, "info", "message"); + const char *errMsg = "method is not support"; + JSIValue errRef = JSI::CreateErrorWithCode(JSI_ERR_CODE_NOT_SUPPORTED, errMsg, extraData); + /** + * @tc.expected: step1. errRef is valid + */ + JSIValue resultExtracted = TO_JSI_VALUE(jerry_get_value_from_error(TO_JERRY_VALUE(errRef), false)); + bool result = JSI::ValueIsObject(resultExtracted); + if (result) { + result = (JSI::GetNumberProperty(resultExtracted, "code") == JSI_ERR_CODE_NOT_SUPPORTED); + } + if (result) { + printf("JSIInterfaceTest035 pass\n"); + } else { + printf("JSIInterfaceTest035 fail\n"); + } + EXPECT_TRUE(result); + JSI::ReleaseValue(resultExtracted); + JSI::ReleaseValue(extraData); + JSI::ReleaseValue(errRef); + TDD_CASE_END(); +} + +void JsiInterfaceTddTest::JSIInterfaceTest036() +{ + TDD_CASE_BEGIN(); + /** + * @tc.steps: step1. try to create one error with extra data + */ + JSIValue extraData = JSI::CreateObject(); + JSI::SetStringProperty(extraData, "test", "info"); + const char *errMsgContent = "check failed"; + JSIValue errRef = JSI::CreateErrorWithCode(JSI_ERR_CODE_PARAM_CHECK_FAILED, errMsgContent, extraData); + + /** + * @tc.expected: step1. errRef is valid + */ + JSIValue extractedValue = TO_JSI_VALUE(jerry_get_value_from_error(TO_JERRY_VALUE(errRef), false)); + bool msgCheckResult = JSI::ValueIsObject(extractedValue); + if (msgCheckResult) { + char *messageStr = JSI::GetStringProperty(extractedValue, "message"); + msgCheckResult = (messageStr != nullptr && strcmp(messageStr, errMsgContent) == 0); + } + if (msgCheckResult) { + printf("JSIInterfaceTest036 pass\n"); + } else { + printf("JSIInterfaceTest036 fail\n"); + } + EXPECT_TRUE(msgCheckResult); + // clean up + JSI::ReleaseValue(extractedValue); + JSI::ReleaseValue(extraData); + JSI::ReleaseValue(errRef); + TDD_CASE_END(); +} + +void JsiInterfaceTddTest::JSIInterfaceTest037() +{ + TDD_CASE_BEGIN(); + /** + * @tc.steps: step1. try to create one error with extra data + */ + JSIValue extraDataObject = JSI::CreateObject(); + const char *propertyKey = "dataKey"; + JSI::SetStringProperty(extraDataObject, propertyKey, "result"); + const char *notSupportedMsg = "not supported"; + JSIValue errRefToBeCheck = JSI::CreateErrorWithCode(JSI_ERR_CODE_NOT_SUPPORTED, notSupportedMsg, extraDataObject); + + /** + * @tc.expected: step1. errRef is valid, check data property + */ + JSIValue extractV = TO_JSI_VALUE(jerry_get_value_from_error(TO_JERRY_VALUE(errRefToBeCheck), false)); + bool dataCheckResult = JSI::ValueIsObject(extractV); + if (dataCheckResult) { + JSIValue dataPropertyValue = JSI::GetNamedProperty(extractV, "data"); + dataCheckResult = JSI::ValueIsObject(dataPropertyValue); + char *dataValue = JSI::GetStringProperty(dataPropertyValue, propertyKey); + if (dataValue != nullptr && strcmp(dataValue, propertyKey) == 0) { + dataCheckResult = true; + } + JSI::ReleaseValue(dataPropertyValue); + } + if (dataCheckResult) { + printf("JSIInterfaceTest037 pass\n"); + } else { + printf("JSIInterfaceTest037 fail\n"); + } + EXPECT_TRUE(dataCheckResult); + // clean up + JSI::ReleaseValue(extractV); + JSI::ReleaseValue(extraDataObject); + JSI::ReleaseValue(errRefToBeCheck); + TDD_CASE_END(); +} + +void JsiInterfaceTddTest::JSIInterfaceTest038() +{ + TDD_CASE_BEGIN(); + /** + * @tc.steps: step1. try to create one error with invalid extra data + */ + JSIValue functionValue = JSI::CreateFunction(Function); // not obj type + const char *errorInfo = "not supported"; + JSIValue errResult = JSI::CreateErrorWithCode(JSI_ERR_CODE_NOT_SUPPORTED, errorInfo, functionValue); + + /** + * @tc.expected: step1. errRef is valid, check data property + */ + JSIValue extractedVal = TO_JSI_VALUE(jerry_get_value_from_error(TO_JERRY_VALUE(errResult), false)); + bool dataCheckRes = JSI::ValueIsObject(extractedVal); + if (dataCheckRes) { + JSIValue dataPropertyValue = JSI::GetNamedProperty(extractedVal, "data"); + dataCheckRes = JSI::ValueIsUndefined(dataPropertyValue); + JSI::ReleaseValue(dataPropertyValue); + } + if (!dataCheckRes) { + printf("JSIInterfaceTest038 pass\n"); + } else { + printf("JSIInterfaceTest038 fail\n"); + } + EXPECT_FALSE(dataCheckRes); + // clean up + JSI::ReleaseValue(extractedVal); + JSI::ReleaseValue(functionValue); + JSI::ReleaseValue(errResult); + TDD_CASE_END(); +} + void JsiInterfaceTddTest::RunTests() { JSIInterfaceTest001(); @@ -1121,6 +1378,15 @@ void JsiInterfaceTddTest::RunTests() JSIInterfaceTest027(); JSIInterfaceTest028(); JSIInterfaceTest029(); + JSIInterfaceTest030(); + JSIInterfaceTest031(); + JSIInterfaceTest032(); + JSIInterfaceTest033(); + JSIInterfaceTest034(); + JSIInterfaceTest035(); + JSIInterfaceTest036(); + JSIInterfaceTest037(); + JSIInterfaceTest038(); } #ifdef TDD_ASSERTIONS @@ -1394,6 +1660,96 @@ HWTEST_F(JsiInterfaceTddTest, test029, TestSize.Level0) { JsiInterfaceTddTest::JSIInterfaceTest029(); } + +/** + * @tc.name: JSIInterfaceTest030 + * @tc.desc: Verify JSI create error function. + * @tc.require: I5TIPU + */ +HWTEST_F(JsiInterfaceTddTest, test030, TestSize.Level0) +{ + JsiInterfaceTddTest::JSIInterfaceTest030(); +} + +/** + * @tc.name: JSIInterfaceTest031 + * @tc.desc: Verify JSI create error function. + * @tc.require: I5TIPU + */ +HWTEST_F(JsiInterfaceTddTest, test031, TestSize.Level0) +{ + JsiInterfaceTddTest::JSIInterfaceTest031(); +} + +/** + * @tc.name: JSIInterfaceTest032 + * @tc.desc: Verify JSI create error function. + * @tc.require: I5TIPU + */ +HWTEST_F(JsiInterfaceTddTest, test032, TestSize.Level0) +{ + JsiInterfaceTddTest::JSIInterfaceTest032(); +} + +/** + * @tc.name: JSIInterfaceTest033 + * @tc.desc: Verify JSI create error function. + * @tc.require: I5TIPU + */ +HWTEST_F(JsiInterfaceTddTest, test033, TestSize.Level0) +{ + JsiInterfaceTddTest::JSIInterfaceTest033(); +} + +/** + * @tc.name: JSIInterfaceTest034 + * @tc.desc: Verify JSI create error function. + * @tc.require: I5TIPU + */ +HWTEST_F(JsiInterfaceTddTest, test034, TestSize.Level0) +{ + JsiInterfaceTddTest::JSIInterfaceTest034(); +} + +/** + * @tc.name: JSIInterfaceTest035 + * @tc.desc: Verify JSI create error function. + * @tc.require: I5TIPU + */ +HWTEST_F(JsiInterfaceTddTest, test035, TestSize.Level0) +{ + JsiInterfaceTddTest::JSIInterfaceTest035(); +} + +/** + * @tc.name: JSIInterfaceTest036 + * @tc.desc: Verify JSI create error function. + * @tc.require: I5TIPU + */ +HWTEST_F(JsiInterfaceTddTest, test036, TestSize.Level0) +{ + JsiInterfaceTddTest::JSIInterfaceTest036(); +} + +/** + * @tc.name: JSIInterfaceTest037 + * @tc.desc: Verify JSI create error function. + * @tc.require: I5TIPU + */ +HWTEST_F(JsiInterfaceTddTest, test037, TestSize.Level0) +{ + JsiInterfaceTddTest::JSIInterfaceTest037(); +} + +/** + * @tc.name: JSIInterfaceTest038 + * @tc.desc: Verify JSI create error function. + * @tc.require: I5TIPU + */ +HWTEST_F(JsiInterfaceTddTest, test038, TestSize.Level0) +{ + JsiInterfaceTddTest::JSIInterfaceTest038(); +} #endif } // namespace ACELite } // namespace OHOS diff --git a/frameworks/native_engine/jsi/test/unittest/common/jsi_interface_tdd_test.h b/frameworks/native_engine/jsi/test/unittest/common/jsi_interface_tdd_test.h index 43e310d8e0b49641a0788709c04367ce609fad23..ffbd21940ba9252b47b9de2b405263caf5075f22 100644 --- a/frameworks/native_engine/jsi/test/unittest/common/jsi_interface_tdd_test.h +++ b/frameworks/native_engine/jsi/test/unittest/common/jsi_interface_tdd_test.h @@ -79,6 +79,15 @@ public: void JSIInterfaceTest027(); void JSIInterfaceTest028(); void JSIInterfaceTest029(); + void JSIInterfaceTest030(); + void JSIInterfaceTest031(); + void JSIInterfaceTest032(); + void JSIInterfaceTest033(); + void JSIInterfaceTest034(); + void JSIInterfaceTest035(); + void JSIInterfaceTest036(); + void JSIInterfaceTest037(); + void JSIInterfaceTest038(); void RunTests(); }; } // namespace ACELite diff --git a/interfaces/inner_api/builtin/jsi/jsi.h b/interfaces/inner_api/builtin/jsi/jsi.h index aa4a962658e8d9e2033917da25fbf14998649085..30eed2273004b1c4a296b60754eb4a807f81c63e 100644 --- a/interfaces/inner_api/builtin/jsi/jsi.h +++ b/interfaces/inner_api/builtin/jsi/jsi.h @@ -748,6 +748,28 @@ public: */ static void SuccessCallback(const JSIValue thisVal, const JSIValue args, const JSIValue *argv, uint8_t argc); + /** + * @brief Create javascript error object with error code and error message. + * This interface can be used to create one uniform error object, which can be throw to JS API caller, + * The error object's structure is shown as following, + * { + * code: 100001, // the error code + * message: "error details" // the error message + * data: {} // more error info, this is optional + * } + * + * @param [in] errCode: the error code which can indicate + * @param [in] errorMsg: value of 'message' property of constructed error object + * @param [in] extraErrData: value of 'data' property of constructed error object, which is optional, + * if it's given by caller, it must be one object, and it should be released by caller itself + * @return value of the constructed error object + * + * value returned should be released by caller with ReleaseValue when it won't be used any more + */ + static JSIValue CreateErrorWithCode(uint32_t errCode, + const char * const errMsg, + const JSIValue extraErrData = 0); + private: // private constructor for singleton instance JSI() {} diff --git a/interfaces/inner_api/builtin/jsi/jsi_types.h b/interfaces/inner_api/builtin/jsi/jsi_types.h index 188c63b25830d930629914c6898c83c2944795e5..e201c85902765b8d15a92f7f90b1af34b9cf7ee1 100644 --- a/interfaces/inner_api/builtin/jsi/jsi_types.h +++ b/interfaces/inner_api/builtin/jsi/jsi_types.h @@ -64,6 +64,11 @@ constexpr uint8_t ARGC_THREE = 3; constexpr int8_t JSI_ERR_OK = 0; constexpr int8_t JSI_ERR_FAIL = -1; +// uniform error code for error throwing +constexpr uint32_t JSI_ERR_CODE_PERMISSION_DENIED = 201; +constexpr uint32_t JSI_ERR_CODE_PARAM_CHECK_FAILED = 401; +constexpr uint32_t JSI_ERR_CODE_NOT_SUPPORTED = 801; + /** * @enum TypedArrayType *