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