1#ifndef SRC_JS_NATIVE_API_V8_H_ 2#define SRC_JS_NATIVE_API_V8_H_ 3 4#include <variant> 5#include "jsvm_types.h" 6#include "js_native_api_v8_internals.h" 7 8#ifdef TARGET_OHOS 9#include <unistd.h> 10extern "C" void ReportData(uint32_t resType, int64_t value, 11 const std::unordered_map<std::string, std::string>& mapPayLoad); 12#endif 13 14inline JSVM_Status jsvm_clear_last_error(JSVM_Env env); 15 16namespace v8impl { 17 18class RefTracker { 19 public: 20 RefTracker() {} 21 virtual ~RefTracker() {} 22 virtual void Finalize() {} 23 24 typedef RefTracker RefList; 25 26 inline void Link(RefList* list) { 27 prev_ = list; 28 next_ = list->next_; 29 if (next_ != nullptr) { 30 next_->prev_ = this; 31 } 32 list->next_ = this; 33 } 34 35 inline void Unlink() { 36 if (prev_ != nullptr) { 37 prev_->next_ = next_; 38 } 39 if (next_ != nullptr) { 40 next_->prev_ = prev_; 41 } 42 prev_ = nullptr; 43 next_ = nullptr; 44 } 45 46 static void FinalizeAll(RefList* list) { 47 while (list->next_ != nullptr) { 48 list->next_->Finalize(); 49 } 50 } 51 52 private: 53 RefList* next_ = nullptr; 54 RefList* prev_ = nullptr; 55}; 56 57class Finalizer; 58class Agent; 59} // end of namespace v8impl 60 61struct JSVM_Data__ { 62 public: 63 using SourcePtr = std::variant<v8::Local<v8::Script>, v8::Global<v8::Script>>; 64 using DataType = enum { kJsvmScript }; 65 66 template<typename T> 67 JSVM_Data__(T ptr, bool retained, DataType type = kJsvmScript) 68 : taggedPointer(ptr), 69 isGlobal(retained), 70 type(type) {} 71 72 template<class T> 73 v8::Local<T> ToV8Local(v8::Isolate *isolate) { 74 if (isGlobal) { 75 return v8::Local<T>::New(isolate, std::get<v8::Global<T>>(taggedPointer)); 76 } else { 77 return std::get<v8::Local<T>>(taggedPointer); 78 } 79 } 80 81 SourcePtr taggedPointer; 82 bool isGlobal = false; 83 DataType type; 84}; 85 86struct JSVM_Env__ { 87 explicit JSVM_Env__(v8::Local<v8::Context> context, 88 int32_t module_api_version) 89 : isolate(context->GetIsolate()), 90 context_persistent(isolate, context), 91 module_api_version(module_api_version) { 92 jsvm_clear_last_error(this); 93 } 94 95 // Constructor for creating partial env. 96 explicit JSVM_Env__(v8::Isolate* isolate, int32_t module_api_version); 97 98 template <typename Fn> 99 inline void RequestInterrupt(Fn&& cb) { 100 auto callback = native_immediates_interrupts_.CreateCallback( 101 std::move(cb), node::CallbackFlags::kRefed); 102 { 103 node::Mutex::ScopedLock lock(native_immediates_threadsafe_mutex_); 104 native_immediates_interrupts_.Push(std::move(callback)); 105 } 106 isolate->RequestInterrupt([](v8::Isolate* isolate, void* data) { 107 static_cast<JSVM_Env__*>(data)->RunAndClearInterrupts(); 108 }, this); 109 } 110 111 void RunAndClearInterrupts(); 112 113 v8impl::Agent* inspector_agent() { return inspector_agent_; } 114 115 v8::Platform* platform(); 116 117 inline v8::Local<v8::Context> context() const { 118 return v8impl::PersistentToLocal::Strong(context_persistent); 119 } 120 121 inline void Ref() { refs++; } 122 inline void Unref() { 123 if (--refs == 0) DeleteMe(); 124 } 125 126 virtual bool can_call_into_js() const { return true; } 127 128 static inline void HandleThrow(JSVM_Env env, v8::Local<v8::Value> value) { 129 if (env->terminatedOrTerminating()) { 130 return; 131 } 132 env->isolate->ThrowException(value); 133 } 134 135 // i.e. whether v8 exited or is about to exit 136 inline bool terminatedOrTerminating() { 137 return this->isolate->IsExecutionTerminating() || !can_call_into_js(); 138 } 139 140 // v8 uses a special exception to indicate termination, the 141 // `handle_exception` callback should identify such case using 142 // terminatedOrTerminating() before actually handle the exception 143 template <typename T, typename U = decltype(HandleThrow)> 144 inline void CallIntoModule(T&& call, U&& handle_exception = HandleThrow) { 145 int open_handle_scopes_before = open_handle_scopes; 146 int open_callback_scopes_before = open_callback_scopes; 147 jsvm_clear_last_error(this); 148 call(this); 149 CHECK_EQ(open_handle_scopes, open_handle_scopes_before); 150 CHECK_EQ(open_callback_scopes, open_callback_scopes_before); 151 if (!last_exception.IsEmpty()) { 152 handle_exception(this, last_exception.Get(this->isolate)); 153 last_exception.Reset(); 154 } 155 } 156 157 // Call finalizer immediately. 158 virtual void CallFinalizer(JSVM_Finalize cb, void* data, void* hint) { 159 v8::HandleScope handle_scope(isolate); 160 CallIntoModule([&](JSVM_Env env) { cb(env, data, hint); }); 161 } 162 163 // Invoke finalizer from V8 garbage collector. 164 void InvokeFinalizerFromGC(v8impl::RefTracker* finalizer); 165 166 // Enqueue the finalizer to the JSVM_Env's own queue of the second pass 167 // weak callback. 168 // Implementation should drain the queue at the time it is safe to call 169 // into JavaScript. 170 virtual void EnqueueFinalizer(v8impl::RefTracker* finalizer) { 171 pending_finalizers.emplace(finalizer); 172 } 173 174 // Remove the finalizer from the scheduled second pass weak callback queue. 175 // The finalizer can be deleted after this call. 176 virtual void DequeueFinalizer(v8impl::RefTracker* finalizer) { 177 pending_finalizers.erase(finalizer); 178 } 179 180 virtual void DeleteMe(); 181 182 void CheckGCAccess() { 183 if (module_api_version == JSVM_VERSION_EXPERIMENTAL && in_gc_finalizer) { 184 v8impl::OnFatalError( 185 nullptr, 186 "Finalizer is calling a function that may affect GC state.\n" 187 "The finalizers are run directly from GC and must not affect GC " 188 "state.\n" 189 "Use `node_api_post_finalizer` from inside of the finalizer to work " 190 "around this issue.\n" 191 "It schedules the call as a new task in the event loop."); 192 } 193 } 194 195 template<typename T> 196 JSVM_Data__ *NewJsvmData(T srcPtr, JSVM_Data__::DataType type = JSVM_Data__::kJsvmScript) { 197 if (dataStack.empty() || open_handle_scopes != dataStack.top().first) { 198 dataStack.emplace(open_handle_scopes, std::vector<JSVM_Data__*>()); 199 } 200 auto newData = new JSVM_Data__(srcPtr, false, type); 201 dataStack.top().second.push_back(newData); 202 return newData; 203 } 204 205 void ReleaseJsvmData() { 206 if (dataStack.empty() || open_handle_scopes != dataStack.top().first) { 207 return; 208 } 209 for (auto data : dataStack.top().second) { 210 if (!data->isGlobal) { 211 delete data; 212 } 213 } 214 dataStack.pop(); 215 } 216 217 v8::Isolate* const isolate; // Shortcut for context()->GetIsolate() 218 v8impl::Persistent<v8::Context> context_persistent; 219 220 v8impl::Persistent<v8::Value> last_exception; 221 222 // We store references in two different lists, depending on whether they have 223 // `JSVM_Finalizer` callbacks, because we must first finalize the ones that 224 // have such a callback. See `~JSVM_Env__()` above for details. 225 v8impl::RefTracker::RefList reflist; 226 v8impl::RefTracker::RefList finalizing_reflist; 227 // The invocation order of the finalizers is not determined. 228 std::unordered_set<v8impl::RefTracker*> pending_finalizers; 229 JSVM_ExtendedErrorInfo last_error; 230 int open_handle_scopes = 0; 231 int open_callback_scopes = 0; 232 int refs = 1; 233 void* instance_data = nullptr; 234 int32_t module_api_version = NODE_API_DEFAULT_MODULE_API_VERSION; 235 bool in_gc_finalizer = false; 236 v8::Locker* locker = nullptr; 237 std::stack<std::pair<int, std::vector<JSVM_Data__*>>> dataStack; 238 239 private: 240 v8impl::Agent* inspector_agent_; 241 typedef node::CallbackQueue<void, JSVM_Env__*> NativeImmediateQueue; 242 node::Mutex native_immediates_threadsafe_mutex_; 243 NativeImmediateQueue native_immediates_interrupts_; 244 245 protected: 246 // Should not be deleted directly. Delete with `JSVM_Env__::DeleteMe()` 247 // instead. 248 virtual ~JSVM_Env__() = default; 249}; 250 251inline JSVM_Status jsvm_clear_last_error(JSVM_Env env) { 252 env->last_error.errorCode = JSVM_OK; 253 env->last_error.engineErrorCode = 0; 254 env->last_error.engineReserved = nullptr; 255 env->last_error.errorMessage = nullptr; 256 return JSVM_OK; 257} 258 259inline JSVM_Status jsvm_set_last_error(JSVM_Env env, 260 JSVM_Status errorCode, 261 uint32_t engineErrorCode = 0, 262 void* engineReserved = nullptr) { 263 env->last_error.errorCode = errorCode; 264 env->last_error.engineErrorCode = engineErrorCode; 265 env->last_error.engineReserved = engineReserved; 266 return errorCode; 267} 268 269#define RETURN_STATUS_IF_FALSE(env, condition, status) \ 270 do { \ 271 if (!(condition)) { \ 272 return jsvm_set_last_error((env), (status)); \ 273 } \ 274 } while (0) 275 276#define RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(env, condition, status) \ 277 do { \ 278 if (!(condition)) { \ 279 return jsvm_set_last_error( \ 280 (env), try_catch.HasCaught() ? JSVM_PENDING_EXCEPTION : (status)); \ 281 } \ 282 } while (0) 283 284#define CHECK_ENV(env) \ 285 do { \ 286 if ((env) == nullptr) { \ 287 return JSVM_INVALID_ARG; \ 288 } \ 289 } while (0) 290 291#define CHECK_ENV_NOT_IN_GC(env) \ 292 do { \ 293 CHECK_ENV((env)); \ 294 (env)->CheckGCAccess(); \ 295 } while (0) 296 297#define CHECK_ARG(env, arg) \ 298 RETURN_STATUS_IF_FALSE((env), ((arg) != nullptr), JSVM_INVALID_ARG) 299 300#define CHECK_ARG_NOT_ZERO(env, arg) \ 301 RETURN_STATUS_IF_FALSE((env), ((arg) != 0), JSVM_INVALID_ARG) 302 303#define CHECK_ARG_WITH_PREAMBLE(env, arg) \ 304 RETURN_STATUS_IF_FALSE_WITH_PREAMBLE( \ 305 (env), ((arg) != nullptr), JSVM_INVALID_ARG) 306 307#define CHECK_MAYBE_EMPTY(env, maybe, status) \ 308 RETURN_STATUS_IF_FALSE((env), !((maybe).IsEmpty()), (status)) 309 310#define CHECK_MAYBE_EMPTY_WITH_PREAMBLE(env, maybe, status) \ 311 RETURN_STATUS_IF_FALSE_WITH_PREAMBLE((env), !((maybe).IsEmpty()), (status)) 312 313// JSVM_PREAMBLE is not wrapped in do..while: try_catch must have function scope 314#define JSVM_PREAMBLE(env) \ 315 CHECK_ENV((env)); \ 316 RETURN_STATUS_IF_FALSE( \ 317 (env), (env)->last_exception.IsEmpty(), JSVM_PENDING_EXCEPTION); \ 318 RETURN_STATUS_IF_FALSE((env), \ 319 (env)->can_call_into_js(), \ 320 (env->module_api_version == JSVM_VERSION_EXPERIMENTAL \ 321 ? JSVM_CANNOT_RUN_JS \ 322 : JSVM_PENDING_EXCEPTION)); \ 323 jsvm_clear_last_error((env)); \ 324 v8impl::TryCatch try_catch((env)) 325 326#define CHECK_TO_TYPE(env, type, context, result, src, status) \ 327 do { \ 328 CHECK_ARG((env), (src)); \ 329 auto maybe = v8impl::V8LocalValueFromJsValue((src))->To##type((context)); \ 330 CHECK_MAYBE_EMPTY((env), maybe, (status)); \ 331 (result) = maybe.ToLocalChecked(); \ 332 } while (0) 333 334#define CHECK_TO_TYPE_WITH_PREAMBLE(env, type, context, result, src, status) \ 335 do { \ 336 CHECK_ARG_WITH_PREAMBLE((env), (src)); \ 337 auto maybe = v8impl::V8LocalValueFromJsValue((src))->To##type((context)); \ 338 CHECK_MAYBE_EMPTY_WITH_PREAMBLE((env), maybe, (status)); \ 339 (result) = maybe.ToLocalChecked(); \ 340 } while (0) 341 342#define CHECK_TO_FUNCTION(env, result, src) \ 343 do { \ 344 CHECK_ARG((env), (src)); \ 345 v8::Local<v8::Value> v8value = v8impl::V8LocalValueFromJsValue((src)); \ 346 RETURN_STATUS_IF_FALSE((env), v8value->IsFunction(), JSVM_INVALID_ARG); \ 347 (result) = v8value.As<v8::Function>(); \ 348 } while (0) 349 350#define CHECK_TO_OBJECT(env, context, result, src) \ 351 CHECK_TO_TYPE((env), Object, (context), (result), (src), JSVM_OBJECT_EXPECTED) 352 353#define CHECK_TO_BIGINT(env, context, result, src) \ 354 CHECK_TO_TYPE((env), BigInt, (context), (result), (src), JSVM_BIGINT_EXPECTED) 355 356#define CHECK_TO_OBJECT_WITH_PREAMBLE(env, context, result, src) \ 357 CHECK_TO_TYPE_WITH_PREAMBLE( \ 358 (env), Object, (context), (result), (src), JSVM_OBJECT_EXPECTED) 359 360#define CHECK_TO_STRING(env, context, result, src) \ 361 CHECK_TO_TYPE((env), String, (context), (result), (src), JSVM_STRING_EXPECTED) 362 363#define GET_RETURN_STATUS(env) \ 364 (!try_catch.HasCaught() \ 365 ? JSVM_OK \ 366 : jsvm_set_last_error((env), JSVM_PENDING_EXCEPTION)) 367 368#define THROW_RANGE_ERROR_IF_FALSE(env, condition, error, message) \ 369 do { \ 370 if (!(condition)) { \ 371 OH_JSVM_ThrowRangeError((env), (error), (message)); \ 372 return jsvm_set_last_error((env), JSVM_GENERIC_FAILURE); \ 373 } \ 374 } while (0) 375 376#define CHECK_MAYBE_EMPTY_WITH_PREAMBLE(env, maybe, status) \ 377 RETURN_STATUS_IF_FALSE_WITH_PREAMBLE((env), !((maybe).IsEmpty()), (status)) 378 379#define STATUS_CALL(call) \ 380 do { \ 381 JSVM_Status status = (call); \ 382 if (status != JSVM_OK) return status; \ 383 } while (0) 384 385namespace v8impl { 386 387//=== Conversion between V8 Handles and JSVM_Value ======================== 388 389// This asserts v8::Local<> will always be implemented with a single 390// pointer field so that we can pass it around as a void*. 391static_assert(sizeof(v8::Local<v8::Value>) == sizeof(JSVM_Value), 392 "Cannot convert between v8::Local<v8::Value> and JSVM_Value"); 393 394inline JSVM_Value JsValueFromV8LocalValue(v8::Local<v8::Value> local) { 395 return reinterpret_cast<JSVM_Value>(*local); 396} 397 398inline v8::Local<v8::Value> V8LocalValueFromJsValue(JSVM_Value v) { 399 v8::Local<v8::Value> local; 400 memcpy(static_cast<void*>(&local), &v, sizeof(v)); 401 return local; 402} 403 404// Adapter for JSVM_Finalize callbacks. 405class Finalizer { 406 protected: 407 Finalizer(JSVM_Env env, 408 JSVM_Finalize finalize_callback, 409 void* finalize_data, 410 void* finalize_hint) 411 : env_(env), 412 finalize_callback_(finalize_callback), 413 finalize_data_(finalize_data), 414 finalize_hint_(finalize_hint) {} 415 416 virtual ~Finalizer() = default; 417 418 public: 419 static Finalizer* New(JSVM_Env env, 420 JSVM_Finalize finalize_callback = nullptr, 421 void* finalize_data = nullptr, 422 void* finalize_hint = nullptr) { 423 return new Finalizer(env, finalize_callback, finalize_data, finalize_hint); 424 } 425 426 JSVM_Finalize callback() { return finalize_callback_; } 427 void* data() { return finalize_data_; } 428 void* hint() { return finalize_hint_; } 429 430 void ResetFinalizer(); 431 432 protected: 433 JSVM_Env env_; 434 JSVM_Finalize finalize_callback_; 435 void* finalize_data_; 436 void* finalize_hint_; 437}; 438 439class TryCatch : public v8::TryCatch { 440 public: 441 explicit TryCatch(JSVM_Env env) : v8::TryCatch(env->isolate), _env(env) {} 442 443 ~TryCatch() { 444 if (HasCaught()) { 445 _env->last_exception.Reset(_env->isolate, Exception()); 446 } 447 } 448 449 private: 450 JSVM_Env _env; 451}; 452 453// Ownership of a reference. 454enum class Ownership { 455 // The reference is owned by the runtime. No userland call is needed to 456 // destruct the reference. 457 kRuntime, 458 // The reference is owned by the userland. User code is responsible to delete 459 // the reference with appropriate node-api calls. 460 kUserland, 461}; 462 463// Wrapper around Finalizer that can be tracked. 464class TrackedFinalizer : public Finalizer, public RefTracker { 465 protected: 466 TrackedFinalizer(JSVM_Env env, 467 JSVM_Finalize finalizeCallback, 468 void* finalizeData, 469 void* finalizeHint); 470 471 public: 472 static TrackedFinalizer* New(JSVM_Env env, 473 JSVM_Finalize finalizeCallback, 474 void* finalizeData, 475 void* finalizeHint); 476 ~TrackedFinalizer() override; 477 478 protected: 479 void Finalize() override; 480 void FinalizeCore(bool deleteMe); 481}; 482 483// Wrapper around Finalizer that implements reference counting. 484class RefBase : public TrackedFinalizer { 485 protected: 486 RefBase(JSVM_Env env, 487 uint32_t initialRefcount, 488 Ownership ownership, 489 JSVM_Finalize finalizeCallback, 490 void* finalizeData, 491 void* finalizeHint); 492 493 public: 494 static RefBase* New(JSVM_Env env, 495 uint32_t initialRefcount, 496 Ownership ownership, 497 JSVM_Finalize finalizeCallback, 498 void* finalizeData, 499 void* finalizeHint); 500 501 void* Data(); 502 uint32_t Ref(); 503 uint32_t Unref(); 504 uint32_t RefCount(); 505 506 Ownership ownership() { return ownership_; } 507 508 protected: 509 void Finalize() override; 510 511 private: 512 uint32_t refcount_; 513 Ownership ownership_; 514}; 515 516// Wrapper around v8impl::Persistent. 517class Reference : public RefBase { 518 protected: 519 template <typename... Args> 520 Reference(JSVM_Env env, v8::Local<v8::Value> value, Args&&... args); 521 522 public: 523 static Reference* New(JSVM_Env env, 524 v8::Local<v8::Value> value, 525 uint32_t initialRefcount, 526 Ownership ownership, 527 JSVM_Finalize finalizeCallback = nullptr, 528 void* finalizeData = nullptr, 529 void* finalizeHint = nullptr); 530 531 virtual ~Reference(); 532 bool HasDeletedByUser() { 533 return deleted_by_user; 534 } 535 uint32_t Ref(); 536 uint32_t Unref(); 537 v8::Local<v8::Value> Get(); 538 void Delete(); 539 540 protected: 541 void Finalize() override; 542 543 private: 544 static void WeakCallback(const v8::WeakCallbackInfo<Reference>& data); 545 546 void SetWeak(); 547 548 v8impl::Persistent<v8::Value> persistent_; 549 bool can_be_weak_; 550 bool deleted_by_user; 551 bool wait_callback; 552}; 553 554typedef JSVM_Value (* GetterCallback)(JSVM_Env, JSVM_Value, JSVM_Value, JSVM_Value); 555typedef JSVM_Value (* SetterCallback)(JSVM_Env, JSVM_Value, JSVM_Value, JSVM_Value, JSVM_Value); 556typedef JSVM_Value (* DeleterCallback)(JSVM_Env, JSVM_Value, JSVM_Value, JSVM_Value); 557typedef JSVM_Value (* EnumeratorCallback)(JSVM_Env, JSVM_Value, JSVM_Value); 558 559struct JSVM_PropertyHandlerCfgStruct { 560 GetterCallback namedGetterCallback_; 561 SetterCallback namedSetterCallback_; 562 DeleterCallback nameDeleterCallback_; 563 EnumeratorCallback namedEnumeratorCallback_; 564 GetterCallback indexedGetterCallback_; 565 SetterCallback indexedSetterCallback_; 566 DeleterCallback indexedDeleterCallback_; 567 EnumeratorCallback indexedEnumeratorCallback_; 568 JSVM_Ref namedPropertyData_; 569 JSVM_Ref indexedPropertyData_; 570}; 571 572inline JSVM_PropertyHandlerCfgStruct* CreatePropertyCfg(JSVM_Env env, JSVM_PropertyHandlerCfg propertyCfg) 573{ 574 JSVM_PropertyHandlerCfgStruct* newPropertyCfg = new JSVM_PropertyHandlerCfgStruct; 575 if (newPropertyCfg != nullptr && propertyCfg != nullptr) { 576 newPropertyCfg->namedGetterCallback_ = propertyCfg->genericNamedPropertyGetterCallback; 577 newPropertyCfg->namedSetterCallback_ = propertyCfg->genericNamedPropertySetterCallback; 578 newPropertyCfg->nameDeleterCallback_ = propertyCfg->genericNamedPropertyDeleterCallback; 579 newPropertyCfg->namedEnumeratorCallback_ = propertyCfg->genericNamedPropertyEnumeratorCallback; 580 newPropertyCfg->indexedGetterCallback_ = propertyCfg->genericIndexedPropertyGetterCallback; 581 newPropertyCfg->indexedSetterCallback_ = propertyCfg->genericIndexedPropertySetterCallback; 582 newPropertyCfg->indexedDeleterCallback_ = propertyCfg->genericIndexedPropertyDeleterCallback; 583 newPropertyCfg->indexedEnumeratorCallback_ = propertyCfg->genericIndexedPropertyEnumeratorCallback; 584 newPropertyCfg->namedPropertyData_ = nullptr; 585 newPropertyCfg->indexedPropertyData_ = nullptr; 586 if (propertyCfg->namedPropertyData != nullptr) { 587 v8::Local<v8::Value> v8_value = v8impl::V8LocalValueFromJsValue(propertyCfg->namedPropertyData); 588 v8impl::Reference* reference = v8impl::Reference::New(env, v8_value, 1, v8impl::Ownership::kUserland); 589 newPropertyCfg->namedPropertyData_ = reinterpret_cast<JSVM_Ref>(reference); 590 } 591 592 if (propertyCfg->indexedPropertyData != nullptr) { 593 v8::Local<v8::Value> v8_value = v8impl::V8LocalValueFromJsValue(propertyCfg->indexedPropertyData); 594 v8impl::Reference* reference = v8impl::Reference::New(env, v8_value, 1, v8impl::Ownership::kUserland); 595 newPropertyCfg->indexedPropertyData_ = reinterpret_cast<JSVM_Ref>(reference); 596 } 597 } 598 599 return newPropertyCfg; 600} 601 602inline void CfgFinalizedCallback(JSVM_Env env, void* finalizeData, void* finalizeHint) 603{ 604 auto cfg = reinterpret_cast<JSVM_PropertyHandlerCfgStruct *>(finalizeData); 605 if (cfg->namedPropertyData_ != nullptr) { 606 delete reinterpret_cast<v8impl::Reference*>(cfg->namedPropertyData_); 607 } 608 if (cfg->indexedPropertyData_ != nullptr) { 609 delete reinterpret_cast<v8impl::Reference*>(cfg->indexedPropertyData_); 610 } 611 delete cfg; 612} 613 614#ifdef TARGET_OHOS 615namespace ResourceSchedule { 616namespace ResType { 617enum : uint32_t { 618 RES_TYPE_REPORT_KEY_THREAD = 39 619}; 620 621enum ReportChangeStatus : int64_t { 622 CREATE = 0, 623 REMOVE = 1 624}; 625 626enum ThreadRole : int64_t { 627 USER_INTERACT = 0, 628 NORMAL_DISPLAY = 1, 629 IMPORTANT_DISPLAY = 2, 630 NORMAL_AUDIO = 3, 631 IMPORTANT_AUDIO = 4, 632 IMAGE_DECODE = 5 633}; 634} 635 636static inline void ReportKeyThread(uid_t uid, pid_t pid, pid_t tid, ResType::ThreadRole role) 637{ 638 std::unordered_map<std::string, std::string> payLoad = { 639 {"uid", std::to_string(uid)}, 640 {"pid", std::to_string(pid)}, 641 {"tid", std::to_string(tid)}, 642 {"role", std::to_string(role)}}; 643 ReportData(v8impl::ResourceSchedule::ResType::RES_TYPE_REPORT_KEY_THREAD, 644 v8impl::ResourceSchedule::ResType::ReportChangeStatus::CREATE, payLoad); 645} 646} 647#endif 648} // end of namespace v8impl 649 650#endif // SRC_JS_NATIVE_API_V8_H_ 651