• 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         if (errCode == ERR_WORKER_INITIALIZATION) {
48             errTitle = "Worker initialization failure, ";
49         } else if (errCode == ERR_WORKER_NOT_RUNNING) {
50             errTitle = "Worker instance is not running, ";
51         } else if (errCode == ERR_WORKER_UNSUPPORTED) {
52             errTitle = "The invoked API is not supported in workers, ";
53         } else if (errCode == ERR_WORKER_SERIALIZATION) {
54             errTitle = "An exception occurred during serialization, ";
55         } else if (errCode == ERR_WORKER_INVALID_FILEPATH) {
56             errTitle = "The worker file path is invalid path, ";
57         } else if (errCode == ERR_NOT_CONCURRENT_FUNCTION) {
58             errTitle = "The function is not mark as concurrent, ";
59         } else if (errCode == ERR_CANCEL_NONEXIST_TASK) {
60             errTitle = "The task does not exist when it is canceled";
61         } else if (errCode == ERR_CANCEL_NONEXIST_TASK_GROUP) {
62             errTitle = "The task group does not exist when it is canceled";
63         } else if (errCode == ERR_CANCEL_RUNNING_TASK) {
64             errTitle = "The task is executing when it is canceled";
65         }
66         napi_create_string_utf8(env, errName.c_str(), NAPI_AUTO_LENGTH, &name);
67         napi_value msg = nullptr;
68         if (errMessage == nullptr) {
69             napi_create_string_utf8(env, errTitle.c_str(), NAPI_AUTO_LENGTH, &msg);
70         } else {
71             napi_create_string_utf8(env, (errTitle + std::string(errMessage)).c_str(), NAPI_AUTO_LENGTH, &msg);
72         }
73 
74         napi_create_error(env, nullptr, msg, &concurrentError);
75         napi_set_named_property(env, concurrentError, "code", code);
76         napi_set_named_property(env, concurrentError, "name", name);
77         return concurrentError;
78     }
79 
80     static void ThrowError(napi_env env, int32_t errCode, const char* errMessage = nullptr)
81     {
82         napi_value concurrentError = NewError(env, errCode, errMessage);
83         napi_throw(env, concurrentError);
84     }
85 
GetCurrentTimeStamp()86     static std::string GetCurrentTimeStamp()
87     {
88         auto now = std::chrono::system_clock::now();
89         std::time_t currentTimeStamp = std::chrono::system_clock::to_time_t(now);
90         std::tm* timeInfo = std::localtime(&currentTimeStamp);
91         std::stringstream ss;
92         ss << std::put_time(timeInfo, "%Y-%m-%d %X");
93         return ss.str();
94     }
95 
GetErrorFileInfo(const std::string & input)96     static std::string GetErrorFileInfo(const std::string& input)
97     {
98         std::regex pattern("\\((.*?)\\)");
99         std::smatch match;
100         if (std::regex_search(input, match, pattern)) {
101             return match[1].str();
102         }
103         return "";
104     }
105 
SplitErrorFileInfo(const std::string & input,char delimiter,int count)106     static std::vector<std::string> SplitErrorFileInfo(const std::string& input, char delimiter, int count)
107     {
108         std::vector<std::string> result;
109         std::string rawErrorInfo = GetErrorFileInfo(input);
110         if (rawErrorInfo.empty()) {
111             return result;
112         }
113 
114         int pos = rawErrorInfo.rfind(delimiter);
115         while (pos != std::string::npos && count > 0) {
116             result.push_back(rawErrorInfo.substr(pos + 1));
117             rawErrorInfo = rawErrorInfo.substr(0, pos);
118             pos = rawErrorInfo.rfind(delimiter);
119             count--;
120         }
121         result.push_back(rawErrorInfo);
122         std::reverse(result.begin(), result.end());
123         return result;
124     }
125 
TranslateErrorEvent(napi_env env,napi_value error)126     static napi_value TranslateErrorEvent(napi_env env, napi_value error)
127     {
128         napi_value obj = NapiHelper::CreateObject(env);
129 
130         // add message
131         napi_value msgValue = nullptr;
132         napi_coerce_to_string(env, error, &msgValue);
133         napi_set_named_property(env, obj, "message", msgValue);
134 
135         // add backtrace
136         napi_value stack = NapiHelper::GetNameProperty(env, error, "stack");
137         napi_set_named_property(env, obj, "backtrace", stack);
138 
139         // add timeStamp
140         std::string current = GetCurrentTimeStamp();
141         napi_value timeStamp = nullptr;
142         napi_create_string_utf8(env, current.c_str(), NAPI_AUTO_LENGTH, &timeStamp);
143         napi_set_named_property(env, obj, "timeStamp", timeStamp);
144 
145         std::string rawStack = NapiHelper::GetString(env, stack);
146         std::vector<std::string> result = SplitErrorFileInfo(rawStack, ':', 2); // 2 : the last two :
147         if (result.size() == 3) { // 3 : the rawStack is divided into three parts by last two :
148             // add filename
149             napi_value filenameValue = nullptr;
150             napi_create_string_utf8(env, result[0].c_str(), NAPI_AUTO_LENGTH, &filenameValue); // 0 : filename
151             napi_set_named_property(env, obj, "filename", filenameValue);
152 
153             // add lineno
154             napi_value lineno = nullptr;
155             napi_create_string_utf8(env, result[1].c_str(), NAPI_AUTO_LENGTH, &lineno); // 1 : lineno
156             napi_set_named_property(env, obj, "lineno", lineno);
157 
158             // add colno
159             napi_value colno = nullptr;
160             napi_create_string_utf8(env, result[2].c_str(), NAPI_AUTO_LENGTH, &colno); // 2 : colno
161             napi_set_named_property(env, obj, "colno", colno);
162         }
163 
164         // add type
165         napi_value eventType = nullptr;
166         napi_create_string_utf8(env, "ErrorEvent", NAPI_AUTO_LENGTH, &eventType);
167         napi_set_named_property(env, obj, "type", eventType);
168 
169         // add error
170         napi_set_named_property(env, obj, "error", error);
171 
172         return obj;
173     }
174 
175     static const int32_t TYPE_ERROR = 401; // 401 : the parameter type is incorrect
176     static const int32_t ERR_WORKER_INITIALIZATION = 10200003; // 10200003 : worker initialization failure
177     static const int32_t ERR_WORKER_NOT_RUNNING = 10200004; // 10200004 : worker instance is not running
178     static const int32_t ERR_WORKER_UNSUPPORTED = 10200005; // 10200005 : the invoked API is not supported in worker
179     static const int32_t ERR_WORKER_SERIALIZATION = 10200006; // 10200006 : serialize an uncaught exception failed
180     static const int32_t ERR_WORKER_INVALID_FILEPATH = 10200007; // 10200007 : the worker file path is invalid path
181     static const int32_t ERR_NOT_CONCURRENT_FUNCTION = 10200014; // 10200014 : the function is not mark as concurrent
182     static const int32_t ERR_CANCEL_NONEXIST_TASK = 10200015; // 10200015 : the task does not exist when it is canceled
183     static const int32_t ERR_CANCEL_RUNNING_TASK = 10200016; // 10200016 : the task is executing when it is canceled
184     static const int32_t ERR_CANCEL_NONEXIST_TASK_GROUP = 10200018; // 10200018 : cancel nonexist task group
185 };
186 } // namespace Commonlibrary::Concurrent::Common::Helper
187 #endif // JS_CONCURRENT_MODULE_COMMON_HELPER_ERROR_HELPER_H