mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Bug 658683: Make xhr.response not create a new ArrayBuffer every time it is accessed. r=sicking. Additional fixes by sicking, r=peterv
This commit is contained in:
parent
8e10a6f050
commit
a19b1cf42c
@ -426,7 +426,8 @@ nsXMLHttpRequest::nsXMLHttpRequest()
|
|||||||
mErrorLoad(PR_FALSE), mTimerIsActive(PR_FALSE),
|
mErrorLoad(PR_FALSE), mTimerIsActive(PR_FALSE),
|
||||||
mProgressEventWasDelayed(PR_FALSE),
|
mProgressEventWasDelayed(PR_FALSE),
|
||||||
mLoadLengthComputable(PR_FALSE), mLoadTotal(0),
|
mLoadLengthComputable(PR_FALSE), mLoadTotal(0),
|
||||||
mFirstStartRequestSeen(PR_FALSE)
|
mFirstStartRequestSeen(PR_FALSE),
|
||||||
|
mResultArrayBuffer(nsnull)
|
||||||
{
|
{
|
||||||
mResponseBodyUnicode.SetIsVoid(PR_TRUE);
|
mResponseBodyUnicode.SetIsVoid(PR_TRUE);
|
||||||
nsLayoutStatics::AddRef();
|
nsLayoutStatics::AddRef();
|
||||||
@ -450,6 +451,12 @@ nsXMLHttpRequest::~nsXMLHttpRequest()
|
|||||||
nsLayoutStatics::Release();
|
nsLayoutStatics::Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXMLHttpRequest::RootResultArrayBuffer()
|
||||||
|
{
|
||||||
|
nsContentUtils::PreserveWrapper(static_cast<nsPIDOMEventTarget*>(this), this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This Init method is called from the factory constructor.
|
* This Init method is called from the factory constructor.
|
||||||
*/
|
*/
|
||||||
@ -572,9 +579,9 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLHttpRequest,
|
|||||||
nsIXMLHttpRequestUpload)
|
nsIXMLHttpRequestUpload)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||||
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXMLHttpRequest,
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXMLHttpRequest,
|
||||||
nsXHREventTarget)
|
nsXHREventTarget)
|
||||||
|
tmp->mResultArrayBuffer = nsnull;
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContext)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContext)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChannel)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChannel)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mReadRequest)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mReadRequest)
|
||||||
@ -592,6 +599,14 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXMLHttpRequest,
|
|||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mUpload)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mUpload)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(nsXMLHttpRequest,
|
||||||
|
nsXHREventTarget)
|
||||||
|
if(tmp->mResultArrayBuffer) {
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(tmp->mResultArrayBuffer,
|
||||||
|
"mResultArrayBuffer")
|
||||||
|
}
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||||
|
|
||||||
DOMCI_DATA(XMLHttpRequest, nsXMLHttpRequest)
|
DOMCI_DATA(XMLHttpRequest, nsXMLHttpRequest)
|
||||||
|
|
||||||
// QueryInterface implementation for nsXMLHttpRequest
|
// QueryInterface implementation for nsXMLHttpRequest
|
||||||
@ -839,27 +854,20 @@ NS_IMETHODIMP nsXMLHttpRequest::GetResponseText(nsAString& aResponseText)
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult nsXMLHttpRequest::GetResponseArrayBuffer(jsval *aResult)
|
nsresult nsXMLHttpRequest::CreateResponseArrayBuffer(JSContext *aCx)
|
||||||
{
|
{
|
||||||
JSContext *cx = nsContentUtils::GetCurrentJSContext();
|
if (!aCx)
|
||||||
if (!cx)
|
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
if (!(mState & (XML_HTTP_REQUEST_DONE |
|
|
||||||
XML_HTTP_REQUEST_LOADING))) {
|
|
||||||
*aResult = JSVAL_NULL;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRInt32 dataLen = mResponseBody.Length();
|
PRInt32 dataLen = mResponseBody.Length();
|
||||||
JSObject *obj = js_CreateArrayBuffer(cx, dataLen);
|
RootResultArrayBuffer();
|
||||||
if (!obj)
|
mResultArrayBuffer = js_CreateArrayBuffer(aCx, dataLen);
|
||||||
|
if (!mResultArrayBuffer) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
*aResult = OBJECT_TO_JSVAL(obj);
|
|
||||||
|
|
||||||
if (dataLen > 0) {
|
if (dataLen > 0) {
|
||||||
js::ArrayBuffer *abuf = js::ArrayBuffer::fromJSObject(obj);
|
js::ArrayBuffer *abuf = js::ArrayBuffer::fromJSObject(mResultArrayBuffer);
|
||||||
NS_ASSERTION(abuf, "What happened?");
|
NS_ASSERTION(abuf, "What happened?");
|
||||||
memcpy(abuf->data, mResponseBody.BeginReading(), dataLen);
|
memcpy(abuf->data, mResponseBody.BeginReading(), dataLen);
|
||||||
}
|
}
|
||||||
@ -954,7 +962,11 @@ NS_IMETHODIMP nsXMLHttpRequest::GetResponse(JSContext *aCx, jsval *aResult)
|
|||||||
|
|
||||||
case XML_HTTP_RESPONSE_TYPE_ARRAYBUFFER:
|
case XML_HTTP_RESPONSE_TYPE_ARRAYBUFFER:
|
||||||
if (mState & XML_HTTP_REQUEST_DONE) {
|
if (mState & XML_HTTP_REQUEST_DONE) {
|
||||||
rv = GetResponseArrayBuffer(aResult);
|
if (!mResultArrayBuffer) {
|
||||||
|
rv = CreateResponseArrayBuffer(aCx);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
}
|
||||||
|
*aResult = OBJECT_TO_JSVAL(mResultArrayBuffer);
|
||||||
} else {
|
} else {
|
||||||
*aResult = JSVAL_NULL;
|
*aResult = JSVAL_NULL;
|
||||||
}
|
}
|
||||||
@ -1073,6 +1085,7 @@ nsXMLHttpRequest::Abort()
|
|||||||
mResponseBodyUnicode.SetIsVoid(PR_TRUE);
|
mResponseBodyUnicode.SetIsVoid(PR_TRUE);
|
||||||
mResponseBlob = nsnull;
|
mResponseBlob = nsnull;
|
||||||
mState |= XML_HTTP_REQUEST_ABORTED;
|
mState |= XML_HTTP_REQUEST_ABORTED;
|
||||||
|
mResultArrayBuffer = nsnull;
|
||||||
|
|
||||||
if (!(mState & (XML_HTTP_REQUEST_UNSENT |
|
if (!(mState & (XML_HTTP_REQUEST_UNSENT |
|
||||||
XML_HTTP_REQUEST_OPENED |
|
XML_HTTP_REQUEST_OPENED |
|
||||||
|
@ -208,10 +208,10 @@ public:
|
|||||||
|
|
||||||
void SetRequestObserver(nsIRequestObserver* aObserver);
|
void SetRequestObserver(nsIRequestObserver* aObserver);
|
||||||
|
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXMLHttpRequest,
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(nsXMLHttpRequest,
|
||||||
nsXHREventTarget)
|
nsXHREventTarget)
|
||||||
|
|
||||||
PRBool AllowUploadProgress();
|
PRBool AllowUploadProgress();
|
||||||
|
void RootResultArrayBuffer();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class nsMultipartProxyListener;
|
friend class nsMultipartProxyListener;
|
||||||
@ -224,7 +224,7 @@ protected:
|
|||||||
PRUint32 toOffset,
|
PRUint32 toOffset,
|
||||||
PRUint32 count,
|
PRUint32 count,
|
||||||
PRUint32 *writeCount);
|
PRUint32 *writeCount);
|
||||||
nsresult GetResponseArrayBuffer(jsval *aResult);
|
nsresult CreateResponseArrayBuffer(JSContext* aCx);
|
||||||
void CreateResponseBlob(nsIRequest *request);
|
void CreateResponseBlob(nsIRequest *request);
|
||||||
// Change the state of the object with this. The broadcast argument
|
// Change the state of the object with this. The broadcast argument
|
||||||
// determines if the onreadystatechange listener should be called.
|
// determines if the onreadystatechange listener should be called.
|
||||||
@ -345,6 +345,8 @@ protected:
|
|||||||
|
|
||||||
nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
|
nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
|
||||||
nsCOMPtr<nsIChannel> mNewRedirectChannel;
|
nsCOMPtr<nsIChannel> mNewRedirectChannel;
|
||||||
|
|
||||||
|
JSObject* mResultArrayBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
// helper class to expose a progress DOM Event
|
// helper class to expose a progress DOM Event
|
||||||
|
@ -134,6 +134,16 @@ ab = xhr.response;
|
|||||||
ok(ab != null, "should have a non-null arraybuffer");
|
ok(ab != null, "should have a non-null arraybuffer");
|
||||||
arraybuffer_equals_to(ab, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb");
|
arraybuffer_equals_to(ab, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb");
|
||||||
|
|
||||||
|
// test array buffer GetResult returns the same object
|
||||||
|
xhr = new XMLHttpRequest();
|
||||||
|
xhr.open("GET", 'file_XHR_binary1.bin', false);
|
||||||
|
xhr.responseType = 'arraybuffer';
|
||||||
|
xhr.send(null)
|
||||||
|
is(xhr.status, 200, "wrong status");
|
||||||
|
checkResponseTextAccessThrows(xhr);
|
||||||
|
checkResponseXMLAccessThrows(xhr);
|
||||||
|
is(xhr.response, xhr.response, "returns the same ArrayBuffer");
|
||||||
|
|
||||||
// test response (responseType='blob')
|
// test response (responseType='blob')
|
||||||
var onloadCount = 0;
|
var onloadCount = 0;
|
||||||
function checkOnloadCount() {
|
function checkOnloadCount() {
|
||||||
|
@ -436,6 +436,20 @@ public:
|
|||||||
"not the nsISupports pointer we expect"); \
|
"not the nsISupports pointer we expect"); \
|
||||||
_class *tmp = Downcast(s);
|
_class *tmp = Downcast(s);
|
||||||
|
|
||||||
|
#define NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(_class, _base_class) \
|
||||||
|
void \
|
||||||
|
NS_CYCLE_COLLECTION_CLASSNAME(_class)::Trace(void *p, \
|
||||||
|
TraceCallback aCallback, \
|
||||||
|
void *aClosure) \
|
||||||
|
{ \
|
||||||
|
nsISupports *s = static_cast<nsISupports*>(p); \
|
||||||
|
NS_ASSERTION(CheckForRightISupports(s), \
|
||||||
|
"not the nsISupports pointer we expect"); \
|
||||||
|
_class *tmp = static_cast<_class*>(Downcast(s)); \
|
||||||
|
NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Trace(s, \
|
||||||
|
aCallback, \
|
||||||
|
aClosure);
|
||||||
|
|
||||||
#define NS_IMPL_CYCLE_COLLECTION_TRACE_NATIVE_BEGIN(_class) \
|
#define NS_IMPL_CYCLE_COLLECTION_TRACE_NATIVE_BEGIN(_class) \
|
||||||
void \
|
void \
|
||||||
NS_CYCLE_COLLECTION_CLASSNAME(_class)::Trace(void *p, \
|
NS_CYCLE_COLLECTION_CLASSNAME(_class)::Trace(void *p, \
|
||||||
|
Loading…
Reference in New Issue
Block a user