• 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 #include "frameworks/bridge/declarative_frontend/engine/quickjs/qjs_declarative_engine.h"
17 
18 #include <cstdlib>
19 
20 #include "native_engine/impl/quickjs/quickjs_native_engine.h"
21 #include "base/log/ace_trace.h"
22 #include "base/log/event_report.h"
23 #include "base/log/log.h"
24 #include "core/common/ace_view.h"
25 #include "core/common/container.h"
26 #include "core/common/container_scope.h"
27 #include "core/components/xcomponent/xcomponent_component_client.h"
28 #include "frameworks/bridge/declarative_frontend/engine/quickjs/modules/qjs_module_manager.h"
29 #include "frameworks/bridge/declarative_frontend/engine/quickjs/qjs_helpers.h"
30 #include "frameworks/bridge/declarative_frontend/frontend_delegate_declarative.h"
31 #include "frameworks/bridge/declarative_frontend/jsview/js_xcomponent.h"
32 #include "frameworks/bridge/declarative_frontend/view_stack_processor.h"
33 #include "frameworks/bridge/js_frontend/engine/common/js_constants.h"
34 #include "frameworks/bridge/js_frontend/engine/quickjs/qjs_utils.h"
35 
36 namespace OHOS::Ace::Framework {
37 
~QJSDeclarativeEngine()38 QJSDeclarativeEngine::~QJSDeclarativeEngine()
39 {
40     if (nativeEngine_ != nullptr) {
41 #if !defined(PREVIEW)
42         nativeEngine_->CancelCheckUVLoop();
43 #endif
44         nativeEngine_->DeleteEngine();
45         delete nativeEngine_;
46     }
47     if (engineInstance_ && engineInstance_->GetQJSRuntime()) {
48         JS_RunGC(engineInstance_->GetQJSRuntime());
49     }
50 }
51 
Initialize(const RefPtr<FrontendDelegate> & delegate)52 bool QJSDeclarativeEngine::Initialize(const RefPtr<FrontendDelegate>& delegate)
53 {
54     LOGI("QJSDeclarativeEngine initialize");
55     JSRuntime* runtime = nullptr;
56     JSContext* context = nullptr;
57 
58     // put JS_NewContext as early as possible to make stack_top in context
59     // closer to the top stack frame pointer of JS thread.
60     runtime = JS_NewRuntime();
61     if (runtime != nullptr) {
62         context = JS_NewContext(runtime);
63     }
64 
65     engineInstance_ = AceType::MakeRefPtr<QJSDeclarativeEngineInstance>(delegate, instanceId_);
66     nativeEngine_ = new QuickJSNativeEngine(runtime, context, static_cast<void*>(this));
67     engineInstance_->SetNativeEngine(nativeEngine_);
68     bool res = engineInstance_->InitJSEnv(runtime, context, GetExtraNativeObject());
69     if (!res) {
70         LOGE("QJSDeclarativeEngine initialize failed: %{public}d", instanceId_);
71         return false;
72     }
73     SetPostTask(nativeEngine_);
74 #if !defined(PREVIEW)
75     nativeEngine_->CheckUVLoop();
76 #endif
77     if (delegate && delegate->GetAssetManager()) {
78         std::vector<std::string> packagePath = delegate->GetAssetManager()->GetLibPath();
79         if (!packagePath.empty()) {
80             auto qjsNativeEngine = static_cast<QuickJSNativeEngine*>(nativeEngine_);
81             qjsNativeEngine->SetPackagePath(packagePath);
82         }
83     }
84     RegisterWorker();
85 
86     return true;
87 }
88 
SetPostTask(NativeEngine * nativeEngine)89 void QJSDeclarativeEngine::SetPostTask(NativeEngine* nativeEngine)
90 {
91     LOGI("SetPostTask");
92     auto weakDelegate = AceType::WeakClaim(AceType::RawPtr(engineInstance_->GetDelegate()));
93     auto&& postTask = [weakDelegate, nativeEngine = nativeEngine_, id = instanceId_](bool needSync) {
94         auto delegate = weakDelegate.Upgrade();
95         if (delegate == nullptr) {
96             LOGE("delegate is nullptr");
97             return;
98         }
99         delegate->PostJsTask([nativeEngine, needSync, id]() {
100             ContainerScope scope(id);
101             if (nativeEngine == nullptr) {
102                 return;
103             }
104             nativeEngine->Loop(LOOP_NOWAIT, needSync);
105         });
106     };
107     nativeEngine_->SetPostTask(postTask);
108 }
109 
RegisterInitWorkerFunc()110 void QJSDeclarativeEngine::RegisterInitWorkerFunc()
111 {
112     auto&& initWorkerFunc = [](NativeEngine* nativeEngine) {
113         LOGI("WorkerCore RegisterInitWorkerFunc called");
114         if (nativeEngine == nullptr) {
115             LOGE("nativeEngine is nullptr");
116             return;
117         }
118         auto qjsNativeEngine = static_cast<QuickJSNativeEngine*>(nativeEngine);
119         if (qjsNativeEngine == nullptr) {
120             LOGE("qjsNativeEngine is nullptr");
121             return;
122         }
123 
124         JSContext* ctx = qjsNativeEngine->GetContext();
125         if (ctx == nullptr) {
126             LOGE("ctx is nullptr");
127             return;
128         }
129         // Note: default 256KB is not enough
130         JS_SetMaxStackSize(ctx, MAX_STACK_SIZE);
131 
132         InitConsole(ctx);
133     };
134     nativeEngine_->SetInitWorkerFunc(initWorkerFunc);
135 }
136 
RegisterAssetFunc()137 void QJSDeclarativeEngine::RegisterAssetFunc()
138 {
139     auto weakDelegate = AceType::WeakClaim(AceType::RawPtr(engineInstance_->GetDelegate()));
140     auto&& assetFunc = [weakDelegate](const std::string& uri, std::vector<uint8_t>& content, std::string& ami) {
141         LOGI("WorkerCore RegisterAssetFunc called");
142         auto delegate = weakDelegate.Upgrade();
143         if (delegate == nullptr) {
144             LOGE("delegate is nullptr");
145             return;
146         }
147         delegate->GetResourceData(uri, content, ami);
148     };
149     nativeEngine_->SetGetAssetFunc(assetFunc);
150 }
151 
RegisterWorker()152 void QJSDeclarativeEngine::RegisterWorker()
153 {
154     RegisterInitWorkerFunc();
155     RegisterAssetFunc();
156 }
157 
LoadJs(const std::string & url,const RefPtr<JsAcePage> & page,bool isMainPage)158 void QJSDeclarativeEngine::LoadJs(const std::string& url, const RefPtr<JsAcePage>& page, bool isMainPage)
159 {
160     LOGD("QJSDeclarativeEngine LoadJs");
161     ACE_SCOPED_TRACE("QJSDeclarativeEngine::LoadJS");
162     ACE_DCHECK(engineInstance_);
163     engineInstance_->SetRunningPage(page);
164     JSContext* ctx = engineInstance_->GetQJSContext();
165     JS_SetContextOpaque(ctx, reinterpret_cast<void*>(AceType::RawPtr(engineInstance_)));
166     if (isMainPage) {
167         std::string commonsJsContent;
168         if (engineInstance_->GetDelegate()->GetAssetContent("commons.js", commonsJsContent)) {
169             auto commonsJsResult = QJSDeclarativeEngineInstance::EvalBuf(
170                 ctx, commonsJsContent.c_str(), commonsJsContent.length(), "commons.js", JS_EVAL_TYPE_GLOBAL);
171             if (commonsJsResult == -1) {
172                 LOGE("fail to execute load commonsjs script");
173                 return;
174             }
175         }
176         std::string vendorsJsContent;
177         if (engineInstance_->GetDelegate()->GetAssetContent("vendors.js", vendorsJsContent)) {
178             auto vendorsJsResult = QJSDeclarativeEngineInstance::EvalBuf(
179                 ctx, vendorsJsContent.c_str(), vendorsJsContent.length(), "vendors.js", JS_EVAL_TYPE_GLOBAL);
180             if (vendorsJsResult == -1) {
181                 LOGE("fail to execute load vendorsjs script");
182                 return;
183             }
184         }
185         std::string appjsContent;
186         if (!engineInstance_->GetDelegate()->GetAssetContent("app.js", appjsContent)) {
187             LOGE("js file load failed!");
188         }
189         std::string appMap;
190         if (engineInstance_->GetDelegate()->GetAssetContent("app.js.map", appMap)) {
191             page->SetAppMap(appMap);
192         } else {
193             LOGI("app map is missing!");
194         }
195         auto result = QJSDeclarativeEngineInstance::EvalBuf(
196             ctx, appjsContent.c_str(), appjsContent.length(), "app.js", JS_EVAL_TYPE_GLOBAL);
197         if (result == -1) {
198             LOGE("failed to execute Loadjs script");
199         } else {
200             CallAppFunc("onCreate", 0, nullptr);
201         }
202     }
203 
204     std::string pageMap;
205     if (engineInstance_->GetDelegate()->GetAssetContent(url + ".map", pageMap)) {
206         page->SetPageMap(pageMap);
207     } else {
208         LOGI("the source map of page load failed!");
209     }
210 
211     std::string jsContent;
212     if (!engineInstance_->GetDelegate()->GetAssetContent(url, jsContent)) {
213         LOGE("js file load failed!");
214         return;
215     }
216 
217     if (jsContent.empty()) {
218         LOGE("js file load failed! url=[%{public}s]", url.c_str());
219         return;
220     }
221 
222     JSValue compiled = engineInstance_->CompileSource(GetInstanceName(), url, jsContent.c_str(), jsContent.size());
223     if (JS_IsException(compiled)) {
224         LOGE("js compilation failed url=[%{public}s]", url.c_str());
225         QJSUtils::JsStdDumpErrorAce(
226             ctx, JsErrorType::LOAD_JS_BUNDLE_ERROR, instanceId_, page->GetUrl().c_str(), page, true);
227         return;
228     }
229     engineInstance_->ExecuteDocumentJS(compiled);
230     js_std_loop(engineInstance_->GetQJSContext());
231 }
232 
LoadPageSource(const std::string & url)233 bool QJSDeclarativeEngine::LoadPageSource(const std::string& url)
234 {
235     LOGI("QJSDeclarativeEngine LoadPageSource");
236     ACE_SCOPED_TRACE("QJSDeclarativeEngine::LoadJS");
237     ACE_DCHECK(engineInstance_);
238     JSContext* ctx = engineInstance_->GetQJSContext();
239     JS_SetContextOpaque(ctx, reinterpret_cast<void*>(AceType::RawPtr(engineInstance_)));
240 
241     std::string jsContent;
242     if (!engineInstance_->GetDelegate()->GetAssetContent(url, jsContent)) {
243         LOGE("js file load failed!");
244         return false;
245     }
246 
247     if (jsContent.empty()) {
248         LOGE("js file load failed! url=[%{public}s]", url.c_str());
249         return false;
250     }
251 
252     JSValue compiled = engineInstance_->CompileSource(GetInstanceName(), url, jsContent.c_str(), jsContent.size());
253     if (JS_IsException(compiled)) {
254         LOGE("js compilation failed url=[%{public}s]", url.c_str());
255         return false;
256     }
257     engineInstance_->ExecuteDocumentJS(compiled);
258     js_std_loop(engineInstance_->GetQJSContext());
259     return true;
260 }
261 
LoadFaAppSource()262 bool QJSDeclarativeEngine::LoadFaAppSource()
263 {
264     LOGI("QJSDeclarativeEngine LoadFaAppSource");
265     ACE_SCOPED_TRACE("QJSDeclarativeEngine::LoadJS");
266     ACE_DCHECK(engineInstance_);
267     JSContext* ctx = engineInstance_->GetQJSContext();
268     std::string commonsJsContent;
269     if (engineInstance_->GetDelegate()->GetAssetContent("commons.js", commonsJsContent)) {
270         auto commonsJsResult = QJSDeclarativeEngineInstance::EvalBuf(
271             ctx, commonsJsContent.c_str(), commonsJsContent.length(), "commons.js", JS_EVAL_TYPE_GLOBAL);
272         if (commonsJsResult == -1) {
273             LOGE("fail to execute load commonsjs script");
274             return false;
275         }
276     }
277     std::string vendorsJsContent;
278     if (engineInstance_->GetDelegate()->GetAssetContent("vendors.js", vendorsJsContent)) {
279         auto vendorsJsResult = QJSDeclarativeEngineInstance::EvalBuf(
280             ctx, vendorsJsContent.c_str(), vendorsJsContent.length(), "vendors.js", JS_EVAL_TYPE_GLOBAL);
281         if (vendorsJsResult == -1) {
282             LOGE("fail to execute load vendorsjs script");
283             return false;
284         }
285     }
286     std::string appjsContent;
287     if (!engineInstance_->GetDelegate()->GetAssetContent("app.js", appjsContent)) {
288         LOGE("js file load failed!");
289     }
290 
291     auto result = QJSDeclarativeEngineInstance::EvalBuf(
292         ctx, appjsContent.c_str(), appjsContent.length(), "app.js", JS_EVAL_TYPE_GLOBAL);
293     if (result == -1) {
294         LOGE("failed to execute Loadjs script");
295     } else {
296         CallAppFunc("onCreate", 0, nullptr);
297     }
298     return true;
299 }
300 
301 #if defined(PREVIEW)
ReplaceJSContent(const std::string & url,const std::string componentName)302 void QJSDeclarativeEngine::ReplaceJSContent(const std::string& url, const std::string componentName)
303 {
304     auto* instance = static_cast<QJSDeclarativeEngineInstance*>(JS_GetContextOpaque(engineInstance_->GetQJSContext()));
305     if (instance == nullptr) {
306         LOGE("Can not cast Context to QJSDeclarativeEngineInstance object.");
307         return;
308     }
309     instance->SetPreviewFlag(true);
310     instance->SetRequiredComponent(componentName);
311 
312     instance->GetDelegate()->Replace(url, "");
313 }
314 #endif
GetNewComponentWithJsCode(const std::string & jsCode,const std::string & viewID)315 RefPtr<Component> QJSDeclarativeEngine::GetNewComponentWithJsCode(const std::string& jsCode, const std::string& viewID)
316 {
317 #ifdef NG_BUILD
318     return nullptr;
319 #else
320     ViewStackProcessor::GetInstance()->ClearStack();
321     ViewStackProcessor::GetInstance()->PushKey(viewID);
322     bool result = engineInstance_->InitAceModules(jsCode.c_str(), jsCode.length(), "AddComponent");
323     ViewStackProcessor::GetInstance()->PopKey();
324     if (!result) {
325         LOGE("execute addComponent failed,script=[%{public}s]", jsCode.c_str());
326         return nullptr;
327     }
328     auto component = ViewStackProcessor::GetInstance()->GetNewComponent();
329     return component;
330 #endif
331 }
332 
UpdateRunningPage(const RefPtr<JsAcePage> & page)333 void QJSDeclarativeEngine::UpdateRunningPage(const RefPtr<JsAcePage>& page)
334 {
335     ACE_DCHECK(engineInstance_);
336     engineInstance_->SetRunningPage(page);
337     js_std_loop(engineInstance_->GetQJSContext());
338 }
339 
UpdateStagingPage(const RefPtr<JsAcePage> & page)340 void QJSDeclarativeEngine::UpdateStagingPage(const RefPtr<JsAcePage>& page)
341 {
342     ACE_DCHECK(engineInstance_);
343     engineInstance_->SetStagingPage(page);
344     js_std_loop(engineInstance_->GetQJSContext());
345 }
346 
ResetStagingPage()347 void QJSDeclarativeEngine::ResetStagingPage()
348 {
349     ACE_DCHECK(engineInstance_);
350     auto runningPage = engineInstance_->GetRunningPage();
351     engineInstance_->ResetStagingPage(runningPage);
352     js_std_loop(engineInstance_->GetQJSContext());
353 }
354 
DestroyPageInstance(int32_t pageId)355 void QJSDeclarativeEngine::DestroyPageInstance(int32_t pageId)
356 {
357     LOGE("Not implemented!");
358     js_std_loop(engineInstance_->GetQJSContext());
359 }
360 
CallAppFunc(const std::string & appFuncName,int argc,JSValueConst * argv)361 void QJSDeclarativeEngine::CallAppFunc(const std::string& appFuncName, int argc, JSValueConst* argv)
362 {
363     JSContext* ctx = engineInstance_->GetQJSContext();
364     if (!ctx) {
365         LOGE("context is null");
366         return;
367     }
368     JSValue ret = JS_NULL;
369     CallAppFunc(appFuncName, argc, argv, ret);
370     js_std_loop(ctx);
371     JS_FreeValue(ctx, ret);
372 }
373 
CallAppFunc(const std::string & appFuncName,int argc,JSValueConst * argv,JSValue & ret)374 void QJSDeclarativeEngine::CallAppFunc(const std::string& appFuncName, int argc, JSValueConst* argv, JSValue& ret)
375 {
376     JSContext* ctx = engineInstance_->GetQJSContext();
377     if (!ctx) {
378         LOGE("context is null");
379         return;
380     }
381     JSValue globalObj = JS_GetGlobalObject(ctx);
382     JSValue exportobj = JS_GetPropertyStr(ctx, globalObj, "exports");
383     JSValue defaultobj = JS_GetPropertyStr(ctx, exportobj, "default");
384 
385     JSValue appFunc = JS_GetPropertyStr(ctx, defaultobj, appFuncName.c_str());
386     if (!JS_IsFunction(ctx, appFunc)) {
387         LOGE("cannot find %s function", appFuncName.c_str());
388         return;
389     }
390     ret = JS_Call(ctx, appFunc, defaultobj, argc, argv);
391     js_std_loop(ctx);
392     JS_FreeValue(ctx, appFunc);
393     JS_FreeValue(ctx, defaultobj);
394     JS_FreeValue(ctx, exportobj);
395     JS_FreeValue(ctx, globalObj);
396 }
397 
DestroyApplication(const std::string & packageName)398 void QJSDeclarativeEngine::DestroyApplication(const std::string& packageName)
399 {
400     LOGI("Enter DestroyApplication: destroy, packageName %{public}s", packageName.c_str());
401     CallAppFunc("onDestroy", 0, nullptr);
402     js_std_loop(engineInstance_->GetQJSContext());
403 }
404 
UpdateApplicationState(const std::string & packageName,Frontend::State state)405 void QJSDeclarativeEngine::UpdateApplicationState(const std::string& packageName, Frontend::State state)
406 {
407     LOGD("Enter UpdateApplicationState: destroy, packageName %{public}s", packageName.c_str());
408 
409     if (state == Frontend::State::ON_SHOW) {
410         CallAppFunc("onShow", 0, nullptr);
411     } else if (state == Frontend::State::ON_HIDE) {
412         CallAppFunc("onHide", 0, nullptr);
413     }
414 
415     js_std_loop(engineInstance_->GetQJSContext());
416 }
417 
OnWindowDisplayModeChanged(bool isShownInMultiWindow,const std::string & data)418 void QJSDeclarativeEngine::OnWindowDisplayModeChanged(bool isShownInMultiWindow, const std::string& data)
419 {
420     JSContext* ctx = engineInstance_->GetQJSContext();
421     if (!ctx) {
422         LOGE("context is null");
423         return;
424     }
425 
426     JSValueConst callBackResult[] = { JS_NewBool(ctx, isShownInMultiWindow),
427         JS_ParseJSON(ctx, data.c_str(), data.length(), "") };
428     CallAppFunc("onWindowDisplayModeChanged", 2, callBackResult);
429 
430     js_std_loop(engineInstance_->GetQJSContext());
431 }
432 
OnConfigurationUpdated(const std::string & data)433 void QJSDeclarativeEngine::OnConfigurationUpdated(const std::string& data)
434 {
435     JSContext* ctx = engineInstance_->GetQJSContext();
436     if (!ctx) {
437         LOGE("context is null");
438         return;
439     }
440 
441     JSValueConst callBackResult[] = { JS_ParseJSON(ctx, data.c_str(), data.length(), "") };
442     CallAppFunc("onConfigurationUpdated", 1, callBackResult);
443 
444     js_std_loop(engineInstance_->GetQJSContext());
445 }
446 
OnStartContinuation()447 bool QJSDeclarativeEngine::OnStartContinuation()
448 {
449     JSContext* ctx = engineInstance_->GetQJSContext();
450     if (!ctx) {
451         LOGE("context is null");
452         return false;
453     }
454     JSValue ret = JS_NULL;
455     CallAppFunc("onStartContinuation", 0, nullptr, ret);
456     std::string result = JS_ToCString(ctx, ret);
457     js_std_loop(engineInstance_->GetQJSContext());
458     return (result == "true");
459 }
460 
OnCompleteContinuation(int32_t code)461 void QJSDeclarativeEngine::OnCompleteContinuation(int32_t code)
462 {
463     JSContext* ctx = engineInstance_->GetQJSContext();
464     if (!ctx) {
465         LOGE("context is null");
466         return;
467     }
468     JSValueConst callBackResult[] = { JS_NewInt32(ctx, code) };
469     CallAppFunc("onCompleteContinuation", 1, callBackResult);
470     js_std_loop(engineInstance_->GetQJSContext());
471 }
472 
OnRemoteTerminated()473 void QJSDeclarativeEngine::OnRemoteTerminated()
474 {
475     JSContext* ctx = engineInstance_->GetQJSContext();
476     if (!ctx) {
477         LOGE("context is null");
478         return;
479     }
480     CallAppFunc("onRemoteTerminated", 0, nullptr);
481     js_std_loop(engineInstance_->GetQJSContext());
482 }
483 
OnSaveData(std::string & data)484 void QJSDeclarativeEngine::OnSaveData(std::string& data)
485 {
486     JSContext* ctx = engineInstance_->GetQJSContext();
487     if (!ctx) {
488         LOGE("context is null");
489         return;
490     }
491     JSValue object = JS_NewObject(ctx);
492     JSValueConst callBackResult[] = { object };
493     JSValue ret = JS_NULL;
494     CallAppFunc("onSaveData", 1, callBackResult, ret);
495     if (JS_ToCString(ctx, ret) == std::string("true")) {
496         data = ScopedString::Stringify(ctx, object);
497     }
498     js_std_loop(engineInstance_->GetQJSContext());
499 }
500 
OnRestoreData(const std::string & data)501 bool QJSDeclarativeEngine::OnRestoreData(const std::string& data)
502 {
503     JSContext* ctx = engineInstance_->GetQJSContext();
504     if (!ctx) {
505         LOGE("context is null");
506         return false;
507     }
508     JSValue jsonObj = JS_ParseJSON(ctx, data.c_str(), data.length(), "");
509     if (JS_IsUndefined(jsonObj) || JS_IsException(jsonObj)) {
510         LOGE("Parse json for restore data failed.");
511         return false;
512     }
513     JSValueConst callBackResult[] = { jsonObj };
514     JSValue ret = JS_NULL;
515     CallAppFunc("onRestoreData", 1, callBackResult, ret);
516     std::string result = JS_ToCString(ctx, ret);
517     js_std_loop(engineInstance_->GetQJSContext());
518     return (result == "true");
519 }
520 
TimerCallback(const std::string & callbackId,const std::string & delay,bool isInterval)521 void QJSDeclarativeEngine::TimerCallback(const std::string& callbackId, const std::string& delay, bool isInterval)
522 {
523     // string with function source
524     LOGD("CallbackId %s", callbackId.c_str());
525     JSContext* ctx = engineInstance_->GetQJSContext();
526     QJSContext::Scope scp(ctx);
527 
528     if (isInterval) {
529         TimerCallJs(callbackId, isInterval);
530         engineInstance_->GetDelegate()->WaitTimer(callbackId, delay, isInterval, false);
531     } else {
532         TimerCallJs(callbackId, isInterval);
533         JSContext* ctx = engineInstance_->GetQJSContext();
534         if (!ctx) {
535             LOGE("TimerCallback no context");
536             return;
537         }
538         ModuleManager::GetInstance()->RemoveCallbackFunc(ctx, std::stoi(callbackId), isInterval);
539         engineInstance_->GetDelegate()->ClearTimer(callbackId);
540     }
541     js_std_loop(engineInstance_->GetQJSContext());
542 }
543 
TimerCallJs(const std::string & callbackId,bool isInterval)544 void QJSDeclarativeEngine::TimerCallJs(const std::string& callbackId, bool isInterval)
545 {
546     JSContext* ctx = engineInstance_->GetQJSContext();
547     if (!ctx) {
548         LOGE("TimerCallJs no context");
549         return;
550     }
551 
552     JSValue jsFunc = ModuleManager::GetInstance()->GetCallbackFunc(std::stoi(callbackId), isInterval);
553     if (!JS_IsFunction(ctx, jsFunc)) {
554         LOGE("TimerCallJs is not func");
555         return;
556     }
557     std::vector<JSValue> jsargv = ModuleManager::GetInstance()->GetCallbackArray(std::stoi(callbackId), isInterval);
558     if (jsargv.empty()) {
559         JS_Call(ctx, jsFunc, JS_UNDEFINED, 0, nullptr);
560     } else {
561         JSValue* argv = new JSValue[jsargv.size()];
562         uint32_t index = 0;
563         while (index < jsargv.size()) {
564             argv[index] = jsargv[index];
565             ++index;
566         }
567         JS_Call(ctx, jsFunc, JS_UNDEFINED, jsargv.size(), argv);
568     }
569     js_std_loop(ctx);
570 }
571 
MediaQueryCallback(const std::string & callbackId,const std::string & args)572 void QJSDeclarativeEngine::MediaQueryCallback(const std::string& callbackId, const std::string& args)
573 {
574     JsEngine::MediaQueryCallback(callbackId, args);
575 }
576 
RequestAnimationCallback(const std::string & callbackId,uint64_t timeStamp)577 void QJSDeclarativeEngine::RequestAnimationCallback(const std::string& callbackId, uint64_t timeStamp)
578 {
579     LOGD("Enter RequestAnimationCallback");
580 }
581 
JsCallback(const std::string & callbackId,const std::string & args)582 void QJSDeclarativeEngine::JsCallback(const std::string& callbackId, const std::string& args)
583 {
584     LOGD("Enter JSCallback");
585 }
586 
FireAsyncEvent(const std::string & eventId,const std::string & param)587 void QJSDeclarativeEngine::FireAsyncEvent(const std::string& eventId, const std::string& param)
588 {
589     LOGW("QJSDeclarativeEngine FireAsyncEvent is unusable");
590 }
591 
FireSyncEvent(const std::string & eventId,const std::string & param)592 void QJSDeclarativeEngine::FireSyncEvent(const std::string& eventId, const std::string& param)
593 {
594     LOGW("QJSDeclarativeEngine FireSyncEvent is unusable");
595 }
596 
FireExternalEvent(const std::string & componentId,const uint32_t nodeId,const bool isDestroy)597 void QJSDeclarativeEngine::FireExternalEvent(
598     const std::string& componentId, const uint32_t nodeId, const bool isDestroy)
599 {
600 #ifndef NG_BUILD
601 #ifdef XCOMPONENT_SUPPORTED
602     if (isDestroy) {
603         XComponentComponentClient::GetInstance().DeleteFromXcomponentsMapById(componentId);
604         XComponentClient::GetInstance().DeleteControllerFromJSXComponentControllersMap(componentId);
605         XComponentClient::GetInstance().DeleteFromNativeXcomponentsMapById(componentId);
606         XComponentClient::GetInstance().DeleteFromJsValMapById(componentId);
607         return;
608     }
609     std::tie(nativeXComponentImpl_, nativeXComponent_) =
610         XComponentClient::GetInstance().GetNativeXComponentFromXcomponentsMap(componentId);
611 
612     RefPtr<XComponentComponent> xcomponent =
613         XComponentComponentClient::GetInstance().GetXComponentFromXcomponentsMap(componentId);
614     if (!xcomponent) {
615         LOGE("FireExternalEvent xcomponent is null.");
616         return;
617     }
618 
619     void* nativeWindow = nullptr;
620 #ifdef OHOS_STANDARD_SYSTEM
621     nativeWindow = const_cast<void*>(xcomponent->GetNativeWindow());
622 #else
623     auto container = Container::Current();
624     if (!container) {
625         LOGE("FireExternalEvent Current container null");
626         return;
627     }
628     auto nativeView = static_cast<AceView*>(container->GetView());
629     if (!nativeView) {
630         LOGE("FireExternalEvent nativeView null");
631         return;
632     }
633     auto textureId = static_cast<uint64_t>(xcomponent->GetTextureId());
634     LOGE("FireExternalEvent textureId = %{public}" PRIu64, textureId);
635     nativeWindow = const_cast<void*>(nativeView->GetNativeWindowById(textureId));
636 #endif
637 
638     if (!nativeWindow) {
639         LOGE("FireExternalEvent nativeWindow invalid");
640         return;
641     }
642     nativeXComponentImpl_->SetSurface(nativeWindow);
643     nativeXComponentImpl_->SetXComponentId(xcomponent->GetId());
644 
645     auto nativeEngine = static_cast<QuickJSNativeEngine*>(nativeEngine_);
646     if (nativeEngine == nullptr) {
647         LOGE("nativeEngine is null");
648         return;
649     }
650 
651     std::string args;
652     auto renderContext = nativeEngine->LoadModuleByName(
653         xcomponent->GetLibraryName(), true, args, OH_NATIVE_XCOMPONENT_OBJ, reinterpret_cast<void*>(nativeXComponent_));
654 
655     JSRef<JSObject> obj = JSRef<JSObject>::Make(renderContext);
656     XComponentClient::GetInstance().AddJsValToJsValMap(componentId, obj);
657 
658     auto task = [weak = WeakClaim(this), xcomponent]() {
659         auto pool = xcomponent->GetTaskPool();
660         if (!pool) {
661             return;
662         }
663         auto bridge = weak.Upgrade();
664         if (bridge) {
665             pool->NativeXComponentInit(
666                 bridge->nativeXComponent_, AceType::WeakClaim(AceType::RawPtr(bridge->nativeXComponentImpl_)));
667         }
668     };
669 
670     auto delegate = engineInstance_->GetDelegate();
671     if (!delegate) {
672         LOGE("Delegate is null");
673         return;
674     }
675     delegate->PostSyncTaskToPage(task);
676 #endif
677 #endif
678 }
679 
SetJsMessageDispatcher(const RefPtr<JsMessageDispatcher> & dispatcher)680 void QJSDeclarativeEngine::SetJsMessageDispatcher(const RefPtr<JsMessageDispatcher>& dispatcher)
681 {
682     ACE_DCHECK(engineInstance_);
683     engineInstance_->SetJsMessageDispatcher(dispatcher);
684 }
685 
RunGarbageCollection()686 void QJSDeclarativeEngine::RunGarbageCollection()
687 {
688     ACE_DCHECK(engineInstance_);
689     engineInstance_->RunGarbageCollection();
690 }
691 
GetGroupJsBridge()692 RefPtr<GroupJsBridge> QJSDeclarativeEngine::GetGroupJsBridge()
693 {
694     return AceType::MakeRefPtr<QuickJsGroupJsBridge>();
695 }
696 
697 } // namespace OHOS::Ace::Framework
698