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