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