• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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/jsview/js_view_functions.h"
17 
18 #include "base/log/ace_trace.h"
19 #include "core/pipeline/base/composed_element.h"
20 #include "frameworks/bridge/declarative_frontend/engine/js_execution_scope_defines.h"
21 #include "frameworks/bridge/declarative_frontend/jsview/js_view.h"
22 #include "frameworks/bridge/declarative_frontend/view_stack_processor.h"
23 
24 namespace OHOS::Ace::Framework {
25 
ViewFunctions(JSRef<JSObject> jsObject,JSRef<JSFunc> jsRenderFunction)26 ViewFunctions::ViewFunctions(JSRef<JSObject> jsObject, JSRef<JSFunc> jsRenderFunction)
27 {
28     jsObject_ = jsObject;
29 
30     JSRef<JSVal> jsAppearFunc = jsObject->GetProperty("aboutToAppear");
31     if (jsAppearFunc->IsFunction()) {
32         jsAppearFunc_ = JSRef<JSFunc>::Cast(jsAppearFunc);
33     }
34 
35     JSRef<JSVal> jsDisappearFunc = jsObject->GetProperty("aboutToDisappear");
36     if (jsDisappearFunc->IsFunction()) {
37         jsDisappearFunc_ = JSRef<JSFunc>::Cast(jsDisappearFunc);
38     } else {
39         LOGD("aboutToDisappear is not a function");
40     }
41 
42     JSRef<JSVal> jsAboutToBeDeletedFunc = jsObject->GetProperty("aboutToBeDeleted");
43     if (jsAboutToBeDeletedFunc->IsFunction()) {
44         jsAboutToBeDeletedFunc_ = JSRef<JSFunc>::Cast(jsAboutToBeDeletedFunc);
45     } else {
46         LOGD("aboutToBeDeleted is not a function");
47     }
48 
49     JSRef<JSVal> jsAboutToRenderFunc = jsObject->GetProperty("aboutToRender");
50     if (jsAboutToRenderFunc->IsFunction()) {
51         jsAboutToRenderFunc_ = JSRef<JSFunc>::Cast(jsAboutToRenderFunc);
52     } else {
53         LOGD("aboutToRender is not a function");
54     }
55 
56     JSRef<JSVal> jsRenderDoneFunc = jsObject->GetProperty("onRenderDone");
57     if (jsRenderDoneFunc->IsFunction()) {
58         jsRenderDoneFunc_ = JSRef<JSFunc>::Cast(jsRenderDoneFunc);
59     } else {
60         LOGD("onRenderDone is not a function");
61     }
62 
63     JSRef<JSVal> jsAboutToBuildFunc = jsObject->GetProperty("aboutToBuild");
64     if (jsAboutToBuildFunc->IsFunction()) {
65         jsAboutToBuildFunc_ = JSRef<JSFunc>::Cast(jsAboutToBuildFunc);
66     } else {
67         LOGD("aboutToBuild is not a function");
68     }
69 
70     JSRef<JSVal> jsBuildDoneFunc = jsObject->GetProperty("onBuildDone");
71     if (jsBuildDoneFunc->IsFunction()) {
72         jsBuildDoneFunc_ = JSRef<JSFunc>::Cast(jsBuildDoneFunc);
73     } else {
74         LOGD("onBuildDone is not a function");
75     }
76 
77     JSRef<JSVal> jsTransitionFunc = jsObject->GetProperty("pageTransition");
78     if (jsTransitionFunc->IsFunction()) {
79         jsTransitionFunc_ = JSRef<JSFunc>::Cast(jsTransitionFunc);
80     } else {
81         LOGD("transition is not a function");
82     }
83 
84     JSRef<JSVal> jsOnHideFunc = jsObject->GetProperty("onPageHide");
85     if (jsOnHideFunc->IsFunction()) {
86         jsOnHideFunc_ = JSRef<JSFunc>::Cast(jsOnHideFunc);
87     } else {
88         LOGD("onHide is not a function");
89     }
90 
91     JSRef<JSVal> jsOnShowFunc = jsObject->GetProperty("onPageShow");
92     if (jsOnShowFunc->IsFunction()) {
93         jsOnShowFunc_ = JSRef<JSFunc>::Cast(jsOnShowFunc);
94     } else {
95         LOGD("onShow is not a function");
96     }
97 
98     JSRef<JSVal> jsBackPressFunc = jsObject->GetProperty("onBackPress");
99     if (jsBackPressFunc->IsFunction()) {
100         jsBackPressFunc_ = JSRef<JSFunc>::Cast(jsBackPressFunc);
101     } else {
102         LOGD("onBackPress is not a function");
103     }
104 
105     JSRef<JSVal> jsUpdateWithValueParamsFunc = jsObject->GetProperty("updateWithValueParams");
106     if (jsUpdateWithValueParamsFunc->IsFunction()) {
107         LOGD("updateWithValueParams is a function");
108         jsUpdateWithValueParamsFunc_ = JSRef<JSFunc>::Cast(jsUpdateWithValueParamsFunc);
109     } else {
110         LOGD("updateWithValueParams is not a function");
111     }
112 
113     jsRenderFunc_ = jsRenderFunction;
114 }
115 
ExecuteRender()116 void ViewFunctions::ExecuteRender()
117 {
118     if (jsRenderFunc_.IsEmpty()) {
119         LOGE("no render function in View!");
120         return;
121     }
122 
123     auto func = jsRenderFunc_.Lock();
124     JSRef<JSVal> jsThis = jsObject_.Lock();
125     jsRenderResult_ = func->Call(jsThis);
126 }
127 
ExecuteAppear()128 void ViewFunctions::ExecuteAppear()
129 {
130     ExecuteFunction(jsAppearFunc_, "aboutToAppear");
131 }
132 
ExecuteDisappear()133 void ViewFunctions::ExecuteDisappear()
134 {
135     ExecuteFunction(jsDisappearFunc_, "aboutToDisappear");
136 }
137 
ExecuteAboutToBeDeleted()138 void ViewFunctions::ExecuteAboutToBeDeleted()
139 {
140     ExecuteFunction(jsAboutToBeDeletedFunc_, "aboutToDisappear");
141 }
142 
ExecuteAboutToRender()143 void ViewFunctions::ExecuteAboutToRender()
144 {
145     // for developer callback.
146     ExecuteFunction(jsAboutToBuildFunc_, "aboutToBuild");
147     // for state manager mark rendering progress.
148     ExecuteFunction(jsAboutToRenderFunc_, "aboutToRender");
149 }
150 
ExecuteOnRenderDone()151 void ViewFunctions::ExecuteOnRenderDone()
152 {
153     // for state manager reset rendering progress.
154     ExecuteFunction(jsRenderDoneFunc_, "onRenderDone");
155     // for developer callback.
156     ExecuteFunction(jsBuildDoneFunc_, "onBuildDone");
157 }
158 
ExecuteTransition()159 void ViewFunctions::ExecuteTransition()
160 {
161     ExecuteFunction(jsTransitionFunc_, "pageTransition");
162 }
163 
HasPageTransition() const164 bool ViewFunctions::HasPageTransition() const
165 {
166     return !jsTransitionFunc_.IsEmpty();
167 }
168 
ExecuteShow()169 void ViewFunctions::ExecuteShow()
170 {
171     ExecuteFunction(jsOnShowFunc_, "onPageShow");
172 }
173 
ExecuteHide()174 void ViewFunctions::ExecuteHide()
175 {
176     ExecuteFunction(jsOnHideFunc_, "onPageHide");
177 }
178 
ExecuteUpdateWithValueParams(const std::string & jsonData)179 void ViewFunctions::ExecuteUpdateWithValueParams(const std::string& jsonData)
180 {
181     ExecuteFunctionWithParams(jsUpdateWithValueParamsFunc_, "updateWithValueParams", jsonData);
182 }
183 
ExecuteOnBackPress()184 bool ViewFunctions::ExecuteOnBackPress()
185 {
186     auto ret = ExecuteFunctionWithReturn(jsBackPressFunc_, "onBackPress");
187     if (!ret->IsEmpty() && ret->IsBoolean()) {
188         return ret->ToBoolean();
189     }
190     return false;
191 }
192 
ExecuteFunction(JSWeak<JSFunc> & func,const char * debugInfo)193 void ViewFunctions::ExecuteFunction(JSWeak<JSFunc>& func, const char* debugInfo)
194 {
195     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
196     if (func.IsEmpty()) {
197         LOGD("View doesn't have %{public}s() method!", debugInfo);
198         return;
199     }
200     ACE_SCOPED_TRACE("%s", debugInfo);
201     JSRef<JSVal> jsObject = jsObject_.Lock();
202     func.Lock()->Call(jsObject);
203 }
204 
ExecuteFunctionWithReturn(JSWeak<JSFunc> & func,const char * debugInfo)205 JSRef<JSVal> ViewFunctions::ExecuteFunctionWithReturn(JSWeak<JSFunc>& func, const char* debugInfo)
206 {
207     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_, JSRef<JSVal>::Make())
208     if (func.IsEmpty()) {
209         LOGD("View doesn't have %{public}s() method!", debugInfo);
210         return JSRef<JSVal>::Make();
211     }
212     ACE_SCOPED_TRACE("%s", debugInfo);
213     JSRef<JSVal> jsObject = jsObject_.Lock();
214     JSRef<JSVal> result = func.Lock()->Call(jsObject);
215     if (result.IsEmpty()) {
216         LOGE("Error calling %{public}s", debugInfo);
217     }
218     return result;
219 }
220 
ExecuteFunctionWithParams(JSWeak<JSFunc> & func,const char * debugInfo,const std::string & jsonData)221 void ViewFunctions::ExecuteFunctionWithParams(JSWeak<JSFunc>& func, const char* debugInfo, const std::string& jsonData)
222 {
223     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
224     if (func.IsEmpty()) {
225         LOGD("View doesn't have %{public}s() method!", debugInfo);
226         return;
227     }
228 
229     JSRef<JSObject> obj = JSRef<JSObject>::New();
230     JSRef<JSVal> param = obj->ToJsonObject(jsonData.c_str());
231 
232     JSRef<JSVal> jsObject = jsObject_.Lock();
233     JSRef<JSVal> result = func.Lock()->Call(jsObject, 1, &param);
234     if (result.IsEmpty()) {
235         LOGE("Error calling %{public}s", debugInfo);
236     }
237 }
238 
Destroy(JSView * parentCustomView)239 void ViewFunctions::Destroy(JSView* parentCustomView)
240 {
241     LOGD("Destroy");
242     // Might be called from parent view, before any result has been produced??
243     if (jsRenderResult_.IsEmpty()) {
244         LOGD("ViewFunctions::Destroy() -> no previous render result to delete");
245         return;
246     }
247 
248     auto renderRes = jsRenderResult_.Lock();
249     if (renderRes.IsEmpty() || !renderRes->IsObject()) {
250         LOGD("ViewFunctions::Destroy() -> result not an object");
251         return;
252     }
253 
254     JSRef<JSObject> obj = JSRef<JSObject>::Cast(renderRes);
255     if (!obj.IsEmpty()) {
256         JSView* view = obj->Unwrap<JSView>();
257         view->Destroy(parentCustomView);
258     }
259     jsRenderResult_.Reset();
260     LOGD("ViewFunctions::Destroy() end");
261 }
262 
263 } // namespace OHOS::Ace::Framework
264