Skip to content

Commit e6a99fd

Browse files
committed
Fixes #9887: ajax now supports circular references into objects passed as context. Prefilter and transport developpers should add their own custom option into flatOptions when needed. Unit test added.
1 parent 28b470d commit e6a99fd

File tree

2 files changed

+50
-16
lines changed

2 files changed

+50
-16
lines changed

src/ajax.js

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,22 @@ function inspectPrefiltersOrTransports( structure, options, originalOptions, jqX
135135
return selection;
136136
}
137137

138+
// A special extend for ajax options
139+
// that takes "flat" options (not to be deep extended)
140+
// Fixes #9887
141+
function ajaxExtend( target, src ) {
142+
var key, deep,
143+
flatOptions = jQuery.ajaxSettings.flatOptions || {};
144+
for( key in src ) {
145+
if ( src[ key ] !== undefined ) {
146+
( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
147+
}
148+
}
149+
if ( deep ) {
150+
jQuery.extend( true, target, deep );
151+
}
152+
}
153+
138154
jQuery.fn.extend({
139155
load: function( url, params, callback ) {
140156
if ( typeof url !== "string" && _load ) {
@@ -278,23 +294,16 @@ jQuery.extend({
278294
// Creates a full fledged settings object into target
279295
// with both ajaxSettings and settings fields.
280296
// If target is omitted, writes into ajaxSettings.
281-
ajaxSetup: function ( target, settings ) {
282-
if ( !settings ) {
283-
// Only one parameter, we extend ajaxSettings
284-
settings = target;
285-
target = jQuery.extend( true, jQuery.ajaxSettings, settings );
297+
ajaxSetup: function( target, settings ) {
298+
if ( settings ) {
299+
// Building a settings object
300+
ajaxExtend( target, jQuery.ajaxSettings );
286301
} else {
287-
// target was provided, we extend into it
288-
jQuery.extend( true, target, jQuery.ajaxSettings, settings );
289-
}
290-
// Flatten fields we don't want deep extended
291-
for( var field in { context: 1, url: 1 } ) {
292-
if ( field in settings ) {
293-
target[ field ] = settings[ field ];
294-
} else if( field in jQuery.ajaxSettings ) {
295-
target[ field ] = jQuery.ajaxSettings[ field ];
296-
}
302+
// Extending ajaxSettings
303+
settings = target;
304+
target = jQuery.ajaxSettings;
297305
}
306+
ajaxExtend( target, settings );
298307
return target;
299308
},
300309

@@ -352,6 +361,15 @@ jQuery.extend({
352361

353362
// Parse text as xml
354363
"text xml": jQuery.parseXML
364+
},
365+
366+
// For options that shouldn't be deep extended:
367+
// you can add your own custom options here if
368+
// and when you create one that shouldn't be
369+
// deep extended (see ajaxExtend)
370+
flatOptions: {
371+
context: true,
372+
url: true
355373
}
356374
},
357375

@@ -563,7 +581,7 @@ jQuery.extend({
563581
completeDeferred.resolveWith( callbackContext, [ jqXHR, statusText ] );
564582

565583
if ( fireGlobals ) {
566-
globalEventContext.trigger( "ajaxComplete", [ jqXHR, s] );
584+
globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
567585
// Handle the global AJAX counter
568586
if ( !( --jQuery.active ) ) {
569587
jQuery.event.trigger( "ajaxStop" );

test/unit/ajax.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2076,6 +2076,22 @@ test( "jQuery.ajax - Location object as url (#7531)", 1, function () {
20762076
ok( success, "document.location did not generate exception" );
20772077
});
20782078

2079+
test( "jQuery.ajax - Context with circular references (#9887)", 2, function () {
2080+
var success = false,
2081+
context = {};
2082+
context.field = context;
2083+
try {
2084+
success = !jQuery.ajax( "non-existing", {
2085+
context: context,
2086+
beforeSend: function() {
2087+
ok( this === context, "context was not deep extended" );
2088+
return false;
2089+
}
2090+
});
2091+
} catch (e) { console.log( e ); }
2092+
ok( success, "context with circular reference did not generate an exception" );
2093+
});
2094+
20792095
test( "jQuery.ajax - statusCode" , function() {
20802096

20812097
var count = 12;

0 commit comments

Comments
 (0)