]> source.dussan.org Git - jquery.git/commitdiff
Callbacks: No object starts out locked
authorRichard Gibson <richard.gibson@gmail.com>
Fri, 2 Jan 2015 14:42:06 +0000 (09:42 -0500)
committerRichard Gibson <richard.gibson@gmail.com>
Sun, 11 Jan 2015 04:04:34 +0000 (23:04 -0500)
Fixes gh-1989

(cherry picked from commit f5a8c649b54e8b7fde6253bd56972347f9bbe012)

src/callbacks.js
test/unit/callbacks.js

index 55a9d719d655aa64417b0bbe2b6379a1d3d0cb10..2c96f0c4a9e2121a5ffed1f9b1a6af67e134827e 100644 (file)
@@ -45,24 +45,27 @@ jQuery.Callbacks = function( options ) {
                ( optionsCache[ options ] || createOptions( options ) ) :
                jQuery.extend( {}, options );
 
-       var // Last fire value (for non-forgettable lists)
+       var // Flag to know if list is currently firing
+               firing,
+               // Last fire value (for non-forgettable lists)
                memory,
                // Flag to know if list was already fired
                fired,
-               // Flag to know if list is currently firing
-               firing,
-               // First callback to fire (used internally by add and fireWith)
-               firingStart,
+               // Flag to prevent .fire/.fireWith
+               locked,
                // End of the loop when firing
                firingLength,
                // Index of currently firing callback (modified by remove if needed)
                firingIndex,
+               // First callback to fire (used internally by add and fireWith)
+               firingStart,
                // Actual callback list
                list = [],
                // Stack of fire calls for repeatable lists
                stack = !options.once && [],
                // Fire callbacks
                fire = function( data ) {
+                       locked = options.once;
                        memory = options.memory && data;
                        fired = true;
                        firingIndex = firingStart || 0;
@@ -78,13 +81,21 @@ jQuery.Callbacks = function( options ) {
                                }
                        }
                        firing = false;
+
+                       // If not disabled,
                        if ( list ) {
+
+                               // If repeatable, check for pending execution
                                if ( stack ) {
                                        if ( stack.length ) {
                                                fire( stack.shift() );
                                        }
+
+                               // If not repeatable but with memory, clear out spent callbacks
                                } else if ( memory ) {
                                        list = [];
+
+                               // Else, disable
                                } else {
                                        self.disable();
                                }
@@ -123,6 +134,7 @@ jQuery.Callbacks = function( options ) {
                                }
                                return this;
                        },
+
                        // Remove a callback from the list
                        remove: function() {
                                if ( list ) {
@@ -144,11 +156,13 @@ jQuery.Callbacks = function( options ) {
                                }
                                return this;
                        },
+
                        // Check if a given callback is in the list.
                        // If no argument is given, return whether or not list has callbacks attached.
                        has: function( fn ) {
                                return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
                        },
+
                        // Remove all callbacks from the list
                        empty: function() {
                                if ( list ) {
@@ -157,30 +171,37 @@ jQuery.Callbacks = function( options ) {
                                }
                                return this;
                        },
-                       // Have the list do nothing anymore
+
+                       // Disable .fire and .add
+                       // Abort any current/pending executions
+                       // Clear all callbacks and values
                        disable: function() {
                                list = stack = memory = undefined;
+                               locked = true;
                                return this;
                        },
-                       // Is it disabled?
                        disabled: function() {
                                return !list;
                        },
-                       // Lock the list in its current state
+
+                       // Disable .fire
+                       // Also disable .add unless we have memory (since it would have no effect)
+                       // Abort any pending executions
                        lock: function() {
                                stack = undefined;
+                               locked = true;
                                if ( !memory ) {
                                        self.disable();
                                }
                                return this;
                        },
-                       // Is it locked?
                        locked: function() {
-                               return !stack;
+                               return !!locked;
                        },
+
                        // Call all callbacks with the given context and arguments
                        fireWith: function( context, args ) {
-                               if ( list && ( !fired || stack ) ) {
+                               if ( !locked ) {
                                        args = args || [];
                                        args = [ context, args.slice ? args.slice() : args ];
                                        if ( firing ) {
@@ -191,11 +212,13 @@ jQuery.Callbacks = function( options ) {
                                }
                                return this;
                        },
+
                        // Call all the callbacks with the given arguments
                        fire: function() {
                                self.fireWith( this, arguments );
                                return this;
                        },
+
                        // To know if the callbacks have already been called at least once
                        fired: function() {
                                return !!fired;
index d997a0d9e127041f096b36b9496f391b590c3c8a..1984e578d863c97c3a0f1b6c27b1d79ed57bd33f 100644 (file)
@@ -65,11 +65,7 @@ jQuery.each( tests, function( strFlags, resultString ) {
 
                                test( "jQuery.Callbacks( " + showFlags( flags ) + " ) - " + filterLabel, function() {
 
-                                       expect( 21 );
-
-                                       // Give qunit a little breathing room
-                                       stop();
-                                       setTimeout( start, 0 );
+                                       expect( 28 );
 
                                        var cblist,
                                                results = resultString.split( /\s+/ );
@@ -77,10 +73,14 @@ jQuery.each( tests, function( strFlags, resultString ) {
                                        // Basic binding and firing
                                        output = "X";
                                        cblist = jQuery.Callbacks( flags );
+                                       strictEqual( cblist.locked(), false, ".locked() initially false" );
+                                       strictEqual( cblist.disabled(), false, ".disabled() initially false" );
+                                       strictEqual( cblist.fired(), false, ".fired() initially false" );
                                        cblist.add(function( str ) {
                                                output += str;
                                        });
-                                       cblist.fire("A");
+                                       strictEqual( cblist.fired(), false, ".fired() still false after .add" );
+                                       cblist.fire( "A" );
                                        strictEqual( output, "XA", "Basic binding and firing" );
                                        strictEqual( cblist.fired(), true, ".fired() detects firing" );
                                        output = "X";
@@ -91,6 +91,8 @@ jQuery.each( tests, function( strFlags, resultString ) {
                                        strictEqual( output, "X", "Adding a callback after disabling" );
                                        cblist.fire("A");
                                        strictEqual( output, "X", "Firing after disabling" );
+                                       strictEqual( cblist.disabled(), true, ".disabled() becomes true" );
+                                       strictEqual( cblist.locked(), true, "disabling locks" );
 
                                        // #13517 - Emptying while firing
                                        cblist = jQuery.Callbacks( flags );
@@ -160,6 +162,7 @@ jQuery.each( tests, function( strFlags, resultString ) {
                                                output += str;
                                        });
                                        strictEqual( output, "X", "Lock early" );
+                                       strictEqual( cblist.locked(), true, "Locking reflected in accessor" );
 
                                        // Ordering
                                        output = "X";