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