Skip to content

Commit 386c6df

Browse files
committed
Merge pull request phaserjs#1359 from pnstickne/wip-optimize-signal
Signal - memory optimization / reductions
2 parents 5b757ea + e62442b commit 386c6df

2 files changed

Lines changed: 94 additions & 40 deletions

File tree

src/core/Signal.js

Lines changed: 64 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,54 +12,49 @@
1212
* @constructor
1313
*/
1414
Phaser.Signal = function () {
15+
};
16+
17+
Phaser.Signal.prototype = {
1518

1619
/**
17-
* @property {Array.<Phaser.SignalBinding>} _bindings - Internal variable.
20+
* @property {?Array.<Phaser.SignalBinding>} _bindings - Internal variable.
1821
* @private
1922
*/
20-
this._bindings = [];
23+
_bindings: null,
2124

2225
/**
2326
* @property {any} _prevParams - Internal variable.
2427
* @private
2528
*/
26-
this._prevParams = null;
27-
28-
// enforce dispatch to aways work on same context (#47)
29-
var self = this;
30-
31-
/**
32-
* @property {function} dispatch - The dispatch function is what sends the Signal out.
33-
*/
34-
this.dispatch = function(){
35-
Phaser.Signal.prototype.dispatch.apply(self, arguments);
36-
};
29+
_prevParams: null,
3730

3831
/**
3932
* If Signal should keep record of previously dispatched parameters and
4033
* automatically execute listener during `add()`/`addOnce()` if Signal was
4134
* already dispatched before.
4235
* @property {boolean} memorize
4336
*/
44-
this.memorize = false;
37+
memorize: false,
4538

4639
/**
4740
* @property {boolean} _shouldPropagate
4841
* @private
4942
*/
50-
this._shouldPropagate = true;
43+
_shouldPropagate: true,
5144

5245
/**
5346
* If Signal is active and should broadcast events.
5447
* IMPORTANT: Setting this property during a dispatch will only affect the next dispatch, if you want to stop the propagation of a signal use `halt()` instead.
5548
* @property {boolean} active
5649
* @default
5750
*/
58-
this.active = true;
59-
60-
};
51+
active: true,
6152

