• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef FOUNDATION_ACE_FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_JS_VIEW_JS_VIEW_H
17 #define FOUNDATION_ACE_FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_JS_VIEW_JS_VIEW_H
18 
19 #include <functional>
20 #include <list>
21 #include <string>
22 
23 #include "base/log/ace_scoring_log.h"
24 #include "base/memory/ace_type.h"
25 #include "base/memory/referenced.h"
26 #include "core/components_ng/base/view_partial_update_model.h"
27 #include "frameworks/bridge/declarative_frontend/engine/js_ref_ptr.h"
28 #include "frameworks/bridge/declarative_frontend/jsview/js_view_abstract.h"
29 #include "frameworks/bridge/declarative_frontend/jsview/js_view_functions.h"
30 
31 namespace OHOS::Ace::Framework {
32 
33 class JSView : public JSViewAbstract, public Referenced {
34 public:
JSView()35     JSView() : instanceId_(Container::CurrentId()) {}
36     ~JSView() override = default;
37     virtual void Destroy(JSView* parentCustomView) = 0;
38 
CreateViewNode()39     virtual RefPtr<AceType> CreateViewNode()
40     {
41         LOGE("Internal error. Not implemented");
42         return nullptr;
43     }
44 
45     void SyncInstanceId();
46     void RestoreInstanceId();
47 
FireOnShow()48     void FireOnShow()
49     {
50         if (jsViewFunction_) {
51             ACE_SCORING_EVENT("OnShow");
52             jsViewFunction_->ExecuteShow();
53         }
54     }
55 
FireOnHide()56     void FireOnHide()
57     {
58         if (jsViewFunction_) {
59             ACE_SCORING_EVENT("OnHide");
60             jsViewFunction_->ExecuteHide();
61         }
62     }
63 
FireOnBackPress()64     bool FireOnBackPress()
65     {
66         if (jsViewFunction_) {
67             ACE_SCORING_EVENT("OnBackPress");
68             return jsViewFunction_->ExecuteOnBackPress();
69         }
70         return false;
71     }
72 
73     void RenderJSExecution();
74 
75     virtual void MarkNeedUpdate() = 0;
76 
77     bool NeedsUpdate();
78 
79     static void JSBind(BindingTarget globalObj);
80     /**
81      * Views which do not have a state can mark static.
82      * The element will be reused and re-render will be skipped.
83      */
84     void MarkStatic();
85 
IsStatic()86     bool IsStatic()
87     {
88         return isStatic_;
89     }
90 
SetContext(const JSExecutionContext & context)91     void SetContext(const JSExecutionContext& context)
92     {
93         jsViewFunction_->SetContext(context);
94     }
95 
96     // Used to set/get card id C++
SetCardId(int64_t cardId)97     void SetCardId(int64_t cardId)
98     {
99         cardId_ = cardId;
100     }
101 
GetCardId()102     int64_t GetCardId() const
103     {
104         return cardId_;
105     }
106 
RegisterRenderDoneCallback(std::function<void ()> && OnRenderDone)107     void RegisterRenderDoneCallback(std::function<void()>&& OnRenderDone)
108     {
109         notifyRenderDone_ = std::move(OnRenderDone);
110     }
111 
112     // Used to set/get card id JS
113     void JsSetCardId(int64_t cardId);
114     void JsGetCardId(const JSCallbackInfo& info);
115 
116     // Used by full update variant only from js_lazy_foreach.cpp
RemoveChildGroupById(const std::string & viewId)117     virtual void RemoveChildGroupById(const std::string& viewId) {}
MarkLazyForEachProcess(const std::string & groudId)118     virtual void MarkLazyForEachProcess(const std::string& groudId) {}
ResetLazyForEachProcess()119     virtual void ResetLazyForEachProcess() {}
ExecuteUpdateWithValueParams(const std::string & jsonData)120     virtual void ExecuteUpdateWithValueParams(const std::string& jsonData) {}
ExecuteInitiallyProvidedValue(const std::string & jsonData)121     virtual void ExecuteInitiallyProvidedValue(const std::string& jsonData) {}
122 
isFullUpdate()123     virtual bool isFullUpdate() const
124     {
125         return true;
126     }
127 
128 #ifdef UICAST_COMPONENT_SUPPORTED
ExecuteCreateChildView(const std::string & childViewId)129     void ExecuteCreateChildView(const std::string& childViewId)
130     {
131         std::string jsonData = R"({"viewID":")" + childViewId + R"("})";
132         LOGI("UICast para: %{public}s", jsonData.c_str());
133         jsViewFunction_->ExecuteCreateChildView(jsonData);
134     }
135 
ExecuteRouterHandle(const std::string & type,const std::string & uri)136     void ExecuteRouterHandle(const std::string& type, const std::string& uri)
137     {
138         std::string jsonData = R"({"uri":")" + uri + R"(","type":")" + type + R"("})";
139         LOGI("UICast para: %{public}s", jsonData.c_str());
140         ContainerScope scope(instanceId_);
141         jsViewFunction_->ExecuteRouterHandle(jsonData);
142     }
143 
ExecuteReplayOnEvent(const std::string & event)144     void ExecuteReplayOnEvent(const std::string& event)
145     {
146         std::string jsonData = R"({"event":")" + event + R"("})";
147         LOGI("UICast para: %{public}s", jsonData.c_str());
148         jsViewFunction_->ExecuteReplayOnEvent(jsonData);
149     }
150 #endif
151 
UICastGetViewId()152     std::string UICastGetViewId() const
153     {
154         return viewId_;
155     }
156 
UICastGetUniqueId()157     int UICastGetUniqueId() const
158     {
159         return uniqueId_;
160     }
161 
GetInstanceId()162     int32_t GetInstanceId() const
163     {
164         return instanceId_;
165     }
166 
167 protected:
168     RefPtr<ViewFunctions> jsViewFunction_;
169     bool needsUpdate_ = false;
170 
171     WeakPtr<AceType> viewNode_;
172     // view id for custom view itself
173     std::string viewId_;
174     int uniqueId_ = -1;
175 
176     // card id for eTS Card
177     // set on the root JSView of the card and inherited by all child JSViews
178     // -1 means not part of a card
179     int64_t cardId_ = -1;
180 
181 private:
182     int32_t instanceId_ = -1;
183     int32_t restoreInstanceId_ = -1;
184     bool isStatic_ = false;
185     std::function<void()> notifyRenderDone_;
186 };
187 
188 class JSViewFullUpdate : public JSView {
189 public:
190     JSViewFullUpdate(const std::string& viewId, JSRef<JSObject> jsObject, JSRef<JSFunc> jsRenderFunction);
191     ~JSViewFullUpdate() override;
192 
193     void Destroy(JSView* parentCustomView) override;
194 
195     // TODO: delete this after the toolchain for partial update is ready.
196     RefPtr<AceType> InternalRender();
197 
198     RefPtr<AceType> CreateViewNode() override;
199 
200     void MarkNeedUpdate() override;
201 
202     /**
203      * During render function execution, the child custom view with same id will
204      * be recycled if they exist already in our child map. The ones which are not
205      * recycled needs to be cleaned. So After render function execution, clean the
206      * abandoned child custom view.
207      */
208     void CleanUpAbandonedChild();
209 
210     /**
211      * Retries the custom view child for recycling
212      * always use FindChildById to be certain before calling this method
213      */
214     JSRef<JSObject> GetChildById(const std::string& viewId);
215 
216     void FindChildById(const JSCallbackInfo& info);
217     void FindChildByIdForPreview(const JSCallbackInfo& info);
218     bool GetChildByViewId(const std::string& viewId, JSRef<JSObject>& childView, JSRef<JSObject>& targetView);
219 
ExecuteUpdateWithValueParams(const std::string & jsonData)220     void ExecuteUpdateWithValueParams(const std::string& jsonData) override
221     {
222         jsViewFunction_->ExecuteUpdateWithValueParams(jsonData);
223     }
224 
MarkLazyForEachProcess(const std::string & groudId)225     void MarkLazyForEachProcess(const std::string& groudId) override
226     {
227         isLazyForEachProcessed_ = true;
228         lazyItemGroupId_ = groudId;
229     }
230 
ResetLazyForEachProcess()231     void ResetLazyForEachProcess() override
232     {
233         isLazyForEachProcessed_ = false;
234         lazyItemGroupId_ = "";
235     }
236 
237     /**
238      * New CustomView child will be added to the map.
239      * and it can be retrieved for recycling in next render function
240      * In next render call if this child is not recycled, it will be destroyed.
241      */
242     std::string AddChildById(const std::string& viewId, const JSRef<JSObject>& obj);
243 
244     void RemoveChildGroupById(const std::string& viewId) override;
245 
246     static void Create(const JSCallbackInfo& info);
247     static void JSBind(BindingTarget globalObj);
248 
249     static void ConstructorCallback(const JSCallbackInfo& args);
250     static void DestructorCallback(JSViewFullUpdate* instance);
251 
252 private:
253     void DestroyChild(JSView* parentCustomView);
254 
255     /**
256      * Takes care of the viewId wrt to foreach
257      */
258     std::string ProcessViewId(const std::string& viewId);
259     /**
260      * creates a set of valid view ids on a render function execution
261      * its cleared after cleaning up the abandoned child.
262      */
263     void ChildAccessedById(const std::string& viewId);
264 
265     bool isLazyForEachProcessed_ = false;
266     std::string lazyItemGroupId_;
267 
268     // unique view id for custom view to recycle.
269     std::string id_;
270     // hold handle to the native and javascript object to keep them alive
271     // until they are abandoned
272     std::unordered_map<std::string, JSRef<JSObject>> customViewChildren_;
273 
274     // hold handle to the native and javascript object to keep them alive
275     // until they are abandoned used by lazyForEach
276     std::unordered_map<std::string, JSRef<JSObject>> customViewChildrenWithLazy_;
277 
278     // hold js view ids by lazy item ground.
279     // until they are abandoned used by lazyForEach
280     std::unordered_map<std::string, std::list<std::string>> lazyItemGroups_;
281 
282     // a set of valid view ids on a render function execution
283     // its cleared after cleaning up the abandoned child.
284     std::unordered_set<std::string> lastAccessedViewIds_;
285 
286     // The C++ JSView object owns a reference to the JS Object
287     // AssignNewView assigns the JS View
288     // Destroy deleted the ref, and thereby triggers the deletion
289     // GC -> JS View Object -> JSView C++ Object
290     JSRef<JSObject> jsViewObject_;
291 };
292 
293 class JSViewPartialUpdate : public JSView {
294 public:
295     explicit JSViewPartialUpdate(JSRef<JSObject> jsObject);
296     ~JSViewPartialUpdate() override;
297 
298     void Destroy(JSView* parentCustomView) override;
299 
300     RefPtr<AceType> InitialRender();
301 
302     RefPtr<AceType> CreateViewNode() override;
303 
304     static void Create(const JSCallbackInfo& info);
305     static void JSBind(BindingTarget globalObj);
306 
307     static void ConstructorCallback(const JSCallbackInfo& args);
308     static void DestructorCallback(JSViewPartialUpdate* instance);
309 
310     // public functions added by partial update added below ==================
311 
312     /**
313      * Last step of executing an partial update function
314      * get the result component from ViewStackProcessor
315      * add it to the queue to [elmtId, Component] to
316      * execute an local update on in the UI thread
317      * parameters
318      * elmtId of the Component/Element that's updated
319      * removedElementId : Array<number>  ids of Elements that were removed while updating
320      * caused by if condition toggle or ForEach array deleted / replaced items
321      * return boolean - true means success
322      */
323     void JsFinishUpdateFunc(int32_t elmtId);
324 
325     // The process of Component to Element sync leads to Elements being
326     // deleted. ElementRegister keeps track of these deletions
327     // before the framework can forget about these elmtIds
328     // these need to be removed from its own book keeping
329     // state variables keep track of dependent elmtIds and
330     // View objects keep a map elmtId -> update function,
331     // both on TS side.
332     // View.purgeDeletedElmtIds cleans both state variables
333     // and update function map from deleted ElmtIds
334     // afterwards it informs the ElementRegister that elmtIds
335     // it was able to purge.
336     // only then ElementRegister can forget about these elmtIds
337     void JsGetDeletedElemtIds(const JSCallbackInfo& info);
338 
339     // JS signature: View.deletedElmtIdsHaveBeenPurged(elmtIds : number[])
340     // inform ElementRegister that given deleted eltIds
341     // have been deleted from partial updates book keeping
342     // at this point ElementRegister can forget about the,
343     void JsDeletedElmtIdsHaveBeenPurged(const JSCallbackInfo& info);
344 
345     /**
346     JS exposed function to check from ElementRegister if given elmtId is (still) in use
347     */
348     bool JsElementIdExists(int32_t elmtId);
349 
350     void JSGetProxiedItemRenderState(const JSCallbackInfo& info);
351 
isFullUpdate()352     bool isFullUpdate() const override
353     {
354         return false;
355     }
356 
357     void IsFirstRender(const JSCallbackInfo& info);
358     void FindChildByIdForPreview(const JSCallbackInfo& info);
359 
ExecuteInitiallyProvidedValue(const std::string & jsonData)360     void ExecuteInitiallyProvidedValue(const std::string& jsonData) override
361     {
362         jsViewFunction_->ExecuteInitiallyProvidedValue(jsonData);
363     }
364 
365 private:
366     void MarkNeedUpdate() override;
367 
368     // indicates if the JSView has ever completed initial render
369     // used for code branching in lambda given to ComposedComponent
370     // render callback
371     bool isFirstRender_ = true;
372 
373     /* list of update function result is a triple (tuple with three entries)
374     <0> elmtId
375     <1> outmost wrapping Component
376     <2> main Component
377     */
378     std::list<UpdateTask> pendingUpdateTasks_;
379 
380     // The C++ JSView object owns a reference to the JS Object
381     // AssignNewView assigns the JS View
382     // Destroy deleted the ref, and thereby triggers the deletion
383     // GC -> JS View Object -> JSView C++ Object
384     JSRef<JSObject> jsViewObject_;
385 };
386 
387 } // namespace OHOS::Ace::Framework
388 #endif // FOUNDATION_ACE_FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_JS_VIEW_JS_VIEW_H
389