• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 PROMISE_BASE_H
17 #define PROMISE_BASE_H
18 
19 #include <napi_api.h>
20 
21 /**
22  * @brief Provide an async state with JavaScript promise semantics.
23  *
24  * Usage example:
25  * struct Promise : public PromiseBase {
26  * using PromiseBase::PromiseBase;
27  *     NapiApi::StrongRef arg;
28  *     bool SetResult() override {
29  *         result_ = DoSomethingWith(arg);
30  *     }
31  * };
32  * auto promise = new Promise();
33  * promise->arg = someVariable;
34  * auto jsValue = promise->ToNapiValue();   // Extract the JS promise before settling.
35  * promise->SettleLater();                  // After a settle call, do not touch the promise object.
36  * return jsValue;
37  *
38  * @note An instance must be dynamically allocated (into a raw pointer) and created in the main thread. Call one of
39  *       SettleLater, SettleNow or Reject to settle the promise. After settling, the object will delete itself.
40  */
41 class PromiseBase {
42 public:
43     /**
44      * @brief Call only with new, in the main thread that is local to the given napi_env.
45      */
46     explicit PromiseBase(napi_env env);
47     virtual ~PromiseBase();
48 
49     /**
50      * @brief Get the JavaScript promise object.
51      */
52     napi_value ToNapiValue() const;
53 
54     /**
55      * @brief Settle the promise later, in the JS thread, and delete this object.
56      * @note Call only from the engine thread. After calling, do not use this object.
57      */
58     void SettleLater();
59 
60     /**
61      * @brief Settle the promise immediately and delete this object.
62      * @note After calling, do not use this object.
63      */
64     void SettleNow();
65 
66     /**
67      * @brief Settle the promise immediately without fulfilling it and delete this object.
68      * @note After calling, do not use this object.
69      */
70     void Reject();
71 
72 protected:
73     /**
74      * @brief Set the result of the promise.
75      * @return True on success. If false, the promise will be rejected.
76      * @note SettleLater will run this in the JS thread; SettleNow in the same thread where it was called.
77      */
78     virtual bool SetResult() = 0;
79     napi_value result_ { nullptr };
80     napi_env env_ { nullptr };
81 
82 private:
83     void Resolve();
84     void CreateJsPromise();
85     void CreateSettleFunc();
86     void ReleaseSettleFunc();
87     void Abort();
88 
89     static inline void SettleCB(napi_env env, napi_value js_callback, void* context, void* inData);
90     static inline void FinalizeCB(napi_env env, void* finalize_data, void* finalize_hint);
91 
92     napi_deferred deferred_ { nullptr };
93     napi_value promise_ { nullptr };
94     napi_threadsafe_function settleLaterFunc_ { nullptr };
95 };
96 
97 #endif
98