Skip to content

Commit 2d0bc7c

Browse files
committed
Moves Deferred-related code into a separate module. Context handling has been simplified in _Deferred.resolve and jQuery.when has been refactored for clarity (and minor optimization).
1 parent c127989 commit 2d0bc7c

17 files changed

+407
-393
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ COMPILER = ${JS_ENGINE} ${BUILD_DIR}/uglify.js --unsafe
1212
POST_COMPILER = ${JS_ENGINE} ${BUILD_DIR}/post-compile.js
1313

1414
BASE_FILES = ${SRC_DIR}/core.js\
15+
${SRC_DIR}/deferred.js\
1516
${SRC_DIR}/support.js\
1617
${SRC_DIR}/data.js\
1718
${SRC_DIR}/queue.js\

src/core.js

Lines changed: 2 additions & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,9 @@ var jQuery = function( selector, context ) {
5050
// For matching the engine and version of the browser
5151
browserMatch,
5252

53-
// Has the ready events already been bound?
54-
readyBound = false,
55-
5653
// The deferred used on DOM ready
5754
readyList,
5855

59-
// Promise methods
60-
promiseMethods = "then done fail isResolved isRejected promise".split( " " ),
61-
6256
// The ready event handler
6357
DOMContentLoaded,
6458

@@ -408,11 +402,11 @@ jQuery.extend({
408402
},
409403

410404
bindReady: function() {
411-
if ( readyBound ) {
405+
if ( readyList ) {
412406
return;
413407
}
414408

415-
readyBound = true;
409+
readyList = jQuery._Deferred();
416410

417411
// Catch cases where $(document).ready() is called after the
418412
// browser event has already occurred.
@@ -792,167 +786,6 @@ jQuery.extend({
792786
return (new Date()).getTime();
793787
},
794788

795-
// Create a simple deferred (one callbacks list)
796-
_Deferred: function() {
797-
var // callbacks list
798-
callbacks = [],
799-
// stored [ context , args ]
800-
fired,
801-
// to avoid firing when already doing so
802-
firing,
803-
// flag to know if the deferred has been cancelled
804-
cancelled,
805-
// the deferred itself
806-
deferred = {
807-
808-
// done( f1, f2, ...)
809-
done: function() {
810-
if ( !cancelled ) {
811-
var args = arguments,
812-
i,
813-
length,
814-
elem,
815-
type,
816-
_fired;
817-
if ( fired ) {
818-
_fired = fired;
819-
fired = 0;
820-
}
821-
for ( i = 0, length = args.length; i < length; i++ ) {
822-
elem = args[ i ];
823-
type = jQuery.type( elem );
824-
if ( type === "array" ) {
825-
deferred.done.apply( deferred, elem );
826-
} else if ( type === "function" ) {
827-
callbacks.push( elem );
828-
}
829-
}
830-
if ( _fired ) {
831-
deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );
832-
}
833-
}
834-
return this;
835-
},
836-
837-
// resolve with given context and args
838-
resolveWith: function( context, args ) {
839-
if ( !cancelled && !fired && !firing ) {
840-
// make sure args are available (#8421)
841-
args = args || [];
842-
firing = 1;
843-
try {
844-
while( callbacks[ 0 ] ) {
845-
callbacks.shift().apply( context, args );
846-
}
847-
}
848-
finally {
849-
fired = [ context, args ];
850-
firing = 0;
851-
}
852-
}
853-
return this;
854-
},
855-
856-
// resolve with this as context and given arguments
857-
resolve: function() {
858-
deferred.resolveWith( jQuery.isFunction( this.promise ) ? this.promise() : this, arguments );
859-
return this;
860-
},
861-
862-
// Has this deferred been resolved?
863-
isResolved: function() {
864-
return !!( firing || fired );
865-
},
866-
867-
// Cancel
868-
cancel: function() {
869-
cancelled = 1;
870-
callbacks = [];
871-
return this;
872-
}
873-
};
874-
875-
return deferred;
876-
},
877-
878-
// Full fledged deferred (two callbacks list)
879-
Deferred: function( func ) {
880-
var deferred = jQuery._Deferred(),
881-
failDeferred = jQuery._Deferred(),
882-
promise;
883-
// Add errorDeferred methods, then and promise
884-
jQuery.extend( deferred, {
885-
then: function( doneCallbacks, failCallbacks ) {
886-
deferred.done( doneCallbacks ).fail( failCallbacks );
887-
return this;
888-
},
889-
fail: failDeferred.done,
890-
rejectWith: failDeferred.resolveWith,
891-
reject: failDeferred.resolve,
892-
isRejected: failDeferred.isResolved,
893-
// Get a promise for this deferred
894-
// If obj is provided, the promise aspect is added to the object
895-
promise: function( obj ) {
896-
if ( obj == null ) {
897-
if ( promise ) {
898-
return promise;
899-
}
900-
promise = obj = {};
901-
}
902-
var i = promiseMethods.length;
903-
while( i-- ) {
904-
obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ];
905-
}
906-
return obj;
907-
}
908-
} );
909-
// Make sure only one callback list will be used
910-
deferred.done( failDeferred.cancel ).fail( deferred.cancel );
911-
// Unexpose cancel
912-
delete deferred.cancel;
913-
// Call given func if any
914-
if ( func ) {
915-
func.call( deferred, deferred );
916-
}
917-
return deferred;
918-
},
919-
920-
// Deferred helper
921-
when: function( object ) {
922-
var lastIndex = arguments.length,
923-
deferred = lastIndex <= 1 && object && jQuery.isFunction( object.promise ) ?
924-
object :
925-
jQuery.Deferred(),
926-
promise = deferred.promise();
927-
928-
if ( lastIndex > 1 ) {
929-
var array = slice.call( arguments, 0 ),
930-
count = lastIndex,
931-
iCallback = function( index ) {
932-
return function( value ) {
933-
array[ index ] = arguments.length > 1 ? slice.call( arguments, 0 ) : value;
934-
if ( !( --count ) ) {
935-
deferred.resolveWith( promise, array );
936-
}
937-
};
938-
};
939-
while( ( lastIndex-- ) ) {
940-
object = array[ lastIndex ];
941-
if ( object && jQuery.isFunction( object.promise ) ) {
942-
object.promise().then( iCallback(lastIndex), deferred.reject );
943-
} else {
944-
--count;
945-
}
946-
}
947-
if ( !count ) {
948-
deferred.resolveWith( promise, array );
949-
}
950-
} else if ( deferred !== object ) {
951-
deferred.resolve( object );
952-
}
953-
return promise;
954-
},
955-
956789
// Use of jQuery.browser is frowned upon.
957790
// More details: http://docs.jquery.com/Utilities/jQuery.browser
958791
uaMatch: function( ua ) {
@@ -991,9 +824,6 @@ jQuery.extend({
991824
browser: {}
992825
});
993826

994-
// Create readyList deferred
995-
readyList = jQuery._Deferred();
996-
997827
// Populate the class2type map
998828
jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
999829
class2type[ "[object " + name + "]" ] = name.toLowerCase();

src/deferred.js

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
(function( jQuery ) {
2+
3+
var // Promise methods
4+
promiseMethods = "then done fail isResolved isRejected promise".split( " " ),
5+
// Static reference to slice
6+
sliceDeferred = [].slice;
7+
8+
jQuery.extend({
9+
// Create a simple deferred (one callbacks list)
10+
_Deferred: function() {
11+
var // callbacks list
12+
callbacks = [],
13+
// stored [ context , args ]
14+
fired,
15+
// to avoid firing when already doing so
16+
firing,
17+
// flag to know if the deferred has been cancelled
18+
cancelled,
19+
// the deferred itself
20+
deferred = {
21+
22+
// done( f1, f2, ...)
23+
done: function() {
24+
if ( !cancelled ) {
25+
var args = arguments,
26+
i,
27+
length,
28+
elem,
29+
type,
30+
_fired;
31+
if ( fired ) {
32+
_fired = fired;
33+
fired = 0;
34+
}
35+
for ( i = 0, length = args.length; i < length; i++ ) {
36+
elem = args[ i ];
37+
type = jQuery.type( elem );
38+
if ( type === "array" ) {
39+
deferred.done.apply( deferred, elem );
40+
} else if ( type === "function" ) {
41+
callbacks.push( elem );
42+
}
43+
}
44+
if ( _fired ) {
45+
deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );
46+
}
47+
}
48+
return this;
49+
},
50+
51+
// resolve with given context and args
52+
resolveWith: function( context, args ) {
53+
if ( !cancelled && !fired && !firing ) {
54+
// make sure args are available (#8421)
55+
args = args || [];
56+
firing = 1;
57+
try {
58+
while( callbacks[ 0 ] ) {
59+
callbacks.shift().apply( context, args );
60+
}
61+
}
62+
finally {
63+
fired = [ context, args ];
64+
firing = 0;
65+
}
66+
}
67+
return this;
68+
},
69+
70+
// resolve with this as context and given arguments
71+
resolve: function() {
72+
deferred.resolveWith( this, arguments );
73+
return this;
74+
},
75+
76+
// Has this deferred been resolved?
77+
isResolved: function() {
78+
return !!( firing || fired );
79+
},
80+
81+
// Cancel
82+
cancel: function() {
83+
cancelled = 1;
84+
callbacks = [];
85+
return this;
86+
}
87+
};
88+
89+
return deferred;
90+
},
91+
92+
// Full fledged deferred (two callbacks list)
93+
Deferred: function( func ) {
94+
var deferred = jQuery._Deferred(),
95+
failDeferred = jQuery._Deferred(),
96+
promise;
97+
// Add errorDeferred methods, then and promise
98+
jQuery.extend( deferred, {
99+
then: function( doneCallbacks, failCallbacks ) {
100+
deferred.done( doneCallbacks ).fail( failCallbacks );
101+
return this;
102+
},
103+
fail: failDeferred.done,
104+
rejectWith: failDeferred.resolveWith,
105+
reject: failDeferred.resolve,
106+
isRejected: failDeferred.isResolved,
107+
// Get a promise for this deferred
108+
// If obj is provided, the promise aspect is added to the object
109+
promise: function( obj ) {
110+
if ( obj == null ) {
111+
if ( promise ) {
112+
return promise;
113+
}
114+
promise = obj = {};
115+
}
116+
var i = promiseMethods.length;
117+
while( i-- ) {
118+
obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ];
119+
}
120+
return obj;
121+
}
122+
} );
123+
// Make sure only one callback list will be used
124+
deferred.done( failDeferred.cancel ).fail( deferred.cancel );
125+
// Unexpose cancel
126+
delete deferred.cancel;
127+
// Call given func if any
128+
if ( func ) {
129+
func.call( deferred, deferred );
130+
}
131+
return deferred;
132+
},
133+
134+
// Deferred helper
135+
when: function( firstParam ) {
136+
var args = arguments,
137+
i = 0,
138+
length = args.length,
139+
count = length,
140+
deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
141+
firstParam :
142+
jQuery.Deferred();
143+
function resolveFunc( i ) {
144+
return function( value ) {
145+
args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
146+
if ( !( --count ) ) {
147+
deferred.resolveWith( deferred, args );
148+
}
149+
};
150+
}
151+
if ( length > 1 ) {
152+
for( ; i < length; i++ ) {
153+
if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) {
154+
args[ i ].promise().then( resolveFunc(i), deferred.reject );
155+
} else {
156+
--count;
157+
}
158+
}
159+
if ( !count ) {
160+
deferred.resolveWith( deferred, args );
161+
}
162+
} else if ( deferred !== firstParam ) {
163+
deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
164+
}
165+
return deferred.promise();
166+
}
167+
});
168+
169+
})( jQuery );

test/csp.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
<title>CSP Test Page</title>
77

88
<script src="../src/core.js"></script>
9+
<script src="../src/deferred.js"></script>
910
<script src="../src/support.js"></script>
1011
<script src="../src/data.js"></script>
1112
<script src="../src/queue.js"></script>

0 commit comments

Comments
 (0)