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