cocos-engine
cocos-engine copied to clipboard
Event System _cachedArray is shared, nested dispatch causes bug
Cocos Creator version
3.8.2
System information
MacOS
Issue description
node-event-processor.ts:
public dispatchEvent (event: Event): void {
const owner = this.node;
let target: Node;
let i = 0;
event.target = owner;
// Event.CAPTURING_PHASE
_cachedArray.length = 0;
this.getCapturingTargets(event.type, _cachedArray);
// capturing
event.eventPhase = 1;
for (i = _cachedArray.length - 1; i >= 0; --i) {
target = _cachedArray[i];
if (target.eventProcessor.capturingTarget) {
event.currentTarget = target;
// fire event
target.eventProcessor.capturingTarget.emit(event.type, event, _cachedArray);
// check if propagation stopped
if (event.propagationStopped) {
_cachedArray.length = 0;
return;
}
}
}
_cachedArray.length = 0;
// Event.AT_TARGET
// checks if destroyed in capturing callbacks
event.eventPhase = 2;
event.currentTarget = owner;
if (this.capturingTarget) {
this.capturingTarget.emit(event.type, event);
}
if (!event.propagationImmediateStopped && this.bubblingTarget) {
this.bubblingTarget.emit(event.type, event);
}
if (!event.propagationStopped && event.bubbles) {
// Event.BUBBLING_PHASE
this.getBubblingTargets(event.type, _cachedArray);
// propagate
event.eventPhase = 3;
for (i = 0; i < _cachedArray.length; ++i) {
target = _cachedArray[i];
if (target.eventProcessor.bubblingTarget) {
event.currentTarget = target;
// fire event
target.eventProcessor.bubblingTarget.emit(event.type, event);
// check if propagation stopped
if (event.propagationStopped) {
_cachedArray.length = 0;
return;
}
}
}
}
_cachedArray.length = 0;
}
If an event is dispatched during the capture or bubbling phase, the event also has a "capture" type listener, which will result in an error.
When there are more than two objects listening to capture events, target is null because the array is cleared.
if (target.eventProcessor.capturingTarget) { <- crash there.
Relevant error log output
No response
Steps to reproduce
.
Minimal reproduction project
No response