Skip to content
Permalink
Browse files

Auto merge of #23033 - Manishearth:xhr-copies, r=jdm,emilio

Stop cloning response text on every chunk in XHR

r? @jdm

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/23033)
<!-- Reviewable:end -->
  • Loading branch information...
bors-servo committed Mar 14, 2019
2 parents 85ed181 + 79a5659 commit 7f85ff45155874331582693a621d65d3e5d229c1
Showing with 26 additions and 14 deletions.
  1. +26 −14 components/script/dom/xmlhttprequest.rs
@@ -70,6 +70,7 @@ use servo_atoms::Atom;
use servo_url::ServoUrl;
use std::borrow::ToOwned;
use std::cell::Cell;
use std::cmp;
use std::default::Default;
use std::ptr;
use std::ptr::NonNull;
@@ -95,7 +96,6 @@ pub struct GenerationId(u32);
struct XHRContext {
xhr: TrustedXHRAddress,
gen_id: GenerationId,
buf: DomRefCell<Vec<u8>>,
sync_status: DomRefCell<Option<ErrorResult>>,
resource_timing: ResourceFetchTiming,
}
@@ -105,7 +105,7 @@ pub enum XHRProgress {
/// Notify that headers have been received
HeadersReceived(GenerationId, Option<HeaderMap>, Option<(u16, Vec<u8>)>),
/// Partial progress (after receiving headers), containing portion of the response
Loading(GenerationId, ByteString),
Loading(GenerationId, Vec<u8>),
/// Loading is done
Done(GenerationId),
/// There was an error (only Error::Abort, Error::Timeout or Error::Network is used)
@@ -133,7 +133,7 @@ pub struct XMLHttpRequest {
response_url: DomRefCell<String>,
status: Cell<u16>,
status_text: DomRefCell<ByteString>,
response: DomRefCell<ByteString>,
response: DomRefCell<Vec<u8>>,
response_type: Cell<XMLHttpRequestResponseType>,
response_xml: MutNullableDom<Document>,
response_blob: MutNullableDom<Blob>,
@@ -185,7 +185,7 @@ impl XMLHttpRequest {
response_url: DomRefCell::new(String::new()),
status: Cell::new(0),
status_text: DomRefCell::new(ByteString::new(vec![])),
response: DomRefCell::new(ByteString::new(vec![])),
response: DomRefCell::new(vec![]),
response_type: Cell::new(XMLHttpRequestResponseType::_empty),
response_xml: Default::default(),
response_blob: Default::default(),
@@ -253,11 +253,8 @@ impl XMLHttpRequest {
}
}

fn process_response_chunk(&mut self, mut chunk: Vec<u8>) {
self.buf.borrow_mut().append(&mut chunk);
self.xhr
.root()
.process_data_available(self.gen_id, self.buf.borrow().clone());
fn process_response_chunk(&mut self, chunk: Vec<u8>) {
self.xhr.root().process_data_available(self.gen_id, chunk);
}

fn process_response_eof(
@@ -1008,7 +1005,7 @@ impl XMLHttpRequest {
}

fn process_data_available(&self, gen_id: GenerationId, payload: Vec<u8>) {
self.process_partial_response(XHRProgress::Loading(gen_id, ByteString::new(payload)));
self.process_partial_response(XHRProgress::Loading(gen_id, payload));
}

fn process_response_complete(
@@ -1077,18 +1074,34 @@ impl XMLHttpRequest {
headers
.as_ref()
.map(|h| *self.response_headers.borrow_mut() = h.clone());

{
let len = headers.and_then(|h| h.typed_get::<ContentLength>());
let mut response = self.response.borrow_mut();
response.clear();
if let Some(len) = len {
// don't attempt to prereserve more than 4 MB of memory,
// to avoid giving servers the ability to DOS the client by
// providing arbitrarily large content-lengths.
//
// this number is arbitrary, it's basically big enough that most
// XHR requests won't hit it, but not so big that it allows for DOS
let size = cmp::min(0b100_0000000000_0000000000, len.0 as usize);

// preallocate the buffer
response.reserve(size);
}
}
// Substep 3
if !self.sync.get() {
self.change_ready_state(XMLHttpRequestState::HeadersReceived);
}
},
XHRProgress::Loading(_, partial_response) => {
XHRProgress::Loading(_, mut partial_response) => {
// For synchronous requests, this should not fire any events, and just store data
// Part of step 11, send() (processing response body)
// XXXManishearth handle errors, if any (substep 2)

*self.response.borrow_mut() = partial_response;
self.response.borrow_mut().append(&mut partial_response);
if !self.sync.get() {
if self.ready_state.get() == XMLHttpRequestState::HeadersReceived {
self.ready_state.set(XMLHttpRequestState::Loading);
@@ -1451,7 +1464,6 @@ impl XMLHttpRequest {
let context = Arc::new(Mutex::new(XHRContext {
xhr: xhr,
gen_id: self.generation_id.get(),
buf: DomRefCell::new(vec![]),
sync_status: DomRefCell::new(None),
resource_timing: ResourceFetchTiming::new(ResourceTimingType::Resource),
}));

1 comment on commit 7f85ff4

@taskcluster

This comment has been minimized.

Copy link

taskcluster bot commented on 7f85ff4 Mar 14, 2019

Submitting the task to Taskcluster failed. Details

InterpreterError at template.tasks[0]: object keys must be strings

Please sign in to comment.
You can’t perform that action at this time.