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