Commit dc2e7317 authored by jaubourg's avatar jaubourg

Replaces "text in-between" technique with a full-fledged one-level transitive...

Replaces "text in-between" technique with a full-fledged one-level transitive search for converters (unit tests added). Also cleans up auto dataType determination and adds converter checks in order to guess the best dataType possible.
parent 2e2d5e9d
...@@ -372,8 +372,9 @@ jQuery.extend({ ...@@ -372,8 +372,9 @@ jQuery.extend({
clearTimeout(timeoutTimer); clearTimeout(timeoutTimer);
} }
var // Reference dataTypes and responseFields var // Reference dataTypes, converters and responseFields
dataTypes = s.dataTypes, dataTypes = s.dataTypes,
converters = s.converters,
responseFields = s.responseFields, responseFields = s.responseFields,
responseField, responseField,
...@@ -400,44 +401,64 @@ jQuery.extend({ ...@@ -400,44 +401,64 @@ jQuery.extend({
transportDataType = dataTypes[0], transportDataType = dataTypes[0],
ct, ct,
type, type,
finalDataType; finalDataType,
firstDataType;
// Auto (xml, json, script or text determined given headers) // Auto (xml, json, script or text determined given headers)
if ( transportDataType === "*" && ( ct = jXHR.getResponseHeader( "content-type" ) ) ) { if ( transportDataType === "*" ) {
// Remove all auto types
while( dataTypes[0] === "*" ) {
dataTypes.shift();
}
transportDataTypes = dataTypes[0];
// Get content type
ct = jXHR.getResponseHeader( "content-type" );
// Check if it's a known type
for ( type in contents ) { for ( type in contents ) {
if ( contents[ type ] && contents[ type ].test( ct ) ) { if ( contents[ type ] && contents[ type ].test( ct ) ) {
transportDataType = dataTypes[0] = type; dataTypes.unshift( ( transportDataType = type ) );
break; break;
} }
} }
type = undefined;
} }
// Get final dataType // Check to see if we have a response for the expected dataType
for( type in responses ) { if ( transportDataType in responses ) {
if ( ! finalDataType && type === transportDataType ) { finalDataType = transportDataType;
finalDataType = type; } else {
} // Try convertible dataTypes
responseField = responseFields[ type ]; for ( type in responses ) {
if ( responseField && ! ( responseField in jXHR ) ) { if ( ! firstDataType ) {
jXHR[ responseField ] = responses[ type ]; firstDataType = type;
}
if ( ! transportDataType || converters[ type + " " + transportDataType ] ) {
finalDataType = type;
break;
}
} }
// Or just use first one
finalDataType = finalDataType || firstDataType;
} }
// If no response with the expected dataType was provided // If we found a dataType
// Take the last response as a default if it exists // We get the corresponding response
if ( ! finalDataType && type ) { // and add the dataType to the list if needed
finalDataType = type; if ( finalDataType ) {
if ( transportDataType === "*" ) { response = responses[ finalDataType ];
dataTypes.shift(); if ( finalDataType !== transportDataType ) {
dataTypes.unshift( finalDataType );
} }
dataTypes.unshift( finalDataType );
} }
// Get final response // Fill responseXXX fields
response = responses[ finalDataType ]; for( type in responseFields ) {
if ( type in responses ) {
jXHR[ responseFields[ type ] ] = responses[ type ];
}
}
} }
// If successful, handle type chaining // If successful, handle type chaining
...@@ -473,6 +494,7 @@ jQuery.extend({ ...@@ -473,6 +494,7 @@ jQuery.extend({
try { try {
var i, var i,
tmp,
// Current dataType // Current dataType
current, current,
// Previous dataType // Previous dataType
...@@ -483,9 +505,7 @@ jQuery.extend({ ...@@ -483,9 +505,7 @@ jQuery.extend({
conv, conv,
// Conversion functions (when text is used in-between) // Conversion functions (when text is used in-between)
conv1, conv1,
conv2, conv2;
// Local references to converters
converters = s.converters;
// For each dataType in the chain // For each dataType in the chain
for( i = 0 ; i < dataTypes.length ; i++ ) { for( i = 0 ; i < dataTypes.length ; i++ ) {
...@@ -505,26 +525,31 @@ jQuery.extend({ ...@@ -505,26 +525,31 @@ jQuery.extend({
// Get the dataType to convert from // Get the dataType to convert from
prev = dataTypes[ i - 1 ]; prev = dataTypes[ i - 1 ];
// If no catch-all and dataTypes are actually different // If no auto and dataTypes are actually different
if ( prev !== "*" && current !== "*" && prev !== current ) { if ( prev !== "*" && current !== "*" && prev !== current ) {
// Get the converter // Get the converter
conversion = prev + " " + current; conversion = prev + " " + current;
conv = converters[ conversion ] || converters[ "* " + current ]; conv = converters[ conversion ] || converters[ "* " + current ];
conv1 = conv2 = 0; // If there is no direct converter, search transitively
if ( ! conv ) {
// If there is no direct converter and none of the dataTypes is text conv1 = conv2 = undefined;
if ( ! conv && prev !== "text" && current !== "text" ) {
// Try with text in-between for( conv1 in converters ) {
conv1 = converters[ prev + " text" ] || converters[ "* text" ]; tmp = conv1.split( " " );
conv2 = converters[ "text " + current ]; if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) {
// Revert back to a single converter conv2 = converters[ tmp[ 1 ] + " " + current ];
// if one of the converter is an equivalence if ( conv2 ) {
if ( conv1 === true ) { conv1 = converters[ conv1 ];
conv = conv2; if ( conv1 === true ) {
} else if ( conv2 === true ) { conv = conv2;
conv = conv1; } else if ( conv2 === true ) {
conv = conv1;
}
break;
}
}
} }
} }
// If we found no converter, dispatch an error // If we found no converter, dispatch an error
......
...@@ -2006,6 +2006,49 @@ test( "jQuery.ajax - statusCode" , function() { ...@@ -2006,6 +2006,49 @@ test( "jQuery.ajax - statusCode" , function() {
}); });
}); });
test("jQuery.ajax - transitive conversions", function() {
expect( 8 );
stop();
jQuery.when(
jQuery.ajax( url("data/json.php") , {
converters: {
"json myjson": function( data ) {
ok( true , "converter called" );
return data;
}
},
dataType: "myjson",
success: function() {
ok( true , "Transitive conversion worked" );
strictEqual( this.dataTypes[0] , "text" , "response was retrieved as text" );
strictEqual( this.dataTypes[1] , "myjson" , "request expected myjson dataType" );
}
}),
jQuery.ajax( url("data/json.php") , {
converters: {
"json myjson": function( data ) {
ok( true , "converter called (*)" );
return data;
}
},
contents: false, /* headers are wrong so we ignore them */
dataType: "* myjson",
success: function() {
ok( true , "Transitive conversion worked (*)" );
strictEqual( this.dataTypes[0] , "text" , "response was retrieved as text (*)" );
strictEqual( this.dataTypes[1] , "myjson" , "request expected myjson dataType (*)" );
}
})
).then( start , start );
});
test("jQuery.ajax - active counter", function() { test("jQuery.ajax - active counter", function() {
ok( jQuery.active == 0, "ajax active counter should be zero: " + jQuery.active ); ok( jQuery.active == 0, "ajax active counter should be zero: " + jQuery.active );
}); });
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment