• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 "events_emitter.h"
17 
18 #include <iterator>
19 #include <memory>
20 #include <mutex>
21 #include <new>
22 #include <uv.h>
23 #include <unordered_set>
24 #include "event_logger.h"
25 #include "js_native_api_types.h"
26 #include "napi/native_node_api.h"
27 
28 using namespace std;
29 namespace OHOS {
30 namespace AppExecFwk {
31 namespace {
32     DEFINE_EH_HILOG_LABEL("EventsEmitter");
33     constexpr static uint32_t ARGC_ONE = 1u;
34 }
35     static std::mutex g_emitterInsMutex;
36     static map<InnerEvent::EventId, std::unordered_set<std::shared_ptr<AsyncCallbackInfo>>> emitterInstances;
37     std::shared_ptr<EventHandlerInstance> eventHandler;
~AsyncCallbackInfo()38     AsyncCallbackInfo::~AsyncCallbackInfo()
39     {
40         env = nullptr;
41     }
EventHandlerInstance(const std::shared_ptr<EventRunner> & runner)42     EventHandlerInstance::EventHandlerInstance(const std::shared_ptr<EventRunner>& runner): EventHandler(runner)
43     {
44         HILOGI("EventHandlerInstance constructed");
45     }
~EventHandlerInstance()46     EventHandlerInstance::~EventHandlerInstance()
47     {
48         HILOGI("EventHandlerInstance de-constructed");
49     }
GetInstance()50     std::shared_ptr<EventHandlerInstance> EventHandlerInstance::GetInstance()
51     {
52         static auto runner = EventRunner::Create("OS_eventsEmtr", ThreadMode::FFRT);
53         if (runner.get() == nullptr) {
54             HILOGE("failed to create EventRunner events_emitter");
55             return nullptr;
56         }
57         static auto instance = std::make_shared<EventHandlerInstance>(runner);
58         return instance;
59     }
60 
ProcessCallback(const EventDataWorker * eventDataInner)61     void ProcessCallback(const EventDataWorker* eventDataInner)
62     {
63         HILOGD("emit ProcessCallback enter");
64 
65         std::shared_ptr<AsyncCallbackInfo> callbackInner = eventDataInner->callbackInfo;
66         napi_value resultData = nullptr;
67         if (eventDataInner->data != nullptr && *(eventDataInner->data) != nullptr) {
68             if (napi_deserialize(callbackInner->env, *(eventDataInner->data), &resultData) != napi_ok ||
69                 resultData == nullptr) {
70                 HILOGE("Deserialize fail.");
71                 return;
72             }
73         }
74         napi_value event = nullptr;
75         napi_create_object(callbackInner->env, &event);
76         napi_set_named_property(callbackInner->env, event, "data", resultData);
77         napi_value callback = nullptr;
78         napi_value returnVal = nullptr;
79         napi_get_reference_value(callbackInner->env, callbackInner->callback, &callback);
80         napi_call_function(callbackInner->env, nullptr, callback, 1, &event, &returnVal);
81         if (callbackInner->once) {
82             HILOGD("ProcessEvent delete once");
83             std::lock_guard<std::mutex> lock(g_emitterInsMutex);
84             auto iter = emitterInstances.find(callbackInner->eventId);
85             if (iter != emitterInstances.end()) {
86                 auto callback = iter->second.find(callbackInner);
87                 if (callback != iter->second.end()) {
88                     iter->second.erase(callback);
89                 }
90             }
91         }
92     }
93 
OutPutEventIdLog(const InnerEvent::EventId & eventId)94     void OutPutEventIdLog(const InnerEvent::EventId &eventId)
95     {
96         if (eventId.index() == TYPE_U32_INDEX) {
97             HILOGD("Event id value:%{public}u", std::get<uint32_t>(eventId));
98         } else {
99             HILOGD("Event id value:%{public}s", std::get<std::string>(eventId).c_str());
100         }
101     }
102 
ThreadSafeCallback(napi_env env,napi_value jsCallback,void * context,void * data)103     void ThreadSafeCallback(napi_env env, napi_value jsCallback, void* context, void* data)
104     {
105         napi_handle_scope scope;
106         EventDataWorker* eventDataInner = static_cast<EventDataWorker*>(data);
107         if (eventDataInner != nullptr) {
108             auto callbackInfoInner = eventDataInner->callbackInfo;
109             if (callbackInfoInner && !(callbackInfoInner->isDeleted)) {
110                 napi_open_handle_scope(callbackInfoInner->env, &scope);
111                 if (scope == nullptr) {
112                     HILOGD("Scope is null");
113                     return;
114                 }
115                 ProcessCallback(eventDataInner);
116                 napi_close_handle_scope(callbackInfoInner->env, scope);
117             }
118         }
119         delete eventDataInner;
120         eventDataInner = nullptr;
121         data = nullptr;
122     }
123 
GetAsyncCallbackInfo(const InnerEvent::EventId & eventId)124     std::unordered_set<std::shared_ptr<AsyncCallbackInfo>> EventHandlerInstance::GetAsyncCallbackInfo(
125         const InnerEvent::EventId &eventId)
126     {
127         std::lock_guard<std::mutex> lock(g_emitterInsMutex);
128         auto iter = emitterInstances.find(eventId);
129         if (iter == emitterInstances.end()) {
130             std::unordered_set<std::shared_ptr<AsyncCallbackInfo>> result;
131             HILOGW("ProcessEvent has no callback");
132             return result;
133         }
134         for (auto it = iter->second.begin(); it != iter->second.end();) {
135             if ((*it)->isDeleted == true || (*it)->env == nullptr) {
136                 it = iter->second.erase(it);
137                 continue;
138             }
139             ++it;
140         }
141         return iter->second;
142     }
143 
ProcessEvent(const InnerEvent::Pointer & event)144     void EventHandlerInstance::ProcessEvent([[maybe_unused]] const InnerEvent::Pointer& event)
145     {
146         InnerEvent::EventId eventId = event->GetInnerEventIdEx();
147         OutPutEventIdLog(eventId);
148         auto callbackInfos = GetAsyncCallbackInfo(eventId);
149         if (callbackInfos.size() <= 0) {
150             HILOGW("ProcessEvent has no valid callback");
151             return;
152         }
153 
154         size_t callbackSize = callbackInfos.size();
155         HILOGD("size = %{public}zu", callbackSize);
156         auto value = event->GetUniqueObject<napi_value>();
157         std::shared_ptr<napi_value> eventData(value.release(), [this](napi_value* pData) {
158             if (pData != nullptr && (*pData) != nullptr && deleteEnv != nullptr) {
159                 napi_delete_serialization_data(deleteEnv, *pData);
160             } else {
161                 HILOGW("EventData delete release failed.");
162             }
163         });
164         for (auto it = callbackInfos.begin(); it != callbackInfos.end(); ++it) {
165             callbackSize--;
166             EventDataWorker* eventDataWorker = new (std::nothrow) EventDataWorker();
167             if (!eventDataWorker) {
168                 HILOGE("new object failed");
169                 if (callbackSize == 0) {
170                     HILOGW("EventData maybe release at process %{public}zu", callbackInfos.size());
171                 }
172                 continue;
173             }
174             if ((*it)->env == nullptr || (*it)->isDeleted) {
175                 HILOGE("env is release");
176                 if (callbackSize == 0) {
177                     HILOGW("EventData maybe release at nullptr %{public}zu", callbackInfos.size());
178                 }
179                 delete eventDataWorker;
180                 continue;
181             }
182             deleteEnv = (*it)->env;
183             eventDataWorker->data = eventData;
184             if (callbackSize == 0) {
185                 eventData.reset();
186             }
187             eventDataWorker->callbackInfo = (*it);
188             napi_acquire_threadsafe_function((*it)->tsfn);
189             napi_call_threadsafe_function((*it)->tsfn, eventDataWorker, napi_tsfn_nonblocking);
190             napi_release_threadsafe_function((*it)->tsfn, napi_tsfn_release);
191         }
192     }
193 
UpdateOnceFlag(std::shared_ptr<AsyncCallbackInfo> callbackInfo,bool once)194     static void UpdateOnceFlag(std::shared_ptr<AsyncCallbackInfo>callbackInfo, bool once)
195     {
196         if (!once) {
197             if (callbackInfo->once) {
198                 HILOGD("JS_On change once to on");
199                 callbackInfo->once = false;
200             } else {
201                 HILOGD("JS_On already on");
202             }
203         } else {
204             if (callbackInfo->once) {
205                 HILOGD("JS_Once already once");
206             } else {
207                 HILOGD("JS_Once change on to once");
208                 callbackInfo->once = true;
209             }
210         }
211     }
212 
DeleteCallbackInfo(napi_env env,const InnerEvent::EventId & eventIdValue,napi_value argv)213     void DeleteCallbackInfo(napi_env env, const InnerEvent::EventId &eventIdValue, napi_value argv)
214     {
215         std::lock_guard<std::mutex> lock(g_emitterInsMutex);
216         auto iter = emitterInstances.find(eventIdValue);
217         if (iter == emitterInstances.end()) {
218             return;
219         }
220         for (auto callbackInfo = iter->second.begin(); callbackInfo != iter->second.end();) {
221             napi_value callback = nullptr;
222             if ((*callbackInfo)->env != env) {
223                 ++callbackInfo;
224                 continue;
225             }
226             napi_get_reference_value((*callbackInfo)->env, (*callbackInfo)->callback, &callback);
227             bool isEq = false;
228             napi_strict_equals(env, argv, callback, &isEq);
229             if (!isEq) {
230                 ++callbackInfo;
231                 continue;
232             }
233             (*callbackInfo)->isDeleted = true;
234             callbackInfo = iter->second.erase(callbackInfo);
235             return;
236         }
237         return;
238     }
239 
SearchCallbackInfo(napi_env env,const InnerEvent::EventId & eventIdValue,napi_value argv)240     std::shared_ptr<AsyncCallbackInfo> SearchCallbackInfo(napi_env env, const InnerEvent::EventId &eventIdValue,
241         napi_value argv)
242     {
243         auto subscribe = emitterInstances.find(eventIdValue);
244         if (subscribe == emitterInstances.end()) {
245             return nullptr;
246         }
247         for (auto callbackInfo : subscribe->second) {
248             napi_value callback = nullptr;
249             if (callbackInfo->isDeleted) {
250                 continue;
251             }
252             if (callbackInfo->env != env) {
253                 continue;
254             }
255             napi_get_reference_value(callbackInfo->env, callbackInfo->callback, &callback);
256             bool isEq = false;
257             napi_strict_equals(env, argv, callback, &isEq);
258             if (!isEq) {
259                 continue;
260             }
261             return callbackInfo;
262         }
263         return nullptr;
264     }
265 
GetEventIdWithObjectOrString(napi_env env,napi_value argv,napi_valuetype eventValueType,InnerEvent::EventId & eventId)266     bool GetEventIdWithObjectOrString(
267         napi_env env, napi_value argv, napi_valuetype eventValueType, InnerEvent::EventId &eventId)
268     {
269         if (eventValueType == napi_string) {
270             auto valueCStr = std::make_unique<char[]>(NAPI_VALUE_STRING_LEN + 1);
271             size_t valueStrLength = 0;
272             napi_get_value_string_utf8(env, argv, valueCStr.get(), NAPI_VALUE_STRING_LEN, &valueStrLength);
273             std::string id(valueCStr.get(), valueStrLength);
274             if (id.empty()) {
275                 HILOGE("Event id is empty for argument 1.");
276                 return false;
277             }
278             eventId = id;
279             HILOGD("Event id value:%{public}s", id.c_str());
280         } else {
281             bool hasEventId = false;
282             napi_has_named_property(env, argv, "eventId", &hasEventId);
283             if (!hasEventId) {
284                 HILOGE("Argument 1 does not have event id.");
285                 return false;
286             }
287 
288             napi_value eventIdValue = nullptr;
289             napi_get_named_property(env, argv, "eventId", &eventIdValue);
290             uint32_t id = 0u;
291             napi_get_value_uint32(env, eventIdValue, &id);
292             eventId = id;
293             HILOGD("Event id value:%{public}u", id);
294         }
295         return true;
296     }
297 
ThreadFinished(napi_env env,void * data,void * context)298     void ThreadFinished(napi_env env, void* data, [[maybe_unused]] void* context)
299     {
300         HILOGD("ThreadFinished");
301     }
302 
ReleaseCallbackInfo(AsyncCallbackInfo * callbackInfo)303     void ReleaseCallbackInfo(AsyncCallbackInfo* callbackInfo)
304     {
305         if (callbackInfo != nullptr) {
306             uv_loop_s *loop = nullptr;
307             if (napi_get_uv_event_loop(callbackInfo->env, &loop) != napi_ok) {
308                 delete callbackInfo;
309                 callbackInfo = nullptr;
310                 return;
311             }
312             uv_work_t *work = new (std::nothrow) uv_work_t;
313             if (work == nullptr) {
314                 delete callbackInfo;
315                 callbackInfo = nullptr;
316                 return;
317             }
318             work->data = reinterpret_cast<void*>(callbackInfo);
319             auto ret = uv_queue_work_with_qos(loop, work, [](uv_work_t* work) {},
320             [](uv_work_t *work, int status) {
321                 AsyncCallbackInfo* callbackInfo = reinterpret_cast<AsyncCallbackInfo*>(work->data);
322                 if (napi_delete_reference(callbackInfo->env, callbackInfo->callback) != napi_ok) {
323                     HILOGE("napi_delete_reference fail.");
324                 }
325                 napi_release_threadsafe_function(callbackInfo->tsfn, napi_tsfn_release);
326                 delete callbackInfo;
327                 callbackInfo = nullptr;
328                 delete work;
329                 work = nullptr;
330             }, uv_qos_user_initiated);
331             if (ret != napi_ok)  {
332                 delete callbackInfo;
333                 callbackInfo = nullptr;
334                 delete work;
335                 work = nullptr;
336             }
337         }
338     }
339 
OnOrOnce(napi_env env,napi_callback_info cbinfo,bool once)340     napi_value OnOrOnce(napi_env env, napi_callback_info cbinfo, bool once)
341     {
342         size_t argc = ARGC_NUM;
343         napi_value argv[ARGC_NUM] = {0};
344         NAPI_CALL(env, napi_get_cb_info(env, cbinfo, &argc, argv, NULL, NULL));
345         if (argc < ARGC_NUM) {
346             HILOGE("requires 2 parameter");
347             return nullptr;
348         }
349 
350         napi_valuetype eventValueType = GetNapiType(env, argv[0]);
351         if (eventValueType != napi_object && eventValueType != napi_string) {
352             HILOGE("type mismatch for parameter 1");
353             return nullptr;
354         }
355 
356         if (GetNapiType(env, argv[1]) != napi_function) {
357             HILOGE("type mismatch for parameter 2");
358             return nullptr;
359         }
360 
361         InnerEvent::EventId eventIdValue = 0u;
362         bool ret = GetEventIdWithObjectOrString(env, argv[0], eventValueType, eventIdValue);
363         if (!ret) {
364             return nullptr;
365         }
366         std::lock_guard<std::mutex> lock(g_emitterInsMutex);
367         auto callbackInfo = SearchCallbackInfo(env, eventIdValue, argv[1]);
368         if (callbackInfo != nullptr) {
369             UpdateOnceFlag(callbackInfo, once);
370         } else {
371             callbackInfo = std::shared_ptr<AsyncCallbackInfo>(new (std::nothrow) AsyncCallbackInfo(),
372                 [](AsyncCallbackInfo* callbackInfo) {
373                 ReleaseCallbackInfo(callbackInfo);
374             });
375             if (!callbackInfo) {
376                 HILOGE("new object failed");
377                 return nullptr;
378             }
379             callbackInfo->env = env;
380             callbackInfo->once = once;
381             callbackInfo->eventId = eventIdValue;
382             napi_create_reference(env, argv[1], 1, &callbackInfo->callback);
383             napi_wrap(env, argv[1], new (std::nothrow) std::weak_ptr<AsyncCallbackInfo>(callbackInfo),
384                 [](napi_env env, void* data, void* hint) {
385                 auto callbackInfoPtr = static_cast<std::weak_ptr<AsyncCallbackInfo>*>(data);
386                 if (callbackInfoPtr != nullptr && (*callbackInfoPtr).lock() != nullptr) {
387                     (*callbackInfoPtr).lock()->isDeleted = true;
388                     (*callbackInfoPtr).lock()->env = nullptr;
389                 }
390             }, nullptr, nullptr);
391             napi_value resourceName = nullptr;
392             napi_create_string_utf8(env, "Call thread-safe function", NAPI_AUTO_LENGTH, &resourceName);
393             napi_create_threadsafe_function(env, argv[1], nullptr, resourceName, 0, 1, nullptr, ThreadFinished,
394                 nullptr, ThreadSafeCallback, &(callbackInfo->tsfn));
395             emitterInstances[eventIdValue].insert(callbackInfo);
396         }
397         return nullptr;
398     }
399 
GetEventIdWithNumberOrString(napi_env env,napi_value argv,napi_valuetype eventValueType,InnerEvent::EventId & eventId)400     bool GetEventIdWithNumberOrString(
401         napi_env env, napi_value argv, napi_valuetype eventValueType, InnerEvent::EventId &eventId)
402     {
403         if (eventValueType == napi_string) {
404             auto valueCStr = std::make_unique<char[]>(NAPI_VALUE_STRING_LEN + 1);
405             size_t valueStrLength = 0;
406             napi_get_value_string_utf8(env, argv, valueCStr.get(), NAPI_VALUE_STRING_LEN, &valueStrLength);
407             std::string id(valueCStr.get(), valueStrLength);
408             if (id.empty()) {
409                 return false;
410             }
411             eventId = id;
412             HILOGD("Event id value:%{public}s", id.c_str());
413         } else {
414             uint32_t id = 0u;
415             napi_get_value_uint32(env, argv, &id);
416             eventId = id;
417             HILOGD("Event id value:%{public}u", id);
418         }
419         return true;
420     }
421 
JS_On(napi_env env,napi_callback_info cbinfo)422     napi_value JS_On(napi_env env, napi_callback_info cbinfo)
423     {
424         HILOGD("JS_On enter");
425         return OnOrOnce(env, cbinfo, false);
426     }
427 
JS_Once(napi_env env,napi_callback_info cbinfo)428     napi_value JS_Once(napi_env env, napi_callback_info cbinfo)
429     {
430         HILOGD("JS_Once enter");
431         return OnOrOnce(env, cbinfo, true);
432     }
433 
JS_Off(napi_env env,napi_callback_info cbinfo)434     napi_value JS_Off(napi_env env, napi_callback_info cbinfo)
435     {
436         HILOGD("JS_Off enter");
437         size_t argc = ARGC_NUM;
438         napi_value argv[ARGC_NUM] = {0};
439         NAPI_CALL(env, napi_get_cb_info(env, cbinfo, &argc, argv, NULL, NULL));
440         if (argc < 1) {
441             HILOGE("requires at least 1 parameter");
442             return nullptr;
443         }
444 
445         napi_valuetype eventValueType;
446         napi_typeof(env, argv[0], &eventValueType);
447         if (eventValueType != napi_number && eventValueType != napi_string) {
448             HILOGE("type mismatch for parameter 1");
449             return nullptr;
450         }
451 
452         InnerEvent::EventId eventId = 0u;
453         bool ret = GetEventIdWithNumberOrString(env, argv[0], eventValueType, eventId);
454         if (!ret) {
455             HILOGE("Event id is empty for parameter 1.");
456             return nullptr;
457         }
458 
459         if (argc == ARGC_NUM) {
460             napi_valuetype eventHandleType;
461             napi_typeof(env, argv[1], &eventHandleType);
462             if (eventHandleType != napi_function) {
463                 HILOGE("type mismatch for parameter 2");
464                 return nullptr;
465             }
466             DeleteCallbackInfo(env, eventId, argv[1]);
467             return nullptr;
468         }
469         std::lock_guard<std::mutex> lock(g_emitterInsMutex);
470         auto iter = emitterInstances.find(eventId);
471         if (iter != emitterInstances.end()) {
472             for (auto callbackInfo : iter->second) {
473                 callbackInfo->isDeleted = true;
474             }
475         }
476         emitterInstances.erase(eventId);
477         return nullptr;
478     }
479 
EmitWithEventData(napi_env env,napi_value argv,const InnerEvent::EventId & eventId,Priority priority)480     bool EmitWithEventData(napi_env env, napi_value argv, const InnerEvent::EventId &eventId, Priority priority)
481     {
482         HILOGD("EmitWithEventData enter");
483         napi_valuetype dataType;
484         napi_typeof(env, argv, &dataType);
485         if (dataType != napi_object) {
486             HILOGE("type mismatch for parameter 2");
487             return false;
488         }
489         bool hasData = false;
490         void* serializeData = nullptr;
491         napi_has_named_property(env, argv, "data", &hasData);
492         if (hasData) {
493             napi_value data = nullptr;
494             napi_get_named_property(env, argv, "data", &data);
495             napi_status serializeResult = napi_ok;
496             napi_value undefined = nullptr;
497             napi_get_undefined(env, &undefined);
498             bool defaultTransfer = false;
499             bool defaultCloneSendable = false;
500             serializeResult = napi_serialize_inner(env, data, undefined, undefined,
501                                                    defaultTransfer, defaultCloneSendable, &serializeData);
502             if (serializeResult != napi_ok || serializeData == nullptr) {
503                 HILOGE("Serialize fail.");
504                 return false;
505             }
506         }
507         OutPutEventIdLog(eventId);
508         auto event = InnerEvent::Get(eventId, make_unique<napi_value>(reinterpret_cast<napi_value>(serializeData)));
509         eventHandler->SendEvent(event, 0, priority);
510         return true;
511     }
512 
IsExistValidCallback(napi_env env,const InnerEvent::EventId & eventId)513     bool IsExistValidCallback(napi_env env, const InnerEvent::EventId &eventId)
514     {
515         std::lock_guard<std::mutex> lock(g_emitterInsMutex);
516         auto subscribe = emitterInstances.find(eventId);
517         if (subscribe == emitterInstances.end()) {
518             EH_LOGW_LIMIT("JS_Emit has no callback");
519             return false;
520         }
521         if (subscribe->second.size() != 0) {
522             return true;
523         }
524         return false;
525     }
526 
EmitWithEventIdUint32(napi_env env,size_t argc,napi_value argv[])527     napi_value EmitWithEventIdUint32(napi_env env, size_t argc, napi_value argv[])
528     {
529         InnerEvent::EventId eventId = 0u;
530         bool hasEventId = false;
531         napi_value value = nullptr;
532         napi_has_named_property(env, argv[0], "eventId", &hasEventId);
533         if (hasEventId == false) {
534             HILOGE("Wrong argument 1 does not have event id.");
535             return nullptr;
536         }
537 
538         napi_get_named_property(env, argv[0], "eventId", &value);
539         uint32_t id = 0u;
540         napi_get_value_uint32(env, value, &id);
541         eventId = id;
542         HILOGD("Event id value:%{public}u", id);
543 
544         if (!IsExistValidCallback(env, eventId)) {
545             EH_LOGE_LIMIT("Invalid callback");
546             return nullptr;
547         }
548 
549         bool hasPriority = false;
550         napi_has_named_property(env, argv[0], "priority", &hasPriority);
551         Priority priority = Priority::LOW;
552         if (hasPriority) {
553             napi_get_named_property(env, argv[0], "priority", &value);
554             uint32_t priorityValue = 0u;
555             napi_get_value_uint32(env, value, &priorityValue);
556             HILOGD("Event priority:%{public}d", priorityValue);
557             priority = static_cast<Priority>(priorityValue);
558         }
559 
560         if (argc == ARGC_NUM && EmitWithEventData(env, argv[1], eventId, priority)) {
561             return nullptr;
562         } else {
563             auto event = InnerEvent::Get(eventId, make_unique<EventData>());
564             eventHandler->SendEvent(event, 0, priority);
565         }
566         return nullptr;
567     }
568 
EmitWithEventIdString(napi_env env,size_t argc,napi_value argv[])569     napi_value EmitWithEventIdString(napi_env env, size_t argc, napi_value argv[])
570     {
571         InnerEvent::EventId eventId = 0u;
572         auto valueCStr = std::make_unique<char[]>(NAPI_VALUE_STRING_LEN + 1);
573         size_t valueStrLength = 0;
574         napi_get_value_string_utf8(env, argv[0], valueCStr.get(), NAPI_VALUE_STRING_LEN, &valueStrLength);
575         std::string id(valueCStr.get(), valueStrLength);
576         if (id.empty()) {
577             HILOGE("Invalid event id:%{public}s", id.c_str());
578             return nullptr;
579         }
580         eventId = id;
581         HILOGD("Event id value:%{public}s", id.c_str());
582 
583         if (!IsExistValidCallback(env, eventId)) {
584             EH_LOGE_LIMIT("Invalid callback");
585             return nullptr;
586         }
587 
588         Priority priority = Priority::LOW;
589         if (argc < ARGC_NUM) {
590             auto event = InnerEvent::Get(eventId, make_unique<EventData>());
591             eventHandler->SendEvent(event, 0, priority);
592             return nullptr;
593         }
594 
595         bool hasPriority = false;
596         napi_value value = nullptr;
597         napi_has_named_property(env, argv[1], "priority", &hasPriority);
598         if (!hasPriority) {
599             if (!EmitWithEventData(env, argv[1], eventId, priority)) {
600                 auto event = InnerEvent::Get(eventId, make_unique<EventData>());
601                 eventHandler->SendEvent(event, 0, priority);
602             }
603             return nullptr;
604         }
605 
606         napi_get_named_property(env, argv[1], "priority", &value);
607         uint32_t priorityValue = 0u;
608         napi_get_value_uint32(env, value, &priorityValue);
609         HILOGD("Event priority:%{public}d", priorityValue);
610         priority = static_cast<Priority>(priorityValue);
611 
612         if (argc > ARGC_NUM && EmitWithEventData(env, argv[ARGC_NUM], eventId, priority)) {
613             return nullptr;
614         } else {
615             auto event = InnerEvent::Get(eventId, make_unique<EventData>());
616             eventHandler->SendEvent(event, 0, priority);
617         }
618         return nullptr;
619     }
620 
JS_Emit(napi_env env,napi_callback_info cbinfo)621     napi_value JS_Emit(napi_env env, napi_callback_info cbinfo)
622     {
623         HILOGD("JS_Emit enter");
624         size_t argc = ARGC_NUM + ARGC_ONE;
625         napi_value argv[ARGC_NUM + ARGC_ONE] = {0};
626         NAPI_CALL(env, napi_get_cb_info(env, cbinfo, &argc, argv, NULL, NULL));
627         if (argc < ARGC_ONE) {
628             HILOGE("Requires more than 1 parameter");
629             return nullptr;
630         }
631 
632         napi_valuetype eventValueType;
633         napi_typeof(env, argv[0], &eventValueType);
634         if (eventValueType != napi_object && eventValueType != napi_string) {
635             HILOGE("Type mismatch for parameter 1");
636             return nullptr;
637         }
638 
639         if (eventValueType == napi_string) {
640             return EmitWithEventIdString(env, argc, argv);
641         }
642         return EmitWithEventIdUint32(env, argc, argv);
643     }
644 
EnumEventClassConstructor(napi_env env,napi_callback_info info)645     napi_value EnumEventClassConstructor(napi_env env, napi_callback_info info)
646     {
647         napi_value thisArg = nullptr;
648         void *data = nullptr;
649 
650         napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, &data);
651 
652         napi_value global = nullptr;
653         napi_get_global(env, &global);
654 
655         return thisArg;
656     }
657 
CreateEnumEventPriority(napi_env env,napi_value exports)658     napi_value CreateEnumEventPriority(napi_env env, napi_value exports)
659     {
660         napi_value immediate = nullptr;
661         napi_value high = nullptr;
662         napi_value low = nullptr;
663         napi_value idle = nullptr;
664 
665         napi_create_uint32(env, (uint32_t)Priority::IMMEDIATE, &immediate);
666         napi_create_uint32(env, (uint32_t)Priority::HIGH, &high);
667         napi_create_uint32(env, (uint32_t)Priority::LOW, &low);
668         napi_create_uint32(env, (uint32_t)Priority::IDLE, &idle);
669 
670         napi_property_descriptor desc[] = {
671             DECLARE_NAPI_STATIC_PROPERTY("IMMEDIATE", immediate),
672             DECLARE_NAPI_STATIC_PROPERTY("HIGH", high),
673             DECLARE_NAPI_STATIC_PROPERTY("LOW", low),
674             DECLARE_NAPI_STATIC_PROPERTY("IDLE", idle),
675         };
676         napi_value result = nullptr;
677         napi_define_class(env, "EventPriority", NAPI_AUTO_LENGTH, EnumEventClassConstructor, nullptr,
678             sizeof(desc) / sizeof(*desc), desc, &result);
679 
680         napi_set_named_property(env, exports, "EventPriority", result);
681 
682         return exports;
683     }
684 
CreateJsUndefined(napi_env env)685     napi_value CreateJsUndefined(napi_env env)
686     {
687         napi_value result = nullptr;
688         napi_get_undefined(env, &result);
689         return result;
690     }
691 
CreateJsNumber(napi_env env,uint32_t value)692     napi_value CreateJsNumber(napi_env env, uint32_t value)
693     {
694         napi_value result = nullptr;
695         napi_create_uint32(env, value, &result);
696         return result;
697     }
698 
JS_GetListenerCount(napi_env env,napi_callback_info cbinfo)699     napi_value JS_GetListenerCount(napi_env env, napi_callback_info cbinfo)
700     {
701         HILOGD("JS_GetListenerCount enter");
702         size_t argc = ARGC_NUM;
703         napi_value argv[ARGC_NUM] = {0};
704         NAPI_CALL(env, napi_get_cb_info(env, cbinfo, &argc, argv, NULL, NULL));
705         if (argc < ARGC_ONE) {
706             HILOGE("Requires more than 1 parameter");
707             return CreateJsUndefined(env);
708         }
709 
710         napi_valuetype eventValueType;
711         napi_typeof(env, argv[0], &eventValueType);
712         if (eventValueType != napi_number && eventValueType != napi_string) {
713             HILOGE("Type mismatch for parameter 1");
714             return CreateJsUndefined(env);
715         }
716 
717         uint32_t cnt = 0u;
718         InnerEvent::EventId eventId = 0u;
719         bool ret = GetEventIdWithNumberOrString(env, argv[0], eventValueType, eventId);
720         if (!ret) {
721             HILOGE("Event id is empty for parameter 1.");
722             return CreateJsUndefined(env);
723         }
724         std::lock_guard<std::mutex> lock(g_emitterInsMutex);
725         auto subscribe = emitterInstances.find(eventId);
726         if (subscribe != emitterInstances.end()) {
727             for (auto it = subscribe->second.begin(); it != subscribe->second.end();) {
728                 if ((*it)->isDeleted == true || (*it)->env == nullptr) {
729                     it = subscribe->second.erase(it);
730                     continue;
731                 }
732                 ++it;
733                 ++cnt;
734             }
735         }
736         return CreateJsNumber(env, cnt);
737     }
738 
EmitterInit(napi_env env,napi_value exports)739     napi_value EmitterInit(napi_env env, napi_value exports)
740     {
741         HILOGD("EmitterInit enter");
742         napi_property_descriptor desc[] = {
743             DECLARE_NAPI_FUNCTION("on", JS_On),
744             DECLARE_NAPI_FUNCTION("once", JS_Once),
745             DECLARE_NAPI_FUNCTION("off", JS_Off),
746             DECLARE_NAPI_FUNCTION("emit", JS_Emit),
747             DECLARE_NAPI_FUNCTION("getListenerCount", JS_GetListenerCount),
748         };
749         NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
750 
751         CreateEnumEventPriority(env, exports);
752 
753         eventHandler = EventHandlerInstance::GetInstance();
754         return exports;
755     }
756 }  // namespace AppExecFwk
757 }  // namespace OHOS
758