diff options
55 files changed, 644 insertions, 591 deletions
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 256612f752f..92283558b9d 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -220,6 +220,9 @@ pub struct IOCompositor<Window: WindowMethods> { /// Pending scroll/zoom events. pending_scroll_zoom_events: Vec<ScrollZoomEvent>, + /// Whether we're waiting on a recomposite after dispatching a scroll. + waiting_for_results_of_scroll: bool, + /// Used by the logic that determines when it is safe to output an /// image for the reftest framework. ready_to_save_state: ReadyState, @@ -254,6 +257,8 @@ struct ScrollZoomEvent { cursor: TypedPoint2D<DevicePixel, i32>, /// The scroll event phase. phase: ScrollEventPhase, + /// The number of OS events that have been coalesced together into this one event. + event_count: u32, } #[derive(PartialEq, Debug)] @@ -398,6 +403,10 @@ impl webrender_traits::RenderNotifier for RenderNotifier { self.compositor_proxy.recomposite(CompositingReason::NewWebRenderFrame); } + fn new_scroll_frame_ready(&mut self, composite_needed: bool) { + self.compositor_proxy.send(Msg::NewScrollFrameReady(composite_needed)); + } + fn pipeline_size_changed(&mut self, pipeline_id: webrender_traits::PipelineId, size: Option<Size2D<f32>>) { @@ -468,6 +477,7 @@ impl<Window: WindowMethods> IOCompositor<Window> { composition_request: CompositionRequest::NoCompositingNecessary, touch_handler: TouchHandler::new(), pending_scroll_zoom_events: Vec::new(), + waiting_for_results_of_scroll: false, composite_target: composite_target, shutdown_state: ShutdownState::NotShuttingDown, page_zoom: ScaleFactor::new(1.0), @@ -677,7 +687,6 @@ impl<Window: WindowMethods> IOCompositor<Window> { } (Msg::DelayedCompositionTimeout(timestamp), ShutdownState::NotShuttingDown) => { - debug!("delayed composition timeout!"); if let CompositionRequest::DelayedComposite(this_timestamp) = self.composition_request { if timestamp == this_timestamp { @@ -789,6 +798,14 @@ impl<Window: WindowMethods> IOCompositor<Window> { } } + (Msg::NewScrollFrameReady(recomposite_needed), ShutdownState::NotShuttingDown) => { + self.waiting_for_results_of_scroll = false; + if recomposite_needed { + self.composition_request = CompositionRequest::CompositeNow( + CompositingReason::NewWebRenderScrollFrame); + } + } + // When we are shutting_down, we need to avoid performing operations // such as Paint that may crash because we have begun tearing down // the rest of our resources. @@ -1186,8 +1203,8 @@ impl<Window: WindowMethods> IOCompositor<Window> { fn schedule_delayed_composite_if_necessary(&mut self) { match self.composition_request { - CompositionRequest::CompositeNow(_) | - CompositionRequest::DelayedComposite(_) => return, + CompositionRequest::CompositeNow(_) => return, + CompositionRequest::DelayedComposite(_) | CompositionRequest::NoCompositingNecessary => {} } @@ -1509,6 +1526,7 @@ impl<Window: WindowMethods> IOCompositor<Window> { delta: scroll_delta, cursor: cursor, phase: ScrollEventPhase::Move(true), + event_count: 1, }); self.composite_if_necessary_if_not_using_webrender(CompositingReason::Zoom); } @@ -1563,6 +1581,7 @@ impl<Window: WindowMethods> IOCompositor<Window> { delta: delta, cursor: cursor, phase: ScrollEventPhase::Move(self.scroll_in_progress), + event_count: 1, }); self.composite_if_necessary_if_not_using_webrender(CompositingReason::Scroll); } @@ -1576,6 +1595,7 @@ impl<Window: WindowMethods> IOCompositor<Window> { delta: delta, cursor: cursor, phase: ScrollEventPhase::Start, + event_count: 1, }); self.composite_if_necessary_if_not_using_webrender(CompositingReason::Scroll); } @@ -1589,6 +1609,7 @@ impl<Window: WindowMethods> IOCompositor<Window> { delta: delta, cursor: cursor, phase: ScrollEventPhase::End, + event_count: 1, }); self.composite_if_necessary_if_not_using_webrender(CompositingReason::Scroll); } @@ -1605,35 +1626,52 @@ impl<Window: WindowMethods> IOCompositor<Window> { let this_cursor = scroll_event.cursor; if let Some(combined_event) = last_combined_event { if combined_event.phase != scroll_event.phase { - webrender_api.scroll( - (combined_event.delta / self.scene.scale).to_untyped(), - (combined_event.cursor.as_f32() / self.scene.scale).to_untyped(), - combined_event.phase); + let delta = (combined_event.delta / self.scene.scale).to_untyped(); + let cursor = (combined_event.cursor.as_f32() / + self.scene.scale).to_untyped(); + webrender_api.scroll(delta, cursor, combined_event.phase); last_combined_event = None } } - match last_combined_event { - None => { - last_combined_event = Some(ScrollZoomEvent { + match (&mut last_combined_event, scroll_event.phase) { + (last_combined_event @ &mut None, _) => { + *last_combined_event = Some(ScrollZoomEvent { magnification: scroll_event.magnification, delta: this_delta, cursor: this_cursor, phase: scroll_event.phase, + event_count: 1, }) } - Some(ref mut last_combined_event) => { + (&mut Some(ref mut last_combined_event), + ScrollEventPhase::Move(false)) => { + // Mac OS X sometimes delivers scroll events out of vsync during a + // fling. This causes events to get bunched up occasionally, causing + // nasty-looking "pops". To mitigate this, during a fling we average + // deltas instead of summing them. + let old_event_count = + ScaleFactor::new(last_combined_event.event_count as f32); + last_combined_event.event_count += 1; + let new_event_count = + ScaleFactor::new(last_combined_event.event_count as f32); + last_combined_event.delta = + (last_combined_event.delta * old_event_count + this_delta) / + new_event_count; + } + (&mut Some(ref mut last_combined_event), _) => { last_combined_event.delta = last_combined_event.delta + this_delta; + last_combined_event.event_count += 1 } } } // TODO(gw): Support zoom (WR issue #28). if let Some(combined_event) = last_combined_event { - webrender_api.scroll( - (combined_event.delta / self.scene.scale).to_untyped(), - (combined_event.cursor.as_f32() / self.scene.scale).to_untyped(), - combined_event.phase); + let delta = (combined_event.delta / self.scene.scale).to_untyped(); + let cursor = (combined_event.cursor.as_f32() / self.scene.scale).to_untyped(); + webrender_api.scroll(delta, cursor, combined_event.phase); + self.waiting_for_results_of_scroll = true } } None => { @@ -1815,6 +1853,7 @@ impl<Window: WindowMethods> IOCompositor<Window> { delta: Point2D::typed(0.0, 0.0), // TODO: Scroll to keep the center in view? cursor: Point2D::typed(-1, -1), // Make sure this hits the base layer. phase: ScrollEventPhase::Move(true), + event_count: 1, }); self.composite_if_necessary_if_not_using_webrender(CompositingReason::Zoom); } @@ -2281,6 +2320,7 @@ impl<Window: WindowMethods> IOCompositor<Window> { self.process_animations(); self.start_scrolling_bounce_if_necessary(); + self.waiting_for_results_of_scroll = false; Ok(rv) } @@ -2515,7 +2555,27 @@ impl<Window: WindowMethods> IOCompositor<Window> { pub fn handle_events(&mut self, messages: Vec<WindowEvent>) -> bool { // Check for new messages coming from the other threads in the system. + let mut compositor_messages = vec![]; + let mut found_recomposite_msg = false; while let Some(msg) = self.port.try_recv_compositor_msg() { + match msg { + Msg::Recomposite(_) if found_recomposite_msg => {} + Msg::Recomposite(_) => { + found_recomposite_msg = true; + compositor_messages.push(msg) + } + _ => compositor_messages.push(msg), + } + } + if found_recomposite_msg { + compositor_messages.retain(|msg| { + match *msg { + Msg::DelayedCompositionTimeout(_) => false, + _ => true, + } + }) + } + for msg in compositor_messages { if !self.handle_browser_message(msg) { break } @@ -2537,10 +2597,6 @@ impl<Window: WindowMethods> IOCompositor<Window> { self.send_buffer_requests_for_all_layers(); } - if !self.pending_scroll_zoom_events.is_empty() && opts::get().use_webrender { - self.process_pending_scroll_events() - } - match self.composition_request { CompositionRequest::NoCompositingNecessary | CompositionRequest::DelayedComposite(_) => {} @@ -2549,6 +2605,11 @@ impl<Window: WindowMethods> IOCompositor<Window> { } } + if !self.pending_scroll_zoom_events.is_empty() && !self.waiting_for_results_of_scroll && + opts::get().use_webrender { + self.process_pending_scroll_events() + } + self.shutdown_state != ShutdownState::FinishedShuttingDown } @@ -2650,4 +2711,6 @@ pub enum CompositingReason { Zoom, /// A new WebRender frame has arrived. NewWebRenderFrame, + /// WebRender has processed a scroll event and has generated a new frame. + NewWebRenderScrollFrame, } diff --git a/components/compositing/compositor_thread.rs b/components/compositing/compositor_thread.rs index d29235858b8..24b9caba0a7 100644 --- a/components/compositing/compositor_thread.rs +++ b/components/compositing/compositor_thread.rs @@ -185,6 +185,9 @@ pub enum Msg { GetScrollOffset(PipelineId, LayerId, IpcSender<Point2D<f32>>), /// Pipeline visibility changed PipelineVisibilityChanged(PipelineId, bool), + /// WebRender has successfully processed a scroll. The boolean specifies whether a composite is + /// needed. + NewScrollFrameReady(bool), /// A pipeline was shut down. // This message acts as a synchronization point between the constellation, // when it shuts down a pipeline, to the compositor; when the compositor @@ -228,6 +231,7 @@ impl Debug for Msg { Msg::PipelineVisibilityChanged(..) => write!(f, "PipelineVisibilityChanged"), Msg::PipelineExited(..) => write!(f, "PipelineExited"), Msg::GetScrollOffset(..) => write!(f, "GetScrollOffset"), + Msg::NewScrollFrameReady(..) => write!(f, "NewScrollFrameReady"), } } } diff --git a/components/compositing/delayed_composition.rs b/components/compositing/delayed_composition.rs index c2ae4b86fa9..36c0306011a 100644 --- a/components/compositing/delayed_composition.rs +++ b/components/compositing/delayed_composition.rs @@ -10,8 +10,9 @@ use compositor_thread::{CompositorProxy, Msg}; use std::sync::mpsc::{Receiver, Sender, channel}; use std::thread::{self, Builder}; +use std::time::Duration; +use std::u32; use time; -use util::time::duration_from_nanoseconds; /// The amount of time in nanoseconds that we give to the painting thread to paint. When this /// expires, we give up and composite anyway. @@ -92,3 +93,15 @@ impl DelayedCompositionTimer { } } +fn duration_from_nanoseconds(nanos: u64) -> Duration { + pub const NANOS_PER_SEC: u32 = 1_000_000_000; + + // Get number of seconds. + let secs = nanos / NANOS_PER_SEC as u64; + + // Get number of extra nanoseconds. This should always fit in a u32, but check anyway. + let subsec_nanos = nanos % NANOS_PER_SEC as u64; + assert!(subsec_nanos <= u32::MAX as u64); + + Duration::new(secs, subsec_nanos as u32) +} diff --git a/components/layout/construct.rs b/components/layout/construct.rs index c7dcf0126c3..2b1b2f49cdc 100644 --- a/components/layout/construct.rs +++ b/components/layout/construct.rs @@ -30,6 +30,7 @@ use fragment::{InlineBlockFragmentInfo, SpecificFragmentInfo, UnscannedTextFragm use gfx::display_list::OpaqueNode; use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, InlineFragmentNodeFlags}; use inline::{InlineFragmentNodeInfo, LAST_FRAGMENT_OF_ELEMENT}; +use linked_list::prepend_from; use list_item::{ListItemFlow, ListStyleTypeContent}; use multicol::{MulticolFlow, MulticolColumnFlow}; use parallel; @@ -57,7 +58,6 @@ use table_wrapper::TableWrapperFlow; use text::TextRunScanner; use traversal::PostorderNodeMutTraversal; use url::Url; -use util::linked_list; use util::opts; use wrapper::{TextContent, ThreadSafeLayoutNodeHelpers}; @@ -1805,8 +1805,7 @@ pub fn strip_ignorable_whitespace_from_start(this: &mut LinkedList<Fragment>) { } } } - linked_list::prepend_from(this, - &mut leading_fragments_consisting_of_solely_bidi_control_characters); + prepend_from(this, &mut leading_fragments_consisting_of_solely_bidi_control_characters); } /// Strips ignorable whitespace from the end of a list of fragments. diff --git a/components/layout/lib.rs b/components/layout/lib.rs index e747993dd84..f05b21c3628 100644 --- a/components/layout/lib.rs +++ b/components/layout/lib.rs @@ -75,6 +75,7 @@ mod fragment; mod generated_content; pub mod incremental; mod inline; +mod linked_list; mod list_item; mod model; mod multicol; diff --git a/components/util/linked_list.rs b/components/layout/linked_list.rs index 5114f02c0e4..5114f02c0e4 100644 --- a/components/util/linked_list.rs +++ b/components/layout/linked_list.rs diff --git a/components/layout/text.rs b/components/layout/text.rs index 472ef9fcd50..250ad9d5e73 100644 --- a/components/layout/text.rs +++ b/components/layout/text.rs @@ -16,6 +16,7 @@ use gfx::text::glyph::ByteIndex; use gfx::text::text_run::TextRun; use gfx::text::util::{self, CompressionMode}; use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFragments, LAST_FRAGMENT_OF_ELEMENT}; +use linked_list::split_off_head; use range::Range; use std::borrow::ToOwned; use std::collections::LinkedList; @@ -28,7 +29,6 @@ use style::properties::style_structs::ServoFont; use style::properties::{ComputedValues, ServoComputedValues}; use unicode_bidi::{is_rtl, process_text}; use unicode_script::{get_script, Script}; -use util::linked_list::split_off_head; /// Returns the concatenated text of a list of unscanned text fragments. fn text(fragments: &LinkedList<Fragment>) -> String { diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index 8b147955569..bcb0373ab20 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -774,7 +774,7 @@ impl LayoutThread { traversal.shutdown() } - self.paint_chan.send(LayoutToPaintMsg::Exit).unwrap(); + let _ = self.paint_chan.send(LayoutToPaintMsg::Exit); } fn handle_add_stylesheet<'a, 'b>(&self, diff --git a/components/net/connector.rs b/components/net/connector.rs index 23aaf9f5566..59858947930 100644 --- a/components/net/connector.rs +++ b/components/net/connector.rs @@ -4,7 +4,7 @@ use hyper::client::Pool; use hyper::net::{HttpStream, HttpsConnector, SslClient}; -use openssl::ssl::{SSL_OP_NO_SSLV2, SSL_OP_NO_SSLV3, SSL_VERIFY_PEER}; +use openssl::ssl::{SSL_OP_NO_COMPRESSION, SSL_OP_NO_SSLV2, SSL_OP_NO_SSLV3, SSL_VERIFY_PEER}; use openssl::ssl::{Ssl, SslContext, SslMethod, SslStream}; use std::sync::Arc; use util::resource_files::resources_dir_path; @@ -31,7 +31,7 @@ pub fn create_http_connector() -> Arc<Pool<Connector>> { let mut context = SslContext::new(SslMethod::Sslv23).unwrap(); context.set_CA_file(&resources_dir_path().join("certs")).unwrap(); context.set_cipher_list(DEFAULT_CIPHERS).unwrap(); - context.set_options(SSL_OP_NO_SSLV2 | SSL_OP_NO_SSLV3); + context.set_options(SSL_OP_NO_SSLV2 | SSL_OP_NO_SSLV3 | SSL_OP_NO_COMPRESSION); let connector = HttpsConnector::new(ServoSslClient { context: Arc::new(context) }); diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs index 2855e38bf45..593ae3e1ead 100644 --- a/components/net/http_loader.rs +++ b/components/net/http_loader.rs @@ -33,6 +33,7 @@ use net_traits::hosts::replace_hosts; use net_traits::response::HttpsState; use net_traits::{CookieSource, IncludeSubdomains, LoadConsumer, LoadContext, LoadData}; use net_traits::{Metadata, NetworkError, RequestSource, CustomResponse}; +use openssl; use openssl::ssl::error::{SslError, OpensslError}; use profile_traits::time::{ProfilerCategory, profile, ProfilerChan, TimerMetadata}; use profile_traits::time::{TimerMetadataReflowType, TimerMetadataFrameType}; @@ -143,8 +144,8 @@ fn load_for_consumer(load_data: LoadData, Err(error) => { match error.error { LoadErrorType::ConnectionAborted { .. } => unreachable!(), - LoadErrorType::Ssl { .. } => send_error(error.url.clone(), - NetworkError::SslValidation(error.url), + LoadErrorType::Ssl { reason } => send_error(error.url.clone(), + NetworkError::SslValidation(error.url, reason), start_chan), LoadErrorType::Cancelled => send_error(error.url, NetworkError::LoadCancelled, start_chan), _ => send_error(error.url, NetworkError::Internal(error.error.description().to_owned()), start_chan) @@ -259,8 +260,21 @@ impl HttpRequestFactory for NetworkHttpRequestFactory { let error: &(Error + Send + 'static) = &**error; if let Some(&SslError::OpenSslErrors(ref errors)) = error.downcast_ref::<SslError>() { if errors.iter().any(is_cert_verify_error) { - let msg = format!("ssl error: {:?} {:?}", error.description(), error.cause()); - return Err(LoadError::new(url, LoadErrorType::Ssl { reason: msg })); + let mut error_report = vec![format!("ssl error ({}):", openssl::version::version())]; + let mut suggestion = None; + for err in errors { + if is_unknown_message_digest_err(err) { + suggestion = Some("<b>Servo recommends upgrading to a newer OpenSSL version.</b>"); + } + error_report.push(format_ssl_error(err)); + } + + if let Some(suggestion) = suggestion { + error_report.push(suggestion.to_owned()); + } + + let error_report = error_report.join("<br>\n"); + return Err(LoadError::new(url, LoadErrorType::Ssl { reason: error_report })); } } } @@ -1126,6 +1140,24 @@ fn is_cert_verify_error(error: &OpensslError) -> bool { } } +fn is_unknown_message_digest_err(error: &OpensslError) -> bool { + match error { + &OpensslError::UnknownError { ref library, ref function, ref reason } => { + library == "asn1 encoding routines" && + function == "ASN1_item_verify" && + reason == "unknown message digest algorithm" + } + } +} + +fn format_ssl_error(error: &OpensslError) -> String { + match error { + &OpensslError::UnknownError { ref library, ref function, ref reason } => { + format!("{}: {} - {}", library, function, reason) + } + } +} + fn to_resource_type(context: &LoadContext) -> ResourceType { match *context { LoadContext::Browsing => ResourceType::Document, diff --git a/components/net/resource_thread.rs b/components/net/resource_thread.rs index 6825437e162..4cb046566af 100644 --- a/components/net/resource_thread.rs +++ b/components/net/resource_thread.rs @@ -158,8 +158,8 @@ fn start_sending_opt(start_chan: LoadConsumer, metadata: Metadata, } LoadConsumer::Listener(target) => { match network_error { - Some(NetworkError::SslValidation(url)) => { - let error = NetworkError::SslValidation(url); + Some(NetworkError::SslValidation(url, reason)) => { + let error = NetworkError::SslValidation(url, reason); target.invoke_with_listener(ResponseAction::HeadersAvailable(Err(error))); } _ => target.invoke_with_listener(ResponseAction::HeadersAvailable(Ok(metadata))), diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs index bb9e31ad160..d4da6d0d058 100644 --- a/components/net_traits/lib.rs +++ b/components/net_traits/lib.rs @@ -667,7 +667,7 @@ pub enum NetworkError { Internal(String), LoadCancelled, /// SSL validation error that has to be handled in the HTML parser - SslValidation(Url), + SslValidation(Url, String), } /// Normalize `slice`, as defined by diff --git a/components/profile/mem.rs b/components/profile/mem.rs index 297584891c2..d1d2ca26b20 100644 --- a/components/profile/mem.rs +++ b/components/profile/mem.rs @@ -12,8 +12,8 @@ use std::borrow::ToOwned; use std::cmp::Ordering; use std::collections::HashMap; use std::thread; +use time::duration_from_seconds; use util::thread::spawn_named; -use util::time::duration_from_seconds; pub struct Profiler { /// The port through which messages are received. diff --git a/components/profile/time.rs b/components/profile/time.rs index 9c310fe9270..9c9debdb738 100644 --- a/components/profile/time.rs +++ b/components/profile/time.rs @@ -19,12 +19,11 @@ use std::io::{self, Write}; use std::path; use std::path::Path; use std::time::Duration; -use std::{thread, f64}; +use std::{f64, thread, u32, u64}; use std_time::precise_time_ns; use trace_dump::TraceDump; use util::opts::OutputOptions; use util::thread::spawn_named; -use util::time::duration_from_seconds; pub trait Formattable { fn format(&self, output: &Option<OutputOptions>) -> String; @@ -408,3 +407,17 @@ fn enforce_range<T>(min: T, max: T, value: T) -> T where T: Ord { }, } } + +pub fn duration_from_seconds(secs: f64) -> Duration { + pub const NANOS_PER_SEC: u32 = 1_000_000_000; + + // Get number of seconds and check that it fits in a u64. + let whole_secs = secs.trunc(); + assert!(whole_secs >= 0.0 && whole_secs <= u64::MAX as f64); + + // Get number of nanoseconds. This should always fit in a u32, but check anyway. + let nanos = (secs.fract() * (NANOS_PER_SEC as f64)).trunc(); + assert!(nanos >= 0.0 && nanos <= u32::MAX as f64); + + Duration::new(whole_secs as u64, nanos as u32) +} diff --git a/components/script/document_loader.rs b/components/script/document_loader.rs index 82e015eef80..a68038572f2 100644 --- a/components/script/document_loader.rs +++ b/components/script/document_loader.rs @@ -86,7 +86,7 @@ impl LoadBlocker { impl Drop for LoadBlocker { fn drop(&mut self) { if !thread::panicking() { - assert!(self.load.is_none()); + debug_assert!(self.load.is_none()); } } } diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index 71edf5c7abb..6c3b008bfc8 100644 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -302,6 +302,14 @@ impl HTMLInputElementMethods for HTMLInputElement { self.form_owner() } + // https://html.spec.whatwg.org/multipage/#dom-input-files + fn GetFiles(&self) -> Option<Root<FileList>> { + match self.filelist.get() { + Some(ref fl) => Some(fl.clone()), + None => None, + } + } + // https://html.spec.whatwg.org/multipage/#dom-input-defaultchecked make_bool_getter!(DefaultChecked, "checked"); @@ -796,6 +804,12 @@ impl VirtualMethods for HTMLInputElement { el.set_read_write_state(false); } + if new_type == InputType::InputFile { + let window = window_from_node(self); + let filelist = FileList::new(window.r(), vec![]); + self.filelist.set(Some(&filelist)); + } + let new_value_mode = self.value_mode(); match (&old_value_mode, old_idl_value.is_empty(), new_value_mode) { diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs index ab2c2a99887..0af076950b3 100644 --- a/components/script/dom/htmllinkelement.rs +++ b/components/script/dom/htmllinkelement.rs @@ -289,43 +289,46 @@ impl AsyncResponseListener for StylesheetContext { } fn response_complete(&mut self, status: Result<(), NetworkError>) { + let elem = self.elem.root(); + let document = document_from_node(&*elem); + if status.is_err() { self.elem.root().upcast::<EventTarget>().fire_simple_event("error"); - return; + } else { + let data = mem::replace(&mut self.data, vec!()); + let metadata = match self.metadata.take() { + Some(meta) => meta, + None => return, + }; + // TODO: Get the actual value. http://dev.w3.org/csswg/css-syntax/#environment-encoding + let environment_encoding = UTF_8 as EncodingRef; + let protocol_encoding_label = metadata.charset.as_ref().map(|s| &**s); + let final_url = metadata.final_url; + + let win = window_from_node(&*elem); + + let mut sheet = Stylesheet::from_bytes(&data, final_url, protocol_encoding_label, + Some(environment_encoding), Origin::Author, + win.css_error_reporter(), + ParserContextExtraData::default()); + let media = self.media.take().unwrap(); + sheet.set_media(Some(media)); + let sheet = Arc::new(sheet); + + let elem = elem.r(); + let document = document.r(); + + let win = window_from_node(elem); + win.layout_chan().send(Msg::AddStylesheet(sheet.clone())).unwrap(); + + *elem.stylesheet.borrow_mut() = Some(sheet); + document.invalidate_stylesheets(); } - let data = mem::replace(&mut self.data, vec!()); - let metadata = match self.metadata.take() { - Some(meta) => meta, - None => return, - }; - // TODO: Get the actual value. http://dev.w3.org/csswg/css-syntax/#environment-encoding - let environment_encoding = UTF_8 as EncodingRef; - let protocol_encoding_label = metadata.charset.as_ref().map(|s| &**s); - let final_url = metadata.final_url; - - let elem = self.elem.root(); - let win = window_from_node(&*elem); - let mut sheet = Stylesheet::from_bytes(&data, final_url, protocol_encoding_label, - Some(environment_encoding), Origin::Author, - win.css_error_reporter(), - ParserContextExtraData::default()); - let media = self.media.take().unwrap(); - sheet.set_media(Some(media)); - let sheet = Arc::new(sheet); - - let elem = elem.r(); - let document = document_from_node(elem); - let document = document.r(); - - let win = window_from_node(elem); - win.layout_chan().send(Msg::AddStylesheet(sheet.clone())).unwrap(); - - *elem.stylesheet.borrow_mut() = Some(sheet); - document.invalidate_stylesheets(); if elem.parser_inserted.get() { document.decrement_script_blocking_stylesheet_count(); } + document.finish_load(LoadType::Stylesheet(self.url.clone())); } } diff --git a/components/script/dom/location.rs b/components/script/dom/location.rs index 9fff2a45837..72361193aa3 100644 --- a/components/script/dom/location.rs +++ b/components/script/dom/location.rs @@ -66,7 +66,10 @@ impl LocationMethods for Location { } // https://html.spec.whatwg.org/multipage/#dom-location-hash - fn SetHash(&self, value: USVString) { + fn SetHash(&self, mut value: USVString) { + if value.0.is_empty() { + value = USVString("#".to_owned()); + } self.set_url_component(value, UrlHelper::SetHash); } diff --git a/components/script/dom/servohtmlparser.rs b/components/script/dom/servohtmlparser.rs index 75d6a5e502f..884ac6c8653 100644 --- a/components/script/dom/servohtmlparser.rs +++ b/components/script/dom/servohtmlparser.rs @@ -81,11 +81,11 @@ impl ParserContext { impl AsyncResponseListener for ParserContext { fn headers_available(&mut self, meta_result: Result<Metadata, NetworkError>) { - let mut is_ssl_error = false; + let mut ssl_error = None; let metadata = match meta_result { Ok(meta) => Some(meta), - Err(NetworkError::SslValidation(url)) => { - is_ssl_error = true; + Err(NetworkError::SslValidation(url, reason)) => { + ssl_error = Some(reason); let mut meta = Metadata::default(url); let mime: Option<Mime> = "text/html".parse().ok(); meta.set_content_type(mime.as_ref()); @@ -124,10 +124,11 @@ impl AsyncResponseListener for ParserContext { parser.set_plaintext_state(); }, Some(ContentType(Mime(TopLevel::Text, SubLevel::Html, _))) => { // Handle text/html - if is_ssl_error { + if let Some(reason) = ssl_error { self.is_synthesized_document = true; let page_bytes = read_resource_file("badcert.html").unwrap(); let page = String::from_utf8(page_bytes).unwrap(); + let page = page.replace("${reason}", &reason); parser.pending_input().borrow_mut().push(page); parser.parse_sync(); } diff --git a/components/script/dom/webidls/HTMLInputElement.webidl b/components/script/dom/webidls/HTMLInputElement.webidl index 48ec3c0ac7b..d145e498659 100644 --- a/components/script/dom/webidls/HTMLInputElement.webidl +++ b/components/script/dom/webidls/HTMLInputElement.webidl @@ -13,7 +13,7 @@ interface HTMLInputElement : HTMLElement { attribute DOMString dirName; attribute boolean disabled; readonly attribute HTMLFormElement? form; - //readonly attribute FileList? files; + readonly attribute FileList? files; attribute DOMString formAction; attribute DOMString formEnctype; attribute DOMString formMethod; diff --git a/components/script/textinput.rs b/components/script/textinput.rs index c724c2691c4..a56bd983f34 100644 --- a/components/script/textinput.rs +++ b/components/script/textinput.rs @@ -215,6 +215,16 @@ impl<T: ClipboardProvider> TextInput<T> { }) } + // Check that the selection is valid. + fn assert_ok_selection(&self) { + if let Some(begin) = self.selection_begin { + debug_assert!(begin.line < self.lines.len()); + debug_assert!(begin.index <= self.lines[begin.line].len()); + } + debug_assert!(self.edit_point.line < self.lines.len()); + debug_assert!(self.edit_point.index <= self.lines[self.edit_point.line].len()); + } + /// Return the selection range as UTF-8 byte offsets from the start of the content. /// /// If there is no selection, returns an empty range at the insertion point. @@ -319,6 +329,7 @@ impl<T: ClipboardProvider> TextInput<T> { self.lines = new_lines; } + self.assert_ok_selection(); } /// Return the length in UTF-8 bytes of the current line under the editing point. @@ -360,6 +371,7 @@ impl<T: ClipboardProvider> TextInput<T> { self.edit_point.line = target_line as usize; self.edit_point.index = len_of_first_n_chars(&self.lines[self.edit_point.line], col); + self.assert_ok_selection(); } /// Adjust the editing point position by a given number of bytes. If the adjustment @@ -441,6 +453,7 @@ impl<T: ClipboardProvider> TextInput<T> { self.edit_point.index + adjust as usize); } } + self.assert_ok_selection(); } /// Deal with a newline input. @@ -462,6 +475,7 @@ impl<T: ClipboardProvider> TextInput<T> { let last_line = self.lines.len() - 1; self.edit_point.line = last_line; self.edit_point.index = self.lines[last_line].len(); + self.assert_ok_selection(); } /// Remove the current selection. @@ -534,6 +548,7 @@ impl<T: ClipboardProvider> TextInput<T> { } Key::End => { self.edit_point.index = self.current_line_length(); + self.assert_ok_selection(); KeyReaction::RedrawSelection } Key::PageUp => { @@ -598,6 +613,7 @@ impl<T: ClipboardProvider> TextInput<T> { self.edit_point.line = min(self.edit_point.line, self.lines.len() - 1); self.edit_point.index = min(self.edit_point.index, self.current_line_length()); self.selection_begin = None; + self.assert_ok_selection(); } /// Get the insertion point as a byte offset from the start of the content. @@ -646,16 +662,16 @@ impl<T: ClipboardProvider> TextInput<T> { let mut end = end as usize; let text_end = self.get_content().len(); - if start > text_end { - start = text_end; - } else if end > text_end { + if end > text_end { end = text_end; - } else if start >= end { + } + if start > end { start = end; } self.selection_begin = Some(self.get_text_point_for_absolute_point(start)); self.edit_point = self.get_text_point_for_absolute_point(end); + self.assert_ok_selection(); } pub fn get_selection_start(&self) -> u32 { diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 318f775337d..f97e69f73c9 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -4,7 +4,7 @@ version = "0.0.1" dependencies = [ "android_glue 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "browserhtml 0.1.8 (git+https://github.com/browserhtml/browserhtml?branch=gh-pages)", + "browserhtml 0.1.14 (git+https://github.com/browserhtml/browserhtml?branch=gh-pages)", "canvas 0.0.1", "canvas_traits 0.0.1", "compiletest_helper 0.0.1", @@ -189,8 +189,8 @@ source = "git+https://github.com/ende76/brotli-rs#d8507fd07e9fa57ed8251d5dc500dc [[package]] name = "browserhtml" -version = "0.1.8" -source = "git+https://github.com/browserhtml/browserhtml?branch=gh-pages#e18298de98273d79fdc450207250a1c2ac11ce0a" +version = "0.1.14" +source = "git+https://github.com/browserhtml/browserhtml?branch=gh-pages#aa577e5d9f436f98b4bd80424a8e48e43f370c43" [[package]] name = "byteorder" @@ -288,7 +288,7 @@ dependencies = [ [[package]] name = "cocoa" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -881,7 +881,7 @@ dependencies = [ "net_traits 0.0.1", "script_traits 0.0.1", "servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "servo-glutin 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)", + "servo-glutin 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)", "style_traits 0.0.1", "url 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2113,12 +2113,12 @@ dependencies = [ [[package]] name = "servo-glutin" -version = "0.4.23" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "android_glue 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "cgl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cocoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cocoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "core-graphics 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "dwmapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2155,7 +2155,7 @@ dependencies = [ "servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "servo-fontconfig 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "servo-freetype-sys 2.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "servo-glutin 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)", + "servo-glutin 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)", "x11 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2585,7 +2585,7 @@ dependencies = [ [[package]] name = "webrender" version = "0.1.0" -source = "git+https://github.com/servo/webrender#85f887b21f6eac3e33aea3fee0f076dc7c890307" +source = "git+https://github.com/servo/webrender#29fcb362a71b0434db186db7e7b9fa8349a0dc3a" dependencies = [ "app_units 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2609,7 +2609,7 @@ dependencies = [ [[package]] name = "webrender_traits" version = "0.2.0" -source = "git+https://github.com/servo/webrender_traits#a466592568193d9ec8a57de9837dddb28ee9631e" +source = "git+https://github.com/servo/webrender_traits#d86e51ace4fd1b43123e0490dc80f631be0726d0" dependencies = [ "app_units 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/components/style/keyframes.rs b/components/style/keyframes.rs index cbfa35b78c4..7d219758848 100644 --- a/components/style/keyframes.rs +++ b/components/style/keyframes.rs @@ -154,8 +154,12 @@ fn get_animated_properties(keyframe: &Keyframe) -> Vec<TransitionProperty> { impl KeyframesAnimation { pub fn from_keyframes(keyframes: &[Keyframe]) -> Option<Self> { + if keyframes.is_empty() { + return None; + } + let animated_properties = get_animated_properties(&keyframes[0]); - if keyframes.is_empty() || animated_properties.is_empty() { + if animated_properties.is_empty() { return None; } diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index 3b75b4ee07b..552f5b303c3 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -25,9 +25,8 @@ use properties::longhands::vertical_align::computed_value::T as VerticalAlign; use properties::longhands::visibility::computed_value::T as Visibility; use properties::longhands::z_index::computed_value::T as ZIndex; use properties::style_struct_traits::*; -use std::cmp::{self, Ordering}; +use std::cmp; use std::fmt; -use std::iter::repeat; use super::ComputedValues; use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone}; use values::computed::{BorderRadiusSize, LengthOrNone}; @@ -119,7 +118,7 @@ impl AnimatedProperty { % for prop in data.longhands: % if prop.animatable: AnimatedProperty::${prop.camel_case}(ref from, ref to) => { - if let Some(value) = from.interpolate(to, progress) { + if let Ok(value) = from.interpolate(to, progress) { style.mutate_${prop.style_struct.ident.strip("_")}().set_${prop.ident}(value); } } @@ -155,27 +154,25 @@ impl AnimatedProperty { /// /// [interpolated-types]: https://drafts.csswg.org/css-transitions/#interpolated-types pub trait Interpolate: Sized { - fn interpolate(&self, other: &Self, time: f64) -> Option<Self>; + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()>; } /// https://drafts.csswg.org/css-transitions/#animtype-number impl Interpolate for Au { #[inline] - fn interpolate(&self, other: &Au, time: f64) -> Option<Au> { - Some(Au((self.0 as f64 + (other.0 as f64 - self.0 as f64) * time).round() as i32)) + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { + Ok(Au((self.0 as f64 + (other.0 as f64 - self.0 as f64) * time).round() as i32)) } } impl <T> Interpolate for Option<T> where T: Interpolate { #[inline] - fn interpolate(&self, other: &Option<T>, time: f64) -> Option<Option<T>> { + fn interpolate(&self, other: &Option<T>, time: f64) -> Result<Option<T>, ()> { match (self, other) { (&Some(ref this), &Some(ref other)) => { - this.interpolate(other, time).and_then(|value| { - Some(Some(value)) - }) + Ok(this.interpolate(other, time).ok()) } - (_, _) => None + _ => Err(()), } } } @@ -183,33 +180,33 @@ impl <T> Interpolate for Option<T> where T: Interpolate { /// https://drafts.csswg.org/css-transitions/#animtype-number impl Interpolate for f32 { #[inline] - fn interpolate(&self, other: &f32, time: f64) -> Option<f32> { - Some(((*self as f64) + ((*other as f64) - (*self as f64)) * time) as f32) + fn interpolate(&self, other: &f32, time: f64) -> Result<Self, ()> { + Ok(((*self as f64) + ((*other as f64) - (*self as f64)) * time) as f32) } } /// https://drafts.csswg.org/css-transitions/#animtype-number impl Interpolate for f64 { #[inline] - fn interpolate(&self, other: &f64, time: f64) -> Option<f64> { - Some(*self + (*other - *self) * time) + fn interpolate(&self, other: &f64, time: f64) -> Result<Self, ()> { + Ok(*self + (*other - *self) * time) } } /// https://drafts.csswg.org/css-transitions/#animtype-number impl Interpolate for i32 { #[inline] - fn interpolate(&self, other: &i32, time: f64) -> Option<i32> { + fn interpolate(&self, other: &i32, time: f64) -> Result<Self, ()> { let a = *self as f64; let b = *other as f64; - Some((a + (b - a) * time).round() as i32) + Ok((a + (b - a) * time).round() as i32) } } /// https://drafts.csswg.org/css-transitions/#animtype-number impl Interpolate for Angle { #[inline] - fn interpolate(&self, other: &Angle, time: f64) -> Option<Angle> { + fn interpolate(&self, other: &Angle, time: f64) -> Result<Self, ()> { self.radians().interpolate(&other.radians(), time).map(Angle) } } @@ -217,19 +214,18 @@ impl Interpolate for Angle { /// https://drafts.csswg.org/css-transitions/#animtype-visibility impl Interpolate for Visibility { #[inline] - fn interpolate(&self, other: &Visibility, time: f64) - -> Option<Visibility> { + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { match (*self, *other) { (Visibility::visible, _) | (_, Visibility::visible) => { - if time >= 0.0 && time <= 1.0 { - Some(Visibility::visible) + Ok(if time >= 0.0 && time <= 1.0 { + Visibility::visible } else if time < 0.0 { - Some(*self) + *self } else { - Some(*other) - } + *other + }) } - (_, _) => None, + _ => Err(()), } } } @@ -237,56 +233,40 @@ impl Interpolate for Visibility { /// https://drafts.csswg.org/css-transitions/#animtype-integer impl Interpolate for ZIndex { #[inline] - fn interpolate(&self, other: &ZIndex, time: f64) - -> Option<ZIndex> { + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { match (*self, *other) { (ZIndex::Number(ref this), ZIndex::Number(ref other)) => { - this.interpolate(other, time).and_then(|value| { - Some(ZIndex::Number(value)) - }) + this.interpolate(other, time).map(ZIndex::Number) } - (_, _) => None, + _ => Err(()), } } } impl<T: Interpolate + Clone> Interpolate for Size2D<T> { #[inline] - fn interpolate(&self, other: &Self, time: f64) -> Option<Self> { - let width = match self.width.interpolate(&other.width, time) { - Some(width) => width, - None => return None, - }; + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { + let width = try!(self.width.interpolate(&other.width, time)); + let height = try!(self.height.interpolate(&other.height, time)); - let height = match self.height.interpolate(&other.height, time) { - Some(height) => height, - None => return None, - }; - Some(Size2D::new(width, height)) + Ok(Size2D::new(width, height)) } } impl<T: Interpolate + Clone> Interpolate for Point2D<T> { #[inline] - fn interpolate(&self, other: &Self, time: f64) -> Option<Self> { - let x = match self.x.interpolate(&other.x, time) { - Some(x) => x, - None => return None, - }; - - let y = match self.y.interpolate(&other.y, time) { - Some(y) => y, - None => return None, - }; + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { + let x = try!(self.x.interpolate(&other.x, time)); + let y = try!(self.y.interpolate(&other.y, time)); - Some(Point2D::new(x, y)) + Ok(Point2D::new(x, y)) } } impl Interpolate for BorderRadiusSize { #[inline] - fn interpolate(&self, other: &Self, time: f64) -> Option<Self> { + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { self.0.interpolate(&other.0, time).map(BorderRadiusSize) } } @@ -294,16 +274,15 @@ impl Interpolate for BorderRadiusSize { /// https://drafts.csswg.org/css-transitions/#animtype-length impl Interpolate for VerticalAlign { #[inline] - fn interpolate(&self, other: &VerticalAlign, time: f64) - -> Option<VerticalAlign> { + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { match (*self, *other) { (VerticalAlign::LengthOrPercentage(LengthOrPercentage::Length(ref this)), VerticalAlign::LengthOrPercentage(LengthOrPercentage::Length(ref other))) => { - this.interpolate(other, time).and_then(|value| { - Some(VerticalAlign::LengthOrPercentage(LengthOrPercentage::Length(value))) + this.interpolate(other, time).map(|value| { + VerticalAlign::LengthOrPercentage(LengthOrPercentage::Length(value)) }) } - (_, _) => None, + _ => Err(()), } } } @@ -311,12 +290,10 @@ impl Interpolate for VerticalAlign { /// https://drafts.csswg.org/css-transitions/#animtype-simple-list impl Interpolate for BorderSpacing { #[inline] - fn interpolate(&self, other: &BorderSpacing, time: f64) - -> Option<BorderSpacing> { - self.horizontal.interpolate(&other.horizontal, time).and_then(|horizontal| { - self.vertical.interpolate(&other.vertical, time).and_then(|vertical| { - Some(BorderSpacing { horizontal: horizontal, vertical: vertical }) - }) + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { + Ok(BorderSpacing { + horizontal: try!(self.horizontal.interpolate(&other.horizontal, time)), + vertical: try!(self.vertical.interpolate(&other.vertical, time)), }) } } @@ -324,30 +301,25 @@ impl Interpolate for BorderSpacing { /// https://drafts.csswg.org/css-transitions/#animtype-color impl Interpolate for RGBA { #[inline] - fn interpolate(&self, other: &RGBA, time: f64) -> Option<RGBA> { - match (self.red.interpolate(&other.red, time), - self.green.interpolate(&other.green, time), - self.blue.interpolate(&other.blue, time), - self.alpha.interpolate(&other.alpha, time)) { - (Some(red), Some(green), Some(blue), Some(alpha)) => { - Some(RGBA { red: red, green: green, blue: blue, alpha: alpha }) - } - (_, _, _, _) => None - } + fn interpolate(&self, other: &RGBA, time: f64) -> Result<Self, ()> { + Ok(RGBA { + red: try!(self.red.interpolate(&other.red, time)), + green: try!(self.green.interpolate(&other.green, time)), + blue: try!(self.blue.interpolate(&other.blue, time)), + alpha: try!(self.alpha.interpolate(&other.alpha, time)), + }) } } /// https://drafts.csswg.org/css-transitions/#animtype-color impl Interpolate for CSSParserColor { #[inline] - fn interpolate(&self, other: &Self, time: f64) -> Option<Self> { + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { match (*self, *other) { (CSSParserColor::RGBA(ref this), CSSParserColor::RGBA(ref other)) => { - this.interpolate(other, time).and_then(|value| { - Some(CSSParserColor::RGBA(value)) - }) + this.interpolate(other, time).map(CSSParserColor::RGBA) } - (_, _) => None, + _ => Err(()), } } } @@ -355,11 +327,10 @@ impl Interpolate for CSSParserColor { /// https://drafts.csswg.org/css-transitions/#animtype-lpcalc impl Interpolate for CalcLengthOrPercentage { #[inline] - fn interpolate(&self, other: &CalcLengthOrPercentage, time: f64) - -> Option<CalcLengthOrPercentage> { - Some(CalcLengthOrPercentage { - length: self.length().interpolate(&other.length(), time), - percentage: self.percentage().interpolate(&other.percentage(), time), + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { + Ok(CalcLengthOrPercentage { + length: try!(self.length.interpolate(&other.length, time)), + percentage: try!(self.percentage.interpolate(&other.percentage, time)), }) } } @@ -367,27 +338,21 @@ impl Interpolate for CalcLengthOrPercentage { /// https://drafts.csswg.org/css-transitions/#animtype-lpcalc impl Interpolate for LengthOrPercentage { #[inline] - fn interpolate(&self, other: &LengthOrPercentage, time: f64) - -> Option<LengthOrPercentage> { + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { match (*self, *other) { (LengthOrPercentage::Length(ref this), LengthOrPercentage::Length(ref other)) => { - this.interpolate(other, time).and_then(|value| { - Some(LengthOrPercentage::Length(value)) - }) + this.interpolate(other, time).map(LengthOrPercentage::Length) } (LengthOrPercentage::Percentage(ref this), LengthOrPercentage::Percentage(ref other)) => { - this.interpolate(other, time).and_then(|value| { - Some(LengthOrPercentage::Percentage(value)) - }) + this.interpolate(other, time).map(LengthOrPercentage::Percentage) } (this, other) => { let this: CalcLengthOrPercentage = From::from(this); let other: CalcLengthOrPercentage = From::from(other); - this.interpolate(&other, time).and_then(|value| { - Some(LengthOrPercentage::Calc(value)) - }) + this.interpolate(&other, time) + .map(LengthOrPercentage::Calc) } } } @@ -396,30 +361,26 @@ impl Interpolate for LengthOrPercentage { /// https://drafts.csswg.org/css-transitions/#animtype-lpcalc impl Interpolate for LengthOrPercentageOrAuto { #[inline] - fn interpolate(&self, other: &LengthOrPercentageOrAuto, time: f64) - -> Option<LengthOrPercentageOrAuto> { + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { match (*self, *other) { (LengthOrPercentageOrAuto::Length(ref this), LengthOrPercentageOrAuto::Length(ref other)) => { - this.interpolate(other, time).and_then(|value| { - Some(LengthOrPercentageOrAuto::Length(value)) - }) + this.interpolate(other, time).map(LengthOrPercentageOrAuto::Length) } (LengthOrPercentageOrAuto::Percentage(ref this), LengthOrPercentageOrAuto::Percentage(ref other)) => { - this.interpolate(other, time).and_then(|value| { - Some(LengthOrPercentageOrAuto::Percentage(value)) - }) + this.interpolate(other, time).map(LengthOrPercentageOrAuto::Percentage) } (LengthOrPercentageOrAuto::Auto, LengthOrPercentageOrAuto::Auto) => { - Some(LengthOrPercentageOrAuto::Auto) + Ok(LengthOrPercentageOrAuto::Auto) } (this, other) => { let this: Option<CalcLengthOrPercentage> = From::from(this); let other: Option<CalcLengthOrPercentage> = From::from(other); - this.interpolate(&other, time).unwrap_or(None).and_then(|value| { - Some(LengthOrPercentageOrAuto::Calc(value)) - }) + match this.interpolate(&other, time) { + Ok(Some(result)) => Ok(LengthOrPercentageOrAuto::Calc(result)), + _ => Err(()), + } } } } @@ -428,25 +389,20 @@ impl Interpolate for LengthOrPercentageOrAuto { /// https://drafts.csswg.org/css-transitions/#animtype-lpcalc impl Interpolate for LengthOrPercentageOrNone { #[inline] - fn interpolate(&self, other: &LengthOrPercentageOrNone, time: f64) - -> Option<LengthOrPercentageOrNone> { + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { match (*self, *other) { (LengthOrPercentageOrNone::Length(ref this), LengthOrPercentageOrNone::Length(ref other)) => { - this.interpolate(other, time).and_then(|value| { - Some(LengthOrPercentageOrNone::Length(value)) - }) + this.interpolate(other, time).map(LengthOrPercentageOrNone::Length) } (LengthOrPercentageOrNone::Percentage(ref this), LengthOrPercentageOrNone::Percentage(ref other)) => { - this.interpolate(other, time).and_then(|value| { - Some(LengthOrPercentageOrNone::Percentage(value)) - }) + this.interpolate(other, time).map(LengthOrPercentageOrNone::Percentage) } (LengthOrPercentageOrNone::None, LengthOrPercentageOrNone::None) => { - Some(LengthOrPercentageOrNone::None) + Ok(LengthOrPercentageOrNone::None) } - (_, _) => None, + _ => Err(()) } } } @@ -455,25 +411,20 @@ impl Interpolate for LengthOrPercentageOrNone { /// https://drafts.csswg.org/css-transitions/#animtype-length impl Interpolate for LineHeight { #[inline] - fn interpolate(&self, other: &LineHeight, time: f64) - -> Option<LineHeight> { + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { match (*self, *other) { (LineHeight::Length(ref this), LineHeight::Length(ref other)) => { - this.interpolate(other, time).and_then(|value| { - Some(LineHeight::Length(value)) - }) + this.interpolate(other, time).map(LineHeight::Length) } (LineHeight::Number(ref this), LineHeight::Number(ref other)) => { - this.interpolate(other, time).and_then(|value| { - Some(LineHeight::Number(value)) - }) + this.interpolate(other, time).map(LineHeight::Number) } (LineHeight::Normal, LineHeight::Normal) => { - Some(LineHeight::Normal) + Ok(LineHeight::Normal) } - (_, _) => None, + _ => Err(()), } } } @@ -481,12 +432,11 @@ impl Interpolate for LineHeight { /// http://dev.w3.org/csswg/css-transitions/#animtype-font-weight impl Interpolate for FontWeight { #[inline] - fn interpolate(&self, other: &FontWeight, time: f64) - -> Option<FontWeight> { + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { let a = (*self as u32) as f64; let b = (*other as u32) as f64; let weight = a + (b - a) * time; - Some(if weight < 150. { + Ok(if weight < 150. { FontWeight::Weight100 } else if weight < 250. { FontWeight::Weight200 @@ -511,48 +461,38 @@ impl Interpolate for FontWeight { /// https://drafts.csswg.org/css-transitions/#animtype-rect impl Interpolate for ClipRect { #[inline] - fn interpolate(&self, other: &ClipRect, time: f64) - -> Option<ClipRect> { - match (self.top.interpolate(&other.top, time), - self.right.interpolate(&other.right, time), - self.bottom.interpolate(&other.bottom, time), - self.left.interpolate(&other.left, time)) { - (Some(top), Some(right), Some(bottom), Some(left)) => { - Some(ClipRect { top: top, right: right, bottom: bottom, left: left }) - }, - (_, _, _, _) => None, - } + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { + Ok(ClipRect { + top: try!(self.top.interpolate(&other.top, time)), + right: try!(self.right.interpolate(&other.right, time)), + bottom: try!(self.bottom.interpolate(&other.bottom, time)), + left: try!(self.left.interpolate(&other.left, time)), + }) } } /// https://drafts.csswg.org/css-transitions/#animtype-simple-list impl Interpolate for BackgroundPosition { #[inline] - fn interpolate(&self, other: &BackgroundPosition, time: f64) - -> Option<BackgroundPosition> { - match (self.horizontal.interpolate(&other.horizontal, time), - self.vertical.interpolate(&other.vertical, time)) { - (Some(horizontal), Some(vertical)) => { - Some(BackgroundPosition { horizontal: horizontal, vertical: vertical }) - }, - (_, _) => None, - } + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { + Ok(BackgroundPosition { + horizontal: try!(self.horizontal.interpolate(&other.horizontal, time)), + vertical: try!(self.vertical.interpolate(&other.vertical, time)), + }) } } impl Interpolate for BackgroundSize { - fn interpolate(&self, other: &Self, time: f64) -> Option<Self> { + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { use properties::longhands::background_size::computed_value::ExplicitSize; match (self, other) { - (&BackgroundSize::Explicit(ref me), &BackgroundSize::Explicit(ref other)) - => match (me.width.interpolate(&other.width, time), - me.height.interpolate(&other.height, time)) { - (Some(width), Some(height)) - => Some(BackgroundSize::Explicit( - ExplicitSize { width: width, height: height })), - _ => None, - }, - _ => None + (&BackgroundSize::Explicit(ref me), &BackgroundSize::Explicit(ref other)) => { + Ok(BackgroundSize::Explicit(ExplicitSize { + width: try!(me.width.interpolate(&other.width, time)), + height: try!(me.height.interpolate(&other.height, time)), + })) + } + _ => Err(()), } } } @@ -560,25 +500,20 @@ impl Interpolate for BackgroundSize { /// https://drafts.csswg.org/css-transitions/#animtype-shadow-list impl Interpolate for TextShadow { #[inline] - fn interpolate(&self, other: &TextShadow, time: f64) - -> Option<TextShadow> { - match (self.offset_x.interpolate(&other.offset_x, time), - self.offset_y.interpolate(&other.offset_y, time), - self.blur_radius.interpolate(&other.blur_radius, time), - self.color.interpolate(&other.color, time)) { - (Some(offset_x), Some(offset_y), Some(blur_radius), Some(color)) => { - Some(TextShadow { offset_x: offset_x, offset_y: offset_y, blur_radius: blur_radius, color: color }) - }, - _ => None, - } + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { + Ok(TextShadow { + offset_x: try!(self.offset_x.interpolate(&other.offset_x, time)), + offset_y: try!(self.offset_y.interpolate(&other.offset_y, time)), + blur_radius: try!(self.blur_radius.interpolate(&other.blur_radius, time)), + color: try!(self.color.interpolate(&other.color, time)), + }) } } /// https://drafts.csswg.org/css-transitions/#animtype-shadow-list impl Interpolate for TextShadowList { #[inline] - fn interpolate(&self, other: &TextShadowList, time: f64) - -> Option<TextShadowList> { + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { let zero = TextShadow { offset_x: Au(0), offset_y: Au(0), @@ -588,14 +523,25 @@ impl Interpolate for TextShadowList { }) }; - let interpolate_each = |(a, b): (&TextShadow, &TextShadow)| { - a.interpolate(b, time).unwrap() - }; + let max_len = cmp::max(self.0.len(), other.0.len()); + let mut result = Vec::with_capacity(max_len); - Some(TextShadowList(match self.0.len().cmp(&other.0.len()) { - Ordering::Less => other.0.iter().chain(repeat(&zero)).zip(other.0.iter()).map(interpolate_each).collect(), - _ => self.0.iter().zip(other.0.iter().chain(repeat(&zero))).map(interpolate_each).collect(), - })) + for i in 0..max_len { + let shadow = match (self.0.get(i), other.0.get(i)) { + (Some(shadow), Some(other)) + => try!(shadow.interpolate(other, time)), + (Some(shadow), None) => { + shadow.interpolate(&zero, time).unwrap() + } + (None, Some(shadow)) => { + zero.interpolate(&shadow, time).unwrap() + } + (None, None) => unreachable!(), + }; + result.push(shadow); + } + + Ok(TextShadowList(result)) } } @@ -725,8 +671,7 @@ fn build_identity_transform_list(list: &[TransformOperation]) -> Vec<TransformOp impl Interpolate for BoxShadowList { #[inline] - fn interpolate(&self, other: &Self, time: f64) - -> Option<Self> { + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { // The inset value must change let mut zero = BoxShadow { offset_x: Au(0), @@ -744,12 +689,8 @@ impl Interpolate for BoxShadowList { for i in 0..max_len { let shadow = match (self.0.get(i), other.0.get(i)) { - (Some(shadow), Some(other)) => { - match shadow.interpolate(other, time) { - Some(shadow) => shadow, - None => return None, - } - } + (Some(shadow), Some(other)) + => try!(shadow.interpolate(other, time)), (Some(shadow), None) => { zero.inset = shadow.inset; shadow.interpolate(&zero, time).unwrap() @@ -763,45 +704,25 @@ impl Interpolate for BoxShadowList { result.push(shadow); } - Some(BoxShadowList(result)) + Ok(BoxShadowList(result)) } } /// https://drafts.csswg.org/css-transitions/#animtype-shadow-list impl Interpolate for BoxShadow { #[inline] - fn interpolate(&self, other: &Self, time: f64) - -> Option<Self> { + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { if self.inset != other.inset { - return None; + return Err(()); } - let x = match self.offset_x.interpolate(&other.offset_x, time) { - Some(x) => x, - None => return None, - }; + let x = try!(self.offset_x.interpolate(&other.offset_x, time)); + let y = try!(self.offset_y.interpolate(&other.offset_y, time)); + let color = try!(self.color.interpolate(&other.color, time)); + let spread = try!(self.spread_radius.interpolate(&other.spread_radius, time)); + let blur = try!(self.blur_radius.interpolate(&other.blur_radius, time)); - let y = match self.offset_y.interpolate(&other.offset_y, time) { - Some(y) => y, - None => return None, - }; - - let color = match self.color.interpolate(&other.color, time) { - Some(c) => c, - None => return None, - }; - - let spread = match self.spread_radius.interpolate(&other.spread_radius, time) { - Some(s) => s, - None => return None, - }; - - let blur = match self.blur_radius.interpolate(&other.blur_radius, time) { - Some(r) => r, - None => return None, - }; - - Some(BoxShadow { + Ok(BoxShadow { offset_x: x, offset_y: y, blur_radius: blur, @@ -813,36 +734,21 @@ impl Interpolate for BoxShadow { } impl Interpolate for LengthOrNone { - fn interpolate(&self, other: &Self, time: f64) -> Option<Self> { + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { match (*self, *other) { (LengthOrNone::Length(ref len), LengthOrNone::Length(ref other)) => len.interpolate(&other, time).map(LengthOrNone::Length), - _ => None, + _ => Err(()), } } } impl Interpolate for TransformOrigin { - fn interpolate(&self, other: &Self, time: f64) -> Option<Self> { - let horizontal = match self.horizontal.interpolate(&other.horizontal, time) { - Some(h) => h, - None => return None, - }; - - let vertical = match self.vertical.interpolate(&other.vertical, time) { - Some(v) => v, - None => return None, - }; - - let depth = match self.depth.interpolate(&other.depth, time) { - Some(d) => d, - None => return None, - }; - - Some(TransformOrigin { - horizontal: horizontal, - vertical: vertical, - depth: depth, + fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { + Ok(TransformOrigin { + horizontal: try!(self.horizontal.interpolate(&other.horizontal, time)), + vertical: try!(self.vertical.interpolate(&other.vertical, time)), + depth: try!(self.depth.interpolate(&other.depth, time)), }) } } @@ -850,7 +756,7 @@ impl Interpolate for TransformOrigin { /// https://drafts.csswg.org/css-transforms/#interpolation-of-transforms impl Interpolate for TransformList { #[inline] - fn interpolate(&self, other: &TransformList, time: f64) -> Option<TransformList> { + fn interpolate(&self, other: &TransformList, time: f64) -> Result<Self, ()> { // http://dev.w3.org/csswg/css-transforms/#interpolation-of-transforms let result = match (&self.0, &other.0) { (&Some(ref from_list), &Some(ref to_list)) => { @@ -873,6 +779,6 @@ impl Interpolate for TransformList { } }; - Some(result) + Ok(result) } } diff --git a/components/util/lib.rs b/components/util/lib.rs index ff1a18ab712..eb71fdf41f1 100644 --- a/components/util/lib.rs +++ b/components/util/lib.rs @@ -39,7 +39,6 @@ pub mod cache; #[allow(unsafe_code)] pub mod debug_utils; pub mod geometry; #[cfg(feature = "servo")] #[allow(unsafe_code)] pub mod ipc; -#[cfg(feature = "servo")] pub mod linked_list; #[allow(unsafe_code)] pub mod opts; #[cfg(feature = "servo")] pub mod panicking; pub mod prefs; @@ -49,7 +48,6 @@ pub mod str; pub mod thread; pub mod thread_state; pub mod tid; -#[cfg(feature = "servo")] pub mod time; pub mod vec; #[allow(unsafe_code)] pub mod workqueue; diff --git a/components/util/opts.rs b/components/util/opts.rs index 1fe76f96d26..a55d7e556f2 100644 --- a/components/util/opts.rs +++ b/components/util/opts.rs @@ -486,7 +486,7 @@ pub fn default_opts() -> Opts { trace_layout: false, devtools_port: None, webdriver_port: None, - initial_window_size: Size2D::typed(800, 600), + initial_window_size: Size2D::typed(1024, 740), user_agent: default_user_agent_string(DEFAULT_USER_AGENT), multiprocess: false, random_pipeline_closure_probability: None, @@ -543,7 +543,7 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult { opts.optflag("F", "soft-fail", "Display about:failure on thread failure instead of exiting"); opts.optflagopt("", "devtools", "Start remote devtools server on port", "6000"); opts.optflagopt("", "webdriver", "Start remote WebDriver server on port", "7000"); - opts.optopt("", "resolution", "Set window resolution.", "800x600"); + opts.optopt("", "resolution", "Set window resolution.", "1024x740"); opts.optopt("u", "user-agent", "Set custom user agent string (or android / desktop for platform default)", @@ -717,7 +717,7 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult { Size2D::typed(res[0], res[1]) } None => { - Size2D::typed(800, 600) + Size2D::typed(1024, 740) } }; diff --git a/components/util/time.rs b/components/util/time.rs deleted file mode 100644 index 4a751c95ee1..00000000000 --- a/components/util/time.rs +++ /dev/null @@ -1,31 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * 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 std::time::Duration; -use std::{u32, u64}; - -pub const NANOS_PER_SEC: u32 = 1_000_000_000; - -pub fn duration_from_seconds(secs: f64) -> Duration { - // Get number of seconds and check that it fits in a u64. - let whole_secs = secs.trunc(); - assert!(whole_secs >= 0.0 && whole_secs <= u64::MAX as f64); - - // Get number of nanoseconds. This should always fit in a u32, but check anyway. - let nanos = (secs.fract() * (NANOS_PER_SEC as f64)).trunc(); - assert!(nanos >= 0.0 && nanos <= u32::MAX as f64); - - Duration::new(whole_secs as u64, nanos as u32) -} - -pub fn duration_from_nanoseconds(nanos: u64) -> Duration { - // Get number of seconds. - let secs = nanos / NANOS_PER_SEC as u64; - - // Get number of extra nanoseconds. This should always fit in a u32, but check anyway. - let subsec_nanos = nanos % NANOS_PER_SEC as u64; - assert!(subsec_nanos <= u32::MAX as u64); - - Duration::new(secs, subsec_nanos as u32) -} diff --git a/etc/ci/upload_nightly.sh b/etc/ci/upload_nightly.sh new file mode 100755 index 00000000000..152f4729452 --- /dev/null +++ b/etc/ci/upload_nightly.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail +shopt -s failglob + + +usage() { + printf "usage: ${0} android|linux|mac|windows\n" +} + + +upload() { + s3cmd put "${2}" "s3://servo-builds/nightly/${1}/" +} + + +main() { + if [[ "$#" != 1 ]]; then + usage >&2 + return 1 + fi + + local platform package + platform="${1}" + + if [[ "${platform}" == "android" ]]; then + package=target/arm-linux-androideabi/release/*.apk + elif [[ "${platform}" == "linux" ]]; then + package=target/*.tar.gz + elif [[ "${platform}" == "mac" ]]; then + package=target/*.dmg + elif [[ "${platform}" == "windows" ]]; then + package=target/*.tar.gz + else + usage >&2 + return 1 + fi + + # Lack of quotes on package allows glob expansion + # Note that this is not robust in the case of embedded spaces + # TODO(aneeshusa): make this glob robust using e.g. arrays or Python + upload "${platform}" ${package} +} + +main "$@" diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index acdd3727e8b..b629fca2138 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -2,7 +2,7 @@ name = "embedding" version = "0.0.1" dependencies = [ - "cocoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cocoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "compositing 0.0.1", "devtools 0.0.1", "euclid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -163,8 +163,8 @@ source = "git+https://github.com/ende76/brotli-rs#d8507fd07e9fa57ed8251d5dc500dc [[package]] name = "browserhtml" -version = "0.1.8" -source = "git+https://github.com/browserhtml/browserhtml?branch=gh-pages#e18298de98273d79fdc450207250a1c2ac11ce0a" +version = "0.1.14" +source = "git+https://github.com/browserhtml/browserhtml?branch=gh-pages#aa577e5d9f436f98b4bd80424a8e48e43f370c43" [[package]] name = "byteorder" @@ -262,7 +262,7 @@ dependencies = [ [[package]] name = "cocoa" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -790,7 +790,7 @@ dependencies = [ "net_traits 0.0.1", "script_traits 0.0.1", "servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "servo-glutin 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)", + "servo-glutin 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)", "style_traits 0.0.1", "url 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1926,7 +1926,7 @@ version = "0.0.1" dependencies = [ "android_glue 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "browserhtml 0.1.8 (git+https://github.com/browserhtml/browserhtml?branch=gh-pages)", + "browserhtml 0.1.14 (git+https://github.com/browserhtml/browserhtml?branch=gh-pages)", "canvas 0.0.1", "canvas_traits 0.0.1", "compositing 0.0.1", @@ -1998,12 +1998,12 @@ dependencies = [ [[package]] name = "servo-glutin" -version = "0.4.23" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "android_glue 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "cgl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cocoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cocoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "core-graphics 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "dwmapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2040,7 +2040,7 @@ dependencies = [ "servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "servo-fontconfig 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "servo-freetype-sys 2.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "servo-glutin 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)", + "servo-glutin 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)", "x11 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2447,7 +2447,7 @@ dependencies = [ [[package]] name = "webrender" version = "0.1.0" -source = "git+https://github.com/servo/webrender#85f887b21f6eac3e33aea3fee0f076dc7c890307" +source = "git+https://github.com/servo/webrender#29fcb362a71b0434db186db7e7b9fa8349a0dc3a" dependencies = [ "app_units 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2471,7 +2471,7 @@ dependencies = [ [[package]] name = "webrender_traits" version = "0.2.0" -source = "git+https://github.com/servo/webrender_traits#a466592568193d9ec8a57de9837dddb28ee9631e" +source = "git+https://github.com/servo/webrender_traits#d86e51ace4fd1b43123e0490dc80f631be0726d0" dependencies = [ "app_units 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ports/geckolib/gecko_bindings/tools/setup_bindgen.sh b/ports/geckolib/gecko_bindings/tools/setup_bindgen.sh index 16c4147e9a7..768fb53794d 100755 --- a/ports/geckolib/gecko_bindings/tools/setup_bindgen.sh +++ b/ports/geckolib/gecko_bindings/tools/setup_bindgen.sh @@ -11,7 +11,7 @@ else fi # Make sure we have llvm38. -if [ ! -x "$(command -v clang++-3.8)" ]; then +if [ ! -x "$(command -v clang-3.8)" ]; then echo "llmv38 must be installed. Mac users should |brew install llvm38|, Linux varies by distro." exit 1 fi @@ -27,12 +27,10 @@ fi # Don't try to clone twice. if [ ! -d rust-bindgen ]; then - git clone https://github.com/ecoal95/rust-bindgen.git - cd rust-bindgen - git checkout sm-hacks-rebase-squashed -else - cd rust-bindgen + git clone https://github.com/servo/rust-bindgen.git fi +cd rust-bindgen + multirust override nightly -cargo build +cargo build --features llvm_stable diff --git a/ports/glutin/window.rs b/ports/glutin/window.rs index 235afd4733c..010c337f01b 100644 --- a/ports/glutin/window.rs +++ b/ports/glutin/window.rs @@ -81,7 +81,6 @@ fn builder_with_platform_options(mut builder: glutin::WindowBuilder) -> glutin:: builder = builder.with_activation_policy(ActivationPolicy::Prohibited) } builder.with_app_name(String::from("Servo")) - .with_transparent_corner_radius(8) } #[cfg(not(target_os = "macos"))] @@ -261,7 +260,8 @@ impl Window { Event::Resized(width, height) => { self.event_queue.borrow_mut().push(WindowEvent::Resize(Size2D::typed(width, height))); } - Event::MouseInput(element_state, mouse_button) => { + Event::MouseInput(element_state, mouse_button, _) => { + // FIXME(#11130, pcwalton): The third field should be used. if mouse_button == MouseButton::Left || mouse_button == MouseButton::Right { let mouse_pos = self.mouse_pos.get(); @@ -576,7 +576,7 @@ impl Window { } fn glutin_mods_to_script_mods(modifiers: KeyModifiers) -> constellation_msg::KeyModifiers { - let mut result = constellation_msg::KeyModifiers::from_bits(0).expect("infallible"); + let mut result = constellation_msg::KeyModifiers::empty(); if modifiers.intersects(LEFT_SHIFT | RIGHT_SHIFT) { result.insert(SHIFT); } diff --git a/python/servo/package_commands.py b/python/servo/package_commands.py index 4693d0136e0..6569598189f 100644 --- a/python/servo/package_commands.py +++ b/python/servo/package_commands.py @@ -154,6 +154,8 @@ class PackageCommands(CommandBase): print("Packaged Servo into " + dmg_path) else: dir_to_package = '/'.join(binary_path.split('/')[:-1]) + dir_to_root = '/'.join(binary_path.split('/')[:-3]) + shutil.copytree(dir_to_root + '/resources', dir_to_package + '/resources') browserhtml_path = find_dep_path_newest('browserhtml', binary_path) if browserhtml_path is None: print("Could not find browserhtml package; perhaps you haven't built Servo.") @@ -172,9 +174,9 @@ class PackageCommands(CommandBase): '--pref', 'dom.mozbrowser.enabled', '--pref', 'dom.forcetouch.enabled', '--pref', 'shell.builtin-key-shortcuts.enabled=false', - path.join(browserhtml_path, 'out', 'index.html')] + path.join('./build/' + browserhtml_path.split('/')[-1], 'out', 'index.html')] - runservo = os.open(dir_to_package + 'runservo.sh', os.O_WRONLY | os.O_CREAT, int("0755", 8)) + runservo = os.open(dir_to_package + '/runservo.sh', os.O_WRONLY | os.O_CREAT, int("0755", 8)) os.write(runservo, "./servo " + ' '.join(servo_args)) os.close(runservo) print("Creating tarball") diff --git a/resources/badcert.html b/resources/badcert.html index 9bb98db2148..fca069fac2a 100644 --- a/resources/badcert.html +++ b/resources/badcert.html @@ -3,6 +3,7 @@ <title>Certificate error</title> </head> <body> - <img src="chrome://resources/badcert.jpg"> + <img src="chrome://resources/itried.jpg"> + <p>${reason}</p> </body> </html> diff --git a/resources/servo.css b/resources/servo.css index c1dbe1c1ddc..98ee52c0982 100644 --- a/resources/servo.css +++ b/resources/servo.css @@ -132,7 +132,7 @@ textarea { -servo-overflow-clip-box: content-box; } -// https://html.spec.whatwg.org/multipage/rendering.html#the-details-and-summary-elements +/* https://html.spec.whatwg.org/multipage/rendering.html#the-details-and-summary-elements */ details { display: block; } diff --git a/resources/shaders/es2_common.vs.glsl b/resources/shaders/es2_common.vs.glsl index ccb8c3dcec5..91d72015e49 100644 --- a/resources/shaders/es2_common.vs.glsl +++ b/resources/shaders/es2_common.vs.glsl @@ -65,6 +65,6 @@ vec2 SnapToPixels(vec2 pos) // Snap the vertex to pixel position to guarantee correct texture // sampling when using bilinear filtering. - // TODO(gw): ES2 doesn't have round(). Do we ever get negative coords here? + // TODO(gw): Do we ever get negative coords here? return floor(0.5 + pos * uDevicePixelRatio) / uDevicePixelRatio; } diff --git a/resources/shaders/gl3_common.vs.glsl b/resources/shaders/gl3_common.vs.glsl index cffcfc80eb7..e24cef9437e 100644 --- a/resources/shaders/gl3_common.vs.glsl +++ b/resources/shaders/gl3_common.vs.glsl @@ -62,5 +62,8 @@ vec2 SnapToPixels(vec2 pos) { // Snap the vertex to pixel position to guarantee correct texture // sampling when using bilinear filtering. - return round(pos * uDevicePixelRatio) / uDevicePixelRatio; + + // Don't use round() because its behavior is implementation-defined on 0.5. + // TODO: Do we ever get negative coords here? + return floor(0.5 + pos * uDevicePixelRatio) / uDevicePixelRatio; } diff --git a/tests/wpt/harness/wptrunner/executors/executorservo.py b/tests/wpt/harness/wptrunner/executors/executorservo.py index 068061b958d..7f5e9067319 100644 --- a/tests/wpt/harness/wptrunner/executors/executorservo.py +++ b/tests/wpt/harness/wptrunner/executors/executorservo.py @@ -216,6 +216,8 @@ class ServoRefTestExecutor(ProcessTestExecutor): if viewport_size: command += ["--resolution", viewport_size] + else: + command += ["--resolution", "800x600"] if dpi: command += ["--device-pixel-ratio", dpi] diff --git a/tests/wpt/metadata/FileAPI/filelist-section/filelist.html.ini b/tests/wpt/metadata/FileAPI/filelist-section/filelist.html.ini deleted file mode 100644 index 4c198fa1a2f..00000000000 --- a/tests/wpt/metadata/FileAPI/filelist-section/filelist.html.ini +++ /dev/null @@ -1,17 +0,0 @@ -[filelist.html] - type: testharness - [Check if item is a instanceof Function] - expected: FAIL - - [Check if item is a method of fileList] - expected: FAIL - - [Check if the item method returns null when no file selected] - expected: FAIL - - [Check if length is fileList's attribute] - expected: FAIL - - [Check if the fileList length is 0 when no file selected] - expected: FAIL - diff --git a/tests/wpt/metadata/FileAPI/idlharness.html.ini b/tests/wpt/metadata/FileAPI/idlharness.html.ini index c3099e70f38..96f7878d2f7 100644 --- a/tests/wpt/metadata/FileAPI/idlharness.html.ini +++ b/tests/wpt/metadata/FileAPI/idlharness.html.ini @@ -3,21 +3,6 @@ [URL interface: operation createFor(Blob)] expected: FAIL - [FileList must be primary interface of file_input.files] - expected: FAIL - - [Stringification of file_input.files] - expected: FAIL - - [FileList interface: file_input.files must inherit property "item" with the proper type (0)] - expected: FAIL - - [FileList interface: calling item(unsigned long) on file_input.files with too few arguments must throw TypeError] - expected: FAIL - - [FileList interface: file_input.files must inherit property "length" with the proper type (1)] - expected: FAIL - [FileReaderSync interface: existence and properties of interface object] expected: FAIL diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json index 9dc86c4804d..1a4452832b9 100644 --- a/tests/wpt/metadata/MANIFEST.json +++ b/tests/wpt/metadata/MANIFEST.json @@ -36263,7 +36263,16 @@ "local_changes": { "deleted": [], "deleted_reftests": {}, - "items": {}, + "items": { + "testharness": { + "html/browsers/browsing-the-web/navigating-across-documents/empty_fragment.html": [ + { + "path": "html/browsers/browsing-the-web/navigating-across-documents/empty_fragment.html", + "url": "/html/browsers/browsing-the-web/navigating-across-documents/empty_fragment.html" + } + ] + } + }, "reftest_nodes": {} }, "reftest_nodes": { diff --git a/tests/wpt/metadata/html/dom/interfaces.html.ini b/tests/wpt/metadata/html/dom/interfaces.html.ini index 5c17f9f2f85..92990e9dab8 100644 --- a/tests/wpt/metadata/html/dom/interfaces.html.ini +++ b/tests/wpt/metadata/html/dom/interfaces.html.ini @@ -3570,9 +3570,6 @@ [HTMLInputElement interface: attribute autofocus] expected: FAIL - [HTMLInputElement interface: attribute files] - expected: FAIL - [HTMLInputElement interface: attribute height] expected: FAIL @@ -3645,9 +3642,6 @@ [HTMLInputElement interface: document.createElement("input") must inherit property "autofocus" with the proper type (3)] expected: FAIL - [HTMLInputElement interface: document.createElement("input") must inherit property "files" with the proper type (9)] - expected: FAIL - [HTMLInputElement interface: document.createElement("input") must inherit property "height" with the proper type (15)] expected: FAIL @@ -7590,9 +7584,6 @@ [HTMLInputElement interface: createInput("text") must inherit property "autofocus" with the proper type (3)] expected: FAIL - [HTMLInputElement interface: createInput("text") must inherit property "files" with the proper type (9)] - expected: FAIL - [HTMLInputElement interface: createInput("text") must inherit property "height" with the proper type (15)] expected: FAIL @@ -7680,9 +7671,6 @@ [HTMLInputElement interface: createInput("hidden") must inherit property "autofocus" with the proper type (3)] expected: FAIL - [HTMLInputElement interface: createInput("hidden") must inherit property "files" with the proper type (9)] - expected: FAIL - [HTMLInputElement interface: createInput("hidden") must inherit property "height" with the proper type (15)] expected: FAIL @@ -7770,9 +7758,6 @@ [HTMLInputElement interface: createInput("search") must inherit property "autofocus" with the proper type (3)] expected: FAIL - [HTMLInputElement interface: createInput("search") must inherit property "files" with the proper type (9)] - expected: FAIL - [HTMLInputElement interface: createInput("search") must inherit property "height" with the proper type (15)] expected: FAIL @@ -7860,9 +7845,6 @@ [HTMLInputElement interface: createInput("tel") must inherit property "autofocus" with the proper type (3)] expected: FAIL - [HTMLInputElement interface: createInput("tel") must inherit property "files" with the proper type (9)] - expected: FAIL - [HTMLInputElement interface: createInput("tel") must inherit property "height" with the proper type (15)] expected: FAIL @@ -7950,9 +7932,6 @@ [HTMLInputElement interface: createInput("url") must inherit property "autofocus" with the proper type (3)] expected: FAIL - [HTMLInputElement interface: createInput("url") must inherit property "files" with the proper type (9)] - expected: FAIL - [HTMLInputElement interface: createInput("url") must inherit property "height" with the proper type (15)] expected: FAIL @@ -8040,9 +8019,6 @@ [HTMLInputElement interface: createInput("email") must inherit property "autofocus" with the proper type (3)] expected: FAIL - [HTMLInputElement interface: createInput("email") must inherit property "files" with the proper type (9)] - expected: FAIL - [HTMLInputElement interface: createInput("email") must inherit property "height" with the proper type (15)] expected: FAIL @@ -8130,9 +8106,6 @@ [HTMLInputElement interface: createInput("password") must inherit property "autofocus" with the proper type (3)] expected: FAIL - [HTMLInputElement interface: createInput("password") must inherit property "files" with the proper type (9)] - expected: FAIL - [HTMLInputElement interface: createInput("password") must inherit property "height" with the proper type (15)] expected: FAIL @@ -8220,9 +8193,6 @@ [HTMLInputElement interface: createInput("date") must inherit property "autofocus" with the proper type (3)] expected: FAIL - [HTMLInputElement interface: createInput("date") must inherit property "files" with the proper type (9)] - expected: FAIL - [HTMLInputElement interface: createInput("date") must inherit property "height" with the proper type (15)] expected: FAIL @@ -8310,9 +8280,6 @@ [HTMLInputElement interface: createInput("month") must inherit property "autofocus" with the proper type (3)] expected: FAIL - [HTMLInputElement interface: createInput("month") must inherit property "files" with the proper type (9)] - expected: FAIL - [HTMLInputElement interface: createInput("month") must inherit property "height" with the proper type (15)] expected: FAIL @@ -8400,9 +8367,6 @@ [HTMLInputElement interface: createInput("week") must inherit property "autofocus" with the proper type (3)] expected: FAIL - [HTMLInputElement interface: createInput("week") must inherit property "files" with the proper type (9)] - expected: FAIL - [HTMLInputElement interface: createInput("week") must inherit property "height" with the proper type (15)] expected: FAIL @@ -8490,9 +8454,6 @@ [HTMLInputElement interface: createInput("time") must inherit property "autofocus" with the proper type (3)] expected: FAIL - [HTMLInputElement interface: createInput("time") must inherit property "files" with the proper type (9)] - expected: FAIL - [HTMLInputElement interface: createInput("time") must inherit property "height" with the proper type (15)] expected: FAIL @@ -8580,9 +8541,6 @@ [HTMLInputElement interface: createInput("datetime-local") must inherit property "autofocus" with the proper type (3)] expected: FAIL - [HTMLInputElement interface: createInput("datetime-local") must inherit property "files" with the proper type (9)] - expected: FAIL - [HTMLInputElement interface: createInput("datetime-local") must inherit property "height" with the proper type (15)] expected: FAIL @@ -8670,9 +8628,6 @@ [HTMLInputElement interface: createInput("number") must inherit property "autofocus" with the proper type (3)] expected: FAIL - [HTMLInputElement interface: createInput("number") must inherit property "files" with the proper type (9)] - expected: FAIL - [HTMLInputElement interface: createInput("number") must inherit property "height" with the proper type (15)] expected: FAIL @@ -8760,9 +8715,6 @@ [HTMLInputElement interface: createInput("range") must inherit property "autofocus" with the proper type (3)] expected: FAIL - [HTMLInputElement interface: createInput("range") must inherit property "files" with the proper type (9)] - expected: FAIL - [HTMLInputElement interface: createInput("range") must inherit property "height" with the proper type (15)] expected: FAIL @@ -8850,9 +8802,6 @@ [HTMLInputElement interface: createInput("color") must inherit property "autofocus" with the proper type (3)] expected: FAIL - [HTMLInputElement interface: createInput("color") must inherit property "files" with the proper type (9)] - expected: FAIL - [HTMLInputElement interface: createInput("color") must inherit property "height" with the proper type (15)] expected: FAIL @@ -8940,9 +8889,6 @@ [HTMLInputElement interface: createInput("checkbox") must inherit property "autofocus" with the proper type (3)] expected: FAIL - [HTMLInputElement interface: createInput("checkbox") must inherit property "files" with the proper type (9)] - expected: FAIL - [HTMLInputElement interface: createInput("checkbox") must inherit property "height" with the proper type (15)] expected: FAIL @@ -9030,9 +8976,6 @@ [HTMLInputElement interface: createInput("radio") must inherit property "autofocus" with the proper type (3)] expected: FAIL - [HTMLInputElement interface: createInput("radio") must inherit property "files" with the proper type (9)] - expected: FAIL - [HTMLInputElement interface: createInput("radio") must inherit property "height" with the proper type (15)] expected: FAIL @@ -9210,9 +9153,6 @@ [HTMLInputElement interface: createInput("submit") must inherit property "autofocus" with the proper type (3)] expected: FAIL - [HTMLInputElement interface: createInput("submit") must inherit property "files" with the proper type (9)] - expected: FAIL - [HTMLInputElement interface: createInput("submit") must inherit property "height" with the proper type (15)] expected: FAIL @@ -9300,9 +9240,6 @@ [HTMLInputElement interface: createInput("image") must inherit property "autofocus" with the proper type (3)] expected: FAIL - [HTMLInputElement interface: createInput("image") must inherit property "files" with the proper type (9)] - expected: FAIL - [HTMLInputElement interface: createInput("image") must inherit property "height" with the proper type (15)] expected: FAIL @@ -9390,9 +9327,6 @@ [HTMLInputElement interface: createInput("reset") must inherit property "autofocus" with the proper type (3)] expected: FAIL - [HTMLInputElement interface: createInput("reset") must inherit property "files" with the proper type (9)] - expected: FAIL - [HTMLInputElement interface: createInput("reset") must inherit property "height" with the proper type (15)] expected: FAIL @@ -9480,9 +9414,6 @@ [HTMLInputElement interface: createInput("button") must inherit property "autofocus" with the proper type (3)] expected: FAIL - [HTMLInputElement interface: createInput("button") must inherit property "files" with the proper type (9)] - expected: FAIL - [HTMLInputElement interface: createInput("button") must inherit property "height" with the proper type (15)] expected: FAIL diff --git a/tests/wpt/metadata/html/semantics/forms/the-input-element/files.html.ini b/tests/wpt/metadata/html/semantics/forms/the-input-element/files.html.ini deleted file mode 100644 index 37cc4c14fcd..00000000000 --- a/tests/wpt/metadata/html/semantics/forms/the-input-element/files.html.ini +++ /dev/null @@ -1,71 +0,0 @@ -[files.html] - type: testharness - [files for input type=hidden] - expected: FAIL - - [files for input type=text] - expected: FAIL - - [files for input type=search] - expected: FAIL - - [files for input type=tel] - expected: FAIL - - [files for input type=url] - expected: FAIL - - [files for input type=email] - expected: FAIL - - [files for input type=password] - expected: FAIL - - [files for input type=datetime] - expected: FAIL - - [files for input type=date] - expected: FAIL - - [files for input type=month] - expected: FAIL - - [files for input type=week] - expected: FAIL - - [files for input type=time] - expected: FAIL - - [files for input type=datetime-local] - expected: FAIL - - [files for input type=number] - expected: FAIL - - [files for input type=range] - expected: FAIL - - [files for input type=color] - expected: FAIL - - [files for input type=checkbox] - expected: FAIL - - [files for input type=radio] - expected: FAIL - - [files for input type=submit] - expected: FAIL - - [files for input type=image] - expected: FAIL - - [files for input type=reset] - expected: FAIL - - [files for input type=button] - expected: FAIL - - [files for input type=file] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/forms/the-input-element/hidden.html.ini b/tests/wpt/metadata/html/semantics/forms/the-input-element/hidden.html.ini index 5b29419eea0..2984d41afe7 100644 --- a/tests/wpt/metadata/html/semantics/forms/the-input-element/hidden.html.ini +++ b/tests/wpt/metadata/html/semantics/forms/the-input-element/hidden.html.ini @@ -1,8 +1,5 @@ [hidden.html] type: testharness - [files attribute must return null for hidden] - expected: FAIL - [valueAsDate attribute must return null for hidden] expected: FAIL diff --git a/tests/wpt/metadata/html/semantics/forms/the-input-element/text.html.ini b/tests/wpt/metadata/html/semantics/forms/the-input-element/text.html.ini index 593054f48b2..bc06afde4b9 100644 --- a/tests/wpt/metadata/html/semantics/forms/the-input-element/text.html.ini +++ b/tests/wpt/metadata/html/semantics/forms/the-input-element/text.html.ini @@ -3,9 +3,6 @@ [Value sanitization algorithm should strip line breaks for text] expected: FAIL - [files attribute must return null for text] - expected: FAIL - [valueAsDate attribute must return null for text] expected: FAIL @@ -24,9 +21,6 @@ [Value sanitization algorithm should strip line breaks for search] expected: FAIL - [files attribute must return null for search] - expected: FAIL - [valueAsDate attribute must return null for search] expected: FAIL diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index c274c632fd7..2fcfe5ff25b 100644 --- a/tests/wpt/mozilla/meta/MANIFEST.json +++ b/tests/wpt/mozilla/meta/MANIFEST.json @@ -4022,6 +4022,18 @@ "viewport_size": "300x300" } ], + "css/pixel_snapping_glyphs.html": [ + { + "path": "css/pixel_snapping_glyphs.html", + "references": [ + [ + "/_mozilla/css/pixel_snapping_glyphs_ref.html", + "==" + ] + ], + "url": "/_mozilla/css/pixel_snapping_glyphs.html" + } + ], "css/pixel_snapping_position_a.html": [ { "dpi": "2", @@ -5509,7 +5521,8 @@ "==" ] ], - "url": "/_mozilla/css/viewport_meta.html" + "url": "/_mozilla/css/viewport_meta.html", + "viewport_size": "800x600" } ], "css/viewport_percentage_vmin_vmax_a.html": [ @@ -5573,7 +5586,8 @@ "==" ] ], - "url": "/_mozilla/css/viewport_rule.html" + "url": "/_mozilla/css/viewport_rule.html", + "viewport_size": "800x600" } ], "css/visibility_hidden.html": [ @@ -6058,6 +6072,12 @@ ] }, "testharness": { + "css/empty-keyframes.html": [ + { + "path": "css/empty-keyframes.html", + "url": "/_mozilla/css/empty-keyframes.html" + } + ], "css/flex-item-assign-inline-size.html": [ { "path": "css/flex-item-assign-inline-size.html", @@ -11122,6 +11142,18 @@ "viewport_size": "300x300" } ], + "css/pixel_snapping_glyphs.html": [ + { + "path": "css/pixel_snapping_glyphs.html", + "references": [ + [ + "/_mozilla/css/pixel_snapping_glyphs_ref.html", + "==" + ] + ], + "url": "/_mozilla/css/pixel_snapping_glyphs.html" + } + ], "css/pixel_snapping_position_a.html": [ { "dpi": "2", @@ -12609,7 +12641,8 @@ "==" ] ], - "url": "/_mozilla/css/viewport_meta.html" + "url": "/_mozilla/css/viewport_meta.html", + "viewport_size": "800x600" } ], "css/viewport_percentage_vmin_vmax_a.html": [ @@ -12673,7 +12706,8 @@ "==" ] ], - "url": "/_mozilla/css/viewport_rule.html" + "url": "/_mozilla/css/viewport_rule.html", + "viewport_size": "800x600" } ], "css/visibility_hidden.html": [ diff --git a/tests/wpt/mozilla/meta/css/pixel_snapping_glyphs.html.ini b/tests/wpt/mozilla/meta/css/pixel_snapping_glyphs.html.ini new file mode 100644 index 00000000000..76450e5e84d --- /dev/null +++ b/tests/wpt/mozilla/meta/css/pixel_snapping_glyphs.html.ini @@ -0,0 +1,4 @@ +[pixel_snapping_glyphs.html] + type: reftest + expected: + if os == "mac": FAIL diff --git a/tests/wpt/mozilla/tests/css/empty-keyframes.html b/tests/wpt/mozilla/tests/css/empty-keyframes.html new file mode 100644 index 00000000000..9f8935fb7f5 --- /dev/null +++ b/tests/wpt/mozilla/tests/css/empty-keyframes.html @@ -0,0 +1,14 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Empty keyframes rule</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style id=style> +@keyframes foo {} +</style> +<div id=log></div> +<script> +test(function() { + // Check that it is exposed in the CSSOM. +}); +</script> diff --git a/tests/wpt/mozilla/tests/css/pixel_snapping_glyphs.html b/tests/wpt/mozilla/tests/css/pixel_snapping_glyphs.html new file mode 100644 index 00000000000..a423250c4d4 --- /dev/null +++ b/tests/wpt/mozilla/tests/css/pixel_snapping_glyphs.html @@ -0,0 +1,5 @@ +<!doctype html> +<meta charset="utf-8"> +<title>pixel snapping glyphs test</title> +<link rel="match" href="pixel_snapping_glyphs_ref.html"> +<div style="font: 13px 'Helvetica Neue'; padding: 0.5px;">illisible</div> diff --git a/tests/wpt/mozilla/tests/css/pixel_snapping_glyphs_ref.html b/tests/wpt/mozilla/tests/css/pixel_snapping_glyphs_ref.html new file mode 100644 index 00000000000..92ef1f14e7f --- /dev/null +++ b/tests/wpt/mozilla/tests/css/pixel_snapping_glyphs_ref.html @@ -0,0 +1,4 @@ +<!doctype html> +<meta charset="utf-8"> +<title>pixel snapping glyphs reference</title> +<div style="font: 13px 'Helvetica Neue'; padding: 1px;">illisible</div> diff --git a/tests/wpt/mozilla/tests/css/viewport_meta.html b/tests/wpt/mozilla/tests/css/viewport_meta.html index e3d336c1e0e..69c57539ec5 100644 --- a/tests/wpt/mozilla/tests/css/viewport_meta.html +++ b/tests/wpt/mozilla/tests/css/viewport_meta.html @@ -2,6 +2,7 @@ <html> <head> <link rel=match href=viewport_rule_ref.html> + <meta name=viewport-size content=800x600> <meta name="viewport" content="width=240"> <style> #container { diff --git a/tests/wpt/mozilla/tests/css/viewport_rule.html b/tests/wpt/mozilla/tests/css/viewport_rule.html index 36d0d4c0082..09d9c72a165 100644 --- a/tests/wpt/mozilla/tests/css/viewport_rule.html +++ b/tests/wpt/mozilla/tests/css/viewport_rule.html @@ -2,6 +2,7 @@ <html> <head> <link rel=match href=viewport_rule_ref.html> + <meta name=viewport-size content=800x600> <style> @viewport { height: auto; diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/navigating-across-documents/empty_fragment.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/navigating-across-documents/empty_fragment.html new file mode 100644 index 00000000000..18a6f84c9f5 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/navigating-across-documents/empty_fragment.html @@ -0,0 +1,20 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Navigating to the same URL with an empty fragment aborts the navigation</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<iframe src="empty_fragment_iframe.html"></iframe> +<script> +// If the navigation were not aborted, we would expect multiple load events +// as the page continually reloads itself. +async_test(function(t) { + var count = 0; + var iframe = document.querySelector('iframe'); + iframe.onload = t.step_func(function() { + count++; + }); + window.child_succeeded = t.step_func_done(function() { + assert_equals(count, 1); + }); +}); +</script> diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/navigating-across-documents/empty_fragment_iframe.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/navigating-across-documents/empty_fragment_iframe.html new file mode 100644 index 00000000000..26b28a0d7dc --- /dev/null +++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/navigating-across-documents/empty_fragment_iframe.html @@ -0,0 +1,11 @@ +<script> +var timeout; +onload = function() { + location.hash = ""; + timeout = setTimeout(function() { parent.child_succeeded() }, 2000); +}; + +onbeforeunload = function() { + clearTimeout(timeout); +} +</script> diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-link-element/link-style-error-01.html b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-link-element/link-style-error-01.html index ce35e03d93f..04608460b83 100644 --- a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-link-element/link-style-error-01.html +++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-link-element/link-style-error-01.html @@ -7,17 +7,32 @@ <div id="log"></div> <div id="test"> <script> -//var t404 = async_test("Should get an error event for a 404 error.") -//t404.step(function() { -// var elt = document.createElement("link"); -// elt.onerror = t404.step_func(function() { -// assert_true(true, "Got error event for 404 error.") -// t404.done() -// }) -// elt.rel = "stylesheet"; -// elt.href = 404 error; -// document.getElementsByTagName("head")[0].appendChild(elt); -//}) +var t404 = async_test("Should get an error event for a 404 error.") +t404.step(function() { + var elt = document.createElement("link"); + elt.onerror = t404.step_func(function() { + assert_true(true, "Got error event for 404 error.") + t404.step_timeout(function() { t404.done() }, 0); + }) + elt.onload = t404.unreached_func("load event should not be fired"); + elt.rel = "stylesheet"; + elt.href = "nonexistent_stylesheet.css"; + document.getElementsByTagName("head")[0].appendChild(elt); +}) + +var tUnsupported = async_test("Should get an error event for an unsupported URL.") +tUnsupported.step(function() { + var elt = document.createElement("link"); + elt.onerror = tUnsupported.step_func(function() { + assert_true(true, "Got error event for unsupported URL.") + tUnsupported.step_timeout(function() { tUnsupported.done() }, 0); + }) + elt.onload = tUnsupported.unreached_func("load event should not be fired"); + elt.rel = "stylesheet"; + elt.href = "nonexistent:stylesheet.css"; + document.getElementsByTagName("head")[0].appendChild(elt); +}) + var tText = async_test("Should get an error event for a text/plain response.") tText.step(function() { var elt = document.createElement("link"); diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html index 5f525736201..60d591bafab 100644 --- a/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html +++ b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html @@ -32,6 +32,18 @@ test(function() { },'input setSelectionRange(0,input.value.length+1)'); test(function() { + input.setSelectionRange(input.value.length+1,input.value.length+1) + assert_equals(input.selectionStart, input.value.length, "Arguments (start) greater than the length of the value of the text field must be treated as pointing at the end of the text field"); + assert_equals(input.selectionEnd, input.value.length, "Arguments (end) greater than the length of the value of the text field must be treated as pointing at the end of the text field"); + },'input setSelectionRange(input.value.length+1,input.value.length+1)'); + + test(function() { + input.setSelectionRange(input.value.length+1,1) + assert_equals(input.selectionStart, 1, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end"); + assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1"); + },'input setSelectionRange(input.value.length+1,input.value.length+1)'); + + test(function() { input.setSelectionRange(2,2) assert_equals(input.selectionStart, 2, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end"); assert_equals(input.selectionEnd, 2, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end"); @@ -74,6 +86,18 @@ test(function() { },'input direction of setSelectionRange(0,1)'); test(function() { + input.setSelectionRange(1,-1); + assert_equals(input.selectionStart, 1, "element.selectionStart should be 1"); + assert_equals(input.selectionEnd, input.value.length, "ECMAScript conversion to unsigned long"); + },'input setSelectionRange(1,-1)'); + + test(function() { + input.setSelectionRange(-1,1); + assert_equals(input.selectionStart, 1, "ECMAScript conversion to unsigned long + if end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end"); + assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1"); + },'input setSelectionRange(-1,1)'); + + test(function() { input.setSelectionRange("string",1); assert_equals(input.selectionStart, 0, "element.selectionStart should be 0"); assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1"); |