From c1279895f3f33cacc08e508c2409b587c0e6a5a2 Mon Sep 17 00:00:00 2001 From: jaubourg Date: Thu, 3 Mar 2011 15:16:47 +0100 Subject: [PATCH 01/19] Fix for #8421. Makes sure resolveWith can be called with only one parameter. --- src/core.js | 2 ++ test/unit/core.js | 16 +++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/core.js b/src/core.js index 036b2db6..1e7250f6 100644 --- a/src/core.js +++ b/src/core.js @@ -837,6 +837,8 @@ jQuery.extend({ // resolve with given context and args resolveWith: function( context, args ) { if ( !cancelled && !fired && !firing ) { + // make sure args are available (#8421) + args = args || []; firing = 1; try { while( callbacks[ 0 ] ) { diff --git a/test/unit/core.js b/test/unit/core.js index bce0de0f..208b21c6 100644 --- a/test/unit/core.js +++ b/test/unit/core.js @@ -916,7 +916,7 @@ test("jQuery.parseJSON", function(){ test("jQuery._Deferred()", function() { - expect( 10 ); + expect( 11 ); var deferred, object, @@ -1005,6 +1005,12 @@ test("jQuery._Deferred()", function() { deferred.resolveWith( jQuery , [ document ] ).done( function( doc ) { ok( this === jQuery && arguments.length === 1 && doc === document , "Test fire context & args" ); }); + + // #8421 + deferred = jQuery._Deferred(); + deferred.resolveWith().done(function() { + ok( true, "Test resolveWith can be called with no argument" ); + }); }); test("jQuery.Deferred()", function() { @@ -1143,16 +1149,16 @@ test("jQuery.sub() - Static Methods", function(){ } }); Subclass.fn.extend({subClassMethod: function() { return this;}}); - + //Test Simple Subclass ok(Subclass.topLevelMethod() === false, 'Subclass.topLevelMethod thought debug was true'); ok(Subclass.config.locale == 'en_US', Subclass.config.locale + ' is wrong!'); same(Subclass.config.test, undefined, 'Subclass.config.test is set incorrectly'); equal(jQuery.ajax, Subclass.ajax, 'The subclass failed to get all top level methods'); - + //Create a SubSubclass var SubSubclass = Subclass.sub(); - + //Make Sure the SubSubclass inherited properly ok(SubSubclass.topLevelMethod() === false, 'SubSubclass.topLevelMethod thought debug was true'); ok(SubSubclass.config.locale == 'en_US', SubSubclass.config.locale + ' is wrong!'); @@ -1169,7 +1175,7 @@ test("jQuery.sub() - Static Methods", function(){ ok(SubSubclass.config.locale == 'es_MX', SubSubclass.config.locale + ' is wrong!'); ok(SubSubclass.config.test == 'worked', 'SubSubclass.config.test is set incorrectly'); notEqual(jQuery.ajax, SubSubclass.ajax, 'The subsubclass failed to get all top level methods'); - + //This shows that the modifications to the SubSubClass did not bubble back up to it's superclass ok(Subclass.topLevelMethod() === false, 'Subclass.topLevelMethod thought debug was true'); ok(Subclass.config.locale == 'en_US', Subclass.config.locale + ' is wrong!'); From 2d0bc7ce72ab8d64da0506a88c8cc543ce3ceaba Mon Sep 17 00:00:00 2001 From: jaubourg Date: Thu, 3 Mar 2011 19:38:06 +0100 Subject: [PATCH 02/19] 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). --- Makefile | 1 + src/core.js | 174 +------------------------- src/deferred.js | 169 +++++++++++++++++++++++++ test/csp.php | 1 + test/data/offset/absolute.html | 1 + test/data/offset/body.html | 1 + test/data/offset/fixed.html | 1 + test/data/offset/relative.html | 1 + test/data/offset/scroll.html | 1 + test/data/offset/static.html | 1 + test/data/offset/table.html | 1 + test/index.html | 2 + test/localfile.html | 1 + test/networkerror.html | 1 + test/readywait.html | 1 + test/unit/core.js | 221 -------------------------------- test/unit/deferred.js | 222 +++++++++++++++++++++++++++++++++ 17 files changed, 407 insertions(+), 393 deletions(-) create mode 100644 src/deferred.js create mode 100644 test/unit/deferred.js diff --git a/Makefile b/Makefile index bf41bccc..a6aae425 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,7 @@ COMPILER = ${JS_ENGINE} ${BUILD_DIR}/uglify.js --unsafe POST_COMPILER = ${JS_ENGINE} ${BUILD_DIR}/post-compile.js BASE_FILES = ${SRC_DIR}/core.js\ + ${SRC_DIR}/deferred.js\ ${SRC_DIR}/support.js\ ${SRC_DIR}/data.js\ ${SRC_DIR}/queue.js\ diff --git a/src/core.js b/src/core.js index 1e7250f6..9312ee28 100644 --- a/src/core.js +++ b/src/core.js @@ -50,15 +50,9 @@ var jQuery = function( selector, context ) { // For matching the engine and version of the browser browserMatch, - // Has the ready events already been bound? - readyBound = false, - // The deferred used on DOM ready readyList, - // Promise methods - promiseMethods = "then done fail isResolved isRejected promise".split( " " ), - // The ready event handler DOMContentLoaded, @@ -408,11 +402,11 @@ jQuery.extend({ }, bindReady: function() { - if ( readyBound ) { + if ( readyList ) { return; } - readyBound = true; + readyList = jQuery._Deferred(); // Catch cases where $(document).ready() is called after the // browser event has already occurred. @@ -792,167 +786,6 @@ jQuery.extend({ return (new Date()).getTime(); }, - // Create a simple deferred (one callbacks list) - _Deferred: function() { - var // callbacks list - callbacks = [], - // stored [ context , args ] - fired, - // to avoid firing when already doing so - firing, - // flag to know if the deferred has been cancelled - cancelled, - // the deferred itself - deferred = { - - // done( f1, f2, ...) - done: function() { - if ( !cancelled ) { - var args = arguments, - i, - length, - elem, - type, - _fired; - if ( fired ) { - _fired = fired; - fired = 0; - } - for ( i = 0, length = args.length; i < length; i++ ) { - elem = args[ i ]; - type = jQuery.type( elem ); - if ( type === "array" ) { - deferred.done.apply( deferred, elem ); - } else if ( type === "function" ) { - callbacks.push( elem ); - } - } - if ( _fired ) { - deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); - } - } - return this; - }, - - // resolve with given context and args - resolveWith: function( context, args ) { - if ( !cancelled && !fired && !firing ) { - // make sure args are available (#8421) - args = args || []; - firing = 1; - try { - while( callbacks[ 0 ] ) { - callbacks.shift().apply( context, args ); - } - } - finally { - fired = [ context, args ]; - firing = 0; - } - } - return this; - }, - - // resolve with this as context and given arguments - resolve: function() { - deferred.resolveWith( jQuery.isFunction( this.promise ) ? this.promise() : this, arguments ); - return this; - }, - - // Has this deferred been resolved? - isResolved: function() { - return !!( firing || fired ); - }, - - // Cancel - cancel: function() { - cancelled = 1; - callbacks = []; - return this; - } - }; - - return deferred; - }, - - // Full fledged deferred (two callbacks list) - Deferred: function( func ) { - var deferred = jQuery._Deferred(), - failDeferred = jQuery._Deferred(), - promise; - // Add errorDeferred methods, then and promise - jQuery.extend( deferred, { - then: function( doneCallbacks, failCallbacks ) { - deferred.done( doneCallbacks ).fail( failCallbacks ); - return this; - }, - fail: failDeferred.done, - rejectWith: failDeferred.resolveWith, - reject: failDeferred.resolve, - isRejected: failDeferred.isResolved, - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - if ( obj == null ) { - if ( promise ) { - return promise; - } - promise = obj = {}; - } - var i = promiseMethods.length; - while( i-- ) { - obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ]; - } - return obj; - } - } ); - // Make sure only one callback list will be used - deferred.done( failDeferred.cancel ).fail( deferred.cancel ); - // Unexpose cancel - delete deferred.cancel; - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } - return deferred; - }, - - // Deferred helper - when: function( object ) { - var lastIndex = arguments.length, - deferred = lastIndex <= 1 && object && jQuery.isFunction( object.promise ) ? - object : - jQuery.Deferred(), - promise = deferred.promise(); - - if ( lastIndex > 1 ) { - var array = slice.call( arguments, 0 ), - count = lastIndex, - iCallback = function( index ) { - return function( value ) { - array[ index ] = arguments.length > 1 ? slice.call( arguments, 0 ) : value; - if ( !( --count ) ) { - deferred.resolveWith( promise, array ); - } - }; - }; - while( ( lastIndex-- ) ) { - object = array[ lastIndex ]; - if ( object && jQuery.isFunction( object.promise ) ) { - object.promise().then( iCallback(lastIndex), deferred.reject ); - } else { - --count; - } - } - if ( !count ) { - deferred.resolveWith( promise, array ); - } - } else if ( deferred !== object ) { - deferred.resolve( object ); - } - return promise; - }, - // Use of jQuery.browser is frowned upon. // More details: http://docs.jquery.com/Utilities/jQuery.browser uaMatch: function( ua ) { @@ -991,9 +824,6 @@ jQuery.extend({ browser: {} }); -// Create readyList deferred -readyList = jQuery._Deferred(); - // Populate the class2type map jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { class2type[ "[object " + name + "]" ] = name.toLowerCase(); diff --git a/src/deferred.js b/src/deferred.js new file mode 100644 index 00000000..f0d7c08c --- /dev/null +++ b/src/deferred.js @@ -0,0 +1,169 @@ +(function( jQuery ) { + +var // Promise methods + promiseMethods = "then done fail isResolved isRejected promise".split( " " ), + // Static reference to slice + sliceDeferred = [].slice; + +jQuery.extend({ + // Create a simple deferred (one callbacks list) + _Deferred: function() { + var // callbacks list + callbacks = [], + // stored [ context , args ] + fired, + // to avoid firing when already doing so + firing, + // flag to know if the deferred has been cancelled + cancelled, + // the deferred itself + deferred = { + + // done( f1, f2, ...) + done: function() { + if ( !cancelled ) { + var args = arguments, + i, + length, + elem, + type, + _fired; + if ( fired ) { + _fired = fired; + fired = 0; + } + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + deferred.done.apply( deferred, elem ); + } else if ( type === "function" ) { + callbacks.push( elem ); + } + } + if ( _fired ) { + deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); + } + } + return this; + }, + + // resolve with given context and args + resolveWith: function( context, args ) { + if ( !cancelled && !fired && !firing ) { + // make sure args are available (#8421) + args = args || []; + firing = 1; + try { + while( callbacks[ 0 ] ) { + callbacks.shift().apply( context, args ); + } + } + finally { + fired = [ context, args ]; + firing = 0; + } + } + return this; + }, + + // resolve with this as context and given arguments + resolve: function() { + deferred.resolveWith( this, arguments ); + return this; + }, + + // Has this deferred been resolved? + isResolved: function() { + return !!( firing || fired ); + }, + + // Cancel + cancel: function() { + cancelled = 1; + callbacks = []; + return this; + } + }; + + return deferred; + }, + + // Full fledged deferred (two callbacks list) + Deferred: function( func ) { + var deferred = jQuery._Deferred(), + failDeferred = jQuery._Deferred(), + promise; + // Add errorDeferred methods, then and promise + jQuery.extend( deferred, { + then: function( doneCallbacks, failCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ); + return this; + }, + fail: failDeferred.done, + rejectWith: failDeferred.resolveWith, + reject: failDeferred.resolve, + isRejected: failDeferred.isResolved, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + if ( obj == null ) { + if ( promise ) { + return promise; + } + promise = obj = {}; + } + var i = promiseMethods.length; + while( i-- ) { + obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ]; + } + return obj; + } + } ); + // Make sure only one callback list will be used + deferred.done( failDeferred.cancel ).fail( deferred.cancel ); + // Unexpose cancel + delete deferred.cancel; + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + return deferred; + }, + + // Deferred helper + when: function( firstParam ) { + var args = arguments, + i = 0, + length = args.length, + count = length, + deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? + firstParam : + jQuery.Deferred(); + function resolveFunc( i ) { + return function( value ) { + args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + if ( !( --count ) ) { + deferred.resolveWith( deferred, args ); + } + }; + } + if ( length > 1 ) { + for( ; i < length; i++ ) { + if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) { + args[ i ].promise().then( resolveFunc(i), deferred.reject ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( deferred, args ); + } + } else if ( deferred !== firstParam ) { + deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); + } + return deferred.promise(); + } +}); + +})( jQuery ); diff --git a/test/csp.php b/test/csp.php index acf8f32c..13c324ea 100644 --- a/test/csp.php +++ b/test/csp.php @@ -6,6 +6,7 @@ CSP Test Page + diff --git a/test/data/offset/absolute.html b/test/data/offset/absolute.html index b4db30a6..9d7990a3 100644 --- a/test/data/offset/absolute.html +++ b/test/data/offset/absolute.html @@ -16,6 +16,7 @@ #positionTest { position: absolute; } + diff --git a/test/data/offset/body.html b/test/data/offset/body.html index e3eb4f80..8dbf282d 100644 --- a/test/data/offset/body.html +++ b/test/data/offset/body.html @@ -9,6 +9,7 @@ #marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; } + diff --git a/test/data/offset/fixed.html b/test/data/offset/fixed.html index f93c20ff..3181718d 100644 --- a/test/data/offset/fixed.html +++ b/test/data/offset/fixed.html @@ -13,6 +13,7 @@ #marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; } + diff --git a/test/data/offset/relative.html b/test/data/offset/relative.html index 35864760..280a2fc0 100644 --- a/test/data/offset/relative.html +++ b/test/data/offset/relative.html @@ -11,6 +11,7 @@ #marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; } + diff --git a/test/data/offset/scroll.html b/test/data/offset/scroll.html index 50de95e0..a0d1f4d1 100644 --- a/test/data/offset/scroll.html +++ b/test/data/offset/scroll.html @@ -14,6 +14,7 @@ #marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; } + diff --git a/test/data/offset/static.html b/test/data/offset/static.html index b1fb9f15..a61b6d10 100644 --- a/test/data/offset/static.html +++ b/test/data/offset/static.html @@ -11,6 +11,7 @@ #marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; } + diff --git a/test/data/offset/table.html b/test/data/offset/table.html index 528e5303..11fb0e79 100644 --- a/test/data/offset/table.html +++ b/test/data/offset/table.html @@ -11,6 +11,7 @@ #marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; } + diff --git a/test/index.html b/test/index.html index d6213153..c7c2ae55 100644 --- a/test/index.html +++ b/test/index.html @@ -9,6 +9,7 @@ + @@ -31,6 +32,7 @@ + diff --git a/test/localfile.html b/test/localfile.html index 96e0f982..c552f214 100644 --- a/test/localfile.html +++ b/test/localfile.html @@ -5,6 +5,7 @@ jQuery Local File Test + diff --git a/test/networkerror.html b/test/networkerror.html index b06a6ba4..f98bf469 100644 --- a/test/networkerror.html +++ b/test/networkerror.html @@ -16,6 +16,7 @@ div { margin-top: 10px; } + diff --git a/test/readywait.html b/test/readywait.html index 8e0d3d53..4f124767 100644 --- a/test/readywait.html +++ b/test/readywait.html @@ -15,6 +15,7 @@ #expectedOutput { background-color: green } + diff --git a/test/unit/core.js b/test/unit/core.js index 208b21c6..6ee8724d 100644 --- a/test/unit/core.js +++ b/test/unit/core.js @@ -914,227 +914,6 @@ test("jQuery.parseJSON", function(){ } }); -test("jQuery._Deferred()", function() { - - expect( 11 ); - - var deferred, - object, - test; - - deferred = jQuery._Deferred(); - - test = false; - - deferred.done( function( value ) { - equals( value , "value" , "Test pre-resolve callback" ); - test = true; - } ); - - deferred.resolve( "value" ); - - ok( test , "Test pre-resolve callbacks called right away" ); - - test = false; - - deferred.done( function( value ) { - equals( value , "value" , "Test post-resolve callback" ); - test = true; - } ); - - ok( test , "Test post-resolve callbacks called right away" ); - - deferred.cancel(); - - test = true; - - deferred.done( function() { - ok( false , "Cancel was ignored" ); - test = false; - } ); - - ok( test , "Test cancel" ); - - deferred = jQuery._Deferred().resolve(); - - try { - deferred.done( function() { - throw "Error"; - } , function() { - ok( true , "Test deferred do not cancel on exception" ); - } ); - } catch( e ) { - strictEqual( e , "Error" , "Test deferred propagates exceptions"); - deferred.done(); - } - - test = ""; - deferred = jQuery._Deferred().done( function() { - - test += "A"; - - }, function() { - - test += "B"; - - } ).resolve(); - - strictEqual( test , "AB" , "Test multiple done parameters" ); - - test = ""; - - deferred.done( function() { - - deferred.done( function() { - - test += "C"; - - } ); - - test += "A"; - - }, function() { - - test += "B"; - } ); - - strictEqual( test , "ABC" , "Test done callbacks order" ); - - deferred = jQuery._Deferred(); - - deferred.resolveWith( jQuery , [ document ] ).done( function( doc ) { - ok( this === jQuery && arguments.length === 1 && doc === document , "Test fire context & args" ); - }); - - // #8421 - deferred = jQuery._Deferred(); - deferred.resolveWith().done(function() { - ok( true, "Test resolveWith can be called with no argument" ); - }); -}); - -test("jQuery.Deferred()", function() { - - expect( 10 ); - - jQuery.Deferred( function( defer ) { - strictEqual( this , defer , "Defer passed as this & first argument" ); - this.resolve( "done" ); - }).then( function( value ) { - strictEqual( value , "done" , "Passed function executed" ); - }); - - jQuery.Deferred().resolve().then( function() { - ok( true , "Success on resolve" ); - }, function() { - ok( false , "Error on resolve" ); - }); - - jQuery.Deferred().reject().then( function() { - ok( false , "Success on reject" ); - }, function() { - ok( true , "Error on reject" ); - }); - - ( new jQuery.Deferred( function( defer ) { - strictEqual( this , defer , "Defer passed as this & first argument (new)" ); - this.resolve( "done" ); - }) ).then( function( value ) { - strictEqual( value , "done" , "Passed function executed (new)" ); - }); - - ( new jQuery.Deferred() ).resolve().then( function() { - ok( true , "Success on resolve (new)" ); - }, function() { - ok( false , "Error on resolve (new)" ); - }); - - ( new jQuery.Deferred() ).reject().then( function() { - ok( false , "Success on reject (new)" ); - }, function() { - ok( true , "Error on reject (new)" ); - }); - - var tmp = jQuery.Deferred(); - - strictEqual( tmp.promise() , tmp.promise() , "Test deferred always return same promise" ); - strictEqual( tmp.promise() , tmp.promise().promise() , "Test deferred's promise always return same promise as deferred" ); -}); - -test("jQuery.when()", function() { - - expect( 23 ); - - // Some other objects - jQuery.each( { - - "an empty string": "", - "a non-empty string": "some string", - "zero": 0, - "a number other than zero": 1, - "true": true, - "false": false, - "null": null, - "undefined": undefined, - "a plain object": {} - - } , function( message , value ) { - - ok( jQuery.isFunction( jQuery.when( value ).then( function( resolveValue ) { - strictEqual( resolveValue , value , "Test the promise was resolved with " + message ); - } ).promise ) , "Test " + message + " triggers the creation of a new Promise" ); - - } ); - - ok( jQuery.isFunction( jQuery.when().then( function( resolveValue ) { - strictEqual( resolveValue , undefined , "Test the promise was resolved with no parameter" ); - } ).promise ) , "Test calling when with no parameter triggers the creation of a new Promise" ); - - var cache, i; - - for( i = 1 ; i < 4 ; i++ ) { - jQuery.when( cache || jQuery.Deferred( function() { - this.resolve( i ); - }) ).then( function( value ) { - strictEqual( value , 1 , "Function executed" + ( i > 1 ? " only once" : "" ) ); - cache = value; - }, function() { - ok( false , "Fail called" ); - }); - } -}); - -test("jQuery.when() - joined", function() { - - expect(8); - - jQuery.when( 1, 2, 3 ).done( function( a, b, c ) { - strictEqual( a , 1 , "Test first param is first resolved value - non-observables" ); - strictEqual( b , 2 , "Test second param is second resolved value - non-observables" ); - strictEqual( c , 3 , "Test third param is third resolved value - non-observables" ); - }).fail( function() { - ok( false , "Test the created deferred was resolved - non-observables"); - }); - - var successDeferred = jQuery.Deferred().resolve( 1 , 2 , 3 ), - errorDeferred = jQuery.Deferred().reject( "error" , "errorParam" ); - - jQuery.when( 1 , successDeferred , 3 ).done( function( a, b, c ) { - strictEqual( a , 1 , "Test first param is first resolved value - resolved observable" ); - same( b , [ 1 , 2 , 3 ] , "Test second param is second resolved value - resolved observable" ); - strictEqual( c , 3 , "Test third param is third resolved value - resolved observable" ); - }).fail( function() { - ok( false , "Test the created deferred was resolved - resolved observable"); - }); - - jQuery.when( 1 , errorDeferred , 3 ).done( function() { - ok( false , "Test the created deferred was rejected - rejected observable"); - }).fail( function( error , errorParam ) { - strictEqual( error , "error" , "Test first param is first rejected value - rejected observable" ); - strictEqual( errorParam , "errorParam" , "Test second param is second rejected value - rejected observable" ); - }); -}); - test("jQuery.sub() - Static Methods", function(){ expect(18); var Subclass = jQuery.sub(); diff --git a/test/unit/deferred.js b/test/unit/deferred.js new file mode 100644 index 00000000..6ba4767a --- /dev/null +++ b/test/unit/deferred.js @@ -0,0 +1,222 @@ +module("deferred", { teardown: moduleTeardown }); + +test("jQuery._Deferred()", function() { + + expect( 11 ); + + var deferred, + object, + test; + + deferred = jQuery._Deferred(); + + test = false; + + deferred.done( function( value ) { + equals( value , "value" , "Test pre-resolve callback" ); + test = true; + } ); + + deferred.resolve( "value" ); + + ok( test , "Test pre-resolve callbacks called right away" ); + + test = false; + + deferred.done( function( value ) { + equals( value , "value" , "Test post-resolve callback" ); + test = true; + } ); + + ok( test , "Test post-resolve callbacks called right away" ); + + deferred.cancel(); + + test = true; + + deferred.done( function() { + ok( false , "Cancel was ignored" ); + test = false; + } ); + + ok( test , "Test cancel" ); + + deferred = jQuery._Deferred().resolve(); + + try { + deferred.done( function() { + throw "Error"; + } , function() { + ok( true , "Test deferred do not cancel on exception" ); + } ); + } catch( e ) { + strictEqual( e , "Error" , "Test deferred propagates exceptions"); + deferred.done(); + } + + test = ""; + deferred = jQuery._Deferred().done( function() { + + test += "A"; + + }, function() { + + test += "B"; + + } ).resolve(); + + strictEqual( test , "AB" , "Test multiple done parameters" ); + + test = ""; + + deferred.done( function() { + + deferred.done( function() { + + test += "C"; + + } ); + + test += "A"; + + }, function() { + + test += "B"; + } ); + + strictEqual( test , "ABC" , "Test done callbacks order" ); + + deferred = jQuery._Deferred(); + + deferred.resolveWith( jQuery , [ document ] ).done( function( doc ) { + ok( this === jQuery && arguments.length === 1 && doc === document , "Test fire context & args" ); + }); + + // #8421 + deferred = jQuery._Deferred(); + deferred.resolveWith().done(function() { + ok( true, "Test resolveWith can be called with no argument" ); + }); +}); + +test("jQuery.Deferred()", function() { + + expect( 10 ); + + jQuery.Deferred( function( defer ) { + strictEqual( this , defer , "Defer passed as this & first argument" ); + this.resolve( "done" ); + }).then( function( value ) { + strictEqual( value , "done" , "Passed function executed" ); + }); + + jQuery.Deferred().resolve().then( function() { + ok( true , "Success on resolve" ); + }, function() { + ok( false , "Error on resolve" ); + }); + + jQuery.Deferred().reject().then( function() { + ok( false , "Success on reject" ); + }, function() { + ok( true , "Error on reject" ); + }); + + ( new jQuery.Deferred( function( defer ) { + strictEqual( this , defer , "Defer passed as this & first argument (new)" ); + this.resolve( "done" ); + }) ).then( function( value ) { + strictEqual( value , "done" , "Passed function executed (new)" ); + }); + + ( new jQuery.Deferred() ).resolve().then( function() { + ok( true , "Success on resolve (new)" ); + }, function() { + ok( false , "Error on resolve (new)" ); + }); + + ( new jQuery.Deferred() ).reject().then( function() { + ok( false , "Success on reject (new)" ); + }, function() { + ok( true , "Error on reject (new)" ); + }); + + var tmp = jQuery.Deferred(); + + strictEqual( tmp.promise() , tmp.promise() , "Test deferred always return same promise" ); + strictEqual( tmp.promise() , tmp.promise().promise() , "Test deferred's promise always return same promise as deferred" ); +}); + +test("jQuery.when()", function() { + + expect( 23 ); + + // Some other objects + jQuery.each( { + + "an empty string": "", + "a non-empty string": "some string", + "zero": 0, + "a number other than zero": 1, + "true": true, + "false": false, + "null": null, + "undefined": undefined, + "a plain object": {} + + } , function( message , value ) { + + ok( jQuery.isFunction( jQuery.when( value ).then( function( resolveValue ) { + strictEqual( resolveValue , value , "Test the promise was resolved with " + message ); + } ).promise ) , "Test " + message + " triggers the creation of a new Promise" ); + + } ); + + ok( jQuery.isFunction( jQuery.when().then( function( resolveValue ) { + strictEqual( resolveValue , undefined , "Test the promise was resolved with no parameter" ); + } ).promise ) , "Test calling when with no parameter triggers the creation of a new Promise" ); + + var cache, i; + + for( i = 1 ; i < 4 ; i++ ) { + jQuery.when( cache || jQuery.Deferred( function() { + this.resolve( i ); + }) ).then( function( value ) { + strictEqual( value , 1 , "Function executed" + ( i > 1 ? " only once" : "" ) ); + cache = value; + }, function() { + ok( false , "Fail called" ); + }); + } +}); + +test("jQuery.when() - joined", function() { + + expect(8); + + jQuery.when( 1, 2, 3 ).done( function( a, b, c ) { + strictEqual( a , 1 , "Test first param is first resolved value - non-observables" ); + strictEqual( b , 2 , "Test second param is second resolved value - non-observables" ); + strictEqual( c , 3 , "Test third param is third resolved value - non-observables" ); + }).fail( function() { + ok( false , "Test the created deferred was resolved - non-observables"); + }); + + var successDeferred = jQuery.Deferred().resolve( 1 , 2 , 3 ), + errorDeferred = jQuery.Deferred().reject( "error" , "errorParam" ); + + jQuery.when( 1 , successDeferred , 3 ).done( function( a, b, c ) { + strictEqual( a , 1 , "Test first param is first resolved value - resolved observable" ); + same( b , [ 1 , 2 , 3 ] , "Test second param is second resolved value - resolved observable" ); + strictEqual( c , 3 , "Test third param is third resolved value - resolved observable" ); + }).fail( function() { + ok( false , "Test the created deferred was resolved - resolved observable"); + }); + + jQuery.when( 1 , errorDeferred , 3 ).done( function() { + ok( false , "Test the created deferred was rejected - rejected observable"); + }).fail( function( error , errorParam ) { + strictEqual( error , "error" , "Test first param is first rejected value - rejected observable" ); + strictEqual( errorParam , "errorParam" , "Test second param is second rejected value - rejected observable" ); + }); +}); From 55ec6a71d2378a5301af71c2c0080e15289c3f78 Mon Sep 17 00:00:00 2001 From: Dave Methvin Date: Fri, 4 Mar 2011 21:16:40 -0500 Subject: [PATCH 03/19] Fixes #7340. Use a single capturing handler to simulate bubbling focusin/focusout event on non-IE browsers. Allow native DOM methods to fire events other than the currently active one back into jQuery. --- src/event.js | 32 +++++++++++++++++++++++--------- test/unit/event.js | 25 +++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/src/event.js b/src/event.js index f7e0a08c..61c8a93f 100644 --- a/src/event.js +++ b/src/event.js @@ -70,10 +70,10 @@ jQuery.event = { } if ( !eventHandle ) { - elemData.handle = eventHandle = function() { + elemData.handle = eventHandle = function( e ) { // Handle the second event of a trigger and when // an event is called after a page has unloaded - return typeof jQuery !== "undefined" && !jQuery.event.triggered ? + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? jQuery.event.handle.apply( eventHandle.elem, arguments ) : undefined; }; @@ -380,7 +380,7 @@ jQuery.event = { target[ "on" + targetType ] = null; } - jQuery.event.triggered = true; + jQuery.event.triggered = event.type; target[ targetType ](); } @@ -391,7 +391,7 @@ jQuery.event = { target[ "on" + targetType ] = old; } - jQuery.event.triggered = false; + jQuery.event.triggered = undefined; } } }, @@ -868,19 +868,33 @@ function trigger( type, elem, args ) { // Create "bubbling" focus and blur events if ( document.addEventListener ) { jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0; + jQuery.event.special[ fix ] = { setup: function() { - this.addEventListener( orig, handler, true ); + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } }, teardown: function() { - this.removeEventListener( orig, handler, true ); + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } } }; - function handler( e ) { - e = jQuery.event.fix( e ); + function handler( donor ) { + // Donor event is always a native one; fix it and switch its type. + // Let focusin/out handler cancel the donor focus/blur event. + var e = jQuery.event.fix( donor ); e.type = fix; - return jQuery.event.handle.call( this, e ); + e.originalEvent = {}; + jQuery.event.trigger( e, null, e.target ); + if ( e.isDefaultPrevented() ) { + donor.preventDefault(); + } } }); } diff --git a/test/unit/event.js b/test/unit/event.js index b7b26046..d5498792 100644 --- a/test/unit/event.js +++ b/test/unit/event.js @@ -1966,6 +1966,31 @@ test("window resize", function() { ok( !jQuery._data(window, "__events__"), "Make sure all the events are gone." ); }); +test("focusin bubbles", function() { + expect(4); + + var input = jQuery( '' ).prependTo( "body" ), + order = 0; + + jQuery( "body" ).bind( "focusin.focusinBubblesTest", function(){ + equals( 1, order++, "focusin on the body second" ); + }); + + input.bind( "focusin.focusinBubblesTest", function(){ + equals( 0, order++, "focusin on the element first" ); + }); + + // DOM focus method + input[0].focus(); + // jQuery trigger, which calls DOM focus + order = 0; + input[0].blur(); + input.trigger( "focus" ); + + input.remove(); + jQuery( "body" ).unbind( "focusin.focusinBubblesTest" ); +}); + /* test("jQuery(function($) {})", function() { stop(); From 5c2d70979c15bbda5c90e1634abe11d8c350abcb Mon Sep 17 00:00:00 2001 From: Jordan Boesch Date: Sat, 5 Mar 2011 09:30:29 -0600 Subject: [PATCH 04/19] bug 6158; fixing replaceWith from throwing errors on empty elements --- src/manipulation.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/manipulation.js b/src/manipulation.js index ba316971..a4a81de4 100644 --- a/src/manipulation.js +++ b/src/manipulation.js @@ -261,6 +261,9 @@ jQuery.fn.extend({ } }); } else { + if ( !this.length ) { + return this; + } return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ); } }, From c9ef09c800ba7b6510d9e3a68f053ae29409f621 Mon Sep 17 00:00:00 2001 From: Jordan Boesch Date: Sat, 5 Mar 2011 09:46:12 -0600 Subject: [PATCH 05/19] bug 6158; fixing replaceWith from throwing errors on non existant elements --- src/manipulation.js | 7 +++---- test/unit/manipulation.js | 7 +++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/manipulation.js b/src/manipulation.js index a4a81de4..613faabb 100644 --- a/src/manipulation.js +++ b/src/manipulation.js @@ -261,10 +261,9 @@ jQuery.fn.extend({ } }); } else { - if ( !this.length ) { - return this; - } - return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ); + return ( this.length ) ? + this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) : + this; } }, diff --git a/test/unit/manipulation.js b/test/unit/manipulation.js index 34425ed3..1169032c 100644 --- a/test/unit/manipulation.js +++ b/test/unit/manipulation.js @@ -739,7 +739,7 @@ test("insertAfter(String|Element|Array<Element>|jQuery)", function() { }); var testReplaceWith = function(val) { - expect(20); + expect(21); jQuery('#yahoo').replaceWith(val( 'buga' )); ok( jQuery("#replace")[0], 'Replace element with string' ); ok( !jQuery("#yahoo")[0], 'Verify that original element is gone, after string' ); @@ -799,6 +799,9 @@ var testReplaceWith = function(val) { var set = jQuery("
").replaceWith(val("test")); equals( set[0].nodeName.toLowerCase(), "span", "Replace the disconnected node." ); equals( set.length, 1, "Replace the disconnected node." ); + + var non_existant = jQuery('#does-not-exist').replaceWith( val("should not throw an error") ); + equals( non_existant.length, 0, "Length of non existant element." ) var $div = jQuery("
").appendTo("body"); // TODO: Work on jQuery(...) inline script execution @@ -827,7 +830,7 @@ test("replaceWith(String|Element|Array<Element>|jQuery)", function() { test("replaceWith(Function)", function() { testReplaceWith(functionReturningObj); - expect(21); + expect(22); var y = jQuery("#yahoo")[0]; From dd100bf5ac56d5d44afe45d73fe1824bd0135872 Mon Sep 17 00:00:00 2001 From: Jordan Boesch Date: Sat, 5 Mar 2011 09:59:25 -0600 Subject: [PATCH 06/19] bug 6158; fixing replaceWith from throwing errors on non existant elements; fixing semicolon --- test/unit/manipulation.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/manipulation.js b/test/unit/manipulation.js index 1169032c..ff3dff16 100644 --- a/test/unit/manipulation.js +++ b/test/unit/manipulation.js @@ -799,9 +799,9 @@ var testReplaceWith = function(val) { var set = jQuery("
").replaceWith(val("test")); equals( set[0].nodeName.toLowerCase(), "span", "Replace the disconnected node." ); equals( set.length, 1, "Replace the disconnected node." ); - + var non_existant = jQuery('#does-not-exist').replaceWith( val("should not throw an error") ); - equals( non_existant.length, 0, "Length of non existant element." ) + equals( non_existant.length, 0, "Length of non existant element." ); var $div = jQuery("
").appendTo("body"); // TODO: Work on jQuery(...) inline script execution From 6c124d3dd47fb399c7512c5c3b3420e438c32b65 Mon Sep 17 00:00:00 2001 From: jaubourg Date: Mon, 7 Mar 2011 00:42:09 +0100 Subject: [PATCH 07/19] Fixes #8423. Never set X-Requested-With header automagically for cross-domain requests. --- src/ajax/xhr.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/ajax/xhr.js b/src/ajax/xhr.js index a6473dd8..5dbc33d3 100644 --- a/src/ajax/xhr.js +++ b/src/ajax/xhr.js @@ -92,11 +92,12 @@ if ( jQuery.support.ajax ) { xhr.overrideMimeType( s.mimeType ); } - // Requested-With header - // Not set for crossDomain requests with no content - // (see why at http://trac.dojotoolkit.org/ticket/9486) - // Won't change header if already provided - if ( !( s.crossDomain && !s.hasContent ) && !headers["X-Requested-With"] ) { + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !s.crossDomain && !headers["X-Requested-With"] ) { headers[ "X-Requested-With" ] = "XMLHttpRequest"; } From 2ac4067a639856a6035c3bd00aab132c9714b52d Mon Sep 17 00:00:00 2001 From: Dave Methvin Date: Wed, 9 Mar 2011 22:38:26 -0500 Subject: [PATCH 08/19] Fixes #8456. Make sure parent is not null before crawling into its lap, so mouseenter is triggered on a mouseover event. --- src/event.js | 2 +- test/unit/event.js | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/event.js b/src/event.js index f7e0a08c..2620646d 100644 --- a/src/event.js +++ b/src/event.js @@ -661,7 +661,7 @@ var withinElement = function( event ) { // Chrome does something similar, the parentNode property // can be accessed but is null. - if ( parent !== document && !parent.parentNode ) { + if ( parent && parent !== document && !parent.parentNode ) { return; } // Traverse up the tree diff --git a/test/unit/event.js b/test/unit/event.js index b7b26046..d66aaac9 100644 --- a/test/unit/event.js +++ b/test/unit/event.js @@ -683,6 +683,20 @@ test("hover()", function() { equals( times, 4, "hover handlers fired" ); }); +test("mouseover triggers mouseenter", function() { + expect(1); + + var count = 0, + elem = jQuery(""); + elem.mouseenter(function () { + count++; + }); + elem.trigger('mouseover'); + equals(count, 1, "make sure mouseover triggers a mouseenter" ); + + elem.remove(); +}); + test("trigger() shortcuts", function() { expect(6); From 124acbfbc523614dc5835cfce2c82b867a59986f Mon Sep 17 00:00:00 2001 From: Jordan Boesch Date: Mon, 14 Mar 2011 14:17:02 -0600 Subject: [PATCH 09/19] removing parens --- src/manipulation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/manipulation.js b/src/manipulation.js index 613faabb..27f81cc2 100644 --- a/src/manipulation.js +++ b/src/manipulation.js @@ -261,7 +261,7 @@ jQuery.fn.extend({ } }); } else { - return ( this.length ) ? + return this.length ? this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) : this; } From 714ae379db9dcb704c04080196a05d13a028f7a4 Mon Sep 17 00:00:00 2001 From: jaubourg Date: Tue, 15 Mar 2011 19:20:03 +0100 Subject: [PATCH 10/19] Fixes #8509. Makes URL regexp less overzealous and ensures it recognizes URL schemes which do not contain a conformant hierarchical structure ( as per section 2.1.2 of http://www.ietf.org/rfc/rfc2718.txt ). Also adds about: and adobe air's app: and app-storage: to the list of local protocols and provides a failover in case document.location is illformed. Unit test added. --- src/ajax.js | 6 +++--- test/unit/ajax.js | 12 +++++++++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/ajax.js b/src/ajax.js index 4714afda..add3b373 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -7,7 +7,7 @@ var r20 = /%20/g, rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i, // #7653, #8125, #8152: local protocol detection - rlocalProtocol = /(?:^file|^widget|\-extension):$/, + rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|widget):$/, rnoContent = /^(?:GET|HEAD)$/, rprotocol = /^\/\//, rquery = /\?/, @@ -19,7 +19,7 @@ var r20 = /%20/g, rucHeadersFunc = function( _, $1, $2 ) { return $1 + $2.toUpperCase(); }, - rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?|\/[^\/])/, + rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/, // Keep a copy of the old load method _load = jQuery.fn.load, @@ -61,7 +61,7 @@ try { } // Segment location into parts -ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ); +ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || []; // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport function addToPrefiltersOrTransports( structure ) { diff --git a/test/unit/ajax.js b/test/unit/ajax.js index 2a2ac46a..7c572a32 100644 --- a/test/unit/ajax.js +++ b/test/unit/ajax.js @@ -492,7 +492,7 @@ test(".ajax() - hash", function() { test("jQuery ajax - cross-domain detection", function() { - expect( 5 ); + expect( 6 ); var loc = document.location, otherPort = loc.port === 666 ? 667 : 666, @@ -508,6 +508,7 @@ test("jQuery ajax - cross-domain detection", function() { }); jQuery.ajax({ + dataType: "jsonp", url: 'app:/path', beforeSend: function( _ , s ) { ok( s.crossDomain , "Adobe AIR app:/ URL detected as cross-domain" ); @@ -533,6 +534,15 @@ test("jQuery ajax - cross-domain detection", function() { } }); + jQuery.ajax({ + dataType: "jsonp", + url: "about:blank", + beforeSend: function( _ , s ) { + ok( s.crossDomain , "Test about:blank is detected as cross-domain" ); + return false; + } + }); + jQuery.ajax({ dataType: "jsonp", url: loc.protocol + "//" + loc.host, From 150d3decb54971a7378fb48d0b6970d3fb50ff95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carl=20F=C3=BCrstenberg?= Date: Tue, 15 Mar 2011 20:16:09 +0100 Subject: [PATCH 11/19] Introduce submodules, closes #8536 Instead of the manual clone of sizzle and qunit, use git submodules instead. this will ensure that all future releases can be recreated by checking out an tag. --- .gitignore | 2 -- .gitmodules | 6 ++++++ Makefile | 34 ++++------------------------------ src/sizzle | 1 + test/qunit | 1 + 5 files changed, 12 insertions(+), 32 deletions(-) create mode 100644 .gitmodules create mode 160000 src/sizzle create mode 160000 test/qunit diff --git a/.gitignore b/.gitignore index a77d67a9..6cd54797 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,5 @@ dist *~ *.diff *.patch -test/qunit -src/sizzle /*.html .DS_Store diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..80ce2368 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "src/sizzle"] + path = src/sizzle + url = git://github.com/jeresig/sizzle.git +[submodule "test/qunit"] + path = test/qunit + url = git://github.com/jquery/qunit.git diff --git a/Makefile b/Makefile index a6aae425..e0d1da71 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,3 @@ -V ?= 0 - SRC_DIR = src TEST_DIR = test BUILD_DIR = build @@ -38,7 +36,6 @@ JQ = ${DIST_DIR}/jquery.js JQ_MIN = ${DIST_DIR}/jquery.min.js SIZZLE_DIR = ${SRC_DIR}/sizzle -QUNIT_DIR = ${TEST_DIR}/qunit JQ_VER = $(shell cat version.txt) VER = sed "s/@VERSION/${JQ_VER}/" @@ -51,32 +48,8 @@ all: jquery min lint ${DIST_DIR}: @@mkdir -p ${DIST_DIR} -ifeq ($(strip $(V)),0) -verbose = --quiet -else ifeq ($(strip $(V)),1) -verbose = -else -verbose = --verbose -endif - -define clone_or_pull --@@if test ! -d $(strip ${1})/.git; then \ - echo "Cloning $(strip ${1})..."; \ - git clone $(strip ${verbose}) --depth=1 $(strip ${2}) $(strip ${1}); \ - else \ - echo "Pulling $(strip ${1})..."; \ - git --git-dir=$(strip ${1})/.git pull $(strip ${verbose}) origin master; \ - fi - -endef - -${QUNIT_DIR}: - $(call clone_or_pull, ${QUNIT_DIR}, git://github.com/jquery/qunit.git) - -${SIZZLE_DIR}: - $(call clone_or_pull, ${SIZZLE_DIR}, git://github.com/jeresig/sizzle.git) - -init: ${QUNIT_DIR} ${SIZZLE_DIR} +init: + @@if [ -d .git ]; then git submodule update --init --recursive; fi jquery: init ${JQ} jq: init ${JQ} @@ -122,7 +95,8 @@ clean: @@echo "Removing built copy of Sizzle" @@rm -f src/selector.js - @@echo "Removing cloned directories" +distclean: clean + @@echo "Removing submodules" @@rm -rf test/qunit src/sizzle .PHONY: all jquery lint min init jq clean diff --git a/src/sizzle b/src/sizzle new file mode 160000 index 00000000..ef19279f --- /dev/null +++ b/src/sizzle @@ -0,0 +1 @@ +Subproject commit ef19279f54ba49242c6461d47577c703f4f4e80e diff --git a/test/qunit b/test/qunit new file mode 160000 index 00000000..d404faf8 --- /dev/null +++ b/test/qunit @@ -0,0 +1 @@ +Subproject commit d404faf8f587fcbe6b8907943022e6318dd51e0c From cd2ca7b5918b3cedfed497ac7d86bfd2c5f92a8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carl=20F=C3=BCrstenberg?= Date: Tue, 15 Mar 2011 21:25:51 +0100 Subject: [PATCH 12/19] pull submodules make command Adding an helper funciton to pull the latest from all registered submodules --- Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Makefile b/Makefile index e0d1da71..7b67f7af 100644 --- a/Makefile +++ b/Makefile @@ -99,4 +99,9 @@ distclean: clean @@echo "Removing submodules" @@rm -rf test/qunit src/sizzle +# update the submodules to the latest at the most logical branch +pull_submodules: + @@git submodule foreach "git pull origin \$$(git branch --no-color --contains \$$(git rev-parse HEAD) | grep -v \( | head -1)" + @@git submodule summary + .PHONY: all jquery lint min init jq clean From bd4468886d97edfb53342e1a10acb300d081ed27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carl=20F=C3=BCrstenberg?= Date: Tue, 15 Mar 2011 21:42:58 +0100 Subject: [PATCH 13/19] adding pull command --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 7b67f7af..84816a19 100644 --- a/Makefile +++ b/Makefile @@ -104,4 +104,7 @@ pull_submodules: @@git submodule foreach "git pull origin \$$(git branch --no-color --contains \$$(git rev-parse HEAD) | grep -v \( | head -1)" @@git submodule summary +pull: pull_submodules + @@git pull ${REMOTE} ${BRANCH} + .PHONY: all jquery lint min init jq clean From a2faed347de389d6f667a4e98576398db88d1a14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carl=20F=C3=BCrstenberg?= Date: Thu, 17 Mar 2011 19:50:53 +0100 Subject: [PATCH 14/19] Merge when updating submodules on make When running make, the submodule update will remove all local changes. Adding flag --rebase or --merge does solve the issue. rebase will probably make it cleaner, but it might stop on conflict, thus --merge will result in fewer (probably none). --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 84816a19..525d3a19 100644 --- a/Makefile +++ b/Makefile @@ -49,7 +49,7 @@ ${DIST_DIR}: @@mkdir -p ${DIST_DIR} init: - @@if [ -d .git ]; then git submodule update --init --recursive; fi + @@if [ -d .git ]; then git submodule update --init --recursive --merge; fi jquery: init ${JQ} jq: init ${JQ} From 22738e0e4b988f8ce2cb341b137ba0fe4646d3f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carl=20F=C3=BCrstenberg?= Date: Thu, 17 Mar 2011 20:15:44 +0100 Subject: [PATCH 15/19] Remove jq target remove obsolete jq target --- Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile b/Makefile index 525d3a19..3223b8da 100644 --- a/Makefile +++ b/Makefile @@ -52,7 +52,6 @@ init: @@if [ -d .git ]; then git submodule update --init --recursive --merge; fi jquery: init ${JQ} -jq: init ${JQ} ${JQ}: ${MODULES} | ${DIST_DIR} @@echo "Building" ${JQ} From 4f9e78616ecd9ca403a25ee0e3dc71781484e553 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carl=20F=C3=BCrstenberg?= Date: Thu, 17 Mar 2011 20:14:15 +0100 Subject: [PATCH 16/19] Change makefile order to only update submodules on 'all' target insterad of always update the submodules, now only "make all" will run that, thus an "make jquery" will not update them --- Makefile | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 3223b8da..9ef44cff 100644 --- a/Makefile +++ b/Makefile @@ -42,16 +42,13 @@ VER = sed "s/@VERSION/${JQ_VER}/" DATE=$(shell git log -1 --pretty=format:%ad) -all: jquery min lint +all: update_submodules jquery min lint @@echo "jQuery build complete." ${DIST_DIR}: @@mkdir -p ${DIST_DIR} -init: - @@if [ -d .git ]; then git submodule update --init --recursive --merge; fi - -jquery: init ${JQ} +jquery: ${JQ} ${JQ}: ${MODULES} | ${DIST_DIR} @@echo "Building" ${JQ} @@ -98,6 +95,10 @@ distclean: clean @@echo "Removing submodules" @@rm -rf test/qunit src/sizzle +# change pointers for submodules and update them to what is specified in jQuery +update_submodules: + @@if [ -d .git ]; then git submodule update --init --recursive --merge; fi + # update the submodules to the latest at the most logical branch pull_submodules: @@git submodule foreach "git pull origin \$$(git branch --no-color --contains \$$(git rev-parse HEAD) | grep -v \( | head -1)" From b4acb7ae819563c3b75bbdabfaf2662fd24b06e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carl=20F=C3=BCrstenberg?= Date: Thu, 17 Mar 2011 20:16:19 +0100 Subject: [PATCH 17/19] updating phony rules --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9ef44cff..d377c4cf 100644 --- a/Makefile +++ b/Makefile @@ -107,4 +107,4 @@ pull_submodules: pull: pull_submodules @@git pull ${REMOTE} ${BRANCH} -.PHONY: all jquery lint min init jq clean +.PHONY: all jquery lint min clean distclean update_submodules pull_submodules pull From e2dd8916eef1daba1a56a5ff1fbb44cb3385f4f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carl=20F=C3=BCrstenberg?= Date: Thu, 17 Mar 2011 20:26:45 +0100 Subject: [PATCH 18/19] Adding core target Adding core target to do jquery, minimization and lint --- Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index d377c4cf..99e742d6 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,9 @@ VER = sed "s/@VERSION/${JQ_VER}/" DATE=$(shell git log -1 --pretty=format:%ad) -all: update_submodules jquery min lint +all: update_submodules core + +core: jquery min lint @@echo "jQuery build complete." ${DIST_DIR}: @@ -107,4 +109,4 @@ pull_submodules: pull: pull_submodules @@git pull ${REMOTE} ${BRANCH} -.PHONY: all jquery lint min clean distclean update_submodules pull_submodules pull +.PHONY: all jquery lint min clean distclean update_submodules pull_submodules pull core From 8a1156da9b835d826bfb4b82c41bcdd0d87aff05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carl=20F=C3=BCrstenberg?= Date: Thu, 17 Mar 2011 20:40:07 +0100 Subject: [PATCH 19/19] merge doesn't work when init sadly the merge strategy doesn't work when doing an initial clone, circumvent that --- Makefile | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 99e742d6..2c7bb808 100644 --- a/Makefile +++ b/Makefile @@ -98,8 +98,16 @@ distclean: clean @@rm -rf test/qunit src/sizzle # change pointers for submodules and update them to what is specified in jQuery +# --merge doesn't work when doing an initial clone, thus test if we have non-existing +# submodules, then do an real update update_submodules: - @@if [ -d .git ]; then git submodule update --init --recursive --merge; fi + @@if [ -d .git ]; then \ + if git submodule status | grep -q -E '^-'; then \ + git submodule update --init --recursive; \ + else \ + git submodule update --init --recursive --merge; \ + fi; \ + fi; # update the submodules to the latest at the most logical branch pull_submodules: