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