зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1411384 - nested sync XHR should throw, r=smaug
This commit is contained in:
Родитель
44cf6e38a4
Коммит
209fb327a0
|
@ -173,6 +173,18 @@ static void AddLoadFlags(nsIRequest *request, nsLoadFlags newFlags)
|
|||
request->SetLoadFlags(flags);
|
||||
}
|
||||
|
||||
// We are in a sync event loop.
|
||||
#define NOT_CALLABLE_IN_SYNC_SEND \
|
||||
if (mFlagSyncLooping) { \
|
||||
return NS_ERROR_DOM_INVALID_STATE_XHR_HAS_INVALID_CONTEXT; \
|
||||
}
|
||||
|
||||
#define NOT_CALLABLE_IN_SYNC_SEND_RV \
|
||||
if (mFlagSyncLooping) { \
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_XHR_HAS_INVALID_CONTEXT); \
|
||||
return; \
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
|
@ -699,6 +711,8 @@ void
|
|||
XMLHttpRequestMainThread::SetResponseType(XMLHttpRequestResponseType aResponseType,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
NOT_CALLABLE_IN_SYNC_SEND_RV
|
||||
|
||||
if (mState == State::loading || mState == State::done) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_XHR_MUST_NOT_BE_LOADING_OR_DONE);
|
||||
return;
|
||||
|
@ -1092,6 +1106,13 @@ XMLHttpRequestMainThread::RequestErrorSteps(const ProgressEventType aEventType,
|
|||
|
||||
void
|
||||
XMLHttpRequestMainThread::Abort(ErrorResult& aRv)
|
||||
{
|
||||
NOT_CALLABLE_IN_SYNC_SEND_RV
|
||||
AbortInternal(aRv);
|
||||
}
|
||||
|
||||
void
|
||||
XMLHttpRequestMainThread::AbortInternal(ErrorResult& aRv)
|
||||
{
|
||||
mFlagAborted = true;
|
||||
|
||||
|
@ -1189,6 +1210,8 @@ void
|
|||
XMLHttpRequestMainThread::GetAllResponseHeaders(nsACString& aResponseHeaders,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
NOT_CALLABLE_IN_SYNC_SEND_RV
|
||||
|
||||
aResponseHeaders.Truncate();
|
||||
|
||||
// If the state is UNSENT or OPENED,
|
||||
|
@ -1254,6 +1277,8 @@ void
|
|||
XMLHttpRequestMainThread::GetResponseHeader(const nsACString& header,
|
||||
nsACString& _retval, ErrorResult& aRv)
|
||||
{
|
||||
NOT_CALLABLE_IN_SYNC_SEND_RV
|
||||
|
||||
_retval.SetIsVoid(true);
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = GetCurrentHttpChannel();
|
||||
|
@ -1515,7 +1540,10 @@ XMLHttpRequestMainThread::Open(const nsACString& aMethod,
|
|||
const nsACString& aUrl,
|
||||
bool aAsync,
|
||||
const nsAString& aUsername,
|
||||
const nsAString& aPassword) {
|
||||
const nsAString& aPassword)
|
||||
{
|
||||
NOT_CALLABLE_IN_SYNC_SEND
|
||||
|
||||
// Gecko-specific
|
||||
if (!aAsync && !DontWarnAboutSyncXHR() && GetOwner() &&
|
||||
GetOwner()->GetExtantDoc()) {
|
||||
|
@ -2861,6 +2889,8 @@ XMLHttpRequestMainThread::Send(JSContext* aCx,
|
|||
const Nullable<DocumentOrBlobOrArrayBufferViewOrArrayBufferOrFormDataOrURLSearchParamsOrUSVString>& aData,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
NOT_CALLABLE_IN_SYNC_SEND_RV
|
||||
|
||||
if (aData.IsNull()) {
|
||||
aRv = SendInternal(nullptr);
|
||||
return;
|
||||
|
@ -3156,6 +3186,8 @@ NS_IMETHODIMP
|
|||
XMLHttpRequestMainThread::SetRequestHeader(const nsACString& aName,
|
||||
const nsACString& aValue)
|
||||
{
|
||||
NOT_CALLABLE_IN_SYNC_SEND
|
||||
|
||||
// Step 1
|
||||
if (mState != State::opened) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_XHR_MUST_BE_OPENED;
|
||||
|
@ -3219,6 +3251,8 @@ XMLHttpRequestMainThread::SetTimeout(uint32_t aTimeout)
|
|||
void
|
||||
XMLHttpRequestMainThread::SetTimeout(uint32_t aTimeout, ErrorResult& aRv)
|
||||
{
|
||||
NOT_CALLABLE_IN_SYNC_SEND_RV
|
||||
|
||||
if (mFlagSynchronous && mState != State::unsent && HasOrHasHadOwner()) {
|
||||
/* Timeout is not supported for synchronous requests with an owning window,
|
||||
per XHR2 spec. */
|
||||
|
@ -3314,8 +3348,12 @@ XMLHttpRequestMainThread::ReadyState() const
|
|||
return 0;
|
||||
}
|
||||
|
||||
void XMLHttpRequestMainThread::OverrideMimeType(const nsAString& aMimeType, ErrorResult& aRv)
|
||||
void
|
||||
XMLHttpRequestMainThread::OverrideMimeType(const nsAString& aMimeType,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
NOT_CALLABLE_IN_SYNC_SEND_RV
|
||||
|
||||
if (mState == State::loading || mState == State::done) {
|
||||
ResetResponse();
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_XHR_MUST_NOT_BE_LOADING_OR_DONE);
|
||||
|
@ -3395,6 +3433,8 @@ XMLHttpRequestMainThread::SetWithCredentials(bool aWithCredentials)
|
|||
void
|
||||
XMLHttpRequestMainThread::SetWithCredentials(bool aWithCredentials, ErrorResult& aRv)
|
||||
{
|
||||
NOT_CALLABLE_IN_SYNC_SEND_RV
|
||||
|
||||
// Return error if we're already processing a request. Note that we can't use
|
||||
// ReadyState() here, because it can't differentiate between "opened" and
|
||||
// "sent", so we use mState directly.
|
||||
|
|
|
@ -352,8 +352,8 @@ public:
|
|||
void
|
||||
Abort()
|
||||
{
|
||||
ErrorResult rv;
|
||||
Abort(rv);
|
||||
IgnoredErrorResult rv;
|
||||
AbortInternal(rv);
|
||||
MOZ_ASSERT(!rv.Failed());
|
||||
}
|
||||
|
||||
|
@ -563,6 +563,9 @@ protected:
|
|||
void SuspendEventDispatching();
|
||||
void ResumeEventDispatching();
|
||||
|
||||
void
|
||||
AbortInternal(ErrorResult& aRv);
|
||||
|
||||
struct PendingEvent
|
||||
{
|
||||
RefPtr<DOMEventTargetHelper> mTarget;
|
||||
|
|
|
@ -113,3 +113,4 @@ support-files = test_XHR_timeout.js
|
|||
[test_XHRResponseURL.html]
|
||||
[test_XHRSendData.html]
|
||||
[test_sync_xhr_document_write_with_iframe.html]
|
||||
[test_nestedSyncXHR.html]
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for sync XHR into sync XHRs</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript">
|
||||
|
||||
|
||||
let xhr = new XMLHttpRequest();
|
||||
let testCompleted = false;
|
||||
|
||||
let frame = document.createElement('frame');
|
||||
frame.addEventListener('load', function() {
|
||||
if (testCompleted) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
xhr.responseType = "blob";
|
||||
ok(false, "xhr.responseType cannot be settable");
|
||||
} catch(e) {
|
||||
ok(true, "xhr.responseType cannot be settable");
|
||||
}
|
||||
|
||||
try {
|
||||
xhr.abort();
|
||||
ok(false, "xhr.abort should throw");
|
||||
} catch(e) {
|
||||
ok(true, "xhr.abort should throw");
|
||||
}
|
||||
|
||||
try {
|
||||
xhr.getAllResponseHeaders();
|
||||
ok(false, "xhr.getAllResponseHeaders should throw");
|
||||
} catch(e) {
|
||||
ok(true, "xhr.getAllResponseHeaders should throw");
|
||||
}
|
||||
|
||||
try {
|
||||
xhr.getResponseHeader("foo");
|
||||
ok(false, "xhr.getResponseHeader should throw");
|
||||
} catch(e) {
|
||||
ok(true, "xhr.getResponseHeader should throw");
|
||||
}
|
||||
|
||||
try {
|
||||
xhr.open('POST', location, false);
|
||||
ok(false, "xhr.open should throw");
|
||||
} catch(e) {
|
||||
ok(true, "xhr.open should throw");
|
||||
}
|
||||
|
||||
try {
|
||||
xhr.send();
|
||||
ok(false, "xhr.send should throw");
|
||||
} catch(e) {
|
||||
ok(true, "xhr.send should throw");
|
||||
}
|
||||
|
||||
try {
|
||||
xhr.timeout = 42;
|
||||
ok(false, "xhr.timeout cannot be settable");
|
||||
} catch(e) {
|
||||
ok(true, "xhr.timeout cannot be settable");
|
||||
}
|
||||
|
||||
try {
|
||||
xhr.withCredentials = false;
|
||||
ok(false, "xhr.withCredentials cannot be settable");
|
||||
} catch(e) {
|
||||
ok(true, "xhr.withCredentials cannot be settable");
|
||||
}
|
||||
|
||||
try {
|
||||
xhr.overrideMimeType("wow")
|
||||
ok(false, "xhr.overrideMimeType should throw");
|
||||
} catch(e) {
|
||||
ok(true, "xhr.overrideMimeType should throw");
|
||||
}
|
||||
}, { once: true });
|
||||
|
||||
// This test is racy because we try to check that the loading of the frame
|
||||
// happens during a sync XHR. If the loading happens after, we still need to
|
||||
// consider the test passed.
|
||||
ok(xhr, "We have an XHR.");
|
||||
|
||||
document.documentElement.appendChild(frame);
|
||||
xhr.open('POST', location, false);
|
||||
xhr.send('X');
|
||||
|
||||
// Nothing can guarantee that the frame is loaded during the sync XHR.
|
||||
testCompleted = true;
|
||||
|
||||
frame.remove();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче