Introduce DOMTracker, cancel eventsource fetch when aborting document load

This commit is contained in:
Gregory Terzian 2018-07-01 20:30:05 +08:00
parent ff62ca7c01
commit f2ee941da2
6 changed files with 105 additions and 20 deletions

View file

@ -16,6 +16,7 @@ use dom::globalscope::GlobalScope;
use dom::messageevent::MessageEvent;
use dom_struct::dom_struct;
use euclid::Length;
use fetch::FetchCanceller;
use hyper::header::{Accept, qitem};
use ipc_channel::ipc;
use ipc_channel::router::ROUTER;
@ -64,6 +65,7 @@ pub struct EventSource {
ready_state: Cell<ReadyState>,
with_credentials: bool,
canceller: DomRefCell<FetchCanceller>,
}
enum ParserState {
@ -118,19 +120,7 @@ impl EventSourceContext {
if self.gen_id != event_source.generation_id.get() {
return;
}
let global = event_source.global();
let event_source = self.event_source.clone();
// FIXME(nox): Why are errors silenced here?
let _ = global.remote_event_task_source().queue(
task!(fail_the_event_source_connection: move || {
let event_source = event_source.root();
if event_source.ready_state.get() != ReadyState::Closed {
event_source.ready_state.set(ReadyState::Closed);
event_source.upcast::<EventTarget>().fire_event(atom!("error"));
}
}),
&global,
);
event_source.fail_the_connection();
}
// https://html.spec.whatwg.org/multipage/#reestablish-the-connection
@ -410,6 +400,7 @@ impl EventSource {
ready_state: Cell::new(ReadyState::Connecting),
with_credentials: with_credentials,
canceller: DomRefCell::new(Default::default())
}
}
@ -419,6 +410,29 @@ impl EventSource {
Wrap)
}
// https://html.spec.whatwg.org/multipage/#sse-processing-model:fail-the-connection-3
pub fn cancel(&self) {
self.canceller.borrow_mut().cancel();
self.fail_the_connection();
}
/// <https://html.spec.whatwg.org/multipage/#fail-the-connection>
pub fn fail_the_connection(&self) {
let global = self.global();
let event_source = Trusted::new(self);
// FIXME(nox): Why are errors silenced here?
let _ = global.remote_event_task_source().queue(
task!(fail_the_event_source_connection: move || {
let event_source = event_source.root();
if event_source.ready_state.get() != ReadyState::Closed {
event_source.ready_state.set(ReadyState::Closed);
event_source.upcast::<EventTarget>().fire_event(atom!("error"));
}
}),
&global,
);
}
pub fn request(&self) -> RequestInit {
self.request.borrow().clone().unwrap()
}
@ -437,6 +451,7 @@ impl EventSource {
};
// Step 1, 5
let ev = EventSource::new(global, url_record.clone(), event_source_init.withCredentials);
global.track_event_source(&ev);
// Steps 6-7
let cors_attribute_state = if event_source_init.withCredentials {
CorsSettings::UseCredentials
@ -491,13 +506,23 @@ impl EventSource {
ROUTER.add_route(action_receiver.to_opaque(), Box::new(move |message| {
listener.notify_fetch(message.to().unwrap());
}));
let cancel_receiver = ev.canceller.borrow_mut().initialize();
global.core_resource_thread().send(
CoreResourceMsg::Fetch(request, FetchChannels::ResponseMsg(action_sender, None))).unwrap();
CoreResourceMsg::Fetch(request, FetchChannels::ResponseMsg(action_sender, Some(cancel_receiver)))).unwrap();
// Step 13
Ok(ev)
}
}
// https://html.spec.whatwg.org/multipage/#garbage-collection-2
impl Drop for EventSource {
fn drop(&mut self) {
// If an EventSource object is garbage collected while its connection is still open,
// the user agent must abort any instance of the fetch algorithm opened by this EventSource.
self.canceller.borrow_mut().cancel();
}
}
impl EventSourceMethods for EventSource {
// https://html.spec.whatwg.org/multipage/#handler-eventsource-onopen
event_handler!(open, GetOnopen, SetOnopen);
@ -527,6 +552,7 @@ impl EventSourceMethods for EventSource {
fn Close(&self) {
let GenerationId(prev_id) = self.generation_id.get();
self.generation_id.set(GenerationId(prev_id + 1));
self.canceller.borrow_mut().cancel();
self.ready_state.set(ReadyState::Closed);
}
}