Ajax: Don't treat array data as binary

PR gh-5197 started treating all non-string non-plain-object
`data` values as binary. However, `jQuery.ajax` also supports
arrays as values of `data`. This change makes regular arrays
no longer be considered binary data.

Surprisingly, we had no tests for array `data` values; otherwise,
we'd detect the issue earlier. This change also adds
a few such missing tests.

Closes gh-5203
Ref gh-5197
This commit is contained in:
Michał Gołębiowski-Owczarek 2023-03-21 00:36:00 +01:00 committed by GitHub
parent e77bd9d64f
commit 992a1911d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 202 additions and 67 deletions

View File

@ -6,6 +6,7 @@ jQuery.ajaxPrefilter( function( s, origOptions ) {
// Binary data needs to be passed to XHR as-is without stringification.
if ( typeof s.data !== "string" && !jQuery.isPlainObject( s.data ) &&
!Array.isArray( s.data ) &&
// Don't disable data processing if explicitly set by the user.
!( "processData" in origOptions ) ) {

View File

@ -397,7 +397,7 @@ QUnit.module( "ajax", {
};
} );
ajaxTest( "jQuery.ajax() - URL fragment component preservation", 4, function( assert ) {
ajaxTest( "jQuery.ajax() - URL fragment component preservation", 5, function( assert ) {
return [
{
url: baseURL + "name.html#foo",
@ -429,6 +429,25 @@ QUnit.module( "ajax", {
},
error: true
},
{
url: baseURL + "name.html?abc#foo",
data: [
{
name: "test",
value: 123
},
{
name: "devo",
value: "hat"
}
],
beforeSend: function( xhr, settings ) {
assert.equal( settings.url, baseURL + "name.html?abc&test=123&devo=hat#foo",
"hash preserved for request with query component and array data." );
return false;
},
error: true
},
{
url: baseURL + "name.html?abc#brownies",
data: {
@ -1489,43 +1508,92 @@ QUnit.module( "ajax", {
};
} );
ajaxTest( "jQuery.ajax() - JSON by content-type", 5, function( assert ) {
return {
url: baseURL + "mock.php?action=json",
data: {
"header": "json",
"array": "1"
ajaxTest( "jQuery.ajax() - JSON by content-type", 10, function( assert ) {
return [
{
url: baseURL + "mock.php?action=json",
data: {
"header": "json",
"array": "1"
},
success: function( json ) {
assert.ok( json.length >= 2, "Check length" );
assert.strictEqual( json[ 0 ][ "name" ], "John", "Check JSON: first, name" );
assert.strictEqual( json[ 0 ][ "age" ], 21, "Check JSON: first, age" );
assert.strictEqual( json[ 1 ][ "name" ], "Peter", "Check JSON: second, name" );
assert.strictEqual( json[ 1 ][ "age" ], 25, "Check JSON: second, age" );
}
},
success: function( json ) {
assert.ok( json.length >= 2, "Check length" );
assert.strictEqual( json[ 0 ][ "name" ], "John", "Check JSON: first, name" );
assert.strictEqual( json[ 0 ][ "age" ], 21, "Check JSON: first, age" );
assert.strictEqual( json[ 1 ][ "name" ], "Peter", "Check JSON: second, name" );
assert.strictEqual( json[ 1 ][ "age" ], 25, "Check JSON: second, age" );
{
url: baseURL + "mock.php?action=json",
data: [
{
name: "header",
value: "json"
},
{
name: "array",
value: "1"
}
],
success: function( json ) {
assert.ok( json.length >= 2, "Check length" );
assert.strictEqual( json[ 0 ][ "name" ], "John", "Check JSON: first, name" );
assert.strictEqual( json[ 0 ][ "age" ], 21, "Check JSON: first, age" );
assert.strictEqual( json[ 1 ][ "name" ], "Peter", "Check JSON: second, name" );
assert.strictEqual( json[ 1 ][ "age" ], 25, "Check JSON: second, age" );
}
}
};
];
} );
ajaxTest( "jQuery.ajax() - JSON by content-type disabled with options", 6, function( assert ) {
return {
url: url( "mock.php?action=json" ),
data: {
"header": "json",
"array": "1"
ajaxTest( "jQuery.ajax() - JSON by content-type disabled with options", 12, function( assert ) {
return [
{
url: url( "mock.php?action=json" ),
data: {
"header": "json",
"array": "1"
},
contents: {
"json": false
},
success: function( text ) {
assert.strictEqual( typeof text, "string", "json wasn't auto-determined" );
var json = JSON.parse( text );
assert.ok( json.length >= 2, "Check length" );
assert.strictEqual( json[ 0 ][ "name" ], "John", "Check JSON: first, name" );
assert.strictEqual( json[ 0 ][ "age" ], 21, "Check JSON: first, age" );
assert.strictEqual( json[ 1 ][ "name" ], "Peter", "Check JSON: second, name" );
assert.strictEqual( json[ 1 ][ "age" ], 25, "Check JSON: second, age" );
}
},
contents: {
"json": false
},
success: function( text ) {
assert.strictEqual( typeof text, "string", "json wasn't auto-determined" );
var json = JSON.parse( text );
assert.ok( json.length >= 2, "Check length" );
assert.strictEqual( json[ 0 ][ "name" ], "John", "Check JSON: first, name" );
assert.strictEqual( json[ 0 ][ "age" ], 21, "Check JSON: first, age" );
assert.strictEqual( json[ 1 ][ "name" ], "Peter", "Check JSON: second, name" );
assert.strictEqual( json[ 1 ][ "age" ], 25, "Check JSON: second, age" );
{
url: url( "mock.php?action=json" ),
data: [
{
name: "header",
value: "json"
},
{
name: "array",
value: "1"
}
],
contents: {
"json": false
},
success: function( text ) {
assert.strictEqual( typeof text, "string", "json wasn't auto-determined" );
var json = JSON.parse( text );
assert.ok( json.length >= 2, "Check length" );
assert.strictEqual( json[ 0 ][ "name" ], "John", "Check JSON: first, name" );
assert.strictEqual( json[ 0 ][ "age" ], 21, "Check JSON: first, age" );
assert.strictEqual( json[ 1 ][ "name" ], "Peter", "Check JSON: second, name" );
assert.strictEqual( json[ 1 ][ "age" ], 25, "Check JSON: second, age" );
}
}
};
];
} );
ajaxTest( "jQuery.ajax() - simple get", 1, function( assert ) {
@ -1573,18 +1641,36 @@ QUnit.module( "ajax", {
};
} );
ajaxTest( "jQuery.ajax() - data - text/plain (gh-2658)", 1, function( assert ) {
return {
url: "bogus.html",
data: { devo: "A Beautiful World" },
type: "post",
contentType: "text/plain",
beforeSend: function( _, s ) {
assert.strictEqual( s.data, "devo=A%20Beautiful%20World", "data is %20-encoded" );
return false;
ajaxTest( "jQuery.ajax() - data - text/plain (gh-2658)", 2, function( assert ) {
return [
{
url: "bogus.html",
data: { devo: "A Beautiful World" },
type: "post",
contentType: "text/plain",
beforeSend: function( _, s ) {
assert.strictEqual( s.data, "devo=A%20Beautiful%20World", "data is %20-encoded" );
return false;
},
error: true
},
error: true
};
{
url: "bogus.html",
data: [
{
name: "devo",
value: "A Beautiful World"
}
],
type: "post",
contentType: "text/plain",
beforeSend: function( _, s ) {
assert.strictEqual( s.data, "devo=A%20Beautiful%20World", "data is %20-encoded" );
return false;
},
error: true
}
];
} );
ajaxTest( "jQuery.ajax() - don't escape %20 with contentType override (gh-4119)", 1, function( assert ) {
@ -1633,34 +1719,82 @@ QUnit.module( "ajax", {
};
} );
ajaxTest( "jQuery.ajax() - data - no processing POST", 1, function( assert ) {
return {
url: "bogus.html",
data: { devo: "A Beautiful World" },
type: "post",
contentType: "x-special-sauce",
processData: false,
beforeSend: function( _, s ) {
assert.deepEqual( s.data, { devo: "A Beautiful World" }, "data is not processed" );
return false;
ajaxTest( "jQuery.ajax() - data - no processing POST", 2, function( assert ) {
return [
{
url: "bogus.html",
data: { devo: "A Beautiful World" },
type: "post",
contentType: "x-special-sauce",
processData: false,
beforeSend: function( _, s ) {
assert.deepEqual( s.data, { devo: "A Beautiful World" }, "data is not processed" );
return false;
},
error: true
},
error: true
};
{
url: "bogus.html",
data: [
{
name: "devo",
value: "A Beautiful World"
}
],
type: "post",
contentType: "x-special-sauce",
processData: false,
beforeSend: function( _, s ) {
assert.deepEqual( s.data, [
{
name: "devo",
value: "A Beautiful World"
}
], "data is not processed" );
return false;
},
error: true
}
];
} );
ajaxTest( "jQuery.ajax() - data - no processing GET", 1, function( assert ) {
return {
url: "bogus.html",
data: { devo: "A Beautiful World" },
type: "get",
contentType: "x-something-else",
processData: false,
beforeSend: function( _, s ) {
assert.deepEqual( s.data, { devo: "A Beautiful World" }, "data is not processed" );
return false;
ajaxTest( "jQuery.ajax() - data - no processing GET", 2, function( assert ) {
return [
{
url: "bogus.html",
data: { devo: "A Beautiful World" },
type: "get",
contentType: "x-something-else",
processData: false,
beforeSend: function( _, s ) {
assert.deepEqual( s.data, { devo: "A Beautiful World" }, "data is not processed" );
return false;
},
error: true
},
error: true
};
{
url: "bogus.html",
data: [
{
name: "devo",
value: "A Beautiful World"
}
],
type: "get",
contentType: "x-something-else",
processData: false,
beforeSend: function( _, s ) {
assert.deepEqual( s.data, [
{
name: "devo",
value: "A Beautiful World"
}
], "data is not processed" );
return false;
},
error: true
}
];
} );
ajaxTest( "jQuery.ajax() - data - process string with GET", 2, function( assert ) {