Defer scriptEval test until first use to prevent Content Security Policy inline-scrip...
[jquery.git] / src / core.js
index 0bf0cb4..4311e31 100644 (file)
@@ -63,6 +63,9 @@ var jQuery = function( selector, context ) {
        // The deferred used on DOM ready
        readyList,
 
+       // Promise methods
+       promiseMethods = "then done fail isResolved isRejected promise".split( " " ),
+
        // The ready event handler
        DOMContentLoaded,
 
@@ -580,7 +583,7 @@ jQuery.extend({
 
                        script.type = "text/javascript";
 
-                       if ( jQuery.support.scriptEval ) {
+                       if ( jQuery.support.scriptEval() ) {
                                script.appendChild( document.createTextNode( data ) );
                        } else {
                                script.text = data;
@@ -898,9 +901,10 @@ jQuery.extend({
        Deferred: function( func ) {
 
                var deferred = jQuery._Deferred(),
-                       failDeferred = jQuery._Deferred();
+                       failDeferred = jQuery._Deferred(),
+                       promise;
 
-               // Add errorDeferred methods and redefine cancel
+               // Add errorDeferred methods, then and promise
                jQuery.extend( deferred , {
 
                        then: function( doneCallbacks , failCallbacks ) {
@@ -913,14 +917,18 @@ jQuery.extend({
                        isRejected: failDeferred.isResolved,
                        // Get a promise for this deferred
                        // If obj is provided, the promise aspect is added to the object
-                       promise: function( obj ) {
-                               obj = obj || {};
-                               jQuery.each( "then done fail isResolved isRejected".split( " " ) , function( _ , method ) {
-                                       obj[ method ] = deferred[ method ];
-                               });
-                               obj.promise = function() {
-                                       return obj;
-                               };
+                       // (i is used internally)
+                       promise: function( obj , i ) {
+                               if ( obj == null ) {
+                                       if ( promise ) {
+                                               return promise;
+                                       }
+                                       promise = obj = {};
+                               }
+                               i = promiseMethods.length;
+                               while( i-- ) {
+                                       obj[ promiseMethods[ i ] ] = deferred[ promiseMethods[ i ] ];
+                               }
                                return obj;
                        }
 
@@ -942,10 +950,32 @@ jQuery.extend({
 
        // Deferred helper
        when: function( object ) {
-               object = object && jQuery.isFunction( object.promise ) ?
-                       object :
-                       jQuery.Deferred().resolve( object );
-               return object.promise();
+               var args = arguments,
+                       length = args.length,
+                       deferred = length <= 1 && object && jQuery.isFunction( object.promise ) ?
+                               object :
+                               jQuery.Deferred(),
+                       promise = deferred.promise(),
+                       resolveArray;
+
+               if ( length > 1 ) {
+                       resolveArray = new Array( length );
+                       jQuery.each( args, function( index, element, args ) {
+                               jQuery.when( element ).done( function( value ) {
+                                       args = arguments;
+                                       resolveArray[ index ] = args.length > 1 ? slice.call( args , 0 ) : value;
+                                       if( ! --length ) {
+                                               deferred.fire( promise, resolveArray );
+                                       }
+                               }).fail( function() {
+                                       deferred.fireReject( promise, arguments );
+                               });
+                               return !deferred.isRejected();
+                       });
+               } else if ( deferred !== object ) {
+                       deferred.resolve( object );
+               }
+               return promise;
        },
 
        // Use of jQuery.browser is frowned upon.