62-
Phaser.Signal.prototype = {
53+
/**
54+
* @property {function} _boundDispatch - The bound dispatch function, if any.
55+
* @private
56+
*/
57+
_boundDispatch: true,
6358

6459
/**
6560
* @method Phaser.Signal#validateListener
@@ -121,6 +116,11 @@ Phaser.Signal.prototype = {
121116
*/
122117
_addBinding: function (binding) {
123118

119+
if (!this._bindings)
120+
{
121+
this._bindings = [];
122+
}
123+
124124
// Simplified insertion sort
125125
var n = this._bindings.length;
126126

@@ -137,10 +137,18 @@ Phaser.Signal.prototype = {
137137
* @method Phaser.Signal#_indexOfListener
138138
* @private
139139
* @param {function} listener - Signal handler function.
140+
* @param {object} [context=null] - Signal handler function.
140141
* @return {number} The index of the listener within the private bindings array.
141142
*/
142143
_indexOfListener: function (listener, context) {
143144

145+
if (!this._bindings)
146+
{
147+
return -1;
148+
}
149+
150+
if (typeof context === 'undefined') { context = null; }
151+
144152
var n = this._bindings.length;
145153
var cur;
146154

@@ -211,7 +219,7 @@ Phaser.Signal.prototype = {
211219
*
212220
* @method Phaser.Signal#remove
213221
* @param {function} listener - Handler function that should be removed.
214-
* @param {object} [context] - Execution context (since you can add the same handler multiple times if executing in a different context).
222+
* @param {object} [context=null] - Execution context (since you can add the same handler multiple times if executing in a different context).
215223
* @return {function} Listener handler function.
216224
*/
217225
remove: function (listener, context) {
@@ -240,6 +248,11 @@ Phaser.Signal.prototype = {
240248

241249
if (typeof context === 'undefined') { context = null; }
242250

251+
if (!this._bindings)
252+
{
253+
return;
254+
}
255+
243256
var n = this._bindings.length;
244257

245258
while (n--)
@@ -273,7 +286,7 @@ Phaser.Signal.prototype = {
273286
*/
274287
getNumListeners: function () {
275288

276-
return this._bindings.length;
289+
return this._bindings ? this._bindings.length : 0;
277290

278291
},
279292

@@ -293,12 +306,14 @@ Phaser.Signal.prototype = {
293306
/**
294307
* Dispatch/Broadcast Signal to all listeners added to the queue.
295308
*
309+
* To create a bound dispatch for this Signal, use {@link Phaser.Signal#boundDispatch}.
310+
*
296311
* @method Phaser.Signal#dispatch
297312
* @param {any} [params] - Parameters that should be passed to each handler.
298313
*/
299314
dispatch: function () {
300315

301-
if (!this.active)
316+
if (!this.active || !this._bindings)
302317
{
303318
return;
304319
}
@@ -338,7 +353,10 @@ Phaser.Signal.prototype = {
338353
*/
339354
forget: function() {
340355

341-
this._prevParams = null;
356+
if (this._prevParams)
357+
{
358+
this._prevParams = null;
359+
}
342360

343361
},
344362

@@ -352,8 +370,11 @@ Phaser.Signal.prototype = {
352370

353371
this.removeAll();
354372

355-
delete this._bindings;
356-
delete this._prevParams;
373+
this._bindings = null;
374+
if (this._prevParams)
375+
{
376+
this._prevParams = null;
377+
}
357378

358379
},
359380

@@ -370,4 +391,22 @@ Phaser.Signal.prototype = {
370391

371392
};
372393

394+
/**
395+
* If the dispatch function needs to be passed somewhere, or called independently
396+
* of the Signal object, use this function.
397+
*
398+
* @memberof Phaser.Signal
399+
* @property {function} boundDispatch
400+
*/
401+
Object.defineProperty(Phaser.Signal.prototype, "boundDispatch", {
402+
403+
get: function () {
404+
var _this = this;
405+
return this._boundDispatch || (this._boundDispatch = function () {
406+
return _this.dispatch.apply(_this, arguments);
407+
});
408+
}
409+
410+
});
411+
373412
Phaser.Signal.prototype.constructor = Phaser.Signal;

src/core/SignalBinding.js

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* @param {Phaser.Signal} signal - Reference to Signal object that listener is currently bound to.
1616
* @param {function} listener - Handler function bound to the signal.
1717
* @param {boolean} isOnce - If binding should be executed just once.
18-
* @param {object} [listenerContext] - Context on which listener will be executed (object that should represent the `this` variable inside listener function).
18+
* @param {object} [listenerContext=null] - Context on which listener will be executed (object that should represent the `this` variable inside listener function).
1919
* @param {number} [priority] - The priority level of the event listener. (default = 0).
2020
*/
2121
Phaser.SignalBinding = function (signal, listener, isOnce, listenerContext, priority) {
@@ -26,51 +26,66 @@ Phaser.SignalBinding = function (signal, listener, isOnce, listenerContext, prio
2626
*/
2727
this._listener = listener;
2828

29+
if (isOnce)
30+
{
31+
this._isOnce = true;
32+
}
33+
34+
if (listenerContext != null) /* not null/undefined */
35+
{
36+
this.context = listenerContext;
37+
}
38+
2939
/**
30-
* @property {boolean} _isOnce - If binding should be executed just once.
40+
* @property {Phaser.Signal} _signal - Reference to Signal object that listener is currently bound to.
3141
* @private
3242
*/
33-
this._isOnce = isOnce;
43+
this._signal = signal;
44+
45+
if (priority)
46+
{
47+
this._priority = priority;
48+
}
49+
50+
};
51+
52+
Phaser.SignalBinding.prototype = {
3453

3554
/**
36-
* @property {object|undefined|null} context - Context on which listener will be executed (object that should represent the `this` variable inside listener function).
55+
* @property {?object} context - Context on which listener will be executed (object that should represent the `this` variable inside listener function).
3756
*/
38-
this.context = listenerContext;
57+
context: null,
3958

4059
/**
41-
* @property {Phaser.Signal} _signal - Reference to Signal object that listener is currently bound to.
60+
* @property {boolean} _isOnce - If binding should be executed just once.
4261
* @private
4362
*/
44-
this._signal = signal;
63+
_isOnce: false,
4564

4665
/**
4766
* @property {number} _priority - Listener priority.
4867
* @private
4968
*/
50-
this._priority = priority || 0;
69+
_priority: 0,
5170

5271
/**
5372
* @property {number} callCount - The number of times the handler function has been called.
5473
*/
55-
this.callCount = 0;
74+
callCount: 0,
5675

5776
/**
5877
* If binding is active and should be executed.
5978
* @property {boolean} active
6079
* @default
6180
*/
62-
this.active = true;
81+
active: true,
6382

6483
/**
6584
* Default parameters passed to listener during `Signal.dispatch` and `SignalBinding.execute` (curried parameters).
6685
* @property {array|null} params
6786
* @default
6887
*/
69-
this.params = null;
70-
71-
};
72-
73-
Phaser.SignalBinding.prototype = {
88+
params: null,
7489

7590
/**
7691
* Call listener passing arbitrary parameters.

0 commit comments

Comments
 (0)