Fixes #2994. Not finding a transport now fires the error callbacks and doesn't make...
[jquery.git] / src / ajax / jsonp.js
index 5cfb783..675ecc0 100644 (file)
@@ -1,52 +1,38 @@
 (function( jQuery ) {
 
 var jsc = jQuery.now(),
-       jsre = /\=\?(&|$)/,
+       jsre = /(\=)(?:\?|%3F)(&|$)|()(?:\?\?|%3F%3F)()/i,
        rquery_jsonp = /\?/;
 
-// Default jsonp callback name
-jQuery.ajaxSettings.jsonpCallback = function() {
-       return "jsonp" + jsc++;
-};
-
-// Normalize jsonp queries
-// 1) put callback parameter in url or data
-// 2) sneakily ensure transportDataType is json
-// 3) ensure options jsonp is always provided so that jsonp requests are always
-//    json request with the jsonp option set
-jQuery.ajax.prefilter("json jsonp", function(s) {
-
-       var transportDataType = s.dataTypes[ 0 ];
+// Default jsonp settings
+jQuery.ajaxSetup({
+       jsonp: "callback",
+       jsonpCallback: function() {
+               return "jsonp" + jsc++;
+       }
 
-       s.dataTypes[ 0 ] = "json";
+// Detect, normalize options and install callbacks for jsonp requests
+}).ajaxPrefilter("json jsonp", function(s, originalSettings) {
 
-       if ( s.jsonp ||
-               transportDataType === "jsonp" ||
-               transportDataType === "json" && ( jsre.test(s.url) || typeof(s.data) === "string" && jsre.test(s.data) ) ) {
+       if ( s.dataTypes[ 0 ] === "jsonp" ||
+               originalSettings.jsonp ||
+               originalSettings.jsonpCallback ||
+               jsre.test(s.url) ||
+               typeof(s.data) === "string" && jsre.test(s.data) ) {
 
-               var jsonp = s.jsonp = s.jsonp || "callback",
+               var responseContainer,
                        jsonpCallback = s.jsonpCallback =
                                jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
-                       url = s.url.replace(jsre, "=" + jsonpCallback + "$1"),
-                       data = s.url == url && typeof(s.data) === "string" ? s.data.replace(jsre, "=" + jsonpCallback + "$1") : s.data;
+                       previous = window[ jsonpCallback ],
+                       url = s.url.replace(jsre, "$1" + jsonpCallback + "$2"),
+                       data = s.url === url && typeof(s.data) === "string" ? s.data.replace(jsre, "$1" + jsonpCallback + "$2") : s.data;
 
-               if ( url == s.url && data == s.data ) {
-                       url = url += (rquery_jsonp.test( url ) ? "&" : "?") + jsonp + "=" + jsonpCallback;
+               if ( url === s.url && data === s.data ) {
+                       url += (rquery_jsonp.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
                }
 
                s.url = url;
                s.data = data;
-       }
-
-// Bind transport to json dataType
-}).transport("json", function(s) {
-
-       if ( s.jsonp ) {
-
-               // Put callback in place
-               var responseContainer,
-                       jsonpCallback = s.jsonpCallback,
-                       previous = window[ jsonpCallback ];
 
                window [ jsonpCallback ] = function( response ) {
                        responseContainer = [response];
@@ -77,7 +63,10 @@ jQuery.ajax.prefilter("json jsonp", function(s) {
                        return responseContainer[ 0 ];
                };
 
-               // Delegate to script transport
+               // force json dataType
+               s.dataTypes[ 0 ] = "json";
+
+               // Delegate to script
                return "script";
        }
 });