1 /*
2 * Copyright (c) 2021-2022 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 "ark_native_engine.h"
17
18 #ifdef ENABLE_HITRACE
19 #include <sys/prctl.h>
20 #endif
21
22 #include <sstream>
23 #include "ark_native_deferred.h"
24 #if !defined(is_arkui_x) && defined(OHOS_PLATFORM)
25 #include "unwinder.h"
26 #endif
27 #include "ark_native_reference.h"
28 #include "native_engine/native_property.h"
29 #include "native_engine/native_utils.h"
30 #include "native_sendable.h"
31 #include "securec.h"
32 #include "utils/file.h"
33 #include "utils/log.h"
34 #if !defined(PREVIEW) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
35 #include "parameters.h"
36 #include <uv.h>
37 #endif
38 #ifdef ENABLE_CONTAINER_SCOPE
39 #include "core/common/container_scope.h"
40 #endif
41 #if defined(ENABLE_EVENT_HANDLER)
42 #include "event_handler.h"
43 #endif
44 #ifdef ENABLE_HITRACE
45 #include "hitrace/trace.h"
46 #include "hitrace_meter.h"
47 #include "parameter.h"
48 #include "musl_preinit_common.h"
49 #include "memory_trace.h"
50
51 // LCOV_EXCL_START
52 struct alignas(8) HookJsConfig { // 8 is 8 bit
53 int32_t jsStackReport = 0;
54 uint8_t maxJsStackDepth = 0;
55 bool jsFpUnwind = false;
56 char filterNapiName[64] = { "" };
57 };
58
59 class BlockHookScope {
60 public:
BlockHookScope()61 BlockHookScope()
62 {
63 previousState_ = __set_hook_flag(false);
64 }
~BlockHookScope()65 ~BlockHookScope()
66 {
67 __set_hook_flag(previousState_);
68 }
69 private:
70 bool previousState_ {true};
71 };
72
73 static HookJsConfig* g_hookJsConfig = nullptr;
74 static std::once_flag g_hookOnceFlag;
75 static std::string JS_CALL_STACK_DEPTH_SEP = ","; // ',' is js call stack depth separator
76 static std::string JS_SYMBOL_FILEPATH_SEP = "|"; // '|' is js symbol and filepath separator
77 static constexpr uint64_t BUF_SIZE = 128;
78 #endif
79
80 using panda::JsiRuntimeCallInfo;
81 using panda::BooleanRef;
82 using panda::ObjectRef;
83 using panda::StringRef;
84 using panda::Global;
85 using panda::JSNApi;
86 using panda::FunctionRef;
87 using panda::PrimitiveRef;
88 using panda::ArrayBufferRef;
89 using panda::TypedArrayRef;
90 using panda::PromiseCapabilityRef;
91 using panda::PropertyAttribute;
92 using panda::NativePointerRef;
93 using panda::SymbolRef;
94 using panda::IntegerRef;
95 using panda::DateRef;
96 using panda::BigIntRef;
97 static constexpr auto PANDA_MAIN_FUNCTION = "_GLOBAL::func_main_0";
98 static constexpr auto PANDA_MODULE_NAME = "_GLOBAL_MODULE_NAME";
99 static constexpr auto PANDA_MODULE_NAME_LEN = 32;
100 static std::unordered_set<std::string> NATIVE_MODULE = {"system.app", "ohos.app", "system.router",
101 "system.curves", "ohos.curves", "system.matrix4", "ohos.matrix4"};
102 static constexpr auto NATIVE_MODULE_PREFIX = "@native:";
103 static constexpr auto OHOS_MODULE_PREFIX = "@ohos:";
104 #ifdef ENABLE_HITRACE
105 constexpr auto NAPI_PROFILER_PARAM_SIZE = 10;
106 std::atomic<uint64_t> g_chainId = 0;
107 constexpr int NAPI_CALL_STACK = 2; // just for napi call stack
108 #endif
109
110 std::string ArkNativeEngine::tempModuleName_ {""};
111 bool ArkNativeEngine::napiProfilerEnabled {false};
112 bool ArkNativeEngine::napiProfilerParamReaded {false};
113 PermissionCheckCallback ArkNativeEngine::permissionCheckCallback_ {nullptr};
114
115 // This interface is using by ace_engine
LocalValueToLocalNapiValue(panda::Local<panda::JSValueRef> local)116 napi_value LocalValueToLocalNapiValue(panda::Local<panda::JSValueRef> local)
117 {
118 return JsValueFromLocalValue(local);
119 }
120
121 // This interface is using by ace_engine
NapiValueToLocalValue(napi_value v)122 panda::Local<panda::JSValueRef> NapiValueToLocalValue(napi_value v)
123 {
124 return LocalValueFromJsValue(v);
125 }
126
127 #ifdef ENABLE_CONTAINER_SCOPE
FunctionSetContainerId(const EcmaVM *vm, panda::Local<panda::JSValueRef> &value)128 void FunctionSetContainerId(const EcmaVM *vm, panda::Local<panda::JSValueRef> &value)
129 {
130 if (!value->IsFunction(vm)) {
131 return;
132 }
133 panda::Local<panda::FunctionRef> funcValue(value);
134 if (funcValue->IsNative(vm)) {
135 return;
136 }
137
138 auto extraInfo = funcValue->GetData(vm);
139 if (extraInfo != nullptr) {
140 return;
141 }
142
143 NapiFunctionInfo *funcInfo = NapiFunctionInfo::CreateNewInstance();
144 if (funcInfo == nullptr) {
145 HILOG_ERROR("funcInfo is nullptr");
146 return;
147 }
148 funcInfo->scopeId = OHOS::Ace::ContainerScope::CurrentId();
149 funcValue->SetData(vm, reinterpret_cast<void*>(funcInfo),
150 [](void* env, void *externalPointer, void *data) {
151 auto info = reinterpret_cast<NapiFunctionInfo*>(data);
152 if (info != nullptr) {
153 delete info;
154 info = nullptr;
155 }
156 }, true);
157 }
158 #endif
159
NapiDefineClass(napi_env env, const char* name, NapiNativeCallback callback, void* data, const NapiPropertyDescriptor* properties, size_t length)160 panda::Local<panda::JSValueRef> NapiDefineClass(napi_env env, const char* name, NapiNativeCallback callback,
161 void* data, const NapiPropertyDescriptor* properties, size_t length)
162 {
163 auto vm = const_cast<EcmaVM*>(reinterpret_cast<NativeEngine*>(env)->GetEcmaVm());
164 std::string className(name);
165 if (ArkNativeEngine::napiProfilerEnabled) {
166 className = ArkNativeEngine::tempModuleName_ + "." + name;
167 }
168
169 NapiFunctionInfo* funcInfo = NapiFunctionInfo::CreateNewInstance();
170 if (funcInfo == nullptr) {
171 HILOG_ERROR("funcInfo is nullptr");
172 return panda::JSValueRef::Undefined(vm);
173 }
174 funcInfo->callback = callback;
175 funcInfo->data = data;
176 #ifdef ENABLE_CONTAINER_SCOPE
177 funcInfo->scopeId = OHOS::Ace::ContainerScope::CurrentId();
178 #endif
179
180 Local<panda::FunctionRef> fn = panda::FunctionRef::NewConcurrentClassFunction(vm, ArkNativeFunctionCallBack,
181 [](void* env, void* externalPointer, void* data) {
182 auto info = reinterpret_cast<NapiFunctionInfo*>(data);
183 if (info != nullptr) {
184 delete info;
185 }
186 },
187 reinterpret_cast<void*>(funcInfo), true);
188
189 Local<panda::StringRef> fnName = panda::StringRef::NewFromUtf8(vm, className.c_str());
190 fn->SetName(vm, fnName);
191
192 if (length == 0) {
193 return fn;
194 }
195 Local<panda::ObjectRef> classPrototype = fn->GetFunctionPrototype(vm);
196 Local<panda::ObjectRef> fnObj = fn->ToObject(vm);
197 for (size_t i = 0; i < length; i++) {
198 if (properties[i].attributes & NATIVE_STATIC) {
199 NapiDefineProperty(env, fnObj, properties[i]);
200 } else {
201 if (classPrototype->IsUndefined()) {
202 HILOG_ERROR("ArkNativeEngineImpl::Class's prototype is null");
203 continue;
204 }
205 reinterpret_cast<ArkNativeEngine*>(env)->SetModuleName(classPrototype, className);
206 NapiDefineProperty(env, classPrototype, properties[i]);
207 }
208 }
209
210 return fn;
211 }
212
NapiNativeCreateSendableFunction(napi_env env, const char* name, NapiNativeCallback cb, void* value)213 Local<panda::JSValueRef> NapiNativeCreateSendableFunction(napi_env env,
214 const char* name,
215 NapiNativeCallback cb,
216 void* value)
217 {
218 auto engine = reinterpret_cast<NativeEngine*>(env);
219 auto vm = const_cast<EcmaVM*>(engine->GetEcmaVm());
220 NapiFunctionInfo* funcInfo = NapiFunctionInfo::CreateNewInstance();
221 if (funcInfo == nullptr) {
222 HILOG_ERROR("funcInfo is nullptr");
223 return JSValueRef::Undefined(vm);
224 }
225 funcInfo->callback = cb;
226 funcInfo->data = value;
227
228 Local<panda::FunctionRef> fn = panda::FunctionRef::NewSendable(
229 vm, ArkNativeFunctionCallBack,
230 [](void* env, void* externalPointer, void* data) {
231 auto info = reinterpret_cast<NapiFunctionInfo*>(data);
232 if (info != nullptr) {
233 delete info;
234 }
235 },
236 reinterpret_cast<void*>(funcInfo), true);
237 return fn;
238 }
239
NapiDefineSendableClass(napi_env env, const char* name, NapiNativeCallback callback, void* data, const NapiPropertyDescriptor* properties, size_t propertiesLength, napi_value parent)240 panda::Local<panda::JSValueRef> NapiDefineSendableClass(napi_env env,
241 const char* name,
242 NapiNativeCallback callback,
243 void* data,
244 const NapiPropertyDescriptor* properties,
245 size_t propertiesLength,
246 napi_value parent)
247 {
248 const EcmaVM* vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
249 NapiFunctionInfo* funcInfo = NapiFunctionInfo::CreateNewInstance();
250 if (funcInfo == nullptr) {
251 HILOG_FATAL("funcInfo is nullptr");
252 return JSValueRef::Undefined(vm);
253 }
254 funcInfo->callback = callback;
255 funcInfo->data = data;
256
257 std::string className(name);
258 if (ArkNativeEngine::napiProfilerEnabled) {
259 className = ArkNativeEngine::tempModuleName_ + "." + name;
260 }
261
262 Local<panda::StringRef> fnName = panda::StringRef::NewFromUtf8(vm, className.c_str());
263 Local<JSValueRef> localParent = JSValueRef::Null(vm);
264 if (parent != nullptr) {
265 localParent = LocalValueFromJsValue(parent);
266 }
267
268 auto infos = NativeSendable::CreateSendablePropertiesInfos(env, properties, propertiesLength);
269 Local<panda::FunctionRef> fn = panda::FunctionRef::NewSendableClassFunction(
270 vm, ArkNativeFunctionCallBack,
271 [](void* env, void* externalPointer, void* data) {
272 auto info = reinterpret_cast<NapiFunctionInfo*>(data);
273 if (info != nullptr) {
274 delete info;
275 }
276 },
277 reinterpret_cast<void*>(funcInfo), fnName, infos, localParent, true);
278
279 return fn;
280 }
281
282 struct MoudleNameLocker {
MoudleNameLockerMoudleNameLocker283 explicit MoudleNameLocker(std::string moduleName)
284 {
285 ArkNativeEngine::tempModuleName_ = moduleName;
286 }
~MoudleNameLockerMoudleNameLocker287 ~MoudleNameLocker()
288 {
289 ArkNativeEngine::tempModuleName_ = "";
290 }
291 };
292
GetNativePtrCallBack(void* data)293 void* ArkNativeEngine::GetNativePtrCallBack(void* data)
294 {
295 if (data == nullptr) {
296 HILOG_ERROR("data is nullptr");
297 return nullptr;
298 }
299 auto info = reinterpret_cast<NapiFunctionInfo*>(data);
300 auto cb = reinterpret_cast<void*>(info->callback);
301 return cb;
302 }
303
CheckArkApiAllowList( NativeModule* module, panda::ecmascript::ApiCheckContext context, panda::Local<panda::ObjectRef>& exportCopy)304 bool ArkNativeEngine::CheckArkApiAllowList(
305 NativeModule* module, panda::ecmascript::ApiCheckContext context, panda::Local<panda::ObjectRef>& exportCopy)
306 {
307 std::unique_ptr<ApiAllowListChecker>& apiAllowListChecker = module->apiAllowListChecker;
308 if (apiAllowListChecker != nullptr) {
309 const std::string apiPath = context.moduleName->ToString(context.ecmaVm);
310 if ((*apiAllowListChecker)(apiPath)) {
311 CopyPropertyApiFilter(apiAllowListChecker, context.ecmaVm, context.exportObj, exportCopy, apiPath);
312 }
313 return true;
314 }
315 return false;
316 }
317
CopyPropertyApiFilter(const std::unique_ptr<ApiAllowListChecker>& apiAllowListChecker, const EcmaVM* ecmaVm, const panda::Local<panda::ObjectRef> exportObj, panda::Local<panda::ObjectRef>& exportCopy, const std::string& apiPath)318 void ArkNativeEngine::CopyPropertyApiFilter(const std::unique_ptr<ApiAllowListChecker>& apiAllowListChecker,
319 const EcmaVM* ecmaVm, const panda::Local<panda::ObjectRef> exportObj, panda::Local<panda::ObjectRef>& exportCopy,
320 const std::string& apiPath)
321 {
322 panda::Local<panda::ArrayRef> namesArrayRef = exportObj->GetAllPropertyNames(ecmaVm, NATIVE_DEFAULT);
323 for (uint32_t i = 0; i < namesArrayRef->Length(ecmaVm); ++i) {
324 const panda::Local<panda::JSValueRef> nameValue = panda::ArrayRef::GetValueAt(ecmaVm, namesArrayRef, i);
325 const panda::Local<panda::JSValueRef> value = exportObj->Get(ecmaVm, nameValue);
326 const std::string curPath = apiPath + "." + nameValue->ToString(ecmaVm)->ToString(ecmaVm);
327 if ((*apiAllowListChecker)(curPath)) {
328 const std::string valueType = value->Typeof(ecmaVm)->ToString(ecmaVm);
329 if (valueType == "object") {
330 panda::Local<panda::ObjectRef> subObject = ObjectRef::New(ecmaVm);
331 CopyPropertyApiFilter(apiAllowListChecker, ecmaVm, value, subObject, curPath);
332 exportCopy->Set(ecmaVm, nameValue, subObject);
333 HILOG_DEBUG("Set the package '%{public}s' to the allow list", curPath.c_str());
334 } else if (valueType == "function") {
335 exportCopy->Set(ecmaVm, nameValue, value);
336 HILOG_DEBUG("Set the function '%{public}s' to the allow list", curPath.c_str());
337 } else {
338 exportCopy->Set(ecmaVm, nameValue, value);
339 HILOG_DEBUG("Set the element type is '%{public}s::%{public}s' to the allow list", valueType.c_str(),
340 curPath.c_str());
341 }
342 }
343 }
344 }
345
ArkNativeEngine(EcmaVM* vm, void* jsEngine, bool isLimitedWorker)346 ArkNativeEngine::ArkNativeEngine(EcmaVM* vm, void* jsEngine, bool isLimitedWorker) : NativeEngine(jsEngine, vm),
347 topScope_(vm),
348 isLimitedWorker_(isLimitedWorker)
349 {
350 HILOG_DEBUG("ArkNativeEngine::ArkNativeEngine");
351 panda::JSNApi::SetEnv(vm, this);
352 #ifdef ENABLE_HITRACE
353 if (!ArkNativeEngine::napiProfilerParamReaded) {
354 char napiProfilerParam[NAPI_PROFILER_PARAM_SIZE] = {0};
355 int ret = GetParameter("persist.hiviewdfx.napiprofiler.enabled", "false",
356 napiProfilerParam, sizeof(napiProfilerParam));
357 if (ret > 0 && strcmp(napiProfilerParam, "true") == 0) {
358 ArkNativeEngine::napiProfilerEnabled = true;
359 }
360 ArkNativeEngine::napiProfilerParamReaded = true;
361 }
362 #endif
363 LocalScope scope(vm_);
364 Local<StringRef> requireInternalName = StringRef::NewFromUtf8(vm, "requireInternal");
365 void* requireData = static_cast<void*>(this);
366
367 options_ = new NapiOptions();
368 crossThreadCheck_ = JSNApi::IsMultiThreadCheckEnabled(vm);
369 #if defined(OHOS_PLATFORM) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
370 int napiProperties = OHOS::system::GetIntParameter<int>("persist.ark.napi.properties", -1);
371 if (options_ != nullptr) {
372 options_->SetProperties(napiProperties);
373 }
374 #endif
375 Local<FunctionRef> requireNapi =
376 FunctionRef::New(
377 vm,
378 [](JsiRuntimeCallInfo *info) -> Local<JSValueRef> {
379 EcmaVM *ecmaVm = info->GetVM();
380 panda::EscapeLocalScope scope(ecmaVm);
381 NativeModuleManager* moduleManager = NativeModuleManager::GetInstance();
382 ArkNativeEngine* arkNativeEngine = static_cast<ArkNativeEngine*>(info->GetData());
383 Local<StringRef> moduleName(info->GetCallArgRef(0));
384 NativeModule* module = nullptr;
385 bool isAppModule = false;
386 std::string errInfo = "";
387 Local<JSValueRef> exports(JSValueRef::Undefined(ecmaVm));
388 #ifdef IOS_PLATFORM
389 if (arkNativeEngine->isLimitedWorker_) {
390 if (!moduleManager->CheckModuleRestricted(moduleName->ToString(ecmaVm).c_str())) {
391 HILOG_ERROR("module %{public}s does not found in whitelist",
392 moduleName->ToString(ecmaVm).c_str());
393 return scope.Escape(exports);
394 }
395 }
396 module = moduleManager->LoadNativeModule(
397 moduleName->ToString(ecmaVm).c_str(), nullptr, false, errInfo, false, "");
398 #else
399 const uint32_t lengthMax = 2;
400 if (info->GetArgsNumber() >= lengthMax) {
401 Local<BooleanRef> ret(info->GetCallArgRef(1));
402 isAppModule = ret->Value();
403 }
404 arkNativeEngine->isAppModule_ = isAppModule;
405 if (arkNativeEngine->isLimitedWorker_ && !isAppModule) {
406 if (!moduleManager->CheckModuleRestricted(moduleName->ToString(ecmaVm).c_str())) {
407 HILOG_ERROR("module %{public}s does not found in whitelist",
408 moduleName->ToString(ecmaVm).c_str());
409 return scope.Escape(exports);
410 }
411 }
412
413 if (info->GetArgsNumber() == 3) { // 3:Determine if the number of parameters is equal to 3
414 Local<StringRef> path(info->GetCallArgRef(2)); // 2:Take the second parameter
415 module = moduleManager->LoadNativeModule(moduleName->ToString(ecmaVm).c_str(),
416 path->ToString(ecmaVm).c_str(), isAppModule, errInfo, false, "");
417 } else if (info->GetArgsNumber() == 4) { // 4:Determine if the number of parameters is equal to 4
418 Local<StringRef> path(info->GetCallArgRef(2)); // 2:Take the second parameter
419 Local<StringRef> relativePath(info->GetCallArgRef(3)); // 3:Take the second parameter
420 module = moduleManager->LoadNativeModule(moduleName->ToString(ecmaVm).c_str(), nullptr, isAppModule,
421 errInfo, false, relativePath->ToString(ecmaVm).c_str());
422 } else {
423 module =
424 moduleManager->LoadNativeModule(moduleName->ToString(ecmaVm).c_str(),
425 nullptr, isAppModule, errInfo, false, "");
426 }
427 #endif
428 if (module != nullptr) {
429 auto it = arkNativeEngine->loadedModules_.find(module);
430 if (it != arkNativeEngine->loadedModules_.end()) {
431 return scope.Escape(it->second.ToLocal(ecmaVm));
432 }
433 std::string strModuleName = moduleName->ToString(ecmaVm);
434 moduleManager->SetNativeEngine(strModuleName, arkNativeEngine);
435 MoudleNameLocker nameLocker(strModuleName);
436
437 if (module->jsCode == nullptr && module->getABCCode != nullptr) {
438 module->getABCCode(&module->jsCode, &module->jsCodeLen);
439 }
440 if (module->jsABCCode != nullptr || module->jsCode != nullptr) {
441 char fileName[NAPI_PATH_MAX] = { 0 };
442 const char* name = module->name;
443 if (sprintf_s(fileName, sizeof(fileName), "lib%s.z.so/%s.js", name, name) == -1) {
444 HILOG_ERROR("sprintf_s file name failed");
445 return scope.Escape(exports);
446 }
447 HILOG_DEBUG("load js code from %{public}s", fileName);
448 const void *buffer = nullptr;
449 if (module->jsABCCode) {
450 buffer = static_cast<const void *>(module->jsABCCode);
451 } else {
452 buffer = static_cast<const void *>(module->jsCode);
453 }
454 auto exportObject = arkNativeEngine->LoadArkModule(buffer, module->jsCodeLen, fileName);
455 if (exportObject->IsUndefined()) {
456 HILOG_ERROR("load module failed");
457 return scope.Escape(exports);
458 } else {
459 exports = exportObject;
460 arkNativeEngine->loadedModules_[module] = Global<JSValueRef>(ecmaVm, exports);
461 }
462 } else if (module->registerCallback != nullptr) {
463 Local<ObjectRef> exportObj = ObjectRef::New(ecmaVm);
464 #ifdef ENABLE_HITRACE
465 StartTrace(HITRACE_TAG_ACE, "NAPI module init, name = " + std::string(module->name));
466 #endif
467 arkNativeEngine->SetModuleName(exportObj, module->name);
468 module->registerCallback(reinterpret_cast<napi_env>(arkNativeEngine),
469 JsValueFromLocalValue(exportObj));
470 #ifdef ENABLE_HITRACE
471 FinishTrace(HITRACE_TAG_ACE);
472 #endif
473 panda::Local<panda::ObjectRef> exportCopy = panda::ObjectRef::New(ecmaVm);
474 panda::ecmascript::ApiCheckContext context{moduleManager, ecmaVm, moduleName, exportObj, scope};
475 if (CheckArkApiAllowList(module, context, exportCopy)) {
476 return scope.Escape(exportCopy);
477 }
478 exports = exportObj;
479 arkNativeEngine->loadedModules_[module] = Global<JSValueRef>(ecmaVm, exports);
480 } else {
481 HILOG_ERROR("init module failed");
482 return scope.Escape(exports);
483 }
484 }
485 if (module == nullptr) {
486 HILOG_INFO("%{public}s", errInfo.c_str());
487 exports = panda::ObjectRef::CreateNativeModuleFailureInfo(ecmaVm, errInfo);
488 }
489 return scope.Escape(exports);
490 },
491 nullptr,
492 requireData);
493
494 Local<FunctionRef> requireInternal =
495 FunctionRef::New(
496 vm,
497 [](JsiRuntimeCallInfo *info) -> Local<JSValueRef> {
498 EcmaVM *ecmaVm = info->GetVM();
499 panda::EscapeLocalScope scope(ecmaVm);
500 NativeModuleManager* moduleManager = NativeModuleManager::GetInstance();
501 ArkNativeEngine* arkNativeEngine = static_cast<ArkNativeEngine*>(info->GetData());
502 Local<StringRef> moduleName(info->GetCallArgRef(0));
503 std::string errInfo = "";
504 Local<JSValueRef> exports(JSValueRef::Undefined(ecmaVm));
505 if (arkNativeEngine->isLimitedWorker_) {
506 if (!moduleManager->CheckModuleRestricted(moduleName->ToString(ecmaVm).c_str())) {
507 HILOG_ERROR("module %{public}s does not found in whitelist",
508 moduleName->ToString(ecmaVm).c_str());
509 return scope.Escape(exports);
510 }
511 }
512 NativeModule* module = moduleManager->LoadNativeModule(moduleName->ToString(ecmaVm).c_str(),
513 nullptr, false, errInfo, false, "");
514 MoudleNameLocker nameLocker(moduleName->ToString(ecmaVm));
515 if (module != nullptr && arkNativeEngine) {
516 auto it = arkNativeEngine->loadedModules_.find(module);
517 if (it != arkNativeEngine->loadedModules_.end()) {
518 return scope.Escape(it->second.ToLocal(ecmaVm));
519 }
520 std::string strModuleName = moduleName->ToString(ecmaVm);
521 moduleManager->SetNativeEngine(strModuleName, arkNativeEngine);
522 Local<ObjectRef> exportObj = ObjectRef::New(ecmaVm);
523 if (exportObj->IsObject(ecmaVm)) {
524 arkNativeEngine->SetModuleName(exportObj, module->name);
525 module->registerCallback(reinterpret_cast<napi_env>(arkNativeEngine),
526 JsValueFromLocalValue(exportObj));
527 exports = exportObj;
528 arkNativeEngine->loadedModules_[module] = Global<JSValueRef>(ecmaVm, exports);
529 } else {
530 HILOG_ERROR("exportObject is nullptr");
531 return scope.Escape(exports);
532 }
533 }
534 return scope.Escape(exports);
535 },
536 nullptr,
537 requireData);
538
539 Local<ObjectRef> global = panda::JSNApi::GetGlobalObject(vm);
540 #if !defined(PREVIEW)
541 Local<StringRef> requireName = StringRef::NewFromUtf8(vm, "requireNapi");
542 global->Set(vm, requireName, requireNapi);
543 #else
544 Local<StringRef> requireNapiPreview = StringRef::NewFromUtf8(vm, "requireNapiPreview");
545 global->Set(vm, requireNapiPreview, requireNapi);
546 #endif
547 global->Set(vm, requireInternalName, requireInternal);
548 JSNApi::SetNativePtrGetter(vm, reinterpret_cast<void*>(ArkNativeEngine::GetNativePtrCallBack));
549 // need to call init of base class.
550 NativeModuleManager* moduleManager = NativeModuleManager::GetInstance();
551 std::function<bool(const std::string&)> func = [moduleManager](const std::string& moduleKey) -> bool {
552 return moduleManager->UnloadNativeModule(moduleKey);
553 };
554 JSNApi::SetUnloadNativeModuleCallback(vm, func);
555 Init();
556 panda::JSNApi::SetLoop(vm, loop_);
557 panda::JSNApi::SetWeakFinalizeTaskCallback(vm, [this] () -> void {
558 this->PostFinalizeTasks();
559 });
560 JSNApi::SetAsyncCleanTaskCallback(vm, [this] (AsyncNativeCallbacksPack *callbacksPack) {
561 this->PostAsyncTask(callbacksPack);
562 });
563 #if defined(ENABLE_EVENT_HANDLER)
564 if (JSNApi::IsJSMainThreadOfEcmaVM(vm)) {
565 arkIdleMonitor_ = new ArkIdleMonitor(vm);
566 JSNApi::SetTriggerGCTaskCallback(vm, [this](TriggerGCData& data) {
567 this->PostTriggerGCTask(data);
568 });
569 arkIdleMonitor_->SetStartTimerCallback();
570 PostLooperTriggerIdleGCTask();
571 }
572 #endif
573 }
574
~ArkNativeEngine()575 ArkNativeEngine::~ArkNativeEngine()
576 {
577 HILOG_DEBUG("ArkNativeEngine::~ArkNativeEngine");
578 Deinit();
579 // Free cached objects
580 for (auto&& [module, exportObj] : loadedModules_) {
581 exportObj.FreeGlobalHandleAddr();
582 }
583 // Free callbackRef
584 if (promiseRejectCallbackRef_ != nullptr) {
585 delete promiseRejectCallbackRef_;
586 }
587 if (checkCallbackRef_ != nullptr) {
588 delete checkCallbackRef_;
589 }
590 if (options_ != nullptr) {
591 delete options_;
592 options_ = nullptr;
593 }
594
595 if (arkIdleMonitor_ != nullptr) {
596 delete arkIdleMonitor_;
597 arkIdleMonitor_ = nullptr;
598 }
599 }
600
601 #ifdef ENABLE_HITRACE
CheckHookConfig(const std::string &nameRef)602 static inline bool CheckHookConfig(const std::string &nameRef)
603 {
604 if (g_hookJsConfig == nullptr || g_hookJsConfig->jsStackReport <= 0 ||
605 g_hookJsConfig->maxJsStackDepth == 0 || !g_hookJsConfig->jsFpUnwind) {
606 return false;
607 } else if (g_hookJsConfig->filterNapiName[0] != '\0' &&
608 nameRef.find(g_hookJsConfig->filterNapiName) != std::string::npos) {
609 return false;
610 }
611 return true;
612 }
613 #endif
614
StartNapiProfilerTrace(panda::JsiRuntimeCallInfo* runtimeInfo, void* cb)615 static inline uint64_t StartNapiProfilerTrace(panda::JsiRuntimeCallInfo* runtimeInfo, void* cb)
616 {
617 #ifdef ENABLE_HITRACE
618 if (ArkNativeEngine::napiProfilerEnabled) {
619 EcmaVM *vm = runtimeInfo->GetVM();
620 LocalScope scope(vm);
621 Local<panda::FunctionRef> fn = runtimeInfo->GetFunctionRef();
622 Local<panda::StringRef> nameRef = fn->GetName(vm);
623 char threadName[BUF_SIZE];
624 prctl(PR_GET_NAME, threadName);
625 StartTraceArgs(HITRACE_TAG_ACE, "Napi called:%s, tname:%s", nameRef->ToString(vm).c_str(), threadName);
626 }
627 bool hookFlag = __get_hook_flag() && __get_global_hook_flag();
628 if (!hookFlag) {
629 return 0;
630 }
631 EcmaVM* vm = runtimeInfo->GetVM();
632 LocalScope scope(vm);
633 Local<panda::FunctionRef> fn = runtimeInfo->GetFunctionRef();
634 Local<panda::StringRef> nameRef = fn->GetName(vm);
635 if (g_hookJsConfig == nullptr) {
636 std::call_once(g_hookOnceFlag, []() { g_hookJsConfig = (HookJsConfig*)__get_hook_config(); });
637 }
638 // add memtrace function
639 if (g_hookJsConfig != nullptr && g_hookJsConfig->jsStackReport == NAPI_CALL_STACK && !g_hookJsConfig->jsFpUnwind) {
640 OHOS::HiviewDFX::HiTraceChain::ClearId();
641 std::unique_ptr<OHOS::HiviewDFX::HiTraceId> arkCallBackTraceId = std::make_unique<OHOS::HiviewDFX::HiTraceId>(
642 OHOS::HiviewDFX::HiTraceChain::Begin("New ArkCallBackTrace", 0));
643 char buffer[256] = {0}; // 256 : buffer size of tag name
644 if (sprintf_s(buffer, sizeof(buffer), "napi:0x%x:%s", arkCallBackTraceId->GetChainId(),
645 nameRef->ToString(vm).c_str()) == -1) {
646 return 0;
647 }
648 uint64_t addr = reinterpret_cast<uint64_t>(cb);
649 ++g_chainId;
650 (void)memtrace(reinterpret_cast<void*>(addr + g_chainId), 8, buffer, true); // 8: the size of addr
651 return 0;
652 }
653 if (!CheckHookConfig(nameRef->ToString(vm))) {
654 return 0;
655 }
656 BlockHookScope blockHook; // block hook
657 std::string rawStack;
658 std::vector<JsFrameInfo> jsFrames;
659 uint64_t nestChainId = 0;
660 jsFrames.reserve(g_hookJsConfig->maxJsStackDepth);
661 auto env = reinterpret_cast<napi_env>(JSNApi::GetEnv(vm));
662 auto engine = reinterpret_cast<NativeEngine*>(env);
663 engine->BuildJsStackInfoListWithCustomDepth(jsFrames);
664 std::stringstream ssRawStack;
665 for (size_t i = 0; i < jsFrames.size() && i < g_hookJsConfig->maxJsStackDepth; i++) {
666 ssRawStack << jsFrames[i].functionName << JS_SYMBOL_FILEPATH_SEP << jsFrames[i].fileName << ":" <<
667 jsFrames[i].pos;
668 if (i < jsFrames.size() - 1) {
669 ssRawStack << JS_CALL_STACK_DEPTH_SEP;
670 }
671 }
672 rawStack = ssRawStack.str();
673 OHOS::HiviewDFX::HiTraceChain::Begin("ArkNativeFunctionCallBack", 0);
674 OHOS::HiviewDFX::HiTraceId hitraceId = OHOS::HiviewDFX::HiTraceChain::GetId();
675 // resolve nested calls to napi and ts
676 if (hitraceId.IsValid()) {
677 nestChainId = hitraceId.GetChainId();
678 }
679 uint64_t chainId = ++g_chainId;
680 hitraceId.SetChainId(chainId);
681 OHOS::HiviewDFX::HiTraceChain::SetId(hitraceId);
682 __send_hook_misc_data(chainId, rawStack.c_str(), rawStack.size() + 1, 1);
683 return nestChainId;
684
685 #endif
686 return 0;
687 }
688
FinishNapiProfilerTrace(uint64_t value)689 static inline void FinishNapiProfilerTrace(uint64_t value)
690 {
691 #ifdef ENABLE_HITRACE
692 if (ArkNativeEngine::napiProfilerEnabled) {
693 FinishTrace(HITRACE_TAG_ACE);
694 }
695 bool hookFlag = __get_hook_flag() && __get_global_hook_flag();
696 if (!hookFlag) {
697 return;
698 }
699 BlockHookScope blockHook; // block hook
700 OHOS::HiviewDFX::HiTraceId hitraceId = OHOS::HiviewDFX::HiTraceChain::GetId();
701 if (hitraceId.IsValid()) {
702 OHOS::HiviewDFX::HiTraceChain::End(hitraceId);
703 OHOS::HiviewDFX::HiTraceChain::ClearId();
704 }
705 // resolve nested calls to napi and ts
706 if (value) {
707 hitraceId.SetChainId(value);
708 OHOS::HiviewDFX::HiTraceChain::SetId(hitraceId);
709 }
710
711 #endif
712 }
713
714 template <bool changeState>
ArkNativeFunctionCallBack(JsiRuntimeCallInfo *runtimeInfo)715 panda::JSValueRef ArkNativeFunctionCallBack(JsiRuntimeCallInfo *runtimeInfo)
716 {
717 EcmaVM *vm = runtimeInfo->GetVM();
718 panda::LocalScope scope(vm);
719 bool getStackBeforeCallNapiSuccess = false;
720 JSNApi::GetStackBeforeCallNapiSuccess(vm, getStackBeforeCallNapiSuccess);
721 auto info = reinterpret_cast<NapiFunctionInfo*>(runtimeInfo->GetData());
722 auto env = reinterpret_cast<napi_env>(JSNApi::GetEnv(vm));
723 auto engine = reinterpret_cast<NativeEngine*>(env);
724 auto cb = info->callback;
725 if (engine == nullptr) {
726 HILOG_ERROR("native engine is null");
727 return **JSValueRef::Undefined(vm);
728 }
729
730 uint64_t nestChainId = StartNapiProfilerTrace(runtimeInfo, reinterpret_cast<void *>(cb));
731
732 if (JSNApi::IsMixedDebugEnabled(vm)) {
733 JSNApi::NotifyNativeCalling(vm, reinterpret_cast<void *>(cb));
734 }
735
736 napi_value result = nullptr;
737 if (cb != nullptr) {
738 if constexpr (changeState) {
739 panda::JsiNativeScope nativeScope(vm);
740 result = cb(env, runtimeInfo);
741 } else {
742 result = cb(env, runtimeInfo);
743 }
744 }
745
746 if (JSNApi::IsMixedDebugEnabled(vm)) {
747 JSNApi::NotifyNativeReturn(vm, reinterpret_cast<void *>(cb));
748 }
749
750 Local<panda::JSValueRef> localRet = panda::JSValueRef::Undefined(vm);
751 if (result != nullptr) {
752 localRet = LocalValueFromJsValue(result);
753 }
754
755 FinishNapiProfilerTrace(nestChainId);
756 // Fixme: Rethrow error to engine while clear lastException_
757 if (!engine->lastException_.IsEmpty()) {
758 engine->lastException_.Empty();
759 }
760
761 if (localRet.IsEmpty()) {
762 return **JSValueRef::Undefined(vm);
763 }
764 if (getStackBeforeCallNapiSuccess) {
765 JSNApi::GetStackAfterCallNapi(vm);
766 }
767 return **localRet;
768 }
769
NapiNativeCreateFunction(napi_env env, const char* name, NapiNativeCallback cb, void* value)770 static Local<panda::JSValueRef> NapiNativeCreateFunction(napi_env env, const char* name,
771 NapiNativeCallback cb, void* value)
772 {
773 auto engine = reinterpret_cast<NativeEngine*>(env);
774 auto vm = const_cast<EcmaVM*>(engine->GetEcmaVm());
775 NapiFunctionInfo* funcInfo = NapiFunctionInfo::CreateNewInstance();
776 if (funcInfo == nullptr) {
777 HILOG_ERROR("funcInfo is nullptr");
778 return JSValueRef::Undefined(vm);
779 }
780 funcInfo->callback = cb;
781 funcInfo->data = value;
782 #ifdef ENABLE_CONTAINER_SCOPE
783 funcInfo->scopeId = OHOS::Ace::ContainerScope::CurrentId();
784 #endif
785
786 Local<panda::FunctionRef> fn = panda::FunctionRef::NewConcurrent(
787 vm, ArkNativeFunctionCallBack,
788 [](void* env, void* externalPointer, void* data) {
789 auto info = reinterpret_cast<NapiFunctionInfo*>(data);
790 if (info != nullptr) {
791 delete info;
792 }
793 },
794 reinterpret_cast<void*>(funcInfo), true
795 );
796 Local<panda::StringRef> fnName = panda::StringRef::NewFromUtf8(vm, name);
797 fn->SetName(vm, fnName);
798 return fn;
799 }
800
GetProperty(EcmaVM* vm, Local<panda::ObjectRef> &obj, const char* name)801 static Local<JSValueRef> GetProperty(EcmaVM* vm, Local<panda::ObjectRef> &obj, const char* name)
802 {
803 Local<StringRef> key = StringRef::NewFromUtf8(vm, name);
804 Local<JSValueRef> val = obj->Get(vm, key);
805 return val;
806 }
807
GetCString(EcmaVM* vm, Local<StringRef> str, char* buffer, size_t size, size_t* length)808 void GetCString(EcmaVM* vm, Local<StringRef> str, char* buffer, size_t size, size_t* length)
809 {
810 if (length == nullptr) {
811 return;
812 }
813 if (buffer == nullptr) {
814 *length = str->Utf8Length(vm, true) - 1;
815 } else if (size != 0) {
816 uint32_t copied = str->WriteUtf8(vm, buffer, size - 1, true) - 1;
817 buffer[copied] = '\0';
818 *length = copied;
819 } else {
820 *length = 0;
821 }
822 }
823
NapiGetModuleName(napi_env env, Local<panda::ObjectRef> &obj)824 std::string NapiGetModuleName(napi_env env, Local<panda::ObjectRef> &obj)
825 {
826 auto engine = reinterpret_cast<NativeEngine*>(env);
827 auto vm = const_cast<EcmaVM*>(engine->GetEcmaVm());
828 std::string moduleName("");
829 auto nativeModuleName = GetProperty(vm, obj, PANDA_MODULE_NAME);
830 if (nativeModuleName->IsString(vm)) {
831 char arrayName[PANDA_MODULE_NAME_LEN] = {0};
832 size_t len = 0;
833 GetCString(vm, nativeModuleName, arrayName, PANDA_MODULE_NAME_LEN, &len);
834 moduleName += arrayName;
835 moduleName += ".";
836 }
837 return moduleName;
838 }
839
NapiDefinePropertyInner(napi_env env, Local<panda::ObjectRef> &obj, NapiPropertyDescriptor &propertyDescriptor, Local<panda::JSValueRef> &propertyName, bool &result)840 void NapiDefinePropertyInner(napi_env env,
841 Local<panda::ObjectRef> &obj,
842 NapiPropertyDescriptor &propertyDescriptor,
843 Local<panda::JSValueRef> &propertyName,
844 bool &result)
845 {
846 auto engine = reinterpret_cast<NativeEngine*>(env);
847 auto vm = engine->GetEcmaVm();
848 bool writable = (propertyDescriptor.attributes & NATIVE_WRITABLE) != 0;
849 bool enumable = (propertyDescriptor.attributes & NATIVE_ENUMERABLE) != 0;
850 bool configable = (propertyDescriptor.attributes & NATIVE_CONFIGURABLE) != 0;
851 std::string fullName("");
852 if (propertyDescriptor.getter != nullptr || propertyDescriptor.setter != nullptr) {
853 #ifdef ENABLE_HITRACE
854 fullName += NapiGetModuleName(env, obj);
855 #endif
856 Local<panda::JSValueRef> localGetter = panda::JSValueRef::Undefined(vm);
857 Local<panda::JSValueRef> localSetter = panda::JSValueRef::Undefined(vm);
858
859 if (propertyDescriptor.getter != nullptr) {
860 fullName += "getter";
861 localGetter = NapiNativeCreateFunction(env, fullName.c_str(),
862 propertyDescriptor.getter, propertyDescriptor.data);
863 }
864 if (propertyDescriptor.setter != nullptr) {
865 fullName += "setter";
866 localSetter = NapiNativeCreateFunction(env, fullName.c_str(),
867 propertyDescriptor.setter, propertyDescriptor.data);
868 }
869
870 PropertyAttribute attr(panda::JSValueRef::Undefined(vm), false, enumable, configable);
871 result = obj->SetAccessorProperty(vm, propertyName, localGetter, localSetter, attr);
872 } else if (propertyDescriptor.method != nullptr) {
873 #ifdef ENABLE_HITRACE
874 fullName += NapiGetModuleName(env, obj);
875 #endif
876 if (propertyDescriptor.utf8name != nullptr) {
877 fullName += propertyDescriptor.utf8name;
878 } else {
879 fullName += propertyName->IsString(vm)
880 ? Local<panda::StringRef>(propertyName)->ToString(vm)
881 : Local<panda::SymbolRef>(propertyName)->GetDescription(vm)->ToString(vm);
882 }
883 Local<panda::JSValueRef> cbObj = NapiNativeCreateFunction(env, fullName.c_str(),
884 propertyDescriptor.method, propertyDescriptor.data);
885 PropertyAttribute attr(cbObj, writable, enumable, configable);
886 result = obj->DefineProperty(vm, propertyName, attr);
887 } else {
888 Local<panda::JSValueRef> val = LocalValueFromJsValue(propertyDescriptor.value);
889
890 PropertyAttribute attr(val, writable, enumable, configable);
891 result = obj->DefineProperty(vm, propertyName, attr);
892 }
893 }
894
NapiDefineProperty(napi_env env, Local<panda::ObjectRef> &obj, NapiPropertyDescriptor propertyDescriptor)895 bool NapiDefineProperty(napi_env env, Local<panda::ObjectRef> &obj, NapiPropertyDescriptor propertyDescriptor)
896 {
897 auto engine = reinterpret_cast<NativeEngine*>(env);
898 auto vm = engine->GetEcmaVm();
899 bool result = false;
900 Local<panda::JSValueRef> propertyName;
901 if (propertyDescriptor.utf8name != nullptr) {
902 propertyName = panda::StringRef::NewFromUtf8(vm, propertyDescriptor.utf8name);
903 } else {
904 propertyName = LocalValueFromJsValue(propertyDescriptor.name);
905 }
906 if (obj->IsJSShared(vm)) {
907 NativeSendable::NapiDefineSendabledProperty(env, obj, propertyDescriptor, propertyName, result);
908 } else {
909 NapiDefinePropertyInner(env, obj, propertyDescriptor, propertyName, result);
910 }
911 Local<panda::ObjectRef> excep = panda::JSNApi::GetUncaughtException(vm);
912 if (!excep.IsNull()) {
913 HILOG_DEBUG("ArkNativeObject::DefineProperty occur Exception");
914 panda::JSNApi::GetAndClearUncaughtException(vm);
915 }
916 return result;
917 }
918
NapiCreateObjectWithProperties(napi_env env, size_t propertyCount, const napi_property_descriptor *properties, Local<panda::JSValueRef> *keys, PropertyAttribute *attrs)919 panda::Local<panda::ObjectRef> NapiCreateObjectWithProperties(napi_env env, size_t propertyCount,
920 const napi_property_descriptor *properties,
921 Local<panda::JSValueRef> *keys,
922 PropertyAttribute *attrs)
923 {
924 auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
925 panda::EscapeLocalScope scope(vm);
926 for (size_t i = 0; i < propertyCount; ++i) {
927 const napi_property_descriptor &property = properties[i];
928
929 const char* utf8name = property.utf8name;
930 uint32_t attributes = property.attributes;
931 bool writable = (attributes & NATIVE_WRITABLE) != 0;
932 bool enumable = (attributes & NATIVE_ENUMERABLE) != 0;
933 bool configable = (attributes & NATIVE_CONFIGURABLE) != 0;
934 NapiNativeCallback method = reinterpret_cast<NapiNativeCallback>(property.method);
935 NapiNativeCallback getter = reinterpret_cast<NapiNativeCallback>(property.getter);
936 NapiNativeCallback setter = reinterpret_cast<NapiNativeCallback>(property.setter);
937 napi_value value = property.value;
938 void *data = property.data;
939
940 Local<panda::JSValueRef> val = panda::JSValueRef::Undefined(vm);
941
942 std::string fullName("");
943 if (getter != nullptr || setter != nullptr) {
944 Local<panda::JSValueRef> localGetter = panda::JSValueRef::Undefined(vm);
945 Local<panda::JSValueRef> localSetter = panda::JSValueRef::Undefined(vm);
946
947 if (getter != nullptr) {
948 fullName += "getter";
949 localGetter = NapiNativeCreateFunction(env, fullName.c_str(), getter, data);
950 }
951 if (setter != nullptr) {
952 fullName += "setter";
953 localSetter = NapiNativeCreateFunction(env, fullName.c_str(), setter, data);
954 }
955
956 val = panda::ObjectRef::CreateAccessorData(vm, localGetter, localSetter);
957 writable = false;
958 } else if (method != nullptr) {
959 fullName += utf8name;
960 val = NapiNativeCreateFunction(env, fullName.c_str(), method, data);
961 } else {
962 val = LocalValueFromJsValue(value);
963 }
964 new (reinterpret_cast<void *>(&attrs[i])) PropertyAttribute(val, writable, enumable, configable);
965 keys[i] = panda::StringRef::NewFromUtf8(vm, utf8name);
966 }
967 Local<panda::ObjectRef> object = panda::ObjectRef::NewWithProperties(vm, propertyCount, keys, attrs);
968 return scope.Escape(object);
969 }
970
NapiCreateSObjectWithProperties(napi_env env, size_t propertyCount, const NapiPropertyDescriptor* properties)971 panda::Local<panda::ObjectRef> NapiCreateSObjectWithProperties(napi_env env,
972 size_t propertyCount,
973 const NapiPropertyDescriptor* properties)
974 {
975 auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
976 panda::EscapeLocalScope scope(vm);
977 FunctionRef::SendablePropertiesInfo info;
978 for (size_t i = 0; i < propertyCount; ++i) {
979 NativeSendable::InitSendablePropertiesInfo(env, info, properties[i]);
980 }
981 Local<panda::ObjectRef> object = panda::ObjectRef::NewSWithProperties(vm, info);
982 return scope.Escape(object);
983 }
984
GetModuleFromName( const std::string& moduleName, bool isAppModule, const std::string& id, const std::string& param, const std::string& instanceName, void** instance)985 panda::Local<panda::ObjectRef> ArkNativeEngine::GetModuleFromName(
986 const std::string& moduleName, bool isAppModule, const std::string& id, const std::string& param,
987 const std::string& instanceName, void** instance)
988 {
989 panda::EscapeLocalScope scope(vm_);
990 Local<ObjectRef> exports(JSValueRef::Undefined(vm_));
991 NativeModuleManager* moduleManager = NativeModuleManager::GetInstance();
992 std::string errInfo = "";
993 NativeModule* module = moduleManager->LoadNativeModule(moduleName.c_str(), nullptr, isAppModule, errInfo);
994 if (module != nullptr) {
995 Local<StringRef> idStr = StringRef::NewFromUtf8(vm_, id.c_str(), id.size());
996 napi_value idValue = JsValueFromLocalValue(idStr);
997 Local<StringRef> paramStr = StringRef::NewFromUtf8(vm_, param.c_str(), param.size());
998 napi_value paramValue = JsValueFromLocalValue(paramStr);
999 Local<ObjectRef> exportObj = ObjectRef::New(vm_);
1000 NapiPropertyDescriptor idProperty, paramProperty;
1001 idProperty.utf8name = "id";
1002 idProperty.value = idValue;
1003 paramProperty.utf8name = "param";
1004 paramProperty.value = paramValue;
1005 SetModuleName(exportObj, module->name);
1006 NapiDefineProperty(reinterpret_cast<napi_env>(this), exportObj, idProperty);
1007 NapiDefineProperty(reinterpret_cast<napi_env>(this), exportObj, paramProperty);
1008 MoudleNameLocker nameLocker(module->name);
1009 module->registerCallback(reinterpret_cast<napi_env>(this), JsValueFromLocalValue(exportObj));
1010 napi_value nExport = JsValueFromLocalValue(exportObj);
1011 napi_value exportInstance = nullptr;
1012 napi_status status = napi_get_named_property(
1013 reinterpret_cast<napi_env>(this), nExport, instanceName.c_str(), &exportInstance);
1014 if (status != napi_ok) {
1015 HILOG_ERROR("GetModuleFromName napi_get_named_property status != napi_ok");
1016 }
1017
1018 status = napi_unwrap(reinterpret_cast<napi_env>(this), exportInstance, reinterpret_cast<void**>(instance));
1019 if (status != napi_ok) {
1020 HILOG_ERROR("GetModuleFromName napi_unwrap status != napi_ok");
1021 }
1022 exports = exportObj;
1023 }
1024 return scope.Escape(exports);
1025 }
1026
CreatePromise(NativeDeferred** deferred)1027 napi_value ArkNativeEngine::CreatePromise(NativeDeferred** deferred)
1028 {
1029 panda::EscapeLocalScope scope(vm_);
1030 Local<PromiseCapabilityRef> capability = PromiseCapabilityRef::New(vm_);
1031 if (capability->IsUndefined()) {
1032 return JsValueFromLocalValue(scope.Escape(JSValueRef::Undefined(vm_)));
1033 }
1034 *deferred = new ArkNativeDeferred(this, capability);
1035 Local<JSValueRef> promiseValue = capability->GetPromise(vm_);
1036 return JsValueFromLocalValue(scope.Escape(promiseValue));
1037 }
1038
LoadModuleByName(const std::string& moduleName, bool isAppModule, const std::string& param, const std::string& instanceName, void* instance, const std::string& path)1039 panda::Local<panda::ObjectRef> ArkNativeEngine::LoadModuleByName(const std::string& moduleName, bool isAppModule,
1040 const std::string& param, const std::string& instanceName, void* instance, const std::string& path)
1041 {
1042 panda::EscapeLocalScope scope(vm_);
1043 Local<ObjectRef> exports(JSValueRef::Undefined(vm_));
1044 NativeModuleManager* moduleManager = NativeModuleManager::GetInstance();
1045 std::string errInfo = "";
1046 NativeModule* module = moduleManager->LoadNativeModule(moduleName.c_str(),
1047 path.empty() ? nullptr : path.c_str(), isAppModule, errInfo);
1048 if (module != nullptr) {
1049 Local<ObjectRef> exportObj = ObjectRef::New(vm_);
1050 NapiPropertyDescriptor paramProperty, instanceProperty;
1051 Local<StringRef> paramStr = StringRef::NewFromUtf8(vm_, param.c_str(), param.size());
1052 napi_value paramValue = JsValueFromLocalValue(paramStr);
1053 paramProperty.utf8name = "param";
1054 paramProperty.value = paramValue;
1055 Local<ObjectRef> instanceValue = ObjectRef::New(vm_);
1056 Local<StringRef> key = StringRef::GetNapiWrapperString(vm_);
1057 if (instance == nullptr && instanceValue->Has(vm_, key)) {
1058 Local<ObjectRef> wrapper = instanceValue->Get(vm_, key);
1059 auto ref = reinterpret_cast<NativeReference*>(wrapper->GetNativePointerField(vm_, 0));
1060 wrapper->SetNativePointerField(vm_, 0, nullptr, nullptr, nullptr, 0);
1061 instanceValue->Delete(vm_, key);
1062 delete ref;
1063 } else {
1064 Local<ObjectRef> object = ObjectRef::New(vm_);
1065 NativeReference* ref = nullptr;
1066 Local<JSValueRef> value(instanceValue);
1067 ref = new ArkNativeReference(this, value, 0, true, nullptr, instance, nullptr);
1068
1069 object->SetNativePointerFieldCount(vm_, 1);
1070 object->SetNativePointerField(vm_, 0, ref, nullptr, nullptr, 0);
1071 PropertyAttribute attr(object, true, false, true);
1072 instanceValue->DefineProperty(vm_, key, attr);
1073 }
1074 instanceProperty.utf8name = instanceName.c_str();
1075 instanceProperty.value = JsValueFromLocalValue(instanceValue);
1076 SetModuleName(exportObj, module->name);
1077 NapiDefineProperty(reinterpret_cast<napi_env>(this), exportObj, paramProperty);
1078 NapiDefineProperty(reinterpret_cast<napi_env>(this), exportObj, instanceProperty);
1079
1080 MoudleNameLocker nameLocker(module->name);
1081 module->registerCallback(reinterpret_cast<napi_env>(this), JsValueFromLocalValue(exportObj));
1082 exports = exportObj;
1083 }
1084 return scope.Escape(exports);
1085 }
1086
Loop(LoopMode mode, bool needSync)1087 void ArkNativeEngine::Loop(LoopMode mode, bool needSync)
1088 {
1089 LocalScope scope(vm_);
1090 NativeEngine::Loop(mode, needSync);
1091 panda::JSNApi::ExecutePendingJob(vm_);
1092 }
1093
SetModuleName(Local<ObjectRef> &nativeObj, std::string moduleName)1094 void ArkNativeEngine::SetModuleName(Local<ObjectRef> &nativeObj, std::string moduleName)
1095 {
1096 #ifdef ENABLE_HITRACE
1097 if (ArkNativeEngine::napiProfilerEnabled) {
1098 Local<StringRef> moduleNameStr = StringRef::NewFromUtf8(vm_, moduleName.c_str(), moduleName.size());
1099 Local<StringRef> key = StringRef::NewFromUtf8(vm_, PANDA_MODULE_NAME);
1100 nativeObj->Set(vm_, key, moduleNameStr);
1101 }
1102 #endif
1103 }
1104
ConcurrentCallbackFunc(Local<JSValueRef> result, bool success, void *taskInfo, void *data)1105 static void ConcurrentCallbackFunc(Local<JSValueRef> result, bool success, void *taskInfo, void *data)
1106 {
1107 if (data == nullptr) {
1108 return;
1109 }
1110 auto engine = static_cast<ArkNativeEngine *>(data);
1111 auto concurrentCallbackFunc = engine->GetConcurrentCallbackFunc();
1112 if (concurrentCallbackFunc == nullptr) {
1113 return;
1114 }
1115 napi_env env = reinterpret_cast<napi_env>(engine);
1116 concurrentCallbackFunc(env, ArkNativeEngine::ArkValueToNapiValue(env, result), success, taskInfo);
1117 }
1118
InitTaskPoolThread(NativeEngine* engine, NapiConcurrentCallback callback)1119 bool ArkNativeEngine::InitTaskPoolThread(NativeEngine* engine, NapiConcurrentCallback callback)
1120 {
1121 concurrentCallbackFunc_ = callback;
1122 return JSNApi::InitForConcurrentThread(vm_, ConcurrentCallbackFunc, static_cast<void *>(this));
1123 }
1124
InitTaskPoolThread(napi_env env, NapiConcurrentCallback callback)1125 bool ArkNativeEngine::InitTaskPoolThread(napi_env env, NapiConcurrentCallback callback)
1126 {
1127 concurrentCallbackFunc_ = callback;
1128 return JSNApi::InitForConcurrentThread(vm_, ConcurrentCallbackFunc, static_cast<void *>(this));
1129 }
1130
InitTaskPoolFunc(napi_env env, napi_value func, void* taskInfo)1131 bool ArkNativeEngine::InitTaskPoolFunc(napi_env env, napi_value func, void* taskInfo)
1132 {
1133 LocalScope scope(vm_);
1134 Local<JSValueRef> function = LocalValueFromJsValue(func);
1135 return JSNApi::InitForConcurrentFunction(vm_, function, taskInfo);
1136 }
1137
HasPendingJob() const1138 bool ArkNativeEngine::HasPendingJob() const
1139 {
1140 return JSNApi::HasPendingJob(vm_);
1141 }
1142
IsProfiling() const1143 bool ArkNativeEngine::IsProfiling() const
1144 {
1145 return JSNApi::IsProfiling(vm_);
1146 }
1147
IsExecutingPendingJob() const1148 bool ArkNativeEngine::IsExecutingPendingJob() const
1149 {
1150 return panda::JSNApi::IsExecutingPendingJob(vm_);
1151 }
1152
GetCurrentTaskInfo() const1153 void* ArkNativeEngine::GetCurrentTaskInfo() const
1154 {
1155 return JSNApi::GetCurrentTaskInfo(vm_);
1156 }
1157
ClearCurrentTaskInfo()1158 void ArkNativeEngine::ClearCurrentTaskInfo()
1159 {
1160 JSNApi::ClearCurrentTaskInfo(vm_);
1161 }
1162
TerminateExecution() const1163 void ArkNativeEngine::TerminateExecution() const
1164 {
1165 DFXJSNApi::TerminateExecution(vm_);
1166 }
1167
NotifyTaskBegin() const1168 void ArkNativeEngine::NotifyTaskBegin() const
1169 {
1170 JSNApi::NotifyTaskBegin(vm_);
1171 }
1172
NotifyTaskFinished() const1173 void ArkNativeEngine::NotifyTaskFinished() const
1174 {
1175 JSNApi::NotifyTaskFinished(vm_);
1176 }
1177
CallFunction( napi_value thisVar, napi_value function, napi_value const* argv, size_t argc)1178 napi_value ArkNativeEngine::CallFunction(
1179 napi_value thisVar, napi_value function, napi_value const* argv, size_t argc)
1180 {
1181 if (function == nullptr) {
1182 return nullptr;
1183 }
1184 panda::EscapeLocalScope scope(vm_);
1185 Local<JSValueRef> thisObj = JSValueRef::Undefined(vm_);
1186 if (thisVar != nullptr) {
1187 thisObj = LocalValueFromJsValue(thisVar);
1188 }
1189 Local<FunctionRef> funcObj = LocalValueFromJsValue(function);
1190 std::vector<Local<JSValueRef>> args;
1191 args.reserve(argc);
1192 for (size_t i = 0; i < argc; i++) {
1193 if (argv[i] != nullptr) {
1194 args.emplace_back(LocalValueFromJsValue(argv[i]));
1195 } else {
1196 args.emplace_back(JSValueRef::Undefined(vm_));
1197 }
1198 }
1199
1200 Local<JSValueRef> value = funcObj->Call(vm_, thisObj, args.data(), argc);
1201 if (panda::JSNApi::HasPendingException(vm_)) {
1202 HILOG_ERROR("pending exception when js function called");
1203 HILOG_ERROR("print exception info: ");
1204 panda::JSNApi::PrintExceptionInfo(vm_);
1205 return nullptr;
1206 }
1207
1208 return JsValueFromLocalValue(scope.Escape(value));
1209 }
1210
NapiNewTypedArray(const EcmaVM* vm, NativeTypedArrayType typedArrayType, Local<panda::ArrayBufferRef> arrayBuf, size_t byte_offset, size_t length, napi_value* result)1211 bool ArkNativeEngine::NapiNewTypedArray(const EcmaVM* vm, NativeTypedArrayType typedArrayType,
1212 Local<panda::ArrayBufferRef> arrayBuf,
1213 size_t byte_offset, size_t length, napi_value* result)
1214 {
1215 Local<panda::TypedArrayRef> typedArray;
1216 switch (typedArrayType) {
1217 case NATIVE_INT8_ARRAY:
1218 typedArray = panda::Int8ArrayRef::New(vm, arrayBuf, byte_offset, length);
1219 break;
1220 case NATIVE_UINT8_ARRAY:
1221 typedArray = panda::Uint8ArrayRef::New(vm, arrayBuf, byte_offset, length);
1222 break;
1223 case NATIVE_UINT8_CLAMPED_ARRAY:
1224 typedArray = panda::Uint8ClampedArrayRef::New(vm, arrayBuf, byte_offset, length);
1225 break;
1226 case NATIVE_INT16_ARRAY:
1227 typedArray = panda::Int16ArrayRef::New(vm, arrayBuf, byte_offset, length);
1228 break;
1229 case NATIVE_UINT16_ARRAY:
1230 typedArray = panda::Uint16ArrayRef::New(vm, arrayBuf, byte_offset, length);
1231 break;
1232 case NATIVE_INT32_ARRAY:
1233 typedArray = panda::Int32ArrayRef::New(vm, arrayBuf, byte_offset, length);
1234 break;
1235 case NATIVE_UINT32_ARRAY:
1236 typedArray = panda::Uint32ArrayRef::New(vm, arrayBuf, byte_offset, length);
1237 break;
1238 case NATIVE_FLOAT32_ARRAY:
1239 typedArray = panda::Float32ArrayRef::New(vm, arrayBuf, byte_offset, length);
1240 break;
1241 case NATIVE_FLOAT64_ARRAY:
1242 typedArray = panda::Float64ArrayRef::New(vm, arrayBuf, byte_offset, length);
1243 break;
1244 case NATIVE_BIGINT64_ARRAY:
1245 typedArray = panda::BigInt64ArrayRef::New(vm, arrayBuf, byte_offset, length);
1246 break;
1247 case NATIVE_BIGUINT64_ARRAY:
1248 typedArray = panda::BigUint64ArrayRef::New(vm, arrayBuf, byte_offset, length);
1249 break;
1250 default:
1251 *result = nullptr;
1252 return false;
1253 }
1254 *result = JsValueFromLocalValue(typedArray);
1255 return true;
1256 }
1257
NapiNewSendableTypedArray(const EcmaVM* vm, NativeTypedArrayType typedArrayType, Local<panda::SendableArrayBufferRef> arrayBuf, size_t byte_offset, size_t length, napi_value* result)1258 bool ArkNativeEngine::NapiNewSendableTypedArray(const EcmaVM* vm, NativeTypedArrayType typedArrayType,
1259 Local<panda::SendableArrayBufferRef> arrayBuf,
1260 size_t byte_offset, size_t length, napi_value* result)
1261 {
1262 Local<panda::SendableTypedArrayRef> typedArray;
1263 switch (typedArrayType) {
1264 case NATIVE_INT8_ARRAY:
1265 typedArray = panda::SharedInt8ArrayRef::New(vm, arrayBuf, byte_offset, length);
1266 break;
1267 case NATIVE_UINT8_ARRAY:
1268 typedArray = panda::SharedUint8ArrayRef::New(vm, arrayBuf, byte_offset, length);
1269 break;
1270 case NATIVE_INT16_ARRAY:
1271 typedArray = panda::SharedInt16ArrayRef::New(vm, arrayBuf, byte_offset, length);
1272 break;
1273 case NATIVE_UINT16_ARRAY:
1274 typedArray = panda::SharedUint16ArrayRef::New(vm, arrayBuf, byte_offset, length);
1275 break;
1276 case NATIVE_INT32_ARRAY:
1277 typedArray = panda::SharedInt32ArrayRef::New(vm, arrayBuf, byte_offset, length);
1278 break;
1279 case NATIVE_UINT32_ARRAY:
1280 typedArray = panda::SharedUint32ArrayRef::New(vm, arrayBuf, byte_offset, length);
1281 break;
1282 case NATIVE_FLOAT32_ARRAY:
1283 typedArray = panda::SharedFloat32ArrayRef::New(vm, arrayBuf, byte_offset, length);
1284 break;
1285 case NATIVE_UINT8_CLAMPED_ARRAY:
1286 typedArray = panda::SharedUint8ClampedArrayRef::New(vm, arrayBuf, byte_offset, length);
1287 break;
1288 default:
1289 *result = nullptr;
1290 return false;
1291 }
1292 *result = JsValueFromLocalValue(typedArray);
1293 return true;
1294 }
1295
GetTypedArrayType(panda::Local<panda::TypedArrayRef> typedArray)1296 NativeTypedArrayType ArkNativeEngine::GetTypedArrayType(panda::Local<panda::TypedArrayRef> typedArray)
1297 {
1298 NativeTypedArrayType thisType = NATIVE_INT8_ARRAY;
1299 if (typedArray->IsInt32Array(vm_)) {
1300 thisType = NATIVE_INT32_ARRAY;
1301 } else if (typedArray->IsInt8Array(vm_)) {
1302 thisType = NATIVE_INT8_ARRAY;
1303 } else if (typedArray->IsUint8Array(vm_)) {
1304 thisType = NATIVE_UINT8_ARRAY;
1305 } else if (typedArray->IsUint8ClampedArray(vm_)) {
1306 thisType = NATIVE_UINT8_CLAMPED_ARRAY;
1307 } else if (typedArray->IsInt16Array(vm_)) {
1308 thisType = NATIVE_INT16_ARRAY;
1309 } else if (typedArray->IsUint16Array(vm_)) {
1310 thisType = NATIVE_UINT16_ARRAY;
1311 } else if (typedArray->IsUint32Array(vm_)) {
1312 thisType = NATIVE_UINT32_ARRAY;
1313 } else if (typedArray->IsFloat32Array(vm_)) {
1314 thisType = NATIVE_FLOAT32_ARRAY;
1315 } else if (typedArray->IsFloat64Array(vm_)) {
1316 thisType = NATIVE_FLOAT64_ARRAY;
1317 } else if (typedArray->IsBigInt64Array(vm_)) {
1318 thisType = NATIVE_BIGINT64_ARRAY;
1319 } else if (typedArray->IsBigUint64Array(vm_)) {
1320 thisType = NATIVE_BIGUINT64_ARRAY;
1321 }
1322
1323 return thisType;
1324 }
1325
GetSendableTypedArrayType(panda::Local<panda::SendableTypedArrayRef> typedArray)1326 NativeTypedArrayType ArkNativeEngine::GetSendableTypedArrayType(panda::Local<panda::SendableTypedArrayRef> typedArray)
1327 {
1328 NativeTypedArrayType thisType = NATIVE_INT8_ARRAY;
1329 if (typedArray->IsJSSharedInt8Array(vm_)) {
1330 thisType = NATIVE_INT8_ARRAY;
1331 } else if (typedArray->IsJSSharedUint8Array(vm_)) {
1332 thisType = NATIVE_UINT8_ARRAY;
1333 } else if (typedArray->IsJSSharedInt16Array(vm_)) {
1334 thisType = NATIVE_INT16_ARRAY;
1335 } else if (typedArray->IsJSSharedUint16Array(vm_)) {
1336 thisType = NATIVE_UINT16_ARRAY;
1337 } else if (typedArray->IsJSSharedInt32Array(vm_)) {
1338 thisType = NATIVE_INT32_ARRAY;
1339 } else if (typedArray->IsJSSharedUint32Array(vm_)) {
1340 thisType = NATIVE_UINT32_ARRAY;
1341 } else if (typedArray->IsJSSharedFloat32Array(vm_)) {
1342 thisType = NATIVE_FLOAT32_ARRAY;
1343 } else if (typedArray->IsJSSharedUint8ClampedArray(vm_)) {
1344 thisType = NATIVE_UINT8_CLAMPED_ARRAY;
1345 }
1346
1347 return thisType;
1348 }
1349
1350 /*
1351 * Before: input: 1. @ohos.hilog
1352 2. @system.app (NATIVE_MODULE contains this name)
1353 * After: return: 1.@ohos:hilog
1354 * 2.@native:system.app
1355 */
GetOhmurl(std::string path)1356 std::string ArkNativeEngine::GetOhmurl(std::string path)
1357 {
1358 const std::regex reg("@(ohos|system)\\.(\\S+)");
1359 path.erase(0, path.find_first_not_of(" "));
1360 path.erase(path.find_last_not_of(" ") + 1);
1361 bool ret = std::regex_match(path, reg);
1362 if (!ret) {
1363 HILOG_ERROR("ArkNativeEngine:The module name doesn't comply with the naming rules");
1364 return "";
1365 }
1366 std::string systemModule = path.substr(1);
1367 if (NATIVE_MODULE.count(systemModule)) {
1368 return NATIVE_MODULE_PREFIX + systemModule;
1369 } else {
1370 int pos = static_cast<int>(path.find('.'));
1371 std::string systemKey = path.substr(pos + 1, systemModule.size());
1372 return OHOS_MODULE_PREFIX + systemKey;
1373 }
1374 }
1375
NapiLoadNativeModule(std::string path)1376 Local<JSValueRef> ArkNativeEngine::NapiLoadNativeModule(std::string path)
1377 {
1378 std::string key = GetOhmurl(path);
1379 if (key.size() == 0) {
1380 return JSValueRef::Undefined(vm_);
1381 }
1382 return panda::JSNApi::ExecuteNativeModule(vm_, key);
1383 }
1384
CheckLoadType(const std::string &path)1385 ModuleTypes ArkNativeEngine::CheckLoadType(const std::string &path)
1386 {
1387 if (path[0] == '@') {
1388 return ModuleTypes::NATIVE_MODULE;
1389 } else if (path.find("ets/") == 0) { // ets/xxx/xxx
1390 return ModuleTypes::MODULE_INNER_FILE;
1391 }
1392 return ModuleTypes::UNKNOWN;
1393 }
1394
NapiLoadModule(const char* path, const char* module_info)1395 napi_value ArkNativeEngine::NapiLoadModule(const char* path, const char* module_info)
1396 {
1397 if (path == nullptr) {
1398 HILOG_ERROR("ArkNativeEngine:The module name is empty");
1399 return nullptr;
1400 }
1401 panda::EscapeLocalScope scope(vm_);
1402 Local<JSValueRef> undefObj = JSValueRef::Undefined(vm_);
1403 Local<ObjectRef> exportObj(undefObj);
1404 std::string inputPath(path);
1405 std::string modulePath;
1406 if (module_info != nullptr) {
1407 modulePath = module_info;
1408 }
1409 switch (CheckLoadType(inputPath)) {
1410 case ModuleTypes::NATIVE_MODULE: {
1411 exportObj = NapiLoadNativeModule(inputPath);
1412 break;
1413 }
1414 case ModuleTypes::MODULE_INNER_FILE: {
1415 exportObj = panda::JSNApi::GetModuleNameSpaceFromFile(vm_, inputPath, modulePath);
1416 break;
1417 }
1418 default: {
1419 std::string msg = "ArkNativeEngine:NapiLoadModule input path:" + inputPath + " is invalid.";
1420 ThrowException(msg.c_str());
1421 }
1422 }
1423 if (!exportObj->IsObject(vm_)) {
1424 ThrowException("ArkNativeEngine:NapiLoadModule failed.");
1425 return JsValueFromLocalValue(scope.Escape(undefObj));
1426 }
1427 return JsValueFromLocalValue(scope.Escape(exportObj));
1428 }
1429
NapiLoadModuleWithInfo(const char* path, const char* module_info)1430 napi_value ArkNativeEngine::NapiLoadModuleWithInfo(const char* path, const char* module_info)
1431 {
1432 if (path == nullptr) {
1433 HILOG_ERROR("ArkNativeEngine:The module name is empty");
1434 return nullptr;
1435 }
1436 panda::EscapeLocalScope scope(vm_);
1437 Local<JSValueRef> undefObj = JSValueRef::Undefined(vm_);
1438 Local<ObjectRef> exportObj(undefObj);
1439 std::string inputPath(path);
1440 std::string modulePath;
1441 if (module_info != nullptr) {
1442 modulePath = module_info;
1443 exportObj = panda::JSNApi::GetModuleNameSpaceWithModuleInfo(vm_, inputPath, modulePath);
1444 } else {
1445 exportObj = NapiLoadNativeModule(inputPath);
1446 }
1447
1448 if (!exportObj->IsObject(vm_)) {
1449 ThrowException("ArkNativeEngine:NapiLoadModuleWithInfo failed.");
1450 return JsValueFromLocalValue(scope.Escape(undefObj));
1451 }
1452 return JsValueFromLocalValue(scope.Escape(exportObj));
1453 }
1454
SuspendVMById(uint32_t tid)1455 bool ArkNativeEngine::SuspendVMById(uint32_t tid)
1456 {
1457 #if !defined(PREVIEW) && !defined(IOS_PLATFORM)
1458 return DFXJSNApi::SuspendVMById(vm_, tid);
1459 #else
1460 HILOG_WARN("ARK does not support dfx on windows");
1461 return false;
1462 #endif
1463 }
1464
ResumeVMById(uint32_t tid)1465 void ArkNativeEngine::ResumeVMById(uint32_t tid)
1466 {
1467 #if !defined(PREVIEW) && !defined(IOS_PLATFORM)
1468 DFXJSNApi::ResumeVMById(vm_, tid);
1469 #else
1470 HILOG_WARN("ARK does not support dfx on windows");
1471 return;
1472 #endif
1473 }
1474
SetPackagePath(const std::string appLibPathKey, const std::vector<std::string>& packagePath)1475 void ArkNativeEngine::SetPackagePath(const std::string appLibPathKey, const std::vector<std::string>& packagePath)
1476 {
1477 auto moduleManager = NativeModuleManager::GetInstance();
1478 if (moduleManager && !packagePath.empty()) {
1479 moduleManager->SetAppLibPath(appLibPathKey, packagePath);
1480 }
1481 }
1482
CreateInstance(napi_value constructor, napi_value const *argv, size_t argc)1483 napi_value ArkNativeEngine::CreateInstance(napi_value constructor, napi_value const *argv, size_t argc)
1484 {
1485 if (constructor == nullptr) {
1486 return nullptr;
1487 }
1488 panda::EscapeLocalScope scope(vm_);
1489 Local<FunctionRef> value = LocalValueFromJsValue(constructor);
1490 std::vector<Local<JSValueRef>> args;
1491 args.reserve(argc);
1492 for (size_t i = 0; i < argc; i++) {
1493 if (argv[i] != nullptr) {
1494 args.emplace_back(LocalValueFromJsValue(argv[i]));
1495 } else {
1496 args.emplace_back(JSValueRef::Undefined(vm_));
1497 }
1498 }
1499 Local<JSValueRef> instance = value->Constructor(vm_, args.data(), argc);
1500 Local<ObjectRef> excep = panda::JSNApi::GetUncaughtException(vm_);
1501 if (!excep.IsNull()) {
1502 HILOG_ERROR("ArkNativeEngineImpl::CreateInstance occur Exception");
1503 return nullptr;
1504 }
1505 return JsValueFromLocalValue(scope.Escape(instance));
1506 }
1507
CreateReference(napi_value value, uint32_t initialRefcount, bool flag, NapiNativeFinalize callback, void* data, void* hint, size_t nativeBindingSize)1508 NativeReference* ArkNativeEngine::CreateReference(napi_value value, uint32_t initialRefcount,
1509 bool flag, NapiNativeFinalize callback, void* data, void* hint, size_t nativeBindingSize)
1510 {
1511 return new ArkNativeReference(this, value, initialRefcount, flag, callback, data, hint, false, nativeBindingSize);
1512 }
1513
CreateAsyncReference(napi_value value, uint32_t initialRefcount, bool flag, NapiNativeFinalize callback, void* data, void* hint)1514 NativeReference* ArkNativeEngine::CreateAsyncReference(napi_value value, uint32_t initialRefcount,
1515 bool flag, NapiNativeFinalize callback, void* data, void* hint)
1516 {
1517 return new ArkNativeReference(this, value, initialRefcount, flag, callback, data, hint, true);
1518 }
1519
RunCallbacks(TriggerGCData *triggerGCData)1520 __attribute__((optnone)) void ArkNativeEngine::RunCallbacks(TriggerGCData *triggerGCData)
1521 {
1522 #ifdef ENABLE_HITRACE
1523 StartTrace(HITRACE_TAG_ACE, "RunTriggerGCTaskCallback");
1524 #endif
1525 std::pair<void *, uint8_t> ¶m = *triggerGCData;
1526 JSNApi::TriggerIdleGC(reinterpret_cast<panda::ecmascript::EcmaVM *>(param.first),
1527 static_cast<panda::JSNApi::TRIGGER_IDLE_GC_TYPE>(param.second));
1528 #ifdef ENABLE_HITRACE
1529 FinishTrace(HITRACE_TAG_ACE);
1530 #endif
1531 }
1532
RunCallbacks(ArkFinalizersPack *finalizersPack)1533 __attribute__((optnone)) void ArkNativeEngine::RunCallbacks(ArkFinalizersPack *finalizersPack)
1534 {
1535 #ifdef ENABLE_HITRACE
1536 StartTrace(HITRACE_TAG_ACE, "RunFinalizeCallbacks:" + std::to_string(finalizersPack->GetNumFinalizers()));
1537 #endif
1538 finalizersPack->ProcessAll();
1539 #ifdef ENABLE_HITRACE
1540 FinishTrace(HITRACE_TAG_ACE);
1541 #endif
1542 }
1543
RunAsyncCallbacks(std::vector<RefFinalizer> *finalizers)1544 __attribute__((optnone)) void ArkNativeEngine::RunAsyncCallbacks(std::vector<RefFinalizer> *finalizers)
1545 {
1546 #ifdef ENABLE_HITRACE
1547 StartTrace(HITRACE_TAG_ACE, "RunFinalizeCallbacks:" + std::to_string(finalizers->size()));
1548 #endif
1549 for (auto iter : (*finalizers)) {
1550 NapiNativeFinalize callback = iter.first;
1551 std::tuple<NativeEngine*, void*, void*> ¶m = iter.second;
1552 callback(reinterpret_cast<napi_env>(std::get<0>(param)),
1553 std::get<1>(param), std::get<2>(param)); // 2 is the param.
1554 }
1555 #ifdef ENABLE_HITRACE
1556 FinishTrace(HITRACE_TAG_ACE);
1557 #endif
1558 }
1559
PostFinalizeTasks()1560 void ArkNativeEngine::PostFinalizeTasks()
1561 {
1562 if (IsInDestructor()) {
1563 return;
1564 }
1565 if (!pendingAsyncFinalizers_.empty()) {
1566 uv_work_t *asynWork = new uv_work_t;
1567 std::vector<RefFinalizer> *asyncFinalizers = new std::vector<RefFinalizer>();
1568 asyncFinalizers->swap(pendingAsyncFinalizers_);
1569 asynWork->data = reinterpret_cast<void *>(asyncFinalizers);
1570
1571 int ret = uv_queue_work_with_qos(GetUVLoop(), asynWork, [](uv_work_t *asynWork) {
1572 std::vector<RefFinalizer> *finalizers = reinterpret_cast<std::vector<RefFinalizer> *>(asynWork->data);
1573 RunAsyncCallbacks(finalizers);
1574 HILOG_DEBUG("uv_queue_work async running ");
1575 delete finalizers;
1576 }, [](uv_work_t *asynWork, int32_t) {
1577 delete asynWork;
1578 }, uv_qos_t(napi_qos_background));
1579 if (ret != 0) {
1580 HILOG_ERROR("uv_queue_work fail ret '%{public}d'", ret);
1581 RunAsyncCallbacks(asyncFinalizers);
1582 delete asynWork;
1583 delete asyncFinalizers;
1584 }
1585 }
1586 if (arkFinalizersPack_.Empty()) {
1587 return;
1588 }
1589 ArkFinalizersPack *finalizersPack = new ArkFinalizersPack();
1590 std::swap(arkFinalizersPack_, *finalizersPack);
1591 if (!IsMainThread()) {
1592 panda::JsiNativeScope nativeScope(vm_);
1593 RunCallbacks(finalizersPack);
1594 delete finalizersPack;
1595 return;
1596 }
1597 size_t bindingSize = finalizersPack->GetTotalNativeBindingSize();
1598 if (pendingFinalizersPackNativeBindingSize_ > FINALIZERS_PACK_PENDING_NATIVE_BINDING_SIZE_THRESHOLD &&
1599 bindingSize > 0) {
1600 HILOG_DEBUG("Pending Finalizers NativeBindingSize '%{public}zu' large than '%{public}zu', process sync.",
1601 pendingFinalizersPackNativeBindingSize_, FINALIZERS_PACK_PENDING_NATIVE_BINDING_SIZE_THRESHOLD);
1602 panda::JsiNativeScope nativeScope(vm_);
1603 RunCallbacks(finalizersPack);
1604 delete finalizersPack;
1605 return;
1606 }
1607 uv_work_t *syncWork = new uv_work_t;
1608 finalizersPack->RegisterFinishNotify([this] (size_t totalNativeBindingSize) {
1609 this->DecreasePendingFinalizersPackNativeBindingSize(totalNativeBindingSize);
1610 });
1611 IncreasePendingFinalizersPackNativeBindingSize(bindingSize);
1612
1613 syncWork->data = reinterpret_cast<void *>(finalizersPack);
1614 int ret = uv_queue_work_with_qos(GetUVLoop(), syncWork, [](uv_work_t *) {}, [](uv_work_t *syncWork, int32_t) {
1615 ArkFinalizersPack *finalizersPack = reinterpret_cast<ArkFinalizersPack*>(syncWork->data);
1616 RunCallbacks(finalizersPack);
1617 HILOG_DEBUG("uv_queue_work running");
1618 delete syncWork;
1619 delete finalizersPack;
1620 }, uv_qos_t(napi_qos_background));
1621 if (ret != 0) {
1622 HILOG_ERROR("uv_queue_work fail ret '%{public}d'", ret);
1623 panda::JsiNativeScope nativeScope(vm_);
1624 RunCallbacks(finalizersPack);
1625 delete syncWork;
1626 delete finalizersPack;
1627 }
1628 }
1629
RunCallbacks(AsyncNativeCallbacksPack *callbacksPack)1630 __attribute__((optnone)) void ArkNativeEngine::RunCallbacks(AsyncNativeCallbacksPack *callbacksPack)
1631 {
1632 #ifdef ENABLE_HITRACE
1633 StartTrace(HITRACE_TAG_ACE, "RunNativeCallbacks:" + std::to_string(callbacksPack->GetNumCallBacks()));
1634 #endif
1635 callbacksPack->ProcessAll();
1636 #ifdef ENABLE_HITRACE
1637 FinishTrace(HITRACE_TAG_ACE);
1638 #endif
1639 }
1640
PostAsyncTask(AsyncNativeCallbacksPack *callBacksPack)1641 void ArkNativeEngine::PostAsyncTask(AsyncNativeCallbacksPack *callBacksPack)
1642 {
1643 if (IsInDestructor()) {
1644 delete callBacksPack;
1645 return;
1646 }
1647 uv_work_t *syncWork = new uv_work_t;
1648 syncWork->data = reinterpret_cast<void *>(callBacksPack);
1649
1650 int ret = uv_queue_work_with_qos(GetUVLoop(), syncWork, [](uv_work_t *) {}, [](uv_work_t *syncWork, int32_t) {
1651 AsyncNativeCallbacksPack *finalizers = reinterpret_cast<AsyncNativeCallbacksPack*>(syncWork->data);
1652 RunCallbacks(finalizers);
1653 HILOG_DEBUG("uv_queue_work running");
1654 delete syncWork;
1655 delete finalizers;
1656 }, uv_qos_t(napi_qos_background));
1657 if (ret != 0) {
1658 HILOG_ERROR("uv_queue_work fail ret '%{public}d'", ret);
1659 panda::JsiNativeScope nativeScope(vm_);
1660 RunCallbacks(callBacksPack);
1661 delete callBacksPack;
1662 delete syncWork;
1663 }
1664 }
1665
PostTriggerGCTask(TriggerGCData& data)1666 void ArkNativeEngine::PostTriggerGCTask(TriggerGCData& data)
1667 {
1668 TriggerGCData *triggerGCData = new TriggerGCData(data);
1669 uv_work_t *syncWork = new uv_work_t;
1670 syncWork->data = reinterpret_cast<void *>(triggerGCData);
1671 int ret = uv_queue_work_with_qos(GetUVLoop(), syncWork, [](uv_work_t *) {}, [](uv_work_t *syncWork, int32_t) {
1672 auto triggerGCData = reinterpret_cast<TriggerGCData *>(syncWork->data);
1673 RunCallbacks(triggerGCData);
1674 delete syncWork;
1675 delete triggerGCData;
1676 }, uv_qos_t(napi_qos_user_initiated));
1677 if (ret != 0) {
1678 HILOG_ERROR("uv_queue_work fail ret '%{public}d'", ret);
1679 RunCallbacks(triggerGCData);
1680 delete syncWork;
1681 delete triggerGCData;
1682 }
1683 }
1684
1685 #if defined(OHOS_PLATFORM) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
SetAttribute(bool isLimitedWorker, panda::RuntimeOption &option)1686 void ArkNativeEngine::SetAttribute(bool isLimitedWorker, panda::RuntimeOption &option)
1687 {
1688 int arkProperties = OHOS::system::GetIntParameter<int>("persist.ark.properties", -1);
1689 std::string bundleName = OHOS::system::GetParameter("persist.ark.arkbundlename", "");
1690 std::string memConfigProperty = OHOS::system::GetParameter("persist.ark.mem_config_property", "");
1691 size_t gcThreadNum = OHOS::system::GetUintParameter<size_t>("persist.ark.gcthreads", 7);
1692 size_t longPauseTime = OHOS::system::GetUintParameter<size_t>("persist.ark.longpausetime", 40);
1693 bool asmInterpreterEnabled = OHOS::system::GetBoolParameter("persist.ark.asminterpreter", true);
1694 std::string asmOpcodeDisableRange = OHOS::system::GetParameter("persist.ark.asmopcodedisablerange", "");
1695 bool builtinsLazyEnabled = OHOS::system::GetBoolParameter("persist.ark.enablebuiltinslazy", true);
1696 option.SetEnableBuiltinsLazy(builtinsLazyEnabled);
1697 option.SetArkProperties(arkProperties);
1698 option.SetArkBundleName(bundleName);
1699 option.SetMemConfigProperty(memConfigProperty);
1700 option.SetGcThreadNum(gcThreadNum);
1701 option.SetLongPauseTime(longPauseTime);
1702 option.SetEnableAsmInterpreter(asmInterpreterEnabled);
1703 option.SetAsmOpcodeDisableRange(asmOpcodeDisableRange);
1704 option.SetIsWorker();
1705 option.SetIsRestrictedWorker(isLimitedWorker);
1706 HILOG_DEBUG("ArkNativeEngineImpl::CreateRuntimeFunc ark properties = %{public}d, bundlename = %{public}s",
1707 arkProperties, bundleName.c_str());
1708 }
1709 #endif
1710
CreateRuntimeFunc(NativeEngine* engine, void* jsEngine, bool isLimitedWorker)1711 NativeEngine* ArkNativeEngine::CreateRuntimeFunc(NativeEngine* engine, void* jsEngine, bool isLimitedWorker)
1712 {
1713 panda::RuntimeOption option;
1714 #if defined(OHOS_PLATFORM) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
1715 SetAttribute(isLimitedWorker, option);
1716 #endif
1717 option.SetGcType(panda::RuntimeOption::GC_TYPE::GEN_GC);
1718 const int64_t poolSize = 0x1000000;
1719 option.SetGcPoolSize(poolSize);
1720 #if !defined(PREVIEW) && !defined(IOS_PLATFORM)
1721 option.SetLogLevel(panda::RuntimeOption::LOG_LEVEL::INFO);
1722 #endif
1723 option.SetDebuggerLibraryPath("");
1724 EcmaVM* vm = panda::JSNApi::CreateJSVM(option);
1725 if (vm == nullptr) {
1726 return nullptr;
1727 }
1728 // worker adaptation mergeabc
1729 const panda::ecmascript::EcmaVM* hostVM = reinterpret_cast<ArkNativeEngine*>(engine)->GetEcmaVm();
1730 panda::JSNApi::SynchronizVMInfo(vm, hostVM);
1731 ArkNativeEngine* arkEngine = new ArkNativeEngine(vm, jsEngine, isLimitedWorker);
1732 // init callback
1733 arkEngine->RegisterWorkerFunction(engine);
1734 arkEngine->SetHostEngine(engine);
1735 // sync apiVersion
1736 arkEngine->SetApiVersion(engine->GetApiVersion());
1737
1738 auto cleanEnv = [vm]() {
1739 if (vm != nullptr) {
1740 HILOG_DEBUG("cleanEnv is called");
1741 panda::JSNApi::DestroyJSVM(vm);
1742 }
1743 };
1744 arkEngine->SetCleanEnv(cleanEnv);
1745 if (hostVM != nullptr) {
1746 panda::JSNApi::AddWorker(const_cast<EcmaVM*>(hostVM), vm);
1747 }
1748 return arkEngine;
1749 }
1750
CreateRuntime(bool isLimitedWorker)1751 void* ArkNativeEngine::CreateRuntime(bool isLimitedWorker)
1752 {
1753 return ArkNativeEngine::CreateRuntimeFunc(this, jsEngine_, isLimitedWorker);
1754 }
1755
SetJsDumpThresholds(size_t thresholds)1756 void ArkNativeEngine::SetJsDumpThresholds(size_t thresholds)
1757 {
1758 DFXJSNApi::SetJsDumpThresholds(vm_, thresholds);
1759 }
1760
SetAppFreezeFilterCallback(AppFreezeFilterCallback callback)1761 void ArkNativeEngine::SetAppFreezeFilterCallback(AppFreezeFilterCallback callback)
1762 {
1763 DFXJSNApi::SetAppFreezeFilterCallback(vm_, callback);
1764 }
1765
StartCpuProfiler(const std::string& fileName)1766 void ArkNativeEngine::StartCpuProfiler(const std::string& fileName)
1767 {
1768 JSNApi::SetNativePtrGetter(vm_, reinterpret_cast<void*>(ArkNativeEngine::GetNativePtrCallBack));
1769 DFXJSNApi::StartCpuProfilerForFile(vm_, fileName);
1770 }
1771
StopCpuProfiler()1772 void ArkNativeEngine::StopCpuProfiler()
1773 {
1774 DFXJSNApi::StopCpuProfilerForFile(vm_);
1775 JSNApi::SetNativePtrGetter(vm_, nullptr);
1776 }
1777
ResumeVM()1778 void ArkNativeEngine::ResumeVM()
1779 {
1780 DFXJSNApi::ResumeVM(vm_);
1781 }
1782
SuspendVM()1783 bool ArkNativeEngine::SuspendVM()
1784 {
1785 return DFXJSNApi::SuspendVM(vm_);
1786 }
1787
IsSuspended()1788 bool ArkNativeEngine::IsSuspended()
1789 {
1790 return DFXJSNApi::IsSuspended(vm_);
1791 }
1792
CheckSafepoint()1793 bool ArkNativeEngine::CheckSafepoint()
1794 {
1795 return DFXJSNApi::CheckSafepoint(vm_);
1796 }
1797
GetCurrentModuleInfo(std::string& moduleName, std::string& fileName, bool needRecordName)1798 void ArkNativeEngine::GetCurrentModuleInfo(std::string& moduleName, std::string& fileName, bool needRecordName)
1799 {
1800 LocalScope scope(vm_);
1801 std::pair<std::string, std::string> moduleInfo = panda::JSNApi::GetCurrentModuleInfo(vm_, needRecordName);
1802 moduleName = moduleInfo.first; // if needRecordName is true, then moduleName is recordName.
1803 fileName = moduleInfo.second;
1804 }
1805
GetIsBundle()1806 bool ArkNativeEngine::GetIsBundle()
1807 {
1808 LocalScope scope(vm_);
1809 return panda::JSNApi::IsBundle(vm_);
1810 }
1811
GetIsNormalizedOhmUrlPack()1812 bool ArkNativeEngine::GetIsNormalizedOhmUrlPack()
1813 {
1814 LocalScope scope(vm_);
1815 return panda::JSNApi::IsNormalizedOhmUrlPack(vm_);
1816 }
1817
GetIsDebugModeEnabled()1818 bool ArkNativeEngine::GetIsDebugModeEnabled()
1819 {
1820 LocalScope scope(vm_);
1821 return panda::JSNApi::IsDebugModeEnabled(vm_);
1822 }
1823
GetBundleName()1824 std::string ArkNativeEngine::GetBundleName()
1825 {
1826 LocalScope scope(vm_);
1827 return panda::JSNApi::GetBundleName(vm_);
1828 }
1829
GetPkgName(const std::string &moduleName)1830 std::string ArkNativeEngine::GetPkgName(const std::string &moduleName)
1831 {
1832 LocalScope scope(vm_);
1833 return panda::JSNApi::GetPkgName(vm_, moduleName);
1834 }
1835
GetProcessStartRealTime()1836 int ArkNativeEngine::GetProcessStartRealTime()
1837 {
1838 LocalScope scope(vm_);
1839 return panda::JSNApi::GetStartRealTime(vm_);
1840 }
1841
IsExecuteModuleInAbcFile(std::string bundleName, std::string moduleName, std::string ohmurl)1842 bool ArkNativeEngine::IsExecuteModuleInAbcFile(std::string bundleName, std::string moduleName, std::string ohmurl)
1843 {
1844 LocalScope scope(vm_);
1845 return panda::JSNApi::IsExecuteModuleInAbcFile(vm_, bundleName, moduleName, ohmurl);
1846 }
1847
ValueToNapiValue(JSValueWrapper& value)1848 napi_value ArkNativeEngine::ValueToNapiValue(JSValueWrapper& value)
1849 {
1850 Global<JSValueRef> arkValue = value;
1851 return JsValueFromLocalValue(arkValue.ToLocal(vm_));
1852 }
1853
ArkValueToNapiValue(napi_env env, Local<JSValueRef> value)1854 napi_value ArkNativeEngine::ArkValueToNapiValue(napi_env env, Local<JSValueRef> value)
1855 {
1856 return JsValueFromLocalValue(value);
1857 }
1858
GetSourceCodeInfo(napi_value value, ErrorPos pos)1859 std::string ArkNativeEngine::GetSourceCodeInfo(napi_value value, ErrorPos pos)
1860 {
1861 if (value == nullptr || pos.first == 0) {
1862 return "";
1863 }
1864
1865 LocalScope scope(vm_);
1866 Local<panda::FunctionRef> func = LocalValueFromJsValue(value);
1867 uint32_t line = pos.first;
1868 uint32_t column = pos.second;
1869 Local<panda::StringRef> sourceCode = func->GetSourceCode(vm_, line);
1870 std::string sourceCodeStr = sourceCode->ToString(vm_);
1871 if (sourceCodeStr.empty()) {
1872 return "";
1873 }
1874 std::string sourceCodeInfo = "SourceCode:\n";
1875 sourceCodeInfo.append(sourceCodeStr).append("\n");
1876 for (uint32_t k = 1; k < column; k++) {
1877 sourceCodeInfo.push_back(' ');
1878 }
1879 sourceCodeInfo.append("^\n");
1880 return sourceCodeInfo;
1881 }
1882
TriggerFatalException(panda::Local<panda::JSValueRef> exceptionValue)1883 void ArkNativeEngine::TriggerFatalException(panda::Local<panda::JSValueRef> exceptionValue)
1884 {
1885 panda::JSNApi::ThrowException(GetEcmaVm(), exceptionValue);
1886 HandleUncaughtException();
1887 }
1888
AdjustExternalMemory(int64_t ChangeInBytes, int64_t* AdjustedValue)1889 bool ArkNativeEngine::AdjustExternalMemory(int64_t ChangeInBytes, int64_t* AdjustedValue)
1890 {
1891 return true;
1892 }
1893
SetPromiseRejectCallback(NativeReference* rejectCallbackRef, NativeReference* checkCallbackRef)1894 void ArkNativeEngine::SetPromiseRejectCallback(NativeReference* rejectCallbackRef, NativeReference* checkCallbackRef)
1895 {
1896 if (rejectCallbackRef == nullptr || checkCallbackRef == nullptr) {
1897 HILOG_ERROR("rejectCallbackRef or checkCallbackRef is nullptr");
1898 return;
1899 }
1900 promiseRejectCallbackRef_ = rejectCallbackRef;
1901 checkCallbackRef_ = checkCallbackRef;
1902 JSNApi::SetHostPromiseRejectionTracker(vm_, reinterpret_cast<void*>(PromiseRejectCallback),
1903 reinterpret_cast<void*>(this));
1904 }
1905
PromiseRejectCallback(void* info)1906 void ArkNativeEngine::PromiseRejectCallback(void* info)
1907 {
1908 panda::PromiseRejectInfo* promiseRejectInfo = reinterpret_cast<panda::PromiseRejectInfo*>(info);
1909 ArkNativeEngine* env = reinterpret_cast<ArkNativeEngine*>(promiseRejectInfo->GetData());
1910
1911 if (env == nullptr) {
1912 HILOG_ERROR("engine is nullptr");
1913 return;
1914 }
1915
1916 if (env->promiseRejectCallbackRef_ == nullptr || env->checkCallbackRef_ == nullptr) {
1917 HILOG_ERROR("promiseRejectCallbackRef or checkCallbackRef is nullptr");
1918 return;
1919 }
1920 panda::ecmascript::EcmaVM* vm = const_cast<EcmaVM*>(env->GetEcmaVm());
1921 LocalScope scope(vm);
1922 Local<JSValueRef> promise = promiseRejectInfo->GetPromise();
1923 Local<JSValueRef> reason = promiseRejectInfo->GetReason();
1924 panda::PromiseRejectInfo::PROMISE_REJECTION_EVENT operation = promiseRejectInfo->GetOperation();
1925
1926 Local<JSValueRef> type(IntegerRef::New(vm, static_cast<int32_t>(operation)));
1927
1928 Local<JSValueRef> args[] = {type, promise, reason};
1929
1930 napi_value promiseNapiRejectCallback = env->promiseRejectCallbackRef_->Get(env);
1931 Local<FunctionRef> promiseRejectCallback = LocalValueFromJsValue(promiseNapiRejectCallback);
1932 if (!promiseRejectCallback.IsEmpty()) {
1933 promiseRejectCallback->Call(vm, JSValueRef::Undefined(vm), args, 3); // 3 args size
1934 }
1935
1936 if (operation == panda::PromiseRejectInfo::PROMISE_REJECTION_EVENT::REJECT) {
1937 Local<JSValueRef> checkCallback = LocalValueFromJsValue(env->checkCallbackRef_->Get(env));
1938 if (!checkCallback.IsEmpty()) {
1939 JSNApi::SetHostEnqueueJob(vm, checkCallback, panda::QueueType::QUEUE_SCRIPT);
1940 }
1941 }
1942 }
1943
DumpHeapSnapshot(const std::string& path, bool isVmMode, DumpFormat dumpFormat, bool isPrivate, bool captureNumericValue)1944 void ArkNativeEngine::DumpHeapSnapshot(const std::string& path, bool isVmMode, DumpFormat dumpFormat,
1945 bool isPrivate, bool captureNumericValue)
1946 {
1947 panda::ecmascript::DumpSnapShotOption dumpOption;
1948 dumpOption.isVmMode = isVmMode;
1949 dumpOption.isSync = true;
1950 if (dumpFormat == DumpFormat::JSON) {
1951 dumpOption.dumpFormat = panda::ecmascript::DumpFormat::JSON;
1952 dumpOption.isPrivate = isPrivate;
1953 dumpOption.captureNumericValue = captureNumericValue;
1954 DFXJSNApi::DumpHeapSnapshot(vm_, path, dumpOption);
1955 }
1956 if (dumpFormat == DumpFormat::BINARY) {
1957 dumpOption.dumpFormat = panda::ecmascript::DumpFormat::BINARY;
1958 DFXJSNApi::DumpHeapSnapshot(vm_, path, dumpOption);
1959 }
1960 if (dumpFormat == DumpFormat::OTHER) {
1961 dumpOption.dumpFormat = panda::ecmascript::DumpFormat::OTHER;
1962 DFXJSNApi::DumpHeapSnapshot(vm_, path, dumpOption); // 2:enum is 2
1963 }
1964 }
1965
DumpCpuProfile()1966 void ArkNativeEngine::DumpCpuProfile()
1967 {
1968 DFXJSNApi::DumpCpuProfile(vm_);
1969 }
1970
DumpHeapSnapshot(bool isVmMode, DumpFormat dumpFormat, bool isPrivate, bool isFullGC)1971 void ArkNativeEngine::DumpHeapSnapshot(bool isVmMode, DumpFormat dumpFormat, bool isPrivate, bool isFullGC)
1972 {
1973 panda::ecmascript::DumpSnapShotOption dumpOption;
1974 dumpOption.isVmMode = isVmMode;
1975 dumpOption.isPrivate = isPrivate;
1976 dumpOption.isFullGC = isFullGC;
1977 dumpOption.isSync = false;
1978 if (dumpFormat == DumpFormat::JSON) {
1979 dumpOption.dumpFormat = panda::ecmascript::DumpFormat::JSON;
1980 DFXJSNApi::DumpHeapSnapshot(vm_, dumpOption);
1981 }
1982 if (dumpFormat == DumpFormat::BINARY) {
1983 dumpOption.dumpFormat = panda::ecmascript::DumpFormat::BINARY;
1984 DFXJSNApi::DumpHeapSnapshot(vm_, dumpOption);
1985 }
1986 if (dumpFormat == DumpFormat::OTHER) {
1987 dumpOption.dumpFormat = panda::ecmascript::DumpFormat::OTHER;
1988 DFXJSNApi::DumpHeapSnapshot(vm_, dumpOption);
1989 }
1990 }
1991
BuildNativeAndJsStackTrace(std::string& stackTraceStr)1992 bool ArkNativeEngine::BuildNativeAndJsStackTrace(std::string& stackTraceStr)
1993 {
1994 #if !defined(PREVIEW) && !defined(IOS_PLATFORM)
1995 return DFXJSNApi::BuildNativeAndJsStackTrace(vm_, stackTraceStr);
1996 #else
1997 HILOG_WARN("ARK does not support dfx on windows");
1998 return false;
1999 #endif
2000 }
2001
BuildJsStackTrace(std::string& stackTraceStr)2002 bool ArkNativeEngine::BuildJsStackTrace(std::string& stackTraceStr)
2003 {
2004 #if !defined(PREVIEW) && !defined(IOS_PLATFORM)
2005 return DFXJSNApi::BuildJsStackTrace(vm_, stackTraceStr);
2006 #else
2007 HILOG_WARN("ARK does not support dfx on windows");
2008 return false;
2009 #endif
2010 }
2011
BuildJsStackInfoListWithCustomDepth(std::vector<JsFrameInfo>& jsFrames)2012 bool ArkNativeEngine::BuildJsStackInfoListWithCustomDepth(std::vector<JsFrameInfo>& jsFrames)
2013 {
2014 #if !defined(PREVIEW) && !defined(IOS_PLATFORM)
2015 bool sign = DFXJSNApi::BuildJsStackInfoList(vm_, gettid(), jsFrames);
2016 return sign;
2017 #else
2018 HILOG_WARN("ARK does not support dfx on windows");
2019 return false;
2020 #endif
2021 }
2022
DeleteWorker(NativeEngine* workerEngine)2023 bool ArkNativeEngine::DeleteWorker(NativeEngine* workerEngine)
2024 {
2025 if (workerEngine != nullptr) {
2026 #if !defined(PREVIEW)
2027 const panda::ecmascript::EcmaVM* workerVM = reinterpret_cast<ArkNativeEngine*>(workerEngine)->GetEcmaVm();
2028 if (workerVM != nullptr) {
2029 return panda::JSNApi::DeleteWorker(vm_, const_cast<EcmaVM*>(workerVM));
2030 }
2031 #else
2032 HILOG_WARN("ARK does not support dfx on windows");
2033 #endif
2034 return false;
2035 }
2036 return false;
2037 }
2038
StartHeapTracking(double timeInterval, bool isVmMode)2039 bool ArkNativeEngine::StartHeapTracking(double timeInterval, bool isVmMode)
2040 {
2041 return DFXJSNApi::StartHeapTracking(vm_, timeInterval, isVmMode);
2042 }
2043
StopHeapTracking(const std::string &filePath)2044 bool ArkNativeEngine::StopHeapTracking(const std::string &filePath)
2045 {
2046 return DFXJSNApi::StopHeapTracking(vm_, filePath);
2047 }
2048
2049 #if !defined(PREVIEW)
PrintStatisticResult()2050 void ArkNativeEngine::PrintStatisticResult()
2051 {
2052 DFXJSNApi::PrintStatisticResult(vm_);
2053 }
2054
StartRuntimeStat()2055 void ArkNativeEngine::StartRuntimeStat()
2056 {
2057 DFXJSNApi::StartRuntimeStat(vm_);
2058 }
2059
StopRuntimeStat()2060 void ArkNativeEngine::StopRuntimeStat()
2061 {
2062 DFXJSNApi::StopRuntimeStat(vm_);
2063 }
2064
GetArrayBufferSize()2065 size_t ArkNativeEngine::GetArrayBufferSize()
2066 {
2067 return DFXJSNApi::GetArrayBufferSize(vm_);
2068 }
2069
GetHeapTotalSize()2070 size_t ArkNativeEngine::GetHeapTotalSize()
2071 {
2072 return DFXJSNApi::GetHeapTotalSize(vm_);
2073 }
2074
GetHeapUsedSize()2075 size_t ArkNativeEngine::GetHeapUsedSize()
2076 {
2077 return DFXJSNApi::GetHeapUsedSize(vm_);
2078 }
2079
GetHeapObjectSize()2080 size_t ArkNativeEngine::GetHeapObjectSize()
2081 {
2082 return DFXJSNApi::GetHeapObjectSize(vm_);
2083 }
2084
GetHeapLimitSize()2085 size_t ArkNativeEngine::GetHeapLimitSize()
2086 {
2087 return DFXJSNApi::GetHeapLimitSize(vm_);
2088 }
2089
GetProcessHeapLimitSize()2090 size_t ArkNativeEngine::GetProcessHeapLimitSize()
2091 {
2092 return DFXJSNApi::GetProcessHeapLimitSize();
2093 }
2094
GetGCCount()2095 size_t ArkNativeEngine::GetGCCount()
2096 {
2097 return DFXJSNApi::GetGCCount(vm_);
2098 }
2099
GetGCDuration()2100 size_t ArkNativeEngine::GetGCDuration()
2101 {
2102 return DFXJSNApi::GetGCDuration(vm_);
2103 }
2104
GetAccumulatedAllocateSize()2105 size_t ArkNativeEngine::GetAccumulatedAllocateSize()
2106 {
2107 return DFXJSNApi::GetAccumulatedAllocateSize(vm_);
2108 }
2109
GetAccumulatedFreeSize()2110 size_t ArkNativeEngine::GetAccumulatedFreeSize()
2111 {
2112 return DFXJSNApi::GetAccumulatedFreeSize(vm_);
2113 }
2114
GetFullGCLongTimeCount()2115 size_t ArkNativeEngine::GetFullGCLongTimeCount()
2116 {
2117 return DFXJSNApi::GetFullGCLongTimeCount(vm_);
2118 }
2119
NotifyApplicationState(bool inBackground)2120 void ArkNativeEngine::NotifyApplicationState(bool inBackground)
2121 {
2122 DFXJSNApi::NotifyApplicationState(vm_, inBackground);
2123 arkIdleMonitor_->NotifyChangeBackgroundState(inBackground);
2124 }
2125
NotifyIdleStatusControl(std::function<void(bool)> callback)2126 void ArkNativeEngine::NotifyIdleStatusControl(std::function<void(bool)> callback)
2127 {
2128 DFXJSNApi::NotifyIdleStatusControl(vm_, callback);
2129 }
2130
NotifyIdleTime(int idleMicroSec)2131 void ArkNativeEngine::NotifyIdleTime(int idleMicroSec)
2132 {
2133 DFXJSNApi::NotifyIdleTime(vm_, idleMicroSec);
2134 }
2135
NotifyMemoryPressure(bool inHighMemoryPressure)2136 void ArkNativeEngine::NotifyMemoryPressure(bool inHighMemoryPressure)
2137 {
2138 DFXJSNApi::NotifyMemoryPressure(vm_, inHighMemoryPressure);
2139 }
2140
NotifyForceExpandState(int32_t value)2141 void ArkNativeEngine::NotifyForceExpandState(int32_t value)
2142 {
2143 switch (ForceExpandState(value)) {
2144 case ForceExpandState::FINISH_COLD_START:
2145 DFXJSNApi::NotifyFinishColdStart(vm_, true);
2146 break;
2147 case ForceExpandState::START_HIGH_SENSITIVE:
2148 DFXJSNApi::NotifyHighSensitive(vm_, true);
2149 break;
2150 case ForceExpandState::FINISH_HIGH_SENSITIVE:
2151 DFXJSNApi::NotifyHighSensitive(vm_, false);
2152 break;
2153 default:
2154 HILOG_ERROR("Invalid Force Expand State: %{public}d.", value);
2155 break;
2156 }
2157 }
2158 #else
PrintStatisticResult()2159 void ArkNativeEngine::PrintStatisticResult()
2160 {
2161 HILOG_WARN("ARK does not support dfx on windows");
2162 }
2163
StartRuntimeStat()2164 void ArkNativeEngine::StartRuntimeStat()
2165 {
2166 HILOG_WARN("ARK does not support dfx on windows");
2167 }
2168
StopRuntimeStat()2169 void ArkNativeEngine::StopRuntimeStat()
2170 {
2171 HILOG_WARN("ARK does not support dfx on windows");
2172 }
2173
GetArrayBufferSize()2174 size_t ArkNativeEngine::GetArrayBufferSize()
2175 {
2176 HILOG_WARN("ARK does not support dfx on windows");
2177 return 0;
2178 }
2179
GetHeapTotalSize()2180 size_t ArkNativeEngine::GetHeapTotalSize()
2181 {
2182 HILOG_WARN("ARK does not support dfx on windows");
2183 return 0;
2184 }
2185
GetHeapUsedSize()2186 size_t ArkNativeEngine::GetHeapUsedSize()
2187 {
2188 HILOG_WARN("ARK does not support dfx on windows");
2189 return 0;
2190 }
2191
GetHeapObjectSize()2192 size_t ArkNativeEngine::GetHeapObjectSize()
2193 {
2194 HILOG_WARN("ARK does not support dfx on windows");
2195 return 0;
2196 }
2197
GetHeapLimitSize()2198 size_t ArkNativeEngine::GetHeapLimitSize()
2199 {
2200 HILOG_WARN("ARK does not support dfx on windows");
2201 return 0;
2202 }
2203
GetProcessHeapLimitSize()2204 size_t ArkNativeEngine::GetProcessHeapLimitSize()
2205 {
2206 HILOG_WARN("ARK does not support dfx on windows");
2207 return 0;
2208 }
2209
GetGCCount()2210 size_t ArkNativeEngine::GetGCCount()
2211 {
2212 HILOG_WARN("ARK does not support dfx on windows");
2213 return 0;
2214 }
2215
GetGCDuration()2216 size_t ArkNativeEngine::GetGCDuration()
2217 {
2218 HILOG_WARN("ARK does not support dfx on windows");
2219 return 0;
2220 }
2221
GetAccumulatedAllocateSize()2222 size_t ArkNativeEngine::GetAccumulatedAllocateSize()
2223 {
2224 HILOG_WARN("ARK does not support dfx on windows");
2225 return 0;
2226 }
2227
GetAccumulatedFreeSize()2228 size_t ArkNativeEngine::GetAccumulatedFreeSize()
2229 {
2230 HILOG_WARN("ARK does not support dfx on windows");
2231 return 0;
2232 }
2233
GetFullGCLongTimeCount()2234 size_t ArkNativeEngine::GetFullGCLongTimeCount()
2235 {
2236 HILOG_WARN("ARK does not support dfx on windows");
2237 return 0;
2238 }
2239
NotifyApplicationState([[maybe_unused]] bool inBackground)2240 void ArkNativeEngine::NotifyApplicationState([[maybe_unused]] bool inBackground)
2241 {
2242 HILOG_WARN("ARK does not support dfx on windows");
2243 }
2244
NotifyIdleStatusControl([[maybe_unused]] std::function<void(bool)> callback)2245 void ArkNativeEngine::NotifyIdleStatusControl([[maybe_unused]] std::function<void(bool)> callback)
2246 {
2247 HILOG_WARN("ARK does not support dfx on windows");
2248 }
2249
NotifyIdleTime([[maybe_unused]] int idleMicroSec)2250 void ArkNativeEngine::NotifyIdleTime([[maybe_unused]] int idleMicroSec)
2251 {
2252 HILOG_WARN("ARK does not support dfx on windows");
2253 }
2254
NotifyMemoryPressure([[maybe_unused]] bool inHighMemoryPressure)2255 void ArkNativeEngine::NotifyMemoryPressure([[maybe_unused]] bool inHighMemoryPressure)
2256 {
2257 HILOG_WARN("ARK does not support dfx on windows");
2258 }
2259
NotifyForceExpandState([[maybe_unused]] int32_t value)2260 void ArkNativeEngine::NotifyForceExpandState([[maybe_unused]] int32_t value)
2261 {
2262 HILOG_WARN("ARK does not support dfx on windows");
2263 }
2264 #endif
2265
SetMockModuleList(const std::map<std::string, std::string> &list)2266 void ArkNativeEngine::SetMockModuleList(const std::map<std::string, std::string> &list)
2267 {
2268 JSNApi::SetMockModuleList(vm_, list);
2269 }
2270
RegisterNapiUncaughtExceptionHandler(NapiUncaughtExceptionCallback callback)2271 void ArkNativeEngine::RegisterNapiUncaughtExceptionHandler(NapiUncaughtExceptionCallback callback)
2272 {
2273 JSNApi::EnableUserUncaughtErrorHandler(vm_);
2274 napiUncaughtExceptionCallback_ = callback;
2275 }
2276
HandleUncaughtException()2277 void ArkNativeEngine::HandleUncaughtException()
2278 {
2279 if (napiUncaughtExceptionCallback_ == nullptr) {
2280 return;
2281 }
2282 LocalScope scope(vm_);
2283 lastException_.Empty();
2284 Local<ObjectRef> exception = JSNApi::GetAndClearUncaughtException(vm_);
2285 if (!exception.IsEmpty() && !exception->IsHole()) {
2286 if (napiUncaughtExceptionCallback_ != nullptr) {
2287 napiUncaughtExceptionCallback_(ArkValueToNapiValue(reinterpret_cast<napi_env>(this), exception));
2288 }
2289 }
2290 }
2291
HasPendingException()2292 bool ArkNativeEngine::HasPendingException()
2293 {
2294 return panda::JSNApi::HasPendingException(vm_);
2295 }
2296
RegisterPermissionCheck(PermissionCheckCallback callback)2297 void ArkNativeEngine::RegisterPermissionCheck(PermissionCheckCallback callback)
2298 {
2299 if (permissionCheckCallback_ == nullptr) {
2300 permissionCheckCallback_ = callback;
2301 }
2302 }
2303
ExecutePermissionCheck()2304 bool ArkNativeEngine::ExecutePermissionCheck()
2305 {
2306 if (permissionCheckCallback_ != nullptr) {
2307 return permissionCheckCallback_();
2308 } else {
2309 HILOG_INFO("permissionCheckCallback_ is still nullptr when executing permission check!");
2310 return true;
2311 }
2312 }
2313
RegisterTranslateBySourceMap(SourceMapCallback callback)2314 void ArkNativeEngine::RegisterTranslateBySourceMap(SourceMapCallback callback)
2315 {
2316 if (SourceMapCallback_ == nullptr) {
2317 SourceMapCallback_ = callback;
2318 }
2319 // regedit SourceMapCallback to ark_js_runtime
2320 panda::JSNApi::SetSourceMapCallback(vm_, callback);
2321 }
2322
RegisterSourceMapTranslateCallback(SourceMapTranslateCallback callback)2323 void ArkNativeEngine::RegisterSourceMapTranslateCallback(SourceMapTranslateCallback callback)
2324 {
2325 panda::JSNApi::SetSourceMapTranslateCallback(vm_, callback);
2326 }
2327
ExecuteTranslateBySourceMap(const std::string& rawStack)2328 std::string ArkNativeEngine::ExecuteTranslateBySourceMap(const std::string& rawStack)
2329 {
2330 if (SourceMapCallback_ != nullptr) {
2331 return SourceMapCallback_(rawStack);
2332 } else {
2333 HILOG_WARN("SourceMapCallback_ is nullptr.");
2334 return rawStack;
2335 }
2336 }
2337
IsMixedDebugEnabled()2338 bool ArkNativeEngine::IsMixedDebugEnabled()
2339 {
2340 return JSNApi::IsMixedDebugEnabled(vm_);
2341 }
2342
NotifyNativeCalling(const void *nativeAddress)2343 void ArkNativeEngine::NotifyNativeCalling(const void *nativeAddress)
2344 {
2345 JSNApi::NotifyNativeCalling(vm_, nativeAddress);
2346 }
2347
AllowCrossThreadExecution() const2348 void ArkNativeEngine::AllowCrossThreadExecution() const
2349 {
2350 JSNApi::AllowCrossThreadExecution(vm_);
2351 }
2352
2353 #if !defined(is_arkui_x) && defined(OHOS_PLATFORM)
DumpHybridStack(const EcmaVM* vm)2354 std::string DumpHybridStack(const EcmaVM* vm)
2355 {
2356 constexpr size_t skipframes = 5;
2357 auto unwinder = std::make_shared<OHOS::HiviewDFX::Unwinder>();
2358 std::vector<OHOS::HiviewDFX::DfxFrame> frames;
2359 unwinder->EnableMethodIdLocal(true);
2360 if (unwinder->UnwindLocal(false, false, DEFAULT_MAX_FRAME_NUM, skipframes)) {
2361 frames = unwinder->GetFrames();
2362 } else {
2363 HILOG_ERROR("Failed to unwind local");
2364 }
2365
2366 for (auto &frame : frames) {
2367 if (frame.isJsFrame) {
2368 DFXJSNApi::TranslateJSStackInfo(vm, frame.mapName, frame.line, frame.column);
2369 }
2370 }
2371
2372 return OHOS::HiviewDFX::Unwinder::GetFramesStr(frames);
2373 }
2374 #endif
2375
PostLooperTriggerIdleGCTask()2376 void ArkNativeEngine::PostLooperTriggerIdleGCTask()
2377 {
2378 #if defined(ENABLE_EVENT_HANDLER)
2379 std::shared_ptr<OHOS::AppExecFwk::EventRunner> mainThreadRunner =
2380 OHOS::AppExecFwk::EventRunner::GetMainEventRunner();
2381 if (mainThreadRunner.get() == nullptr) {
2382 HILOG_FATAL("ArkNativeEngine:: the mainEventRunner is nullptr");
2383 return;
2384 }
2385 auto callback = [this](OHOS::AppExecFwk::EventRunnerStage stage,
2386 const OHOS::AppExecFwk::StageInfo* info) -> int {
2387 switch (stage) {
2388 case OHOS::AppExecFwk::EventRunnerStage::STAGE_BEFORE_WAITING:
2389 arkIdleMonitor_->NotifyLooperIdleStart(info->timestamp, info->sleepTime);
2390 break;
2391 case OHOS::AppExecFwk::EventRunnerStage::STAGE_AFTER_WAITING:
2392 arkIdleMonitor_->NotifyLooperIdleEnd(info->timestamp);
2393 break;
2394 default:
2395 HILOG_ERROR("this branch is unreachable");
2396 }
2397 return 0;
2398 };
2399 uint32_t stage = (static_cast<uint32_t>(OHOS::AppExecFwk::EventRunnerStage::STAGE_BEFORE_WAITING) |
2400 static_cast<uint32_t>(OHOS::AppExecFwk::EventRunnerStage::STAGE_AFTER_WAITING));
2401 mainThreadRunner->GetEventQueue()->AddObserver(OHOS::AppExecFwk::Observer::ARKTS_GC, stage, callback);
2402 #endif
2403 }
2404
GetObjectHash(napi_env env, napi_value src)2405 int32_t ArkNativeEngine::GetObjectHash(napi_env env, napi_value src)
2406 {
2407 auto engine = reinterpret_cast<NativeEngine*>(env);
2408 auto vm = engine->GetEcmaVm();
2409 auto nativeValue = LocalValueFromJsValue(src);
2410 return DFXJSNApi::GetObjectHash(vm, nativeValue);
2411 }
2412 // LCOV_EXCL_STOP
2413
RunScriptPath(const char* path, bool checkPath)2414 bool ArkNativeEngine::RunScriptPath(const char* path, bool checkPath)
2415 {
2416 if (checkPath && !IsValidPandaFile(path)) {
2417 HILOG_ERROR("file is not exist or format is invalid");
2418 return false;
2419 }
2420 // LCOV_EXCL_START
2421 panda::JSExecutionScope executionScope(vm_);
2422 LocalScope scope(vm_);
2423 [[maybe_unused]] bool ret = panda::JSNApi::Execute(vm_, path, PANDA_MAIN_FUNCTION);
2424 if (panda::JSNApi::HasPendingException(vm_)) {
2425 HandleUncaughtException();
2426 return false;
2427 }
2428 // LCOV_EXCL_STOP
2429 return true;
2430 }
2431
IsValidPandaFile(const char* path)2432 bool ArkNativeEngine::IsValidPandaFile(const char* path)
2433 {
2434 if (path == nullptr) {
2435 HILOG_ERROR("file path is nullptr");
2436 return false;
2437 }
2438
2439 char filePath[PATH_MAX + 1] = { 0 };
2440 if (!RealPath(path, filePath, PATH_MAX + 1)) {
2441 HILOG_ERROR("failed to format path");
2442 return false;
2443 }
2444 struct stat fileStat;
2445 int ret = stat(filePath, &fileStat);
2446 if (ret != 0) {
2447 HILOG_ERROR("script file \"%{public}s\" is not exist", filePath);
2448 return false;
2449 }
2450
2451 if (!(fileStat.st_mode & S_IFREG)) {
2452 HILOG_ERROR("script path \"%{public}s\" is a directory", filePath);
2453 return false;
2454 }
2455 std::ifstream abcStream(filePath, std::ios::in | std::ios::binary);
2456
2457 constexpr size_t fileHeaderLength = sizeof(uint64_t);
2458 uint8_t fileHeader[fileHeaderLength] = { 0 };
2459 if (abcStream.is_open()) {
2460 size_t fileSize = fileStat.st_size;
2461 if (fileSize < fileHeaderLength) {
2462 HILOG_ERROR("faild to read file header, invalid format \"%{public}s\"", filePath);
2463 abcStream.close();
2464 return false;
2465 }
2466 abcStream.read(reinterpret_cast<char*>(fileHeader), fileHeaderLength);
2467 abcStream.close();
2468 return IsValidScriptBuffer(fileHeader, fileHeaderLength);
2469 }
2470 return false;
2471 }
2472
IsValidScriptBuffer(uint8_t* scriptBuffer, size_t bufferSize)2473 bool ArkNativeEngine::IsValidScriptBuffer(uint8_t* scriptBuffer, size_t bufferSize)
2474 {
2475 if (scriptBuffer == nullptr) {
2476 HILOG_ERROR("buffer is nullptr");
2477 return false;
2478 }
2479 constexpr size_t headerLen = sizeof(uint64_t);
2480 if (bufferSize < headerLen) {
2481 HILOG_ERROR("invalid buffer");
2482 return false;
2483 }
2484 constexpr char pandaFileHeader[headerLen] = "PANDA";
2485 const uint64_t bytePandaHeader = *reinterpret_cast<const uint64_t*>(pandaFileHeader);
2486 char fileHeader[headerLen] = { 0 };
2487 // Ensure destMax paramter is set correctly to avoid buffer overflows
2488 if (memcpy_s(fileHeader, sizeof(fileHeader), scriptBuffer, sizeof(fileHeader)) != 0) {
2489 HILOG_ERROR("faild to read file header of buffer");
2490 return false;
2491 }
2492
2493 uint64_t byteFileHeader = *reinterpret_cast<uint64_t*>(fileHeader);
2494 if (byteFileHeader != bytePandaHeader) {
2495 HILOG_ERROR("invalid format of file buffer");
2496 return false;
2497 }
2498 return true;
2499 }
2500
2501 // The security interface needs to be modified accordingly.
RunScriptBuffer(const char* path, std::vector<uint8_t>& buffer, bool isBundle)2502 napi_value ArkNativeEngine::RunScriptBuffer(const char* path, std::vector<uint8_t>& buffer, bool isBundle)
2503 {
2504 if (!IsValidScriptBuffer(buffer.data(), buffer.size())) {
2505 HILOG_ERROR("invalid script buffer");
2506 return nullptr;
2507 }
2508
2509 // LCOV_EXCL_START
2510 panda::EscapeLocalScope scope(vm_);
2511 [[maybe_unused]] bool ret = false;
2512 if (isBundle) {
2513 ret = panda::JSNApi::Execute(vm_, buffer.data(), buffer.size(), PANDA_MAIN_FUNCTION, path);
2514 } else {
2515 ret = panda::JSNApi::ExecuteModuleBuffer(vm_, buffer.data(), buffer.size(), path);
2516 }
2517
2518 if (panda::JSNApi::HasPendingException(vm_)) {
2519 HandleUncaughtException();
2520 return nullptr;
2521 }
2522 Local<JSValueRef> undefObj = JSValueRef::Undefined(vm_);
2523 // LCOV_EXCL_STOP
2524 return JsValueFromLocalValue(scope.Escape(undefObj));
2525 }
2526
RunScriptBuffer(const std::string& path, uint8_t* buffer, size_t size, bool isBundle)2527 bool ArkNativeEngine::RunScriptBuffer(const std::string& path, uint8_t* buffer, size_t size, bool isBundle)
2528 {
2529 if (!IsValidScriptBuffer(buffer, size)) {
2530 HILOG_ERROR("invalid script buffer");
2531 return false;
2532 }
2533
2534 // LCOV_EXCL_START
2535 panda::JSExecutionScope executionScope(vm_);
2536 LocalScope scope(vm_);
2537 bool ret = false;
2538 if (isBundle) {
2539 ret = panda::JSNApi::ExecuteSecure(vm_, buffer, size, PANDA_MAIN_FUNCTION, path);
2540 } else {
2541 ret = panda::JSNApi::ExecuteModuleBufferSecure(vm_, buffer, size, path);
2542 }
2543
2544 if (panda::JSNApi::HasPendingException(vm_)) {
2545 HandleUncaughtException();
2546 return false;
2547 }
2548 return ret;
2549 // LCOV_EXCL_STOP
2550 }
2551
RunBufferScript(std::vector<uint8_t>& buffer)2552 napi_value ArkNativeEngine::RunBufferScript(std::vector<uint8_t>& buffer)
2553 {
2554 if (!IsValidScriptBuffer(buffer.data(), buffer.size())) {
2555 HILOG_ERROR("invalid script buffer");
2556 return nullptr;
2557 }
2558
2559 // LCOV_EXCL_START
2560 panda::EscapeLocalScope scope(vm_);
2561 [[maybe_unused]] bool ret = panda::JSNApi::Execute(vm_, buffer.data(), buffer.size(), PANDA_MAIN_FUNCTION);
2562
2563 if (panda::JSNApi::HasPendingException(vm_)) {
2564 HandleUncaughtException();
2565 return nullptr;
2566 }
2567 Local<JSValueRef> undefObj = JSValueRef::Undefined(vm_);
2568 return JsValueFromLocalValue(scope.Escape(undefObj));
2569 // LCOV_EXCL_STOP
2570 }
2571
2572 #define EXECUTE_BUFFER(functionName) \
2573 if (panda::JSNApi::IsBundle(vm_)) { \
2574 /* FA doesn't enable securemem */ \
2575 ret = panda::JSNApi::Execute(vm_, buffer, bufferSize, PANDA_MAIN_FUNCTION, desc); \
2576 } else if (bufferSize != 0) { \
2577 if (entryPoint == nullptr) { \
2578 HILOG_DEBUG("Input entryPoint is nullptr, please input entryPoint for merged ESModule"); \
2579 /* this path for bundle and abc compiled by single module js */ \
2580 ret = panda::JSNApi::functionName(vm_, buffer, bufferSize, PANDA_MAIN_FUNCTION, desc); \
2581 } else { \
2582 /* this path for mergeabc with specific entryPoint */ \
2583 ret = panda::JSNApi::functionName(vm_, buffer, bufferSize, entryPoint, desc); \
2584 } \
2585 } else { \
2586 /* this path for worker */ \
2587 ret = panda::JSNApi::Execute(vm_, desc, PANDA_MAIN_FUNCTION); \
2588 }
2589
RunActor(uint8_t* buffer, size_t bufferSize, const char* descriptor, char* entryPoint, bool checkPath)2590 napi_value ArkNativeEngine::RunActor(uint8_t* buffer, size_t bufferSize,
2591 const char* descriptor, char* entryPoint, bool checkPath)
2592 {
2593 if (buffer == nullptr && descriptor == nullptr) {
2594 HILOG_ERROR("invalid param, both buffer and descriptor are nullptr");
2595 return nullptr;
2596 }
2597
2598 if ((buffer != nullptr && !IsValidScriptBuffer(buffer, bufferSize)) &&
2599 (checkPath && descriptor != nullptr && !IsValidPandaFile(descriptor))) {
2600 HILOG_ERROR("invalid param");
2601 return nullptr;
2602 }
2603
2604 // LCOV_EXCL_START
2605 panda::EscapeLocalScope scope(vm_);
2606 std::string desc(descriptor);
2607 [[maybe_unused]] bool ret = false;
2608 // if apiVersion > API11, use secure path.
2609 if (IsApplicationApiVersionAPI11Plus()) {
2610 EXECUTE_BUFFER(ExecuteSecure);
2611 } else {
2612 EXECUTE_BUFFER(Execute);
2613 }
2614 if (panda::JSNApi::HasPendingException(vm_)) {
2615 HandleUncaughtException();
2616 return nullptr;
2617 }
2618 Local<JSValueRef> undefObj = JSValueRef::Undefined(vm_);
2619 return JsValueFromLocalValue(scope.Escape(undefObj));
2620 // LCOV_EXCL_STOP
2621 }
2622
LoadArkModule(const void* buffer, int32_t len, const std::string& fileName)2623 panda::Local<panda::ObjectRef> ArkNativeEngine::LoadArkModule(const void* buffer,
2624 int32_t len, const std::string& fileName)
2625 {
2626 panda::EscapeLocalScope scope(vm_);
2627 Local<ObjectRef> undefObj(JSValueRef::Undefined(vm_));
2628 if (buffer == nullptr || len <= 0 || fileName.empty()) {
2629 HILOG_ERROR("fileName is nullptr or source code is nullptr");
2630 return scope.Escape(undefObj);
2631 }
2632 if (!IsValidScriptBuffer(reinterpret_cast<uint8_t*>(const_cast<void*>(buffer)), len)) {
2633 HILOG_ERROR("invalid script buffer");
2634 return scope.Escape(undefObj);
2635 }
2636
2637 // LCOV_EXCL_START
2638 bool res = JSNApi::ExecuteModuleFromBuffer(vm_, buffer, len, fileName);
2639 if (!res) {
2640 HILOG_ERROR("Execute module failed");
2641 return scope.Escape(undefObj);
2642 }
2643
2644 Local<ObjectRef> exportObj = JSNApi::GetExportObjectFromBuffer(vm_, fileName, "default");
2645 if (exportObj->IsNull()) {
2646 HILOG_ERROR("Get export object failed");
2647 return scope.Escape(undefObj);
2648 }
2649
2650 HILOG_DEBUG("ArkNativeEngineImpl::LoadModule end");
2651 return scope.Escape(exportObj);
2652 // LCOV_EXCL_STOP
2653 }
2654
ExecuteJsBin(const std::string& fileName, bool checkPath)2655 bool ArkNativeEngine::ExecuteJsBin(const std::string& fileName, bool checkPath)
2656 {
2657 if (checkPath && !IsValidPandaFile(fileName.c_str())) {
2658 HILOG_ERROR("faild to execute js bin, file is not exist or format is invalid");
2659 return false;
2660 }
2661 // LCOV_EXCL_START
2662 panda::JSExecutionScope executionScope(vm_);
2663 LocalScope scope(vm_);
2664 bool ret = JSNApi::Execute(vm_, fileName, PANDA_MAIN_FUNCTION);
2665 return ret;
2666 // LCOV_EXCL_STOP
2667 }
2668