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