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