1 /*
2 * Copyright (c) 2021-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 #include "frameworks/bridge/declarative_frontend/engine/jsi/modules/jsi_timer_module.h"
17
18 #include "base/log/log.h"
19 #include "frameworks/bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.h"
20 #include "frameworks/bridge/js_frontend/engine/common/js_constants.h"
21 #include "frameworks/bridge/js_frontend/frontend_delegate.h"
22
23 namespace OHOS::Ace::Framework {
24
25 namespace {
26
SetTimeoutOrInterval(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc,bool isInterval)27 shared_ptr<JsValue> SetTimeoutOrInterval(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
28 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc, bool isInterval)
29 {
30 auto instance = static_cast<JsiDeclarativeEngineInstance*>(runtime->GetEmbedderData());
31 if (instance == nullptr) {
32 LOGE("get jsi engine instance failed");
33 return runtime->NewNull();
34 }
35 auto delegate = instance->GetDelegate();
36 if (!delegate) {
37 LOGE("get frontend delegate failed");
38 return runtime->NewNull();
39 }
40
41 if (argc < 1) {
42 LOGE("argc should be greater than or equal to 1");
43 return runtime->NewNull();
44 }
45 if (!argv[0]->IsFunction(runtime)) {
46 LOGW("argv[0] is not function");
47 return runtime->NewNull();
48 }
49 uint32_t delay = 0;
50 std::vector<shared_ptr<JsValue>> callBackParams;
51 if (argc < 2 || !argv[1]->IsNumber(runtime)) {
52 uint32_t callbackId = JsiTimerModule::GetInstance()->AddCallBack(argv[0], callBackParams);
53 delegate->WaitTimer(std::to_string(callbackId), std::to_string(delay), isInterval, true);
54 return runtime->NewInt32(callbackId);
55 }
56 delay = static_cast<uint32_t>(argv[1]->ToInt32(runtime));
57
58 for (int i = 2; i < argc; ++i) {
59 callBackParams.emplace_back(argv[i]);
60 }
61 uint32_t callbackId = JsiTimerModule::GetInstance()->AddCallBack(argv[0], callBackParams);
62 delegate->WaitTimer(std::to_string(callbackId), std::to_string(delay), isInterval, true);
63 return runtime->NewInt32(callbackId);
64 }
65
ClearTimeoutOrInterval(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)66 void ClearTimeoutOrInterval(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
67 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
68 {
69 if (argc < 1) {
70 LOGE("argc is invalid");
71 return;
72 }
73 if (!argv[0]->IsNumber(runtime)) {
74 LOGE("argv[0] is not number");
75 return;
76 }
77
78 auto instance = static_cast<JsiDeclarativeEngineInstance*>(runtime->GetEmbedderData());
79 if (instance == nullptr) {
80 LOGE("get jsi engine instance failed");
81 return;
82 }
83 auto delegate = instance->GetDelegate();
84 if (!delegate) {
85 LOGE("get frontend delegate failed");
86 return;
87 }
88
89 uint32_t callbackId = static_cast<uint32_t>(argv[0]->ToInt32(runtime));
90 JsiTimerModule::GetInstance()->RemoveCallBack(callbackId);
91 delegate->ClearTimer(std::to_string(callbackId));
92 }
93
94 }
95
SetTimeout(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)96 shared_ptr<JsValue> SetTimeout(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
97 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
98 {
99 return SetTimeoutOrInterval(runtime, thisObj, argv, argc, false);
100 }
101
SetInterval(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)102 shared_ptr<JsValue> SetInterval(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
103 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
104 {
105 return SetTimeoutOrInterval(runtime, thisObj, argv, argc, true);
106 }
107
ClearTimeout(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)108 shared_ptr<JsValue> ClearTimeout(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
109 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
110 {
111 ClearTimeoutOrInterval(runtime, thisObj, argv, argc);
112 return runtime->NewNull();
113 }
114
ClearInterval(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)115 shared_ptr<JsValue> ClearInterval(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
116 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
117 {
118 ClearTimeoutOrInterval(runtime, thisObj, argv, argc);
119 return runtime->NewNull();
120 }
121
GetInstance()122 JsiTimerModule* JsiTimerModule::GetInstance()
123 {
124 static JsiTimerModule instance;
125 return &instance;
126 }
127
AddCallBack(const shared_ptr<JsValue> & func,const std::vector<shared_ptr<JsValue>> & params)128 uint32_t JsiTimerModule::AddCallBack(const shared_ptr<JsValue>& func, const std::vector<shared_ptr<JsValue>>& params)
129 {
130 std::lock_guard<std::mutex> lock(moduleMutex_);
131 ++callBackId_;
132 callBackFuncMap_[callBackId_] = func;
133 callBackParamsMap_[callBackId_] = params;
134 return callBackId_;
135 }
136
RemoveCallBack(uint32_t callBackId)137 void JsiTimerModule::RemoveCallBack(uint32_t callBackId)
138 {
139 std::lock_guard<std::mutex> lock(moduleMutex_);
140 if (callBackFuncMap_.find(callBackId) != callBackFuncMap_.end()) {
141 callBackFuncMap_.erase(callBackId);
142 }
143 if (callBackParamsMap_.find(callBackId) != callBackParamsMap_.end()) {
144 callBackParamsMap_.erase(callBackId);
145 }
146 }
147
GetCallBack(uint32_t callBackId,shared_ptr<JsValue> & func,std::vector<shared_ptr<JsValue>> & params)148 bool JsiTimerModule::GetCallBack(uint32_t callBackId, shared_ptr<JsValue>& func,
149 std::vector<shared_ptr<JsValue>>& params)
150 {
151 std::lock_guard<std::mutex> lock(moduleMutex_);
152 auto iterFunc = callBackFuncMap_.find(callBackId);
153 auto iterParams = callBackParamsMap_.find(callBackId);
154 if (iterFunc == callBackFuncMap_.end()) {
155 LOGE("find callback function failed, callbackId = %{public}u", callBackId);
156 return false;
157 }
158 if (iterParams == callBackParamsMap_.end()) {
159 LOGE("find callback parameters failed, callbackId = %{public}u", callBackId);
160 return false;
161 }
162 func = iterFunc->second;
163 params = iterParams->second;
164 return true;
165 }
166
InitTimerModule(const shared_ptr<JsRuntime> & runtime,shared_ptr<JsValue> & moduleObj)167 void JsiTimerModule::InitTimerModule(const shared_ptr<JsRuntime>& runtime, shared_ptr<JsValue>& moduleObj)
168 {
169 moduleObj->SetProperty(runtime, SET_TIMEOUT, runtime->NewFunction(SetTimeout));
170 moduleObj->SetProperty(runtime, SET_INTERVAL, runtime->NewFunction(SetInterval));
171 moduleObj->SetProperty(runtime, CLEAR_TIMEOUT, runtime->NewFunction(ClearTimeout));
172 moduleObj->SetProperty(runtime, CLEAR_INTERVAL, runtime->NewFunction(ClearInterval));
173 }
174
175 } // namespace OHOS::Ace::Framework