• 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 FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_ENGINE_JSI_JSI_DECLARATIVE_ENGINE_H
17 #define FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_ENGINE_JSI_JSI_DECLARATIVE_ENGINE_H
18 
19 #include <mutex>
20 #include <string>
21 #include <vector>
22 
23 #include "ecmascript/napi/include/jsnapi.h"
24 #include "native_engine/impl/ark/ark_native_engine.h"
25 
26 #include "base/log/log.h"
27 #include "base/memory/ace_type.h"
28 #include "base/subwindow/subwindow_manager.h"
29 #include "base/utils/noncopyable.h"
30 #include "core/common/ace_application_info.h"
31 #include "core/common/ace_page.h"
32 #include "core/components/xcomponent/native_interface_xcomponent_impl.h"
33 #include "core/components_ng/base/ui_node.h"
34 #include "frameworks/bridge/js_frontend/engine/common/js_engine.h"
35 #include "frameworks/bridge/js_frontend/engine/jsi/js_runtime.h"
36 #include "frameworks/bridge/js_frontend/js_ace_page.h"
37 
38 namespace OHOS::Ace::Framework {
39 
40 struct NamedRouterProperty {
41     panda::Global<panda::FunctionRef> pageGenerator;
42     std::string bundleName;
43     std::string moduleName;
44     std::string pagePath;
45 };
46 
47 class JsiDeclarativeEngineInstance final : public AceType, public JsEngineInstance {
DECLARE_ACE_TYPE(JsiDeclarativeEngineInstance,AceType)48     DECLARE_ACE_TYPE(JsiDeclarativeEngineInstance, AceType)
49 public:
50     explicit JsiDeclarativeEngineInstance(const RefPtr<FrontendDelegate>& delegate) : frontendDelegate_(delegate) {}
51     ~JsiDeclarativeEngineInstance() override;
52 
53     void FlushCommandBuffer(void* context, const std::string& command) override;
54 
55     bool InitJsEnv(bool debuggerMode, const std::unordered_map<std::string, void*>& extraNativeObject,
56         const shared_ptr<JsRuntime>& runtime = nullptr);
57 
58     bool FireJsEvent(const std::string& eventStr);
59 
60     // add Console object to worker
61     void InitConsoleModule(ArkNativeEngine* engine);
62 
63     static void RootViewHandle(panda::Local<panda::ObjectRef> value);
64     void DestroyRootViewHandle(int32_t pageId);
65     void DestroyAllRootViewHandle();
66     void FlushReload();
67     NativeValue* GetContextValue();
68 
69     static std::unique_ptr<JsonValue> GetI18nStringResource(
70         const std::string& targetStringKey, const std::string& targetStringValue);
71     static std::string GetMediaResource(const std::string& targetFileName);
72 
73     static RefPtr<JsAcePage> GetRunningPage(int32_t instanceId);
74     static RefPtr<JsAcePage> GetStagingPage(int32_t instanceId);
75     static shared_ptr<JsRuntime> GetCurrentRuntime();
76     static void PostJsTask(const shared_ptr<JsRuntime>&, std::function<void()>&& task);
77     static void TriggerPageUpdate(const shared_ptr<JsRuntime>&);
78     static RefPtr<PipelineBase> GetPipelineContext(const shared_ptr<JsRuntime>& runtime);
79     static void PreloadAceModule(void* runtime);
80 
GetJsMessageDispatcher()81     WeakPtr<JsMessageDispatcher> GetJsMessageDispatcher() const
82     {
83         return dispatcher_;
84     }
85 
SetRunningPage(const RefPtr<JsAcePage> & page)86     void SetRunningPage(const RefPtr<JsAcePage>& page)
87     {
88         std::lock_guard<std::mutex> lock(mutex_);
89         runningPage_ = page;
90     }
91 
GetRunningPage()92     RefPtr<JsAcePage> GetRunningPage() const
93     {
94         std::lock_guard<std::mutex> lock(mutex_);
95         return runningPage_;
96     }
97 
SetStagingPage(const RefPtr<JsAcePage> & page)98     void SetStagingPage(const RefPtr<JsAcePage>& page)
99     {
100         std::lock_guard<std::mutex> lock(mutex_);
101         stagingPage_ = page;
102     }
103 
GetStagingPage()104     RefPtr<JsAcePage> GetStagingPage() const
105     {
106         std::lock_guard<std::mutex> lock(mutex_);
107         return stagingPage_;
108     }
109 
ResetStagingPage(const RefPtr<JsAcePage> & page)110     void ResetStagingPage(const RefPtr<JsAcePage>& page)
111     {
112         stagingPage_ = page;
113     }
114 
SetJsMessageDispatcher(const RefPtr<JsMessageDispatcher> & dispatcher)115     void SetJsMessageDispatcher(const RefPtr<JsMessageDispatcher>& dispatcher)
116     {
117         dispatcher_ = dispatcher;
118     }
119 
GetDelegate()120     RefPtr<FrontendDelegate> GetDelegate() const
121     {
122         return frontendDelegate_;
123     }
124 
GetJsRuntime()125     shared_ptr<JsRuntime> GetJsRuntime()
126     {
127         return runtime_;
128     }
129 
SetDebugMode(bool isDebugMode)130     void SetDebugMode(bool isDebugMode)
131     {
132         isDebugMode_ = isDebugMode;
133     }
134 
135     void SetDebuggerPostTask();
136 
SetInstanceId(int32_t instanceId)137     void SetInstanceId(int32_t instanceId)
138     {
139         instanceId_ = instanceId;
140     }
141 
SetRootView(int32_t pageId,panda::Global<panda::ObjectRef> value)142     void SetRootView(int32_t pageId, panda::Global<panda::ObjectRef> value)
143     {
144         rootViewMap_.emplace(pageId, value);
145     }
146 
IsEngineInstanceInitialized()147     bool IsEngineInstanceInitialized()
148     {
149         return isEngineInstanceInitialized_;
150     }
151 
152     void RegisterFaPlugin(); // load ReatureAbility plugin
153 
SetContextValue(shared_ptr<JsValue> uiContext)154     void SetContextValue(shared_ptr<JsValue> uiContext)
155     {
156         uiContext_ = uiContext;
157     }
158 
159 #if defined(PREVIEW)
CallCurlFunction(const OHOS::Ace::RequestData & requestData,int32_t callbackId)160     bool CallCurlFunction(const OHOS::Ace::RequestData& requestData, int32_t callbackId)
161     {
162         auto dispatcher = dispatcher_.Upgrade();
163         if (dispatcher) {
164             dispatcher->CallCurlFunction(requestData, callbackId);
165             return true;
166         } else {
167             LOGW("Dispatcher Upgrade fail when dispatch request message to platform");
168             return false;
169         }
170     }
171 
InitAceModule(const uint8_t * start,size_t length)172     bool InitAceModule(const uint8_t* start, size_t length)
173     {
174         if (!runtime_) {
175             LOGE("jsi runtime is nullptr");
176         }
177         bool result = runtime_->EvaluateJsCode(start, length);
178         if (!result) {
179             LOGE("jsi runtime InitAceModule Evaluate JsCode failed");
180             return false;
181         }
182         return true;
183     }
184 #endif
185 
186 // ArkTsCard start
187     static void PreloadAceModuleCard(void* runtime, const std::unordered_set<std::string>& formModuleList);
188     static void ReloadAceModuleCard(void* runtime, const std::unordered_set<std::string>& formModuleList);
189 // ArkTsCard end
190     static bool IsPlugin();
191 private:
192     void InitGlobalObjectTemplate();
193     void InitConsoleModule();  // add Console object to global
194     void InitAceModule();      // add ace object to global
195     void InitPerfUtilModule(); // add perfutil object to global
196     void InitJsExportsUtilObject();
197     void InitJsNativeModuleObject();
198     void InitJsContextModuleObject();
199     void InitGroupJsBridge();
200     static shared_ptr<JsRuntime> InnerGetCurrentRuntime();
201     shared_ptr<JsValue> CallGetUIContextFunc(const shared_ptr<JsRuntime>& runtime,
202         const std::vector<shared_ptr<JsValue>>& argv);
203 
204     std::unordered_map<int32_t, panda::Global<panda::ObjectRef>> rootViewMap_;
205     static std::unique_ptr<JsonValue> currentConfigResourceData_;
206     static std::map<std::string, std::string> mediaResourceFileMap_;
207 
208     // runningPage_ is the page that is loaded and rendered successfully, while stagingPage_ is to
209     // handle all page routing situation, which include two stages:
210     // - Loading stage: when a new page is loaded by qjs engine but not rendered, stagingPage_ point to
211     //   a new created page, which is different with runningPage_, the DOM build operations should call
212     //   this one, such as domCreateBody, domAddElement.
213     // - Running stage: If the stagingPage_ rendered successfully, the runningPage_ will update to stagingPage_.
214     //   If the stagingPage_ render failed, it will reset to runningPage_. So in running stage, runningPage_
215     //   and stagingPage_ point to the same page. But it's better to use runningPage_ in dom update tasks,
216     //   such as removeElement, updateElementAttrs and updateElementStyles.
217     RefPtr<JsAcePage> runningPage_;
218     RefPtr<JsAcePage> stagingPage_;
219 
220     shared_ptr<JsRuntime> runtime_;
221     RefPtr<FrontendDelegate> frontendDelegate_;
222     WeakPtr<JsMessageDispatcher> dispatcher_;
223     mutable std::mutex mutex_;
224     bool isDebugMode_ = true;
225     bool usingSharedRuntime_ = false;
226     bool isEngineInstanceInitialized_ = false;
227     int32_t instanceId_ = 0;
228     static bool isModulePreloaded_;
229     static bool isModuleInitialized_;
230     static shared_ptr<JsRuntime> globalRuntime_;
231     shared_ptr<JsValue> uiContext_;
232 
233     ACE_DISALLOW_COPY_AND_MOVE(JsiDeclarativeEngineInstance);
234 };
235 
236 class JsiDeclarativeEngine : public JsEngine {
DECLARE_ACE_TYPE(JsiDeclarativeEngine,JsEngine)237     DECLARE_ACE_TYPE(JsiDeclarativeEngine, JsEngine)
238 public:
239     JsiDeclarativeEngine(int32_t instanceId, void* runtime) : instanceId_(instanceId), runtime_(runtime) {}
JsiDeclarativeEngine(int32_t instanceId)240     explicit JsiDeclarativeEngine(int32_t instanceId) : instanceId_(instanceId) {}
241     ~JsiDeclarativeEngine() override;
242 
243     bool Initialize(const RefPtr<FrontendDelegate>& delegate) override;
244 
245     void Destroy() override;
246 
247     // Load and initialize a JS bundle into the JS Framework
248     void LoadJs(const std::string& url, const RefPtr<JsAcePage>& page, bool isMainPage) override;
249 #if !defined(PREVIEW)
250     bool IsModule();
251 
252     void LoadJsWithModule(std::string& urlName,
253         const std::function<void(const std::string&, int32_t)>& errorCallback = nullptr);
254 
255     void LoadPluginJsWithModule(std::string& urlName);
256 
257 #endif
258     // Load the app.js file of the FA model in NG structure..
259     bool LoadFaAppSource() override;
260 
261     // Load the je file of the page in NG structure..
262     bool LoadPageSource(const std::string& url,
263         const std::function<void(const std::string&, int32_t)>& errorCallback = nullptr) override;
264 
265     bool LoadCard(const std::string& url, int64_t cardId) override;
266 
267     // Update running page
268     void UpdateRunningPage(const RefPtr<JsAcePage>& page) override;
269 
270     // Update staging page
271     void UpdateStagingPage(const RefPtr<JsAcePage>& page) override;
272 
273     // Reset staging page
274     void ResetStagingPage() override;
275 
276     void SetJsMessageDispatcher(const RefPtr<JsMessageDispatcher>& dispatcher) override;
277 
278     // Fire AsyncEvent on JS
279     void FireAsyncEvent(const std::string& eventId, const std::string& param) override;
280 
281     // Fire SyncEvent on JS
282     void FireSyncEvent(const std::string& eventId, const std::string& param) override;
283 
284     void FireExternalEvent(const std::string& componentId, uint32_t nodeId, bool isDestroy) override;
285 
286     // Timer callback
287     void TimerCallback(const std::string& callbackId, const std::string& delay, bool isInterval) override;
288 
289     // Destroy page instance
290     void DestroyPageInstance(int32_t pageId) override;
291 
292     void OnActive() override;
293 
294     void OnInactive() override;
295 
296     void OnNewWant(const std::string& data) override;
297 
298     bool OnStartContinuation() override;
299 
300     void OnCompleteContinuation(int32_t code) override;
301 
302     void OnRemoteTerminated() override;
303 
304     void OnSaveData(std::string& data) override;
305 
306     bool OnRestoreData(const std::string& data) override;
307 
308     // Destroy application instance according to packageName
309     void DestroyApplication(const std::string& packageName) override;
310 
311     void UpdateApplicationState(const std::string& packageName, Frontend::State state) override;
312 
313     void OnWindowDisplayModeChanged(bool isShownInMultiWindow, const std::string& data) override;
314 
315     void MediaQueryCallback(const std::string& callbackId, const std::string& args) override;
316 
317     void RequestAnimationCallback(const std::string& callbackId, uint64_t timeStamp) override;
318 
319     void JsCallback(const std::string& callbackId, const std::string& args) override;
320 
321     void RunGarbageCollection() override;
322 
323     void RunFullGarbageCollection() override;
324 
325     void DumpHeapSnapshot(bool isPrivate) override;
326 
327     std::string GetStacktraceMessage() override;
328 
329     void GetStackTrace(std::string& trace) override;
330 
331     void SetLocalStorage(int32_t instanceId, NativeReference* storage) override;
332 
333     void SetContext(int32_t instanceId, NativeReference* context) override;
334 
335     void SetErrorEventHandler(
336         std::function<void(const std::string&, const std::string&)>&& errorCallback) override;
337 
338     RefPtr<GroupJsBridge> GetGroupJsBridge() override;
339 
GetFrontend()340     RefPtr<FrontendDelegate> GetFrontend() override
341     {
342         return engineInstance_->GetDelegate();
343     }
344 
GetEngineInstance()345     RefPtr<JsiDeclarativeEngineInstance> GetEngineInstance()
346     {
347         return engineInstance_;
348     }
349 
FlushReload()350     void FlushReload() override
351     {
352         if (engineInstance_) {
353             engineInstance_->FlushReload();
354         }
355     }
356 
RunNativeEngineLoop()357     void RunNativeEngineLoop() override
358     {
359         if (nativeEngine_ != nullptr) {
360             nativeEngine_->Loop(LOOP_NOWAIT, false);
361         }
362     }
363 
GetRenderContext()364     const shared_ptr<JsValue>& GetRenderContext() const
365     {
366         return renderContext_;
367     }
368 
SetPluginBundleName(const std::string & pluginBundleName)369     void SetPluginBundleName(const std::string& pluginBundleName) override
370     {
371         pluginBundleName_ = pluginBundleName;
372     }
373 
SetPluginModuleName(const std::string & pluginModuleName)374     void SetPluginModuleName(const std::string& pluginModuleName) override
375     {
376         pluginModuleName_ = pluginModuleName;
377     }
378 
GetContextValue()379     NativeValue* GetContextValue() override
380     {
381         return engineInstance_->GetContextValue();
382     }
383 #if defined(PREVIEW)
384     void ReplaceJSContent(const std::string& url, const std::string componentName) override;
385     RefPtr<Component> GetNewComponentWithJsCode(const std::string& jsCode, const std::string& viewID) override;
386     bool ExecuteJsForFastPreview(const std::string& jsCode, const std::string& viewID) override;
387 
InitializeModuleSearcher(const std::string & bundleName,const std::string & moduleName,const std::string assetPath,bool isBundle)388     void InitializeModuleSearcher(const std::string& bundleName, const std::string& moduleName,
389         const std::string assetPath, bool isBundle) override
390     {
391         bundleName_ = bundleName;
392         moduleName_ = moduleName;
393         assetPath_ = assetPath;
394         isBundle_ = isBundle;
395     }
396 #endif
397     void AddToNamedRouterMap(panda::Global<panda::FunctionRef> pageGenerator, const std::string& namedRoute,
398         panda::Local<panda::ObjectRef> params);
399     bool LoadNamedRouterSource(const std::string& namedRoute, bool isTriggeredByJs) override;
400 
401 private:
402     bool CallAppFunc(const std::string& appFuncName);
403 
404     bool CallAppFunc(const std::string& appFuncName, std::vector<shared_ptr<JsValue>>& argv);
405 
406     void SetPostTask(NativeEngine* nativeEngine);
407 
408     void TimerCallJs(const std::string& callbackId) const;
409 
410     void InitXComponent(const std::string& componentId);
411 
412     void RegisterWorker();
413     void RegisterInitWorkerFunc();
414     void RegisterOffWorkerFunc();
415     void RegisterAssetFunc();
416     bool ExecuteAbc(const std::string& fileName);
417     bool ExecuteCardAbc(const std::string& fileName, int64_t cardId);
418 
419     RefPtr<JsiDeclarativeEngineInstance> engineInstance_;
420 
421     RefPtr<NativeXComponentImpl> nativeXComponentImpl_;
422 
423     OH_NativeXComponent* nativeXComponent_ = nullptr;
424 
425     int32_t instanceId_ = 0;
426     void* runtime_ = nullptr;
427     shared_ptr<JsValue> renderContext_;
428 #if defined(PREVIEW)
429     std::string assetPath_;
430     std::string bundleName_;
431     std::string moduleName_;
432     bool isBundle_ = true;
433 #endif
434     std::string pluginBundleName_;
435     std::string pluginModuleName_;
436     std::unordered_map<std::string, NamedRouterProperty> namedRouterRegisterMap;
437     bool isFirstCallShow_ = true;
438     ACE_DISALLOW_COPY_AND_MOVE(JsiDeclarativeEngine);
439 };
440 
441 } // namespace OHOS::Ace::Framework
442 
443 #endif // FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_ENGINE_JSI_JSI_DECLARATIVE_ENGINE_H
444