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