133eb0b6dSopenharmony_ci/* 233eb0b6dSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 333eb0b6dSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 433eb0b6dSopenharmony_ci * you may not use this file except in compliance with the License. 533eb0b6dSopenharmony_ci * You may obtain a copy of the License at 633eb0b6dSopenharmony_ci * 733eb0b6dSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 833eb0b6dSopenharmony_ci * 933eb0b6dSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1033eb0b6dSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1133eb0b6dSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1233eb0b6dSopenharmony_ci * See the License for the specific language governing permissions and 1333eb0b6dSopenharmony_ci * limitations under the License. 1433eb0b6dSopenharmony_ci */ 1533eb0b6dSopenharmony_ci#include "event_target.h" 1633eb0b6dSopenharmony_ci 1733eb0b6dSopenharmony_ci#include <cstring> 1833eb0b6dSopenharmony_ci 1933eb0b6dSopenharmony_ci#include "securec.h" 2033eb0b6dSopenharmony_ci#include "utils/log.h" 2133eb0b6dSopenharmony_ci 2233eb0b6dSopenharmony_ci#define LISTENER_TYPTE_MAX_LENGTH 64 2333eb0b6dSopenharmony_ci 2433eb0b6dSopenharmony_cistruct EventListener { 2533eb0b6dSopenharmony_ci char type[LISTENER_TYPTE_MAX_LENGTH] = { 0 }; 2633eb0b6dSopenharmony_ci bool isOnce = false; 2733eb0b6dSopenharmony_ci napi_ref handlerRef = nullptr; 2833eb0b6dSopenharmony_ci EventListener* back = nullptr; 2933eb0b6dSopenharmony_ci EventListener* next = nullptr; 3033eb0b6dSopenharmony_ci}; 3133eb0b6dSopenharmony_ci 3233eb0b6dSopenharmony_ciEventTarget::EventTarget(napi_env env, napi_value thisVar) 3333eb0b6dSopenharmony_ci : env_(env), thisVarRef_(nullptr), first_(nullptr), last_(nullptr) 3433eb0b6dSopenharmony_ci{ 3533eb0b6dSopenharmony_ci napi_create_reference(env, thisVar, 1, &thisVarRef_); 3633eb0b6dSopenharmony_ci} 3733eb0b6dSopenharmony_ci 3833eb0b6dSopenharmony_ciEventTarget::~EventTarget() 3933eb0b6dSopenharmony_ci{ 4033eb0b6dSopenharmony_ci EventListener* temp = nullptr; 4133eb0b6dSopenharmony_ci for (EventListener* i = first_; i != nullptr; i = temp) { 4233eb0b6dSopenharmony_ci temp = i->next; 4333eb0b6dSopenharmony_ci if (i == first_) { 4433eb0b6dSopenharmony_ci first_ = first_->next; 4533eb0b6dSopenharmony_ci } else if (i == last_) { 4633eb0b6dSopenharmony_ci last_ = last_->back; 4733eb0b6dSopenharmony_ci } else { 4833eb0b6dSopenharmony_ci i->next->back = i->back; 4933eb0b6dSopenharmony_ci i->back->next = i->next; 5033eb0b6dSopenharmony_ci } 5133eb0b6dSopenharmony_ci napi_delete_reference(env_, i->handlerRef); 5233eb0b6dSopenharmony_ci delete i; 5333eb0b6dSopenharmony_ci } 5433eb0b6dSopenharmony_ci napi_delete_reference(env_, thisVarRef_); 5533eb0b6dSopenharmony_ci} 5633eb0b6dSopenharmony_ci 5733eb0b6dSopenharmony_civoid EventTarget::On(const char* type, napi_value handler) 5833eb0b6dSopenharmony_ci{ 5933eb0b6dSopenharmony_ci auto tmp = new EventListener(); 6033eb0b6dSopenharmony_ci 6133eb0b6dSopenharmony_ci if (strncpy_s(tmp->type, LISTENER_TYPTE_MAX_LENGTH, type, strlen(type)) != EOK) { 6233eb0b6dSopenharmony_ci delete tmp; 6333eb0b6dSopenharmony_ci tmp = nullptr; 6433eb0b6dSopenharmony_ci return; 6533eb0b6dSopenharmony_ci } 6633eb0b6dSopenharmony_ci 6733eb0b6dSopenharmony_ci if (first_ == nullptr) { 6833eb0b6dSopenharmony_ci first_ = last_ = tmp; 6933eb0b6dSopenharmony_ci } else { 7033eb0b6dSopenharmony_ci last_->next = tmp; 7133eb0b6dSopenharmony_ci last_->next->back = last_; 7233eb0b6dSopenharmony_ci last_ = last_->next; 7333eb0b6dSopenharmony_ci } 7433eb0b6dSopenharmony_ci last_->isOnce = false; 7533eb0b6dSopenharmony_ci napi_create_reference(env_, handler, 1, &last_->handlerRef); 7633eb0b6dSopenharmony_ci} 7733eb0b6dSopenharmony_ci 7833eb0b6dSopenharmony_civoid EventTarget::Once(const char* type, napi_value handler) 7933eb0b6dSopenharmony_ci{ 8033eb0b6dSopenharmony_ci auto tmp = new EventListener(); 8133eb0b6dSopenharmony_ci 8233eb0b6dSopenharmony_ci if (strncpy_s(tmp->type, LISTENER_TYPTE_MAX_LENGTH, type, strlen(type)) != EOK) { 8333eb0b6dSopenharmony_ci delete tmp; 8433eb0b6dSopenharmony_ci tmp = nullptr; 8533eb0b6dSopenharmony_ci return; 8633eb0b6dSopenharmony_ci } 8733eb0b6dSopenharmony_ci 8833eb0b6dSopenharmony_ci if (first_ == nullptr) { 8933eb0b6dSopenharmony_ci first_ = last_ = tmp; 9033eb0b6dSopenharmony_ci } else { 9133eb0b6dSopenharmony_ci last_->next = tmp; 9233eb0b6dSopenharmony_ci last_->next->back = last_; 9333eb0b6dSopenharmony_ci last_ = last_->next; 9433eb0b6dSopenharmony_ci } 9533eb0b6dSopenharmony_ci last_->isOnce = true; 9633eb0b6dSopenharmony_ci napi_create_reference(env_, handler, 1, &last_->handlerRef); 9733eb0b6dSopenharmony_ci} 9833eb0b6dSopenharmony_ci 9933eb0b6dSopenharmony_civoid EventTarget::Off(const char* type, napi_value handler) 10033eb0b6dSopenharmony_ci{ 10133eb0b6dSopenharmony_ci napi_handle_scope scope = nullptr; 10233eb0b6dSopenharmony_ci napi_open_handle_scope(env_, &scope); 10333eb0b6dSopenharmony_ci if (scope == nullptr) { 10433eb0b6dSopenharmony_ci HILOG_ERROR("scope is nullptr"); 10533eb0b6dSopenharmony_ci return; 10633eb0b6dSopenharmony_ci } 10733eb0b6dSopenharmony_ci 10833eb0b6dSopenharmony_ci EventListener* temp = nullptr; 10933eb0b6dSopenharmony_ci for (EventListener* eventListener = first_; eventListener != nullptr; eventListener = temp) { 11033eb0b6dSopenharmony_ci temp = eventListener->next; 11133eb0b6dSopenharmony_ci bool isEquals = false; 11233eb0b6dSopenharmony_ci napi_value handlerTemp = nullptr; 11333eb0b6dSopenharmony_ci napi_get_reference_value(env_, eventListener->handlerRef, &handlerTemp); 11433eb0b6dSopenharmony_ci napi_strict_equals(env_, handlerTemp, handler, &isEquals); 11533eb0b6dSopenharmony_ci if (strcmp(eventListener->type, type) == 0 && isEquals) { 11633eb0b6dSopenharmony_ci if (eventListener == first_) { 11733eb0b6dSopenharmony_ci first_ = first_->next; 11833eb0b6dSopenharmony_ci } else if (eventListener == last_) { 11933eb0b6dSopenharmony_ci last_ = last_->back; 12033eb0b6dSopenharmony_ci } else { 12133eb0b6dSopenharmony_ci eventListener->next->back = eventListener->back; 12233eb0b6dSopenharmony_ci eventListener->back->next = eventListener->next; 12333eb0b6dSopenharmony_ci } 12433eb0b6dSopenharmony_ci napi_delete_reference(env_, eventListener->handlerRef); 12533eb0b6dSopenharmony_ci delete eventListener; 12633eb0b6dSopenharmony_ci eventListener = nullptr; 12733eb0b6dSopenharmony_ci break; 12833eb0b6dSopenharmony_ci } 12933eb0b6dSopenharmony_ci } 13033eb0b6dSopenharmony_ci napi_close_handle_scope(env_, scope); 13133eb0b6dSopenharmony_ci} 13233eb0b6dSopenharmony_ci 13333eb0b6dSopenharmony_civoid EventTarget::Off(const char* type) 13433eb0b6dSopenharmony_ci{ 13533eb0b6dSopenharmony_ci EventListener* temp = nullptr; 13633eb0b6dSopenharmony_ci for (EventListener* eventListener = first_; eventListener != nullptr; eventListener = temp) { 13733eb0b6dSopenharmony_ci temp = eventListener->next; 13833eb0b6dSopenharmony_ci if (strcmp(eventListener->type, type) == 0) { 13933eb0b6dSopenharmony_ci if (eventListener == first_) { 14033eb0b6dSopenharmony_ci first_ = first_->next; 14133eb0b6dSopenharmony_ci } else if (eventListener == last_) { 14233eb0b6dSopenharmony_ci last_ = last_->back; 14333eb0b6dSopenharmony_ci } else { 14433eb0b6dSopenharmony_ci eventListener->next->back = eventListener->back; 14533eb0b6dSopenharmony_ci eventListener->back->next = eventListener->next; 14633eb0b6dSopenharmony_ci } 14733eb0b6dSopenharmony_ci napi_delete_reference(env_, eventListener->handlerRef); 14833eb0b6dSopenharmony_ci delete eventListener; 14933eb0b6dSopenharmony_ci eventListener = nullptr; 15033eb0b6dSopenharmony_ci } 15133eb0b6dSopenharmony_ci } 15233eb0b6dSopenharmony_ci} 15333eb0b6dSopenharmony_ci 15433eb0b6dSopenharmony_civoid EventTarget::Emit(const char* type, Event* event) 15533eb0b6dSopenharmony_ci{ 15633eb0b6dSopenharmony_ci napi_handle_scope scope = nullptr; 15733eb0b6dSopenharmony_ci napi_open_handle_scope(env_, &scope); 15833eb0b6dSopenharmony_ci 15933eb0b6dSopenharmony_ci napi_value thisVar = nullptr; 16033eb0b6dSopenharmony_ci napi_get_reference_value(env_, thisVarRef_, &thisVar); 16133eb0b6dSopenharmony_ci for (EventListener* eventListener = first_; eventListener != nullptr; eventListener = eventListener->next) { 16233eb0b6dSopenharmony_ci if (strcmp(eventListener->type, type) == 0) { 16333eb0b6dSopenharmony_ci napi_value jsEvent = event ? event->ToJsObject() : nullptr; 16433eb0b6dSopenharmony_ci napi_value handler = nullptr; 16533eb0b6dSopenharmony_ci napi_get_reference_value(env_, eventListener->handlerRef, &handler); 16633eb0b6dSopenharmony_ci napi_call_function(env_, thisVar, handler, jsEvent ? 1 : 0, jsEvent ? &jsEvent : nullptr, nullptr); 16733eb0b6dSopenharmony_ci if (eventListener->isOnce) { 16833eb0b6dSopenharmony_ci Off(type, handler); 16933eb0b6dSopenharmony_ci } 17033eb0b6dSopenharmony_ci } 17133eb0b6dSopenharmony_ci } 17233eb0b6dSopenharmony_ci 17333eb0b6dSopenharmony_ci napi_close_handle_scope(env_, scope); 17433eb0b6dSopenharmony_ci} 175