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>
10 extern "C" void ReportData(uint32_t resType, int64_t value,
11   const std::unordered_map<std::string, std::string>& mapPayLoad);
12 #endif
13 
14 inline JSVM_Status jsvm_clear_last_error(JSVM_Env env);
15 
16 namespace v8impl {
17 
18 class RefTracker {
19  public:
RefTracker()20   RefTracker() {}
~RefTracker()21   virtual ~RefTracker() {}
Finalize()22   virtual void Finalize() {}
23 
24   typedef RefTracker RefList;
25 
Link(RefList* list)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 
Unlink()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 
FinalizeAll(RefList* list)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 
57 class Finalizer;
58 class Agent;
59 }  // end of namespace v8impl
60 
61 struct 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>
JSVM_Data__JSVM_Data__67   JSVM_Data__(T ptr, bool retained, DataType type = kJsvmScript)
68     : taggedPointer(ptr),
69       isGlobal(retained),
70       type(type) {}
71 
72   template<class T>
ToV8LocalJSVM_Data__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 
86 struct JSVM_Env__ {
JSVM_Env__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>
RequestInterruptJSVM_Env__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 
inspector_agentJSVM_Env__113   v8impl::Agent* inspector_agent() { return inspector_agent_; }
114 
115   v8::Platform* platform();
116 
contextJSVM_Env__117   inline v8::Local<v8::Context> context() const {
118     return v8impl::PersistentToLocal::Strong(context_persistent);
119   }
120 
RefJSVM_Env__121   inline void Ref() { refs++; }
UnrefJSVM_Env__122   inline void Unref() {
123     if (--refs == 0) DeleteMe();
124   }
125 
can_call_into_jsJSVM_Env__126   virtual bool can_call_into_js() const { return true; }
127 
HandleThrowJSVM_Env__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
terminatedOrTerminatingJSVM_Env__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)>
CallIntoModuleJSVM_Env__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.
CallFinalizerJSVM_Env__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.
EnqueueFinalizerJSVM_Env__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.
DequeueFinalizerJSVM_Env__176   virtual void DequeueFinalizer(v8impl::RefTracker* finalizer) {
177     pending_finalizers.erase(finalizer);
178   }
179 
180   virtual void DeleteMe();
181 
CheckGCAccessJSVM_Env__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>
NewJsvmDataJSVM_Env__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 
ReleaseJsvmDataJSVM_Env__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 
jsvm_clear_last_error(JSVM_Env env)251 inline 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 
jsvm_set_last_error(JSVM_Env env, JSVM_Status errorCode, uint32_t engineErrorCode = 0, void* engineReserved = nullptr)259 inline 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 
385 namespace 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*.
391 static_assert(sizeof(v8::Local<v8::Value>) == sizeof(JSVM_Value),
392               "Cannot convert between v8::Local<v8::Value> and JSVM_Value");
393 
JsValueFromV8LocalValue(v8::Local<v8::Value> local)394 inline JSVM_Value JsValueFromV8LocalValue(v8::Local<v8::Value> local) {
395   return reinterpret_cast<JSVM_Value>(*local);
396 }
397 
V8LocalValueFromJsValue(JSVM_Value v)398 inline 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.
405 class Finalizer {
406  protected:
Finalizer(JSVM_Env env, JSVM_Finalize finalize_callback, void* finalize_data, void* finalize_hint)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:
New(JSVM_Env env, JSVM_Finalize finalize_callback = nullptr, void* finalize_data = nullptr, void* finalize_hint = nullptr)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 
callback()426   JSVM_Finalize callback() { return finalize_callback_; }
data()427   void* data() { return finalize_data_; }
hint()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 
439 class TryCatch : public v8::TryCatch {
440  public:
TryCatch(JSVM_Env env)441   explicit TryCatch(JSVM_Env env) : v8::TryCatch(env->isolate), _env(env) {}
442 
~TryCatch()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.
454 enum 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.
464 class 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.
484 class 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 
ownership()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.
517 class 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();
HasDeletedByUser()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 
554 typedef JSVM_Value (* GetterCallback)(JSVM_Env, JSVM_Value, JSVM_Value, JSVM_Value);
555 typedef JSVM_Value (* SetterCallback)(JSVM_Env, JSVM_Value, JSVM_Value, JSVM_Value, JSVM_Value);
556 typedef JSVM_Value (* DeleterCallback)(JSVM_Env, JSVM_Value, JSVM_Value, JSVM_Value);
557 typedef JSVM_Value (* EnumeratorCallback)(JSVM_Env, JSVM_Value, JSVM_Value);
558 
559 struct 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 
CreatePropertyCfg(JSVM_Env env, JSVM_PropertyHandlerCfg propertyCfg)572 inline 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 
CfgFinalizedCallback(JSVM_Env env, void* finalizeData, void* finalizeHint)602 inline 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
615 namespace ResourceSchedule {
616 namespace ResType {
617 enum : uint32_t {
618   RES_TYPE_REPORT_KEY_THREAD = 39
619 };
620 
621 enum ReportChangeStatus : int64_t {
622   CREATE = 0,
623   REMOVE = 1
624 };
625 
626 enum 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 
ReportKeyThread(uid_t uid, pid_t pid, pid_t tid, ResType::ThreadRole role)636 static 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