• 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_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 "core/common/container.h"
29 #include "frameworks/bridge/common/utils/engine_helper.h"
30 #include "frameworks/bridge/declarative_frontend/engine/bindings_implementation.h"
31 #include "frameworks/bridge/declarative_frontend/engine/quickjs/modules/qjs_module_manager.h"
32 #include "frameworks/bridge/declarative_frontend/engine/quickjs/qjs_helpers.h"
33 #include "frameworks/bridge/declarative_frontend/jsview/js_view_register.h"
34 #include "frameworks/bridge/js_frontend/engine/common/js_constants.h"
35 #include "frameworks/bridge/js_frontend/engine/common/runtime_constants.h"
36 #include "frameworks/bridge/js_frontend/engine/quickjs/qjs_group_js_bridge.h"
37 #include "frameworks/core/common/ace_application_info.h"
38 #include "frameworks/core/image/image_cache.h"
39 
40 #if !defined(PREVIEW)
41 #include "native_engine/impl/quickjs/quickjs_native_engine.h"
42 #endif
43 
44 extern const char _binary_stateMgmt_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) || defined(IOS_PLATFORM) || defined(LINUX_PLATFORM)
49 extern const char* _binary_stateMgmt_js_end;
50 extern const char* _binary_jsEnumStyle_js_end;
51 extern const char* _binary_jsMockSystemPlugin_js_end;
52 #else
53 extern const char _binary_stateMgmt_js_end[];
54 extern const char _binary_jsEnumStyle_js_end[];
55 extern const char _binary_jsMockSystemPlugin_js_end[];
56 #endif
57 
58 namespace OHOS::Ace::Framework {
59 
60 thread_local JSRuntime* QJSDeclarativeEngineInstance::runtime_ = nullptr;
61 
UnWrapEngineInstance(JSContext * ctx)62 QJSDeclarativeEngineInstance* QJSDeclarativeEngineInstance::UnWrapEngineInstance(JSContext* ctx)
63 {
64     auto* instance = static_cast<QJSDeclarativeEngineInstance*>(JS_GetContextOpaque(ctx));
65     if (instance == nullptr) {
66         LOGE("Can not unwrap ctx and obtain QJSDeclarativeEngineInstance object.");
67     }
68     return instance;
69 }
70 
FlushCommandBuffer(void * context,const std::string & command)71 void QJSDeclarativeEngineInstance::FlushCommandBuffer(void* context, const std::string& command)
72 {
73     return;
74 }
75 
SetRunningPage(const RefPtr<JsAcePage> & page)76 void QJSDeclarativeEngineInstance::SetRunningPage(const RefPtr<JsAcePage>& page)
77 {
78     std::lock_guard<std::mutex> lock(mutex_);
79     LOGD("new running page is %d.", (int)page->GetPageId());
80     runningPage_ = page;
81 }
82 
SetStagingPage(const RefPtr<JsAcePage> & page)83 void QJSDeclarativeEngineInstance::SetStagingPage(const RefPtr<JsAcePage>& page)
84 {
85     std::lock_guard<std::mutex> lock(mutex_);
86     LOGD("new staging page is %d.", (int)page->GetPageId());
87     stagingPage_ = page;
88 }
89 
ResetStagingPage(const RefPtr<JsAcePage> & page)90 void QJSDeclarativeEngineInstance::ResetStagingPage(const RefPtr<JsAcePage>& page)
91 {
92     std::lock_guard<std::mutex> lock(mutex_);
93     LOGD("new staging page is %d.", (int)page->GetPageId());
94     stagingPage_ = page;
95 }
96 
GetRunningPage(JSContext * ctx)97 RefPtr<JsAcePage> QJSDeclarativeEngineInstance::GetRunningPage(JSContext* ctx)
98 {
99     auto* instance = QJSDeclarativeEngineInstance::UnWrapEngineInstance(ctx);
100     if (instance != nullptr) {
101         return instance->GetRunningPage();
102     } else {
103         LOGE("QJS context has no ref to engine instance. Failed!");
104         return nullptr;
105     }
106 }
107 
GetStagingPage(JSContext * ctx)108 RefPtr<JsAcePage> QJSDeclarativeEngineInstance::GetStagingPage(JSContext* ctx)
109 {
110     auto* instance = QJSDeclarativeEngineInstance::UnWrapEngineInstance(ctx);
111     if (instance != nullptr) {
112         return instance->GetStagingPage();
113     } else {
114         LOGE("QJS context has no ref to engine instance. Failed!");
115         return nullptr;
116     }
117 }
118 
GetCurrentContext()119 JSContext* QJSDeclarativeEngineInstance::GetCurrentContext()
120 {
121     auto engine = EngineHelper::GetCurrentEngine();
122     auto qjsEngine = AceType::DynamicCast<QJSDeclarativeEngine>(engine);
123     if (!qjsEngine) {
124         LOGE("qjsEngine is null");
125         return nullptr;
126     }
127     auto engineInstance = qjsEngine->GetEngineInstance();
128     if (engineInstance == nullptr) {
129         LOGE("engineInstance is nullptr");
130         return nullptr;
131     }
132     return engineInstance->GetQJSContext();
133 }
134 
PushJSCommand(const RefPtr<JsCommand> & jsCommand,bool forcePush) const135 void QJSDeclarativeEngineInstance::PushJSCommand(const RefPtr<JsCommand>& jsCommand, bool forcePush) const
136 {
137 #ifndef NG_BUILD
138     auto page = GetRunningPage();
139     if (page == nullptr) {
140         LOGE("Internal error: running page is null.");
141         return;
142     }
143 
144     ACE_SCOPED_TRACE("PushJSCommand");
145     page->PushCommand(jsCommand);
146 
147     if (!page->CheckPageCreated() && (forcePush || (page->GetCommandSize() > (FRAGMENT_SIZE + 4)))) {
148         page->FlushCommands();
149     }
150 #endif
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<PipelineBase> 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 instanceName,std::string url,const char * buf,size_t bufSize)236 JSValue QJSDeclarativeEngineInstance::CompileSource(
237     std::string instanceName, std::string url, const char* buf, size_t bufSize)
238 {
239     LOGD("Compiling file url %s", url.c_str());
240 
241     ACE_SCOPED_TRACE("Compile JS");
242     JSContext* ctx = GetQJSContext();
243 
244     // temporary use image cache path to store the snapshot
245     std::string separator = "/";
246 #if defined(WINDOWS_PLATFORM)
247     separator = "\\";
248 #endif
249     std::size_t h1 = std::hash<std::string> {}(instanceName + separator + url);
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 opened 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         auto page = GetRunningPage(ctx);
332         QJSUtils::JsStdDumpErrorAce(ctx, JsErrorType::LOAD_JS_BUNDLE_ERROR, instanceId_,
333             page ? page->GetUrl().c_str() : "unknown", page, true);
334         return false;
335     }
336     js_std_loop(ctx);
337     LOGD("Executing JS -- DONE OK!");
338     return true;
339 }
340 
341 const JSCFunctionListEntry moduleFunctions[] = {};
342 
InitializeModules(JSContext * ctx,JSModuleDef * m)343 int InitializeModules(JSContext* ctx, JSModuleDef* m)
344 {
345     QJSContext::Scope scope(ctx);
346     return JS_SetModuleExportList(ctx, m, moduleFunctions, countof(moduleFunctions));
347 }
348 
JsInitModule(JSContext * ctx)349 JSModuleDef* JsInitModule(JSContext* ctx)
350 {
351     LOGD("registering ace module methods\n");
352 
353     JSModuleDef* m = JS_NewCModule(ctx, "ace", InitializeModules);
354     if (!m)
355         return nullptr;
356 
357     JS_AddModuleExportList(ctx, m, moduleFunctions, countof(moduleFunctions));
358     return m;
359 }
360 
InitJSContext(JSContext * ctx1,size_t maxStackSize,const std::unordered_map<std::string,void * > & extraNativeObject)361 JSContext* InitJSContext(JSContext* ctx1, size_t maxStackSize,
362     const std::unordered_map<std::string, void*>& extraNativeObject)
363 {
364     LOGD("QJS Creating new JS context and loading HBS module");
365 
366     ACE_SCOPED_TRACE("Init JS Context");
367     if (!ctx1) {
368         LOGD("QJS cannot allocate JS context");
369         return nullptr;
370     }
371 
372     /*
373      * Note: default 260k stack is not enough, lets use a value that should be enough
374      *        for five cards 512k is too small, use 1MB
375      */
376     JS_SetMaxStackSize(ctx1, maxStackSize);
377 
378     js_std_add_helpers(ctx1, 0, NULL);
379 
380     InitConsole(ctx1);
381 
382     /* inject hbs native functions module */
383     QJSContext::Scope scope(ctx1);
384     JSValue globalObj = JS_GetGlobalObject(ctx1);
385     JsRegisterViews(globalObj);
386 
387     /* make 'std' and 'os' visible to non module code */
388     /* dito for hbs */
389     const char* str = "// import ACE own functions in sce module \n"
390                       "// QJS rel 1 Sept no longer defines global but globalThis object, fix it \n"
391                       "var global = globalThis;\n";
392 
393     if (JS_CALL_FAIL ==
394         QJSDeclarativeEngineInstance::EvalBuf(ctx1, str, strlen(str), "JS Context initialize", JS_EVAL_TYPE_GLOBAL)) {
395         LOGE("QJS created JS context but failed to init hbs, os, or std module.!");
396     }
397 
398 #if !defined(PREVIEW)
399     for (const auto& [key, value] : extraNativeObject) {
400         auto nativeObjectInfo = std::make_unique<NativeObjectInfo>();
401         nativeObjectInfo->nativeObject = value;
402         JSValue abilityValue = JS_NewExternal(ctx1, nativeObjectInfo.release(),
403             [](JSContext* ctx, void *data, void *hint) {
404                 std::unique_ptr<NativeObjectInfo> info(static_cast<NativeObjectInfo*>(data));
405             }, nullptr);
406         JS_SetPropertyStr(ctx1, globalObj, key.c_str(), abilityValue);
407     }
408 #endif
409     JS_FreeValue(ctx1, globalObj);
410     return ctx1;
411 }
412 
413 std::map<std::string, std::string> QJSDeclarativeEngineInstance::mediaResourceFileMap_;
414 
415 std::unique_ptr<JsonValue> QJSDeclarativeEngineInstance::currentConfigResourceData_;
416 
InitJSEnv(JSRuntime * runtime,JSContext * context,const std::unordered_map<std::string,void * > & extraNativeObject)417 bool QJSDeclarativeEngineInstance::InitJSEnv(JSRuntime* runtime, JSContext* context,
418     const std::unordered_map<std::string, void*>& extraNativeObject)
419 {
420     ACE_SCOPED_TRACE("Init JS Env");
421     if (runtime == nullptr) {
422         runtime = JS_NewRuntime();
423     }
424     if (runtime_ != nullptr) {
425         JS_FreeRuntime(runtime_);
426     }
427     runtime_ = runtime;
428     if (runtime_ == nullptr) {
429         LOGE("Qjs cannot allocate JS runtime");
430         EventReport::SendJsException(JsExcepType::JS_ENGINE_INIT_ERR);
431         return false;
432     }
433 
434     if (context == nullptr) {
435         context = JS_NewContext(runtime_);
436     }
437     if (context_ != nullptr) {
438         JS_FreeContext(context_);
439     }
440     context_ = context;
441     bool initRet = InitJSContext(context_, MAX_STACK_SIZE, extraNativeObject);
442     if (!initRet) {
443         LOGE("QJS cannot allocate JS context");
444         JS_FreeRuntime(runtime_);
445         return false;
446     }
447 
448     auto groupJsBridge = AceType::DynamicCast<QuickJsGroupJsBridge>(frontendDelegate_->GetGroupJsBridge());
449     if (!groupJsBridge || JS_CALL_FAIL == groupJsBridge->InitializeGroupJsBridge(context_)) {
450         LOGE("QJSDeclarative Initialize GroupJsBridge failed!");
451         EventReport::SendJsException(JsExcepType::JS_ENGINE_INIT_ERR);
452         return false;
453     }
454 
455     std::string jsProxy = std::string(_binary_stateMgmt_js_start,
456         _binary_stateMgmt_js_end - _binary_stateMgmt_js_start);
457 
458     // make jsProxy end of '\0'
459     std::string jsEnum(_binary_jsEnumStyle_js_start, _binary_jsEnumStyle_js_end - _binary_jsEnumStyle_js_start);
460     if (!InitAceModules(jsProxy.c_str(), jsProxy.length(), "stateMgmt.js")
461         || !InitAceModules(jsEnum.c_str(), jsEnum.length(), "jsEnumStyle.js")) {
462         return false;
463     }
464 
465 #if defined(PREVIEW)
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 
GetMediaResource(const std::string & targetMediaFileName)595 std::string QJSDeclarativeEngineInstance::GetMediaResource(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