@@ -247,143 +247,122 @@ function qFactory(nextTick, exceptionHandler) {
247247   * @returns  {Deferred } Returns a new instance of deferred. 
248248   */ 
249249  var  defer  =  function ( )  { 
250-     var  pending  =  [ ] , 
251-         value ,  deferred ; 
252- 
253-     deferred  =  { 
254- 
255-       resolve : function ( val )  { 
256-         if  ( pending )  { 
257-           var  callbacks  =  pending ; 
258-           pending  =  undefined ; 
259-           value  =  ref ( val ) ; 
260- 
261-           if  ( callbacks . length )  { 
262-             nextTick ( function ( )  { 
263-               var  callback ; 
264-               for  ( var  i  =  0 ,  ii  =  callbacks . length ;  i  <  ii ;  i ++ )  { 
265-                 callback  =  callbacks [ i ] ; 
266-                 value . then ( callback [ 0 ] ,  callback [ 1 ] ,  callback [ 2 ] ) ; 
267-               } 
268-             } ) ; 
269-           } 
270-         } 
271-       } , 
272- 
273- 
274-       reject : function ( reason )  { 
275-         deferred . resolve ( createInternalRejectedPromise ( reason ) ) ; 
276-       } , 
250+     return  new  Deferred ( ) ; 
251+   } ; 
277252
253+   function  Promise  ( )  { 
254+     this . $$pending  =  [ ] ; 
255+   } 
278256
279-        notify :  function ( progress )  { 
280-          if   ( pending )  { 
281-            var  callbacks  =  pending ; 
257+   Promise . prototype   =  { 
258+     then :  function ( callback ,   errback ,   progressback )  { 
259+       var  result  =  new   Deferred ( ) ; 
282260
283-           if  ( pending . length )  { 
284-             nextTick ( function ( )  { 
285-               var  callback ; 
286-               for  ( var  i  =  0 ,  ii  =  callbacks . length ;  i  <  ii ;  i ++ )  { 
287-                 callback  =  callbacks [ i ] ; 
288-                 callback [ 2 ] ( progress ) ; 
289-               } 
290-             } ) ; 
291-           } 
261+       var  wrappedCallback  =  function ( value )  { 
262+         try  { 
263+           result . resolve ( ( isFunction ( callback )  ? callback  : defaultCallback ) ( value ) ) ; 
264+         }  catch ( e )  { 
265+           result . reject ( e ) ; 
266+           exceptionHandler ( e ) ; 
292267        } 
293-       } , 
294- 
295- 
296-       promise : { 
297-         then : function ( callback ,  errback ,  progressback )  { 
298-           var  result  =  defer ( ) ; 
299- 
300-           var  wrappedCallback  =  function ( value )  { 
301-             try  { 
302-               result . resolve ( ( isFunction ( callback )  ? callback  : defaultCallback ) ( value ) ) ; 
303-             }  catch ( e )  { 
304-               result . reject ( e ) ; 
305-               exceptionHandler ( e ) ; 
306-             } 
307-           } ; 
308- 
309-           var  wrappedErrback  =  function ( reason )  { 
310-             try  { 
311-               result . resolve ( ( isFunction ( errback )  ? errback  : defaultErrback ) ( reason ) ) ; 
312-             }  catch ( e )  { 
313-               result . reject ( e ) ; 
314-               exceptionHandler ( e ) ; 
315-             } 
316-           } ; 
317- 
318-           var  wrappedProgressback  =  function ( progress )  { 
319-             try  { 
320-               result . notify ( ( isFunction ( progressback )  ? progressback  : defaultCallback ) ( progress ) ) ; 
321-             }  catch ( e )  { 
322-               exceptionHandler ( e ) ; 
323-             } 
324-           } ; 
268+       } ; 
269+ 
270+       var  wrappedErrback  =  function ( reason )  { 
271+         try  { 
272+           result . resolve ( ( isFunction ( errback )  ? errback  : defaultErrback ) ( reason ) ) ; 
273+         }  catch ( e )  { 
274+           result . reject ( e ) ; 
275+           exceptionHandler ( e ) ; 
276+         } 
277+       } ; 
325278
326-           if  ( pending )  { 
327-             pending . push ( [ wrappedCallback ,  wrappedErrback ,  wrappedProgressback ] ) ; 
328-           }  else  { 
329-             value . then ( wrappedCallback ,  wrappedErrback ,  wrappedProgressback ) ; 
330-           } 
279+       var  wrappedProgressback  =  function ( progress )  { 
280+         try  { 
281+           result . notify ( ( isFunction ( progressback )  ? progressback  : defaultCallback ) ( progress ) ) ; 
282+         }  catch ( e )  { 
283+           exceptionHandler ( e ) ; 
284+         } 
285+       } ; 
331286
332-           return  result . promise ; 
333-         } , 
287+       if  ( this . $$pending )  { 
288+         this . $$pending . push ( [ wrappedCallback ,  wrappedErrback ,  wrappedProgressback ] ) ; 
289+       }  else  { 
290+         this . $$value . then ( wrappedCallback ,  wrappedErrback ,  wrappedProgressback ) ; 
291+       } 
334292
335-         "catch" : function ( callback )  { 
336-           return  this . then ( null ,  callback ) ; 
337-         } , 
293+       return  result . promise ; 
294+     } , 
295+ 
296+     "catch" : function ( callback )  { 
297+       return  this . then ( null ,  callback ) ; 
298+     } , 
299+     "finally" : function ( callback )  { 
300+       return  this . then ( function ( value )  { 
301+         return  handleCallback ( value ,  true ,  callback ) ; 
302+       } ,  function ( error )  { 
303+         return  handleCallback ( error ,  false ,  callback ) ; 
304+       } ) ; 
305+     } 
306+   } ; 
338307
339-         "finally" : function ( callback )  { 
308+   //Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native 
309+   function  simpleBind ( context ,  fn )  { 
310+     return  function ( value )  { 
311+       fn . call ( context ,  value ) ; 
312+     } ; 
313+   } 
340314
341-           function  makePromise ( value ,  resolved )  { 
342-             var  result  =  defer ( ) ; 
343-             if  ( resolved )  { 
344-               result . resolve ( value ) ; 
345-             }  else  { 
346-               result . reject ( value ) ; 
347-             } 
348-             return  result . promise ; 
349-           } 
315+   function  Deferred  ( )  { 
316+     this . promise  =  new  Promise ( ) ; 
317+     //Necessary to support unbound execution :/ 
318+     this . resolve  =  simpleBind ( this ,  this . resolve ) ; 
319+     this . reject  =  simpleBind ( this ,  this . reject ) ; 
320+     this . notify  =  simpleBind ( this ,  this . notify ) ; 
321+   } 
350322
351-           function  handleCallback ( value ,  isResolved )  { 
352-             var  callbackOutput  =  null ; 
353-             try  { 
354-               callbackOutput  =  ( callback  || defaultCallback ) ( ) ; 
355-             }  catch ( e )  { 
356-               return  makePromise ( e ,  false ) ; 
323+   Deferred . prototype  =  { 
324+     resolve : function ( val )  { 
325+       if  ( this . promise . $$pending )  { 
326+         var  callbacks  =  this . promise . $$pending ; 
327+         this . promise . $$pending  =  undefined ; 
328+         this . promise . $$value  =  ref ( val ) ; 
329+ 
330+         if  ( callbacks . length )  { 
331+           nextTick ( simpleBind ( this ,  function ( )  { 
332+             var  callback ; 
333+             for  ( var  i  =  0 ,  ii  =  callbacks . length ;  i  <  ii ;  i ++ )  { 
334+               callback  =  callbacks [ i ] ; 
335+               this . promise . $$value . then ( callback [ 0 ] ,  callback [ 1 ] ,  callback [ 2 ] ) ; 
357336            } 
358-             if  ( isPromiseLike ( callbackOutput ) )  { 
359-               return  callbackOutput . then ( function ( )  { 
360-                 return  makePromise ( value ,  isResolved ) ; 
361-               } ,  function ( error )  { 
362-                 return  makePromise ( error ,  false ) ; 
363-               } ) ; 
364-             }  else  { 
365-               return  makePromise ( value ,  isResolved ) ; 
337+           } ) ) ; 
338+         } 
339+       } 
340+     } , 
341+     reject : function ( reason )  { 
342+       this . resolve ( createInternalRejectedPromise ( reason ) ) ; 
343+     } , 
344+     notify : function ( progress )  { 
345+       if  ( this . promise . $$pending )  { 
346+         var  callbacks  =  this . promise . $$pending ; 
347+ 
348+         if  ( this . promise . $$pending . length )  { 
349+           nextTick ( function ( )  { 
350+             var  callback ; 
351+             for  ( var  i  =  0 ,  ii  =  callbacks . length ;  i  <  ii ;  i ++ )  { 
352+               callback  =  callbacks [ i ] ; 
353+               callback [ 2 ] ( progress ) ; 
366354            } 
367-           } 
368- 
369-           return  this . then ( function ( value )  { 
370-             return  handleCallback ( value ,  true ) ; 
371-           } ,  function ( error )  { 
372-             return  handleCallback ( error ,  false ) ; 
373355          } ) ; 
374356        } 
375357      } 
376-     } ; 
377- 
378-     return  deferred ; 
358+     } 
379359  } ; 
380360
381- 
382361  var  ref  =  function ( value )  { 
383362    if  ( isPromiseLike ( value ) )  return  value ; 
384363    return  { 
385364      then : function ( callback )  { 
386-         var  result  =  defer ( ) ; 
365+         var  result  =  new   Deferred ( ) ; 
387366        nextTick ( function ( )  { 
388367          result . resolve ( callback ( value ) ) ; 
389368        } ) ; 
@@ -430,15 +409,43 @@ function qFactory(nextTick, exceptionHandler) {
430409   * @returns  {Promise } Returns a promise that was already resolved as rejected with the `reason`. 
431410   */ 
432411  var  reject  =  function ( reason )  { 
433-     var  result  =  defer ( ) ; 
412+     var  result  =  new   Deferred ( ) ; 
434413    result . reject ( reason ) ; 
435414    return  result . promise ; 
436415  } ; 
437416
417+   var  makePromise  =  function  makePromise ( value ,  resolved )  { 
418+     var  result  =  new  Deferred ( ) ; 
419+     if  ( resolved )  { 
420+       result . resolve ( value ) ; 
421+     }  else  { 
422+       result . reject ( value ) ; 
423+     } 
424+     return  result . promise ; 
425+   } ; 
426+ 
427+   var  handleCallback  =  function  handleCallback ( value ,  isResolved ,  callback )  { 
428+     var  callbackOutput  =  null ; 
429+     try  { 
430+       callbackOutput  =  ( callback  || defaultCallback ) ( ) ; 
431+     }  catch ( e )  { 
432+       return  makePromise ( e ,  false ) ; 
433+     } 
434+     if  ( isPromiseLike ( callbackOutput ) )  { 
435+       return  callbackOutput . then ( function ( )  { 
436+         return  makePromise ( value ,  isResolved ) ; 
437+       } ,  function ( error )  { 
438+         return  makePromise ( error ,  false ) ; 
439+       } ) ; 
440+     }  else  { 
441+       return  makePromise ( value ,  isResolved ) ; 
442+     } 
443+   } ; 
444+ 
438445  var  createInternalRejectedPromise  =  function ( reason )  { 
439446    return  { 
440447      then : function ( callback ,  errback )  { 
441-         var  result  =  defer ( ) ; 
448+         var  result  =  new   Deferred ( ) ; 
442449        nextTick ( function ( )  { 
443450          try  { 
444451            result . resolve ( ( isFunction ( errback )  ? errback  : defaultErrback ) ( reason ) ) ; 
@@ -467,7 +474,7 @@ function qFactory(nextTick, exceptionHandler) {
467474   * @returns  {Promise } Returns a promise of the passed value or promise 
468475   */ 
469476  var  when  =  function ( value ,  callback ,  errback ,  progressback )  { 
470-     var  result  =  defer ( ) , 
477+     var  result  =  new   Deferred ( ) , 
471478        done ; 
472479
473480    var  wrappedCallback  =  function ( value )  { 
@@ -541,7 +548,7 @@ function qFactory(nextTick, exceptionHandler) {
541548   *   with the same rejection value. 
542549   */ 
543550  function  all ( promises )  { 
544-     var  deferred  =  defer ( ) , 
551+     var  deferred  =  new   Deferred ( ) , 
545552        counter  =  0 , 
546553        results  =  isArray ( promises )  ? [ ]  : { } ; 
547554
@@ -575,7 +582,7 @@ function qFactory(nextTick, exceptionHandler) {
575582      return  new  Q ( resolver ) ; 
576583    } 
577584
578-     var  deferred  =  defer ( ) ; 
585+     var  deferred  =  new   Deferred ( ) ; 
579586
580587    function  resolveFn ( value )  { 
581588      deferred . resolve ( value ) ; 
0 commit comments