• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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_instance.h"
17 
18 #include <cstdlib>
19 #include <fcntl.h>
20 #include <fstream>
21 #include <streambuf>
22 #include <sys/stat.h>
23 #include <unistd.h>
24 
25 #include "base/log/ace_trace.h"
26 #include "base/log/event_report.h"
27 #include "base/log/log.h"
28 #include "frameworks/bridge/common/utils/engine_helper.h"
29 #include "frameworks/bridge/declarative_frontend/engine/bindings_implementation.h"
30 #include "frameworks/bridge/declarative_frontend/engine/quickjs/modules/qjs_module_manager.h"
31 #include "frameworks/bridge/declarative_frontend/engine/quickjs/qjs_helpers.h"
32 #include "frameworks/bridge/declarative_frontend/jsview/js_view_register.h"
33 #include "frameworks/bridge/js_frontend/engine/common/js_constants.h"
34 #include "frameworks/bridge/js_frontend/engine/common/runtime_constants.h"
35 #include "frameworks/bridge/js_frontend/engine/quickjs/qjs_group_js_bridge.h"
36 #include "frameworks/core/common/ace_application_info.h"
37 #include "frameworks/core/image/image_cache.h"
38 
39 #if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM)
40 #include "native_engine/impl/quickjs/quickjs_native_engine.h"
41 #endif
42 
43 extern const char _binary_stateMgmt_js_start[];
44 extern const char _binary_contentStorage_js_start[];
45 extern const char _binary_jsEnumStyle_js_start[];
46 extern const char _binary_jsMockSystemPlugin_js_start[];
47 
48 #if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM)
49 extern const char* _binary_stateMgmt_js_end;
50 extern const char* _binary_contentStorage_js_end;
51 extern const char* _binary_jsEnumStyle_js_end;
52 extern const char* _binary_jsMockSystemPlugin_js_end;
53 #else
54 extern const char _binary_stateMgmt_js_end[];
55 extern const char _binary_contentStorage_js_end[];
56 extern const char _binary_jsEnumStyle_js_end[];
57 extern const char _binary_jsMockSystemPlugin_js_end[];
58 #endif
59 
60 namespace OHOS::Ace::Framework {
61 
62 thread_local JSRuntime* QJSDeclarativeEngineInstance::runtime_ = nullptr;
63 
UnWrapEngineInstance(JSContext * ctx)64 QJSDeclarativeEngineInstance* QJSDeclarativeEngineInstance::UnWrapEngineInstance(JSContext* ctx)
65 {
66     auto* instance = static_cast<QJSDeclarativeEngineInstance*>(JS_GetContextOpaque(ctx));
67     if (instance == nullptr) {
68         LOGE("Can not unwrap ctx and obtain QJSDeclarativeEngineInstance object.");
69     }
70     return instance;
71 }
72 
FlushCommandBuffer(void * context,const std::string & command)73 void QJSDeclarativeEngineInstance::FlushCommandBuffer(void* context, const std::string& command)
74 {
75     return;
76 }
77 
SetRunningPage(const RefPtr<JsAcePage> & page)78 void QJSDeclarativeEngineInstance::SetRunningPage(const RefPtr<JsAcePage>& page)
79 {
80     std::lock_guard<std::mutex> lock(mutex_);
81     LOGD("new running page is %d.", (int)page->GetPageId());
82     runningPage_ = page;
83 }
84 
SetStagingPage(const RefPtr<JsAcePage> & page)85 void QJSDeclarativeEngineInstance::SetStagingPage(const RefPtr<JsAcePage>& page)
86 {
87     std::lock_guard<std::mutex> lock(mutex_);
88     LOGD("new staging page is %d.", (int)page->GetPageId());
89     stagingPage_ = page;
90 }
91 
ResetStagingPage(const RefPtr<JsAcePage> & page)92 void QJSDeclarativeEngineInstance::ResetStagingPage(const RefPtr<JsAcePage>& page)
93 {
94     std::lock_guard<std::mutex> lock(mutex_);
95     LOGD("new staging page is %d.", (int)page->GetPageId());
96     stagingPage_ = page;
97 }
98 
GetRunningPage(JSContext * ctx)99 RefPtr<JsAcePage> QJSDeclarativeEngineInstance::GetRunningPage(JSContext* ctx)
100 {
101     auto* instance = QJSDeclarativeEngineInstance::UnWrapEngineInstance(ctx);
102     if (instance != nullptr) {
103         return instance->GetRunningPage();
104     } else {
105         LOGE("QJS context has no ref to engine instance. Failed!");
106         return nullptr;
107     }
108 }
109 
GetStagingPage(JSContext * ctx)110 RefPtr<JsAcePage> QJSDeclarativeEngineInstance::GetStagingPage(JSContext* ctx)
111 {
112     auto* instance = QJSDeclarativeEngineInstance::UnWrapEngineInstance(ctx);
113     if (instance != nullptr) {
114         return instance->GetStagingPage();
115     } else {
116         LOGE("QJS context has no ref to engine instance. Failed!");
117         return nullptr;
118     }
119 }
120 
GetCurrentContext()121 JSContext* QJSDeclarativeEngineInstance::GetCurrentContext()
122 {
123     auto engine = EngineHelper::GetCurrentEngine();
124     auto qjsEngine = AceType::DynamicCast<QJSDeclarativeEngine>(engine);
125     if (!qjsEngine) {
126         LOGE("qjsEngine is null");
127         return nullptr;
128     }
129     auto engineInstance = qjsEngine->GetEngineInstance();
130     if (engineInstance == nullptr) {
131         LOGE("engineInstance is nullptr");
132         return nullptr;
133     }
134     return engineInstance->GetQJSContext();
135 }
136 
PushJSCommand(const RefPtr<JsCommand> & jsCommand,bool forcePush) const137 void QJSDeclarativeEngineInstance::PushJSCommand(const RefPtr<JsCommand>& jsCommand, bool forcePush) const
138 {
139     auto page = GetRunningPage();
140     if (page == nullptr) {
141         LOGE("Internal error: running page is null.");
142         return;
143     }
144 
145     ACE_SCOPED_TRACE("PushJSCommand");
146     page->PushCommand(jsCommand);
147 
148     if (!page->CheckPageCreated() && (forcePush || (page->GetCommandSize() > (FRAGMENT_SIZE + 4)))) {
149         page->FlushCommands();
150     }
151 }
152 
PushJSCommand(JSContext * ctx,const RefPtr<JsCommand> & jsCommand,bool forceFlush)153 void QJSDeclarativeEngineInstance::PushJSCommand(JSContext* ctx, const RefPtr<JsCommand>& jsCommand, bool forceFlush)
154 {
155     auto* instance = QJSDeclarativeEngineInstance::UnWrapEngineInstance(ctx);
156     if (instance != nullptr) {
157         instance->PushJSCommand(jsCommand, forceFlush);
158     } else {
159         LOGE("QJS context has no ref to engine instance. Failed!");
160         return;
161     }
162 }
163 
PostJsTask(JSContext * ctx,std::function<void ()> && task)164 void QJSDeclarativeEngineInstance::PostJsTask(JSContext* ctx, std::function<void()>&& task)
165 {
166     auto* instance = QJSDeclarativeEngineInstance::UnWrapEngineInstance(ctx);
167     if (instance != nullptr) {
168         instance->GetDelegate()->PostJsTask(std::move(task));
169     }
170 }
171 
TriggerPageUpdate(JSContext * ctx)172 void QJSDeclarativeEngineInstance::TriggerPageUpdate(JSContext* ctx)
173 {
174     auto* instance = QJSDeclarativeEngineInstance::UnWrapEngineInstance(ctx);
175     if (instance != nullptr) {
176         instance->GetDelegate()->TriggerPageUpdate(instance->GetRunningPage()->GetPageId());
177         return;
178     }
179     LOGE("QJS context has no ref to instance. Failed!");
180 }
181 
GetPipelineContext(JSContext * ctx)182 RefPtr<PipelineContext> QJSDeclarativeEngineInstance::GetPipelineContext(JSContext* ctx)
183 {
184     auto* instance = QJSDeclarativeEngineInstance::UnWrapEngineInstance(ctx);
185     if (instance != nullptr) {
186         return instance->GetDelegate()->GetPipelineContext();
187     }
188     return nullptr;
189 }
190 
EvalBuf(JSContext * ctx,const char * buf,size_t bufLen,const char * filename,int evalFlags)191 int QJSDeclarativeEngineInstance::EvalBuf(
192     JSContext* ctx, const char* buf, size_t bufLen, const char* filename, int evalFlags)
193 {
194     JSValue val = JS_Eval(ctx, buf, bufLen, filename, evalFlags);
195     int32_t ret = JS_CALL_SUCCESS;
196     if (JS_IsException(val)) {
197         LOGE("[Qjs Native] EvalBuf failed!");
198         QJSUtils::JsStdDumpErrorAce(ctx);
199         ret = JS_CALL_FAIL;
200     }
201     JS_FreeValue(ctx, val);
202     js_std_loop(ctx);
203     return ret;
204 }
205 
output_object_code(JSContext * ctx,int fho,JSValueConst obj)206 void QJSDeclarativeEngineInstance::output_object_code(JSContext* ctx, int fho, JSValueConst obj)
207 {
208     uint8_t* out_buf;
209     size_t out_buf_len;
210     out_buf = JS_WriteObject(ctx, &out_buf_len, obj, JS_WRITE_OBJ_BYTECODE);
211     if (!out_buf) {
212         js_std_dump_error(ctx);
213         return;
214     }
215 
216     int count __attribute__((unused));
217     count = write(fho, out_buf, out_buf_len);
218     LOGD("Bytes written to file: %d vs. %zu", count, out_buf_len);
219 
220     js_free(ctx, out_buf);
221 }
222 
eval_binary_buf(JSContext * ctx,const uint8_t * buf,size_t buf_len)223 JSValue QJSDeclarativeEngineInstance::eval_binary_buf(JSContext* ctx, const uint8_t* buf, size_t buf_len)
224 {
225     JSValue obj;
226     obj = JS_ReadObject(ctx, buf, buf_len, JS_READ_OBJ_BYTECODE);
227     if (JS_IsException(obj)) {
228         LOGE("eval_binary_buf (ReadObj) failed");
229         js_std_dump_error(ctx);
230         return obj;
231     }
232     js_std_loop(ctx);
233     return JS_EvalFunction(ctx, obj);
234 }
235 
CompileSource(std::string url,const char * buf,size_t bufSize)236 JSValue QJSDeclarativeEngineInstance::CompileSource(std::string url, const char* buf, size_t bufSize)
237 {
238     LOGD("Compiling file url %s", url.c_str());
239 
240     ACE_SCOPED_TRACE("Compile JS");
241     JSContext* ctx = GetQJSContext();
242 
243     std::size_t h1 = std::hash<std::string> {}(url);
244 
245     // temporary use image cache path to store the snapshot
246     std::string separator = "/";
247 #if defined(WINDOWS_PLATFORM)
248     separator = "\\";
249 #endif
250     std::string filename = ImageCache::GetImageCacheFilePath() + separator;
251     filename.append(std::to_string(h1));
252 
253     struct stat statbuf;
254     int statres = stat(filename.c_str(), &statbuf);
255 
256     JSValue retVal = JS_NULL;
257     int fhi;
258     if (statres == 0 && (fhi = open(filename.c_str(), O_RDONLY)) != -1) {
259         uint8_t* in_buf = (uint8_t*)malloc(statbuf.st_size + 5);
260         if (!in_buf) {
261             close(fhi);
262             return JS_NULL;
263         }
264         read(fhi, in_buf, statbuf.st_size);
265         close(fhi);
266         retVal = eval_binary_buf(GetQJSContext(), in_buf, statbuf.st_size);
267         free(in_buf);
268     } else {
269         // Evaluate and write to the file
270         LOGD("cache file does not exist, compiling source file");
271         retVal = JS_Eval(GetQJSContext(), buf, bufSize, url.c_str(), JS_EVAL_TYPE_GLOBAL | JS_EVAL_FLAG_COMPILE_ONLY);
272         js_std_loop(ctx);
273         if (JS_IsException(retVal)) {
274             LOGE("Failed reading (source) JS file %s into QuickJS!", url.c_str());
275             QJSUtils::JsStdDumpErrorAce(ctx);
276             return JS_UNDEFINED;
277         }
278 
279         int fho = creat(filename.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
280         if (fho != -1) {
281             LOGD("Compiled cache file opend for writing %s", filename.c_str());
282             output_object_code(GetQJSContext(), fho, retVal);
283             close(fho);
284         } else {
285             LOGE("Compiled cache file writing failed to %s", filename.c_str());
286         }
287     }
288     return retVal;
289 }
290 
CallAnimationFinishJs(JSValue animationContext)291 void QJSDeclarativeEngineInstance::CallAnimationFinishJs(JSValue animationContext)
292 {
293     JSContext* ctx = GetQJSContext();
294     QJSHandleScope handleScope(ctx);
295     auto proto = QJSUtils::GetPropertyStr(ctx, animationContext, "onfinish");
296     if (!JS_IsFunction(ctx, proto)) {
297         LOGE("cannot find 'CallAnimationFinishJs' function from global object, this should not happen!");
298         return;
299     }
300     LOGD("animation onfinish event call");
301     JSValue retVal = JS_Call(ctx, proto, animationContext, 0, {});
302     JS_FreeValue(ctx, retVal);
303     js_std_loop(ctx);
304 }
305 
CallAnimationCancelJs(JSValue animationContext)306 void QJSDeclarativeEngineInstance::CallAnimationCancelJs(JSValue animationContext)
307 {
308     JSContext* ctx = GetQJSContext();
309     QJSHandleScope handleScope(ctx);
310     auto proto = QJSUtils::GetPropertyStr(ctx, animationContext, "oncancel");
311     if (!JS_IsFunction(ctx, proto)) {
312         return;
313     }
314 
315     LOGD("animation oncancel event call");
316     JSValue retVal = JS_Call(ctx, proto, animationContext, 0, {});
317     JS_FreeValue(ctx, retVal);
318     js_std_loop(ctx);
319 }
320 
ExecuteDocumentJS(JSValue jsCode)321 bool QJSDeclarativeEngineInstance::ExecuteDocumentJS(JSValue jsCode)
322 {
323     LOGD("Executing JS ....");
324     ACE_SCOPED_TRACE("Execute JS");
325 
326     JSContext* ctx = GetQJSContext();
327 
328     JSValue result = JS_EvalFunction(ctx, jsCode);
329     if (JS_IsException(result)) {
330         LOGD("Failed executing JS!");
331         QJSUtils::JsStdDumpErrorAce(ctx);
332         return false;
333     }
334     js_std_loop(ctx);
335     LOGD("Executing JS -- DONE OK!");
336     return true;
337 }
338 
339 const JSCFunctionListEntry moduleFunctions[] = {};
340 
InitializeModules(JSContext * ctx,JSModuleDef * m)341 int InitializeModules(JSContext* ctx, JSModuleDef* m)
342 {
343     QJSContext::Scope scope(ctx);
344     return JS_SetModuleExportList(ctx, m, moduleFunctions, countof(moduleFunctions));
345 }
346 
JsInitModule(JSContext * ctx)347 JSModuleDef* JsInitModule(JSContext* ctx)
348 {
349     LOGD("registering ace module methods\n");
350 
351     JSModuleDef* m = JS_NewCModule(ctx, "ace", InitializeModules);
352     if (!m)
353         return nullptr;
354 
355     JS_AddModuleExportList(ctx, m, moduleFunctions, countof(moduleFunctions));
356     return m;
357 }
358 
InitJSContext(JSContext * ctx1,size_t maxStackSize,const std::unordered_map<std::string,void * > & extraNativeObject)359 JSContext* InitJSContext(JSContext* ctx1, size_t maxStackSize,
360     const std::unordered_map<std::string, void*>& extraNativeObject)
361 {
362     LOGD("QJS Creating new JS context and loading HBS module");
363 
364     ACE_SCOPED_TRACE("Init JS Context");
365     if (!ctx1) {
366         LOGD("QJS cannot allocate JS context");
367         return nullptr;
368     }
369 
370     /*
371      * Note: default 260k stack is not enough, lets use a value that should be enough
372      *        for five cards 512k is too small, use 1MB
373      */
374     JS_SetMaxStackSize(ctx1, maxStackSize);
375 
376     js_std_add_helpers(ctx1, 0, NULL);
377 
378     InitConsole(ctx1);
379 
380     /* inject hbs native functions module */
381     QJSContext::Scope scope(ctx1);
382     JSValue globalObj = JS_GetGlobalObject(ctx1);
383     JsRegisterViews(globalObj);
384 
385     /* make 'std' and 'os' visible to non module code */
386     /* dito for hbs */
387     const char* str = "// import ACE own functions in sce module \n"
388                       "// QJS rel 1 Sept no longer defines global but globalThis object, fix it \n"
389                       "var global = globalThis;\n";
390 
391     if (JS_CALL_FAIL ==
392         QJSDeclarativeEngineInstance::EvalBuf(ctx1, str, strlen(str), "JS Context initialize", JS_EVAL_TYPE_GLOBAL)) {
393         LOGE("QJS created JS context but failed to init hbs, os, or std module.!");
394     }
395 
396 #if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM)
397     for (const auto& [key, value] : extraNativeObject) {
398         auto nativeObjectInfo = std::make_unique<NativeObjectInfo>();
399         nativeObjectInfo->nativeObject = value;
400         JSValue abilityValue = JS_NewExternal(ctx1, nativeObjectInfo.release(),
401             [](JSContext* ctx, void *data, void *hint) {
402                 std::unique_ptr<NativeObjectInfo> info(static_cast<NativeObjectInfo*>(data));
403             }, nullptr);
404         JS_SetPropertyStr(ctx1, globalObj, key.c_str(), abilityValue);
405     }
406 #endif
407     JS_FreeValue(ctx1, globalObj);
408     return ctx1;
409 }
410 
411 std::map<std::string, std::string> QJSDeclarativeEngineInstance::mediaResourceFileMap_;
412 
413 std::unique_ptr<JsonValue> QJSDeclarativeEngineInstance::currentConfigResourceData_;
414 
InitJSEnv(JSRuntime * runtime,JSContext * context,const std::unordered_map<std::string,void * > & extraNativeObject)415 bool QJSDeclarativeEngineInstance::InitJSEnv(JSRuntime* runtime, JSContext* context,
416     const std::unordered_map<std::string, void*>& extraNativeObject)
417 {
418     ACE_SCOPED_TRACE("Init JS Env");
419     if (runtime == nullptr) {
420         runtime = JS_NewRuntime();
421     }
422     if (runtime_ != nullptr) {
423         JS_FreeRuntime(runtime_);
424     }
425     runtime_ = runtime;
426     if (runtime_ == nullptr) {
427         LOGE("Qjs cannot allocate JS runtime");
428         EventReport::SendJsException(JsExcepType::JS_ENGINE_INIT_ERR);
429         return false;
430     }
431 
432     if (context == nullptr) {
433         context = JS_NewContext(runtime_);
434     }
435     if (context_ != nullptr) {
436         JS_FreeContext(context_);
437     }
438     context_ = context;
439     bool initRet = InitJSContext(context_, MAX_STACK_SIZE, extraNativeObject);
440     if (!initRet) {
441         LOGE("QJS cannot allocate JS context");
442         JS_FreeRuntime(runtime_);
443         return false;
444     }
445 
446     auto groupJsBridge = AceType::DynamicCast<QuickJsGroupJsBridge>(frontendDelegate_->GetGroupJsBridge());
447     if (!groupJsBridge || JS_CALL_FAIL == groupJsBridge->InitializeGroupJsBridge(context_)) {
448         LOGE("QJSDeclarative Initialize GroupJsBridge failed!");
449         EventReport::SendJsException(JsExcepType::JS_ENGINE_INIT_ERR);
450         return false;
451     }
452 
453     // make jsProxy end of '\0'
454     std::string jsProxy(_binary_stateMgmt_js_start, _binary_stateMgmt_js_end - _binary_stateMgmt_js_start);
455     std::string jsEnum(_binary_jsEnumStyle_js_start, _binary_jsEnumStyle_js_end - _binary_jsEnumStyle_js_start);
456     std::string jsContentStorage(_binary_contentStorage_js_start,
457         _binary_contentStorage_js_end - _binary_contentStorage_js_start);
458 
459     if (!InitAceModules(jsProxy.c_str(), jsProxy.length(), "stateMgmt.js")
460         || !InitAceModules(jsEnum.c_str(), jsEnum.length(), "jsEnumStyle.js")
461         || !InitAceModules(jsContentStorage.c_str(), jsContentStorage.length(), "contentStorage.js")) {
462         return false;
463     }
464 
465 #if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM)
466     std::string jsMockSystemPlugin(_binary_jsMockSystemPlugin_js_start,
467                                    _binary_jsMockSystemPlugin_js_end - _binary_jsMockSystemPlugin_js_start);
468     if (!InitAceModules(jsMockSystemPlugin.c_str(), jsMockSystemPlugin.length(), "jsMockSystemPlugin.js")) {
469         return false;
470     }
471 #endif
472     InitJsNativeModuleObject(context_);
473     InitJsExportsUtilObject(context_);
474 
475     currentConfigResourceData_ = JsonUtil::CreateArray(true);
476     frontendDelegate_->LoadResourceConfiguration(mediaResourceFileMap_, currentConfigResourceData_);
477 
478     return true;
479 }
480 
FreeGroupJsBridge()481 void QJSDeclarativeEngineInstance::FreeGroupJsBridge()
482 {
483     // free JSValue reference of channel bridge and animation bridge
484     if (!frontendDelegate_) {
485         LOGE("frontend delegate is null.");
486         return;
487     }
488 
489     auto groupJsBridge = AceType::DynamicCast<QuickJsGroupJsBridge>(frontendDelegate_->GetGroupJsBridge());
490     if (!groupJsBridge) {
491         LOGE("group js bridge is null.");
492         return;
493     }
494 
495     groupJsBridge->Uninitialize();
496 }
497 
InitAceModules(const char * start,size_t length,const char * fileName)498 bool QJSDeclarativeEngineInstance::InitAceModules(const char* start, size_t length, const char* fileName)
499 {
500     QJSContext::Scope scp(context_);
501     if (start == nullptr || length == 0 || fileName == nullptr) {
502         LOGE("Failed to init Ace modules, start, end or fileName can not be null!");
503         return false;
504     }
505     auto result = EvalBuf(context_, start, length, fileName, JS_EVAL_TYPE_GLOBAL);
506     if (result == -1) {
507         EventInfo eventInfo;
508         eventInfo.eventType = EXCEPTION_JS;
509         eventInfo.errorType = static_cast<int32_t>(JsExcepType::JS_CONTEXT_INIT_ERR);
510         EventReport::SendEvent(eventInfo);
511         LOGE("JS Engine created JS context but failed to init Ace modules!");
512         return false;
513     }
514     return true;
515 }
516 
RequireNativeModule(JSContext * ctx,JSValueConst new_target,int argc,JSValueConst * argv)517 JSValue RequireNativeModule(JSContext* ctx, JSValueConst new_target, int argc, JSValueConst* argv)
518 {
519     if ((argc != 1) || !JS_IsString(argv[0])) {
520         LOGE("RequireNativeModule expects a single string as parameter");
521         return JS_NULL;
522     }
523     ScopedString moduleName(ctx, argv[0]);
524 
525     // has already init module object
526     JSValue globalObj = JS_GetGlobalObject(ctx);
527     JSValue moduleObject = JS_GetPropertyStr(ctx, globalObj, moduleName.get());
528     if (JS_IsObject(moduleObject)) {
529         LOGD("has already init moduleObject %s", moduleName.get());
530         JS_FreeValue(ctx, globalObj);
531         return JS_DupValue(ctx, moduleObject);
532     }
533 
534     // init module object first time
535     JSValue jsModuleObject = JS_NewObject(ctx);
536     JS_SetPropertyStr(ctx, globalObj, moduleName.get(), jsModuleObject);
537     JS_FreeValue(ctx, globalObj);
538     if (ModuleManager::GetInstance()->InitModule(ctx, moduleName, jsModuleObject)) {
539         return JS_DupValue(ctx, jsModuleObject);
540     } else {
541         LOGE("init moduleObject %s failed", moduleName.get());
542         return JS_NULL;
543     }
544     return JS_NULL;
545 }
546 
InitJsNativeModuleObject(JSContext * ctx)547 void QJSDeclarativeEngineInstance::InitJsNativeModuleObject(JSContext* ctx)
548 {
549     QJSUtils::DefineGlobalFunction(ctx, RequireNativeModule, "requireNativeModule", 1);
550     ModuleManager::GetInstance()->InitTimerModule(ctx);
551     ModuleManager::GetInstance()->InitSyscapModule(ctx);
552 }
553 
InitJsExportsUtilObject(JSContext * ctx)554 void QJSDeclarativeEngineInstance::InitJsExportsUtilObject(JSContext* ctx)
555 {
556     JSValue exportsUtilObj = JS_NewObject(ctx);
557     JSValue globalObj = JS_GetGlobalObject(ctx);
558     JS_SetPropertyStr(ctx, globalObj, "exports", exportsUtilObj);
559     JS_FreeValue(ctx, globalObj);
560 }
561 
~QJSDeclarativeEngineInstance()562 QJSDeclarativeEngineInstance::~QJSDeclarativeEngineInstance()
563 {
564     FreeGroupJsBridge();
565     if (context_) {
566         JS_FreeContext(context_);
567     }
568     if (runtime_) {
569         JS_FreeRuntime(runtime_);
570     }
571 }
572 
FireAsyncEvent(const std::string & eventId,const std::string & param)573 void QJSDeclarativeEngineInstance::FireAsyncEvent(const std::string& eventId, const std::string& param)
574 {
575     LOGW("QJSDeclarativeEngineInstance FireAsyncEvent is unusable");
576 }
577 
GetI18nStringResource(const std::string & targetStringKey,const std::string & targetStringValue)578 std::unique_ptr<JsonValue> QJSDeclarativeEngineInstance::GetI18nStringResource(const std::string& targetStringKey,
579     const std::string& targetStringValue)
580 {
581     auto resourceI18nFileNum = currentConfigResourceData_->GetArraySize();
582     for (int i = 0; i < resourceI18nFileNum; i++) {
583         auto priorResource = currentConfigResourceData_->GetArrayItem(i);
584         if ((priorResource->Contains(targetStringKey))) {
585             auto valuePair = priorResource->GetValue(targetStringKey);
586             if (valuePair->Contains(targetStringValue)) {
587                 return valuePair->GetValue(targetStringValue);
588             }
589         }
590     }
591 
592     return JsonUtil::Create(true);
593 }
594 
GetMeidaResource(const std::string & targetMediaFileName)595 std::string QJSDeclarativeEngineInstance::GetMeidaResource(const std::string& targetMediaFileName)
596 {
597     auto iter = mediaResourceFileMap_.find(targetMediaFileName);
598 
599     if (iter != mediaResourceFileMap_.end()) {
600         return iter->second;
601     }
602 
603     return std::string();
604 }
605 
606 
RunGarbageCollection()607 void QJSDeclarativeEngineInstance::RunGarbageCollection()
608 {
609     if (runtime_) {
610         JS_RunGC(runtime_);
611     }
612 }
613 
614 } // namespace OHOS::Ace::Framework
615