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