• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 UDMF_NAPI_QUEUE_H
17 #define UDMF_NAPI_QUEUE_H
18 
19 #include <functional>
20 #include <memory>
21 #include <string>
22 
23 #include "napi/native_api.h"
24 #include "napi/native_common.h"
25 #include "napi/native_node_api.h"
26 #include "napi_error_utils.h"
27 
28 namespace OHOS {
29 namespace UDMF {
30 using NapiCbInfoParser = std::function<void(size_t argc, napi_value *argv)>;
31 using NapiAsyncExecute = std::function<void(void)>;
32 using NapiAsyncComplete = std::function<void(napi_value &)>;
33 static constexpr size_t ARGC_MAX = 6;
34 struct ContextBase {
35     virtual ~ContextBase();
36     void GetCbInfo(
37         napi_env env, napi_callback_info info, NapiCbInfoParser parse = NapiCbInfoParser(), bool sync = false);
38 
39     inline void GetCbInfoSync(napi_env env, napi_callback_info info, const NapiCbInfoParser &parse = NapiCbInfoParser())
40     {
41         /* sync = true, means no callback, not AsyncWork. */
42         GetCbInfo(env, info, parse, true);
43     }
44 
45     napi_env env = nullptr;
46     napi_value output = nullptr;
47     napi_status status = napi_invalid_arg;
48     std::string error;
49     int32_t jsCode = 0;
50     bool isThrowError = false;
51 
52     napi_value self = nullptr;
53     void *native = nullptr;
54 
55 private:
56     napi_deferred deferred = nullptr;
57     napi_async_work work = nullptr;
58     napi_ref callbackRef = nullptr;
59     napi_ref selfRef = nullptr;
60 
61     NapiAsyncExecute execute = nullptr;
62     NapiAsyncComplete complete = nullptr;
63     std::shared_ptr<ContextBase> hold; /* cross thread data */
64 
65     friend class NapiQueue;
66 };
67 
68 /* check condition related to argc/argv, return and logging. */
69 #define ASSERT_ARGS(ctxt, condition, message)                                    \
70     do {                                                                         \
71         if (!(condition)) {                                                      \
72             (ctxt)->status = napi_invalid_arg;                                   \
73             (ctxt)->error = std::string(message);                                \
74             LOG_ERROR(UDMF_KITS_NAPI, "test (" #condition ") failed: " message); \
75             return;                                                              \
76         }                                                                        \
77     } while (0)
78 
79 #define ASSERT_STATUS(ctxt, message)                                                      \
80     do {                                                                                  \
81         if ((ctxt)->status != napi_ok) {                                                  \
82             (ctxt)->error = std::string(message);                                         \
83             LOG_ERROR(UDMF_KITS_NAPI, "test (ctxt->status == napi_ok) failed: " message); \
84             return;                                                                       \
85         }                                                                                 \
86     } while (0)
87 
88 /* check condition, return and logging if condition not true. */
89 #define ASSERT(condition, message, retVal)                                       \
90     do {                                                                         \
91         if (!(condition)) {                                                      \
92             LOG_ERROR(UDMF_KITS_NAPI, "test (" #condition ") failed: " message); \
93             return retVal;                                                       \
94         }                                                                        \
95     } while (0)
96 
97 #define ASSERT_VOID(condition, message)                                          \
98     do {                                                                         \
99         if (!(condition)) {                                                      \
100             LOG_ERROR(UDMF_KITS_NAPI, "test (" #condition ") failed: " message); \
101             return;                                                              \
102         }                                                                        \
103     } while (0)
104 
105 #define ASSERT_FALSE(condition, message)                                         \
106     do {                                                                         \
107         if (!(condition)) {                                                      \
108             LOG_ERROR(UDMF_KITS_NAPI, "test (" #condition ") failed: " message); \
109             return false;                                                        \
110         }                                                                        \
111     } while (0)
112 
113 #define ASSERT_NULL(condition, message) ASSERT(condition, message, nullptr)
114 
115 #define ASSERT_CALL(env, theCall, object)    \
116     do {                                     \
117         if ((theCall) != napi_ok) {          \
118             delete (object);                 \
119             GET_AND_THROW_LAST_ERROR((env)); \
120             return nullptr;                  \
121         }                                    \
122     } while (0)
123 
124 #define ASSERT_CALL_DELETE(env, theCall, object) \
125     do {                                         \
126         if ((theCall) != napi_ok) {              \
127             delete (object);                     \
128             GET_AND_THROW_LAST_ERROR((env));     \
129             return;                              \
130         }                                        \
131     } while (0)
132 
133 #define ASSERT_CALL_VOID(env, theCall)       \
134     do {                                     \
135         if ((theCall) != napi_ok) {          \
136             GET_AND_THROW_LAST_ERROR((env)); \
137             return;                          \
138         }                                    \
139     } while (0)
140 
141 #define ASSERT_WITH_ERRCODE(ctxt, condition, errcode, message)                                     \
142     do {                                                                                           \
143         if (!(condition)) {                                                                        \
144             (ctxt)->status = napi_generic_failure;                                                 \
145             GenerateNapiError(errcode, (ctxt)->jsCode, (ctxt)->error);                             \
146             LOG_ERROR(UDMF_KITS_NAPI, "test (" #condition ") failed: " message);                   \
147             return;                                                                                \
148         }                                                                                          \
149     } while (0)
150 
151 class NapiQueue {
152 public:
153     static napi_value AsyncWork(napi_env env, std::shared_ptr<ContextBase> ctxt, const std::string &name,
154         NapiAsyncExecute execute = NapiAsyncExecute(), NapiAsyncComplete complete = NapiAsyncComplete());
155 
156 private:
157     enum {
158         /* AsyncCallback / Promise output result index  */
159         RESULT_ERROR = 0,
160         RESULT_DATA = 1,
161         RESULT_ALL = 2
162     };
163 
164     static void GenerateOutput(ContextBase *ctxt);
165 };
166 } // namespace UDMF
167 } // namespace OHOS
168 #endif // UDMF_NAPI_QUEUE_H
169