@xiacg/exia-event 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,109 @@
1
+ /**
2
+ * @Description: 事件管理器 - 支持递归保护
3
+ */
4
+ /**
5
+ * 事件管理器 - 防止递归调用栈溢出
6
+ *
7
+ * 功能特性:
8
+ * - 递归深度限制防止栈溢出
9
+ * - 完全向后兼容现有API
10
+ */
11
+ declare class EventManager {
12
+ /**
13
+ * 添加事件监听器
14
+ * @param name - 事件名称
15
+ * @param callback - 回调函数,当事件触发时执行
16
+ * @param target - 可选参数,指定事件监听的目标对象
17
+ * @returns 返回事件ID,可用于移除事件
18
+ */
19
+ add(name: string, callback: (...args: any[]) => void, target?: any): number;
20
+ /**
21
+ * 添加一个只触发一次的事件监听器
22
+ * @param name - 事件名称
23
+ * @param callback - 事件触发时要执行的回调函数
24
+ * @param target - 可选参数,指定事件监听器的目标对象
25
+ * @returns 返回事件ID,可用于移除事件
26
+ */
27
+ addOnce(name: string, callback: (...args: any[]) => void, target?: any): number;
28
+ /**
29
+ * 发送事件给所有注册的监听器(带递归保护)
30
+ * @param name - 事件名称
31
+ * @param target - 可选参数,指定目标对象,只有目标对象匹配时才会触发监听器
32
+ * @param args - 传递给监听器回调函数的参数
33
+ */
34
+ send(name: string, target?: any, ...args: any[]): void;
35
+ /**
36
+ * 通过事件ID移除事件
37
+ * @param eventId 事件ID
38
+ */
39
+ remove(eventId: number): void;
40
+ /**
41
+ * 移除指定名称的所有事件
42
+ * @param name 事件名称
43
+ */
44
+ removeByName(name: string): void;
45
+ /**
46
+ * 移除指定目标的所有事件
47
+ * @param target 目标对象
48
+ */
49
+ removeByTarget(target: any): void;
50
+ /**
51
+ * 移除指定名称和指定目标的事件
52
+ * @param name 事件名称
53
+ * @param target 绑定的目标对象
54
+ */
55
+ removeByNameAndTarget(name: string, target: any): void;
56
+ /**
57
+ * 清空所有注册的事件
58
+ */
59
+ clearAll(): void;
60
+ }
61
+
62
+ /**
63
+ * @Description: 全局事件
64
+ */
65
+ declare class GlobalEvent {
66
+ /**
67
+ * 添加一个事件
68
+ * @param name 事件名称
69
+ * @param callback 事件回调
70
+ * @param target 事件目标
71
+ */
72
+ static add(name: string, callback: (...args: any[]) => void, target?: any): number;
73
+ /**
74
+ * 添加一个只触发一次的事件
75
+ */
76
+ static addOnce(name: string, callback: (...args: any[]) => void, target?: any): number;
77
+ /**
78
+ * 发送一个事件
79
+ * @param name 事件名称
80
+ * @param args 事件参数
81
+ */
82
+ static send(name: string, ...args: any[]): void;
83
+ /**
84
+ * 发送一个事件给指定目标
85
+ * @param name 事件名称
86
+ * @param target 事件目标
87
+ * @param args 事件参数
88
+ */
89
+ static sendToTarget(name: string, target: any, ...args: any[]): void;
90
+ /**
91
+ * 移除一个指定ID的事件
92
+ * @param eventId 事件ID
93
+ */
94
+ static remove(eventId: number): void;
95
+ static removeByName(name: string): void;
96
+ static removeByTarget(target: any): void;
97
+ /**
98
+ * 通过目标和事件名称批量移除事件
99
+ * @param name 事件名称
100
+ * @param target 事件目标
101
+ */
102
+ static removeByNameAndTarget(name: string, target: any): void;
103
+ /**
104
+ * 清空所有事件
105
+ */
106
+ static clearAll(): void;
107
+ }
108
+
109
+ export { EventManager, GlobalEvent };
@@ -0,0 +1 @@
1
+ "use strict";var e;!function(e){e[e.Add=1]="Add",e[e.RemoveById=2]="RemoveById",e[e.RemoveByName=3]="RemoveByName",e[e.RemoveByTarget=4]="RemoveByTarget",e[e.RemoveByNameAndTarget=5]="RemoveByNameAndTarget",e[e.ClearAll=6]="ClearAll"}(e||(e={}));class t{constructor(){this.type=e.Add}reset(){this.type=e.Add,this.eventId=0,this.event=null,this.name=null,this.target=null}}class s{constructor(){this.commands=[],this.index=0,this.length=0,this.clearAll=!1}addEvent(s){if(this.index==this.length){let a=new t;a.type=e.Add,a.event=s,this.commands.push(a),this.length++,this.index++}else{let t=this.commands[this.index++];t.type=e.Add,t.event=s}}add(s,a,n,i){if(s!=e.ClearAll)if(this.index==this.length){let e=new t;e.type=s,e.eventId=a,e.name=n,e.target=i,this.commands.push(e),this.length++,this.index++}else{let e=this.commands[this.index++];e.type=s,e.eventId=a,e.name=n,e.target=i}else this.clearAll=!0}forEach(t){if(this.clearAll)t({type:e.ClearAll,eventId:0,event:null,name:null,target:null,reset:null});else{for(let e=0;e<this.index;e++){let s=this.commands[e];t(s),s.reset()}this.index=0}}clear(){this.commands.length=0,this.index=0,this.clearAll=!1,this.length=0}}class a{constructor(){this.once=!1}}class n{constructor(e,t){this._id=0,this._stack=[],this._maxCapacity=64,this._maxCapacity=e,this._msgClass=t}allocate(){if(0==this._stack.length){const e=new this._msgClass;return e.id=++this._id,e}const e=this._stack.pop();return e.id=++this._id,e}recycle(e){return this._maxCapacity>0&&this._stack.length<this._maxCapacity&&(this._stack.push(e),!0)}}class i{constructor(){this.sending_depth=0,this.events=new Map,this.nameToIds=new Map,this.targetToIds=new Map,this.factory=new n(64,a),this.commandManager=new s}add(e,t,s){if(!e)throw new Error("事件名称不能为空");if(!t)throw new Error("回调函数不能为空");let a=this.factory.allocate();return a.name=e,a.callback=t,a.target=s,a.once=!1,this.sending_depth>0?(this.commandManager.addEvent(a),a.id):(this._addEvent(a),a.id)}addOnce(e,t,s){if(!e)throw new Error("事件名称不能为空");if(!t)throw new Error("回调函数不能为空");let a=this.factory.allocate();return a.name=e,a.callback=t,a.target=s,a.once=!0,this.sending_depth>0?(this.commandManager.addEvent(a),a.id):(this._addEvent(a),a.id)}_addEvent(e){this.events.set(e.id,e),this.nameToIds.has(e.name)||this.nameToIds.set(e.name,new Set);this.nameToIds.get(e.name).add(e.id);let t=e.target;t&&(this.targetToIds.has(t)||this.targetToIds.set(t,new Set),this.targetToIds.get(t).add(e.id))}send(t,s,...a){if(this.sending_depth>=20)return console.error("[EventManager] 递归深度超出限制!"),console.error(` 事件名称: "${t}"`),console.error(` 当前深度: ${this.sending_depth}`),console.error(" 最大深度: 20"),void console.error(" 为防止栈溢出,事件执行已被阻止");if(!this.nameToIds.has(t))return;const n=this.nameToIds.get(t);if(0===n.size)return;const i=[],r=[];this.sending_depth++;for(const e of n.values()){if(!this.events.has(e)){i.push(e);continue}let t=this.events.get(e);s&&s!==t.target||(r.push(t),t.once&&i.push(e))}for(const e of r)e.callback(...a);if(this.sending_depth--,0===this.sending_depth){if(i.length>0)for(const e of i)this.remove(e);this.commandManager.forEach(t=>{switch(t.type){case e.Add:this._addEvent(t.event);break;case e.RemoveById:this.remove(t.eventId);break;case e.RemoveByName:this.removeByName(t.name);break;case e.RemoveByTarget:this.removeByTarget(t.target);break;case e.RemoveByNameAndTarget:this.removeByNameAndTarget(t.name,t.target);break;case e.ClearAll:this.clearAll()}})}}remove(t){if(!this.events.has(t))return;if(this.sending_depth>0)return void this.commandManager.add(e.RemoveById,t,null,null);let s=this.events.get(t),a=s.name,n=s.target;this.events.delete(t),this.factory.recycle(s),this.nameToIds.has(a)&&this.nameToIds.get(a).delete(t),n&&this.targetToIds.has(n)&&this.targetToIds.get(n).delete(t)}removeByName(t){if(!this.nameToIds.has(t))return;let s=this.nameToIds.get(t);0!==s.size&&(this.sending_depth>0?this.commandManager.add(e.RemoveByName,null,t,null):(s.forEach(e=>{if(this.events.has(e)){let t=this.events.get(e);t.target&&this.targetToIds.has(t.target)&&this.targetToIds.get(t.target).delete(e),this.events.delete(e),this.factory.recycle(t)}}),this.nameToIds.delete(t)))}removeByTarget(t){if(!this.targetToIds.has(t))return;let s=this.targetToIds.get(t);0!==s.size&&(this.sending_depth>0?this.commandManager.add(e.RemoveByTarget,null,null,t):(s.forEach(e=>{if(this.events.has(e)){let t=this.events.get(e);this.nameToIds.has(t.name)&&this.nameToIds.get(t.name).delete(e),this.events.delete(e),this.factory.recycle(t)}}),this.targetToIds.delete(t)))}removeByNameAndTarget(t,s){if(!this.nameToIds.has(t))return;let a=this.nameToIds.get(t),n=this.targetToIds.get(s);if(0===a.size||!n||0===n.size)return;if(this.sending_depth>0)return void this.commandManager.add(e.RemoveByNameAndTarget,null,t,s);const i=[];if(a.size<n.size?a.forEach(e=>{this.events.get(e).target===s&&i.push(e)}):n.forEach(e=>{this.events.get(e).name===t&&i.push(e)}),i.length>0)for(const e of i)this.remove(e)}clearAll(){if(this.sending_depth>0)this.commandManager.add(e.ClearAll,null,null,null);else{for(const e of this.events.values())this.factory.recycle(e);this.events.clear(),this.nameToIds.clear(),this.targetToIds.clear(),this.commandManager.clear(),this.sending_depth=0}}}class r{static add(e,t,s){return this.event.add(e,t,s)}static addOnce(e,t,s){return this.event.addOnce(e,t,s)}static send(e,...t){this.event.send(e,null,...t)}static sendToTarget(e,t,...s){this.event.send(e,t,...s)}static remove(e){this.event.remove(e)}static removeByName(e){this.event.removeByName(e)}static removeByTarget(e){this.event.removeByTarget(e)}static removeByNameAndTarget(e,t){this.event.removeByNameAndTarget(e,t)}static clearAll(){this.event.clearAll()}}r.event=new i,exports.EventManager=i,exports.GlobalEvent=r;
@@ -0,0 +1 @@
1
+ var e;!function(e){e[e.Add=1]="Add",e[e.RemoveById=2]="RemoveById",e[e.RemoveByName=3]="RemoveByName",e[e.RemoveByTarget=4]="RemoveByTarget",e[e.RemoveByNameAndTarget=5]="RemoveByNameAndTarget",e[e.ClearAll=6]="ClearAll"}(e||(e={}));class t{constructor(){this.type=e.Add}reset(){this.type=e.Add,this.eventId=0,this.event=null,this.name=null,this.target=null}}class s{constructor(){this.commands=[],this.index=0,this.length=0,this.clearAll=!1}addEvent(s){if(this.index==this.length){let a=new t;a.type=e.Add,a.event=s,this.commands.push(a),this.length++,this.index++}else{let t=this.commands[this.index++];t.type=e.Add,t.event=s}}add(s,a,n,i){if(s!=e.ClearAll)if(this.index==this.length){let e=new t;e.type=s,e.eventId=a,e.name=n,e.target=i,this.commands.push(e),this.length++,this.index++}else{let e=this.commands[this.index++];e.type=s,e.eventId=a,e.name=n,e.target=i}else this.clearAll=!0}forEach(t){if(this.clearAll)t({type:e.ClearAll,eventId:0,event:null,name:null,target:null,reset:null});else{for(let e=0;e<this.index;e++){let s=this.commands[e];t(s),s.reset()}this.index=0}}clear(){this.commands.length=0,this.index=0,this.clearAll=!1,this.length=0}}class a{constructor(){this.once=!1}}class n{constructor(e,t){this._id=0,this._stack=[],this._maxCapacity=64,this._maxCapacity=e,this._msgClass=t}allocate(){if(0==this._stack.length){const e=new this._msgClass;return e.id=++this._id,e}const e=this._stack.pop();return e.id=++this._id,e}recycle(e){return this._maxCapacity>0&&this._stack.length<this._maxCapacity&&(this._stack.push(e),!0)}}class i{constructor(){this.sending_depth=0,this.events=new Map,this.nameToIds=new Map,this.targetToIds=new Map,this.factory=new n(64,a),this.commandManager=new s}add(e,t,s){if(!e)throw new Error("事件名称不能为空");if(!t)throw new Error("回调函数不能为空");let a=this.factory.allocate();return a.name=e,a.callback=t,a.target=s,a.once=!1,this.sending_depth>0?(this.commandManager.addEvent(a),a.id):(this._addEvent(a),a.id)}addOnce(e,t,s){if(!e)throw new Error("事件名称不能为空");if(!t)throw new Error("回调函数不能为空");let a=this.factory.allocate();return a.name=e,a.callback=t,a.target=s,a.once=!0,this.sending_depth>0?(this.commandManager.addEvent(a),a.id):(this._addEvent(a),a.id)}_addEvent(e){this.events.set(e.id,e),this.nameToIds.has(e.name)||this.nameToIds.set(e.name,new Set);this.nameToIds.get(e.name).add(e.id);let t=e.target;t&&(this.targetToIds.has(t)||this.targetToIds.set(t,new Set),this.targetToIds.get(t).add(e.id))}send(t,s,...a){if(this.sending_depth>=20)return console.error("[EventManager] 递归深度超出限制!"),console.error(` 事件名称: "${t}"`),console.error(` 当前深度: ${this.sending_depth}`),console.error(" 最大深度: 20"),void console.error(" 为防止栈溢出,事件执行已被阻止");if(!this.nameToIds.has(t))return;const n=this.nameToIds.get(t);if(0===n.size)return;const i=[],h=[];this.sending_depth++;for(const e of n.values()){if(!this.events.has(e)){i.push(e);continue}let t=this.events.get(e);s&&s!==t.target||(h.push(t),t.once&&i.push(e))}for(const e of h)e.callback(...a);if(this.sending_depth--,0===this.sending_depth){if(i.length>0)for(const e of i)this.remove(e);this.commandManager.forEach(t=>{switch(t.type){case e.Add:this._addEvent(t.event);break;case e.RemoveById:this.remove(t.eventId);break;case e.RemoveByName:this.removeByName(t.name);break;case e.RemoveByTarget:this.removeByTarget(t.target);break;case e.RemoveByNameAndTarget:this.removeByNameAndTarget(t.name,t.target);break;case e.ClearAll:this.clearAll()}})}}remove(t){if(!this.events.has(t))return;if(this.sending_depth>0)return void this.commandManager.add(e.RemoveById,t,null,null);let s=this.events.get(t),a=s.name,n=s.target;this.events.delete(t),this.factory.recycle(s),this.nameToIds.has(a)&&this.nameToIds.get(a).delete(t),n&&this.targetToIds.has(n)&&this.targetToIds.get(n).delete(t)}removeByName(t){if(!this.nameToIds.has(t))return;let s=this.nameToIds.get(t);0!==s.size&&(this.sending_depth>0?this.commandManager.add(e.RemoveByName,null,t,null):(s.forEach(e=>{if(this.events.has(e)){let t=this.events.get(e);t.target&&this.targetToIds.has(t.target)&&this.targetToIds.get(t.target).delete(e),this.events.delete(e),this.factory.recycle(t)}}),this.nameToIds.delete(t)))}removeByTarget(t){if(!this.targetToIds.has(t))return;let s=this.targetToIds.get(t);0!==s.size&&(this.sending_depth>0?this.commandManager.add(e.RemoveByTarget,null,null,t):(s.forEach(e=>{if(this.events.has(e)){let t=this.events.get(e);this.nameToIds.has(t.name)&&this.nameToIds.get(t.name).delete(e),this.events.delete(e),this.factory.recycle(t)}}),this.targetToIds.delete(t)))}removeByNameAndTarget(t,s){if(!this.nameToIds.has(t))return;let a=this.nameToIds.get(t),n=this.targetToIds.get(s);if(0===a.size||!n||0===n.size)return;if(this.sending_depth>0)return void this.commandManager.add(e.RemoveByNameAndTarget,null,t,s);const i=[];if(a.size<n.size?a.forEach(e=>{this.events.get(e).target===s&&i.push(e)}):n.forEach(e=>{this.events.get(e).name===t&&i.push(e)}),i.length>0)for(const e of i)this.remove(e)}clearAll(){if(this.sending_depth>0)this.commandManager.add(e.ClearAll,null,null,null);else{for(const e of this.events.values())this.factory.recycle(e);this.events.clear(),this.nameToIds.clear(),this.targetToIds.clear(),this.commandManager.clear(),this.sending_depth=0}}}class h{static add(e,t,s){return this.event.add(e,t,s)}static addOnce(e,t,s){return this.event.addOnce(e,t,s)}static send(e,...t){this.event.send(e,null,...t)}static sendToTarget(e,t,...s){this.event.send(e,t,...s)}static remove(e){this.event.remove(e)}static removeByName(e){this.event.removeByName(e)}static removeByTarget(e){this.event.removeByTarget(e)}static removeByNameAndTarget(e,t){this.event.removeByNameAndTarget(e,t)}static clearAll(){this.event.clearAll()}}h.event=new i;export{i as EventManager,h as GlobalEvent};
@@ -0,0 +1,562 @@
1
+ /**
2
+ * @Description: 命令
3
+ */
4
+ var CommandType;
5
+ (function (CommandType) {
6
+ CommandType[CommandType["Add"] = 1] = "Add";
7
+ CommandType[CommandType["RemoveById"] = 2] = "RemoveById";
8
+ CommandType[CommandType["RemoveByName"] = 3] = "RemoveByName";
9
+ CommandType[CommandType["RemoveByTarget"] = 4] = "RemoveByTarget";
10
+ CommandType[CommandType["RemoveByNameAndTarget"] = 5] = "RemoveByNameAndTarget";
11
+ CommandType[CommandType["ClearAll"] = 6] = "ClearAll";
12
+ })(CommandType || (CommandType = {}));
13
+ /**
14
+ * 命令
15
+ * @internal
16
+ */
17
+ class Command {
18
+ constructor() {
19
+ this.type = CommandType.Add;
20
+ }
21
+ reset() {
22
+ this.type = CommandType.Add;
23
+ this.eventId = 0;
24
+ this.event = null;
25
+ this.name = null;
26
+ this.target = null;
27
+ }
28
+ }
29
+ /**
30
+ * 命令管理器
31
+ * @internal
32
+ */
33
+ class CommandManager {
34
+ constructor() {
35
+ this.commands = [];
36
+ this.index = 0;
37
+ this.length = 0;
38
+ this.clearAll = false;
39
+ }
40
+ /**
41
+ * 添加一个添加事件的命令
42
+ * @param event 事件
43
+ */
44
+ addEvent(event) {
45
+ if (this.index == this.length) {
46
+ let command = new Command();
47
+ command.type = CommandType.Add;
48
+ command.event = event;
49
+ this.commands.push(command);
50
+ this.length++;
51
+ this.index++;
52
+ }
53
+ else {
54
+ let command = this.commands[this.index++];
55
+ command.type = CommandType.Add;
56
+ command.event = event;
57
+ }
58
+ }
59
+ /**
60
+ * 添加一个删除事件或者清理所有的命令
61
+ */
62
+ add(type, eventId, name, target) {
63
+ if (type == CommandType.ClearAll) {
64
+ this.clearAll = true;
65
+ return;
66
+ }
67
+ if (this.index == this.length) {
68
+ let command = new Command();
69
+ command.type = type;
70
+ command.eventId = eventId;
71
+ command.name = name;
72
+ command.target = target;
73
+ this.commands.push(command);
74
+ this.length++;
75
+ this.index++;
76
+ }
77
+ else {
78
+ let command = this.commands[this.index++];
79
+ command.type = type;
80
+ command.eventId = eventId;
81
+ command.name = name;
82
+ command.target = target;
83
+ }
84
+ }
85
+ forEach(callback) {
86
+ if (this.clearAll) {
87
+ callback({
88
+ type: CommandType.ClearAll,
89
+ eventId: 0,
90
+ event: null,
91
+ name: null,
92
+ target: null,
93
+ reset: null,
94
+ });
95
+ return;
96
+ }
97
+ for (let i = 0; i < this.index; i++) {
98
+ let command = this.commands[i];
99
+ callback(command);
100
+ command.reset();
101
+ }
102
+ this.index = 0;
103
+ }
104
+ clear() {
105
+ this.commands.length = 0;
106
+ this.index = 0;
107
+ this.clearAll = false;
108
+ this.length = 0;
109
+ }
110
+ }
111
+
112
+ /** @internal */
113
+ class Event {
114
+ constructor() {
115
+ this.once = false;
116
+ }
117
+ }
118
+
119
+ /** @internal */
120
+ class EventFactory {
121
+ constructor(capacity, objectClass) {
122
+ this._id = 0;
123
+ this._stack = [];
124
+ this._maxCapacity = 64;
125
+ this._maxCapacity = capacity;
126
+ this._msgClass = objectClass;
127
+ }
128
+ allocate() {
129
+ if (this._stack.length == 0) {
130
+ const ret = new this._msgClass();
131
+ ret.id = ++this._id;
132
+ return ret;
133
+ }
134
+ const ret = this._stack.pop();
135
+ // 分配新ID,避免ID重用导致误删
136
+ ret.id = ++this._id;
137
+ return ret;
138
+ }
139
+ recycle(ret) {
140
+ if (this._maxCapacity > 0 && this._stack.length < this._maxCapacity) {
141
+ this._stack.push(ret);
142
+ return true;
143
+ }
144
+ return false;
145
+ }
146
+ }
147
+
148
+ /**
149
+ * @Description: 事件管理器 - 支持递归保护
150
+ */
151
+ /**
152
+ * 最大递归深度常量
153
+ */
154
+ const MAX_RECURSION_DEPTH = 20;
155
+ /**
156
+ * 事件管理器 - 防止递归调用栈溢出
157
+ *
158
+ * 功能特性:
159
+ * - 递归深度限制防止栈溢出
160
+ * - 完全向后兼容现有API
161
+ */
162
+ class EventManager {
163
+ constructor() {
164
+ /**
165
+ * 当前递归发送深度
166
+ * 0 表示没有在发送,> 0 表示正在发送事件
167
+ * @internal
168
+ */
169
+ this.sending_depth = 0;
170
+ /**
171
+ * 注册的所有事件 事件ID -> 事件
172
+ * @internal
173
+ */
174
+ this.events = new Map();
175
+ /**
176
+ * 事件名称 -> 事件ID集合
177
+ * @internal
178
+ */
179
+ this.nameToIds = new Map();
180
+ /**
181
+ * 事件目标 -> 事件ID集合
182
+ * @internal
183
+ */
184
+ this.targetToIds = new Map();
185
+ /**
186
+ * 事件工厂
187
+ * @internal
188
+ */
189
+ this.factory = new EventFactory(64, Event);
190
+ /**
191
+ * 命令管理器
192
+ * @internal
193
+ */
194
+ this.commandManager = new CommandManager();
195
+ }
196
+ /**
197
+ * 添加事件监听器
198
+ * @param name - 事件名称
199
+ * @param callback - 回调函数,当事件触发时执行
200
+ * @param target - 可选参数,指定事件监听的目标对象
201
+ * @returns 返回事件ID,可用于移除事件
202
+ */
203
+ add(name, callback, target) {
204
+ if (!name) {
205
+ throw new Error("事件名称不能为空");
206
+ }
207
+ if (!callback) {
208
+ throw new Error("回调函数不能为空");
209
+ }
210
+ let event = this.factory.allocate();
211
+ event.name = name;
212
+ event.callback = callback;
213
+ event.target = target;
214
+ event.once = false;
215
+ if (this.sending_depth > 0) {
216
+ this.commandManager.addEvent(event);
217
+ return event.id;
218
+ }
219
+ this._addEvent(event);
220
+ return event.id;
221
+ }
222
+ /**
223
+ * 添加一个只触发一次的事件监听器
224
+ * @param name - 事件名称
225
+ * @param callback - 事件触发时要执行的回调函数
226
+ * @param target - 可选参数,指定事件监听器的目标对象
227
+ * @returns 返回事件ID,可用于移除事件
228
+ */
229
+ addOnce(name, callback, target) {
230
+ if (!name) {
231
+ throw new Error("事件名称不能为空");
232
+ }
233
+ if (!callback) {
234
+ throw new Error("回调函数不能为空");
235
+ }
236
+ let event = this.factory.allocate();
237
+ event.name = name;
238
+ event.callback = callback;
239
+ event.target = target;
240
+ event.once = true;
241
+ if (this.sending_depth > 0) {
242
+ this.commandManager.addEvent(event);
243
+ return event.id;
244
+ }
245
+ this._addEvent(event);
246
+ return event.id;
247
+ }
248
+ /**
249
+ * 添加事件内部方法
250
+ * @param event 事件对象
251
+ * @internal
252
+ */
253
+ _addEvent(event) {
254
+ this.events.set(event.id, event);
255
+ if (!this.nameToIds.has(event.name)) {
256
+ this.nameToIds.set(event.name, new Set());
257
+ }
258
+ const ids = this.nameToIds.get(event.name);
259
+ ids.add(event.id);
260
+ let target = event.target;
261
+ if (target) {
262
+ if (!this.targetToIds.has(target)) {
263
+ this.targetToIds.set(target, new Set());
264
+ }
265
+ this.targetToIds.get(target).add(event.id);
266
+ }
267
+ }
268
+ /**
269
+ * 发送事件给所有注册的监听器(带递归保护)
270
+ * @param name - 事件名称
271
+ * @param target - 可选参数,指定目标对象,只有目标对象匹配时才会触发监听器
272
+ * @param args - 传递给监听器回调函数的参数
273
+ */
274
+ send(name, target, ...args) {
275
+ // 递归深度保护:阻止超过限制的执行并报告错误
276
+ if (this.sending_depth >= MAX_RECURSION_DEPTH) {
277
+ console.error(`[EventManager] 递归深度超出限制!`);
278
+ console.error(` 事件名称: "${name}"`);
279
+ console.error(` 当前深度: ${this.sending_depth}`);
280
+ console.error(` 最大深度: ${MAX_RECURSION_DEPTH}`);
281
+ console.error(` 为防止栈溢出,事件执行已被阻止`);
282
+ return;
283
+ }
284
+ if (!this.nameToIds.has(name)) {
285
+ return;
286
+ }
287
+ const eventIds = this.nameToIds.get(name);
288
+ if (eventIds.size === 0) {
289
+ return;
290
+ }
291
+ // 使用局部变量,避免嵌套调用时互相污染
292
+ const needRemoveIds = [];
293
+ const triggerList = [];
294
+ // 增加递归深度
295
+ this.sending_depth++;
296
+ // 构建触发列表
297
+ for (const eventId of eventIds.values()) {
298
+ if (!this.events.has(eventId)) {
299
+ needRemoveIds.push(eventId);
300
+ continue;
301
+ }
302
+ let event = this.events.get(eventId);
303
+ if (!target || target === event.target) {
304
+ triggerList.push(event);
305
+ if (event.once) {
306
+ needRemoveIds.push(eventId);
307
+ }
308
+ }
309
+ }
310
+ // 同步触发事件
311
+ for (const event of triggerList) {
312
+ event.callback(...args);
313
+ }
314
+ // 减少递归深度
315
+ this.sending_depth--;
316
+ // 只在最外层执行清理工作
317
+ if (this.sending_depth === 0) {
318
+ // 清理 once 事件
319
+ if (needRemoveIds.length > 0) {
320
+ for (const id of needRemoveIds) {
321
+ this.remove(id);
322
+ }
323
+ }
324
+ // 处理命令队列
325
+ this.commandManager.forEach((command) => {
326
+ switch (command.type) {
327
+ case CommandType.Add:
328
+ this._addEvent(command.event);
329
+ break;
330
+ case CommandType.RemoveById:
331
+ this.remove(command.eventId);
332
+ break;
333
+ case CommandType.RemoveByName:
334
+ this.removeByName(command.name);
335
+ break;
336
+ case CommandType.RemoveByTarget:
337
+ this.removeByTarget(command.target);
338
+ break;
339
+ case CommandType.RemoveByNameAndTarget:
340
+ this.removeByNameAndTarget(command.name, command.target);
341
+ break;
342
+ case CommandType.ClearAll:
343
+ this.clearAll();
344
+ break;
345
+ }
346
+ });
347
+ }
348
+ }
349
+ /**
350
+ * 通过事件ID移除事件
351
+ * @param eventId 事件ID
352
+ */
353
+ remove(eventId) {
354
+ if (!this.events.has(eventId)) {
355
+ return;
356
+ }
357
+ if (this.sending_depth > 0) {
358
+ this.commandManager.add(CommandType.RemoveById, eventId, null, null);
359
+ return;
360
+ }
361
+ let event = this.events.get(eventId);
362
+ let name = event.name;
363
+ let target = event.target;
364
+ this.events.delete(eventId);
365
+ this.factory.recycle(event);
366
+ if (this.nameToIds.has(name)) {
367
+ this.nameToIds.get(name).delete(eventId);
368
+ }
369
+ if (target && this.targetToIds.has(target)) {
370
+ this.targetToIds.get(target).delete(eventId);
371
+ }
372
+ }
373
+ /**
374
+ * 移除指定名称的所有事件
375
+ * @param name 事件名称
376
+ */
377
+ removeByName(name) {
378
+ if (!this.nameToIds.has(name)) {
379
+ return;
380
+ }
381
+ let eventIds = this.nameToIds.get(name);
382
+ if (eventIds.size === 0) {
383
+ return;
384
+ }
385
+ if (this.sending_depth > 0) {
386
+ this.commandManager.add(CommandType.RemoveByName, null, name, null);
387
+ return;
388
+ }
389
+ eventIds.forEach((eventId) => {
390
+ if (this.events.has(eventId)) {
391
+ let event = this.events.get(eventId);
392
+ if (event.target && this.targetToIds.has(event.target)) {
393
+ this.targetToIds.get(event.target).delete(eventId);
394
+ }
395
+ this.events.delete(eventId);
396
+ this.factory.recycle(event);
397
+ }
398
+ });
399
+ this.nameToIds.delete(name);
400
+ }
401
+ /**
402
+ * 移除指定目标的所有事件
403
+ * @param target 目标对象
404
+ */
405
+ removeByTarget(target) {
406
+ if (!this.targetToIds.has(target)) {
407
+ return;
408
+ }
409
+ let eventIds = this.targetToIds.get(target);
410
+ if (eventIds.size === 0) {
411
+ return;
412
+ }
413
+ if (this.sending_depth > 0) {
414
+ this.commandManager.add(CommandType.RemoveByTarget, null, null, target);
415
+ return;
416
+ }
417
+ eventIds.forEach((eventId) => {
418
+ if (this.events.has(eventId)) {
419
+ let event = this.events.get(eventId);
420
+ if (this.nameToIds.has(event.name)) {
421
+ this.nameToIds.get(event.name).delete(eventId);
422
+ }
423
+ this.events.delete(eventId);
424
+ this.factory.recycle(event);
425
+ }
426
+ });
427
+ this.targetToIds.delete(target);
428
+ }
429
+ /**
430
+ * 移除指定名称和指定目标的事件
431
+ * @param name 事件名称
432
+ * @param target 绑定的目标对象
433
+ */
434
+ removeByNameAndTarget(name, target) {
435
+ if (!this.nameToIds.has(name)) {
436
+ return;
437
+ }
438
+ let nameIds = this.nameToIds.get(name);
439
+ let targetIds = this.targetToIds.get(target);
440
+ // 检查targetIds是否存在,避免NPE
441
+ if (nameIds.size === 0 || !targetIds || targetIds.size === 0) {
442
+ return;
443
+ }
444
+ if (this.sending_depth > 0) {
445
+ this.commandManager.add(CommandType.RemoveByNameAndTarget, null, name, target);
446
+ return;
447
+ }
448
+ // 使用局部变量
449
+ const needRemoveIds = [];
450
+ if (nameIds.size < targetIds.size) {
451
+ nameIds.forEach((eventId) => {
452
+ let event = this.events.get(eventId);
453
+ if (event.target === target) {
454
+ needRemoveIds.push(eventId);
455
+ }
456
+ });
457
+ }
458
+ else {
459
+ targetIds.forEach((eventId) => {
460
+ let event = this.events.get(eventId);
461
+ if (event.name === name) {
462
+ needRemoveIds.push(eventId);
463
+ }
464
+ });
465
+ }
466
+ if (needRemoveIds.length > 0) {
467
+ for (const id of needRemoveIds) {
468
+ this.remove(id);
469
+ }
470
+ }
471
+ }
472
+ /**
473
+ * 清空所有注册的事件
474
+ */
475
+ clearAll() {
476
+ if (this.sending_depth > 0) {
477
+ this.commandManager.add(CommandType.ClearAll, null, null, null);
478
+ return;
479
+ }
480
+ for (const event of this.events.values()) {
481
+ this.factory.recycle(event);
482
+ }
483
+ this.events.clear();
484
+ this.nameToIds.clear();
485
+ this.targetToIds.clear();
486
+ this.commandManager.clear();
487
+ // 清理递归保护相关状态
488
+ this.sending_depth = 0;
489
+ }
490
+ }
491
+
492
+ /**
493
+ * @Description: 全局事件
494
+ */
495
+ class GlobalEvent {
496
+ /**
497
+ * 添加一个事件
498
+ * @param name 事件名称
499
+ * @param callback 事件回调
500
+ * @param target 事件目标
501
+ */
502
+ static add(name, callback, target) {
503
+ return this.event.add(name, callback, target);
504
+ }
505
+ /**
506
+ * 添加一个只触发一次的事件
507
+ */
508
+ static addOnce(name, callback, target) {
509
+ return this.event.addOnce(name, callback, target);
510
+ }
511
+ /**
512
+ * 发送一个事件
513
+ * @param name 事件名称
514
+ * @param args 事件参数
515
+ */
516
+ static send(name, ...args) {
517
+ this.event.send(name, null, ...args);
518
+ }
519
+ /**
520
+ * 发送一个事件给指定目标
521
+ * @param name 事件名称
522
+ * @param target 事件目标
523
+ * @param args 事件参数
524
+ */
525
+ static sendToTarget(name, target, ...args) {
526
+ this.event.send(name, target, ...args);
527
+ }
528
+ /**
529
+ * 移除一个指定ID的事件
530
+ * @param eventId 事件ID
531
+ */
532
+ static remove(eventId) {
533
+ this.event.remove(eventId);
534
+ }
535
+ static removeByName(name) {
536
+ this.event.removeByName(name);
537
+ }
538
+ static removeByTarget(target) {
539
+ this.event.removeByTarget(target);
540
+ }
541
+ /**
542
+ * 通过目标和事件名称批量移除事件
543
+ * @param name 事件名称
544
+ * @param target 事件目标
545
+ */
546
+ static removeByNameAndTarget(name, target) {
547
+ this.event.removeByNameAndTarget(name, target);
548
+ }
549
+ /**
550
+ * 清空所有事件
551
+ */
552
+ static clearAll() {
553
+ this.event.clearAll();
554
+ }
555
+ }
556
+ /**
557
+ * 事件管理器
558
+ * @internal
559
+ */
560
+ GlobalEvent.event = new EventManager();
561
+
562
+ export { EventManager, GlobalEvent };