• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 <regex>
22 
23 #include <atomic>
24 #include <sys/epoll.h>
25 #include <unistd.h>
26 
27 #include "accesstoken_kit.h"
28 #include "constants.h"
29 #include "connect_server_manager.h"
30 #include "ecmascript/napi/include/jsnapi.h"
31 #include "extract_resource_manager.h"
32 #include "file_path_utils.h"
33 #include "hdc_register.h"
34 #include "hilog_wrapper.h"
35 #include "hitrace_meter.h"
36 #include "hot_reloader.h"
37 #include "ipc_skeleton.h"
38 #include "js_environment.h"
39 #include "js_module_reader.h"
40 #include "js_module_searcher.h"
41 #include "js_quickfix_callback.h"
42 #include "js_runtime_utils.h"
43 #include "js_utils.h"
44 #include "js_worker.h"
45 #include "module_checker_delegate.h"
46 #include "native_engine/impl/ark/ark_native_engine.h"
47 #include "ohos_js_env_logger.h"
48 #include "ohos_js_environment_impl.h"
49 #include "parameters.h"
50 #include "extractor.h"
51 #include "systemcapability.h"
52 #include "source_map.h"
53 #include "source_map_operator.h"
54 
55 #ifdef SUPPORT_GRAPHICS
56 #include "declarative_module_preloader.h"
57 #endif
58 
59 using namespace OHOS::AbilityBase;
60 using Extractor = OHOS::AbilityBase::Extractor;
61 
62 namespace OHOS {
63 namespace AbilityRuntime {
64 namespace {
65 constexpr size_t PARAM_TWO = 2;
66 constexpr uint8_t SYSCAP_MAX_SIZE = 64;
67 constexpr int64_t DEFAULT_GC_POOL_SIZE = 0x10000000; // 256MB
68 constexpr int32_t DEFAULT_INTER_VAL = 500;
69 constexpr int32_t TRIGGER_GC_AFTER_CLEAR_STAGE_MS = 3000;
70 constexpr int32_t API8 = 8;
71 const std::string SANDBOX_ARK_CACHE_PATH = "/data/storage/ark-cache/";
72 const std::string SANDBOX_ARK_PROIFILE_PATH = "/data/storage/ark-profile";
73 #ifdef APP_USE_ARM
74 constexpr char ARK_DEBUGGER_LIB_PATH[] = "/system/lib/libark_debugger.z.so";
75 #else
76 constexpr char ARK_DEBUGGER_LIB_PATH[] = "/system/lib64/libark_debugger.z.so";
77 #endif
78 
79 constexpr char MERGE_ABC_PATH[] = "/ets/modules.abc";
80 constexpr char BUNDLE_INSTALL_PATH[] = "/data/storage/el1/bundle/";
81 constexpr const char* PERMISSION_RUN_ANY_CODE = "ohos.permission.RUN_ANY_CODE";
82 
__anon6260fd760202() 83 static auto PermissionCheckFunc = []() {
84     Security::AccessToken::AccessTokenID callerToken = IPCSkeleton::GetCallingTokenID();
85 
86     int result = Security::AccessToken::AccessTokenKit::VerifyAccessToken(callerToken, PERMISSION_RUN_ANY_CODE);
87     if (result == Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
88         return true;
89     } else {
90         return false;
91     }
92 };
93 
CanIUse(NativeEngine * engine,NativeCallbackInfo * info)94 NativeValue* CanIUse(NativeEngine* engine, NativeCallbackInfo* info)
95 {
96     if (engine == nullptr || info == nullptr) {
97         HILOG_ERROR("get syscap failed since engine or callback info is nullptr.");
98         return nullptr;
99     }
100 
101     if (info->argc != 1 || info->argv[0]->TypeOf() != NATIVE_STRING) {
102         HILOG_ERROR("Get syscap failed with invalid parameter.");
103         return engine->CreateUndefined();
104     }
105 
106     char syscap[SYSCAP_MAX_SIZE] = { 0 };
107 
108     NativeString* str = ConvertNativeValueTo<NativeString>(info->argv[0]);
109     if (str == nullptr) {
110         HILOG_ERROR("Convert to NativeString failed.");
111         return engine->CreateUndefined();
112     }
113     size_t bufferLen = str->GetLength();
114     size_t strLen = 0;
115     str->GetCString(syscap, bufferLen + 1, &strLen);
116 
117     bool ret = HasSystemCapability(syscap);
118     return engine->CreateBoolean(ret);
119 }
120 
InitSyscapModule(NativeEngine & engine,NativeObject & globalObject)121 void InitSyscapModule(NativeEngine& engine, NativeObject& globalObject)
122 {
123     const char *moduleName = "JsRuntime";
124     BindNativeFunction(engine, globalObject, "canIUse", moduleName, CanIUse);
125 }
126 
PrintVmLog(int32_t,int32_t,const char *,const char *,const char * message)127 int32_t PrintVmLog(int32_t, int32_t, const char*, const char*, const char* message)
128 {
129     HILOG_INFO("ArkLog: %{public}s", message);
130     return 0;
131 }
132 } // namespace
133 
134 std::atomic<bool> JsRuntime::hasInstance(false);
135 
JsRuntime()136 JsRuntime::JsRuntime()
137 {
138     HILOG_DEBUG("JsRuntime costructor.");
139 }
140 
~JsRuntime()141 JsRuntime::~JsRuntime()
142 {
143     HILOG_DEBUG("JsRuntime destructor.");
144     Deinitialize();
145     StopDebugMode();
146 }
147 
Create(const Options & options)148 std::unique_ptr<JsRuntime> JsRuntime::Create(const Options& options)
149 {
150     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
151     std::unique_ptr<JsRuntime> instance;
152 
153     if (!options.preload && options.isStageModel) {
154         auto preloadedInstance = Runtime::GetPreloaded();
155         if (preloadedInstance && preloadedInstance->GetLanguage() == Runtime::Language::JS) {
156             instance.reset(static_cast<JsRuntime*>(preloadedInstance.release()));
157         } else {
158             instance = std::make_unique<JsRuntime>();
159         }
160     } else {
161         instance = std::make_unique<JsRuntime>();
162     }
163 
164     if (!instance->Initialize(options)) {
165         return std::unique_ptr<JsRuntime>();
166     }
167     return instance;
168 }
169 
StartDebugMode(bool needBreakPoint)170 void JsRuntime::StartDebugMode(bool needBreakPoint)
171 {
172     if (debugMode_) {
173         HILOG_INFO("Already in debug mode");
174         return;
175     }
176     CHECK_POINTER(jsEnv_);
177     // Set instance id to tid after the first instance.
178     if (JsRuntime::hasInstance.exchange(true, std::memory_order_relaxed)) {
179         instanceId_ = static_cast<uint32_t>(gettid());
180     }
181 
182     HILOG_INFO("Ark VM is starting debug mode [%{public}s]", needBreakPoint ? "break" : "normal");
183     StartDebuggerInWorkerModule();
184     HdcRegister::Get().StartHdcRegister(bundleName_);
185     ConnectServerManager::Get().StartConnectServer(bundleName_);
186     ConnectServerManager::Get().AddInstance(instanceId_);
187     debugMode_ = StartDebugger(needBreakPoint, instanceId_);
188 }
189 
StopDebugMode()190 void JsRuntime::StopDebugMode()
191 {
192     if (debugMode_) {
193         ConnectServerManager::Get().RemoveInstance(instanceId_);
194         StopDebugger();
195     }
196 }
197 
InitConsoleModule()198 void JsRuntime::InitConsoleModule()
199 {
200     CHECK_POINTER(jsEnv_);
201     jsEnv_->InitConsoleModule();
202 }
203 
StartDebugger(bool needBreakPoint,uint32_t instanceId)204 bool JsRuntime::StartDebugger(bool needBreakPoint, uint32_t instanceId)
205 {
206     CHECK_POINTER_AND_RETURN(jsEnv_, false);
207     return jsEnv_->StartDebugger(ARK_DEBUGGER_LIB_PATH, needBreakPoint, instanceId);
208 }
209 
StopDebugger()210 void JsRuntime::StopDebugger()
211 {
212     CHECK_POINTER(jsEnv_);
213     jsEnv_->StopDebugger();
214 }
215 
JsperfProfilerCommandParse(const std::string & command,int32_t defaultValue)216 int32_t JsRuntime::JsperfProfilerCommandParse(const std::string &command, int32_t defaultValue)
217 {
218     HILOG_DEBUG("profiler command parse %{public}s", command.c_str());
219     auto findPos = command.find("jsperf");
220     if (findPos == std::string::npos) {
221         // jsperf command not found, so not to do, return zero.
222         HILOG_DEBUG("jsperf command not found");
223         return 0;
224     }
225 
226     // match jsperf command
227     auto jsPerfStr = command.substr(findPos, command.length() - findPos);
228     const std::regex regexJsperf(R"(^jsperf($|\s+($|\d*\s*($|nativeperf.*))))");
229     std::match_results<std::string::const_iterator> matchResults;
230     if (!std::regex_match(jsPerfStr, matchResults, regexJsperf)) {
231         HILOG_DEBUG("the order not match");
232         return defaultValue;
233     }
234 
235     // get match resuflt
236     std::string jsperfResuflt;
237     constexpr size_t matchResultIndex = 1;
238     if (matchResults.size() < PARAM_TWO) {
239         HILOG_ERROR("no results need to be matched");
240         return defaultValue;
241     }
242 
243     jsperfResuflt = matchResults[matchResultIndex].str();
244     // match number result
245     const std::regex regexJsperfNum(R"(^\s*(\d+).*)");
246     std::match_results<std::string::const_iterator> jsperfMatchResults;
247     if (!std::regex_match(jsperfResuflt, jsperfMatchResults, regexJsperfNum)) {
248         HILOG_DEBUG("the jsperf results not match");
249         return defaultValue;
250     }
251 
252     // get match result
253     std::string interval;
254     constexpr size_t matchNumResultIndex = 1;
255     if (jsperfMatchResults.size() < PARAM_TWO) {
256         HILOG_ERROR("no results need to be matched");
257         return defaultValue;
258     }
259 
260     interval = jsperfMatchResults[matchNumResultIndex].str();
261     if (interval.empty()) {
262         HILOG_DEBUG("match order result error");
263         return defaultValue;
264     }
265 
266     return std::stoi(interval);
267 }
268 
StartProfiler(const std::string & perfCmd)269 void JsRuntime::StartProfiler(const std::string &perfCmd)
270 {
271     CHECK_POINTER(jsEnv_);
272     if (JsRuntime::hasInstance.exchange(true, std::memory_order_relaxed)) {
273         instanceId_ = static_cast<uint32_t>(gettid());
274     }
275 
276     StartDebuggerInWorkerModule();
277     HdcRegister::Get().StartHdcRegister(bundleName_);
278     ConnectServerManager::Get().StartConnectServer(bundleName_);
279     ConnectServerManager::Get().AddInstance(instanceId_);
280     JsEnv::JsEnvironment::PROFILERTYPE profiler = JsEnv::JsEnvironment::PROFILERTYPE::PROFILERTYPE_HEAP;
281     int32_t interval = 0;
282     const std::string profilerCommand("profile");
283     if (perfCmd.find(profilerCommand) != std::string::npos) {
284         profiler = JsEnv::JsEnvironment::PROFILERTYPE::PROFILERTYPE_CPU;
285         interval = JsperfProfilerCommandParse(perfCmd, DEFAULT_INTER_VAL);
286     }
287 
288     HILOG_DEBUG("profiler:%{public}d interval:%{public}d.", profiler, interval);
289     jsEnv_->StartProfiler(ARK_DEBUGGER_LIB_PATH, instanceId_, profiler, interval);
290 }
291 
GetFileBuffer(const std::string & filePath,std::string & fileFullName,std::vector<uint8_t> & buffer)292 bool JsRuntime::GetFileBuffer(const std::string& filePath, std::string& fileFullName, std::vector<uint8_t>& buffer)
293 {
294     Extractor extractor(filePath);
295     if (!extractor.Init()) {
296         HILOG_ERROR("GetFileBuffer, Extractor of %{private}s init failed.", filePath.c_str());
297         return false;
298     }
299 
300     std::vector<std::string> fileNames;
301     extractor.GetSpecifiedTypeFiles(fileNames, ".abc");
302     if (fileNames.empty()) {
303         HILOG_WARN("GetFileBuffer, There's no abc file in hap or hqf %{private}s.", filePath.c_str());
304         return true;
305     }
306 
307     std::string fileName = fileNames.front();
308     fileFullName = filePath + "/" + fileName;
309     std::ostringstream outStream;
310     if (!extractor.ExtractByName(fileName, outStream)) {
311         HILOG_ERROR("GetFileBuffer, Extract %{public}s failed.", fileFullName.c_str());
312         return false;
313     }
314 
315     const auto &outStr = outStream.str();
316     buffer.assign(outStr.begin(), outStr.end());
317     return true;
318 }
319 
LoadRepairPatch(const std::string & hqfFile,const std::string & hapPath)320 bool JsRuntime::LoadRepairPatch(const std::string& hqfFile, const std::string& hapPath)
321 {
322     HILOG_DEBUG("LoadRepairPatch function called.");
323     auto vm = GetEcmaVm();
324     CHECK_POINTER_AND_RETURN(vm, false);
325 
326     std::string patchFile;
327     std::vector<uint8_t> patchBuffer;
328     if (!GetFileBuffer(hqfFile, patchFile, patchBuffer)) {
329         HILOG_ERROR("LoadRepairPatch, get patch file buffer failed.");
330         return false;
331     }
332 
333     std::string baseFile;
334     std::vector<uint8_t> baseBuffer;
335     if (!GetFileBuffer(hapPath, baseFile, baseBuffer)) {
336         HILOG_ERROR("LoadRepairPatch, get base file buffer failed.");
337         return false;
338     }
339 
340     std::string resolvedHapPath;
341     auto position = hapPath.find(".hap");
342     if (position != std::string::npos) {
343         resolvedHapPath = hapPath.substr(0, position) + MERGE_ABC_PATH;
344     }
345 
346     auto hspPosition = hapPath.find(".hsp");
347     if (hspPosition != std::string::npos) {
348         resolvedHapPath = hapPath.substr(0, hspPosition) + MERGE_ABC_PATH;
349     }
350 
351     HILOG_DEBUG("LoadRepairPatch, LoadPatch, patchFile: %{private}s, baseFile: %{private}s.",
352         patchFile.c_str(), resolvedHapPath.c_str());
353     auto ret = panda::JSNApi::LoadPatch(vm, patchFile, patchBuffer.data(), patchBuffer.size(),
354         resolvedHapPath, baseBuffer.data(), baseBuffer.size());
355     if (ret != panda::JSNApi::PatchErrorCode::SUCCESS) {
356         HILOG_ERROR("LoadPatch failed with %{public}d.", static_cast<int32_t>(ret));
357         return false;
358     }
359 
360     HILOG_DEBUG("LoadRepairPatch, Load patch %{private}s succeed.", patchFile.c_str());
361     return true;
362 }
363 
UnLoadRepairPatch(const std::string & hqfFile)364 bool JsRuntime::UnLoadRepairPatch(const std::string& hqfFile)
365 {
366     HILOG_DEBUG("UnLoadRepairPatch function called.");
367     auto vm = GetEcmaVm();
368     CHECK_POINTER_AND_RETURN(vm, false);
369 
370     Extractor extractor(hqfFile);
371     if (!extractor.Init()) {
372         HILOG_ERROR("UnLoadRepairPatch, Extractor of %{private}s init failed.", hqfFile.c_str());
373         return false;
374     }
375 
376     std::vector<std::string> fileNames;
377     extractor.GetSpecifiedTypeFiles(fileNames, ".abc");
378     if (fileNames.empty()) {
379         HILOG_WARN("UnLoadRepairPatch, There's no abc file in hqf %{private}s.", hqfFile.c_str());
380         return true;
381     }
382 
383     for (const auto &fileName : fileNames) {
384         std::string patchFile = hqfFile + "/" + fileName;
385         HILOG_DEBUG("UnLoadRepairPatch, UnloadPatch, patchFile: %{private}s.", patchFile.c_str());
386         auto ret = panda::JSNApi::UnloadPatch(vm, patchFile);
387         if (ret != panda::JSNApi::PatchErrorCode::SUCCESS) {
388             HILOG_WARN("UnLoadPatch failed with %{public}d.", static_cast<int32_t>(ret));
389         }
390         HILOG_DEBUG("UnLoadRepairPatch, UnLoad patch %{private}s succeed.", patchFile.c_str());
391     }
392 
393     return true;
394 }
395 
NotifyHotReloadPage()396 bool JsRuntime::NotifyHotReloadPage()
397 {
398     HILOG_DEBUG("function called.");
399     Ace::HotReloader::HotReload();
400     return true;
401 }
402 
LoadScript(const std::string & path,std::vector<uint8_t> * buffer,bool isBundle)403 bool JsRuntime::LoadScript(const std::string& path, std::vector<uint8_t>* buffer, bool isBundle)
404 {
405     HILOG_DEBUG("function called.");
406     CHECK_POINTER_AND_RETURN(jsEnv_, false);
407     return jsEnv_->LoadScript(path, buffer, isBundle);
408 }
409 
LoadScript(const std::string & path,uint8_t * buffer,size_t len,bool isBundle)410 bool JsRuntime::LoadScript(const std::string& path, uint8_t *buffer, size_t len, bool isBundle)
411 {
412     HILOG_DEBUG("function called.");
413     CHECK_POINTER_AND_RETURN(jsEnv_, false);
414     return jsEnv_->LoadScript(path, buffer, len, isBundle);
415 }
416 
LoadSystemModuleByEngine(NativeEngine * engine,const std::string & moduleName,NativeValue * const * argv,size_t argc)417 std::unique_ptr<NativeReference> JsRuntime::LoadSystemModuleByEngine(NativeEngine* engine,
418     const std::string& moduleName, NativeValue* const* argv, size_t argc)
419 {
420     HILOG_DEBUG("JsRuntime::LoadSystemModule(%{public}s)", moduleName.c_str());
421     if (engine == nullptr) {
422         HILOG_INFO("JsRuntime::LoadSystemModule: invalid engine.");
423         return std::unique_ptr<NativeReference>();
424     }
425 
426     NativeObject* globalObj = ConvertNativeValueTo<NativeObject>(engine->GetGlobal());
427     std::unique_ptr<NativeReference> methodRequireNapiRef_;
428     methodRequireNapiRef_.reset(engine->CreateReference(globalObj->GetProperty("requireNapi"), 1));
429     if (!methodRequireNapiRef_) {
430         HILOG_ERROR("Failed to create reference for global.requireNapi");
431         return nullptr;
432     }
433     NativeValue* className = engine->CreateString(moduleName.c_str(), moduleName.length());
434     NativeValue* classValue =
435         engine->CallFunction(engine->GetGlobal(), methodRequireNapiRef_->Get(), &className, 1);
436     NativeValue* instanceValue = engine->CreateInstance(classValue, argv, argc);
437     if (instanceValue == nullptr) {
438         HILOG_ERROR("Failed to create object instance");
439         return std::unique_ptr<NativeReference>();
440     }
441 
442     return std::unique_ptr<NativeReference>(engine->CreateReference(instanceValue, 1));
443 }
444 
FinishPreload()445 void JsRuntime::FinishPreload()
446 {
447     auto vm = GetEcmaVm();
448     CHECK_POINTER(vm);
449     panda::JSNApi::PreFork(vm);
450 }
451 
Initialize(const Options & options)452 bool JsRuntime::Initialize(const Options& options)
453 {
454     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
455     if (!preloaded_) {
456         if (!CreateJsEnv(options)) {
457             HILOG_ERROR("Create js environment failed.");
458             return false;
459         }
460     }
461     apiTargetVersion_ = options.apiTargetVersion;
462     HILOG_INFO("Initialize: %{public}d.", apiTargetVersion_);
463     bool isModular = false;
464     if (IsUseAbilityRuntime(options)) {
465         HandleScope handleScope(*this);
466         auto nativeEngine = GetNativeEnginePointer();
467         CHECK_POINTER_AND_RETURN(nativeEngine, false);
468 
469         auto vm = GetEcmaVm();
470         CHECK_POINTER_AND_RETURN(vm, false);
471 
472         if (preloaded_) {
473             panda::RuntimeOption postOption;
474             postOption.SetBundleName(options.bundleName);
475             if (!options.arkNativeFilePath.empty()) {
476                 std::string sandBoxAnFilePath = SANDBOX_ARK_CACHE_PATH + options.arkNativeFilePath;
477                 postOption.SetAnDir(sandBoxAnFilePath);
478             }
479             bool profileEnabled = OHOS::system::GetBoolParameter("ark.profile", false);
480             postOption.SetEnableProfile(profileEnabled);
481             panda::JSNApi::PostFork(vm, postOption);
482             nativeEngine->ReinitUVLoop();
483             panda::JSNApi::SetLoop(vm, nativeEngine->GetUVLoop());
484         }
485 
486         NativeObject* globalObj = ConvertNativeValueTo<NativeObject>(nativeEngine->GetGlobal());
487         CHECK_POINTER_AND_RETURN(globalObj, false);
488 
489         if (!preloaded_) {
490             InitSyscapModule(*nativeEngine, *globalObj);
491 
492             // Simple hook function 'isSystemplugin'
493             const char* moduleName = "JsRuntime";
494             BindNativeFunction(*nativeEngine, *globalObj, "isSystemplugin", moduleName,
495                 [](NativeEngine* engine, NativeCallbackInfo* info) -> NativeValue* {
496                     return engine->CreateUndefined();
497                 });
498 
499             methodRequireNapiRef_.reset(nativeEngine->CreateReference(globalObj->GetProperty("requireNapi"), 1));
500             if (!methodRequireNapiRef_) {
501                 HILOG_ERROR("Failed to create reference for global.requireNapi");
502                 return false;
503             }
504 
505             PreloadAce(options);
506             nativeEngine->RegisterPermissionCheck(PermissionCheckFunc);
507         }
508 
509         if (!options.preload) {
510             isBundle_ = options.isBundle;
511             bundleName_ = options.bundleName;
512             codePath_ = options.codePath;
513             ReInitJsEnvImpl(options);
514 
515             if (!options.hapPath.empty()) {
516                 bool newCreate = false;
517                 std::string loadPath = ExtractorUtil::GetLoadFilePath(options.hapPath);
518                 std::shared_ptr<Extractor> extractor = ExtractorUtil::GetExtractor(loadPath, newCreate, true);
519                 if (!extractor) {
520                     HILOG_ERROR("Get extractor failed. hapPath[%{private}s]", options.hapPath.c_str());
521                     return false;
522                 }
523                 if (newCreate) {
524                     panda::JSNApi::LoadAotFile(vm, options.moduleName);
525                 }
526             }
527 
528             panda::JSNApi::SetBundle(vm, options.isBundle);
529             panda::JSNApi::SetBundleName(vm, options.bundleName);
530             panda::JSNApi::SetHostResolveBufferTracker(
531                 vm, JsModuleReader(options.bundleName, options.hapPath, options.isUnique));
532             isModular = !panda::JSNApi::IsBundle(vm);
533         }
534     }
535 
536     if (!preloaded_) {
537         InitConsoleModule();
538     }
539 
540     if (!options.preload) {
541         auto operatorObj = std::make_shared<JsEnv::SourceMapOperator>(options.hapPath, isModular);
542         InitSourceMap(operatorObj);
543 
544         if (options.isUnique) {
545             HILOG_INFO("Not supported TimerModule when form render");
546         } else {
547             InitTimerModule();
548         }
549 
550         InitWorkerModule(options);
551         SetModuleLoadChecker(options.moduleCheckerDelegate);
552 
553         if (!InitLoop()) {
554             HILOG_ERROR("Initialize loop failed.");
555             return false;
556         }
557     }
558 
559     preloaded_ = options.preload;
560     return true;
561 }
562 
CreateJsEnv(const Options & options)563 bool JsRuntime::CreateJsEnv(const Options& options)
564 {
565     panda::RuntimeOption pandaOption;
566     int arkProperties = OHOS::system::GetIntParameter<int>("persist.ark.properties", -1);
567     std::string bundleName = OHOS::system::GetParameter("persist.ark.arkbundlename", "");
568     size_t gcThreadNum = OHOS::system::GetUintParameter<size_t>("persist.ark.gcthreads", 7);
569     size_t longPauseTime = OHOS::system::GetUintParameter<size_t>("persist.ark.longpausetime", 40);
570     pandaOption.SetArkProperties(arkProperties);
571     pandaOption.SetArkBundleName(bundleName);
572     pandaOption.SetGcThreadNum(gcThreadNum);
573     pandaOption.SetLongPauseTime(longPauseTime);
574     HILOG_INFO("JSRuntime::Initialize ark properties = %{public}d bundlename = %{public}s",
575         arkProperties, bundleName.c_str());
576     pandaOption.SetGcType(panda::RuntimeOption::GC_TYPE::GEN_GC);
577     pandaOption.SetGcPoolSize(DEFAULT_GC_POOL_SIZE);
578     pandaOption.SetLogLevel(panda::RuntimeOption::LOG_LEVEL::FOLLOW);
579     pandaOption.SetLogBufPrint(PrintVmLog);
580 
581     bool asmInterpreterEnabled = OHOS::system::GetBoolParameter("persist.ark.asminterpreter", true);
582     std::string asmOpcodeDisableRange = OHOS::system::GetParameter("persist.ark.asmopcodedisablerange", "");
583     pandaOption.SetEnableAsmInterpreter(asmInterpreterEnabled);
584     pandaOption.SetAsmOpcodeDisableRange(asmOpcodeDisableRange);
585 
586     if (IsUseAbilityRuntime(options)) {
587         // aot related
588         bool aotEnabled = OHOS::system::GetBoolParameter("persist.ark.aot", true);
589         pandaOption.SetEnableAOT(aotEnabled);
590         pandaOption.SetProfileDir(SANDBOX_ARK_PROIFILE_PATH);
591     }
592 
593     OHOSJsEnvLogger::RegisterJsEnvLogger();
594     jsEnv_ = std::make_shared<JsEnv::JsEnvironment>(std::make_unique<OHOSJsEnvironmentImpl>(options.eventRunner));
595     if (jsEnv_ == nullptr || !jsEnv_->Initialize(pandaOption, static_cast<void*>(this))) {
596         HILOG_ERROR("Initialize js environment failed.");
597         return false;
598     }
599 
600     return true;
601 }
602 
PreloadAce(const Options & options)603 void JsRuntime::PreloadAce(const Options& options)
604 {
605     auto nativeEngine = GetNativeEnginePointer();
606     CHECK_POINTER(nativeEngine);
607 #ifdef SUPPORT_GRAPHICS
608     if (options.loadAce) {
609         // ArkTsCard start
610         if (options.isUnique) {
611             OHOS::Ace::DeclarativeModulePreloader::PreloadCard(*nativeEngine, options.bundleName);
612         } else {
613             OHOS::Ace::DeclarativeModulePreloader::Preload(*nativeEngine);
614         }
615         // ArkTsCard end
616     }
617 #endif
618 }
619 
ReloadFormComponent()620 void JsRuntime::ReloadFormComponent()
621 {
622     HILOG_DEBUG("Call.");
623     auto nativeEngine = GetNativeEnginePointer();
624     CHECK_POINTER(nativeEngine);
625     // ArkTsCard update condition, need to reload new component
626     OHOS::Ace::DeclarativeModulePreloader::ReloadCard(*nativeEngine, bundleName_);
627 }
628 
DoCleanWorkAfterStageCleaned()629 void JsRuntime::DoCleanWorkAfterStageCleaned()
630 {
631     // Force gc. If the jsRuntime is destroyed, this task should not be executed.
632     HILOG_DEBUG("DoCleanWorkAfterStageCleaned begin");
633     RemoveTask("ability_destruct_gc");
634     auto gcTask = [this]() {
635         panda::JSNApi::TriggerGC(GetEcmaVm(), panda::JSNApi::TRIGGER_GC_TYPE::FULL_GC);
636     };
637     PostTask(gcTask, "ability_destruct_gc", TRIGGER_GC_AFTER_CLEAR_STAGE_MS);
638 }
639 
InitLoop()640 bool JsRuntime::InitLoop()
641 {
642     CHECK_POINTER_AND_RETURN(jsEnv_, false);
643     return jsEnv_->InitLoop();
644 }
645 
SetAppLibPath(const AppLibPathMap & appLibPaths,const bool & isSystemApp)646 void JsRuntime::SetAppLibPath(const AppLibPathMap& appLibPaths, const bool& isSystemApp)
647 {
648     HILOG_DEBUG("Set library path.");
649 
650     if (appLibPaths.size() == 0) {
651         HILOG_WARN("There's no library path need to set.");
652         return;
653     }
654 
655     auto moduleManager = NativeModuleManager::GetInstance();
656     if (moduleManager == nullptr) {
657         HILOG_ERROR("Get module manager failed.");
658         return;
659     }
660 
661     for (const auto &appLibPath : appLibPaths) {
662         moduleManager->SetAppLibPath(appLibPath.first, appLibPath.second, isSystemApp);
663     }
664 }
665 
InitSourceMap(const std::shared_ptr<JsEnv::SourceMapOperator> operatorObj)666 void JsRuntime::InitSourceMap(const std::shared_ptr<JsEnv::SourceMapOperator> operatorObj)
667 {
668     CHECK_POINTER(jsEnv_);
669     jsEnv_->InitSourceMap(operatorObj);
670     JsEnv::SourceMap::RegisterReadSourceMapCallback(JsRuntime::ReadSourceMapData);
671 }
672 
Deinitialize()673 void JsRuntime::Deinitialize()
674 {
675     HILOG_DEBUG("JsRuntime deinitialize.");
676     for (auto it = modules_.begin(); it != modules_.end(); it = modules_.erase(it)) {
677         delete it->second;
678         it->second = nullptr;
679     }
680 
681     methodRequireNapiRef_.reset();
682 
683     CHECK_POINTER(jsEnv_);
684     jsEnv_->DeInitLoop();
685 }
686 
LoadJsBundle(const std::string & path,const std::string & hapPath,bool useCommonChunk)687 NativeValue* JsRuntime::LoadJsBundle(const std::string& path, const std::string& hapPath, bool useCommonChunk)
688 {
689     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
690     auto nativeEngine = GetNativeEnginePointer();
691     CHECK_POINTER_AND_RETURN(nativeEngine, nullptr);
692     NativeObject* globalObj = ConvertNativeValueTo<NativeObject>(nativeEngine->GetGlobal());
693     NativeValue* exports = nativeEngine->CreateObject();
694     globalObj->SetProperty("exports", exports);
695 
696     if (!RunScript(path, hapPath, useCommonChunk)) {
697         HILOG_ERROR("Failed to run script: %{private}s", path.c_str());
698         return nullptr;
699     }
700 
701     NativeObject* exportsObj = ConvertNativeValueTo<NativeObject>(globalObj->GetProperty("exports"));
702     if (exportsObj == nullptr) {
703         HILOG_ERROR("Failed to get exports objcect: %{private}s", path.c_str());
704         return nullptr;
705     }
706 
707     NativeValue* exportObj = exportsObj->GetProperty("default");
708     if (exportObj == nullptr) {
709         HILOG_ERROR("Failed to get default objcect: %{private}s", path.c_str());
710         return nullptr;
711     }
712 
713     return exportObj;
714 }
715 
LoadJsModule(const std::string & path,const std::string & hapPath)716 NativeValue* JsRuntime::LoadJsModule(const std::string& path, const std::string& hapPath)
717 {
718     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
719     if (!RunScript(path, hapPath, false)) {
720         HILOG_ERROR("Failed to run script: %{private}s", path.c_str());
721         return nullptr;
722     }
723 
724     auto vm = GetEcmaVm();
725     CHECK_POINTER_AND_RETURN(vm, nullptr);
726     panda::Local<panda::ObjectRef> exportObj = panda::JSNApi::GetExportObject(vm, path, "default");
727     if (exportObj->IsNull()) {
728         HILOG_ERROR("Get export object failed");
729         return nullptr;
730     }
731 
732     auto nativeEngine = GetNativeEnginePointer();
733     CHECK_POINTER_AND_RETURN(nativeEngine, nullptr);
734     return ArkNativeEngine::ArkValueToNativeValue(static_cast<ArkNativeEngine*>(nativeEngine), exportObj);
735 }
736 
LoadModule(const std::string & moduleName,const std::string & modulePath,const std::string & hapPath,bool esmodule,bool useCommonChunk)737 std::unique_ptr<NativeReference> JsRuntime::LoadModule(const std::string& moduleName, const std::string& modulePath,
738     const std::string& hapPath, bool esmodule, bool useCommonChunk)
739 {
740     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
741     HILOG_DEBUG("JsRuntime::LoadModule(%{public}s, %{private}s, %{private}s, %{public}s)",
742         moduleName.c_str(), modulePath.c_str(), hapPath.c_str(), esmodule ? "true" : "false");
743     auto nativeEngine = GetNativeEnginePointer();
744     CHECK_POINTER_AND_RETURN(nativeEngine, std::unique_ptr<NativeReference>());
745 
746     HandleScope handleScope(*this);
747 
748     std::string path = moduleName;
749     auto pos = path.find("::");
750     if (pos != std::string::npos) {
751         path.erase(pos, path.size() - pos);
752         moduleName_ = path;
753     }
754 
755     NativeValue* classValue = nullptr;
756 
757     auto it = modules_.find(modulePath);
758     if (it != modules_.end()) {
759         classValue = it->second->Get();
760     } else {
761         std::string fileName;
762         if (!hapPath.empty()) {
763             fileName.append(codePath_).append(Constants::FILE_SEPARATOR).append(modulePath);
764             std::regex pattern(std::string(Constants::FILE_DOT) + std::string(Constants::FILE_SEPARATOR));
765             fileName = std::regex_replace(fileName, pattern, "");
766         } else {
767             if (!MakeFilePath(codePath_, modulePath, fileName)) {
768                 HILOG_ERROR("Failed to make module file path: %{private}s", modulePath.c_str());
769                 return std::unique_ptr<NativeReference>();
770             }
771         }
772         classValue = esmodule ? LoadJsModule(fileName, hapPath) : LoadJsBundle(fileName, hapPath, useCommonChunk);
773         if (classValue == nullptr) {
774             return std::unique_ptr<NativeReference>();
775         }
776 
777         modules_.emplace(modulePath, nativeEngine->CreateReference(classValue, 1));
778     }
779 
780     NativeValue* instanceValue = nativeEngine->CreateInstance(classValue, nullptr, 0);
781     if (instanceValue == nullptr) {
782         HILOG_ERROR("Failed to create object instance");
783         return std::unique_ptr<NativeReference>();
784     }
785 
786     return std::unique_ptr<NativeReference>(nativeEngine->CreateReference(instanceValue, 1));
787 }
788 
LoadSystemModule(const std::string & moduleName,NativeValue * const * argv,size_t argc)789 std::unique_ptr<NativeReference> JsRuntime::LoadSystemModule(
790     const std::string& moduleName, NativeValue* const* argv, size_t argc)
791 {
792     HILOG_INFO("JsRuntime::LoadSystemModule(%{public}s)", moduleName.c_str());
793     auto nativeEngine = GetNativeEnginePointer();
794     CHECK_POINTER_AND_RETURN(nativeEngine, std::unique_ptr<NativeReference>());
795 
796     HandleScope handleScope(*this);
797 
798     NativeValue* className = nativeEngine->CreateString(moduleName.c_str(), moduleName.length());
799     NativeValue* classValue =
800         nativeEngine->CallFunction(nativeEngine->GetGlobal(), methodRequireNapiRef_->Get(), &className, 1);
801     NativeValue* instanceValue = nativeEngine->CreateInstance(classValue, argv, argc);
802     if (instanceValue == nullptr) {
803         HILOG_ERROR("Failed to create object instance");
804         return std::unique_ptr<NativeReference>();
805     }
806 
807     return std::unique_ptr<NativeReference>(nativeEngine->CreateReference(instanceValue, 1));
808 }
809 
RunScript(const std::string & srcPath,const std::string & hapPath,bool useCommonChunk)810 bool JsRuntime::RunScript(const std::string& srcPath, const std::string& hapPath, bool useCommonChunk)
811 {
812     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
813     auto nativeEngine = GetNativeEnginePointer();
814     CHECK_POINTER_AND_RETURN(nativeEngine, false);
815     auto vm = GetEcmaVm();
816     CHECK_POINTER_AND_RETURN(vm, false);
817 
818     std::string commonsPath = std::string(Constants::LOCAL_CODE_PATH) + "/" + moduleName_ + "/ets/commons.abc";
819     std::string vendorsPath = std::string(Constants::LOCAL_CODE_PATH) + "/" + moduleName_ + "/ets/vendors.abc";
820     if (hapPath.empty()) {
821         if (useCommonChunk) {
822             (void)LoadScript(commonsPath);
823             (void)LoadScript(vendorsPath);
824         }
825         return LoadScript(srcPath);
826     }
827 
828     bool newCreate = false;
829     std::string loadPath = ExtractorUtil::GetLoadFilePath(hapPath);
830     std::shared_ptr<Extractor> extractor = ExtractorUtil::GetExtractor(loadPath, newCreate, true);
831     if (!extractor) {
832         HILOG_ERROR("Get extractor failed. hapPath[%{private}s]", hapPath.c_str());
833         return false;
834     }
835     if (newCreate) {
836         panda::JSNApi::LoadAotFile(vm, moduleName_);
837         auto resourceManager = AbilityBase::ExtractResourceManager::GetExtractResourceManager().GetGlobalObject();
838         if (resourceManager) {
839             resourceManager->AddResource(loadPath.c_str());
840         }
841     }
842 
843     auto func = [&](std::string modulePath, const std::string abcPath) {
844         bool useSafeMempry = apiTargetVersion_ == 0 || apiTargetVersion_ > API8;
845         if (!extractor->IsHapCompress(modulePath) && useSafeMempry) {
846             auto safeData = extractor->GetSafeData(modulePath);
847             if (!safeData) {
848                 HILOG_ERROR("Get abc file failed.");
849                 return false;
850             }
851             return LoadScript(abcPath, safeData->GetDataPtr(), safeData->GetDataLen(), isBundle_);
852         } else {
853             std::ostringstream outStream;
854             if (!extractor->GetFileBuffer(modulePath, outStream)) {
855                 HILOG_ERROR("Get abc file failed");
856                 return false;
857             }
858             const auto& outStr = outStream.str();
859             std::vector<uint8_t> buffer;
860             buffer.assign(outStr.begin(), outStr.end());
861 
862             return LoadScript(abcPath, &buffer, isBundle_);
863         }
864     };
865 
866     if (useCommonChunk) {
867         (void)func(commonsPath, commonsPath);
868         (void)func(vendorsPath, vendorsPath);
869     }
870 
871     std::string path = srcPath;
872     if (!isBundle_) {
873         if (moduleName_.empty()) {
874             HILOG_ERROR("moduleName is hole");
875             return false;
876         }
877         path = BUNDLE_INSTALL_PATH + moduleName_ + MERGE_ABC_PATH;
878         panda::JSNApi::SetAssetPath(vm, path);
879         panda::JSNApi::SetModuleName(vm, moduleName_);
880     }
881     return func(path, srcPath);
882 }
883 
RunSandboxScript(const std::string & path,const std::string & hapPath)884 bool JsRuntime::RunSandboxScript(const std::string& path, const std::string& hapPath)
885 {
886     std::string fileName;
887     if (!hapPath.empty()) {
888         fileName.append(codePath_).append(Constants::FILE_SEPARATOR).append(path);
889         std::regex pattern(std::string(Constants::FILE_DOT) + std::string(Constants::FILE_SEPARATOR));
890         fileName = std::regex_replace(fileName, pattern, "");
891     } else {
892         if (!MakeFilePath(codePath_, path, fileName)) {
893             HILOG_ERROR("Failed to make module file path: %{private}s", path.c_str());
894             return false;
895         }
896     }
897 
898     if (!RunScript(fileName, hapPath)) {
899         HILOG_ERROR("Failed to run script: %{public}s", fileName.c_str());
900         return false;
901     }
902     return true;
903 }
904 
PostTask(const std::function<void ()> & task,const std::string & name,int64_t delayTime)905 void JsRuntime::PostTask(const std::function<void()>& task, const std::string& name, int64_t delayTime)
906 {
907     CHECK_POINTER(jsEnv_);
908     jsEnv_->PostTask(task, name, delayTime);
909 }
910 
PostSyncTask(const std::function<void ()> & task,const std::string & name)911 void JsRuntime::PostSyncTask(const std::function<void()>& task, const std::string& name)
912 {
913     CHECK_POINTER(jsEnv_);
914     jsEnv_->PostSyncTask(task, name);
915 }
916 
RemoveTask(const std::string & name)917 void JsRuntime::RemoveTask(const std::string& name)
918 {
919     CHECK_POINTER(jsEnv_);
920     jsEnv_->RemoveTask(name);
921 }
922 
DumpHeapSnapshot(bool isPrivate)923 void JsRuntime::DumpHeapSnapshot(bool isPrivate)
924 {
925     auto nativeEngine = GetNativeEnginePointer();
926     CHECK_POINTER(nativeEngine);
927     nativeEngine->DumpHeapSnapshot(true, DumpFormat::JSON, isPrivate);
928 }
929 
BuildJsStackInfoList(uint32_t tid,std::vector<JsFrames> & jsFrames)930 bool JsRuntime::BuildJsStackInfoList(uint32_t tid, std::vector<JsFrames>& jsFrames)
931 {
932     auto nativeEngine = GetNativeEnginePointer();
933     CHECK_POINTER_AND_RETURN(nativeEngine, false);
934     std::vector<JsFrameInfo> jsFrameInfo;
935     bool ret = nativeEngine->BuildJsStackInfoList(tid, jsFrameInfo);
936     if (!ret) {
937         return ret;
938     }
939     for (auto jf : jsFrameInfo) {
940         struct JsFrames jsFrame;
941         jsFrame.functionName = jf.functionName;
942         jsFrame.fileName = jf.fileName;
943         jsFrame.pos = jf.pos;
944         jsFrame.nativePointer = jf.nativePointer;
945         jsFrames.emplace_back(jsFrame);
946     }
947     return ret;
948 }
949 
NotifyApplicationState(bool isBackground)950 void JsRuntime::NotifyApplicationState(bool isBackground)
951 {
952     auto nativeEngine = GetNativeEnginePointer();
953     CHECK_POINTER(nativeEngine);
954     nativeEngine->NotifyApplicationState(isBackground);
955     HILOG_INFO("NotifyApplicationState, isBackground %{public}d.", isBackground);
956 }
957 
SuspendVM(uint32_t tid)958 bool JsRuntime::SuspendVM(uint32_t tid)
959 {
960     auto nativeEngine = GetNativeEnginePointer();
961     CHECK_POINTER_AND_RETURN(nativeEngine, false);
962     return nativeEngine->SuspendVMById(tid);
963 }
964 
ResumeVM(uint32_t tid)965 void JsRuntime::ResumeVM(uint32_t tid)
966 {
967     auto nativeEngine = GetNativeEnginePointer();
968     CHECK_POINTER(nativeEngine);
969     nativeEngine->ResumeVMById(tid);
970 }
971 
PreloadSystemModule(const std::string & moduleName)972 void JsRuntime::PreloadSystemModule(const std::string& moduleName)
973 {
974     HandleScope handleScope(*this);
975     auto nativeEngine = GetNativeEnginePointer();
976     CHECK_POINTER(nativeEngine);
977     NativeValue* className = nativeEngine->CreateString(moduleName.c_str(), moduleName.length());
978     nativeEngine->CallFunction(nativeEngine->GetGlobal(), methodRequireNapiRef_->Get(), &className, 1);
979 }
980 
GetNativeEngine() const981 NativeEngine& JsRuntime::GetNativeEngine() const
982 {
983     return *GetNativeEnginePointer();
984 }
985 
GetNativeEnginePointer() const986 NativeEngine* JsRuntime::GetNativeEnginePointer() const
987 {
988     CHECK_POINTER_AND_RETURN(jsEnv_, nullptr);
989     return jsEnv_->GetNativeEngine();
990 }
991 
GetEcmaVm() const992 panda::ecmascript::EcmaVM* JsRuntime::GetEcmaVm() const
993 {
994     CHECK_POINTER_AND_RETURN(jsEnv_, nullptr);
995     return jsEnv_->GetVM();
996 }
997 
IsUseAbilityRuntime(const Options & options) const998 bool JsRuntime::IsUseAbilityRuntime(const Options& options) const
999 {
1000     return (options.isStageModel) || (options.isTestFramework);
1001 }
1002 
UpdateModuleNameAndAssetPath(const std::string & moduleName)1003 void JsRuntime::UpdateModuleNameAndAssetPath(const std::string& moduleName)
1004 {
1005     if (isBundle_) {
1006         return;
1007     }
1008 
1009     auto vm = GetEcmaVm();
1010     if (!vm || moduleName.empty()) {
1011         HILOG_ERROR("vm is nullptr or moduleName is empty");
1012         return;
1013     }
1014 
1015     moduleName_ = moduleName;
1016     std::string path = BUNDLE_INSTALL_PATH + moduleName_ + MERGE_ABC_PATH;
1017     panda::JSNApi::SetAssetPath(vm, path);
1018     panda::JSNApi::SetModuleName(vm, moduleName_);
1019 }
1020 
RegisterUncaughtExceptionHandler(JsEnv::UncaughtExceptionInfo uncaughtExceptionInfo)1021 void JsRuntime::RegisterUncaughtExceptionHandler(JsEnv::UncaughtExceptionInfo uncaughtExceptionInfo)
1022 {
1023     CHECK_POINTER(jsEnv_);
1024     jsEnv_->RegisterUncaughtExceptionHandler(uncaughtExceptionInfo);
1025 }
1026 
RegisterQuickFixQueryFunc(const std::map<std::string,std::string> & moduleAndPath)1027 void JsRuntime::RegisterQuickFixQueryFunc(const std::map<std::string, std::string>& moduleAndPath)
1028 {
1029     auto vm = GetEcmaVm();
1030     if (vm != nullptr) {
1031         panda::JSNApi::RegisterQuickFixQueryFunc(vm, JsQuickfixCallback(moduleAndPath));
1032     }
1033 }
1034 
ReadSourceMapData(const std::string & hapPath,const std::string & sourceMapPath,std::string & content)1035 bool JsRuntime::ReadSourceMapData(const std::string& hapPath, const std::string& sourceMapPath, std::string& content)
1036 {
1037     // Source map relative path, FA: "/assets/js", Stage: "/ets"
1038     if (hapPath.empty()) {
1039         HILOG_ERROR("hapPath is empty");
1040         return false;
1041     }
1042     bool newCreate = false;
1043     std::shared_ptr<Extractor> extractor = ExtractorUtil::GetExtractor(
1044         ExtractorUtil::GetLoadFilePath(hapPath), newCreate);
1045     if (extractor == nullptr) {
1046         HILOG_ERROR("hap's path: %{public}s, get extractor failed", hapPath.c_str());
1047         return false;
1048     }
1049     std::unique_ptr<uint8_t[]> dataPtr = nullptr;
1050     size_t len = 0;
1051     if (!extractor->ExtractToBufByName(sourceMapPath, dataPtr, len)) {
1052         HILOG_DEBUG("can't find source map, and switch to stage model.");
1053         std::string tempPath = std::regex_replace(sourceMapPath, std::regex("ets"), "assets/js");
1054         if (!extractor->ExtractToBufByName(tempPath, dataPtr, len)) {
1055             HILOG_ERROR("get mergeSourceMapData fileBuffer failed, map path: %{private}s", tempPath.c_str());
1056             return false;
1057         }
1058     }
1059     content.assign(dataPtr.get(), dataPtr.get() + len);
1060     return true;
1061 }
1062 
FreeNativeReference(std::unique_ptr<NativeReference> reference)1063 void JsRuntime::FreeNativeReference(std::unique_ptr<NativeReference> reference)
1064 {
1065     FreeNativeReference(std::move(reference), nullptr);
1066 }
1067 
FreeNativeReference(std::shared_ptr<NativeReference> && reference)1068 void JsRuntime::FreeNativeReference(std::shared_ptr<NativeReference>&& reference)
1069 {
1070     FreeNativeReference(nullptr, std::move(reference));
1071 }
1072 
1073 struct JsNativeReferenceDeleterObject {
1074     std::unique_ptr<NativeReference> uniqueNativeRef_ = nullptr;
1075     std::shared_ptr<NativeReference> sharedNativeRef_ = nullptr;
1076 };
1077 
FreeNativeReference(std::unique_ptr<NativeReference> uniqueNativeRef,std::shared_ptr<NativeReference> && sharedNativeRef)1078 void JsRuntime::FreeNativeReference(std::unique_ptr<NativeReference> uniqueNativeRef,
1079     std::shared_ptr<NativeReference>&& sharedNativeRef)
1080 {
1081     if (uniqueNativeRef == nullptr && sharedNativeRef == nullptr) {
1082         HILOG_WARN("native reference is invalid.");
1083         return;
1084     }
1085 
1086     auto nativeEngine = GetNativeEnginePointer();
1087     CHECK_POINTER(nativeEngine);
1088     auto uvLoop = nativeEngine->GetUVLoop();
1089     CHECK_POINTER(uvLoop);
1090 
1091     auto work = new (std::nothrow) uv_work_t;
1092     if (work == nullptr) {
1093         HILOG_ERROR("new uv work failed.");
1094         return;
1095     }
1096 
1097     auto cb = new (std::nothrow) JsNativeReferenceDeleterObject();
1098     if (cb == nullptr) {
1099         HILOG_ERROR("new deleter object failed.");
1100         delete work;
1101         work = nullptr;
1102         return;
1103     }
1104 
1105     if (uniqueNativeRef != nullptr) {
1106         cb->uniqueNativeRef_ = std::move(uniqueNativeRef);
1107     }
1108     if (sharedNativeRef != nullptr) {
1109         cb->sharedNativeRef_ = std::move(sharedNativeRef);
1110     }
1111     work->data = reinterpret_cast<void*>(cb);
1112     int ret = uv_queue_work(uvLoop, work, [](uv_work_t *work) {},
1113     [](uv_work_t *work, int status) {
1114         if (work != nullptr) {
1115             if (work->data != nullptr) {
1116                 delete reinterpret_cast<JsNativeReferenceDeleterObject*>(work->data);
1117                 work->data = nullptr;
1118             }
1119             delete work;
1120             work = nullptr;
1121         }
1122     });
1123     if (ret != 0) {
1124         delete reinterpret_cast<JsNativeReferenceDeleterObject*>(work->data);
1125         work->data = nullptr;
1126         delete work;
1127         work = nullptr;
1128     }
1129 }
1130 
InitTimerModule()1131 void JsRuntime::InitTimerModule()
1132 {
1133     CHECK_POINTER(jsEnv_);
1134     jsEnv_->InitTimerModule();
1135 }
1136 
InitWorkerModule(const Options & options)1137 void JsRuntime::InitWorkerModule(const Options& options)
1138 {
1139     CHECK_POINTER(jsEnv_);
1140     std::shared_ptr<JsEnv::WorkerInfo> workerInfo = std::make_shared<JsEnv::WorkerInfo>();
1141     workerInfo->codePath = options.codePath;
1142     workerInfo->isDebugVersion = options.isDebugVersion;
1143     workerInfo->isBundle = options.isBundle;
1144     workerInfo->packagePathStr = options.packagePathStr;
1145     workerInfo->assetBasePathStr = options.assetBasePathStr;
1146     workerInfo->hapPath = options.hapPath;
1147     workerInfo->isStageModel = options.isStageModel;
1148     if (options.isJsFramework) {
1149         SetJsFramework();
1150     }
1151     jsEnv_->InitWorkerModule(workerInfo);
1152 }
1153 
ReInitJsEnvImpl(const Options & options)1154 void JsRuntime::ReInitJsEnvImpl(const Options& options)
1155 {
1156     CHECK_POINTER(jsEnv_);
1157     jsEnv_->ReInitJsEnvImpl(std::make_unique<OHOSJsEnvironmentImpl>(options.eventRunner));
1158 }
1159 
SetModuleLoadChecker(const std::shared_ptr<ModuleCheckerDelegate> & moduleCheckerDelegate) const1160 void JsRuntime::SetModuleLoadChecker(const std::shared_ptr<ModuleCheckerDelegate>& moduleCheckerDelegate) const
1161 {
1162     CHECK_POINTER(jsEnv_);
1163     jsEnv_->SetModuleLoadChecker(moduleCheckerDelegate);
1164 }
1165 }  // namespace AbilityRuntime
1166 }  // namespace OHOS
1167