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