Rewrote the data conversion logic in ajax. Should be cleaner and faster.
authorjaubourg <aubourg.julian@gmail.com>
Tue, 21 Dec 2010 15:58:52 +0000 (16:58 +0100)
committerjaubourg <j@ubourg.net>
Fri, 31 Dec 2010 02:56:10 +0000 (03:56 +0100)
src/ajax.js
src/xhr.js

index a5fff4e..6f09362 100644 (file)
@@ -166,11 +166,6 @@ jQuery.extend({
                xhr: function() {
                        return new window.XMLHttpRequest();
                },
-               xhrResponseFields: {
-                       xml: "XML",
-                       text: "Text",
-                       json: "JSON"
-               },
 
                accepts: {
                        xml: "application/xml, text/xml",
@@ -195,13 +190,13 @@ jQuery.extend({
                // 4) the catchall symbol "*" can be used
                // 5) execution will start with transport dataType and THEN continue down to "*" if needed
                prefilters: {},
-               
+
                // Transports bindings
                // 1) key is the dataType
                // 2) the catchall symbol "*" can be used
                // 3) selection will start with transport dataType and THEN go to "*" if needed
                transports: {},
-               
+
                // Checkers
                // 1) key is dataType
                // 2) they are called to control successful response
index d64238a..94c6fe1 100644 (file)
@@ -6,11 +6,9 @@ var rquery_xhr = /\?/,
        rnoContent = /^(?:GET|HEAD)$/,
        rts = /([?&])_=[^&]*/,
        rurl = /^(\w+:)?\/\/([^\/?#]+)/,
-
-       sliceFunc = Array.prototype.slice,
-
-       isFunction = jQuery.isFunction;
-
+       
+       sliceFunc = Array.prototype.slice;
+       
 // Creates a jQuery xhr object
 jQuery.xhr = function( _native ) {
 
@@ -86,7 +84,7 @@ jQuery.xhr = function( _native ) {
                if ( data && s.processData && typeof data != "string" ) {
                        data = s.data = jQuery.param( data , s.traditional );
                }
-               
+
                // Get internal
                internal = jQuery.xhr.prefilter( s ).transport( s );
                
@@ -147,7 +145,7 @@ jQuery.xhr = function( _native ) {
                                requestHeaders[ i.toLowerCase() ] = headers[ i ];
                        }
                }
-
+               
                callbackContext = s.context || s;
                globalEventContext = s.context ? jQuery(s.context) : jQuery.event;
                
@@ -223,112 +221,77 @@ jQuery.xhr = function( _native ) {
                                // Chain data conversions and determine the final value
                                // (if an exception is thrown in the process, it'll be notified as an error)
                                try {
-
-                                       function checkData(data) {
-                                               if ( data !== undefined ) {
-                                                       var testFunction = s.dataCheckers[srcDataType];
-                                                       if ( isFunction( testFunction ) ) {
-                                                               testFunction(data);
-                                                       }
-                                               }
-                                       }
-
-                                       function convertData (data) {
-                                               var conversionFunction = dataConverters[srcDataType+" => "+destDataType] ||
-                                                               dataConverters["* => "+destDataType],
-                                                       noFunction = ! isFunction( conversionFunction );
-                                               if ( noFunction ) {
-                                                       if ( srcDataType != "text" && destDataType != "text" ) {
-                                                               // We try to put text inbetween
-                                                               var first = dataConverters[srcDataType+" => text"] ||
-                                                                               dataConverters["* => text"],
-                                                                       second = dataConverters["text => "+destDataType] ||
-                                                                               dataConverters["* => "+destDataType],
-                                                                       areFunctions = isFunction( first ) && isFunction( second );
-                                                               if ( areFunctions ) {
-                                                                       conversionFunction = function (data) {
-                                                                               return second( first ( data ) );
-                                                                       };
+                                       
+                                       var i,
+                                               current,
+                                               prev,
+                                               checker,
+                                               conv1,
+                                               conv2,
+                                               oneConv,
+                                               convertion,
+                                               dataTypes = s.dataTypes,
+                                               dataCheckers = s.dataCheckers,
+                                               dataConverters = s.dataConverters,
+                                               dataFilter = s.dataFilter,
+                                               responses = {
+                                                       "xml": "XML",
+                                                       "text": "Text"
+                                               };
+                                       
+                                       for( i = 0 ; i < dataTypes.length ; i++ ) {
+                                               
+                                               current = dataTypes[ i ];
+                                               
+                                               if ( i ) {
+                                                       
+                                                       prev = dataTypes[ i - 1 ];
+                                                       
+                                                       if ( prev === "*" ) {
+                                                               
+                                                               prev = current;
+                                                               
+                                                       } else if ( current !== "*" && prev !== current ) {
+                                                       
+                                                               oneConv = conv1 = 
+                                                                       dataConverters[ ( conversion = prev + " => " + current ) ] ||
+                                                                       dataConverters[ "* => " + current ];
+                                                               
+                                                               if ( ! oneConv && prev !== "text" && current !== "text" ) {
+                                                                       conv1 = dataConverters[ prev + " => text" ] || dataConverters[ "* => text" ];
+                                                                       conv2 = dataConverters[ "text => " + current ];
+                                                               }
+                                                               if ( oneConv || conv1 && conv2 ) {
+                                                                       response = oneConv ? conv1( response ) : conv2( conv1( response ) );
+                                                               } else {
+                                                                       throw "no " + conversion;
                                                                }
-                                                               noFunction = ! areFunctions;
-                                                       }
-                                                       if ( noFunction ) {
-                                                               jQuery.error( "no data converter between " + srcDataType + " and " + destDataType );
                                                        }
-
                                                }
-                                               return conversionFunction(data);
-                                       }
-
-                                       var dataTypes = s.dataTypes,
-                                               i,
-                                               length,
-                                               data = response,
-                                               dataConverters = s.dataConverters,
-                                               srcDataType,
-                                               destDataType,
-                                               responseTypes = s.xhrResponseFields;
-
-                                       for ( i = 0, length = dataTypes.length ; i < length ; i++ ) {
-
-                                               destDataType = dataTypes[i];
-
-                                               if ( !srcDataType ) { // First time
-
-                                                       // Copy type
-                                                       srcDataType = destDataType;
-                                                       // Check
-                                                       checkData(data);
-                                                       // Apply dataFilter
-                                                       if ( isFunction( s.dataFilter ) ) {
-                                                               data = s.dataFilter(data, s.dataType);
-                                                               // Recheck data
-                                                               checkData(data);
-                                                       }
-
-                                               } else { // Subsequent times
-
-                                                       // handle auto
-                                                       // JULIAN: for reasons unknown to me === doesn't work here
-                                                       if (destDataType == "*") {
-
-                                                               destDataType = srcDataType;
-
-                                                       } else if ( srcDataType != destDataType ) {
-
-                                                               // Convert
-                                                               data = convertData(data);
-                                                               // Copy type & check
-                                                               srcDataType = destDataType;
-                                                               checkData(data);
-
-                                                       }
-
+                                               
+                                               checker = dataCheckers[ current ];
+                                               
+                                               if ( response != null && checker ) {
+                                                       checker( response );
                                                }
-
-                                               // Copy response into the xhr if it hasn't been already
-                                               var responseDataType,
-                                                       responseType = responseTypes[srcDataType];
-
-                                               if ( responseType ) {
-
-                                                       responseDataType = srcDataType;
-
-                                               } else {
-
-                                                       responseType = responseTypes[ responseDataType = "text" ];
-
+                                               
+                                               if ( responses[ current ] ) {
+                                                       xhr[ "response" + responses[ current ] ] = response;
+                                                       responses[ current ] = 0;
                                                }
-
-                                               if ( responseType !== 1 ) {
-                                                       xhr[ "response" + responseType ] = data;
-                                                       responseTypes[ responseType ] = 1;
+                                               
+                                               if ( ! i && dataFilter ) {
+                                                       
+                                                       response = dataFilter( response );
+                                                       
+                                                       dataTypes = s.dataTypes;
+                                                       dataFilter = 0;
+                                                       i--;
                                                }
-
                                        }
 
                                        // We have a real success
-                                       success = data;
+                                       success = response;
                                        isSuccess = 1;
 
                                } catch(e) {
@@ -406,7 +369,7 @@ jQuery.xhr = function( _native ) {
        // Ready state change
        function setState( value ) {
                xhr.readyState = value;
-               if ( isFunction( xhr.onreadystatechange ) ) {
+               if ( jQuery.isFunction( xhr.onreadystatechange ) ) {
                        xhr.onreadystatechange();
                }
        }