• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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 "js_runtime.h"
17 
18 #include <cerrno>
19 #include <climits>
20 #include <cstdlib>
21 #include <fstream>
22 #include <mutex>
23 #include <regex>
24 
25 #include <atomic>
26 #include <sys/epoll.h>
27 #include <unistd.h>
28 
29 #include "accesstoken_kit.h"
30 #include "config_policy_utils.h"
31 #include "constants.h"
32 #include "connect_server_manager.h"
33 #include "ecmascript/napi/include/jsnapi.h"
34 #include "extract_resource_manager.h"
35 #include "file_mapper.h"
36 #include "file_path_utils.h"
37 #include "hdc_register.h"
38 #include "hilog_tag_wrapper.h"
39 #include "hitrace_meter.h"
40 #include "hot_reloader.h"
41 #include "ipc_skeleton.h"
42 #include "iservice_registry.h"
43 #include "js_environment.h"
44 #include "js_module_reader.h"
45 #include "js_module_searcher.h"
46 #include "js_quickfix_callback.h"
47 #include "js_runtime_utils.h"
48 #include "js_utils.h"
49 #include "js_worker.h"
50 #include "module_checker_delegate.h"
51 #include "napi/native_api.h"
52 #include "native_engine/impl/ark/ark_native_engine.h"
53 #include "native_engine/native_create_env.h"
54 #include "native_engine/native_engine.h"
55 #include "js_runtime_lite.h"
56 #include "ohos_js_env_logger.h"
57 #include "ohos_js_environment_impl.h"
58 #include "parameters.h"
59 #include "extractor.h"
60 #include "system_ability_definition.h"
61 #include "systemcapability.h"
62 #include "source_map.h"
63 #include "source_map_operator.h"
64 
65 #ifdef SUPPORT_GRAPHICS
66 #include "ace_forward_compatibility.h"
67 #include "declarative_module_preloader.h"
68 #endif
69 
70 using namespace OHOS::AbilityBase;
71 using Extractor = OHOS::AbilityBase::Extractor;
72 
73 namespace OHOS {
74 namespace AbilityRuntime {
75 namespace {
76 constexpr size_t PARAM_TWO = 2;
77 constexpr uint8_t SYSCAP_MAX_SIZE = 100;
78 constexpr int64_t DEFAULT_GC_POOL_SIZE = 0x10000000; // 256MB
79 constexpr int32_t DEFAULT_INTER_VAL = 500;
80 constexpr int32_t API8 = 8;
81 const std::string SANDBOX_ARK_CACHE_PATH = "/data/storage/ark-cache/";
82 const std::string SANDBOX_ARK_PROIFILE_PATH = "/data/storage/ark-profile";
83 const std::string DEBUGGER = "@Debugger";
84 
85 constexpr char MERGE_ABC_PATH[] = "/ets/modules.abc";
86 constexpr char BUNDLE_INSTALL_PATH[] = "/data/storage/el1/bundle/";
87 constexpr const char* PERMISSION_RUN_ANY_CODE = "ohos.permission.RUN_ANY_CODE";
88 
89 const std::string CONFIG_PATH = "/etc/system_kits_config.json";
90 const std::string SYSTEM_KITS_CONFIG_PATH = "/system/etc/system_kits_config.json";
91 
92 const std::string SYSTEM_KITS = "systemkits";
93 const std::string NAMESPACE = "namespace";
94 const std::string TARGET_OHM = "targetohm";
95 const std::string SINCE_VERSION = "sinceVersion";
96 
97 constexpr char DEVELOPER_MODE_STATE[] = "const.security.developermode.state";
__anon581947160202() 98 static auto PermissionCheckFunc = []() {
99     Security::AccessToken::AccessTokenID callerToken = IPCSkeleton::GetCallingTokenID();
100 
101     int result = Security::AccessToken::AccessTokenKit::VerifyAccessToken(callerToken, PERMISSION_RUN_ANY_CODE);
102     if (result == Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
103         return true;
104     } else {
105         return false;
106     }
107 };
108 
CanIUse(napi_env env,napi_callback_info info)109 napi_value CanIUse(napi_env env, napi_callback_info info)
110 {
111     if (env == nullptr || info == nullptr) {
112         TAG_LOGE(AAFwkTag::JSRUNTIME, "null env or info");
113         return nullptr;
114     }
115     napi_value undefined = CreateJsUndefined(env);
116 
117     size_t argc = 1;
118     napi_value argv[1] = { nullptr };
119     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
120     if (argc != 1) {
121         TAG_LOGE(AAFwkTag::JSRUNTIME, "invalid argc");
122         return undefined;
123     }
124 
125     napi_valuetype valueType = napi_undefined;
126     napi_typeof(env, argv[0], &valueType);
127     if (valueType != napi_string) {
128         TAG_LOGI(AAFwkTag::JSRUNTIME, "invalid type");
129         return undefined;
130     }
131 
132     char syscap[SYSCAP_MAX_SIZE] = { 0 };
133 
134     size_t strLen = 0;
135     napi_get_value_string_utf8(env, argv[0], syscap, sizeof(syscap), &strLen);
136 
137     bool ret = HasSystemCapability(syscap);
138     return CreateJsValue(env, ret);
139 }
140 
InitSyscapModule(napi_env env,napi_value globalObject)141 void InitSyscapModule(napi_env env, napi_value globalObject)
142 {
143     const char *moduleName = "JsRuntime";
144     BindNativeFunction(env, globalObject, "canIUse", moduleName, CanIUse);
145 }
146 
PrintVmLog(int32_t,int32_t,const char *,const char *,const char * message)147 int32_t PrintVmLog(int32_t, int32_t, const char*, const char*, const char* message)
148 {
149     TAG_LOGI(AAFwkTag::JSRUNTIME, "ArkLog: %{public}s", message);
150     return 0;
151 }
152 } // namespace
153 
154 std::atomic<bool> JsRuntime::hasInstance(false);
JsRuntime()155 JsRuntime::JsRuntime()
156 {
157     TAG_LOGD(AAFwkTag::JSRUNTIME, "called");
158 }
159 
~JsRuntime()160 JsRuntime::~JsRuntime()
161 {
162     TAG_LOGD(AAFwkTag::JSRUNTIME, "called");
163     Deinitialize();
164     StopDebugMode();
165 }
166 
Create(const Options & options)167 std::unique_ptr<JsRuntime> JsRuntime::Create(const Options& options)
168 {
169     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
170     std::unique_ptr<JsRuntime> instance;
171     JsRuntimeLite::InitJsRuntimeLite(options);
172     if (!options.preload && options.isStageModel) {
173         auto preloadedInstance = Runtime::GetPreloaded();
174 #ifdef SUPPORT_GRAPHICS
175         // reload ace if compatible mode changes
176         if (Ace::AceForwardCompatibility::PipelineChanged() && preloadedInstance) {
177             preloadedInstance.reset();
178         }
179 #endif
180         if (preloadedInstance && preloadedInstance->GetLanguage() == Runtime::Language::JS) {
181             instance.reset(static_cast<JsRuntime*>(preloadedInstance.release()));
182         } else {
183             instance = std::make_unique<JsRuntime>();
184         }
185     } else {
186         instance = std::make_unique<JsRuntime>();
187     }
188 
189     if (!instance->Initialize(options)) {
190         return std::unique_ptr<JsRuntime>();
191     }
192     return instance;
193 }
194 
StartDebugMode(const DebugOption dOption)195 void JsRuntime::StartDebugMode(const DebugOption dOption)
196 {
197     if (!system::GetBoolParameter(DEVELOPER_MODE_STATE, false)) {
198         TAG_LOGE(AAFwkTag::JSRUNTIME, "Developer Mode is false.");
199         return;
200     }
201     CHECK_POINTER(jsEnv_);
202     if (jsEnv_->GetDebugMode()) {
203         TAG_LOGI(AAFwkTag::JSRUNTIME, "debugMode");
204         return;
205     }
206     // Set instance id to tid after the first instance.
207     if (JsRuntime::hasInstance.exchange(true, std::memory_order_relaxed)) {
208         instanceId_ = static_cast<uint32_t>(getproctid());
209     }
210 
211     bool isStartWithDebug = dOption.isStartWithDebug;
212     bool isDebugApp = dOption.isDebugApp;
213     TAG_LOGD(AAFwkTag::JSRUNTIME, "Ark VM is starting debug mode [%{public}s]", isStartWithDebug ? "break" : "normal");
214     StartDebuggerInWorkerModule(isDebugApp, dOption.isStartWithNative);
215     const std::string bundleName = bundleName_;
216     uint32_t instanceId = instanceId_;
217     auto weak = jsEnv_;
218     std::string inputProcessName = bundleName_ != dOption.processName ? dOption.processName : "";
219     HdcRegister::Get().StartHdcRegister(bundleName_, inputProcessName, isDebugApp, [bundleName,
220             isStartWithDebug, instanceId, weak, isDebugApp] (int socketFd, std::string option) {
221             TAG_LOGI(AAFwkTag::JSRUNTIME, "HdcRegister msg, fd= %{public}d, option= %{public}s",
222                 socketFd, option.c_str());
223         if (weak == nullptr) {
224                 TAG_LOGE(AAFwkTag::JSRUNTIME, "null weak");
225             return;
226         }
227         if (option.find(DEBUGGER) == std::string::npos) {
228             if (isDebugApp) {
229                 ConnectServerManager::Get().StopConnectServer(false);
230             }
231             ConnectServerManager::Get().SendDebuggerInfo(isStartWithDebug, isDebugApp);
232             ConnectServerManager::Get().StartConnectServer(bundleName, socketFd, false);
233         } else {
234             if (isDebugApp) {
235                 weak->StopDebugger(option);
236             }
237             weak->StartDebugger(option, socketFd, isDebugApp);
238         }
239     });
240     if (isDebugApp) {
241         ConnectServerManager::Get().StartConnectServer(bundleName_, -1, true);
242     }
243 
244     DebuggerConnectionHandler(isDebugApp, isStartWithDebug);
245 }
246 
DebuggerConnectionHandler(bool isDebugApp,bool isStartWithDebug)247 void JsRuntime::DebuggerConnectionHandler(bool isDebugApp, bool isStartWithDebug)
248 {
249     ConnectServerManager::Get().StoreInstanceMessage(getproctid(), instanceId_);
250     EcmaVM* vm = GetEcmaVm();
251     auto dTask = jsEnv_->GetDebuggerPostTask();
252     panda::JSNApi::DebugOption option = {ARK_DEBUGGER_LIB_PATH, isDebugApp ? isStartWithDebug : false};
253     ConnectServerManager::Get().StoreDebuggerInfo(getproctid(), reinterpret_cast<void*>(vm), option, dTask, isDebugApp);
254     jsEnv_->NotifyDebugMode(getproctid(), ARK_DEBUGGER_LIB_PATH, instanceId_, isDebugApp, isStartWithDebug);
255 }
256 
StopDebugMode()257 void JsRuntime::StopDebugMode()
258 {
259     CHECK_POINTER(jsEnv_);
260     if (jsEnv_->GetDebugMode()) {
261         ConnectServerManager::Get().RemoveInstance(instanceId_);
262         StopDebugger();
263     }
264 }
265 
InitConsoleModule()266 void JsRuntime::InitConsoleModule()
267 {
268     CHECK_POINTER(jsEnv_);
269     jsEnv_->InitConsoleModule();
270 }
271 
StartDebugger(bool needBreakPoint,uint32_t instanceId)272 bool JsRuntime::StartDebugger(bool needBreakPoint, uint32_t instanceId)
273 {
274     TAG_LOGD(AAFwkTag::JSRUNTIME, "called");
275     return true;
276 }
277 
StopDebugger()278 void JsRuntime::StopDebugger()
279 {
280     CHECK_POINTER(jsEnv_);
281     jsEnv_->StopDebugger();
282 }
283 
JsperfProfilerCommandParse(const std::string & command,int32_t defaultValue)284 int32_t JsRuntime::JsperfProfilerCommandParse(const std::string &command, int32_t defaultValue)
285 {
286     TAG_LOGD(AAFwkTag::JSRUNTIME, "profiler command parse %{public}s", command.c_str());
287     auto findPos = command.find("jsperf");
288     if (findPos == std::string::npos) {
289         // jsperf command not found, so not to do, return zero.
290         TAG_LOGD(AAFwkTag::JSRUNTIME, "jsperf command not found");
291         return 0;
292     }
293 
294     // match jsperf command
295     auto jsPerfStr = command.substr(findPos, command.length() - findPos);
296     const std::regex regexJsperf(R"(^jsperf($|\s+($|\d*\s*($|nativeperf.*))))");
297     std::match_results<std::string::const_iterator> matchResults;
298     if (!std::regex_match(jsPerfStr, matchResults, regexJsperf)) {
299         TAG_LOGD(AAFwkTag::JSRUNTIME, "the order not match");
300         return defaultValue;
301     }
302 
303     // get match resuflt
304     std::string jsperfResuflt;
305     constexpr size_t matchResultIndex = 1;
306     if (matchResults.size() < PARAM_TWO) {
307         TAG_LOGE(AAFwkTag::JSRUNTIME, "no results need to be matched");
308         return defaultValue;
309     }
310 
311     jsperfResuflt = matchResults[matchResultIndex].str();
312     // match number result
313     const std::regex regexJsperfNum(R"(^\s*(\d+).*)");
314     std::match_results<std::string::const_iterator> jsperfMatchResults;
315     if (!std::regex_match(jsperfResuflt, jsperfMatchResults, regexJsperfNum)) {
316         TAG_LOGD(AAFwkTag::JSRUNTIME, "the jsperf results not match");
317         return defaultValue;
318     }
319 
320     // get match result
321     std::string interval;
322     constexpr size_t matchNumResultIndex = 1;
323     if (jsperfMatchResults.size() < PARAM_TWO) {
324         TAG_LOGE(AAFwkTag::JSRUNTIME, "jsperfMatchResults not match");
325         return defaultValue;
326     }
327 
328     interval = jsperfMatchResults[matchNumResultIndex].str();
329     if (interval.empty()) {
330         TAG_LOGD(AAFwkTag::JSRUNTIME, "empty interval");
331         return defaultValue;
332     }
333 
334     return std::stoi(interval);
335 }
336 
StartProfiler(const DebugOption dOption)337 void JsRuntime::StartProfiler(const DebugOption dOption)
338 {
339     if (!system::GetBoolParameter(DEVELOPER_MODE_STATE, false)) {
340         TAG_LOGE(AAFwkTag::JSRUNTIME, "Developer Mode is false.");
341         return;
342     }
343     CHECK_POINTER(jsEnv_);
344     if (JsRuntime::hasInstance.exchange(true, std::memory_order_relaxed)) {
345         instanceId_ = static_cast<uint32_t>(getproctid());
346     }
347 
348     bool isStartWithDebug = dOption.isStartWithDebug;
349     bool isDebugApp = dOption.isDebugApp;
350     StartDebuggerInWorkerModule(isDebugApp, dOption.isStartWithNative);
351     const std::string bundleName = bundleName_;
352     auto weak = jsEnv_;
353     uint32_t instanceId = instanceId_;
354     std::string inputProcessName = bundleName_ != dOption.processName ? dOption.processName : "";
355     HdcRegister::Get().StartHdcRegister(bundleName_, inputProcessName, isDebugApp,
356         [bundleName, isStartWithDebug, instanceId, weak, isDebugApp](int socketFd, std::string option) {
357         TAG_LOGI(AAFwkTag::JSRUNTIME, "HdcRegister msg, fd= %{public}d, option= %{public}s", socketFd, option.c_str());
358         if (weak == nullptr) {
359             TAG_LOGE(AAFwkTag::JSRUNTIME, "null jsEnv");
360             return;
361         }
362         if (option.find(DEBUGGER) == std::string::npos) {
363             if (isDebugApp) {
364                 ConnectServerManager::Get().StopConnectServer(false);
365             }
366             ConnectServerManager::Get().SendDebuggerInfo(isStartWithDebug, isDebugApp);
367             ConnectServerManager::Get().StartConnectServer(bundleName, socketFd, false);
368         } else {
369             if (isDebugApp) {
370                 weak->StopDebugger(option);
371             }
372             weak->StartDebugger(option, socketFd, isDebugApp);
373         }
374     });
375 
376     DebuggerConnectionManager(isDebugApp, isStartWithDebug, dOption);
377 }
378 
DebuggerConnectionManager(bool isDebugApp,bool isStartWithDebug,const DebugOption dOption)379 void JsRuntime::DebuggerConnectionManager(bool isDebugApp, bool isStartWithDebug, const DebugOption dOption)
380 {
381     if (isDebugApp) {
382         ConnectServerManager::Get().StartConnectServer(bundleName_, 0, true);
383     }
384     ConnectServerManager::Get().StoreInstanceMessage(getproctid(), instanceId_);
385     JsEnv::JsEnvironment::PROFILERTYPE profiler = JsEnv::JsEnvironment::PROFILERTYPE::PROFILERTYPE_HEAP;
386     int32_t interval = 0;
387     const std::string profilerCommand("profile");
388     if (dOption.perfCmd.find(profilerCommand) != std::string::npos) {
389         profiler = JsEnv::JsEnvironment::PROFILERTYPE::PROFILERTYPE_CPU;
390         interval = JsperfProfilerCommandParse(dOption.perfCmd, DEFAULT_INTER_VAL);
391     }
392     EcmaVM* vm = GetEcmaVm();
393     auto dTask = jsEnv_->GetDebuggerPostTask();
394     panda::JSNApi::DebugOption option = {ARK_DEBUGGER_LIB_PATH, isDebugApp ? isStartWithDebug : false};
395     ConnectServerManager::Get().StoreDebuggerInfo(getproctid(), reinterpret_cast<void*>(vm), option, dTask, isDebugApp);
396     TAG_LOGD(AAFwkTag::JSRUNTIME, "profiler:%{public}d interval:%{public}d", profiler, interval);
397     jsEnv_->StartProfiler(ARK_DEBUGGER_LIB_PATH, instanceId_, profiler, interval, getproctid(), isDebugApp);
398 }
399 
GetFileBuffer(const std::string & filePath,std::string & fileFullName,std::vector<uint8_t> & buffer,bool isABC)400 bool JsRuntime::GetFileBuffer(const std::string& filePath, std::string& fileFullName, std::vector<uint8_t>& buffer,
401                               bool isABC)
402 {
403     Extractor extractor(filePath);
404     if (!extractor.Init()) {
405         TAG_LOGE(AAFwkTag::JSRUNTIME, "Extractor of %{private}s init failed", filePath.c_str());
406         return false;
407     }
408 
409     std::vector<std::string> fileNames;
410     if (isABC) {
411         extractor.GetSpecifiedTypeFiles(fileNames, ".abc");
412     } else {
413         extractor.GetSpecifiedTypeFiles(fileNames, ".map");
414     }
415     if (fileNames.empty()) {
416         TAG_LOGW(
417             AAFwkTag::JSRUNTIME, "no .abc in hap/hqf %{private}s", filePath.c_str());
418         return true;
419     }
420 
421     std::string fileName = fileNames.front();
422     fileFullName = filePath + "/" + fileName;
423     std::ostringstream outStream;
424     if (!extractor.ExtractByName(fileName, outStream)) {
425         TAG_LOGE(AAFwkTag::JSRUNTIME, "Extract %{public}s failed", fileFullName.c_str());
426         return false;
427     }
428 
429     const auto &outStr = outStream.str();
430     buffer.assign(outStr.begin(), outStr.end());
431     return true;
432 }
433 
GetSafeData(const std::string & path,std::string & fileFullName)434 std::shared_ptr<AbilityBase::FileMapper> JsRuntime::GetSafeData(const std::string& path, std::string& fileFullName)
435 {
436     bool newCreate = false;
437     auto extractor = ExtractorUtil::GetExtractor(path, newCreate, true);
438     if (extractor == nullptr) {
439         TAG_LOGE(AAFwkTag::JSRUNTIME, "Get extractor failed. path: %{private}s", path.c_str());
440         return nullptr;
441     }
442 
443     std::vector<std::string> fileNames;
444     extractor->GetSpecifiedTypeFiles(fileNames, ".abc");
445     if (fileNames.empty()) {
446         TAG_LOGI(AAFwkTag::JSRUNTIME, "There's no abc file in hap or hqf: %{private}s", path.c_str());
447         return nullptr;
448     }
449     std::string fileName = fileNames.front();
450     fileFullName = path + "/" + fileName;
451 
452     auto safeData = extractor->GetSafeData(fileName);
453     if (safeData == nullptr) {
454         TAG_LOGE(AAFwkTag::JSRUNTIME, "Get safe data failed. path: %{private}s", path.c_str());
455         return nullptr;
456     }
457 
458     return safeData;
459 }
460 
LoadRepairPatch(const std::string & hqfFile,const std::string & hapPath)461 bool JsRuntime::LoadRepairPatch(const std::string& hqfFile, const std::string& hapPath)
462 {
463     TAG_LOGD(AAFwkTag::JSRUNTIME, "called");
464     auto vm = GetEcmaVm();
465     CHECK_POINTER_AND_RETURN(vm, false);
466 
467     InitSourceMap(hqfFile);
468 
469     std::string patchFile;
470     auto hqfSafeData = GetSafeData(hqfFile, patchFile);
471     if (hqfSafeData == nullptr) {
472         if (patchFile.empty()) {
473             TAG_LOGI(AAFwkTag::JSRUNTIME, "No need to load patch cause no ets. path: %{private}s", hqfFile.c_str());
474             return true;
475         }
476         return false;
477     }
478 
479     std::string baseFile;
480     auto hapSafeData = GetSafeData(hapPath, baseFile);
481     if (hapSafeData == nullptr) {
482         return false;
483     }
484 
485     std::string resolvedHapPath;
486     auto position = hapPath.find(".hap");
487     if (position != std::string::npos) {
488         resolvedHapPath = hapPath.substr(0, position) + MERGE_ABC_PATH;
489     }
490 
491     auto hspPosition = hapPath.find(".hsp");
492     if (hspPosition != std::string::npos) {
493         resolvedHapPath = hapPath.substr(0, hspPosition) + MERGE_ABC_PATH;
494     }
495 
496     TAG_LOGD(AAFwkTag::JSRUNTIME, "LoadPatch, patchFile: %{private}s, baseFile: %{private}s",
497         patchFile.c_str(), resolvedHapPath.c_str());
498     auto ret = panda::JSNApi::LoadPatch(vm, patchFile, hqfSafeData->GetDataPtr(), hqfSafeData->GetDataLen(),
499         resolvedHapPath, hapSafeData->GetDataPtr(), hapSafeData->GetDataLen());
500     if (ret != panda::JSNApi::PatchErrorCode::SUCCESS) {
501         TAG_LOGE(AAFwkTag::JSRUNTIME, "LoadPatch failed:%{public}d", static_cast<int32_t>(ret));
502         return false;
503     }
504 
505     TAG_LOGD(AAFwkTag::JSRUNTIME, "Load patch %{private}s succeed", patchFile.c_str());
506     return true;
507 }
508 
UnLoadRepairPatch(const std::string & hqfFile)509 bool JsRuntime::UnLoadRepairPatch(const std::string& hqfFile)
510 {
511     TAG_LOGD(AAFwkTag::JSRUNTIME, "called");
512     auto vm = GetEcmaVm();
513     CHECK_POINTER_AND_RETURN(vm, false);
514 
515     Extractor extractor(hqfFile);
516     if (!extractor.Init()) {
517         TAG_LOGE(AAFwkTag::JSRUNTIME, "Extractor of %{private}s init failed", hqfFile.c_str());
518         return false;
519     }
520 
521     std::vector<std::string> fileNames;
522     extractor.GetSpecifiedTypeFiles(fileNames, ".abc");
523     if (fileNames.empty()) {
524         TAG_LOGW(AAFwkTag::JSRUNTIME, "no .abc in hqf %{private}s", hqfFile.c_str());
525         return true;
526     }
527 
528     for (const auto &fileName : fileNames) {
529         std::string patchFile = hqfFile + "/" + fileName;
530         TAG_LOGD(AAFwkTag::JSRUNTIME, "UnloadPatch, patchFile: %{private}s", patchFile.c_str());
531         auto ret = panda::JSNApi::UnloadPatch(vm, patchFile);
532         if (ret != panda::JSNApi::PatchErrorCode::SUCCESS) {
533             TAG_LOGW(AAFwkTag::JSRUNTIME, "UnLoadPatch failed with %{public}d", static_cast<int32_t>(ret));
534         }
535         TAG_LOGD(AAFwkTag::JSRUNTIME, "UnLoad patch %{private}s succeed", patchFile.c_str());
536     }
537 
538     return true;
539 }
540 
NotifyHotReloadPage()541 bool JsRuntime::NotifyHotReloadPage()
542 {
543     TAG_LOGD(AAFwkTag::JSRUNTIME, "called");
544     Ace::HotReloader::HotReload();
545     return true;
546 }
547 
LoadScript(const std::string & path,std::vector<uint8_t> * buffer,bool isBundle)548 bool JsRuntime::LoadScript(const std::string& path, std::vector<uint8_t>* buffer, bool isBundle)
549 {
550     TAG_LOGD(AAFwkTag::JSRUNTIME, "path: %{private}s", path.c_str());
551     CHECK_POINTER_AND_RETURN(jsEnv_, false);
552     return jsEnv_->LoadScript(path, buffer, isBundle);
553 }
554 
LoadScript(const std::string & path,uint8_t * buffer,size_t len,bool isBundle)555 bool JsRuntime::LoadScript(const std::string& path, uint8_t* buffer, size_t len, bool isBundle)
556 {
557     TAG_LOGD(AAFwkTag::JSRUNTIME, "path: %{private}s", path.c_str());
558     CHECK_POINTER_AND_RETURN(jsEnv_, false);
559     return jsEnv_->LoadScript(path, buffer, len, isBundle);
560 }
561 
LoadSystemModuleByEngine(napi_env env,const std::string & moduleName,const napi_value * argv,size_t argc)562 std::unique_ptr<NativeReference> JsRuntime::LoadSystemModuleByEngine(
563     napi_env env, const std::string& moduleName, const napi_value* argv, size_t argc)
564 {
565     TAG_LOGD(AAFwkTag::JSRUNTIME, "ModuleName %{public}s", moduleName.c_str());
566     if (env == nullptr) {
567         TAG_LOGI(AAFwkTag::JSRUNTIME, "invalid engine");
568         return nullptr;
569     }
570 
571     napi_value globalObj = nullptr;
572     napi_get_global(env, &globalObj);
573     napi_value propertyValue = nullptr;
574     napi_get_named_property(env, globalObj, "requireNapi", &propertyValue);
575 
576     std::unique_ptr<NativeReference> methodRequireNapiRef_;
577     napi_ref tmpRef = nullptr;
578     napi_create_reference(env, propertyValue, 1, &tmpRef);
579     methodRequireNapiRef_.reset(reinterpret_cast<NativeReference*>(tmpRef));
580     if (!methodRequireNapiRef_) {
581         TAG_LOGE(AAFwkTag::JSRUNTIME, "Failed to create reference for global.requireNapi");
582         return nullptr;
583     }
584 
585     napi_value className = nullptr;
586     napi_create_string_utf8(env, moduleName.c_str(), moduleName.length(), &className);
587     auto refValue = methodRequireNapiRef_->GetNapiValue();
588     napi_value args[1] = { className };
589     napi_value classValue = nullptr;
590     napi_call_function(env, globalObj, refValue, 1, args, &classValue);
591     napi_value instanceValue = nullptr;
592     napi_new_instance(env, classValue, argc, argv, &instanceValue);
593     if (instanceValue == nullptr) {
594         TAG_LOGE(AAFwkTag::JSRUNTIME, "Failed to create object instance");
595         return nullptr;
596     }
597 
598     napi_ref resultRef = nullptr;
599     napi_create_reference(env, instanceValue, 1, &resultRef);
600     return std::unique_ptr<NativeReference>(reinterpret_cast<NativeReference*>(resultRef));
601 }
602 
FinishPreload()603 void JsRuntime::FinishPreload()
604 {
605     auto vm = GetEcmaVm();
606     CHECK_POINTER(vm);
607     panda::JSNApi::PreFork(vm);
608 }
609 
PostPreload(const Options & options)610 void JsRuntime::PostPreload(const Options& options)
611 {
612     auto vm = GetEcmaVm();
613     CHECK_POINTER(vm);
614     auto env = GetNapiEnv();
615     CHECK_POINTER(env);
616     panda::RuntimeOption postOption;
617     postOption.SetBundleName(options.bundleName);
618     if (!options.arkNativeFilePath.empty()) {
619         std::string sandBoxAnFilePath = SANDBOX_ARK_CACHE_PATH + options.arkNativeFilePath;
620         postOption.SetAnDir(sandBoxAnFilePath);
621     }
622     if (options.isMultiThread) {
623         TAG_LOGD(AAFwkTag::JSRUNTIME, "Multi-Thread Mode: %{public}d", options.isMultiThread);
624         panda::JSNApi::SetMultiThreadCheck();
625     }
626     if (options.isErrorInfoEnhance) {
627         TAG_LOGD(AAFwkTag::JSRUNTIME, "Start Error-Info-Enhance Mode: %{public}d.", options.isErrorInfoEnhance);
628         panda::JSNApi::SetErrorInfoEnhance();
629     }
630     bool profileEnabled = OHOS::system::GetBoolParameter("ark.profile", false);
631     postOption.SetEnableProfile(profileEnabled);
632     TAG_LOGD(AAFwkTag::JSRUNTIME, "ASMM JIT Verify PostFork, jitEnabled: %{public}d", options.jitEnabled);
633     postOption.SetEnableJIT(options.jitEnabled);
634     postOption.SetAOTCompileStatusMap(options.aotCompileStatusMap);
635     {
636         HITRACE_METER_NAME(HITRACE_TAG_APP, "panda::JSNApi::PostFork");
637         panda::JSNApi::PostFork(vm, postOption);
638     }
639     reinterpret_cast<NativeEngine*>(env)->ReinitUVLoop();
640     uv_loop_s* loop = nullptr;
641     napi_get_uv_event_loop(env, &loop);
642     panda::JSNApi::SetLoop(vm, loop);
643 }
644 
LoadAotFile(const Options & options)645 void JsRuntime::LoadAotFile(const Options& options)
646 {
647     auto vm = GetEcmaVm();
648     CHECK_POINTER(vm);
649     if (options.hapPath.empty()) {
650         return;
651     }
652 
653     bool newCreate = false;
654     std::string loadPath = ExtractorUtil::GetLoadFilePath(options.hapPath);
655     std::shared_ptr<Extractor> extractor = ExtractorUtil::GetExtractor(loadPath, newCreate, true);
656     if (extractor != nullptr && newCreate) {
657         panda::JSNApi::LoadAotFile(vm, options.moduleName);
658     }
659 }
660 
Initialize(const Options & options)661 bool JsRuntime::Initialize(const Options& options)
662 {
663     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
664 #ifdef SUPPORT_GRAPHICS
665     if (Ace::AceForwardCompatibility::PipelineChanged()) {
666         preloaded_ = false;
667     }
668 #endif
669     if (!preloaded_) {
670         if (!CreateJsEnv(options)) {
671             TAG_LOGE(AAFwkTag::JSRUNTIME, "Create jsEnv failed");
672             return false;
673         }
674     }
675     apiTargetVersion_ = options.apiTargetVersion;
676     TAG_LOGD(AAFwkTag::JSRUNTIME, "Initialize: %{public}d", apiTargetVersion_);
677     bool isModular = false;
678     if (IsUseAbilityRuntime(options)) {
679         auto env = GetNapiEnv();
680         auto nativeEngine = reinterpret_cast<NativeEngine*>(env);
681         CHECK_POINTER_AND_RETURN(nativeEngine, false);
682 
683         auto vm = GetEcmaVm();
684         CHECK_POINTER_AND_RETURN(vm, false);
685 
686         if (preloaded_) {
687             PostPreload(options);
688         }
689         HandleScope handleScope(*this);
690         napi_value globalObj = nullptr;
691         napi_get_global(env, &globalObj);
692         CHECK_POINTER_AND_RETURN(globalObj, false);
693 
694         if (!preloaded_) {
695             InitSyscapModule(env, globalObj);
696 
697             // Simple hook function 'isSystemplugin'
698             const char* moduleName = "JsRuntime";
699             BindNativeFunction(env, globalObj, "isSystemplugin", moduleName,
700                 [](napi_env env, napi_callback_info cbinfo) -> napi_value {
701                     return CreateJsUndefined(env);
702                 });
703 
704             napi_value propertyValue = nullptr;
705             napi_get_named_property(env, globalObj, "requireNapi", &propertyValue);
706             napi_ref tmpRef = nullptr;
707             napi_create_reference(env, propertyValue, 1, &tmpRef);
708             methodRequireNapiRef_.reset(reinterpret_cast<NativeReference*>(tmpRef));
709             if (!methodRequireNapiRef_) {
710                 TAG_LOGE(AAFwkTag::JSRUNTIME, "Failed to create reference for global.requireNapi");
711                 return false;
712             }
713             TAG_LOGD(AAFwkTag::JSRUNTIME, "PreloadAce start");
714             PreloadAce(options);
715             TAG_LOGD(AAFwkTag::JSRUNTIME, "PreloadAce end");
716             nativeEngine->RegisterPermissionCheck(PermissionCheckFunc);
717         }
718 
719         if (!options.preload) {
720             isBundle_ = options.isBundle;
721             bundleName_ = options.bundleName;
722             codePath_ = options.codePath;
723             panda::JSNApi::SetSearchHapPathTracker(
724                 vm, [options](const std::string moduleName, std::string& hapPath)-> bool {
725                     if (options.hapModulePath.find(moduleName) == options.hapModulePath.end()) {
726                         return false;
727                     }
728                     hapPath = options.hapModulePath.find(moduleName)->second;
729                     return true;
730                 });
731             ReInitJsEnvImpl(options);
732             LoadAotFile(options);
733             panda::JSNApi::SetBundle(vm, options.isBundle);
734             panda::JSNApi::SetBundleName(vm, options.bundleName);
735             panda::JSNApi::SetHostResolveBufferTracker(
736                 vm, JsModuleReader(options.bundleName, options.hapPath, options.isUnique));
737             isModular = !panda::JSNApi::IsBundle(vm);
738             std::vector<panda::HmsMap> systemKitsMap = GetSystemKitsMap(apiTargetVersion_);
739             panda::JSNApi::SetHmsModuleList(vm, systemKitsMap);
740             std::map<std::string, std::vector<std::vector<std::string>>> pkgContextInfoMap;
741             std::map<std::string, std::string> pkgAliasMap;
742             pkgContextInfoJsonStringMap_ = options.pkgContextInfoJsonStringMap;
743             packageNameList_ = options.packageNameList;
744             JsRuntimeLite::GetInstance().GetPkgContextInfoListMap(
745                 options.pkgContextInfoJsonStringMap, pkgContextInfoMap, pkgAliasMap);
746             panda::JSNApi::SetpkgContextInfoList(vm, pkgContextInfoMap);
747             panda::JSNApi::SetPkgAliasList(vm, pkgAliasMap);
748             panda::JSNApi::SetPkgNameList(vm, options.packageNameList);
749         }
750     }
751 
752     if (!preloaded_) {
753         InitConsoleModule();
754     }
755 
756     if (!options.preload) {
757         auto operatorObj = std::make_shared<JsEnv::SourceMapOperator>(options.bundleName, isModular,
758                                                                       options.isDebugVersion);
759         InitSourceMap(operatorObj);
760 
761         if (options.isUnique) {
762             TAG_LOGD(AAFwkTag::JSRUNTIME, "Not supported TimerModule when form render");
763         } else {
764             InitTimerModule();
765         }
766 
767         InitWorkerModule(options);
768         SetModuleLoadChecker(options.moduleCheckerDelegate);
769         SetRequestAotCallback();
770 
771         if (!InitLoop(options.isStageModel)) {
772             TAG_LOGE(AAFwkTag::JSRUNTIME, "Init loop failed");
773             return false;
774         }
775     }
776 
777     preloaded_ = options.preload;
778     return true;
779 }
780 
CreateJsEnv(const Options & options)781 bool JsRuntime::CreateJsEnv(const Options& options)
782 {
783     panda::RuntimeOption pandaOption;
784     int arkProperties = OHOS::system::GetIntParameter<int>("persist.ark.properties", -1);
785     std::string bundleName = OHOS::system::GetParameter("persist.ark.arkbundlename", "");
786     std::string memConfigProperty = OHOS::system::GetParameter("persist.ark.mem_config_property", "");
787     size_t gcThreadNum = OHOS::system::GetUintParameter<size_t>("persist.ark.gcthreads", 7);
788     size_t longPauseTime = OHOS::system::GetUintParameter<size_t>("persist.ark.longpausetime", 40);
789     pandaOption.SetArkProperties(arkProperties);
790     pandaOption.SetArkBundleName(bundleName);
791     pandaOption.SetMemConfigProperty(memConfigProperty);
792     pandaOption.SetGcThreadNum(gcThreadNum);
793     pandaOption.SetLongPauseTime(longPauseTime);
794     TAG_LOGD(AAFwkTag::JSRUNTIME, "ark properties=%{public}d bundlename=%{public}s",
795         arkProperties, bundleName.c_str());
796     pandaOption.SetGcType(panda::RuntimeOption::GC_TYPE::GEN_GC);
797     pandaOption.SetGcPoolSize(DEFAULT_GC_POOL_SIZE);
798     pandaOption.SetLogLevel(panda::RuntimeOption::LOG_LEVEL::FOLLOW);
799     pandaOption.SetLogBufPrint(PrintVmLog);
800 
801     bool asmInterpreterEnabled = OHOS::system::GetBoolParameter("persist.ark.asminterpreter", true);
802     std::string asmOpcodeDisableRange = OHOS::system::GetParameter("persist.ark.asmopcodedisablerange", "");
803     pandaOption.SetEnableAsmInterpreter(asmInterpreterEnabled);
804     pandaOption.SetAsmOpcodeDisableRange(asmOpcodeDisableRange);
805     TAG_LOGD(AAFwkTag::JSRUNTIME, "ASMM JIT Verify CreateJsEnv, jitEnabled: %{public}d", options.jitEnabled);
806     pandaOption.SetEnableJIT(options.jitEnabled);
807 
808     if (options.isMultiThread) {
809         TAG_LOGD(AAFwkTag::JSRUNTIME, "Start Multi Thread Mode: %{public}d", options.isMultiThread);
810         panda::JSNApi::SetMultiThreadCheck();
811     }
812 
813     if (options.isErrorInfoEnhance) {
814         TAG_LOGD(AAFwkTag::JSRUNTIME, "Start Error Info Enhance Mode: %{public}d.", options.isErrorInfoEnhance);
815         panda::JSNApi::SetErrorInfoEnhance();
816     }
817 
818     if (IsUseAbilityRuntime(options)) {
819         // aot related
820         bool aotEnabled = OHOS::system::GetBoolParameter("persist.ark.aot", true);
821         pandaOption.SetEnableAOT(aotEnabled);
822         pandaOption.SetProfileDir(SANDBOX_ARK_PROIFILE_PATH);
823     }
824 
825     OHOSJsEnvLogger::RegisterJsEnvLogger();
826     jsEnv_ = std::make_shared<JsEnv::JsEnvironment>(std::make_unique<OHOSJsEnvironmentImpl>(options.eventRunner));
827     if (jsEnv_ == nullptr || !jsEnv_->Initialize(pandaOption, static_cast<void*>(this))) {
828         TAG_LOGE(AAFwkTag::JSRUNTIME, "Init jsEnv failed");
829         return false;
830     }
831 
832     return true;
833 }
834 
PreloadAce(const Options & options)835 void JsRuntime::PreloadAce(const Options& options)
836 {
837     auto nativeEngine = GetNativeEnginePointer();
838     CHECK_POINTER(nativeEngine);
839 #ifdef SUPPORT_GRAPHICS
840     if (options.loadAce) {
841         // ArkTsCard start
842         if (options.isUnique) {
843             OHOS::Ace::DeclarativeModulePreloader::PreloadCard(
844                 *nativeEngine, options.bundleName, options.pkgContextInfoJsonStringMap);
845         } else {
846             OHOS::Ace::DeclarativeModulePreloader::Preload(*nativeEngine);
847         }
848         // ArkTsCard end
849     }
850 #endif
851 }
852 
ReloadFormComponent()853 void JsRuntime::ReloadFormComponent()
854 {
855     TAG_LOGD(AAFwkTag::JSRUNTIME, "called");
856     auto nativeEngine = GetNativeEnginePointer();
857     CHECK_POINTER(nativeEngine);
858     // ArkTsCard update condition, need to reload new component
859     OHOS::Ace::DeclarativeModulePreloader::ReloadCard(*nativeEngine, bundleName_, pkgContextInfoJsonStringMap_);
860 }
861 
InitLoop(bool isStage)862 bool JsRuntime::InitLoop(bool isStage)
863 {
864     CHECK_POINTER_AND_RETURN(jsEnv_, false);
865     return jsEnv_->InitLoop(isStage);
866 }
867 
SetAppLibPath(const AppLibPathMap & appLibPaths,const bool & isSystemApp)868 void JsRuntime::SetAppLibPath(const AppLibPathMap& appLibPaths, const bool& isSystemApp)
869 {
870     TAG_LOGD(AAFwkTag::JSRUNTIME, "Set library path");
871 
872     if (appLibPaths.size() == 0) {
873         TAG_LOGW(AAFwkTag::JSRUNTIME, "no lib path to set");
874         return;
875     }
876 
877     auto moduleManager = NativeModuleManager::GetInstance();
878     if (moduleManager == nullptr) {
879         TAG_LOGE(AAFwkTag::JSRUNTIME, "null moduleManager");
880         return;
881     }
882 
883     for (const auto &appLibPath : appLibPaths) {
884         moduleManager->SetAppLibPath(appLibPath.first, appLibPath.second, isSystemApp);
885     }
886 }
887 
InitSourceMap(const std::shared_ptr<JsEnv::SourceMapOperator> operatorObj)888 void JsRuntime::InitSourceMap(const std::shared_ptr<JsEnv::SourceMapOperator> operatorObj)
889 {
890     CHECK_POINTER(jsEnv_);
891     jsEnv_->InitSourceMap(operatorObj);
892     JsEnv::SourceMap::RegisterReadSourceMapCallback(JsRuntime::ReadSourceMapData);
893     JsEnv::SourceMap::RegisterGetHapPathCallback(JsModuleReader::GetHapPathList);
894 }
895 
InitSourceMap(const std::string hqfFilePath)896 void JsRuntime::InitSourceMap(const std::string hqfFilePath)
897 {
898     std::string patchSoureMapFile;
899     std::vector<uint8_t> soureMapBuffer;
900     if (!GetFileBuffer(hqfFilePath, patchSoureMapFile, soureMapBuffer, false)) {
901         TAG_LOGE(AAFwkTag::JSRUNTIME, "get patchSoureMap file buffer failed");
902         return;
903     }
904     std::string str(soureMapBuffer.begin(), soureMapBuffer.end());
905     auto sourceMapOperator = jsEnv_->GetSourceMapOperator();
906     if (sourceMapOperator != nullptr) {
907         auto sourceMapObj = sourceMapOperator->GetSourceMapObj();
908         if (sourceMapObj != nullptr) {
909             sourceMapObj->SplitSourceMap(str);
910         }
911     }
912 }
913 
Deinitialize()914 void JsRuntime::Deinitialize()
915 {
916     TAG_LOGD(AAFwkTag::JSRUNTIME, "called");
917     for (auto it = modules_.begin(); it != modules_.end(); it = modules_.erase(it)) {
918         delete it->second;
919         it->second = nullptr;
920     }
921 
922     methodRequireNapiRef_.reset();
923 
924     CHECK_POINTER(jsEnv_);
925     jsEnv_->DeInitLoop();
926 }
927 
LoadJsBundle(const std::string & path,const std::string & hapPath,bool useCommonChunk)928 napi_value JsRuntime::LoadJsBundle(const std::string& path, const std::string& hapPath, bool useCommonChunk)
929 {
930     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
931     auto env = GetNapiEnv();
932     CHECK_POINTER_AND_RETURN(env, nullptr);
933     napi_value globalObj = nullptr;
934     napi_get_global(env, &globalObj);
935     napi_value exports = nullptr;
936     napi_create_object(env, &exports);
937     napi_set_named_property(env, globalObj, "exports", exports);
938 
939     if (!RunScript(path, hapPath, useCommonChunk)) {
940         TAG_LOGE(AAFwkTag::JSRUNTIME, "Failed to run script: %{private}s", path.c_str());
941         return nullptr;
942     }
943 
944     napi_value exportsObj = nullptr;
945     napi_get_named_property(env, globalObj, "exports", &exportsObj);
946     if (exportsObj == nullptr) {
947         TAG_LOGE(AAFwkTag::JSRUNTIME, "Failed to get exports objcect: %{private}s", path.c_str());
948         return nullptr;
949     }
950 
951     napi_value exportObj = nullptr;
952     napi_get_named_property(env, exportsObj, "default", &exportObj);
953     if (exportObj == nullptr) {
954         TAG_LOGE(AAFwkTag::JSRUNTIME, "Failed to get default objcect: %{private}s", path.c_str());
955         return nullptr;
956     }
957 
958     return exportObj;
959 }
960 
LoadJsModule(const std::string & path,const std::string & hapPath)961 napi_value JsRuntime::LoadJsModule(const std::string& path, const std::string& hapPath)
962 {
963     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
964     if (!RunScript(path, hapPath, false)) {
965         TAG_LOGE(AAFwkTag::JSRUNTIME, "Failed to run script: %{private}s", path.c_str());
966         return nullptr;
967     }
968 
969     auto vm = GetEcmaVm();
970     CHECK_POINTER_AND_RETURN(vm, nullptr);
971     panda::Local<panda::ObjectRef> exportObj = panda::JSNApi::GetExportObject(vm, path, "default");
972     if (exportObj->IsNull()) {
973         TAG_LOGE(AAFwkTag::JSRUNTIME, "Get export object failed");
974         return nullptr;
975     }
976 
977     auto env = GetNapiEnv();
978     CHECK_POINTER_AND_RETURN(env, nullptr);
979     return ArkNativeEngine::ArkValueToNapiValue(env, exportObj);
980 }
981 
LoadModule(const std::string & moduleName,const std::string & modulePath,const std::string & hapPath,bool esmodule,bool useCommonChunk)982 std::unique_ptr<NativeReference> JsRuntime::LoadModule(const std::string& moduleName, const std::string& modulePath,
983     const std::string& hapPath, bool esmodule, bool useCommonChunk)
984 {
985     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
986     TAG_LOGD(AAFwkTag::JSRUNTIME, "Load module(%{public}s, %{private}s, %{private}s, %{public}s)",
987         moduleName.c_str(), modulePath.c_str(), hapPath.c_str(), esmodule ? "true" : "false");
988     auto vm = GetEcmaVm();
989     CHECK_POINTER_AND_RETURN(vm, std::unique_ptr<NativeReference>());
990     // use for debugger, js engine need to know load module to handle debug event
991     panda::JSNApi::NotifyLoadModule(vm);
992     auto env = GetNapiEnv();
993     CHECK_POINTER_AND_RETURN(env, std::unique_ptr<NativeReference>());
994 
995     HandleScope handleScope(*this);
996 
997     std::string path = moduleName;
998     auto pos = path.find("::");
999     if (pos != std::string::npos) {
1000         path.erase(pos, path.size() - pos);
1001         moduleName_ = path;
1002     }
1003 
1004     napi_value classValue = nullptr;
1005 
1006     auto it = modules_.find(modulePath);
1007     if (it != modules_.end()) {
1008         classValue = it->second->GetNapiValue();
1009     } else {
1010         std::string fileName;
1011         if (!hapPath.empty()) {
1012             fileName.append(codePath_).append(Constants::FILE_SEPARATOR).append(modulePath);
1013             std::regex pattern(std::string(Constants::FILE_DOT) + std::string(Constants::FILE_SEPARATOR));
1014             fileName = std::regex_replace(fileName, pattern, "");
1015         } else {
1016             if (!MakeFilePath(codePath_, modulePath, fileName)) {
1017                 TAG_LOGE(AAFwkTag::JSRUNTIME, "Failed to make module file path: %{private}s", modulePath.c_str());
1018                 return std::unique_ptr<NativeReference>();
1019             }
1020         }
1021         classValue = esmodule ? LoadJsModule(fileName, hapPath) : LoadJsBundle(fileName, hapPath, useCommonChunk);
1022         if (classValue == nullptr) {
1023             return std::unique_ptr<NativeReference>();
1024         }
1025 
1026         napi_ref tmpRef = nullptr;
1027         napi_create_reference(env, classValue, 1, &tmpRef);
1028         modules_.emplace(modulePath, reinterpret_cast<NativeReference*>(tmpRef));
1029     }
1030 
1031     napi_value instanceValue = nullptr;
1032     napi_new_instance(env, classValue, 0, nullptr, &instanceValue);
1033     if (instanceValue == nullptr) {
1034         TAG_LOGE(AAFwkTag::JSRUNTIME, "Failed to create object instance");
1035         return std::unique_ptr<NativeReference>();
1036     }
1037 
1038     napi_ref resultRef = nullptr;
1039     napi_create_reference(env, instanceValue, 1, &resultRef);
1040     return std::unique_ptr<NativeReference>(reinterpret_cast<NativeReference*>(resultRef));
1041 }
1042 
LoadSystemModule(const std::string & moduleName,const napi_value * argv,size_t argc)1043 std::unique_ptr<NativeReference> JsRuntime::LoadSystemModule(
1044     const std::string& moduleName, const napi_value* argv, size_t argc)
1045 {
1046     TAG_LOGD(AAFwkTag::JSRUNTIME, "SystemModule %{public}s", moduleName.c_str());
1047     napi_env env = GetNapiEnv();
1048     CHECK_POINTER_AND_RETURN(env, std::unique_ptr<NativeReference>());
1049 
1050     HandleScope handleScope(*this);
1051 
1052     napi_value className = nullptr;
1053     napi_create_string_utf8(env, moduleName.c_str(), moduleName.length(), &className);
1054     napi_value globalObj = nullptr;
1055     napi_get_global(env, &globalObj);
1056     napi_value refValue = methodRequireNapiRef_->GetNapiValue();
1057     napi_value args[1] = { className };
1058     napi_value classValue = nullptr;
1059     napi_call_function(env, globalObj, refValue, 1, args, &classValue);
1060     napi_value instanceValue = nullptr;
1061     napi_new_instance(env, classValue, argc, argv, &instanceValue);
1062     if (instanceValue == nullptr) {
1063         TAG_LOGE(AAFwkTag::JSRUNTIME, "Failed to create object instance");
1064         return std::unique_ptr<NativeReference>();
1065     }
1066 
1067     napi_ref resultRef = nullptr;
1068     napi_create_reference(env, instanceValue, 1, &resultRef);
1069     return std::unique_ptr<NativeReference>(reinterpret_cast<NativeReference*>(resultRef));
1070 }
1071 
RunScript(const std::string & srcPath,const std::string & hapPath,bool useCommonChunk)1072 bool JsRuntime::RunScript(const std::string& srcPath, const std::string& hapPath, bool useCommonChunk)
1073 {
1074     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
1075     auto vm = GetEcmaVm();
1076     CHECK_POINTER_AND_RETURN(vm, false);
1077     std::string commonsPath = std::string(Constants::LOCAL_CODE_PATH) + "/" + moduleName_ + "/ets/commons.abc";
1078     std::string vendorsPath = std::string(Constants::LOCAL_CODE_PATH) + "/" + moduleName_ + "/ets/vendors.abc";
1079     if (hapPath.empty()) {
1080         if (useCommonChunk) {
1081             (void)LoadScript(commonsPath);
1082             (void)LoadScript(vendorsPath);
1083         }
1084         return LoadScript(srcPath);
1085     }
1086 
1087     bool newCreate = false;
1088     std::string loadPath = ExtractorUtil::GetLoadFilePath(hapPath);
1089     std::shared_ptr<Extractor> extractor = ExtractorUtil::GetExtractor(loadPath, newCreate, true);
1090     if (!extractor) {
1091         TAG_LOGE(AAFwkTag::JSRUNTIME, "Get extractor failed. hapPath[%{private}s]", hapPath.c_str());
1092         return false;
1093     }
1094     if (newCreate) {
1095         panda::JSNApi::LoadAotFile(vm, moduleName_);
1096         auto resourceManager = AbilityBase::ExtractResourceManager::GetExtractResourceManager().GetGlobalObject();
1097         if (resourceManager) {
1098             resourceManager->AddResource(loadPath.c_str());
1099         }
1100     }
1101 
1102     auto func = [&](std::string modulePath, const std::string abcPath) {
1103         bool useSafeMempry = apiTargetVersion_ == 0 || apiTargetVersion_ > API8;
1104         if (!extractor->IsHapCompress(modulePath) && useSafeMempry) {
1105             auto safeData = extractor->GetSafeData(modulePath);
1106             if (!safeData) {
1107                 TAG_LOGE(AAFwkTag::JSRUNTIME, "Get safeData abc file failed");
1108                 return false;
1109             }
1110             return LoadScript(abcPath, safeData->GetDataPtr(), safeData->GetDataLen(), isBundle_);
1111         } else {
1112             std::ostringstream outStream;
1113             if (!extractor->GetFileBuffer(modulePath, outStream)) {
1114                 TAG_LOGE(AAFwkTag::JSRUNTIME, "Get File  Buffer abc file failed");
1115                 return false;
1116             }
1117             const auto& outStr = outStream.str();
1118             std::vector<uint8_t> buffer;
1119             buffer.assign(outStr.begin(), outStr.end());
1120 
1121             return LoadScript(abcPath, &buffer, isBundle_);
1122         }
1123     };
1124 
1125     if (useCommonChunk) {
1126         (void)func(commonsPath, commonsPath);
1127         (void)func(vendorsPath, vendorsPath);
1128     }
1129 
1130     std::string path = srcPath;
1131     if (!isBundle_) {
1132         if (moduleName_.empty()) {
1133             TAG_LOGE(AAFwkTag::JSRUNTIME, "moduleName is hole");
1134             return false;
1135         }
1136         path = BUNDLE_INSTALL_PATH + moduleName_ + MERGE_ABC_PATH;
1137         panda::JSNApi::SetAssetPath(vm, path);
1138         panda::JSNApi::SetModuleName(vm, moduleName_);
1139     }
1140     return func(path, srcPath);
1141 }
1142 
RunSandboxScript(const std::string & path,const std::string & hapPath)1143 bool JsRuntime::RunSandboxScript(const std::string& path, const std::string& hapPath)
1144 {
1145     std::string fileName;
1146     if (!hapPath.empty()) {
1147         fileName.append(codePath_).append(Constants::FILE_SEPARATOR).append(path);
1148         std::regex pattern(std::string(Constants::FILE_DOT) + std::string(Constants::FILE_SEPARATOR));
1149         fileName = std::regex_replace(fileName, pattern, "");
1150     } else {
1151         if (!MakeFilePath(codePath_, path, fileName)) {
1152             TAG_LOGE(AAFwkTag::JSRUNTIME, "Failed to make module file path: %{private}s", path.c_str());
1153             return false;
1154         }
1155     }
1156 
1157     if (!RunScript(fileName, hapPath)) {
1158         TAG_LOGE(AAFwkTag::JSRUNTIME, "Failed to run script: %{public}s", fileName.c_str());
1159         return false;
1160     }
1161     return true;
1162 }
1163 
PostTask(const std::function<void ()> & task,const std::string & name,int64_t delayTime)1164 void JsRuntime::PostTask(const std::function<void()>& task, const std::string& name, int64_t delayTime)
1165 {
1166     CHECK_POINTER(jsEnv_);
1167     jsEnv_->PostTask(task, name, delayTime);
1168 }
1169 
PostSyncTask(const std::function<void ()> & task,const std::string & name)1170 void JsRuntime::PostSyncTask(const std::function<void()>& task, const std::string& name)
1171 {
1172     CHECK_POINTER(jsEnv_);
1173     jsEnv_->PostSyncTask(task, name);
1174 }
1175 
RemoveTask(const std::string & name)1176 void JsRuntime::RemoveTask(const std::string& name)
1177 {
1178     CHECK_POINTER(jsEnv_);
1179     jsEnv_->RemoveTask(name);
1180 }
1181 
DumpCpuProfile()1182 void JsRuntime::DumpCpuProfile()
1183 {
1184     auto nativeEngine = GetNativeEnginePointer();
1185     CHECK_POINTER(nativeEngine);
1186     nativeEngine->DumpCpuProfile();
1187 }
1188 
DumpHeapSnapshot(bool isPrivate)1189 void JsRuntime::DumpHeapSnapshot(bool isPrivate)
1190 {
1191     auto nativeEngine = GetNativeEnginePointer();
1192     CHECK_POINTER(nativeEngine);
1193     nativeEngine->DumpHeapSnapshot(true, DumpFormat::JSON, isPrivate, false);
1194 }
1195 
DumpHeapSnapshot(uint32_t tid,bool isFullGC)1196 void JsRuntime::DumpHeapSnapshot(uint32_t tid, bool isFullGC)
1197 {
1198     auto vm = GetEcmaVm();
1199     CHECK_POINTER(vm);
1200     panda::ecmascript::DumpSnapShotOption dumpOption;
1201     dumpOption.dumpFormat = panda::ecmascript::DumpFormat::JSON;
1202     dumpOption.isVmMode = true;
1203     dumpOption.isPrivate = false;
1204     dumpOption.captureNumericValue = true;
1205     dumpOption.isFullGC = isFullGC;
1206     dumpOption.isSync = false;
1207     DFXJSNApi::DumpHeapSnapshot(vm, dumpOption, tid);
1208 }
1209 
ForceFullGC(uint32_t tid)1210 void JsRuntime::ForceFullGC(uint32_t tid)
1211 {
1212     auto vm = GetEcmaVm();
1213     CHECK_POINTER(vm);
1214     DFXJSNApi::TriggerGC(vm, tid);
1215 }
1216 
DestroyHeapProfiler()1217 void JsRuntime::DestroyHeapProfiler()
1218 {
1219     CHECK_POINTER(jsEnv_);
1220     jsEnv_->DestroyHeapProfiler();
1221 }
1222 
ForceFullGC()1223 void JsRuntime::ForceFullGC()
1224 {
1225     auto vm = GetEcmaVm();
1226     CHECK_POINTER(vm);
1227     panda::JSNApi::TriggerGC(vm, panda::ecmascript::GCReason::TRIGGER_BY_ABILITY,
1228         panda::JSNApi::TRIGGER_GC_TYPE::FULL_GC);
1229 }
1230 
AllowCrossThreadExecution()1231 void JsRuntime::AllowCrossThreadExecution()
1232 {
1233     auto vm = GetEcmaVm();
1234     CHECK_POINTER(vm);
1235     panda::JSNApi::AllowCrossThreadExecution(vm);
1236 }
1237 
GetHeapPrepare()1238 void JsRuntime::GetHeapPrepare()
1239 {
1240     CHECK_POINTER(jsEnv_);
1241     jsEnv_->GetHeapPrepare();
1242 }
1243 
NotifyApplicationState(bool isBackground)1244 void JsRuntime::NotifyApplicationState(bool isBackground)
1245 {
1246     auto nativeEngine = GetNativeEnginePointer();
1247     CHECK_POINTER(nativeEngine);
1248     nativeEngine->NotifyApplicationState(isBackground);
1249     TAG_LOGD(AAFwkTag::JSRUNTIME, "isBackground %{public}d", isBackground);
1250 }
1251 
SuspendVM(uint32_t tid)1252 bool JsRuntime::SuspendVM(uint32_t tid)
1253 {
1254     auto nativeEngine = GetNativeEnginePointer();
1255     CHECK_POINTER_AND_RETURN(nativeEngine, false);
1256     return nativeEngine->SuspendVMById(tid);
1257 }
1258 
ResumeVM(uint32_t tid)1259 void JsRuntime::ResumeVM(uint32_t tid)
1260 {
1261     auto nativeEngine = GetNativeEnginePointer();
1262     CHECK_POINTER(nativeEngine);
1263     nativeEngine->ResumeVMById(tid);
1264 }
1265 
PreloadSystemModule(const std::string & moduleName)1266 void JsRuntime::PreloadSystemModule(const std::string& moduleName)
1267 {
1268     HandleScope handleScope(*this);
1269     auto env = GetNapiEnv();
1270     CHECK_POINTER(env);
1271     napi_value className = nullptr;
1272     napi_create_string_utf8(env, moduleName.c_str(), moduleName.length(), &className);
1273     napi_value globalObj = nullptr;
1274     napi_get_global(env, &globalObj);
1275     napi_value refValue = methodRequireNapiRef_->GetNapiValue();
1276     napi_value args[1] = { className };
1277     napi_call_function(env, globalObj, refValue, 1, args, nullptr);
1278 }
1279 
GetNativeEngine() const1280 NativeEngine& JsRuntime::GetNativeEngine() const
1281 {
1282     return *GetNativeEnginePointer();
1283 }
1284 
GetNapiEnv() const1285 napi_env JsRuntime::GetNapiEnv() const
1286 {
1287     return reinterpret_cast<napi_env>(GetNativeEnginePointer());
1288 }
1289 
GetNativeEnginePointer() const1290 NativeEngine* JsRuntime::GetNativeEnginePointer() const
1291 {
1292     CHECK_POINTER_AND_RETURN(jsEnv_, nullptr);
1293     return jsEnv_->GetNativeEngine();
1294 }
1295 
GetEcmaVm() const1296 panda::ecmascript::EcmaVM* JsRuntime::GetEcmaVm() const
1297 {
1298     CHECK_POINTER_AND_RETURN(jsEnv_, nullptr);
1299     return jsEnv_->GetVM();
1300 }
1301 
IsUseAbilityRuntime(const Options & options) const1302 bool JsRuntime::IsUseAbilityRuntime(const Options& options) const
1303 {
1304     return (options.isStageModel) || (options.isTestFramework);
1305 }
1306 
UpdateModuleNameAndAssetPath(const std::string & moduleName)1307 void JsRuntime::UpdateModuleNameAndAssetPath(const std::string& moduleName)
1308 {
1309     if (isBundle_) {
1310         return;
1311     }
1312 
1313     auto vm = GetEcmaVm();
1314     if (!vm || moduleName.empty()) {
1315         TAG_LOGE(AAFwkTag::JSRUNTIME, "vm is nullptr or moduleName is empty");
1316         return;
1317     }
1318 
1319     moduleName_ = moduleName;
1320     std::string path = BUNDLE_INSTALL_PATH + moduleName_ + MERGE_ABC_PATH;
1321     panda::JSNApi::SetAssetPath(vm, path);
1322     panda::JSNApi::SetModuleName(vm, moduleName_);
1323 }
1324 
RegisterUncaughtExceptionHandler(const JsEnv::UncaughtExceptionInfo & uncaughtExceptionInfo)1325 void JsRuntime::RegisterUncaughtExceptionHandler(const JsEnv::UncaughtExceptionInfo& uncaughtExceptionInfo)
1326 {
1327     CHECK_POINTER(jsEnv_);
1328     jsEnv_->RegisterUncaughtExceptionHandler(uncaughtExceptionInfo);
1329 }
1330 
RegisterQuickFixQueryFunc(const std::map<std::string,std::string> & moduleAndPath)1331 void JsRuntime::RegisterQuickFixQueryFunc(const std::map<std::string, std::string>& moduleAndPath)
1332 {
1333     auto vm = GetEcmaVm();
1334     CHECK_POINTER(vm);
1335     for (auto it = moduleAndPath.begin(); it != moduleAndPath.end(); it++) {
1336         std::string hqfFile(AbilityBase::GetLoadPath(it->second));
1337         InitSourceMap(hqfFile);
1338     }
1339     panda::JSNApi::RegisterQuickFixQueryFunc(vm, JsQuickfixCallback(moduleAndPath));
1340 }
1341 
ReadSourceMapData(const std::string & hapPath,const std::string & sourceMapPath,std::string & content)1342 bool JsRuntime::ReadSourceMapData(const std::string& hapPath, const std::string& sourceMapPath, std::string& content)
1343 {
1344     // Source map relative path, FA: "/assets/js", Stage: "/ets"
1345     if (hapPath.empty()) {
1346         TAG_LOGE(AAFwkTag::JSRUNTIME, "empty hapPath");
1347         return false;
1348     }
1349     bool newCreate = false;
1350     std::shared_ptr<Extractor> extractor = ExtractorUtil::GetExtractor(
1351         ExtractorUtil::GetLoadFilePath(hapPath), newCreate);
1352     if (extractor == nullptr) {
1353         TAG_LOGE(AAFwkTag::JSRUNTIME, "hap's path: %{public}s, get extractor failed", hapPath.c_str());
1354         return false;
1355     }
1356     std::unique_ptr<uint8_t[]> dataPtr = nullptr;
1357     size_t len = 0;
1358     if (!extractor->ExtractToBufByName(sourceMapPath, dataPtr, len)) {
1359         TAG_LOGD(AAFwkTag::JSRUNTIME, "can't find source map, and switch to stage model");
1360         std::string tempPath = std::regex_replace(sourceMapPath, std::regex("ets"), "assets/js");
1361         if (!extractor->ExtractToBufByName(tempPath, dataPtr, len)) {
1362             TAG_LOGD(AAFwkTag::JSRUNTIME, "get mergeSourceMapData fileBuffer failed, map path: %{private}s",
1363                 tempPath.c_str());
1364             return false;
1365         }
1366     }
1367     content.assign(dataPtr.get(), dataPtr.get() + len);
1368     return true;
1369 }
1370 
FreeNativeReference(std::unique_ptr<NativeReference> reference)1371 void JsRuntime::FreeNativeReference(std::unique_ptr<NativeReference> reference)
1372 {
1373     FreeNativeReference(std::move(reference), nullptr);
1374 }
1375 
FreeNativeReference(std::shared_ptr<NativeReference> && reference)1376 void JsRuntime::FreeNativeReference(std::shared_ptr<NativeReference>&& reference)
1377 {
1378     FreeNativeReference(nullptr, std::move(reference));
1379 }
1380 
1381 struct JsNativeReferenceDeleterObject {
1382     std::unique_ptr<NativeReference> uniqueNativeRef_ = nullptr;
1383     std::shared_ptr<NativeReference> sharedNativeRef_ = nullptr;
1384 };
1385 
FreeNativeReference(std::unique_ptr<NativeReference> uniqueNativeRef,std::shared_ptr<NativeReference> && sharedNativeRef)1386 void JsRuntime::FreeNativeReference(std::unique_ptr<NativeReference> uniqueNativeRef,
1387     std::shared_ptr<NativeReference>&& sharedNativeRef)
1388 {
1389     if (uniqueNativeRef == nullptr && sharedNativeRef == nullptr) {
1390         TAG_LOGW(AAFwkTag::JSRUNTIME, "invalid nativeRef");
1391         return;
1392     }
1393 
1394     auto nativeEngine = GetNativeEnginePointer();
1395     CHECK_POINTER(nativeEngine);
1396     auto uvLoop = nativeEngine->GetUVLoop();
1397     CHECK_POINTER(uvLoop);
1398 
1399     auto work = new (std::nothrow) uv_work_t;
1400     if (work == nullptr) {
1401         TAG_LOGE(AAFwkTag::JSRUNTIME, "null work");
1402         return;
1403     }
1404 
1405     auto cb = new (std::nothrow) JsNativeReferenceDeleterObject();
1406     if (cb == nullptr) {
1407         TAG_LOGE(AAFwkTag::JSRUNTIME, "null cb");
1408         delete work;
1409         work = nullptr;
1410         return;
1411     }
1412 
1413     if (uniqueNativeRef != nullptr) {
1414         cb->uniqueNativeRef_ = std::move(uniqueNativeRef);
1415     }
1416     if (sharedNativeRef != nullptr) {
1417         cb->sharedNativeRef_ = std::move(sharedNativeRef);
1418     }
1419     work->data = reinterpret_cast<void*>(cb);
1420     int ret = uv_queue_work(uvLoop, work, [](uv_work_t *work) {},
1421     [](uv_work_t *work, int status) {
1422         if (work != nullptr) {
1423             if (work->data != nullptr) {
1424                 delete reinterpret_cast<JsNativeReferenceDeleterObject*>(work->data);
1425                 work->data = nullptr;
1426             }
1427             delete work;
1428             work = nullptr;
1429         }
1430     });
1431     if (ret != 0) {
1432         delete reinterpret_cast<JsNativeReferenceDeleterObject*>(work->data);
1433         work->data = nullptr;
1434         delete work;
1435         work = nullptr;
1436     }
1437 }
1438 
InitTimerModule()1439 void JsRuntime::InitTimerModule()
1440 {
1441     CHECK_POINTER(jsEnv_);
1442     jsEnv_->InitTimerModule();
1443 }
1444 
InitWorkerModule(const Options & options)1445 void JsRuntime::InitWorkerModule(const Options& options)
1446 {
1447     CHECK_POINTER(jsEnv_);
1448     std::shared_ptr<JsEnv::WorkerInfo> workerInfo = std::make_shared<JsEnv::WorkerInfo>();
1449     workerInfo->codePath = panda::panda_file::StringPacProtect(options.codePath);
1450     workerInfo->isDebugVersion = options.isDebugVersion;
1451     workerInfo->isBundle = options.isBundle;
1452     workerInfo->packagePathStr = options.packagePathStr;
1453     workerInfo->assetBasePathStr = options.assetBasePathStr;
1454     workerInfo->hapPath = panda::panda_file::StringPacProtect(options.hapPath);
1455     workerInfo->isStageModel = panda::panda_file::BoolPacProtect(options.isStageModel);
1456     workerInfo->moduleName = options.moduleName;
1457     workerInfo->apiTargetVersion = panda::panda_file::DataProtect(static_cast<uintptr_t>(options.apiTargetVersion));
1458     if (options.isJsFramework) {
1459         SetJsFramework();
1460     }
1461     jsEnv_->InitWorkerModule(workerInfo);
1462 }
1463 
SetModuleLoadChecker(const std::shared_ptr<ModuleCheckerDelegate> moduleCheckerDelegate) const1464 void JsRuntime::SetModuleLoadChecker(const std::shared_ptr<ModuleCheckerDelegate> moduleCheckerDelegate) const
1465 {
1466     CHECK_POINTER(jsEnv_);
1467     jsEnv_->SetModuleLoadChecker(moduleCheckerDelegate);
1468 }
1469 
ReInitJsEnvImpl(const Options & options)1470 void JsRuntime::ReInitJsEnvImpl(const Options& options)
1471 {
1472     CHECK_POINTER(jsEnv_);
1473     jsEnv_->ReInitJsEnvImpl(std::make_unique<OHOSJsEnvironmentImpl>(options.eventRunner));
1474 }
1475 
SetRequestAotCallback()1476 void JsRuntime::SetRequestAotCallback()
1477 {
1478     CHECK_POINTER(jsEnv_);
1479     auto callback = [](const std::string& bundleName, const std::string& moduleName, int32_t triggerMode) -> int32_t {
1480         auto systemAbilityMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
1481         if (systemAbilityMgr == nullptr) {
1482             TAG_LOGE(AAFwkTag::JSRUNTIME, "get SaMgr failed");
1483             return ERR_INVALID_VALUE;
1484         }
1485 
1486         auto remoteObj = systemAbilityMgr->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
1487         if (remoteObj == nullptr) {
1488             TAG_LOGE(AAFwkTag::JSRUNTIME, "null remoteObject");
1489             return ERR_INVALID_VALUE;
1490         }
1491 
1492         auto bundleMgr = iface_cast<AppExecFwk::IBundleMgr>(remoteObj);
1493         if (bundleMgr == nullptr) {
1494             TAG_LOGE(AAFwkTag::JSRUNTIME, "get bms failed");
1495             return ERR_INVALID_VALUE;
1496         }
1497 
1498         TAG_LOGD(AAFwkTag::JSRUNTIME,
1499             "Reset compile status, bundleName: %{public}s, moduleName: %{public}s, triggerMode: %{public}d",
1500             bundleName.c_str(), moduleName.c_str(), triggerMode);
1501         return bundleMgr->ResetAOTCompileStatus(bundleName, moduleName, triggerMode);
1502     };
1503 
1504     jsEnv_->SetRequestAotCallback(callback);
1505 }
1506 
SetDeviceDisconnectCallback(const std::function<bool ()> & cb)1507 void JsRuntime::SetDeviceDisconnectCallback(const std::function<bool()> &cb)
1508 {
1509     TAG_LOGD(AAFwkTag::JSRUNTIME, "called");
1510     CHECK_POINTER(jsEnv_);
1511     jsEnv_->SetDeviceDisconnectCallback(cb);
1512 }
1513 
GetSystemKitPath()1514 std::string JsRuntime::GetSystemKitPath()
1515 {
1516     char buf[MAX_PATH_LEN] = { 0 };
1517     char *configPath = GetOneCfgFile(CONFIG_PATH.c_str(), buf, MAX_PATH_LEN);
1518     if (configPath == nullptr || configPath[0] == '\0' || strlen(configPath) > MAX_PATH_LEN) {
1519         return SYSTEM_KITS_CONFIG_PATH;
1520     }
1521     return configPath;
1522 }
1523 
GetSystemKitsMap(uint32_t version)1524 std::vector<panda::HmsMap> JsRuntime::GetSystemKitsMap(uint32_t version)
1525 {
1526     std::vector<panda::HmsMap> systemKitsMap;
1527     nlohmann::json jsonBuf;
1528     std::string configPath = GetSystemKitPath();
1529     if (configPath == "" || access(configPath.c_str(), F_OK) != 0) {
1530         return systemKitsMap;
1531     }
1532 
1533     std::fstream in;
1534     char errBuf[256];
1535     errBuf[0] = '\0';
1536     in.open(configPath, std::ios_base::in);
1537     if (!in.is_open()) {
1538         strerror_r(errno, errBuf, sizeof(errBuf));
1539         return systemKitsMap;
1540     }
1541 
1542     in.seekg(0, std::ios::end);
1543     int64_t size = in.tellg();
1544     if (size <= 0) {
1545         in.close();
1546         return systemKitsMap;
1547     }
1548 
1549     in.seekg(0, std::ios::beg);
1550     jsonBuf = nlohmann::json::parse(in, nullptr, false);
1551     in.close();
1552     if (jsonBuf.is_discarded()) {
1553         return systemKitsMap;
1554     }
1555 
1556     if (!jsonBuf.contains(SYSTEM_KITS)) {
1557         return systemKitsMap;
1558     }
1559     for (auto &item : jsonBuf.at(SYSTEM_KITS).items()) {
1560         nlohmann::json& jsonObject = item.value();
1561         if (!jsonObject.contains(NAMESPACE) || !jsonObject.at(NAMESPACE).is_string() ||
1562             !jsonObject.contains(TARGET_OHM) || !jsonObject.at(TARGET_OHM).is_string() ||
1563             !jsonObject.contains(SINCE_VERSION) || !jsonObject.at(SINCE_VERSION).is_number()) {
1564             continue;
1565         }
1566         uint32_t sinceVersion = jsonObject.at(SINCE_VERSION).get<uint32_t>();
1567         if (version >= sinceVersion) {
1568             panda::HmsMap hmsMap = {
1569                 .originalPath = jsonObject.at(NAMESPACE).get<std::string>(),
1570                 .targetPath = jsonObject.at(TARGET_OHM).get<std::string>(),
1571                 .sinceVersion = sinceVersion
1572             };
1573             systemKitsMap.emplace_back(hmsMap);
1574         }
1575     }
1576     TAG_LOGD(AAFwkTag::JSRUNTIME, "The size of the map is %{public}zu", systemKitsMap.size());
1577     return systemKitsMap;
1578 }
1579 
UpdatePkgContextInfoJson(std::string moduleName,std::string hapPath,std::string packageName)1580 void JsRuntime::UpdatePkgContextInfoJson(std::string moduleName, std::string hapPath, std::string packageName)
1581 {
1582     auto iterator = pkgContextInfoJsonStringMap_.find(moduleName);
1583     if (iterator == pkgContextInfoJsonStringMap_.end()) {
1584         pkgContextInfoJsonStringMap_[moduleName] = hapPath;
1585         packageNameList_[moduleName] = packageName;
1586         auto vm = GetEcmaVm();
1587         std::map<std::string, std::vector<std::vector<std::string>>> pkgContextInfoMap;
1588         std::map<std::string, std::string> pkgAliasMap;
1589         JsRuntimeLite::GetInstance().GetPkgContextInfoListMap(
1590             pkgContextInfoJsonStringMap_, pkgContextInfoMap, pkgAliasMap);
1591         panda::JSNApi::SetpkgContextInfoList(vm, pkgContextInfoMap);
1592         panda::JSNApi::SetPkgAliasList(vm, pkgAliasMap);
1593         panda::JSNApi::SetPkgNameList(vm, packageNameList_);
1594     }
1595 }
1596 } // namespace AbilityRuntime
1597 } // namespace OHOS
1598