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