@@ -228,23 +228,14 @@ private function call(callable $callback)
228
228
if ($ args === 0 ) {
229
229
$ callback ();
230
230
} else {
231
- // Store a reference to all progress handlers (will be cleared when settled)
232
- // This way, we can use a static progress callback that is not bound to this promise instance.
233
- // This helps avoiding garbage cycles if the callback creates an Exception.
234
- $ progress =& $ this ->progressHandlers ;
235
-
236
231
$ callback (
237
232
function ($ value = null ) {
238
233
$ this ->resolve ($ value );
239
234
},
240
235
function ($ reason = null ) {
241
236
$ this ->reject ($ reason );
242
237
},
243
- \Closure::bind (function ($ update = null ) use (&$ progress ) {
244
- foreach ($ progress as $ handler ) {
245
- $ handler ($ update );
246
- }
247
- }, null )
238
+ self ::notifier ($ this ->progressHandlers )
248
239
);
249
240
}
250
241
} catch (\Throwable $ e ) {
@@ -253,4 +244,28 @@ function ($reason = null) {
253
244
$ this ->reject ($ e );
254
245
}
255
246
}
247
+
248
+ /**
249
+ * Creates a static progress callback that is not bound to a promise instance.
250
+ *
251
+ * Moving the closure creation to a static method allows us to create a
252
+ * callback that is not bound to a promise instance. By passing its progress
253
+ * handlers by reference, we can still execute them when requested and still
254
+ * clear this reference when settling the promise. This helps avoiding
255
+ * garbage cycles if any callback creates an Exception.
256
+ *
257
+ * These assumptions are covered by the test suite, so if you ever feel like
258
+ * refactoring this, go ahead, any alternative suggestions are welcome!
259
+ *
260
+ * @param array $progressHandlers
261
+ * @return callable
262
+ */
263
+ private static function notifier (&$ progressHandlers )
264
+ {
265
+ return function ($ update = null ) use (&$ progressHandlers ) {
266
+ foreach ($ progressHandlers as $ handler ) {
267
+ $ handler ($ update );
268
+ }
269
+ };
270
+ }
256
271
}
0 commit comments