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