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