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