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