aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
Diffstat (limited to 'components/script')
-rw-r--r--components/script/Cargo.toml2
-rw-r--r--components/script/dom/bindings/trace.rs6
-rw-r--r--components/script/dom/bluetooth.rs12
-rw-r--r--components/script/dom/domparser.rs7
-rw-r--r--components/script/dom/element.rs2
-rw-r--r--components/script/dom/eventsource.rs486
-rw-r--r--components/script/dom/globalscope.rs5
-rw-r--r--components/script/dom/htmlimageelement.rs8
-rw-r--r--components/script/dom/htmlinputelement.rs17
-rw-r--r--components/script/dom/htmllinkelement.rs4
-rw-r--r--components/script/dom/htmlmediaelement.rs5
-rw-r--r--components/script/dom/htmlmetaelement.rs4
-rw-r--r--components/script/dom/htmlscriptelement.rs49
-rw-r--r--components/script/dom/node.rs4
-rw-r--r--components/script/dom/request.rs12
-rw-r--r--components/script/dom/servoparser/html.rs236
-rw-r--r--components/script/dom/servoparser/mod.rs196
-rw-r--r--components/script/dom/servoparser/xml.rs92
-rw-r--r--components/script/dom/webidls/CSSStyleDeclaration.webidl61
-rw-r--r--components/script/dom/webidls/EventSource.webidl3
-rw-r--r--components/script/dom/webidls/Navigator.webidl7
-rw-r--r--components/script/dom/websocket.rs38
-rw-r--r--components/script/dom/window.rs2
-rw-r--r--components/script/dom/workerglobalscope.rs5
-rw-r--r--components/script/dom/xmlhttprequest.rs46
-rw-r--r--components/script/fetch.rs9
-rw-r--r--components/script/lib.rs11
-rw-r--r--components/script/network_listener.rs10
-rw-r--r--components/script/script_thread.rs27
-rw-r--r--components/script/task_source/networking.rs31
-rw-r--r--components/script/textinput.rs1
-rw-r--r--components/script/timers.rs3
32 files changed, 964 insertions, 437 deletions
diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml
index 81bf9bde314..e096dae1347 100644
--- a/components/script/Cargo.toml
+++ b/components/script/Cargo.toml
@@ -37,7 +37,7 @@ fnv = "1.0"
gfx_traits = {path = "../gfx_traits"}
heapsize = "0.3.6"
heapsize_derive = "0.1"
-html5ever = {version = "0.9.0", features = ["heap_size", "unstable"]}
+html5ever = {version = "0.10.1", features = ["heap_size", "unstable"]}
html5ever-atoms = {version = "0.1", features = ["heap_size"]}
hyper = "0.9.9"
hyper_serde = "0.1.4"
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index b8274aec90c..b38d5d4ec91 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -46,6 +46,7 @@ use euclid::{Matrix2D, Matrix4D, Point2D};
use euclid::length::Length as EuclidLength;
use euclid::rect::Rect;
use euclid::size::Size2D;
+use html5ever::tokenizer::buffer_queue::BufferQueue;
use html5ever::tree_builder::QuirksMode;
use html5ever_atoms::{Prefix, LocalName, Namespace, QualName};
use hyper::header::Headers;
@@ -63,7 +64,7 @@ use net_traits::{Metadata, NetworkError, ReferrerPolicy, ResourceThreads};
use net_traits::filemanager_thread::RelativePos;
use net_traits::image::base::{Image, ImageMetadata};
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread};
-use net_traits::request::Request;
+use net_traits::request::{Request, RequestInit};
use net_traits::response::{Response, ResponseBody};
use net_traits::response::HttpsState;
use net_traits::storage_thread::StorageType;
@@ -322,7 +323,7 @@ no_jsmanaged_fields!(HashSet<T>);
no_jsmanaged_fields!(FrameId, FrameType, WindowSizeData, WindowSizeType, PipelineId);
no_jsmanaged_fields!(TimerEventId, TimerSource);
no_jsmanaged_fields!(WorkerId);
-no_jsmanaged_fields!(QuirksMode);
+no_jsmanaged_fields!(BufferQueue, QuirksMode);
no_jsmanaged_fields!(Runtime);
no_jsmanaged_fields!(Headers, Method);
no_jsmanaged_fields!(WindowProxyHandler);
@@ -349,6 +350,7 @@ no_jsmanaged_fields!(AttrValue);
no_jsmanaged_fields!(Snapshot);
no_jsmanaged_fields!(HttpsState);
no_jsmanaged_fields!(Request);
+no_jsmanaged_fields!(RequestInit);
no_jsmanaged_fields!(SharedRt);
no_jsmanaged_fields!(TouchpadPressurePhase);
no_jsmanaged_fields!(USVString);
diff --git a/components/script/dom/bluetooth.rs b/components/script/dom/bluetooth.rs
index 1f5fd15c49f..6125680d637 100644
--- a/components/script/dom/bluetooth.rs
+++ b/components/script/dom/bluetooth.rs
@@ -148,14 +148,14 @@ pub fn response_async<T: AsyncBluetoothListener + Reflectable + 'static>(
promise: &Rc<Promise>,
receiver: &T) -> IpcSender<BluetoothResponseResult> {
let (action_sender, action_receiver) = ipc::channel().unwrap();
- let chan = receiver.global().networking_task_source();
+ let task_source = receiver.global().networking_task_source();
let context = Arc::new(Mutex::new(BluetoothContext {
promise: Some(TrustedPromise::new(promise.clone())),
receiver: Trusted::new(receiver),
}));
let listener = NetworkListener {
context: context,
- script_chan: chan,
+ task_source: task_source,
wrapper: None,
};
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
@@ -194,7 +194,7 @@ fn convert_request_device_options(filters: &Option<Vec<BluetoothRequestDeviceFil
// Step 2.7.
// Note: What we are doing here is adding the not blacklisted UUIDs to the result vector,
- // insted of removing them from an already filled vector.
+ // instead of removing them from an already filled vector.
if !uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) {
optional_services_uuids.push(uuid);
}
@@ -337,11 +337,7 @@ impl BluetoothMethods for Bluetooth {
return p;
}
// Step 2.
- if !option.acceptAllDevices {
- self.request_bluetooth_devices(&p, &option.filters, &option.optionalServices);
- } else {
- self.request_bluetooth_devices(&p, &None, &option.optionalServices);
- }
+ self.request_bluetooth_devices(&p, &option.filters, &option.optionalServices);
// TODO(#4282): Step 3-5: Reject and resolve promise.
return p;
}
diff --git a/components/script/dom/domparser.rs b/components/script/dom/domparser.rs
index 0186b7e8b2a..2a770aeb3a0 100644
--- a/components/script/dom/domparser.rs
+++ b/components/script/dom/domparser.rs
@@ -18,8 +18,7 @@ use dom::bindings::str::DOMString;
use dom::document::{Document, IsHTMLDocument};
use dom::document::DocumentSource;
use dom::globalscope::GlobalScope;
-use dom::servoparser::html::{ParseContext, parse_html};
-use dom::servoparser::xml::{self, parse_xml};
+use dom::servoparser::ServoParser;
use dom::window::Window;
#[dom_struct]
@@ -70,7 +69,7 @@ impl DOMParserMethods for DOMParser {
loader,
None,
None);
- parse_html(&document, s, url, ParseContext::Owner(None));
+ ServoParser::parse_html_document(&document, s, url, None);
document.set_ready_state(DocumentReadyState::Complete);
Ok(document)
}
@@ -86,7 +85,7 @@ impl DOMParserMethods for DOMParser {
loader,
None,
None);
- parse_xml(&document, s, url, xml::ParseContext::Owner(None));
+ ServoParser::parse_xml_document(&document, s, url, None);
Ok(document)
}
}
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs
index 15a4ef816c8..ac65c01e24c 100644
--- a/components/script/dom/element.rs
+++ b/components/script/dom/element.rs
@@ -368,7 +368,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
PropertyDeclaration::BackgroundImage(DeclaredValue::Value(
background_image::SpecifiedValue(vec![
background_image::single_value::SpecifiedValue(Some(
- specified::Image::Url(url, specified::UrlExtraData { })
+ specified::Image::for_cascade(Some(Arc::new(url)), specified::url::UrlExtraData { })
))
])))));
}
diff --git a/components/script/dom/eventsource.rs b/components/script/dom/eventsource.rs
index f05e73beafa..2eabfcbc8b0 100644
--- a/components/script/dom/eventsource.rs
+++ b/components/script/dom/eventsource.rs
@@ -6,18 +6,50 @@ use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::Bindings::EventSourceBinding::{EventSourceInit, EventSourceMethods, Wrap};
use dom::bindings::error::{Error, Fallible};
+use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
-use dom::bindings::reflector::reflect_dom_object;
+use dom::bindings::refcounted::Trusted;
+use dom::bindings::reflector::{Reflectable, reflect_dom_object};
use dom::bindings::str::DOMString;
+use dom::event::Event;
use dom::eventtarget::EventTarget;
use dom::globalscope::GlobalScope;
+use dom::messageevent::MessageEvent;
+use encoding::Encoding;
+use encoding::all::UTF_8;
+use euclid::length::Length;
+use hyper::header::{Accept, qitem};
+use ipc_channel::ipc;
+use ipc_channel::router::ROUTER;
+use js::conversions::ToJSValConvertible;
+use js::jsapi::JSAutoCompartment;
+use js::jsval::UndefinedValue;
+use mime::{Mime, TopLevel, SubLevel};
+use net_traits::{CoreResourceMsg, FetchMetadata, FetchResponseMsg, FetchResponseListener, NetworkError};
+use net_traits::request::{CacheMode, CorsSettings, CredentialsMode};
+use net_traits::request::{RequestInit, RequestMode};
+use network_listener::{NetworkListener, PreInvoke};
+use script_thread::Runnable;
+use servo_atoms::Atom;
use std::cell::Cell;
+use std::mem;
+use std::str::{Chars, FromStr};
+use std::sync::{Arc, Mutex};
+use task_source::TaskSource;
+use timers::OneshotTimerCallback;
use url::Url;
+header! { (LastEventId, "Last-Event-ID") => [String] }
+
+const DEFAULT_RECONNECTION_TIME: u64 = 5000;
+
+#[derive(JSTraceable, PartialEq, Copy, Clone, Debug, HeapSizeOf)]
+struct GenerationId(u32);
+
#[derive(JSTraceable, PartialEq, Copy, Clone, Debug, HeapSizeOf)]
-enum EventSourceReadyState {
+/// https://html.spec.whatwg.org/multipage/#dom-eventsource-readystate
+enum ReadyState {
Connecting = 0,
- #[allow(dead_code)]
Open = 1,
Closed = 2
}
@@ -26,9 +58,254 @@ enum EventSourceReadyState {
pub struct EventSource {
eventtarget: EventTarget,
url: Url,
- ready_state: Cell<EventSourceReadyState>,
+ request: DOMRefCell<Option<RequestInit>>,
+ last_event_id: DOMRefCell<DOMString>,
+ reconnection_time: Cell<u64>,
+ generation_id: Cell<GenerationId>,
+
+ ready_state: Cell<ReadyState>,
with_credentials: bool,
- last_event_id: DOMRefCell<DOMString>
+}
+
+enum ParserState {
+ Field,
+ Comment,
+ Value,
+ Eol
+}
+
+struct EventSourceContext {
+ event_source: Trusted<EventSource>,
+ gen_id: GenerationId,
+ action_sender: ipc::IpcSender<FetchResponseMsg>,
+
+ parser_state: ParserState,
+ field: String,
+ value: String,
+ origin: String,
+
+ event_type: String,
+ data: String,
+ last_event_id: String,
+}
+
+impl EventSourceContext {
+ fn announce_the_connection(&self) {
+ let event_source = self.event_source.root();
+ if self.gen_id != event_source.generation_id.get() {
+ return;
+ }
+ let runnable = box AnnounceConnectionRunnable {
+ event_source: self.event_source.clone()
+ };
+ let _ = event_source.global().networking_task_source().queue(runnable, &*event_source.global());
+ }
+
+ fn fail_the_connection(&self) {
+ let event_source = self.event_source.root();
+ if self.gen_id != event_source.generation_id.get() {
+ return;
+ }
+ let runnable = box FailConnectionRunnable {
+ event_source: self.event_source.clone()
+ };
+ let _ = event_source.global().networking_task_source().queue(runnable, &*event_source.global());
+ }
+
+ // https://html.spec.whatwg.org/multipage/#reestablish-the-connection
+ fn reestablish_the_connection(&self) {
+ let event_source = self.event_source.root();
+
+ if self.gen_id != event_source.generation_id.get() {
+ return;
+ }
+
+ // Step 1
+ let runnable = box ReestablishConnectionRunnable {
+ event_source: self.event_source.clone(),
+ action_sender: self.action_sender.clone()
+ };
+ let _ = event_source.global().networking_task_source().queue(runnable, &*event_source.global());
+ }
+
+ // https://html.spec.whatwg.org/multipage/#processField
+ fn process_field(&mut self) {
+ match &*self.field {
+ "event" => mem::swap(&mut self.event_type, &mut self.value),
+ "data" => {
+ self.data.push_str(&self.value);
+ self.data.push('\n');
+ }
+ "id" => mem::swap(&mut self.last_event_id, &mut self.value),
+ "retry" => if let Ok(time) = u64::from_str(&self.value) {
+ self.event_source.root().reconnection_time.set(time);
+ },
+ _ => ()
+ }
+
+ self.field.clear();
+ self.value.clear();
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dispatchMessage
+ #[allow(unsafe_code)]
+ fn dispatch_event(&mut self) {
+ let event_source = self.event_source.root();
+ // Step 1
+ *event_source.last_event_id.borrow_mut() = DOMString::from(self.last_event_id.clone());
+ // Step 2
+ if self.data.is_empty() {
+ self.data.clear();
+ self.event_type.clear();
+ return;
+ }
+ // Step 3
+ if let Some(last) = self.data.pop() {
+ if last != '\n' {
+ self.data.push(last);
+ }
+ }
+ // Step 6
+ let type_ = if !self.event_type.is_empty() {
+ Atom::from(self.event_type.clone())
+ } else {
+ atom!("message")
+ };
+ // Steps 4-5
+ let event = {
+ let _ac = JSAutoCompartment::new(event_source.global().get_cx(),
+ event_source.reflector().get_jsobject().get());
+ rooted!(in(event_source.global().get_cx()) let mut data = UndefinedValue());
+ unsafe { self.data.to_jsval(event_source.global().get_cx(), data.handle_mut()) };
+ MessageEvent::new(&*event_source.global(), type_, false, false, data.handle(),
+ DOMString::from(self.origin.clone()),
+ event_source.last_event_id.borrow().clone())
+ };
+ // Step 7
+ self.event_type.clear();
+ self.data.clear();
+ // Step 8
+ let runnable = box DispatchEventRunnable {
+ event_source: self.event_source.clone(),
+ event: Trusted::new(&event)
+ };
+ let _ = event_source.global().networking_task_source().queue(runnable, &*event_source.global());
+ }
+
+ // https://html.spec.whatwg.org/multipage/#event-stream-interpretation
+ fn parse(&mut self, stream: Chars) {
+ let mut stream = stream.peekable();
+
+ while let Some(ch) = stream.next() {
+ match (ch, &self.parser_state) {
+ (':', &ParserState::Eol) => self.parser_state = ParserState::Comment,
+ (':', &ParserState::Field) => {
+ self.parser_state = ParserState::Value;
+ if let Some(&' ') = stream.peek() {
+ stream.next();
+ }
+ }
+
+ ('\n', &ParserState::Value) => {
+ self.parser_state = ParserState::Eol;
+ self.process_field();
+ }
+ ('\r', &ParserState::Value) => {
+ if let Some(&'\n') = stream.peek() {
+ continue;
+ }
+ self.parser_state = ParserState::Eol;
+ self.process_field();
+ }
+
+ ('\n', &ParserState::Field) => {
+ self.parser_state = ParserState::Eol;
+ self.process_field();
+ }
+ ('\r', &ParserState::Field) => {
+ if let Some(&'\n') = stream.peek() {
+ continue;
+ }
+ self.parser_state = ParserState::Eol;
+ self.process_field();
+ }
+
+ ('\n', &ParserState::Eol) => self.dispatch_event(),
+ ('\r', &ParserState::Eol) => {
+ if let Some(&'\n') = stream.peek() {
+ continue;
+ }
+ self.dispatch_event();
+ }
+
+ ('\n', &ParserState::Comment) => self.parser_state = ParserState::Eol,
+ ('\r', &ParserState::Comment) => {
+ if let Some(&'\n') = stream.peek() {
+ continue;
+ }
+ self.parser_state = ParserState::Eol;
+ }
+
+ (_, &ParserState::Field) => self.field.push(ch),
+ (_, &ParserState::Value) => self.value.push(ch),
+ (_, &ParserState::Eol) => {
+ self.parser_state = ParserState::Field;
+ self.field.push(ch);
+ }
+ (_, &ParserState::Comment) => (),
+ }
+ }
+ }
+}
+
+impl FetchResponseListener for EventSourceContext {
+ fn process_request_body(&mut self) {
+ // TODO
+ }
+
+ fn process_request_eof(&mut self) {
+ // TODO
+ }
+
+ fn process_response(&mut self, metadata: Result<FetchMetadata, NetworkError>) {
+ match metadata {
+ Ok(fm) => {
+ let meta = match fm {
+ FetchMetadata::Unfiltered(m) => m,
+ FetchMetadata::Filtered { unsafe_, .. } => unsafe_
+ };
+ match meta.content_type {
+ None => self.fail_the_connection(),
+ Some(ct) => match ct.into_inner().0 {
+ Mime(TopLevel::Text, SubLevel::EventStream, _) => {
+ self.origin = meta.final_url.origin().unicode_serialization();
+ self.announce_the_connection();
+ }
+ _ => self.fail_the_connection()
+ }
+ }
+ }
+ Err(_) => {
+ self.reestablish_the_connection();
+ }
+ }
+ }
+
+ fn process_response_chunk(&mut self, chunk: Vec<u8>) {
+ let mut stream = String::new();
+ UTF_8.raw_decoder().raw_feed(&chunk, &mut stream);
+ self.parse(stream.chars())
+ }
+
+ fn process_response_eof(&mut self, _response: Result<(), NetworkError>) {
+ self.reestablish_the_connection();
+ }
+}
+
+impl PreInvoke for EventSourceContext {
+ fn should_invoke(&self) -> bool {
+ self.event_source.root().generation_id.get() == self.gen_id
+ }
}
impl EventSource {
@@ -36,9 +313,13 @@ impl EventSource {
EventSource {
eventtarget: EventTarget::new_inherited(),
url: url,
- ready_state: Cell::new(EventSourceReadyState::Connecting),
+ request: DOMRefCell::new(None),
+ last_event_id: DOMRefCell::new(DOMString::from("")),
+ reconnection_time: Cell::new(DEFAULT_RECONNECTION_TIME),
+ generation_id: Cell::new(GenerationId(0)),
+
+ ready_state: Cell::new(ReadyState::Connecting),
with_credentials: with_credentials,
- last_event_id: DOMRefCell::new(DOMString::from(""))
}
}
@@ -48,27 +329,78 @@ impl EventSource {
Wrap)
}
+ pub fn request(&self) -> RequestInit {
+ self.request.borrow().clone().unwrap()
+ }
+
pub fn Constructor(global: &GlobalScope,
- url_str: DOMString,
+ url: DOMString,
event_source_init: &EventSourceInit) -> Fallible<Root<EventSource>> {
- // Steps 1-2
- let base_url = global.get_url();
- let url = match base_url.join(&*url_str) {
+ // TODO: Step 2 relevant settings object
+ // Step 3
+ let base_url = global.api_base_url();
+ let url_record = match base_url.join(&*url) {
Ok(u) => u,
+ // Step 4
Err(_) => return Err(Error::Syntax)
};
- // Step 3
- let event_source = EventSource::new(global, url, event_source_init.withCredentials);
- // Step 4
- // Step 5
- // Step 6
- // Step 7
+ // Step 1, 5
+ let ev = EventSource::new(global, url_record.clone(), event_source_init.withCredentials);
+ // Steps 6-7
+ let cors_attribute_state = if event_source_init.withCredentials {
+ CorsSettings::UseCredentials
+ } else {
+ CorsSettings::Anonymous
+ };
// Step 8
- // Step 9
+ // TODO: Step 9 set request's client settings
+ let mut request = RequestInit {
+ url: url_record,
+ origin: global.get_url(),
+ pipeline_id: Some(global.pipeline_id()),
+ // https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request
+ use_url_credentials: true,
+ mode: RequestMode::CorsMode,
+ credentials_mode: if cors_attribute_state == CorsSettings::Anonymous {
+ CredentialsMode::CredentialsSameOrigin
+ } else {
+ CredentialsMode::Include
+ },
+ ..RequestInit::default()
+ };
// Step 10
+ request.headers.set(Accept(vec![qitem(mime!(Text / EventStream))]));
// Step 11
- Ok(event_source)
+ request.cache_mode = CacheMode::NoStore;
// Step 12
+ *ev.request.borrow_mut() = Some(request.clone());
+ // Step 14
+ let (action_sender, action_receiver) = ipc::channel().unwrap();
+ let context = EventSourceContext {
+ event_source: Trusted::new(&ev),
+ gen_id: ev.generation_id.get(),
+ action_sender: action_sender.clone(),
+
+ parser_state: ParserState::Eol,
+ field: String::new(),
+ value: String::new(),
+ origin: String::new(),
+
+ event_type: String::new(),
+ data: String::new(),
+ last_event_id: String::new(),
+ };
+ let listener = NetworkListener {
+ context: Arc::new(Mutex::new(context)),
+ task_source: global.networking_task_source(),
+ wrapper: Some(global.get_runnable_wrapper())
+ };
+ ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
+ listener.notify_fetch(message.to().unwrap());
+ });
+ global.core_resource_thread().send(CoreResourceMsg::Fetch(request, action_sender)).unwrap();
+ // Step 13
+ Ok(ev)
}
}
@@ -99,7 +431,119 @@ impl EventSourceMethods for EventSource {
// https://html.spec.whatwg.org/multipage/#dom-eventsource-close
fn Close(&self) {
- self.ready_state.set(EventSourceReadyState::Closed);
- // TODO: Terminate ongoing fetch
+ let GenerationId(prev_id) = self.generation_id.get();
+ self.generation_id.set(GenerationId(prev_id + 1));
+ self.ready_state.set(ReadyState::Closed);
+ }
+}
+
+pub struct AnnounceConnectionRunnable {
+ event_source: Trusted<EventSource>,
+}
+
+impl Runnable for AnnounceConnectionRunnable {
+ fn name(&self) -> &'static str { "EventSource AnnounceConnectionRunnable" }
+
+ // https://html.spec.whatwg.org/multipage/#announce-the-connection
+ fn handler(self: Box<AnnounceConnectionRunnable>) {
+ let event_source = self.event_source.root();
+ if event_source.ready_state.get() != ReadyState::Closed {
+ event_source.ready_state.set(ReadyState::Open);
+ event_source.upcast::<EventTarget>().fire_event(atom!("open"));
+ }
+ }
+}
+
+pub struct FailConnectionRunnable {
+ event_source: Trusted<EventSource>,
+}
+
+impl Runnable for FailConnectionRunnable {
+ fn name(&self) -> &'static str { "EventSource FailConnectionRunnable" }
+
+ // https://html.spec.whatwg.org/multipage/#fail-the-connection
+ fn handler(self: Box<FailConnectionRunnable>) {
+ let event_source = self.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"));
+ }
+ }
+}
+
+pub struct ReestablishConnectionRunnable {
+ event_source: Trusted<EventSource>,
+ action_sender: ipc::IpcSender<FetchResponseMsg>,
+}
+
+impl Runnable for ReestablishConnectionRunnable {
+ fn name(&self) -> &'static str { "EventSource ReestablishConnectionRunnable" }
+
+ // https://html.spec.whatwg.org/multipage/#reestablish-the-connection
+ fn handler(self: Box<ReestablishConnectionRunnable>) {
+ let event_source = self.event_source.root();
+ // Step 1.1
+ if event_source.ready_state.get() == ReadyState::Closed {
+ return;
+ }
+ // Step 1.2
+ event_source.ready_state.set(ReadyState::Connecting);
+ // Step 1.3
+ event_source.upcast::<EventTarget>().fire_event(atom!("error"));
+ // Step 2
+ let duration = Length::new(event_source.reconnection_time.get());
+ // TODO Step 3: Optionally wait some more
+ // Steps 4-5
+ let callback = OneshotTimerCallback::EventSourceTimeout(EventSourceTimeoutCallback {
+ event_source: self.event_source.clone(),
+ action_sender: self.action_sender.clone()
+ });
+ let _ = event_source.global().schedule_callback(callback, duration);
+ }
+}
+
+#[derive(JSTraceable, HeapSizeOf)]
+pub struct EventSourceTimeoutCallback {
+ #[ignore_heap_size_of = "Because it is non-owning"]
+ event_source: Trusted<EventSource>,
+ #[ignore_heap_size_of = "Because it is non-owning"]
+ action_sender: ipc::IpcSender<FetchResponseMsg>,
+}
+
+impl EventSourceTimeoutCallback {
+ // https://html.spec.whatwg.org/multipage/#reestablish-the-connection
+ pub fn invoke(self) {
+ let event_source = self.event_source.root();
+ let global = event_source.global();
+ // Step 5.1
+ if event_source.ready_state.get() != ReadyState::Connecting {
+ return;
+ }
+ // Step 5.2
+ let mut request = event_source.request();
+ // Step 5.3
+ if !event_source.last_event_id.borrow().is_empty() {
+ request.headers.set(LastEventId(String::from(event_source.last_event_id.borrow().clone())));
+ }
+ // Step 5.4
+ global.core_resource_thread().send(CoreResourceMsg::Fetch(request, self.action_sender)).unwrap();
+ }
+}
+
+pub struct DispatchEventRunnable {
+ event_source: Trusted<EventSource>,
+ event: Trusted<MessageEvent>,
+}
+
+impl Runnable for DispatchEventRunnable {
+ fn name(&self) -> &'static str { "EventSource DispatchEventRunnable" }
+
+ // https://html.spec.whatwg.org/multipage/#dispatchMessage
+ fn handler(self: Box<DispatchEventRunnable>) {
+ let event_source = self.event_source.root();
+ // Step 8
+ if event_source.ready_state.get() != ReadyState::Closed {
+ self.event.root().upcast::<Event>().fire(&event_source.upcast());
+ }
}
}
diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs
index fc160675df5..2338dcf32e7 100644
--- a/components/script/dom/globalscope.rs
+++ b/components/script/dom/globalscope.rs
@@ -42,6 +42,7 @@ use std::collections::hash_map::Entry;
use std::ffi::CString;
use std::panic;
use task_source::file_reading::FileReadingTaskSource;
+use task_source::networking::NetworkingTaskSource;
use time::{Timespec, get_time};
use timers::{IsInterval, OneshotTimerCallback, OneshotTimerHandle};
use timers::{OneshotTimers, TimerCallback};
@@ -325,12 +326,12 @@ impl GlobalScope {
/// `ScriptChan` to send messages to the networking task source of
/// this of this global scope.
- pub fn networking_task_source(&self) -> Box<ScriptChan + Send> {
+ pub fn networking_task_source(&self) -> NetworkingTaskSource {
if let Some(window) = self.downcast::<Window>() {
return window.networking_task_source();
}
if let Some(worker) = self.downcast::<WorkerGlobalScope>() {
- return worker.script_chan();
+ return worker.networking_task_source();
}
unreachable!();
}
diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs
index e8a269c782c..d8ecda30943 100644
--- a/components/script/dom/htmlimageelement.rs
+++ b/components/script/dom/htmlimageelement.rs
@@ -26,8 +26,6 @@ use ipc_channel::ipc;
use ipc_channel::router::ROUTER;
use net_traits::image::base::{Image, ImageMetadata};
use net_traits::image_cache_thread::{ImageResponder, ImageResponse};
-use script_runtime::CommonScriptMsg;
-use script_runtime::ScriptThreadEventCategory::UpdateReplacedElement;
use script_thread::Runnable;
use std::i32;
use std::sync::Arc;
@@ -140,7 +138,7 @@ impl HTMLImageElement {
let trusted_node = Trusted::new(self);
let (responder_sender, responder_receiver) = ipc::channel().unwrap();
- let script_chan = window.networking_task_source();
+ let task_source = window.networking_task_source();
let wrapper = window.get_runnable_wrapper();
ROUTER.add_route(responder_receiver.to_opaque(), box move |message| {
// Return the image via a message to the script thread, which marks the element
@@ -148,9 +146,7 @@ impl HTMLImageElement {
let image_response = message.to().unwrap();
let runnable = box ImageResponseHandlerRunnable::new(
trusted_node.clone(), image_response);
- let runnable = wrapper.wrap_runnable(runnable);
- let _ = script_chan.send(CommonScriptMsg::RunnableMsg(
- UpdateReplacedElement, runnable));
+ let _ = task_source.queue_with_wrapper(runnable, &wrapper);
});
image_cache.request_image_and_metadata(img_url,
diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs
index b599d4369dc..ddbd57d2438 100644
--- a/components/script/dom/htmlinputelement.rs
+++ b/components/script/dom/htmlinputelement.rs
@@ -35,7 +35,6 @@ use dom::virtualmethods::VirtualMethods;
use html5ever_atoms::LocalName;
use ipc_channel::ipc::{self, IpcSender};
use mime_guess;
-use msg::constellation_msg::Key;
use net_traits::{CoreResourceMsg, IpcSend};
use net_traits::blob_url_store::get_blob_origin;
use net_traits::filemanager_thread::{FileManagerThreadMsg, FilterPattern};
@@ -1097,18 +1096,10 @@ impl VirtualMethods for HTMLInputElement {
let action = self.textinput.borrow_mut().handle_keydown(keyevent);
match action {
TriggerDefaultAction => {
- if let Some(key) = keyevent.get_key() {
- match key {
- Key::Enter | Key::KpEnter =>
- self.implicit_submission(keyevent.CtrlKey(),
- keyevent.ShiftKey(),
- keyevent.AltKey(),
- keyevent.MetaKey()),
- // Issue #12071: Tab should not submit forms
- // TODO(3982): Implement form keyboard navigation
- _ => (),
- }
- };
+ self.implicit_submission(keyevent.CtrlKey(),
+ keyevent.ShiftKey(),
+ keyevent.AltKey(),
+ keyevent.MetaKey());
},
DispatchInput => {
self.value_changed.set(true);
diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs
index 90499388153..5df64f62ca0 100644
--- a/components/script/dom/htmllinkelement.rs
+++ b/components/script/dom/htmllinkelement.rs
@@ -243,8 +243,8 @@ impl HTMLLinkElement {
let (action_sender, action_receiver) = ipc::channel().unwrap();
let listener = NetworkListener {
context: context,
- script_chan: document.window().networking_task_source(),
- wrapper: Some(document.window().get_runnable_wrapper()),
+ task_source: document.window().networking_task_source(),
+ wrapper: Some(document.window().get_runnable_wrapper())
};
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
listener.notify_fetch(message.to().unwrap());
diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs
index 0627bcf0ffb..09a1b7cc438 100644
--- a/components/script/dom/htmlmediaelement.rs
+++ b/components/script/dom/htmlmediaelement.rs
@@ -521,11 +521,10 @@ impl HTMLMediaElement {
let context = Arc::new(Mutex::new(HTMLMediaElementContext::new(self, url.clone())));
let (action_sender, action_receiver) = ipc::channel().unwrap();
let window = window_from_node(self);
- let script_chan = window.networking_task_source();
let listener = NetworkListener {
context: context,
- script_chan: script_chan,
- wrapper: Some(window.get_runnable_wrapper()),
+ task_source: window.networking_task_source(),
+ wrapper: Some(window.get_runnable_wrapper())
};
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
diff --git a/components/script/dom/htmlmetaelement.rs b/components/script/dom/htmlmetaelement.rs
index 7ddca9f2f8a..82855472589 100644
--- a/components/script/dom/htmlmetaelement.rs
+++ b/components/script/dom/htmlmetaelement.rs
@@ -22,7 +22,7 @@ use std::ascii::AsciiExt;
use std::sync::Arc;
use style::attr::AttrValue;
use style::str::HTML_SPACE_CHARACTERS;
-use style::stylesheets::{Stylesheet, CSSRule, Origin};
+use style::stylesheets::{Stylesheet, CssRule, Origin};
use style::viewport::ViewportRule;
#[dom_struct]
@@ -81,7 +81,7 @@ impl HTMLMetaElement {
if !content.is_empty() {
if let Some(translated_rule) = ViewportRule::from_meta(&**content) {
*self.stylesheet.borrow_mut() = Some(Arc::new(Stylesheet {
- rules: vec![CSSRule::Viewport(Arc::new(RwLock::new(translated_rule)))],
+ rules: vec![CssRule::Viewport(Arc::new(RwLock::new(translated_rule)))],
origin: Origin::Author,
media: Default::default(),
// Viewport constraints are always recomputed on resize; they don't need to
diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs
index 3b2057e4338..68b65f93142 100644
--- a/components/script/dom/htmlscriptelement.rs
+++ b/components/script/dom/htmlscriptelement.rs
@@ -27,13 +27,12 @@ use dom::node::{document_from_node, window_from_node};
use dom::virtualmethods::VirtualMethods;
use encoding::label::encoding_from_whatwg_label;
use encoding::types::{DecoderTrap, EncodingRef};
-use html5ever::tree_builder::NextParserState;
use html5ever_atoms::LocalName;
use ipc_channel::ipc;
use ipc_channel::router::ROUTER;
use js::jsval::UndefinedValue;
use net_traits::{FetchMetadata, FetchResponseListener, Metadata, NetworkError};
-use net_traits::request::{CORSSettings, CredentialsMode, Destination, RequestInit, RequestMode, Type as RequestType};
+use net_traits::request::{CorsSettings, CredentialsMode, Destination, RequestInit, RequestMode, Type as RequestType};
use network_listener::{NetworkListener, PreInvoke};
use servo_atoms::Atom;
use std::ascii::AsciiExt;
@@ -221,7 +220,7 @@ impl PreInvoke for ScriptContext {}
/// https://html.spec.whatwg.org/multipage/#fetch-a-classic-script
fn fetch_a_classic_script(script: &HTMLScriptElement,
url: Url,
- cors_setting: Option<CORSSettings>,
+ cors_setting: Option<CorsSettings>,
character_encoding: EncodingRef) {
let doc = document_from_node(script);
@@ -233,13 +232,13 @@ fn fetch_a_classic_script(script: &HTMLScriptElement,
// https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request
// Step 1
mode: match cors_setting {
- Some(_) => RequestMode::CORSMode,
- None => RequestMode::NoCORS,
+ Some(_) => RequestMode::CorsMode,
+ None => RequestMode::NoCors,
},
// https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request
// Step 3-4
credentials_mode: match cors_setting {
- Some(CORSSettings::Anonymous) => CredentialsMode::CredentialsSameOrigin,
+ Some(CorsSettings::Anonymous) => CredentialsMode::CredentialsSameOrigin,
_ => CredentialsMode::Include,
},
origin: doc.url().clone(),
@@ -263,8 +262,8 @@ fn fetch_a_classic_script(script: &HTMLScriptElement,
let (action_sender, action_receiver) = ipc::channel().unwrap();
let listener = NetworkListener {
context: context,
- script_chan: doc.window().networking_task_source(),
- wrapper: Some(doc.window().get_runnable_wrapper()),
+ task_source: doc.window().networking_task_source(),
+ wrapper: Some(doc.window().get_runnable_wrapper())
};
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
@@ -275,10 +274,12 @@ fn fetch_a_classic_script(script: &HTMLScriptElement,
impl HTMLScriptElement {
/// https://html.spec.whatwg.org/multipage/#prepare-a-script
- pub fn prepare(&self) -> NextParserState {
+ ///
+ /// Returns true if tokenization should continue, false otherwise.
+ pub fn prepare(&self) -> bool {
// Step 1.
if self.already_started.get() {
- return NextParserState::Continue;
+ return true;
}
// Step 2.
@@ -296,17 +297,17 @@ impl HTMLScriptElement {
// Step 4.
let text = self.Text();
if text.is_empty() && !element.has_attribute(&local_name!("src")) {
- return NextParserState::Continue;
+ return true;
}
// Step 5.
if !self.upcast::<Node>().is_in_doc() {
- return NextParserState::Continue;
+ return true;
}
// Step 6.
if !self.is_javascript() {
- return NextParserState::Continue;
+ return true;
}
// Step 7.
@@ -321,12 +322,12 @@ impl HTMLScriptElement {
// Step 9.
let doc = document_from_node(self);
if self.parser_inserted.get() && &*self.parser_document != &*doc {
- return NextParserState::Continue;
+ return true;
}
// Step 10.
if !doc.is_scripting_enabled() {
- return NextParserState::Continue;
+ return true;
}
// TODO(#4577): Step 11: CSP.
@@ -339,13 +340,13 @@ impl HTMLScriptElement {
let for_value = for_attribute.value().to_ascii_lowercase();
let for_value = for_value.trim_matches(HTML_SPACE_CHARACTERS);
if for_value != "window" {
- return NextParserState::Continue;
+ return true;
}
let event_value = event_attribute.value().to_ascii_lowercase();
let event_value = event_value.trim_matches(HTML_SPACE_CHARACTERS);
if event_value != "onload" && event_value != "onload()" {
- return NextParserState::Continue;
+ return true;
}
},
(_, _) => (),
@@ -358,8 +359,8 @@ impl HTMLScriptElement {
// Step 14.
let cors_setting = match self.GetCrossOrigin() {
- Some(ref s) if *s == "anonymous" => Some(CORSSettings::Anonymous),
- Some(ref s) if *s == "use-credentials" => Some(CORSSettings::UseCredentials),
+ Some(ref s) if *s == "anonymous" => Some(CorsSettings::Anonymous),
+ Some(ref s) if *s == "use-credentials" => Some(CorsSettings::UseCredentials),
None => None,
_ => unreachable!()
};
@@ -380,7 +381,7 @@ impl HTMLScriptElement {
// Step 18.2.
if src.is_empty() {
self.queue_error_event();
- return NextParserState::Continue;
+ return true;
}
// Step 18.4-18.5.
@@ -388,7 +389,7 @@ impl HTMLScriptElement {
Err(_) => {
warn!("error parsing URL for script {}", &**src);
self.queue_error_event();
- return NextParserState::Continue;
+ return true;
}
Ok(url) => url,
};
@@ -411,7 +412,7 @@ impl HTMLScriptElement {
!async {
doc.add_deferred_script(self);
// Second part implemented in Document::process_deferred_scripts.
- return NextParserState::Continue;
+ return true;
// Step 20.b: classic, has src, was parser-inserted, is not async.
} else if is_external &&
was_parser_inserted &&
@@ -442,7 +443,7 @@ impl HTMLScriptElement {
self.ready_to_be_parser_executed.set(true);
*self.load.borrow_mut() = Some(Ok(ScriptOrigin::internal(text, base_url)));
self.execute();
- return NextParserState::Continue;
+ return true;
}
// TODO: make this suspension happen automatically.
@@ -451,7 +452,7 @@ impl HTMLScriptElement {
parser.suspend();
}
}
- NextParserState::Suspend
+ false
}
pub fn is_ready_to_be_executed(&self) -> bool {
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index 5fcfd74f1f6..0f510719640 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -47,7 +47,7 @@ use dom::htmltextareaelement::{HTMLTextAreaElement, LayoutHTMLTextAreaElementHel
use dom::nodelist::NodeList;
use dom::processinginstruction::ProcessingInstruction;
use dom::range::WeakRangeVec;
-use dom::servoparser::html::parse_html_fragment;
+use dom::servoparser::ServoParser;
use dom::svgsvgelement::{SVGSVGElement, LayoutSVGSVGElementHelpers};
use dom::text::Text;
use dom::virtualmethods::{VirtualMethods, vtable_for};
@@ -833,7 +833,7 @@ impl Node {
let context_document = document_from_node(self);
let fragment = DocumentFragment::new(&context_document);
if context_document.is_html_document() {
- parse_html_fragment(self.upcast(), markup, fragment.upcast());
+ ServoParser::parse_html_fragment(self.upcast(), markup, fragment.upcast());
} else {
// FIXME: XML case
unimplemented!();
diff --git a/components/script/dom/request.rs b/components/script/dom/request.rs
index fa649702259..614c51398e8 100644
--- a/components/script/dom/request.rs
+++ b/components/script/dom/request.rs
@@ -114,7 +114,7 @@ impl Request {
url,
false);
// Step 5.5
- fallback_mode = Some(NetTraitsRequestMode::CORSMode);
+ fallback_mode = Some(NetTraitsRequestMode::CorsMode);
// Step 5.6
fallback_credentials = Some(NetTraitsRequestCredentials::Omit);
}
@@ -335,7 +335,7 @@ impl Request {
// deep copied headers in Step 27.
// Step 30
- if r.request.borrow().mode == NetTraitsRequestMode::NoCORS {
+ if r.request.borrow().mode == NetTraitsRequestMode::NoCors {
let borrowed_request = r.request.borrow();
// Step 30.1
if !is_cors_safelisted_method(&borrowed_request.method.borrow()) {
@@ -814,8 +814,8 @@ impl Into<NetTraitsRequestMode> for RequestMode {
match self {
RequestMode::Navigate => NetTraitsRequestMode::Navigate,
RequestMode::Same_origin => NetTraitsRequestMode::SameOrigin,
- RequestMode::No_cors => NetTraitsRequestMode::NoCORS,
- RequestMode::Cors => NetTraitsRequestMode::CORSMode,
+ RequestMode::No_cors => NetTraitsRequestMode::NoCors,
+ RequestMode::Cors => NetTraitsRequestMode::CorsMode,
}
}
}
@@ -825,8 +825,8 @@ impl Into<RequestMode> for NetTraitsRequestMode {
match self {
NetTraitsRequestMode::Navigate => RequestMode::Navigate,
NetTraitsRequestMode::SameOrigin => RequestMode::Same_origin,
- NetTraitsRequestMode::NoCORS => RequestMode::No_cors,
- NetTraitsRequestMode::CORSMode => RequestMode::Cors,
+ NetTraitsRequestMode::NoCors => RequestMode::No_cors,
+ NetTraitsRequestMode::CorsMode => RequestMode::Cors,
}
}
}
diff --git a/components/script/dom/servoparser/html.rs b/components/script/dom/servoparser/html.rs
index fd4a5a923b9..a2d636da6f3 100644
--- a/components/script/dom/servoparser/html.rs
+++ b/components/script/dom/servoparser/html.rs
@@ -4,23 +4,19 @@
#![allow(unrooted_must_root)]
-use document_loader::DocumentLoader;
-use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::inheritance::{Castable, CharacterDataTypeId, NodeTypeId};
-use dom::bindings::js::{JS, RootedReference};
+use dom::bindings::js::{JS, Root};
use dom::bindings::str::DOMString;
+use dom::bindings::trace::JSTraceable;
use dom::characterdata::CharacterData;
use dom::comment::Comment;
-use dom::document::{DocumentSource, IsHTMLDocument};
use dom::document::Document;
use dom::documenttype::DocumentType;
use dom::element::{Element, ElementCreator};
-use dom::htmlformelement::HTMLFormElement;
use dom::htmlscriptelement::HTMLScriptElement;
use dom::htmltemplateelement::HTMLTemplateElement;
-use dom::node::{document_from_node, window_from_node};
use dom::node::Node;
use dom::processinginstruction::ProcessingInstruction;
use dom::text::Text;
@@ -29,28 +25,107 @@ use html5ever::serialize::{AttrRef, Serializable, Serializer};
use html5ever::serialize::TraversalScope;
use html5ever::serialize::TraversalScope::{ChildrenOnly, IncludeNode};
use html5ever::tendril::StrTendril;
-use html5ever::tokenizer::{Tokenizer as H5ETokenizer, TokenizerOpts};
-use html5ever::tree_builder::{NextParserState, NodeOrText, QuirksMode};
-use html5ever::tree_builder::{TreeBuilder, TreeBuilderOpts, TreeSink};
+use html5ever::tokenizer::{Tokenizer as HtmlTokenizer, TokenizerOpts, TokenizerResult};
+use html5ever::tokenizer::buffer_queue::BufferQueue;
+use html5ever::tree_builder::{NodeOrText, QuirksMode};
+use html5ever::tree_builder::{Tracer as HtmlTracer, TreeBuilder, TreeBuilderOpts, TreeSink};
use html5ever_atoms::QualName;
-use msg::constellation_msg::PipelineId;
+use js::jsapi::JSTracer;
use std::borrow::Cow;
use std::io::{self, Write};
-use super::{HtmlTokenizer, LastChunkState, ServoParser, Sink, Tokenizer};
+use super::{FragmentContext, Sink};
use url::Url;
-fn insert(parent: &Node, reference_child: Option<&Node>, child: NodeOrText<JS<Node>>) {
- match child {
- NodeOrText::AppendNode(n) => {
- assert!(parent.InsertBefore(&n, reference_child).is_ok());
- },
- NodeOrText::AppendText(t) => {
- // FIXME(ajeffrey): convert directly from tendrils to DOMStrings
- let s: String = t.into();
- let text = Text::new(DOMString::from(s), &parent.owner_doc());
- assert!(parent.InsertBefore(text.upcast(), reference_child).is_ok());
+#[derive(HeapSizeOf, JSTraceable)]
+#[must_root]
+pub struct Tokenizer {
+ #[ignore_heap_size_of = "Defined in html5ever"]
+ inner: HtmlTokenizer<TreeBuilder<JS<Node>, Sink>>,
+ #[ignore_heap_size_of = "Defined in html5ever"]
+ input_buffer: BufferQueue,
+}
+
+impl Tokenizer {
+ pub fn new(
+ document: &Document,
+ url: Url,
+ fragment_context: Option<FragmentContext>)
+ -> Self {
+ let sink = Sink {
+ base_url: url,
+ document: JS::from_ref(document),
+ };
+
+ let options = TreeBuilderOpts {
+ ignore_missing_rules: true,
+ .. Default::default()
+ };
+
+ let inner = if let Some(fc) = fragment_context {
+ let tb = TreeBuilder::new_for_fragment(
+ sink,
+ JS::from_ref(fc.context_elem),
+ fc.form_elem.map(|n| JS::from_ref(n)),
+ options);
+
+ let tok_options = TokenizerOpts {
+ initial_state: Some(tb.tokenizer_state_for_context_elem()),
+ .. Default::default()
+ };
+
+ HtmlTokenizer::new(tb, tok_options)
+ } else {
+ HtmlTokenizer::new(TreeBuilder::new(sink, options), Default::default())
+ };
+
+ Tokenizer {
+ inner: inner,
+ input_buffer: BufferQueue::new(),
}
}
+
+ pub fn feed(&mut self, input: String) {
+ self.input_buffer.push_back(input.into());
+ self.run();
+ }
+
+ #[allow(unrooted_must_root)]
+ pub fn run(&mut self) {
+ while let TokenizerResult::Script(script) = self.inner.feed(&mut self.input_buffer) {
+ let script = Root::from_ref(script.downcast::<HTMLScriptElement>().unwrap());
+ if !script.prepare() {
+ break;
+ }
+ }
+ }
+
+ pub fn end(&mut self) {
+ assert!(self.input_buffer.is_empty());
+ self.inner.end();
+ }
+
+ pub fn set_plaintext_state(&mut self) {
+ self.inner.set_plaintext_state();
+ }
+}
+
+impl JSTraceable for HtmlTokenizer<TreeBuilder<JS<Node>, Sink>> {
+ fn trace(&self, trc: *mut JSTracer) {
+ struct Tracer(*mut JSTracer);
+ let tracer = Tracer(trc);
+
+ impl HtmlTracer for Tracer {
+ type Handle = JS<Node>;
+ #[allow(unrooted_must_root)]
+ fn trace_handle(&self, node: &JS<Node>) {
+ node.trace(self.0);
+ }
+ }
+
+ let tree_builder = self.sink();
+ tree_builder.trace_handles(&tracer);
+ tree_builder.sink().trace(trc);
+ }
}
impl<'a> TreeSink for Sink {
@@ -153,14 +228,6 @@ impl<'a> TreeSink for Sink {
script.map(|script| script.set_already_started(true));
}
- fn complete_script(&mut self, node: JS<Node>) -> NextParserState {
- let script = node.downcast::<HTMLScriptElement>();
- if let Some(script) = script {
- return script.prepare();
- }
- NextParserState::Continue
- }
-
fn reparent_children(&mut self, node: JS<Node>, new_parent: JS<Node>) {
while let Some(ref child) = node.GetFirstChild() {
new_parent.AppendChild(&child).unwrap();
@@ -169,6 +236,20 @@ impl<'a> TreeSink for Sink {
}
}
+fn insert(parent: &Node, reference_child: Option<&Node>, child: NodeOrText<JS<Node>>) {
+ match child {
+ NodeOrText::AppendNode(n) => {
+ assert!(parent.InsertBefore(&n, reference_child).is_ok());
+ },
+ NodeOrText::AppendText(t) => {
+ // FIXME(ajeffrey): convert directly from tendrils to DOMStrings
+ let s: String = t.into();
+ let text = Text::new(DOMString::from(s), &parent.owner_doc());
+ assert!(parent.InsertBefore(text.upcast(), reference_child).is_ok());
+ }
+ }
+}
+
impl<'a> Serializable for &'a Node {
fn serialize<'wr, Wr: Write>(&self, serializer: &mut Serializer<'wr, Wr>,
traversal_scope: TraversalScope) -> io::Result<()> {
@@ -245,100 +326,3 @@ impl<'a> Serializable for &'a Node {
}
}
}
-
-/// FragmentContext is used only to pass this group of related values
-/// into functions.
-#[derive(Copy, Clone)]
-pub struct FragmentContext<'a> {
- pub context_elem: &'a Node,
- pub form_elem: Option<&'a Node>,
-}
-
-pub enum ParseContext<'a> {
- Fragment(FragmentContext<'a>),
- Owner(Option<PipelineId>),
-}
-
-pub fn parse_html(document: &Document,
- input: DOMString,
- url: Url,
- context: ParseContext) {
- let sink = Sink {
- base_url: url,
- document: JS::from_ref(document),
- };
-
- let options = TreeBuilderOpts {
- ignore_missing_rules: true,
- .. Default::default()
- };
-
- let parser = match context {
- ParseContext::Owner(owner) => {
- let tb = TreeBuilder::new(sink, options);
- let tok = H5ETokenizer::new(tb, Default::default());
-
- ServoParser::new(
- document,
- owner,
- Tokenizer::HTML(HtmlTokenizer::new(tok)),
- LastChunkState::NotReceived)
- },
- ParseContext::Fragment(fc) => {
- let tb = TreeBuilder::new_for_fragment(
- sink,
- JS::from_ref(fc.context_elem),
- fc.form_elem.map(|n| JS::from_ref(n)),
- options);
-
- let tok_options = TokenizerOpts {
- initial_state: Some(tb.tokenizer_state_for_context_elem()),
- .. Default::default()
- };
- let tok = H5ETokenizer::new(tb, tok_options);
-
- ServoParser::new(
- document,
- None,
- Tokenizer::HTML(HtmlTokenizer::new(tok)),
- LastChunkState::Received)
- }
- };
- parser.parse_chunk(String::from(input));
-}
-
-// https://html.spec.whatwg.org/multipage/#parsing-html-fragments
-pub fn parse_html_fragment(context_node: &Node,
- input: DOMString,
- output: &Node) {
- let window = window_from_node(context_node);
- let context_document = document_from_node(context_node);
- let url = context_document.url();
-
- // Step 1.
- let loader = DocumentLoader::new(&*context_document.loader());
- let document = Document::new(&window, None, Some(url.clone()),
- IsHTMLDocument::HTMLDocument,
- None, None,
- DocumentSource::FromParser,
- loader,
- None, None);
-
- // Step 2.
- document.set_quirks_mode(context_document.quirks_mode());
-
- // Step 11.
- let form = context_node.inclusive_ancestors()
- .find(|element| element.is::<HTMLFormElement>());
- let fragment_context = FragmentContext {
- context_elem: context_node,
- form_elem: form.r(),
- };
- parse_html(&document, input, url.clone(), ParseContext::Fragment(fragment_context));
-
- // Step 14.
- let root_element = document.GetDocumentElement().expect("no document element");
- for child in root_element.upcast::<Node>().children() {
- output.AppendChild(&child).unwrap();
- }
-}
diff --git a/components/script/dom/servoparser/mod.rs b/components/script/dom/servoparser/mod.rs
index 4df82a457a7..7b5c5c7f4ab 100644
--- a/components/script/dom/servoparser/mod.rs
+++ b/components/script/dom/servoparser/mod.rs
@@ -2,32 +2,27 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-use document_loader::LoadType;
+use document_loader::{DocumentLoader, LoadType};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::HTMLImageElementBinding::HTMLImageElementMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::codegen::Bindings::ServoParserBinding;
use dom::bindings::inheritance::Castable;
-use dom::bindings::js::{JS, Root};
+use dom::bindings::js::{JS, Root, RootedReference};
use dom::bindings::refcounted::Trusted;
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use dom::bindings::str::DOMString;
-use dom::bindings::trace::JSTraceable;
-use dom::document::Document;
+use dom::document::{Document, DocumentSource, IsHTMLDocument};
use dom::globalscope::GlobalScope;
+use dom::htmlformelement::HTMLFormElement;
use dom::htmlimageelement::HTMLImageElement;
-use dom::node::Node;
+use dom::node::{Node, document_from_node, window_from_node};
use encoding::all::UTF_8;
use encoding::types::{DecoderTrap, Encoding};
-use html5ever::tokenizer::Tokenizer as H5ETokenizer;
-use html5ever::tokenizer::buffer_queue::BufferQueue;
-use html5ever::tree_builder::Tracer as HtmlTracer;
-use html5ever::tree_builder::TreeBuilder as HtmlTreeBuilder;
use hyper::header::ContentType;
use hyper::mime::{Mime, SubLevel, TopLevel};
use hyper_serde::Serde;
-use js::jsapi::JSTracer;
use msg::constellation_msg::PipelineId;
use net_traits::{FetchMetadata, FetchResponseListener, Metadata, NetworkError};
use network_listener::PreInvoke;
@@ -38,11 +33,9 @@ use std::cell::Cell;
use std::collections::VecDeque;
use url::Url;
use util::resource_files::read_resource_file;
-use xml5ever::tokenizer::XmlTokenizer;
-use xml5ever::tree_builder::{Tracer as XmlTracer, XmlTreeBuilder};
-pub mod html;
-pub mod xml;
+mod html;
+mod xml;
#[dom_struct]
pub struct ServoParser {
@@ -69,6 +62,76 @@ enum LastChunkState {
}
impl ServoParser {
+ pub fn parse_html_document(
+ document: &Document,
+ input: DOMString,
+ url: Url,
+ owner: Option<PipelineId>) {
+ let parser = ServoParser::new(
+ document,
+ owner,
+ Tokenizer::Html(self::html::Tokenizer::new(document, url, None)),
+ LastChunkState::NotReceived);
+ parser.parse_chunk(String::from(input));
+ }
+
+ // https://html.spec.whatwg.org/multipage/#parsing-html-fragments
+ pub fn parse_html_fragment(
+ context_node: &Node,
+ input: DOMString,
+ output: &Node) {
+ let window = window_from_node(context_node);
+ let context_document = document_from_node(context_node);
+ let url = context_document.url();
+
+ // Step 1.
+ let loader = DocumentLoader::new(&*context_document.loader());
+ let document = Document::new(&window, None, Some(url.clone()),
+ IsHTMLDocument::HTMLDocument,
+ None, None,
+ DocumentSource::FromParser,
+ loader,
+ None, None);
+
+ // Step 2.
+ document.set_quirks_mode(context_document.quirks_mode());
+
+ // Step 11.
+ let form = context_node.inclusive_ancestors()
+ .find(|element| element.is::<HTMLFormElement>());
+ let fragment_context = FragmentContext {
+ context_elem: context_node,
+ form_elem: form.r(),
+ };
+
+ let parser = ServoParser::new(
+ &document,
+ None,
+ Tokenizer::Html(
+ self::html::Tokenizer::new(&document, url.clone(), Some(fragment_context))),
+ LastChunkState::Received);
+ parser.parse_chunk(String::from(input));
+
+ // Step 14.
+ let root_element = document.GetDocumentElement().expect("no document element");
+ for child in root_element.upcast::<Node>().children() {
+ output.AppendChild(&child).unwrap();
+ }
+ }
+
+ pub fn parse_xml_document(
+ document: &Document,
+ input: DOMString,
+ url: Url,
+ owner: Option<PipelineId>) {
+ let parser = ServoParser::new(
+ document,
+ owner,
+ Tokenizer::Xml(self::xml::Tokenizer::new(document, url)),
+ LastChunkState::NotReceived);
+ parser.parse_chunk(String::from(input));
+ }
+
#[allow(unrooted_must_root)]
fn new_inherited(
document: &Document,
@@ -214,51 +277,11 @@ impl ServoParser {
}
}
-#[derive(HeapSizeOf)]
+#[derive(HeapSizeOf, JSTraceable)]
#[must_root]
enum Tokenizer {
- HTML(HtmlTokenizer),
- XML(
- #[ignore_heap_size_of = "Defined in xml5ever"]
- XmlTokenizer<XmlTreeBuilder<JS<Node>, Sink>>
- ),
-}
-
-#[derive(HeapSizeOf)]
-#[must_root]
-struct HtmlTokenizer {
- #[ignore_heap_size_of = "Defined in html5ever"]
- inner: H5ETokenizer<HtmlTreeBuilder<JS<Node>, Sink>>,
- #[ignore_heap_size_of = "Defined in html5ever"]
- input_buffer: BufferQueue,
-}
-
-impl HtmlTokenizer {
- #[allow(unrooted_must_root)]
- fn new(inner: H5ETokenizer<HtmlTreeBuilder<JS<Node>, Sink>>) -> Self {
- HtmlTokenizer {
- inner: inner,
- input_buffer: BufferQueue::new(),
- }
- }
-
- fn feed(&mut self, input: String) {
- self.input_buffer.push_back(input.into());
- self.run();
- }
-
- fn run(&mut self) {
- self.inner.feed(&mut self.input_buffer);
- }
-
- fn end(&mut self) {
- assert!(self.input_buffer.is_empty());
- self.inner.end();
- }
-
- fn set_plaintext_state(&mut self) {
- self.inner.set_plaintext_state();
- }
+ Html(self::html::Tokenizer),
+ Xml(self::xml::Tokenizer),
}
#[derive(JSTraceable, HeapSizeOf)]
@@ -271,70 +294,36 @@ struct Sink {
impl Tokenizer {
fn feed(&mut self, input: String) {
match *self {
- Tokenizer::HTML(ref mut tokenizer) => tokenizer.feed(input),
- Tokenizer::XML(ref mut tokenizer) => tokenizer.feed(input.into()),
+ Tokenizer::Html(ref mut tokenizer) => tokenizer.feed(input),
+ Tokenizer::Xml(ref mut tokenizer) => tokenizer.feed(input.into()),
}
}
fn run(&mut self) {
match *self {
- Tokenizer::HTML(ref mut tokenizer) => tokenizer.run(),
- Tokenizer::XML(ref mut tokenizer) => tokenizer.run(),
+ Tokenizer::Html(ref mut tokenizer) => tokenizer.run(),
+ Tokenizer::Xml(ref mut tokenizer) => tokenizer.run(),
}
}
fn end(&mut self) {
match *self {
- Tokenizer::HTML(ref mut tokenizer) => tokenizer.end(),
- Tokenizer::XML(ref mut tokenizer) => tokenizer.end(),
+ Tokenizer::Html(ref mut tokenizer) => tokenizer.end(),
+ Tokenizer::Xml(ref mut tokenizer) => tokenizer.end(),
}
}
fn set_plaintext_state(&mut self) {
match *self {
- Tokenizer::HTML(ref mut tokenizer) => tokenizer.set_plaintext_state(),
- Tokenizer::XML(_) => { /* todo */ },
+ Tokenizer::Html(ref mut tokenizer) => tokenizer.set_plaintext_state(),
+ Tokenizer::Xml(_) => unimplemented!(),
}
}
fn profiler_category(&self) -> ProfilerCategory {
match *self {
- Tokenizer::HTML(_) => ProfilerCategory::ScriptParseHTML,
- Tokenizer::XML(_) => ProfilerCategory::ScriptParseXML,
- }
- }
-}
-
-impl JSTraceable for Tokenizer {
- fn trace(&self, trc: *mut JSTracer) {
- struct Tracer(*mut JSTracer);
- let tracer = Tracer(trc);
-
- match *self {
- Tokenizer::HTML(ref tokenizer) => {
- impl HtmlTracer for Tracer {
- type Handle = JS<Node>;
- #[allow(unrooted_must_root)]
- fn trace_handle(&self, node: &JS<Node>) {
- node.trace(self.0);
- }
- }
- let tree_builder = tokenizer.inner.sink();
- tree_builder.trace_handles(&tracer);
- tree_builder.sink().trace(trc);
- },
- Tokenizer::XML(ref tokenizer) => {
- impl XmlTracer for Tracer {
- type Handle = JS<Node>;
- #[allow(unrooted_must_root)]
- fn trace_handle(&self, node: JS<Node>) {
- node.trace(self.0);
- }
- }
- let tree_builder = tokenizer.sink();
- tree_builder.trace_handles(&tracer);
- tree_builder.sink().trace(trc);
- }
+ Tokenizer::Html(_) => ProfilerCategory::ScriptParseHTML,
+ Tokenizer::Xml(_) => ProfilerCategory::ScriptParseXML,
}
}
}
@@ -492,3 +481,8 @@ impl FetchResponseListener for ParserContext {
}
impl PreInvoke for ParserContext {}
+
+pub struct FragmentContext<'a> {
+ pub context_elem: &'a Node,
+ pub form_elem: Option<&'a Node>,
+}
diff --git a/components/script/dom/servoparser/xml.rs b/components/script/dom/servoparser/xml.rs
index 879bb9320d6..6f87d6a389c 100644
--- a/components/script/dom/servoparser/xml.rs
+++ b/components/script/dom/servoparser/xml.rs
@@ -8,6 +8,7 @@ use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{JS, Root};
use dom::bindings::str::DOMString;
+use dom::bindings::trace::JSTraceable;
use dom::comment::Comment;
use dom::document::Document;
use dom::documenttype::DocumentType;
@@ -16,15 +17,69 @@ use dom::htmlscriptelement::HTMLScriptElement;
use dom::node::Node;
use dom::processinginstruction::ProcessingInstruction;
use dom::text::Text;
-use html5ever;
use html5ever_atoms::{Prefix, QualName};
-use msg::constellation_msg::PipelineId;
+use js::jsapi::JSTracer;
use std::borrow::Cow;
-use super::{LastChunkState, ServoParser, Sink, Tokenizer};
+use super::Sink;
use url::Url;
use xml5ever::tendril::StrTendril;
use xml5ever::tokenizer::{Attribute, QName, XmlTokenizer};
-use xml5ever::tree_builder::{NextParserState, NodeOrText, TreeSink, XmlTreeBuilder};
+use xml5ever::tree_builder::{NextParserState, NodeOrText};
+use xml5ever::tree_builder::{Tracer as XmlTracer, TreeSink, XmlTreeBuilder};
+
+#[derive(HeapSizeOf, JSTraceable)]
+#[must_root]
+pub struct Tokenizer {
+ #[ignore_heap_size_of = "Defined in xml5ever"]
+ inner: XmlTokenizer<XmlTreeBuilder<JS<Node>, Sink>>,
+}
+
+impl Tokenizer {
+ pub fn new(document: &Document, url: Url) -> Self {
+ let sink = Sink {
+ base_url: url,
+ document: JS::from_ref(document),
+ };
+
+ let tb = XmlTreeBuilder::new(sink);
+ let tok = XmlTokenizer::new(tb, Default::default());
+
+ Tokenizer {
+ inner: tok,
+ }
+ }
+
+ pub fn feed(&mut self, input: String) {
+ self.inner.feed(input.into())
+ }
+
+ pub fn run(&mut self) {
+ self.inner.run()
+ }
+
+ pub fn end(&mut self) {
+ self.inner.end()
+ }
+}
+
+impl JSTraceable for XmlTokenizer<XmlTreeBuilder<JS<Node>, Sink>> {
+ fn trace(&self, trc: *mut JSTracer) {
+ struct Tracer(*mut JSTracer);
+ let tracer = Tracer(trc);
+
+ impl XmlTracer for Tracer {
+ type Handle = JS<Node>;
+ #[allow(unrooted_must_root)]
+ fn trace_handle(&self, node: JS<Node>) {
+ node.trace(self.0);
+ }
+ }
+
+ let tree_builder = self.sink();
+ tree_builder.trace_handles(&tracer);
+ tree_builder.sink().trace(trc);
+ }
+}
impl<'a> TreeSink for Sink {
type Handle = JS<Node>;
@@ -113,35 +168,10 @@ impl<'a> TreeSink for Sink {
let script = node.downcast::<HTMLScriptElement>();
if let Some(script) = script {
return match script.prepare() {
- html5ever::tree_builder::NextParserState::Continue => NextParserState::Continue,
- html5ever::tree_builder::NextParserState::Suspend => NextParserState::Suspend
+ true => NextParserState::Continue,
+ false => NextParserState::Suspend,
};
}
NextParserState::Continue
}
}
-
-
-pub enum ParseContext {
- Owner(Option<PipelineId>)
-}
-
-
-pub fn parse_xml(document: &Document,
- input: DOMString,
- url: Url,
- context: ParseContext) {
- let parser = match context {
- ParseContext::Owner(owner) => {
- let tb = XmlTreeBuilder::new(Sink {
- base_url: url,
- document: JS::from_ref(document),
- });
- let tok = XmlTokenizer::new(tb, Default::default());
-
- ServoParser::new(
- document, owner, Tokenizer::XML(tok), LastChunkState::NotReceived)
- }
- };
- parser.parse_chunk(String::from(input));
-}
diff --git a/components/script/dom/webidls/CSSStyleDeclaration.webidl b/components/script/dom/webidls/CSSStyleDeclaration.webidl
index c64ecd119c7..3424e5593a6 100644
--- a/components/script/dom/webidls/CSSStyleDeclaration.webidl
+++ b/components/script/dom/webidls/CSSStyleDeclaration.webidl
@@ -103,6 +103,39 @@ partial interface CSSStyleDeclaration {
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderTopWidth;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-top-width;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-block-start-color;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderBlockStartColor;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-block-start-width;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderBlockStartWidth;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-block-start-style;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderBlockStartStyle;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-block-end-color;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderBlockEndColor;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-block-end-width;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderBlockEndWidth;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-block-end-style;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderBlockEndStyle;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-inline-start-color;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderInlineStartColor;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-inline-start-width;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderInlineStartWidth;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-inline-start-style;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderInlineStartStyle;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-inline-end-color;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderInlineEndColor;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-inline-end-width;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderInlineEndWidth;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-inline-end-style;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderInlineEndStyle;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-block-start;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderBlockStart;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-block-end;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderBlockEnd;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-inline-start;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderInlineStart;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-inline-end;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderInlineEnd;
+
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString content;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString color;
@@ -242,6 +275,14 @@ partial interface CSSStyleDeclaration {
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString margin-right;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString marginTop;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString margin-top;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString margin-block-start;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString marginBlockStart;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString margin-block-end;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString marginBlockEnd;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString margin-inline-start;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString marginInlineStart;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString margin-inline-end;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString marginInlineEnd;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString padding;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString paddingBottom;
@@ -252,6 +293,14 @@ partial interface CSSStyleDeclaration {
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString padding-right;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString paddingTop;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString padding-top;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString padding-block-start;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString paddingBlockStart;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString padding-block-end;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString paddingBlockEnd;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString padding-inline-start;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString paddingInlineStart;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString padding-inline-end;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString paddingInlineEnd;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString outline;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString outlineColor;
@@ -284,6 +333,18 @@ partial interface CSSStyleDeclaration {
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString min-width;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString maxWidth;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString max-width;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString block-size;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString blockSize;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString inline-size;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString inlineSize;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString max-block-size;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString maxBlockSize;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString max-inline-size;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString maxInlineSize;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString min-block-size;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString minBlockSize;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString min-inline-size;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString minInlineSize;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString zIndex;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString z-index;
diff --git a/components/script/dom/webidls/EventSource.webidl b/components/script/dom/webidls/EventSource.webidl
index b9cf82d6a3e..11c30e959d4 100644
--- a/components/script/dom/webidls/EventSource.webidl
+++ b/components/script/dom/webidls/EventSource.webidl
@@ -7,8 +7,7 @@
*/
[Constructor(DOMString url, optional EventSourceInit eventSourceInitDict),
- Exposed=(Window,Worker),
- Pref="dom.eventsource.enabled"]
+ Exposed=(Window,Worker)]
interface EventSource : EventTarget {
readonly attribute DOMString url;
readonly attribute boolean withCredentials;
diff --git a/components/script/dom/webidls/Navigator.webidl b/components/script/dom/webidls/Navigator.webidl
index 0f32e3bdf1e..84d5a7c3ccb 100644
--- a/components/script/dom/webidls/Navigator.webidl
+++ b/components/script/dom/webidls/Navigator.webidl
@@ -7,7 +7,6 @@ interface Navigator {
// objects implementing this interface also implement the interfaces given below
};
Navigator implements NavigatorID;
-Navigator implements NavigatorBluetooth;
Navigator implements NavigatorLanguage;
//Navigator implements NavigatorOnLine;
//Navigator implements NavigatorContentUtils;
@@ -27,9 +26,9 @@ interface NavigatorID {
readonly attribute DOMString userAgent;
};
-[NoInterfaceObject]
-interface NavigatorBluetooth {
- readonly attribute Bluetooth bluetooth;
+// https://webbluetoothcg.github.io/web-bluetooth/#navigator-extensions
+partial interface Navigator {
+ readonly attribute Bluetooth bluetooth;
};
// https://w3c.github.io/ServiceWorker/#navigator-service-worker
diff --git a/components/script/dom/websocket.rs b/components/script/dom/websocket.rs
index dd49f62d247..1764db20764 100644
--- a/components/script/dom/websocket.rs
+++ b/components/script/dom/websocket.rs
@@ -33,14 +33,16 @@ use net_traits::CoreResourceMsg::{SetCookiesForUrl, WebsocketConnect};
use net_traits::MessageData;
use net_traits::hosts::replace_hosts;
use net_traits::unwrap_websocket_protocol;
-use script_runtime::{CommonScriptMsg, ScriptChan};
+use script_runtime::CommonScriptMsg;
use script_runtime::ScriptThreadEventCategory::WebSocketEvent;
-use script_thread::Runnable;
+use script_thread::{Runnable, RunnableWrapper};
use std::ascii::AsciiExt;
use std::borrow::ToOwned;
use std::cell::Cell;
use std::ptr;
use std::thread;
+use task_source::TaskSource;
+use task_source::networking::NetworkingTaskSource;
use websocket::client::request::Url;
use websocket::header::{Headers, WebSocketProtocol};
use websocket::ws::util::url::parse_url;
@@ -141,7 +143,8 @@ mod close_code {
}
pub fn close_the_websocket_connection(address: Trusted<WebSocket>,
- sender: Box<ScriptChan>,
+ task_source: &NetworkingTaskSource,
+ wrapper: &RunnableWrapper,
code: Option<u16>,
reason: String) {
let close_task = box CloseTask {
@@ -150,17 +153,19 @@ pub fn close_the_websocket_connection(address: Trusted<WebSocket>,
code: code,
reason: Some(reason),
};
- sender.send(CommonScriptMsg::RunnableMsg(WebSocketEvent, close_task)).unwrap();
+ task_source.queue_with_wrapper(close_task, &wrapper).unwrap();
}
-pub fn fail_the_websocket_connection(address: Trusted<WebSocket>, sender: Box<ScriptChan>) {
+pub fn fail_the_websocket_connection(address: Trusted<WebSocket>,
+ task_source: &NetworkingTaskSource,
+ wrapper: &RunnableWrapper) {
let close_task = box CloseTask {
address: address,
failed: true,
code: Some(close_code::ABNORMAL),
reason: None,
};
- sender.send(CommonScriptMsg::RunnableMsg(WebSocketEvent, close_task)).unwrap();
+ task_source.queue_with_wrapper(close_task, &wrapper).unwrap();
}
#[dom_struct]
@@ -268,7 +273,8 @@ impl WebSocket {
*ws.sender.borrow_mut() = Some(dom_action_sender);
let moved_address = address.clone();
- let sender = global.networking_task_source();
+ let task_source = global.networking_task_source();
+ let wrapper = global.get_runnable_wrapper();
thread::spawn(move || {
while let Ok(event) = dom_event_receiver.recv() {
match event {
@@ -278,20 +284,22 @@ impl WebSocket {
headers: headers,
protocols: protocols,
};
- sender.send(CommonScriptMsg::RunnableMsg(WebSocketEvent, open_thread)).unwrap();
+ task_source.queue_with_wrapper(open_thread, &wrapper).unwrap();
},
WebSocketNetworkEvent::MessageReceived(message) => {
let message_thread = box MessageReceivedTask {
address: moved_address.clone(),
message: message,
};
- sender.send(CommonScriptMsg::RunnableMsg(WebSocketEvent, message_thread)).unwrap();
+ task_source.queue_with_wrapper(message_thread, &wrapper).unwrap();
},
WebSocketNetworkEvent::Fail => {
- fail_the_websocket_connection(moved_address.clone(), sender.clone());
+ fail_the_websocket_connection(moved_address.clone(),
+ &task_source, &wrapper);
},
WebSocketNetworkEvent::Close(code, reason) => {
- close_the_websocket_connection(moved_address.clone(), sender.clone(), code, reason);
+ close_the_websocket_connection(moved_address.clone(),
+ &task_source, &wrapper, code, reason);
},
}
}
@@ -436,8 +444,8 @@ impl WebSocketMethods for WebSocket {
self.ready_state.set(WebSocketRequestState::Closing);
let address = Trusted::new(self);
- let sender = self.global().networking_task_source();
- fail_the_websocket_connection(address, sender);
+ let task_source = self.global().networking_task_source();
+ fail_the_websocket_connection(address, &task_source, &self.global().get_runnable_wrapper());
}
WebSocketRequestState::Open => {
self.ready_state.set(WebSocketRequestState::Closing);
@@ -470,8 +478,8 @@ impl Runnable for ConnectionEstablishedTask {
// Step 1: Protocols.
if !self.protocols.is_empty() && self.headers.get::<WebSocketProtocol>().is_none() {
- let sender = ws.global().networking_task_source();
- fail_the_websocket_connection(self.address, sender);
+ let task_source = ws.global().networking_task_source();
+ fail_the_websocket_connection(self.address, &task_source, &ws.global().get_runnable_wrapper());
return;
}
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index a78dcda8893..63485e45dfc 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -267,7 +267,7 @@ impl Window {
self.user_interaction_task_source.clone()
}
- pub fn networking_task_source(&self) -> Box<ScriptChan + Send> {
+ pub fn networking_task_source(&self) -> NetworkingTaskSource {
self.networking_task_source.clone()
}
diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs
index 2efa2920cb8..041ce8448de 100644
--- a/components/script/dom/workerglobalscope.rs
+++ b/components/script/dom/workerglobalscope.rs
@@ -41,6 +41,7 @@ use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::Receiver;
use task_source::file_reading::FileReadingTaskSource;
+use task_source::networking::NetworkingTaskSource;
use timers::{IsInterval, TimerCallback};
use url::Url;
@@ -361,6 +362,10 @@ impl WorkerGlobalScope {
FileReadingTaskSource(self.script_chan())
}
+ pub fn networking_task_source(&self) -> NetworkingTaskSource {
+ NetworkingTaskSource(self.script_chan())
+ }
+
pub fn new_script_pair(&self) -> (Box<ScriptChan + Send>, Box<ScriptPort + Send>) {
let dedicated = self.downcast::<DedicatedWorkerGlobalScope>();
if let Some(dedicated) = dedicated {
diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs
index c404c482308..57191d1d4e9 100644
--- a/components/script/dom/xmlhttprequest.rs
+++ b/components/script/dom/xmlhttprequest.rs
@@ -28,8 +28,7 @@ use dom::globalscope::GlobalScope;
use dom::headers::is_forbidden_header_name;
use dom::htmlformelement::{encode_multipart_form_data, generate_boundary};
use dom::progressevent::ProgressEvent;
-use dom::servoparser::html::{ParseContext, parse_html};
-use dom::servoparser::xml::{self, parse_xml};
+use dom::servoparser::ServoParser;
use dom::window::Window;
use dom::workerglobalscope::WorkerGlobalScope;
use dom::xmlhttprequesteventtarget::XMLHttpRequestEventTarget;
@@ -49,13 +48,12 @@ use js::jsapi::{JSContext, JS_ParseJSON};
use js::jsapi::JS_ClearPendingException;
use js::jsval::{JSVal, NullValue, UndefinedValue};
use msg::constellation_msg::PipelineId;
-use net_traits::{CoreResourceThread, FetchMetadata, FilteredMetadata};
+use net_traits::{FetchMetadata, FilteredMetadata};
use net_traits::{FetchResponseListener, LoadOrigin, NetworkError, ReferrerPolicy};
use net_traits::CoreResourceMsg::Fetch;
use net_traits::request::{CredentialsMode, Destination, RequestInit, RequestMode};
use net_traits::trim_http_whitespace;
use network_listener::{NetworkListener, PreInvoke};
-use script_runtime::ScriptChan;
use servo_atoms::Atom;
use std::ascii::AsciiExt;
use std::borrow::ToOwned;
@@ -63,6 +61,7 @@ use std::cell::Cell;
use std::default::Default;
use std::str;
use std::sync::{Arc, Mutex};
+use task_source::networking::NetworkingTaskSource;
use time;
use timers::{OneshotTimerCallback, OneshotTimerHandle};
use url::{Position, Url};
@@ -214,8 +213,8 @@ impl XMLHttpRequest {
}
fn initiate_async_xhr(context: Arc<Mutex<XHRContext>>,
- script_chan: Box<ScriptChan + Send>,
- core_resource_thread: CoreResourceThread,
+ task_source: NetworkingTaskSource,
+ global: &GlobalScope,
init: RequestInit) {
impl FetchResponseListener for XHRContext {
fn process_request_body(&mut self) {
@@ -262,13 +261,13 @@ impl XMLHttpRequest {
let (action_sender, action_receiver) = ipc::channel().unwrap();
let listener = NetworkListener {
context: context,
- script_chan: script_chan,
- wrapper: None,
+ task_source: task_source,
+ wrapper: Some(global.get_runnable_wrapper())
};
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
listener.notify_fetch(message.to().unwrap());
});
- core_resource_thread.send(Fetch(init, action_sender)).unwrap();
+ global.core_resource_thread().send(Fetch(init, action_sender)).unwrap();
}
}
@@ -590,7 +589,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
// https://github.com/whatwg/xhr/issues/71
destination: Destination::None,
synchronous: self.sync.get(),
- mode: RequestMode::CORSMode,
+ mode: RequestMode::CorsMode,
use_cors_preflight: has_handlers,
credentials_mode: credentials_mode,
use_url_credentials: use_url_credentials,
@@ -1199,10 +1198,11 @@ impl XMLHttpRequest {
let decoded = charset.decode(&self.response.borrow(), DecoderTrap::Replace).unwrap();
let document = self.new_doc(IsHTMLDocument::HTMLDocument);
// TODO: Disable scripting while parsing
- parse_html(&document,
- DOMString::from(decoded),
- wr.get_url(),
- ParseContext::Owner(Some(wr.pipeline_id())));
+ ServoParser::parse_html_document(
+ &document,
+ DOMString::from(decoded),
+ wr.get_url(),
+ Some(wr.pipeline_id()));
document
}
@@ -1212,10 +1212,11 @@ impl XMLHttpRequest {
let decoded = charset.decode(&self.response.borrow(), DecoderTrap::Replace).unwrap();
let document = self.new_doc(IsHTMLDocument::NonHTMLDocument);
// TODO: Disable scripting while parsing
- parse_xml(&document,
- DOMString::from(decoded),
- wr.get_url(),
- xml::ParseContext::Owner(Some(wr.pipeline_id())));
+ ServoParser::parse_xml_document(
+ &document,
+ DOMString::from(decoded),
+ wr.get_url(),
+ Some(wr.pipeline_id()));
document
}
@@ -1293,16 +1294,15 @@ impl XMLHttpRequest {
sync_status: DOMRefCell::new(None),
}));
- let (script_chan, script_port) = if self.sync.get() {
+ let (task_source, script_port) = if self.sync.get() {
let (tx, rx) = global.new_script_pair();
- (tx, Some(rx))
+ (NetworkingTaskSource(tx), Some(rx))
} else {
(global.networking_task_source(), None)
};
- let core_resource_thread = global.core_resource_thread();
- XMLHttpRequest::initiate_async_xhr(context.clone(), script_chan,
- core_resource_thread, init);
+ XMLHttpRequest::initiate_async_xhr(context.clone(), task_source,
+ global, init);
if let Some(script_port) = script_port {
loop {
diff --git a/components/script/fetch.rs b/components/script/fetch.rs
index ed1a66fc683..740099344bf 100644
--- a/components/script/fetch.rs
+++ b/components/script/fetch.rs
@@ -2,10 +2,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+use dom::bindings::codegen::Bindings::RequestBinding::RequestInfo;
use dom::bindings::codegen::Bindings::RequestBinding::RequestInit;
use dom::bindings::codegen::Bindings::ResponseBinding::ResponseBinding::ResponseMethods;
use dom::bindings::codegen::Bindings::ResponseBinding::ResponseType as DOMResponseType;
-use dom::bindings::codegen::UnionTypes::RequestOrUSVString;
use dom::bindings::error::Error;
use dom::bindings::js::Root;
use dom::bindings::refcounted::{Trusted, TrustedPromise};
@@ -62,12 +62,13 @@ fn request_init_from_request(request: NetTraitsRequest) -> NetTraitsRequestInit
referrer_policy: request.referrer_policy.get(),
pipeline_id: request.pipeline_id.get(),
redirect_mode: request.redirect_mode.get(),
+ ..NetTraitsRequestInit::default()
}
}
// https://fetch.spec.whatwg.org/#fetch-method
#[allow(unrooted_must_root)]
-pub fn Fetch(global: &GlobalScope, input: RequestOrUSVString, init: &RequestInit) -> Rc<Promise> {
+pub fn Fetch(global: &GlobalScope, input: RequestInfo, init: &RequestInit) -> Rc<Promise> {
let core_resource_thread = global.core_resource_thread();
// Step 1
@@ -96,8 +97,8 @@ pub fn Fetch(global: &GlobalScope, input: RequestOrUSVString, init: &RequestInit
}));
let listener = NetworkListener {
context: fetch_context,
- script_chan: global.networking_task_source(),
- wrapper: None,
+ task_source: global.networking_task_source(),
+ wrapper: Some(global.get_runnable_wrapper())
};
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
diff --git a/components/script/lib.rs b/components/script/lib.rs
index 94e9683ffaf..ed3283868d5 100644
--- a/components/script/lib.rs
+++ b/components/script/lib.rs
@@ -48,6 +48,7 @@ extern crate heapsize;
#[macro_use] extern crate heapsize_derive;
extern crate html5ever;
#[macro_use] extern crate html5ever_atoms;
+#[macro_use]
extern crate hyper;
extern crate hyper_serde;
extern crate image;
@@ -163,15 +164,17 @@ fn perform_platform_specific_initialization() {
#[cfg(not(target_os = "linux"))]
fn perform_platform_specific_initialization() {}
+pub fn init_service_workers(sw_senders: SWManagerSenders) {
+ // Spawn the service worker manager passing the constellation sender
+ ServiceWorkerManager::spawn_manager(sw_senders);
+}
+
#[allow(unsafe_code)]
-pub fn init(sw_senders: SWManagerSenders) {
+pub fn init() {
unsafe {
proxyhandler::init();
}
- // Spawn the service worker manager passing the constellation sender
- ServiceWorkerManager::spawn_manager(sw_senders);
-
// Create the global vtables used by the (generated) DOM
// bindings to implement JS proxies.
RegisterBindings::RegisterProxyHandlers();
diff --git a/components/script/network_listener.rs b/components/script/network_listener.rs
index cd0158409f1..5a96317fb18 100644
--- a/components/script/network_listener.rs
+++ b/components/script/network_listener.rs
@@ -4,16 +4,16 @@
use bluetooth_traits::{BluetoothResponseListener, BluetoothResponseResult};
use net_traits::{Action, FetchResponseListener, FetchResponseMsg};
-use script_runtime::{CommonScriptMsg, ScriptChan};
-use script_runtime::ScriptThreadEventCategory::NetworkEvent;
use script_thread::{Runnable, RunnableWrapper};
use std::sync::{Arc, Mutex};
+use task_source::TaskSource;
+use task_source::networking::NetworkingTaskSource;
/// An off-thread sink for async network event runnables. All such events are forwarded to
/// a target thread, where they are invoked on the provided context object.
pub struct NetworkListener<Listener: PreInvoke + Send + 'static> {
pub context: Arc<Mutex<Listener>>,
- pub script_chan: Box<ScriptChan + Send>,
+ pub task_source: NetworkingTaskSource,
pub wrapper: Option<RunnableWrapper>,
}
@@ -24,9 +24,9 @@ impl<Listener: PreInvoke + Send + 'static> NetworkListener<Listener> {
action: action,
};
let result = if let Some(ref wrapper) = self.wrapper {
- self.script_chan.send(CommonScriptMsg::RunnableMsg(NetworkEvent, wrapper.wrap_runnable(runnable)))
+ self.task_source.queue_with_wrapper(runnable, wrapper)
} else {
- self.script_chan.send(CommonScriptMsg::RunnableMsg(NetworkEvent, runnable))
+ self.task_source.queue_wrapperless(runnable)
};
if let Err(err) = result {
warn!("failed to deliver network data: {:?}", err);
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index cccfbda842d..7dfe41dac20 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -51,8 +51,6 @@ use dom::node::{Node, NodeDamage, window_from_node};
use dom::serviceworker::TrustedServiceWorkerAddress;
use dom::serviceworkerregistration::ServiceWorkerRegistration;
use dom::servoparser::{ParserContext, ServoParser};
-use dom::servoparser::html::{ParseContext, parse_html};
-use dom::servoparser::xml::{self, parse_xml};
use dom::transitionevent::TransitionEvent;
use dom::uievent::UIEvent;
use dom::window::{ReflowReason, Window};
@@ -659,7 +657,7 @@ impl ScriptThread {
chan: MainThreadScriptChan(chan.clone()),
dom_manipulation_task_source: DOMManipulationTaskSource(chan.clone()),
user_interaction_task_source: UserInteractionTaskSource(chan.clone()),
- networking_task_source: NetworkingTaskSource(chan.clone()),
+ networking_task_source: NetworkingTaskSource(boxed_script_sender.clone()),
history_traversal_task_source: HistoryTraversalTaskSource(chan),
file_reading_task_source: FileReadingTaskSource(boxed_script_sender),
@@ -1623,7 +1621,6 @@ impl ScriptThread {
let MainThreadScriptChan(ref sender) = self.chan;
let DOMManipulationTaskSource(ref dom_sender) = self.dom_manipulation_task_source;
let UserInteractionTaskSource(ref user_sender) = self.user_interaction_task_source;
- let NetworkingTaskSource(ref network_sender) = self.networking_task_source;
let HistoryTraversalTaskSource(ref history_sender) = self.history_traversal_task_source;
let (ipc_timer_event_chan, ipc_timer_event_port) = ipc::channel().unwrap();
@@ -1635,7 +1632,7 @@ impl ScriptThread {
MainThreadScriptChan(sender.clone()),
DOMManipulationTaskSource(dom_sender.clone()),
UserInteractionTaskSource(user_sender.clone()),
- NetworkingTaskSource(network_sender.clone()),
+ self.networking_task_source.clone(),
HistoryTraversalTaskSource(history_sender.clone()),
self.file_reading_task_source.clone(),
self.image_cache_channel.clone(),
@@ -1780,15 +1777,17 @@ impl ScriptThread {
};
if is_xml {
- parse_xml(&document,
- parse_input,
- final_url,
- xml::ParseContext::Owner(Some(incomplete.pipeline_id)));
+ ServoParser::parse_xml_document(
+ &document,
+ parse_input,
+ final_url,
+ Some(incomplete.pipeline_id));
} else {
- parse_html(&document,
- parse_input,
- final_url,
- ParseContext::Owner(Some(incomplete.pipeline_id)));
+ ServoParser::parse_html_document(
+ &document,
+ parse_input,
+ final_url,
+ Some(incomplete.pipeline_id));
}
if incomplete.is_frozen {
@@ -2050,7 +2049,7 @@ impl ScriptThread {
let (action_sender, action_receiver) = ipc::channel().unwrap();
let listener = NetworkListener {
context: context,
- script_chan: self.chan.clone(),
+ task_source: self.networking_task_source.clone(),
wrapper: None,
};
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
diff --git a/components/script/task_source/networking.rs b/components/script/task_source/networking.rs
index 4f85ac6c3e6..8306a4789bb 100644
--- a/components/script/task_source/networking.rs
+++ b/components/script/task_source/networking.rs
@@ -2,19 +2,32 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-use script_runtime::{CommonScriptMsg, ScriptChan};
-use script_thread::MainThreadScriptMsg;
-use std::sync::mpsc::Sender;
+use script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory};
+use script_thread::{Runnable, RunnableWrapper};
+use task_source::TaskSource;
#[derive(JSTraceable)]
-pub struct NetworkingTaskSource(pub Sender<MainThreadScriptMsg>);
+pub struct NetworkingTaskSource(pub Box<ScriptChan + Send + 'static>);
-impl ScriptChan for NetworkingTaskSource {
- fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> {
- self.0.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ())
+impl Clone for NetworkingTaskSource {
+ fn clone(&self) -> NetworkingTaskSource {
+ NetworkingTaskSource(self.0.clone())
}
+}
+
+impl TaskSource for NetworkingTaskSource {
+ fn queue_with_wrapper<T>(&self,
+ msg: Box<T>,
+ wrapper: &RunnableWrapper)
+ -> Result<(), ()>
+ where T: Runnable + Send + 'static {
+ self.0.send(CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::NetworkEvent,
+ wrapper.wrap_runnable(msg)))
+ }
+}
- fn clone(&self) -> Box<ScriptChan + Send> {
- box NetworkingTaskSource((&self.0).clone())
+impl NetworkingTaskSource {
+ pub fn queue_wrapperless<T: Runnable + Send + 'static>(&self, msg: Box<T>) -> Result<(), ()> {
+ self.0.send(CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::NetworkEvent, msg))
}
}
diff --git a/components/script/textinput.rs b/components/script/textinput.rs
index 25243d739ab..5f04b5b187e 100644
--- a/components/script/textinput.rs
+++ b/components/script/textinput.rs
@@ -544,7 +544,6 @@ impl<T: ClipboardProvider> TextInput<T> {
self.adjust_vertical(28, maybe_select);
KeyReaction::RedrawSelection
}
- (None, Key::Tab) => KeyReaction::TriggerDefaultAction,
_ => KeyReaction::Nothing,
}
}
diff --git a/components/script/timers.rs b/components/script/timers.rs
index 34ac02b6589..6b67d6959e3 100644
--- a/components/script/timers.rs
+++ b/components/script/timers.rs
@@ -7,6 +7,7 @@ use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::FunctionBinding::Function;
use dom::bindings::reflector::Reflectable;
use dom::bindings::str::DOMString;
+use dom::eventsource::EventSourceTimeoutCallback;
use dom::globalscope::GlobalScope;
use dom::testbinding::TestBindingCallback;
use dom::xmlhttprequest::XHRTimeoutCallback;
@@ -67,6 +68,7 @@ struct OneshotTimer {
#[derive(JSTraceable, HeapSizeOf)]
pub enum OneshotTimerCallback {
XhrTimeout(XHRTimeoutCallback),
+ EventSourceTimeout(EventSourceTimeoutCallback),
JsTimer(JsTimerTask),
TestBindingCallback(TestBindingCallback),
}
@@ -75,6 +77,7 @@ impl OneshotTimerCallback {
fn invoke<T: Reflectable>(self, this: &T, js_timers: &JsTimers) {
match self {
OneshotTimerCallback::XhrTimeout(callback) => callback.invoke(),
+ OneshotTimerCallback::EventSourceTimeout(callback) => callback.invoke(),
OneshotTimerCallback::JsTimer(task) => task.invoke(this, js_timers),
OneshotTimerCallback::TestBindingCallback(callback) => callback.invoke(),
}