@@ -5,7 +5,11 @@ import { migrateWarn, migratePatchAndWarnFunc, migratePatchFunc } from "../main.
5
5
if ( jQuery . ajax ) {
6
6
7
7
var oldAjax = jQuery . ajax ,
8
- rjsonp = / ( = ) \? (? = & | $ ) | \? \? / ;
8
+ oldCallbacks = [ ] ,
9
+ guid = "migrate-" + Date . now ( ) ,
10
+ origJsonpCallback = jQuery . ajaxSettings . jsonpCallback ,
11
+ rjsonp = / ( = ) \? (? = & | $ ) | \? \? / ,
12
+ rquery = / \? / ;
9
13
10
14
migratePatchFunc ( jQuery , "ajax" , function ( ) {
11
15
var jQXHR = oldAjax . apply ( this , arguments ) ;
@@ -23,16 +27,120 @@ migratePatchFunc( jQuery, "ajax", function() {
23
27
return jQXHR ;
24
28
} , "jqXHR-methods" ) ;
25
29
26
- // Only trigger the logic in jQuery <4 as the JSON-to-JSONP auto-promotion
27
- // behavior is gone in jQuery 4.0 and as it has security implications, we don't
28
- // want to restore the legacy behavior.
29
- if ( ! jQueryVersionSince ( "4.0.0" ) ) {
30
+ jQuery . ajaxSetup ( {
31
+ jsonpCallback : function ( ) {
30
32
31
- // Register this prefilter before the jQuery one. Otherwise, a promoted
32
- // request is transformed into one with the script dataType and we can't
33
- // catch it anymore.
33
+ // Source is virtually the same as in Core, but we need to duplicate
34
+ // to maintain a proper `oldCallbacks` reference.
35
+ if ( jQuery . migrateIsPatchEnabled ( "jsonp-promotion" ) ) {
36
+ var callback = oldCallbacks . pop ( ) || ( jQuery . expando + "_" + ( guid ++ ) ) ;
37
+ this [ callback ] = true ;
38
+ return callback ;
39
+ } else {
40
+ return origJsonpCallback . apply ( this , arguments ) ;
41
+ }
42
+ }
43
+ } ) ;
44
+
45
+ // Register this prefilter before the jQuery one. Otherwise, a promoted
46
+ // request is transformed into one with the script dataType, and we can't
47
+ // catch it anymore.
48
+ if ( jQueryVersionSince ( "4.0.0" ) ) {
49
+
50
+ // Code mostly from:
51
+ // https://github.com/jquery/jquery/blob/fa0058af426c4e482059214c29c29f004254d9a1/src/ajax/jsonp.js#L20-L97
52
+ jQuery . ajaxPrefilter ( "+json" , function ( s , originalSettings , jqXHR ) {
53
+
54
+ if ( ! jQuery . migrateIsPatchEnabled ( "jsonp-promotion" ) ) {
55
+ return ;
56
+ }
57
+
58
+ var callbackName , overwritten , responseContainer ,
59
+ jsonProp = s . jsonp !== false && ( rjsonp . test ( s . url ) ?
60
+ "url" :
61
+ typeof s . data === "string" &&
62
+ ( s . contentType || "" )
63
+ . indexOf ( "application/x-www-form-urlencoded" ) === 0 &&
64
+ rjsonp . test ( s . data ) && "data"
65
+ ) ;
66
+
67
+ // Handle iff the expected data type is "jsonp" or we have a parameter to set
68
+ if ( jsonProp || s . dataTypes [ 0 ] === "jsonp" ) {
69
+ migrateWarn ( "jsonp-promotion" , "JSON-to-JSONP auto-promotion is deprecated" ) ;
70
+
71
+ // Get callback name, remembering preexisting value associated with it
72
+ callbackName = s . jsonpCallback = typeof s . jsonpCallback === "function" ?
73
+ s . jsonpCallback ( ) :
74
+ s . jsonpCallback ;
75
+
76
+ // Insert callback into url or form data
77
+ if ( jsonProp ) {
78
+ s [ jsonProp ] = s [ jsonProp ] . replace ( rjsonp , "$1" + callbackName ) ;
79
+ } else if ( s . jsonp !== false ) {
80
+ s . url += ( rquery . test ( s . url ) ? "&" : "?" ) + s . jsonp + "=" + callbackName ;
81
+ }
82
+
83
+ // Use data converter to retrieve json after script execution
84
+ s . converters [ "script json" ] = function ( ) {
85
+ if ( ! responseContainer ) {
86
+ jQuery . error ( callbackName + " was not called" ) ;
87
+ }
88
+ return responseContainer [ 0 ] ;
89
+ } ;
90
+
91
+ // Force json dataType
92
+ s . dataTypes [ 0 ] = "json" ;
93
+
94
+ // Install callback
95
+ overwritten = window [ callbackName ] ;
96
+ window [ callbackName ] = function ( ) {
97
+ responseContainer = arguments ;
98
+ } ;
99
+
100
+ // Clean-up function (fires after converters)
101
+ jqXHR . always ( function ( ) {
102
+
103
+ // If previous value didn't exist - remove it
104
+ if ( overwritten === undefined ) {
105
+ jQuery ( window ) . removeProp ( callbackName ) ;
106
+
107
+ // Otherwise restore preexisting value
108
+ } else {
109
+ window [ callbackName ] = overwritten ;
110
+ }
111
+
112
+ // Save back as free
113
+ if ( s [ callbackName ] ) {
114
+
115
+ // Make sure that re-using the options doesn't screw things around
116
+ s . jsonpCallback = originalSettings . jsonpCallback ;
117
+
118
+ // Save the callback name for future use
119
+ oldCallbacks . push ( callbackName ) ;
120
+ }
121
+
122
+ // Call if it was a function and we have a response
123
+ if ( responseContainer && typeof overwritten === "function" ) {
124
+ overwritten ( responseContainer [ 0 ] ) ;
125
+ }
126
+
127
+ responseContainer = overwritten = undefined ;
128
+ } ) ;
129
+
130
+ // Delegate to script
131
+ return "script" ;
132
+ }
133
+ } ) ;
134
+ } else {
135
+
136
+ // jQuery <4 already contains this prefixer; don't duplicate the whole logic,
137
+ // but only enough to know when to warn.
34
138
jQuery . ajaxPrefilter ( "+json" , function ( s ) {
35
139
140
+ if ( ! jQuery . migrateIsPatchEnabled ( "jsonp-promotion" ) ) {
141
+ return ;
142
+ }
143
+
36
144
// Warn if JSON-to-JSONP auto-promotion happens.
37
145
if ( s . jsonp !== false && ( rjsonp . test ( s . url ) ||
38
146
typeof s . data === "string" &&
@@ -45,4 +153,12 @@ if ( !jQueryVersionSince( "4.0.0" ) ) {
45
153
} ) ;
46
154
}
47
155
156
+
157
+ // Don't trigger the above logic in jQuery >=4 by default as the JSON-to-JSONP
158
+ // auto-promotion behavior is gone in jQuery 4.0 and as it has security implications,
159
+ // we don't want to restore the legacy behavior by default.
160
+ if ( jQueryVersionSince ( "4.0.0" ) ) {
161
+ jQuery . migrateDisablePatches ( "jsonp-promotion" ) ;
162
+ }
163
+
48
164
}
0 commit comments