1 /* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef JS_CONCURRENT_MODULE_COMMON_HELPER_ERROR_HELPER_H 17 #define JS_CONCURRENT_MODULE_COMMON_HELPER_ERROR_HELPER_H 18 19 #include <ctime> 20 #include <iomanip> 21 #include <iostream> 22 #include <regex> 23 #include <sstream> 24 #include <vector> 25 26 #include "napi/native_api.h" 27 #include "napi/native_node_api.h" 28 #include "napi_helper.h" 29 #include "native_engine/native_engine.h" 30 31 namespace Commonlibrary::Concurrent::Common::Helper { 32 class ErrorHelper { 33 public: 34 ErrorHelper() = default; 35 ~ErrorHelper() = default; 36 37 static napi_value NewError(napi_env env, int32_t errCode, const char* errMessage = nullptr) 38 { 39 std::string errTitle = ""; 40 napi_value concurrentError = nullptr; 41 42 napi_value code = nullptr; 43 napi_create_uint32(env, errCode, &code); 44 45 napi_value name = nullptr; 46 std::string errName = "BusinessError"; 47 switch (errCode) { 48 case ERR_WORKER_INITIALIZATION: 49 errTitle = "Worker initialization failed, "; 50 break; 51 case ERR_WORKER_NOT_RUNNING: 52 errTitle = "The Worker instance is not running, "; 53 break; 54 case ERR_WORKER_UNSUPPORTED: 55 errTitle = "The called API is not supported in the worker thread, "; 56 break; 57 case ERR_WORKER_SERIALIZATION: 58 errTitle = "An exception occurred during serialization, "; 59 break; 60 case ERR_WORKER_INVALID_FILEPATH: 61 errTitle = "The worker file path is invalid, "; 62 break; 63 case ERR_NOT_CONCURRENT_FUNCTION: 64 errTitle = "The function is not marked as concurrent, "; 65 break; 66 case ERR_CANCEL_NONEXIST_TASK: 67 errTitle = "The task to cancel does not exist, "; 68 break; 69 case ERR_CANCEL_NONEXIST_TASK_GROUP: 70 errTitle = "The task group to cancel does not exist, "; 71 break; 72 case ERR_CANCEL_RUNNING_TASK: 73 errTitle = "The task to cancel is being executed"; 74 break; 75 case ERR_TRIGGER_NONEXIST_EVENT: 76 errTitle = "The globalCallObject is not registered"; 77 break; 78 case ERR_CALL_METHOD_ON_BINDING_OBJ: 79 errTitle = "The method to be called is not callable or is an async method or a generator."; 80 break; 81 case ERR_GLOBAL_CALL_TIMEOUT: 82 errTitle = "Waiting for a global call timed out"; 83 break; 84 case ERR_NOT_IN_TASKPOOL_THREAD: 85 errTitle = "The function is not called in the TaskPool thread"; 86 break; 87 case ERR_NOT_IN_CONCURRENT_FUNCTION: 88 errTitle = "The function is not called in the concurrent function"; 89 break; 90 case ERR_NOT_REGISTERED: 91 errTitle = "The callback is not registered on the host side"; 92 break; 93 case ERR_CIRCULAR_DEPENDENCY: 94 errTitle = "There is a circular dependency"; 95 break; 96 case ERR_INEXISTENT_DEPENDENCY: 97 errTitle = "The dependency does not exist, "; 98 break; 99 case ERR_DELAY_TIME_ERROR: 100 errTitle = ""; 101 break; 102 case ERR_IN_BOTH_CLONE_AND_TRANSFER: 103 errTitle = "An ArrayBuffer cannot be set as both a transfer list and a clone list"; 104 break; 105 case ERR_NO_SUCH_ASYNCLOCK: 106 errTitle = "The lock does not exist"; 107 break; 108 case ERR_ASYNCLOCK_TIMEOUT: 109 errTitle = "lockAsync timed out"; 110 break; 111 case TYPE_ERROR: 112 errTitle = "Parameter error. The input parameters are invalid, "; 113 break; 114 case ERR_REGISTRATION_OF_LISTENERS: 115 errTitle = "The executed task does not support the registration of listeners."; 116 break; 117 case ERR_TASK_EXECUTE_PERIODICALLY: 118 errTitle = "The concurrent task has been executed and cannot be executed periodically."; 119 break; 120 case ERR_TASK_EXECUTE_AGAIN: 121 errTitle = "The periodic task cannot be executed again, "; 122 break; 123 case ERR_TASK_HAVE_DEPENDENCY: 124 errTitle = "The periodic task cannot have a dependency."; 125 break; 126 case ERR_ASYNCRUNNER_TASK_DISCARDED: 127 errTitle = "The asyncRunner task is discarded."; 128 break; 129 case ERR_ASYNCRUNNER_TASK_CANCELED: 130 errTitle = "The asyncRunner task has been canceled."; 131 break; 132 case ERR_ASYNCRUNNER_TASK_HAVE_DEPENDENCY: 133 errTitle = "The task has been executed by AsyncRunner."; 134 break; 135 case ERR_TASK_CANNOT_EXECUTED: 136 errTitle = "The task cannot be executed by two APIs, "; 137 break; 138 default: 139 break; 140 } 141 napi_create_string_utf8(env, errName.c_str(), NAPI_AUTO_LENGTH, &name); 142 napi_value msg = nullptr; 143 if (errMessage == nullptr) { 144 napi_create_string_utf8(env, errTitle.c_str(), NAPI_AUTO_LENGTH, &msg); 145 } else { 146 napi_create_string_utf8(env, (errTitle + std::string(errMessage)).c_str(), NAPI_AUTO_LENGTH, &msg); 147 } 148 149 napi_create_error(env, nullptr, msg, &concurrentError); 150 napi_set_named_property(env, concurrentError, "code", code); 151 napi_set_named_property(env, concurrentError, "name", name); 152 return concurrentError; 153 } 154 155 static void ThrowError(napi_env env, int32_t errCode, const char* errMessage = nullptr) 156 { 157 napi_value concurrentError = NewError(env, errCode, errMessage); 158 napi_throw(env, concurrentError); 159 } 160 GetCurrentTimeStamp()161 static std::string GetCurrentTimeStamp() 162 { 163 auto now = std::chrono::system_clock::now(); 164 std::time_t currentTimeStamp = std::chrono::system_clock::to_time_t(now); 165 std::tm* timeInfo = std::localtime(¤tTimeStamp); 166 std::stringstream ss; 167 ss << std::put_time(timeInfo, "%Y-%m-%d %X"); 168 return ss.str(); 169 } 170 GetErrorFileInfo(const std::string & input)171 static std::string GetErrorFileInfo(const std::string& input) 172 { 173 std::regex pattern("\\((.*?)\\)"); 174 std::smatch match; 175 if (std::regex_search(input, match, pattern)) { 176 return match[1].str(); 177 } 178 return ""; 179 } 180 SplitErrorFileInfo(const std::string & input,char delimiter,int count)181 static std::vector<std::string> SplitErrorFileInfo(const std::string& input, char delimiter, int count) 182 { 183 std::vector<std::string> result; 184 std::string rawErrorInfo = GetErrorFileInfo(input); 185 if (rawErrorInfo.empty()) { 186 return result; 187 } 188 189 auto pos = rawErrorInfo.rfind(delimiter); 190 while (pos != std::string::npos && count > 0) { 191 result.push_back(rawErrorInfo.substr(pos + 1)); 192 rawErrorInfo = rawErrorInfo.substr(0, pos); 193 pos = rawErrorInfo.rfind(delimiter); 194 count--; 195 } 196 result.push_back(rawErrorInfo); 197 std::reverse(result.begin(), result.end()); 198 return result; 199 } 200 TranslateErrorEvent(napi_env env,napi_value error)201 static napi_value TranslateErrorEvent(napi_env env, napi_value error) 202 { 203 napi_value obj = NapiHelper::CreateObject(env); 204 205 // add message 206 napi_value msgValue = nullptr; 207 napi_coerce_to_string(env, error, &msgValue); 208 napi_set_named_property(env, obj, "message", msgValue); 209 210 // add backtrace 211 napi_value stack = NapiHelper::GetNameProperty(env, error, "stack"); 212 napi_set_named_property(env, obj, "backtrace", stack); 213 214 // add timeStamp 215 std::string current = GetCurrentTimeStamp(); 216 napi_value timeStamp = nullptr; 217 napi_create_string_utf8(env, current.c_str(), NAPI_AUTO_LENGTH, &timeStamp); 218 napi_set_named_property(env, obj, "timeStamp", timeStamp); 219 std::string rawStack = NapiHelper::GetString(env, stack); 220 std::vector<std::string> result = SplitErrorFileInfo(rawStack, ':', 2); // 2 : the last two : 221 if (result.size() == 3) { // 3 : the rawStack is divided into three parts by last two : 222 // add filename 223 napi_value filenameValue = nullptr; 224 napi_create_string_utf8(env, result[0].c_str(), NAPI_AUTO_LENGTH, &filenameValue); // 0 : filename 225 napi_set_named_property(env, obj, "filename", filenameValue); 226 227 // add lineno 228 double line = result[1].empty() ? 0 : std::strtod(result[1].c_str(), nullptr); // 1 : index of lineno 229 napi_value lineno = nullptr; 230 napi_create_double(env, line, &lineno); 231 napi_set_named_property(env, obj, "lineno", lineno); 232 233 // add colno 234 double col = result[2].empty() ? 0 : std::strtod(result[2].c_str(), nullptr); // 2 : index of colno 235 napi_value colno = nullptr; 236 napi_create_double(env, col, &colno); 237 napi_set_named_property(env, obj, "colno", colno); 238 } 239 240 // add type 241 napi_value eventType = nullptr; 242 napi_create_string_utf8(env, "ErrorEvent", NAPI_AUTO_LENGTH, &eventType); 243 napi_set_named_property(env, obj, "type", eventType); 244 245 // add error 246 napi_set_named_property(env, obj, "error", error); 247 248 return obj; 249 } 250 ObjectToError(napi_env env,napi_value error)251 static napi_value ObjectToError(napi_env env, napi_value error) 252 { 253 napi_value message = NapiHelper::GetNameProperty(env, error, "message"); 254 napi_value backtrace = NapiHelper::GetNameProperty(env, error, "backtrace"); 255 napi_value businessError = nullptr; 256 napi_create_error(env, nullptr, message, &businessError); 257 napi_set_named_property(env, businessError, "stack", backtrace); 258 napi_set_named_property(env, businessError, "name", message); 259 return businessError; 260 } 261 262 static const int32_t TYPE_ERROR = 401; // 401 : the parameter type is incorrect 263 static const int32_t ERR_WORKER_INITIALIZATION = 10200003; // 10200003 : Worker initialization failed 264 static const int32_t ERR_WORKER_NOT_RUNNING = 10200004; // 10200004 : The Worker instance is not running 265 // 10200005 : The called API is not supported in the worker thread 266 static const int32_t ERR_WORKER_UNSUPPORTED = 10200005; 267 static const int32_t ERR_WORKER_SERIALIZATION = 10200006; // 10200006 : serialize an uncaught exception failed 268 static const int32_t ERR_WORKER_INVALID_FILEPATH = 10200007; // 10200007 : The worker file path is invalid 269 static const int32_t ERR_NOT_CONCURRENT_FUNCTION = 10200014; // 10200014 : The function is not marked as concurrent 270 static const int32_t ERR_CANCEL_NONEXIST_TASK = 10200015; // 10200015 : The task to cancel does not exist 271 static const int32_t ERR_CANCEL_RUNNING_TASK = 10200016; // 10200016 : The task to cancel is being executed 272 // 10200018 : The task group to cancel does not exist 273 static const int32_t ERR_CANCEL_NONEXIST_TASK_GROUP = 10200018; 274 static const int32_t ERR_TRIGGER_NONEXIST_EVENT = 10200019; // 10200019 : The triggered event does not exist 275 // 10200020 : The called method is not callable or async or generator 276 static const int32_t ERR_CALL_METHOD_ON_BINDING_OBJ = 10200020; 277 static const int32_t ERR_GLOBAL_CALL_TIMEOUT = 10200021; // 10200021 : Waiting for a global call timed out 278 // 10200022 : The function is not called in the TaskPool thread 279 static const int32_t ERR_NOT_IN_TASKPOOL_THREAD = 10200022; 280 // 10200023 : The function is not called in the concurrent function 281 static const int32_t ERR_NOT_IN_CONCURRENT_FUNCTION = 10200023; 282 static const int32_t ERR_NOT_REGISTERED = 10200024; // 10200024 : The callback is not registered on the host side 283 // 10200025 : dependent task not allowed. 284 static const int32_t ERR_ADD_DEPENDENT_TASK_TO_SEQRUNNER = 10200025; 285 static const int32_t ERR_CIRCULAR_DEPENDENCY = 10200026; // 10200026 : There is a circular dependency 286 static const int32_t ERR_INEXISTENT_DEPENDENCY = 10200027; // 10200027: The dependency does not exist 287 static const int32_t ERR_DELAY_TIME_ERROR = 10200028; // 10200028 : The delayTime is less than zero 288 // 10200029 : An ArrayBuffer cannot be set as both a transfer list and a clone list 289 static const int32_t ERR_IN_BOTH_CLONE_AND_TRANSFER = 10200029; 290 static const int32_t ERR_NO_SUCH_ASYNCLOCK = 10200030; 291 // 10200031 : lockAsync funtion timeout exceeded 292 static const int32_t ERR_ASYNCLOCK_TIMEOUT = 10200031; 293 // 10200034 : The executed task does not support the registration of listeners 294 static const int32_t ERR_REGISTRATION_OF_LISTENERS = 10200034; 295 // 10200050 : The concurrent task has been executed and cannot be executed periodically 296 static const int32_t ERR_TASK_EXECUTE_PERIODICALLY = 10200050; 297 // 10200051 : The periodic task cannot be executed again 298 static const int32_t ERR_TASK_EXECUTE_AGAIN = 10200051; 299 // 10200052 : The periodic task cannot have a dependency 300 static const int32_t ERR_TASK_HAVE_DEPENDENCY = 10200052; 301 // 10200054 : The asyncRunner task discarded 302 static const int32_t ERR_ASYNCRUNNER_TASK_DISCARDED = 10200054; 303 // 10200055 : The asyncRunner task has been canceled 304 static const int32_t ERR_ASYNCRUNNER_TASK_CANCELED = 10200055; 305 // 10200056 : The task has been executed by AsyncRunner 306 static const int32_t ERR_ASYNCRUNNER_TASK_HAVE_DEPENDENCY = 10200056; 307 // 10200056 : The task cannot be executed by two APIs 308 static const int32_t ERR_TASK_CANNOT_EXECUTED = 10200057; 309 }; 310 } // namespace Commonlibrary::Concurrent::Common::Helper 311 #endif // JS_CONCURRENT_MODULE_COMMON_HELPER_ERROR_HELPER_H