• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&currentTimeStamp);
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