• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2025 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 "simulator.h"
17 
18 #include <condition_variable>
19 #include <fstream>
20 #include <functional>
21 #include <mutex>
22 #include <thread>
23 #include <unordered_map>
24 
25 #include "ability_context.h"
26 #include "ability_stage_context.h"
27 #include "bundle_container.h"
28 #include "console.h"
29 #include "declarative_module_preloader.h"
30 #include "hilog_tag_wrapper.h"
31 #include "js_ability_context.h"
32 #include "js_ability_stage_context.h"
33 #include "js_console_log.h"
34 #include "js_data_converter.h"
35 #include "js_module_searcher.h"
36 #include "js_runtime.h"
37 #include "js_runtime_utils.h"
38 #include "js_timer.h"
39 #include "js_window_stage.h"
40 #include "json_serializer.h"
41 #include "JsMockUtil.h"
42 #include "launch_param.h"
43 #include "native_engine/impl/ark/ark_native_engine.h"
44 #include "res_config.h"
45 #include "resource_manager_helper.h"
46 #include "resource_manager.h"
47 #include "window_scene.h"
48 #include "sys_timer.h"
49 #include "source_map.h"
50 
51 
52 namespace OHOS {
53 namespace AbilityRuntime {
54 namespace {
55 constexpr int64_t DEFAULT_GC_POOL_SIZE = 0x10000000; // 256MB
56 constexpr int32_t DEFAULT_ARK_PROPERTIES = -1;
57 constexpr size_t DEFAULT_GC_THREAD_NUM = 7;
58 constexpr size_t DEFAULT_LONG_PAUSE_TIME = 40;
59 
60 constexpr char BUNDLE_INSTALL_PATH[] = "/data/storage/el1/bundle/";
61 constexpr char MERGE_ABC_PATH[] = "/ets/modules.abc";
62 constexpr char SOURCE_MAPS_PATH[] = "/ets/sourceMaps.map";
63 const std::string PACKAGE_NAME = "packageName";
64 const std::string BUNDLE_NAME = "bundleName";
65 const std::string MODULE_NAME = "moduleName";
66 const std::string VERSION = "version";
67 const std::string ENTRY_PATH = "entryPath";
68 const std::string IS_SO = "isSO";
69 const std::string DEPENDENCY_ALIAS = "dependencyAlias";
70 
71 #if defined(WINDOWS_PLATFORM)
72 constexpr char ARK_DEBUGGER_LIB_PATH[] = "libark_inspector.dll";
73 #elif defined(MAC_PLATFORM)
74 constexpr char ARK_DEBUGGER_LIB_PATH[] = "libark_inspector.dylib";
75 #else
76 #error "Unsupported platform"
77 #endif
78 
PrintVmLog(int32_t,int32_t,const char *,const char *,const char * message)79 int32_t PrintVmLog(int32_t, int32_t, const char*, const char*, const char *message)
80 {
81     TAG_LOGD(AAFwkTag::ABILITY_SIM, "ArkLog:%{public}s", message);
82     return 0;
83 }
84 
85 template<typename T, size_t N>
ArraySize(T (&)[N])86 inline constexpr size_t ArraySize(T (&)[N]) noexcept
87 {
88     return N;
89 }
90 
91 struct DebuggerTask {
92     void OnPostTask(std::function<void()> &&task);
93 
94     static void HandleTask(const uv_async_t *req);
95 
96     uv_async_t onPostTaskSignal {};
97     std::function<void()> func;
98 };
99 
100 class SimulatorImpl : public Simulator, public std::enable_shared_from_this<SimulatorImpl> {
101 public:
102     SimulatorImpl() = default;
103     ~SimulatorImpl();
104 
105     bool Initialize(const Options &options);
106 
107     int64_t StartAbility(
108         const std::string &abilitySrcPath, TerminateCallback callback, const std::string &abilityName = "") override;
109     void TerminateAbility(int64_t abilityId) override;
110     void UpdateConfiguration(const AppExecFwk::Configuration &config) override;
111     void SetMockList(const std::map<std::string, std::string> &mockList) override;
112     void SetHostResolveBufferTracker(ResolveBufferTrackerCallback cb) override;
113 private:
114     bool OnInit();
115     void Run();
116     napi_value LoadScript(const std::string &srcPath);
117     void InitResourceMgr();
118     void InitJsAbilityContext(napi_env env, napi_value instanceValue);
119     void DispatchStartLifecycle(napi_value instanceValue);
120     std::unique_ptr<NativeReference> CreateJsWindowStage(const std::shared_ptr<Rosen::WindowScene> &windowScene);
121     napi_value CreateJsWant(napi_env env);
122     bool LoadAbilityStage(uint8_t *buffer, size_t len);
123     void InitJsAbilityStageContext(napi_value instanceValue);
124     napi_value CreateJsLaunchParam(napi_env env);
125     bool ParseBundleAndModuleInfo();
126     bool ParseAbilityInfo(const std::string &abilitySrcPath, const std::string &abilityName = "");
127     bool LoadRuntimeEnv(napi_env env, napi_value globalObject);
128     static napi_value RequireNapi(napi_env env, napi_callback_info info);
129     inline void SetHostResolveBufferTracker();
130     void LoadJsMock(const std::string &fileName);
131     void ReportJsError(napi_value obj);
132     std::string GetNativeStrFromJsTaggedObj(napi_value obj, const char* key);
133     void CreateStageContext();
134     std::string ReadSourceMap();
135 
136     panda::ecmascript::EcmaVM *CreateJSVM();
137     Options options_;
138     std::string abilityPath_;
139     panda::ecmascript::EcmaVM *vm_ = nullptr;
140     DebuggerTask debuggerTask_;
141     napi_env nativeEngine_ = nullptr;
142     TerminateCallback terminateCallback_;
143     bool isOhmUrl_ = false;
144 
145     int64_t currentId_ = 0;
146     std::unordered_map<int64_t, std::shared_ptr<NativeReference>> abilities_;
147     std::unordered_map<int64_t, std::shared_ptr<Rosen::WindowScene>> windowScenes_;
148     std::unordered_map<int64_t, std::shared_ptr<NativeReference>> jsWindowStages_;
149     std::unordered_map<int64_t, std::shared_ptr<NativeReference>> jsContexts_;
150     std::shared_ptr<Global::Resource::ResourceManager> resourceMgr_;
151     std::shared_ptr<AbilityContext> context_;
152     std::shared_ptr<NativeReference> abilityStage_;
153     std::shared_ptr<AbilityStageContext> stageContext_;
154     std::shared_ptr<NativeReference> jsStageContext_;
155     std::shared_ptr<AppExecFwk::ApplicationInfo> appInfo_;
156     std::shared_ptr<AppExecFwk::HapModuleInfo> moduleInfo_;
157     std::shared_ptr<AppExecFwk::AbilityInfo> abilityInfo_;
158     std::shared_ptr<JsEnv::SourceMap> sourceMapPtr_;
159     CallbackTypePostTask postTask_ = nullptr;
160     void GetPkgContextInfoListMap(const std::map<std::string, std::string> &contextInfoMap,
161         std::map<std::string, std::vector<std::vector<std::string>>> &pkgContextInfoMap,
162         std::map<std::string, std::string> &pkgAliasMap);
163     void GetPkgContextInfoListInner(nlohmann::json &itemObject, std::vector<std::string> &items,
164         std::map<std::string, std::string> &pkgAliasMap, std::string &pkgName);
165 };
166 
HandleTask(const uv_async_t * req)167 void DebuggerTask::HandleTask(const uv_async_t *req)
168 {
169     auto *debuggerTask = reinterpret_cast<DebuggerTask*>(req->data);
170     if (debuggerTask == nullptr) {
171         TAG_LOGE(AAFwkTag::ABILITY_SIM, "null HandleTask debuggerTask");
172         return;
173     }
174     debuggerTask->func();
175 }
176 
OnPostTask(std::function<void ()> && task)177 void DebuggerTask::OnPostTask(std::function<void()> &&task)
178 {
179     if (uv_is_active((uv_handle_t*)&onPostTaskSignal)) {
180         func = std::move(task);
181         onPostTaskSignal.data = static_cast<void*>(this);
182         uv_async_send(&onPostTaskSignal);
183     }
184 }
185 
~SimulatorImpl()186 SimulatorImpl::~SimulatorImpl()
187 {
188     if (context_ != nullptr) {
189         context_->Unbind();
190     }
191     if (stageContext_ != nullptr) {
192         stageContext_->Unbind();
193     }
194     if (nativeEngine_) {
195         uv_close(reinterpret_cast<uv_handle_t*>(&debuggerTask_.onPostTaskSignal), nullptr);
196         uv_loop_t* uvLoop = nullptr;
197         napi_get_uv_event_loop(nativeEngine_, &uvLoop);
198         if (uvLoop != nullptr) {
199             uv_work_t work;
200             uv_queue_work(uvLoop, &work, [](uv_work_t*) {}, [](uv_work_t *work, int32_t status) {
201                 TAG_LOGE(AAFwkTag::ABILITY_SIM, "Simulator stop uv loop");
202                 uv_stop(work->loop);
203             });
204         }
205     }
206 
207     panda::JSNApi::StopDebugger(vm_);
208 
209     abilities_.clear();
210     nativeEngine_ = nullptr;
211     panda::JSNApi::DestroyJSVM(vm_);
212     vm_ = nullptr;
213 }
214 
Initialize(const Options & options)215 bool SimulatorImpl::Initialize(const Options &options)
216 {
217     if (nativeEngine_) {
218         TAG_LOGE(AAFwkTag::ABILITY_SIM, "initialized");
219         return true;
220     }
221 
222     options_ = options;
223     sourceMapPtr_ = std::make_shared<JsEnv::SourceMap>();
224     auto content = ReadSourceMap();
225     sourceMapPtr_->SplitSourceMap(content);
226 
227     postTask_ = options.postTask;
228     if (!OnInit()) {
229         return false;
230     }
231 
232     uv_loop_t* uvLoop = nullptr;
233     napi_get_uv_event_loop(nativeEngine_, &uvLoop);
234     if (uvLoop == nullptr) {
235         return false;
236     }
237 
238     uv_async_init(uvLoop, &debuggerTask_.onPostTaskSignal,
239         reinterpret_cast<uv_async_cb>(DebuggerTask::HandleTask));
240 
241     Run();
242     return true;
243 }
244 
CallObjectMethod(napi_env env,napi_value obj,const char * name,napi_value const * argv,size_t argc)245 void CallObjectMethod(napi_env env, napi_value obj, const char *name, napi_value const *argv, size_t argc)
246 {
247     if (obj == nullptr) {
248         TAG_LOGE(AAFwkTag::ABILITY_SIM, "get Ability object failed");
249         return;
250     }
251     napi_value methodOnCreate = nullptr;
252     napi_get_named_property(env, obj, name, &methodOnCreate);
253     if (methodOnCreate == nullptr) {
254         TAG_LOGE(AAFwkTag::ABILITY_SIM, "get '%{public}s' failed", name);
255         return;
256     }
257     napi_status status = napi_call_function(env, obj, methodOnCreate, argc, argv, nullptr);
258     if (status != napi_ok) {
259         TAG_LOGE(AAFwkTag::ABILITY_SIM, "napi call function failed");
260     }
261 }
262 
LoadScript(const std::string & srcPath)263 napi_value SimulatorImpl::LoadScript(const std::string &srcPath)
264 {
265     panda::Local<panda::ObjectRef> objRef;
266     if (isOhmUrl_) {
267         objRef = panda::JSNApi::GetExportObjectFromOhmUrl(vm_, srcPath, "default");
268     } else {
269         objRef = panda::JSNApi::GetExportObject(vm_, srcPath, "default");
270     }
271 
272     if (objRef->IsNull()) {
273         TAG_LOGE(AAFwkTag::ABILITY_SIM, "Get export object failed");
274         return nullptr;
275     }
276 
277     auto obj = ArkNativeEngine::ArkValueToNapiValue(nativeEngine_, objRef);
278     napi_value instanceValue = nullptr;
279     napi_new_instance(nativeEngine_, obj, 0, nullptr, &instanceValue);
280     return instanceValue;
281 }
282 
ParseBundleAndModuleInfo()283 bool SimulatorImpl::ParseBundleAndModuleInfo()
284 {
285     AppExecFwk::BundleContainer::GetInstance().LoadBundleInfos(options_.moduleJsonBuffer, options_.resourcePath);
286     appInfo_ = AppExecFwk::BundleContainer::GetInstance().GetApplicationInfo();
287     if (appInfo_ == nullptr) {
288         TAG_LOGE(AAFwkTag::ABILITY_SIM, "appinfo parse failed");
289         return false;
290     }
291     nlohmann::json appInfoJson;
292     to_json(appInfoJson, *appInfo_);
293     std::cout << "appinfo : " << appInfoJson.dump() << std::endl;
294 
295     AppExecFwk::BundleContainer::GetInstance().LoadDependencyHspInfo(appInfo_->bundleName, options_.dependencyHspInfos);
296     AppExecFwk::BundleContainer::GetInstance().SetBundleCodeDir(options_.previewPath);
297 
298     options_.bundleName = appInfo_->bundleName;
299     options_.compatibleVersion = appInfo_->apiCompatibleVersion;
300     options_.installationFree = (appInfo_->bundleType == AppExecFwk::BundleType::ATOMIC_SERVICE ? true : false);
301     options_.targetVersion = appInfo_->apiTargetVersion;
302     options_.releaseType = appInfo_->apiReleaseType;
303     options_.compileMode = "esmodule";
304 
305     if (appInfo_->moduleInfos.empty()) {
306         TAG_LOGE(AAFwkTag::ABILITY_SIM, "module name not exist");
307         return false;
308     }
309     options_.moduleName = appInfo_->moduleInfos[0].moduleName;
310     std::cout << "module name is " << options_.moduleName << std::endl;
311 
312     moduleInfo_ = AppExecFwk::BundleContainer::GetInstance().GetHapModuleInfo(options_.moduleName);
313     if (moduleInfo_ == nullptr) {
314         TAG_LOGE(AAFwkTag::ABILITY_SIM, "module info parse failed");
315         return false;
316     }
317     nlohmann::json moduleInfoJson;
318     to_json(moduleInfoJson, *moduleInfo_);
319     std::cout << "moduleInfo : " << moduleInfoJson.dump() << std::endl;
320 
321     options_.pageProfile = moduleInfo_->pages;
322     options_.enablePartialUpdate = true;
323     for (auto iter : moduleInfo_->metadata) {
324         if (iter.name == "ArkTSPartialUpdate" && iter.value == "false") {
325             options_.enablePartialUpdate = false;
326             break;
327         }
328     }
329     return true;
330 }
331 
ParseAbilityInfo(const std::string & abilitySrcPath,const std::string & abilityName)332 bool SimulatorImpl::ParseAbilityInfo(const std::string &abilitySrcPath, const std::string &abilityName)
333 {
334     if (!abilityName.empty()) {
335         abilityInfo_ = AppExecFwk::BundleContainer::GetInstance().GetAbilityInfo(options_.moduleName, abilityName);
336     } else {
337         auto path = abilitySrcPath;
338         path.erase(path.rfind("."));
339         auto abilityNameFromPath = path.substr(path.rfind('/') + 1, path.length());
340         abilityInfo_ = AppExecFwk::BundleContainer::GetInstance().GetAbilityInfo(
341             options_.moduleName, abilityNameFromPath);
342     }
343 
344     if (abilityInfo_ == nullptr) {
345         TAG_LOGE(AAFwkTag::ABILITY_SIM, "ability info parse failed");
346         return false;
347     }
348     nlohmann::json json;
349     to_json(json, *abilityInfo_);
350     std::cout << "abilityInfo : " << json.dump() << std::endl;
351 
352     options_.labelId = abilityInfo_->labelId;
353     return true;
354 }
355 
StartAbility(const std::string & abilitySrcPath,TerminateCallback callback,const std::string & abilityName)356 int64_t SimulatorImpl::StartAbility(
357     const std::string &abilitySrcPath, TerminateCallback callback, const std::string &abilityName)
358 {
359     if (!ParseAbilityInfo(abilitySrcPath, abilityName)) {
360         return -1;
361     }
362 
363     CreateStageContext();
364     std::ifstream stream(options_.modulePath, std::ios::ate | std::ios::binary);
365     if (!stream.is_open()) {
366         TAG_LOGE(AAFwkTag::ABILITY_SIM, "open:%{public}s failed", options_.modulePath.c_str());
367         return -1;
368     }
369 
370     size_t len = stream.tellg();
371     std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(len);
372     stream.seekg(0);
373     stream.read(reinterpret_cast<char*>(buffer.get()), len);
374     stream.close();
375 
376     auto buf = buffer.release();
377     if (!LoadAbilityStage(buf, len)) {
378         TAG_LOGE(AAFwkTag::ABILITY_SIM, "Load ability stage failed");
379         return -1;
380     }
381 
382     isOhmUrl_ = panda::JSNApi::IsOhmUrl(abilitySrcPath);
383     napi_value instanceValue = nullptr;
384     if (isOhmUrl_) {
385         std::string srcFilename = "";
386         srcFilename = BUNDLE_INSTALL_PATH + options_.moduleName + MERGE_ABC_PATH;
387         if (!panda::JSNApi::ExecuteSecureWithOhmUrl(vm_, buf, len, srcFilename, abilitySrcPath)) {
388             return -1;
389         }
390         instanceValue = LoadScript(abilitySrcPath);
391     } else {
392         abilityPath_ = BUNDLE_INSTALL_PATH + options_.moduleName + "/" + abilitySrcPath;
393         if (!reinterpret_cast<NativeEngine*>(nativeEngine_)->RunScriptBuffer(abilityPath_, buf, len, false)) {
394             TAG_LOGE(AAFwkTag::ABILITY_SIM, "run script:%{public}s failed", abilityPath_.c_str());
395             return -1;
396         }
397         instanceValue = LoadScript(abilityPath_);
398     }
399 
400     if (instanceValue == nullptr) {
401         TAG_LOGE(AAFwkTag::ABILITY_SIM, "create object instance failed");
402         return -1;
403     }
404 
405     ++currentId_;
406     terminateCallback_ = callback;
407     InitResourceMgr();
408     InitJsAbilityContext(nativeEngine_, instanceValue);
409     DispatchStartLifecycle(instanceValue);
410     napi_ref ref = nullptr;
411     napi_create_reference(nativeEngine_, instanceValue, 1, &ref);
412     abilities_.emplace(currentId_, std::shared_ptr<NativeReference>(reinterpret_cast<NativeReference*>(ref)));
413     return currentId_;
414 }
415 
LoadAbilityStage(uint8_t * buffer,size_t len)416 bool SimulatorImpl::LoadAbilityStage(uint8_t *buffer, size_t len)
417 {
418     if (moduleInfo_ == nullptr) {
419         TAG_LOGE(AAFwkTag::ABILITY_SIM, "null moduleInfo");
420         return false;
421     }
422 
423     if (moduleInfo_->srcEntrance.empty()) {
424         TAG_LOGD(AAFwkTag::ABILITY_SIM, "module src path empty");
425         return true;
426     }
427 
428     if (nativeEngine_ == nullptr) {
429         TAG_LOGE(AAFwkTag::ABILITY_SIM, "null nativeEngine_");
430         return false;
431     }
432     std::string srcEntrance = moduleInfo_->srcEntrance;
433     srcEntrance.erase(srcEntrance.rfind("."));
434     srcEntrance.append(".abc");
435     srcEntrance = srcEntrance.substr(srcEntrance.find('/') + 1, srcEntrance.length());
436 
437     auto moduleSrcPath = BUNDLE_INSTALL_PATH + options_.moduleName + "/" + srcEntrance;
438     TAG_LOGD(AAFwkTag::ABILITY_SIM, "moduleSrcPath is %{public}s", moduleSrcPath.c_str());
439     if (!reinterpret_cast<NativeEngine*>(nativeEngine_)->RunScriptBuffer(moduleSrcPath, buffer, len, false)) {
440         TAG_LOGE(AAFwkTag::ABILITY_SIM, "run ability stage script:%{public}s failed", moduleSrcPath.c_str());
441         return false;
442     }
443 
444     napi_value instanceValue = LoadScript(moduleSrcPath);
445     if (instanceValue == nullptr) {
446         TAG_LOGE(AAFwkTag::ABILITY_SIM, "create ability stage instance failed");
447         return false;
448     }
449 
450     InitJsAbilityStageContext(instanceValue);
451     CallObjectMethod(nativeEngine_, instanceValue, "onCreate", nullptr, 0);
452 
453     napi_value wantArgv[] = {
454         CreateJsWant(nativeEngine_)
455     };
456     CallObjectMethod(nativeEngine_, instanceValue, "onAcceptWant", wantArgv, ArraySize(wantArgv));
457     napi_ref ref = nullptr;
458     napi_create_reference(nativeEngine_, instanceValue, 1, &ref);
459     abilityStage_ = std::shared_ptr<NativeReference>(reinterpret_cast<NativeReference*>(ref));
460     return true;
461 }
462 
InitJsAbilityStageContext(napi_value obj)463 void SimulatorImpl::InitJsAbilityStageContext(napi_value obj)
464 {
465     napi_value contextObj = CreateJsAbilityStageContext(nativeEngine_, stageContext_);
466     if (contextObj == nullptr) {
467         TAG_LOGE(AAFwkTag::ABILITY_SIM, "null contextObj");
468         return;
469     }
470 
471     jsStageContext_ = std::shared_ptr<NativeReference>(
472         JsRuntime::LoadSystemModuleByEngine(nativeEngine_, "application.AbilityStageContext", &contextObj, 1));
473     if (jsStageContext_ == nullptr) {
474         TAG_LOGE(AAFwkTag::ABILITY_SIM, "null get LoadSystemModuleByEngine failed");
475         return;
476     }
477 
478     contextObj = jsStageContext_->GetNapiValue();
479     if (contextObj == nullptr) {
480         TAG_LOGE(AAFwkTag::ABILITY_SIM, "null contextObj");
481         return;
482     }
483 
484     if (obj == nullptr) {
485         TAG_LOGE(AAFwkTag::ABILITY_SIM, "null obj");
486         return;
487     }
488 
489     auto workContext = new (std::nothrow) std::weak_ptr<AbilityStageContext>(stageContext_);
490     auto status = napi_wrap(nativeEngine_, contextObj, workContext,
491         [](napi_env, void *data, void*) {
492             TAG_LOGD(AAFwkTag::ABILITY_SIM, "finalizer for weak_ptr ui ability context");
493             delete static_cast<std::weak_ptr<AbilityStageContext> *>(data);
494         },
495         nullptr, nullptr);
496     if (status != napi_ok) {
497         TAG_LOGW(AAFwkTag::ABILITY_SIM, "wrap ability context failed: %{public}d", status);
498         delete workContext;
499         return;
500     }
501 
502     JsRuntime jsRuntime;
503     stageContext_->Bind(jsRuntime, jsStageContext_.get());
504     napi_set_named_property(nativeEngine_, obj, "context", contextObj);
505 }
506 
TerminateAbility(int64_t abilityId)507 void SimulatorImpl::TerminateAbility(int64_t abilityId)
508 {
509     if (abilityId == 0 && abilities_.begin() != abilities_.end()) {
510         TerminateAbility(abilities_.begin()->first);
511         return;
512     }
513 
514     auto it = abilities_.find(abilityId);
515     if (it == abilities_.end()) {
516         return;
517     }
518 
519     std::shared_ptr<NativeReference> ref = it->second;
520     abilities_.erase(it);
521 
522     auto instanceValue = ref->GetNapiValue();
523     if (instanceValue == nullptr) {
524         return;
525     }
526 
527     CallObjectMethod(nativeEngine_, instanceValue, "onBackground", nullptr, 0);
528     CallObjectMethod(nativeEngine_, instanceValue, "onWindowStageDestroy", nullptr, 0);
529     CallObjectMethod(nativeEngine_, instanceValue, "onDestroy", nullptr, 0);
530 
531     auto windowSceneIter = windowScenes_.find(abilityId);
532     if (windowSceneIter != windowScenes_.end()) {
533         windowScenes_.erase(windowSceneIter);
534     }
535 
536     auto windowStageIter = jsWindowStages_.find(abilityId);
537     if (windowStageIter != jsWindowStages_.end()) {
538         jsWindowStages_.erase(windowStageIter);
539     }
540 
541     auto jsContextIter = jsContexts_.find(abilityId);
542     if (jsContextIter != jsContexts_.end()) {
543         jsContexts_.erase(jsContextIter);
544     }
545 }
546 
UpdateConfiguration(const AppExecFwk::Configuration & config)547 void SimulatorImpl::UpdateConfiguration(const AppExecFwk::Configuration &config)
548 {
549     TAG_LOGD(AAFwkTag::ABILITY_SIM, "called");
550     if (abilityStage_ == nullptr) {
551         TAG_LOGE(AAFwkTag::ABILITY_SIM, "null abilityStage_");
552         return;
553     }
554 
555     auto configuration = std::make_shared<AppExecFwk::Configuration>(config);
556     if (configuration == nullptr) {
557         return;
558     }
559 
560     if (stageContext_) {
561         stageContext_->SetConfiguration(configuration);
562     }
563 
564     napi_value configArgv[] = {
565         CreateJsConfiguration(nativeEngine_, config)
566     };
567 
568     auto abilityStage = abilityStage_->GetNapiValue();
569     if (abilityStage == nullptr) {
570         TAG_LOGE(AAFwkTag::ABILITY_SIM, "null abilityStage");
571         return;
572     }
573     CallObjectMethod(nativeEngine_, abilityStage, "onConfigurationUpdated", configArgv, ArraySize(configArgv));
574     CallObjectMethod(nativeEngine_, abilityStage, "onConfigurationUpdate", configArgv, ArraySize(configArgv));
575     JsAbilityStageContext::ConfigurationUpdated(nativeEngine_, jsStageContext_, configuration);
576 
577     for (auto iter = abilities_.begin(); iter != abilities_.end(); iter++) {
578         auto ability = iter->second->GetNapiValue();
579         if (ability == nullptr) {
580             TAG_LOGE(AAFwkTag::ABILITY_SIM, "null ability");
581             continue;
582         }
583 
584         CallObjectMethod(nativeEngine_, ability, "onConfigurationUpdated", configArgv, ArraySize(configArgv));
585         CallObjectMethod(nativeEngine_, ability, "onConfigurationUpdate", configArgv, ArraySize(configArgv));
586         JsAbilityContext::ConfigurationUpdated(nativeEngine_, iter->second, configuration);
587     }
588 }
589 
SetMockList(const std::map<std::string,std::string> & mockList)590 void SimulatorImpl::SetMockList(const std::map<std::string, std::string> &mockList)
591 {
592     TAG_LOGD(AAFwkTag::ABILITY_SIM, "called. mockList size: %{public}zu", mockList.size());
593     panda::JSNApi::SetMockModuleList(vm_, mockList);
594 }
595 
InitResourceMgr()596 void SimulatorImpl::InitResourceMgr()
597 {
598     TAG_LOGD(AAFwkTag::ABILITY_SIM, "called");
599     resourceMgr_ = std::shared_ptr<Global::Resource::ResourceManager>(Global::Resource::CreateResourceManager());
600     if (resourceMgr_ == nullptr) {
601         TAG_LOGE(AAFwkTag::ABILITY_SIM, "resourceMgr");
602         return;
603     }
604 
605     if (!resourceMgr_->AddResource(options_.resourcePath.c_str())) {
606         TAG_LOGE(AAFwkTag::ABILITY_SIM, "Add app resource failed");
607     }
608     ResourceManagerHelper::GetInstance().Init(options_);
609     ResourceManagerHelper::GetInstance().AddSystemResource(resourceMgr_);
610     std::unique_ptr<Global::Resource::ResConfig> resConfig(Global::Resource::CreateResConfig());
611     if (resConfig == nullptr) {
612         TAG_LOGE(AAFwkTag::ABILITY_SIM, "null resConfig");
613         return;
614     }
615     ResourceManagerHelper::GetInstance().GetResConfig(*resConfig);
616     resourceMgr_->UpdateResConfig(*resConfig);
617 }
618 
InitJsAbilityContext(napi_env env,napi_value obj)619 void SimulatorImpl::InitJsAbilityContext(napi_env env, napi_value obj)
620 {
621     if (context_ == nullptr) {
622         context_ = std::make_shared<AbilityContext>();
623         context_->SetSimulator(static_cast<Simulator*>(this));
624         context_->SetOptions(options_);
625         context_->SetAbilityStageContext(stageContext_);
626         context_->SetResourceManager(resourceMgr_);
627         context_->SetAbilityInfo(abilityInfo_);
628     }
629     napi_value contextObj = CreateJsAbilityContext(nativeEngine_, context_);
630     auto systemModule = std::shared_ptr<NativeReference>(
631         JsRuntime::LoadSystemModuleByEngine(nativeEngine_, "application.AbilityContext", &contextObj, 1));
632     if (systemModule == nullptr) {
633         TAG_LOGE(AAFwkTag::ABILITY_SIM, "null systemModule");
634         return;
635     }
636     contextObj = systemModule->GetNapiValue();
637     if (contextObj == nullptr) {
638         TAG_LOGE(AAFwkTag::ABILITY_SIM, "null contextObj");
639         return;
640     }
641 
642     if (obj == nullptr) {
643         TAG_LOGE(AAFwkTag::ABILITY_SIM, "null obj");
644         return;
645     }
646 
647     auto workContext = new (std::nothrow) std::weak_ptr<AbilityContext>(context_);
648     auto status = napi_wrap(nativeEngine_, contextObj, workContext,
649         [](napi_env, void *data, void*) {
650             TAG_LOGD(AAFwkTag::ABILITY_SIM, "finalizer for weak_ptr ui ability context");
651             delete static_cast<std::weak_ptr<AbilityContext> *>(data);
652         },
653         nullptr, nullptr);
654     if (status != napi_ok) {
655         TAG_LOGW(AAFwkTag::ABILITY_SIM, "wrap ability context failed: %{public}d", status);
656         delete workContext;
657         return;
658     }
659 
660     JsRuntime jsRuntime;
661     context_->Bind(jsRuntime, systemModule.get());
662     napi_set_named_property(env, obj, "context", contextObj);
663     jsContexts_.emplace(currentId_, systemModule);
664 }
665 
CreateJsWant(napi_env env)666 napi_value SimulatorImpl::CreateJsWant(napi_env env)
667 {
668     napi_value objValue = nullptr;
669     napi_create_object(env, &objValue);
670     napi_set_named_property(env, objValue, "deviceId", CreateJsValue(env, std::string("")));
671     napi_set_named_property(env, objValue, "bundleName", CreateJsValue(env, options_.bundleName));
672     if (abilityInfo_) {
673         napi_set_named_property(env, objValue, "abilityName", CreateJsValue(env, abilityInfo_->name));
674     }
675     napi_set_named_property(env, objValue, "moduleName", CreateJsValue(env, options_.moduleName));
676 
677     napi_set_named_property(env, objValue, "uri", CreateJsValue(env, std::string("")));
678     napi_set_named_property(env, objValue, "type", CreateJsValue(env, std::string("")));
679     napi_set_named_property(env, objValue, "flags", CreateJsValue(env, 0));
680     napi_set_named_property(env, objValue, "type", CreateJsValue(env, std::string("")));
681     napi_value object = nullptr;
682     napi_create_object(env, &object);
683     napi_set_named_property(env, objValue, "parameters", object);
684     napi_value array = nullptr;
685     napi_create_array_with_length(env, 0, &array);
686     napi_set_named_property(env, objValue, "entities", array);
687     return objValue;
688 }
689 
CreateJsLaunchParam(napi_env env)690 napi_value SimulatorImpl::CreateJsLaunchParam(napi_env env)
691 {
692     napi_value objValue = nullptr;
693     napi_create_object(env, &objValue);
694     napi_set_named_property(env, objValue, "launchReason", CreateJsValue(env, AAFwk::LAUNCHREASON_UNKNOWN));
695     napi_set_named_property(env, objValue, "lastExitReason", CreateJsValue(env, AAFwk::LASTEXITREASON_UNKNOWN));
696     napi_set_named_property(env, objValue, "lastExitMessage", CreateJsValue(env, std::string("")));
697     return objValue;
698 }
699 
DispatchStartLifecycle(napi_value instanceValue)700 void SimulatorImpl::DispatchStartLifecycle(napi_value instanceValue)
701 {
702     napi_value wantArgv[] = {
703         CreateJsWant(nativeEngine_),
704         CreateJsLaunchParam(nativeEngine_)
705     };
706     CallObjectMethod(nativeEngine_, instanceValue, "onCreate", wantArgv, ArraySize(wantArgv));
707     auto windowScene = std::make_shared<Rosen::WindowScene>();
708     if (windowScene == nullptr) {
709         return;
710     }
711     sptr<Rosen::IWindowLifeCycle> listener = nullptr;
712     windowScene->Init(-1, context_, listener);
713     auto jsWindowStage = CreateJsWindowStage(windowScene);
714     if (jsWindowStage == nullptr) {
715         return;
716     }
717     napi_value argv[] = { jsWindowStage->GetNapiValue() };
718     CallObjectMethod(nativeEngine_, instanceValue, "onWindowStageCreate", argv, ArraySize(argv));
719 
720     CallObjectMethod(nativeEngine_, instanceValue, "onForeground", nullptr, 0);
721 
722     windowScenes_.emplace(currentId_, windowScene);
723     jsWindowStages_.emplace(currentId_, std::shared_ptr<NativeReference>(jsWindowStage.release()));
724 }
725 
CreateJsWindowStage(const std::shared_ptr<Rosen::WindowScene> & windowScene)726 std::unique_ptr<NativeReference> SimulatorImpl::CreateJsWindowStage(
727     const std::shared_ptr<Rosen::WindowScene> &windowScene)
728 {
729     napi_value jsWindowStage = Rosen::CreateJsWindowStage(nativeEngine_, windowScene);
730     if (jsWindowStage == nullptr) {
731         TAG_LOGE(AAFwkTag::ABILITY_SIM, "null jsWindowSatge");
732         return nullptr;
733     }
734     return JsRuntime::LoadSystemModuleByEngine(nativeEngine_, "application.WindowStage", &jsWindowStage, 1);
735 }
736 
CreateJSVM()737 panda::ecmascript::EcmaVM *SimulatorImpl::CreateJSVM()
738 {
739     panda::RuntimeOption pandaOption;
740     pandaOption.SetArkProperties(DEFAULT_ARK_PROPERTIES);
741     pandaOption.SetGcThreadNum(DEFAULT_GC_THREAD_NUM);
742     pandaOption.SetLongPauseTime(DEFAULT_LONG_PAUSE_TIME);
743     pandaOption.SetGcType(panda::RuntimeOption::GC_TYPE::GEN_GC);
744     pandaOption.SetGcPoolSize(DEFAULT_GC_POOL_SIZE);
745     pandaOption.SetLogLevel(panda::RuntimeOption::LOG_LEVEL::FOLLOW);
746     pandaOption.SetLogBufPrint(PrintVmLog);
747     pandaOption.SetEnableAsmInterpreter(true);
748     pandaOption.SetAsmOpcodeDisableRange("");
749     return panda::JSNApi::CreateJSVM(pandaOption);
750 }
751 
ReadSourceMap()752 std::string SimulatorImpl::ReadSourceMap()
753 {
754     std::string normalizedPath = options_.modulePath;
755     TAG_LOGD(AAFwkTag::ABILITY_SIM, "modulePath:%{public}s", normalizedPath.c_str());
756     std::replace(normalizedPath.begin(), normalizedPath.end(), '\\', '/');
757     auto sourceMapPath = std::regex_replace(normalizedPath, std::regex(MERGE_ABC_PATH), SOURCE_MAPS_PATH);
758     TAG_LOGD(AAFwkTag::ABILITY_SIM, "is mac sourceMapPath:%{public}s", sourceMapPath.c_str());
759 
760 #if defined(WINDOWS_PLATFORM)
761     std::replace(sourceMapPath.begin(), sourceMapPath.end(), '/', '\\');
762     TAG_LOGD(AAFwkTag::ABILITY_SIM, "is windows sourceMapPath:%{public}s", sourceMapPath.c_str());
763 #endif
764     std::ifstream stream(sourceMapPath, std::ios::ate | std::ios::binary);
765     if (!stream.is_open()) {
766         TAG_LOGE(AAFwkTag::ABILITY_SIM, "open:%{public}s failed", sourceMapPath.c_str());
767         return "";
768     }
769 
770     size_t len = stream.tellg();
771     std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(len);
772     stream.seekg(0);
773     stream.read(reinterpret_cast<char*>(buffer.get()), len);
774     stream.close();
775     std::string content;
776     content.assign(reinterpret_cast<char*>(buffer.get()), len);
777     return content;
778 }
779 
OnInit()780 bool SimulatorImpl::OnInit()
781 {
782     if (!ParseBundleAndModuleInfo()) {
783         TAG_LOGE(AAFwkTag::ABILITY_SIM, "failed");
784         return false;
785     }
786 
787     vm_ = CreateJSVM();
788     if (vm_ == nullptr) {
789         return false;
790     }
791 
792     panda::JSNApi::DebugOption debugOption = {ARK_DEBUGGER_LIB_PATH, (options_.debugPort != 0), options_.debugPort};
793     panda::JSNApi::StartDebugger(vm_, debugOption, 0, [this](std::function<void()> &&arg) {
794         debuggerTask_.OnPostTask(std::move(arg));
795     });
796 
797     auto nativeEngine = new (std::nothrow) ArkNativeEngine(vm_, nullptr);
798     if (nativeEngine == nullptr) {
799         TAG_LOGE(AAFwkTag::ABILITY_SIM, "null nativeEngine");
800         return false;
801     }
802     napi_env env = reinterpret_cast<napi_env>(nativeEngine);
803     auto uncaughtTask = [weak = weak_from_this()](napi_value value) {
804         TAG_LOGE(AAFwkTag::ABILITY_SIM, "uncaught exception");
805         auto self = weak.lock();
806         if (self == nullptr) {
807             TAG_LOGE(AAFwkTag::ABILITY_SIM, "null SimulatorImpl");
808             return;
809         }
810         self->ReportJsError(value);
811         if (self->terminateCallback_ == nullptr) {
812             TAG_LOGE(AAFwkTag::ABILITY_SIM, "null terminateCallback");
813             return;
814         }
815         self->terminateCallback_(self->currentId_);
816     };
817     nativeEngine->RegisterNapiUncaughtExceptionHandler(uncaughtTask);
818     Ace::DeclarativeModulePreloader::Preload(*nativeEngine);
819 
820     napi_value globalObj;
821     napi_get_global(env, &globalObj);
822     if (globalObj == nullptr) {
823         delete nativeEngine;
824         TAG_LOGE(AAFwkTag::ABILITY_SIM, "null global object");
825         return false;
826     }
827 
828 #if defined(PREVIEW)
829     ArkNativeEngine::SetCurrentPreviewenv(options_.enableFileOperation);
830 #endif
831 
832     if (!LoadRuntimeEnv(env, globalObj)) {
833         delete nativeEngine;
834         TAG_LOGE(AAFwkTag::ABILITY_SIM, "Load runtime env failed");
835         return false;
836     }
837 
838     panda::JSNApi::SetBundle(vm_, false);
839     panda::JSNApi::SetBundleName(vm_, options_.bundleName);
840     panda::JSNApi::SetModuleName(vm_, options_.moduleName);
841     panda::JSNApi::SetAssetPath(vm_, options_.modulePath);
842     std::map<std::string, std::vector<std::vector<std::string>>> pkgContextInfoMap;
843     std::map<std::string, std::string> pkgAliasMap;
844     GetPkgContextInfoListMap(options_.pkgContextInfoJsonStringMap, pkgContextInfoMap, pkgAliasMap);
845     panda::JSNApi::SetpkgContextInfoList(vm_, pkgContextInfoMap);
846     panda::JSNApi::SetPkgAliasList(vm_, pkgAliasMap);
847     panda::JSNApi::SetPkgNameList(vm_, options_.packageNameList);
848 
849     nativeEngine_ = env;
850     return true;
851 }
852 
RequireNapi(napi_env env,napi_callback_info info)853 napi_value SimulatorImpl::RequireNapi(napi_env env, napi_callback_info info)
854 {
855     napi_value globalObj;
856     napi_get_global(env, &globalObj);
857     napi_value requireNapi = nullptr;
858     napi_get_named_property(env, globalObj, "requireNapiPreview", &requireNapi);
859     size_t argc = ARGC_MAX_COUNT;
860     napi_value argv[ARGC_MAX_COUNT] = {nullptr};
861     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
862     napi_value result = nullptr;
863     napi_call_function(env, CreateJsUndefined(env), requireNapi, argc, argv, &result);
864     if (!CheckTypeForNapiValue(env, result, napi_undefined)) {
865         return result;
866     }
867     napi_value mockRequireNapi = nullptr;
868     napi_get_named_property(env, globalObj, "mockRequireNapi", &mockRequireNapi);
869     napi_call_function(env, CreateJsUndefined(env), mockRequireNapi, argc, argv, &result);
870     return result;
871 }
872 
LoadJsMock(const std::string & fileName)873 void SimulatorImpl::LoadJsMock(const std::string &fileName)
874 {
875     std::ifstream stream(fileName, std::ios::ate | std::ios::binary);
876     if (!stream.is_open()) {
877         TAG_LOGE(AAFwkTag::ABILITY_SIM, "open: %{public}s failed", fileName.c_str());
878         return;
879     }
880     size_t len = stream.tellg();
881     std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(len);
882     stream.seekg(0);
883     stream.read(reinterpret_cast<char*>(buffer.get()), len);
884     stream.close();
885     panda::JSNApi::Execute(vm_, buffer.get(), len, "_GLOBAL::func_main_0");
886 }
887 
LoadRuntimeEnv(napi_env env,napi_value globalObj)888 bool SimulatorImpl::LoadRuntimeEnv(napi_env env, napi_value globalObj)
889 {
890     JsSysModule::Console::InitConsoleModule(env);
891     auto ret = JsSysModule::Timer::RegisterTime(env);
892     if (!ret) {
893         TAG_LOGE(AAFwkTag::ABILITY_SIM, "Register timer failed");
894     }
895     napi_value object = nullptr;
896     napi_create_object(env, &object);
897     napi_set_named_property(env, globalObj, "group", object);
898 
899     const OHOS::Ide::JsMockUtil::AbcInfo info = OHOS::Ide::JsMockUtil::GetAbcBufferInfo();
900     const uint8_t *buffer = info.buffer;
901     std::size_t size = info.bufferSize;
902     panda::JSNApi::Execute(vm_, buffer, size, "_GLOBAL::func_main_0");
903 
904     napi_value mockRequireNapi = nullptr;
905     napi_get_named_property(env, globalObj, "requireNapi", &mockRequireNapi);
906     napi_set_named_property(env, globalObj, "mockRequireNapi", mockRequireNapi);
907     auto* moduleManager = reinterpret_cast<NativeEngine*>(env)->GetModuleManager();
908     if (moduleManager != nullptr) {
909         TAG_LOGE(
910             AAFwkTag::ABILITY_SIM, "moduleManager SetPreviewSearchPath: %{public}s", options_.containerSdkPath.c_str());
911         moduleManager->SetPreviewSearchPath(options_.containerSdkPath);
912     }
913 
914     std::string fileSeparator = "/";
915     auto pos = options_.containerSdkPath.find(fileSeparator);
916     if (pos == std::string::npos) {
917         fileSeparator = "\\";
918     }
919 
920     std::string fileName = options_.containerSdkPath + fileSeparator + "apiMock" + fileSeparator + "jsMockHmos.abc";
921     TAG_LOGD(AAFwkTag::ABILITY_SIM, "file name:%{public}s", fileName.c_str());
922     if (!fileName.empty() && AbilityStageContext::Access(fileName)) {
923         LoadJsMock(fileName);
924     }
925 
926     const char *moduleName = "SimulatorImpl";
927     BindNativeFunction(env, globalObj, "requireNapi", moduleName, SimulatorImpl::RequireNapi);
928     return true;
929 }
930 
Run()931 void SimulatorImpl::Run()
932 {
933     uv_loop_t* uvLoop = nullptr;
934     napi_get_uv_event_loop(nativeEngine_, &uvLoop);
935     if (uvLoop != nullptr) {
936         uv_run(uvLoop, UV_RUN_NOWAIT);
937     }
938 
939     if (postTask_ != nullptr) {
940         postTask_([this]() { Run(); }, 0);
941     }
942 }
943 }
944 
Create(const Options & options)945 std::shared_ptr<Simulator> Simulator::Create(const Options &options)
946 {
947     auto simulator = std::make_shared<SimulatorImpl>();
948     if (simulator->Initialize(options)) {
949         return simulator;
950     }
951     return nullptr;
952 }
953 
SetHostResolveBufferTracker(ResolveBufferTrackerCallback cb)954 void SimulatorImpl::SetHostResolveBufferTracker(ResolveBufferTrackerCallback cb)
955 {
956     if (vm_ == nullptr || cb == nullptr) {
957         TAG_LOGE(AAFwkTag::ABILITY_SIM, "Params invalid");
958         return;
959     }
960     panda::JSNApi::SetHostResolveBufferTracker(vm_, cb);
961 }
962 
GetPkgContextInfoListMap(const std::map<std::string,std::string> & contextInfoMap,std::map<std::string,std::vector<std::vector<std::string>>> & pkgContextInfoMap,std::map<std::string,std::string> & pkgAliasMap)963 void SimulatorImpl::GetPkgContextInfoListMap(const std::map<std::string, std::string> &contextInfoMap,
964     std::map<std::string, std::vector<std::vector<std::string>>> &pkgContextInfoMap,
965     std::map<std::string, std::string> &pkgAliasMap)
966 {
967     for (auto it = contextInfoMap.begin(); it != contextInfoMap.end(); it++) {
968         std::vector<std::vector<std::string>> pkgContextInfoList;
969         auto jsonObject = nlohmann::json::parse(it->second);
970         if (jsonObject.is_discarded()) {
971             TAG_LOGE(AAFwkTag::JSRUNTIME, "moduleName: %{public}s parse json error", it->first.c_str());
972             continue;
973         }
974         for (nlohmann::json::iterator jsonIt = jsonObject.begin(); jsonIt != jsonObject.end(); jsonIt++) {
975             std::vector<std::string> items;
976             items.emplace_back(jsonIt.key());
977             nlohmann::json itemObject = jsonIt.value();
978             std::string pkgName = "";
979             items.emplace_back(PACKAGE_NAME);
980             if (itemObject[PACKAGE_NAME].is_null() || !itemObject[PACKAGE_NAME].is_string()) {
981                 items.emplace_back(pkgName);
982             } else {
983                 pkgName = itemObject[PACKAGE_NAME].get<std::string>();
984                 items.emplace_back(pkgName);
985             }
986 
987             items.emplace_back(BUNDLE_NAME);
988             if (itemObject[BUNDLE_NAME].is_null() || !itemObject[BUNDLE_NAME].is_string()) {
989                 items.emplace_back("");
990             } else {
991                 items.emplace_back(itemObject[BUNDLE_NAME].get<std::string>());
992             }
993 
994             items.emplace_back(MODULE_NAME);
995             if (itemObject[MODULE_NAME].is_null() || !itemObject[MODULE_NAME].is_string()) {
996                 items.emplace_back("");
997             } else {
998                 items.emplace_back(itemObject[MODULE_NAME].get<std::string>());
999             }
1000 
1001             GetPkgContextInfoListInner(itemObject, items, pkgAliasMap, pkgName);
1002             pkgContextInfoList.emplace_back(items);
1003         }
1004         TAG_LOGI(AAFwkTag::JSRUNTIME, "moduleName: %{public}s parse json success", it->first.c_str());
1005         pkgContextInfoMap[it->first] = pkgContextInfoList;
1006     }
1007 }
1008 
GetPkgContextInfoListInner(nlohmann::json & itemObject,std::vector<std::string> & items,std::map<std::string,std::string> & pkgAliasMap,std::string & pkgName)1009 void SimulatorImpl::GetPkgContextInfoListInner(nlohmann::json &itemObject, std::vector<std::string> &items,
1010     std::map<std::string, std::string> &pkgAliasMap, std::string &pkgName)
1011 {
1012     items.emplace_back(VERSION);
1013     if (itemObject[VERSION].is_null() || !itemObject[VERSION].is_string()) {
1014         items.emplace_back("");
1015     } else {
1016         items.emplace_back(itemObject[VERSION].get<std::string>());
1017     }
1018 
1019     items.emplace_back(ENTRY_PATH);
1020     if (itemObject[ENTRY_PATH].is_null() || !itemObject[ENTRY_PATH].is_string()) {
1021         items.emplace_back("");
1022     } else {
1023         items.emplace_back(itemObject[ENTRY_PATH].get<std::string>());
1024     }
1025 
1026     items.emplace_back(IS_SO);
1027     if (itemObject[IS_SO].is_null() || !itemObject[IS_SO].is_boolean()) {
1028         items.emplace_back("false");
1029     } else {
1030         bool isSo = itemObject[IS_SO].get<bool>();
1031         if (isSo) {
1032             items.emplace_back("true");
1033         } else {
1034             items.emplace_back("false");
1035         }
1036     }
1037     if (!itemObject[DEPENDENCY_ALIAS].is_null() && itemObject[DEPENDENCY_ALIAS].is_string()) {
1038         std::string pkgAlias = itemObject[DEPENDENCY_ALIAS].get<std::string>();
1039         if (!pkgAlias.empty()) {
1040             pkgAliasMap[pkgAlias] = pkgName;
1041         }
1042     }
1043 }
1044 
GetNativeStrFromJsTaggedObj(napi_value obj,const char * key)1045 std::string SimulatorImpl::GetNativeStrFromJsTaggedObj(napi_value obj, const char* key)
1046 {
1047     if (obj == nullptr) {
1048         TAG_LOGE(AAFwkTag::ABILITY_SIM, "get value failed");
1049         return "";
1050     }
1051 
1052     napi_value valueStr = nullptr;
1053     napi_get_named_property(nativeEngine_, obj, key, &valueStr);
1054     napi_valuetype valueType = napi_undefined;
1055     napi_typeof(nativeEngine_, valueStr, &valueType);
1056     if (valueType != napi_string) {
1057         TAG_LOGE(AAFwkTag::ABILITY_SIM, "convert value failed");
1058         return "";
1059     }
1060 
1061     size_t valueStrBufLength = 0;
1062     napi_get_value_string_utf8(nativeEngine_, valueStr, nullptr, 0, &valueStrBufLength);
1063     auto valueCStr = std::make_unique<char[]>(valueStrBufLength + 1);
1064     size_t valueStrLength = 0;
1065     napi_get_value_string_utf8(nativeEngine_, valueStr, valueCStr.get(), valueStrBufLength + 1, &valueStrLength);
1066     std::string ret(valueCStr.get(), valueStrLength);
1067     TAG_LOGD(AAFwkTag::ABILITY_SIM, "GetNativeStrFromJsTaggedObj Success");
1068     return ret;
1069 }
1070 
ReportJsError(napi_value obj)1071 void SimulatorImpl::ReportJsError(napi_value obj)
1072 {
1073     std::string errorMsg = GetNativeStrFromJsTaggedObj(obj, "message");
1074     std::string errorName = GetNativeStrFromJsTaggedObj(obj, "name");
1075     std::string errorStack = GetNativeStrFromJsTaggedObj(obj, "stack");
1076     std::string topStack = GetNativeStrFromJsTaggedObj(obj, "topstack");
1077     std::string summary = "Error name:" + errorName + "\n";
1078     summary += "Error message:" + errorMsg + "\n";
1079     bool hasProperty = false;
1080     napi_has_named_property(nativeEngine_, obj, "code", &hasProperty);
1081     if (hasProperty) {
1082         std::string errorCode = GetNativeStrFromJsTaggedObj(obj, "code");
1083         summary += "Error code:" + errorCode + "\n";
1084     }
1085     if (errorStack.empty()) {
1086         TAG_LOGE(AAFwkTag::ABILITY_SIM, "errorStack empty");
1087         return;
1088     }
1089     auto newErrorStack = sourceMapPtr_->TranslateBySourceMap(errorStack);
1090     summary += "Stacktrace:\n" + newErrorStack;
1091 
1092     std::stringstream summaryBody(summary);
1093     std::string line;
1094     std::string formattedSummary;
1095     while (std::getline(summaryBody, line)) {
1096         formattedSummary += "[Simulator Log]" + line + "\n";
1097     }
1098 
1099     TAG_LOGE(AAFwkTag::ABILITY_SIM, "summary:\n%{public}s", formattedSummary.c_str());
1100 }
1101 
CreateStageContext()1102 void SimulatorImpl::CreateStageContext()
1103 {
1104     if (stageContext_ == nullptr) {
1105         stageContext_ = std::make_shared<AbilityStageContext>();
1106         stageContext_->SetOptions(options_);
1107         stageContext_->SetConfiguration(options_.configuration);
1108         stageContext_->SetApplicationInfo(appInfo_);
1109         stageContext_->SetHapModuleInfo(moduleInfo_);
1110     }
1111 }
1112 } // namespace AbilityRuntime
1113 } // namespace OHOS
1114