Skip to content

Commit fdad2fc

Browse files
committed
Listeners can be removed during dispatch without breaking the array.
1 parent 66a5647 commit fdad2fc

5 files changed

Lines changed: 75 additions & 13 deletions

File tree

v3/src/checksum.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
var CHECKSUM = {
2-
build: '5698c930-bafb-11e6-b48c-79e3e967cbc9'
2+
build: 'c00d4450-bb0e-11e6-9ec8-0d50f46875d4'
33
};
44
module.exports = CHECKSUM;

v3/src/events/EventDispatcher.js

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ EventDispatcher.prototype = {
2323
return;
2424
}
2525

26-
console.log('Add listener', type, listener);
26+
// console.log('Add listener', type, listener);
2727

2828
if (!this.listeners[type])
2929
{
@@ -38,19 +38,19 @@ EventDispatcher.prototype = {
3838
}
3939
else
4040
{
41-
listeners.push({ listener: listener, priority: priority, isOnce: isOnce });
41+
listeners.push({ listener: listener, priority: priority, isOnce: isOnce, toRemove: false });
4242
}
4343

4444
listeners.sort(this.sortHandler);
4545
},
4646

4747
sortHandler: function (listenerA, listenerB)
4848
{
49-
if (listenerA.priority < listenerB.priority)
49+
if (listenerB.priority < listenerA.priority)
5050
{
5151
return -1;
5252
}
53-
else if (listenerA.priority > listenerB.priority)
53+
else if (listenerB.priority > listenerA.priority)
5454
{
5555
return 1;
5656
}
@@ -76,6 +76,8 @@ EventDispatcher.prototype = {
7676

7777
},
7878

79+
// Need to test what happens if array is sorted during DISPATCH phase (does it screw it all up?)
80+
7981
on: function (type, listener, priority)
8082
{
8183
if (priority === undefined) { priority = 0; }
@@ -94,6 +96,16 @@ EventDispatcher.prototype = {
9496
return this;
9597
},
9698

99+
total: function (type)
100+
{
101+
if (!this.listeners || !this.listeners[type])
102+
{
103+
return -1;
104+
}
105+
106+
return this.listeners[type].length;
107+
},
108+
97109
has: function (type, listener)
98110
{
99111
if (!this.listeners || !this.listeners[type])
@@ -129,9 +141,17 @@ EventDispatcher.prototype = {
129141
{
130142
if (listeners[i].listener === listener)
131143
{
132-
console.log('Remove listener', type, listener);
144+
if (this._state === EventDispatcher.STATE_DISPATCHING)
145+
{
146+
console.log('Flag listener for removal', type);
147+
listeners[i].toRemove = true;
148+
}
149+
else
150+
{
151+
console.log('Remove listener', type);
152+
listeners.splice(i, 1);
153+
}
133154

134-
listeners.splice(i, 1);
135155
break;
136156
}
137157
}
@@ -148,21 +168,39 @@ EventDispatcher.prototype = {
148168
return false;
149169
}
150170

151-
this._state = EventDispatcher.STATE_DISPATCHING;
152-
153171
var listeners = this.listeners[event.type];
154172

173+
// This was a valid dispatch call, we just had nothing to do ...
174+
if (listeners.length === 0)
175+
{
176+
return true;
177+
}
178+
179+
this._state = EventDispatcher.STATE_DISPATCHING;
180+
155181
event.reset(this);
156182

157183
var toRemove = [];
184+
185+
var entry;
158186
var entries = listeners.slice();
187+
// var entries = listeners;
159188

160189
console.log('Dispatching', entries.length, 'listeners');
161190

162191
for (var i = 0; i < entries.length; i++)
163192
{
193+
entry = entries[i];
194+
195+
if (entry.toRemove)
196+
{
197+
toRemove.push(entry);
198+
continue;
199+
}
200+
164201
// Add Custom Events
165-
entries[i].listener.call(this, event);
202+
// If this adjusts the entries.length for any reason, the reference is still valid
203+
entry.listener.call(this, event);
166204

167205
// Has the callback done something disastrous? Like called removeAll, or nuked the dispatcher?
168206
if (this._state !== EventDispatcher.STATE_DISPATCHING)
@@ -171,9 +209,10 @@ EventDispatcher.prototype = {
171209
break;
172210
}
173211

174-
if (entries[i].isOnce)
212+
// Was a 'once' or was removed during the callback
213+
if (entry.isOnce || entry.toRemove)
175214
{
176-
toRemove.push(entries[i]);
215+
toRemove.push(entry);
177216
}
178217

179218
// Has the event been halted?
@@ -200,9 +239,11 @@ EventDispatcher.prototype = {
200239

201240
for (i = 0; i < toRemove.length; i++)
202241
{
203-
this.off(toRemove[i].type, toRemove[i].listener);
242+
this.off(event.type, toRemove[i].listener);
204243
}
205244

245+
toRemove.length = 0;
246+
206247
this._state = EventDispatcher.STATE_PENDING;
207248
}
208249

v3/src/loader/BaseLoader.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
var FILE_CONST = require('./const');
33
var Set = require('../structs/Set');
44
var XHRSettings = require('./XHRSettings');
5+
var Events = require('./events/');
56

67
var BaseLoader = function ()
78
{
@@ -90,6 +91,8 @@ BaseLoader.prototype = {
9091
return;
9192
}
9293

94+
this.state.sys.events.dispatch(new Events.LOADER_START_EVENT(this));
95+
9396
if (this.list.size === 0)
9497
{
9598
this.finishedLoading();
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
var Event = require('../../events/Event');
2+
3+
var LoaderStartEvent = function (loader)
4+
{
5+
Event.call(this);
6+
7+
this.loader = loader;
8+
};
9+
10+
LoaderStartEvent.prototype = Object.create(Event.prototype);
11+
LoaderStartEvent.prototype.constructor = LoaderStartEvent;
12+
13+
module.exports = LoaderStartEvent;

v3/src/loader/events/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
3+
LOADER_START_EVENT: require('./LoaderStartEvent')
4+
5+
};

0 commit comments

Comments
 (0)