diff options
71 files changed, 829 insertions, 1344 deletions
diff --git a/appveyor.yml b/appveyor.yml index a313b572d5b..6c3eb9b1e83 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -50,7 +50,7 @@ install: - if %BUILD_ENV%==gnu set MSYS=winsymlinks=lnk - if %BUILD_ENV%==gnu bash -lc "echo $MSYSTEM; pacman --needed --noconfirm -Sy pacman-mirrors" - if %BUILD_ENV%==gnu bash -lc "pacman --noconfirm -Sy" - - if %BUILD_ENV%==gnu bash -lc "pacman -Sy --needed --noconfirm git mingw-w64-x86_64-toolchain mingw-w64-x86_64-freetype mingw-w64-x86_64-icu mingw-w64-x86_64-nspr mingw-w64-x86_64-ca-certificates mingw-w64-x86_64-expat mingw-w64-x86_64-cmake tar diffutils patch patchutils make python2-setuptools mingw-w64-x86_64-ffmpeg" + - if %BUILD_ENV%==gnu bash -lc "pacman -Sy --needed --noconfirm mingw-w64-x86_64-toolchain mingw-w64-x86_64-freetype mingw-w64-x86_64-icu mingw-w64-x86_64-nspr mingw-w64-x86_64-ca-certificates mingw-w64-x86_64-expat mingw-w64-x86_64-cmake tar diffutils patch patchutils make python2-setuptools mingw-w64-x86_64-ffmpeg" - if %BUILD_ENV%==gnu bash -lc "easy_install-2.7 pip virtualenv" - if %BUILD_ENV%==gnu bash -lc "mv /mingw64/bin/python2.exe /mingw64/bin/python2-mingw64.exe" - if %BUILD_ENV%==gnu bash -lc "mv /mingw64/bin/python2.7.exe /mingw64/bin/python2.7-mingw64.exe" diff --git a/components/devtools_traits/lib.rs b/components/devtools_traits/lib.rs index 17362ed5558..3155835fefe 100644 --- a/components/devtools_traits/lib.rs +++ b/components/devtools_traits/lib.rs @@ -38,13 +38,13 @@ use url::Url; // Information would be attached to NewGlobal to be received and show in devtools. // Extend these fields if we need more information. -#[derive(Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize)] pub struct DevtoolsPageInfo { pub title: String, pub url: Url } -#[derive(Deserialize, HeapSizeOf, Serialize, Clone)] +#[derive(Debug, Deserialize, HeapSizeOf, Serialize, Clone)] pub struct CSSError { pub filename: String, pub line: usize, @@ -54,6 +54,7 @@ pub struct CSSError { /// Messages to instruct the devtools server to update its known actors/state /// according to changes in the browser. +#[derive(Debug)] pub enum DevtoolsControlMsg { /// Messages from threads in the chrome process (resource/constellation/devtools) FromChrome(ChromeToDevtoolsControlMsg), @@ -62,6 +63,7 @@ pub enum DevtoolsControlMsg { } /// Events that the devtools server must act upon. +#[derive(Debug)] pub enum ChromeToDevtoolsControlMsg { /// A new client has connected to the server. AddClient(TcpStream), @@ -72,7 +74,7 @@ pub enum ChromeToDevtoolsControlMsg { NetworkEvent(String, NetworkEvent), } -#[derive(Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize)] /// Events that the devtools server must act upon. pub enum ScriptToDevtoolsControlMsg { /// A new global object was created, associated with a particular pipeline. @@ -92,7 +94,7 @@ pub enum ScriptToDevtoolsControlMsg { /// Serialized JS return values /// TODO: generalize this beyond the EvaluateJS message? -#[derive(Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize)] pub enum EvaluateJSReply { VoidValue, NullValue, @@ -102,14 +104,14 @@ pub enum EvaluateJSReply { ActorValue { class: String, uuid: String }, } -#[derive(Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize)] pub struct AttrInfo { pub namespace: String, pub name: String, pub value: String, } -#[derive(Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize)] pub struct NodeInfo { pub uniqueId: String, pub baseURI: String, @@ -137,7 +139,7 @@ pub struct StartedTimelineMarker { start_stack: Option<Vec<()>>, } -#[derive(Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize)] pub struct TimelineMarker { pub name: String, pub start_time: PreciseTime, @@ -146,14 +148,14 @@ pub struct TimelineMarker { pub end_stack: Option<Vec<()>>, } -#[derive(PartialEq, Eq, Hash, Clone, Deserialize, Serialize, HeapSizeOf)] +#[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize, Serialize, HeapSizeOf)] pub enum TimelineMarkerType { Reflow, DOMEvent, } /// The properties of a DOM node as computed by layout. -#[derive(Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize)] pub struct ComputedNodeLayout { pub display: String, pub position: String, @@ -180,7 +182,7 @@ pub struct ComputedNodeLayout { pub height: f32, } -#[derive(Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize)] pub struct AutoMargins { pub top: bool, pub right: bool, @@ -190,7 +192,7 @@ pub struct AutoMargins { /// Messages to process in a particular script thread, as instructed by a devtools client. /// TODO: better error handling, e.g. if pipeline id lookup fails? -#[derive(Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize)] pub enum DevtoolScriptControlMsg { /// Evaluate a JS snippet in the context of the global for the given pipeline. EvaluateJS(PipelineId, String, IpcSender<EvaluateJSReply>), @@ -219,13 +221,13 @@ pub enum DevtoolScriptControlMsg { Reload(PipelineId), } -#[derive(Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize)] pub struct Modification { pub attributeName: String, pub newValue: Option<String>, } -#[derive(Clone, Deserialize, Serialize)] +#[derive(Debug, Clone, Deserialize, Serialize)] pub enum LogLevel { Log, Debug, @@ -234,7 +236,7 @@ pub enum LogLevel { Error, } -#[derive(Clone, Deserialize, Serialize)] +#[derive(Debug, Clone, Deserialize, Serialize)] pub struct ConsoleMessage { pub message: String, pub logLevel: LogLevel, @@ -251,7 +253,7 @@ bitflags! { } } -#[derive(Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize)] pub struct PageError { #[serde(rename = "_type")] pub type_: String, @@ -269,7 +271,7 @@ pub struct PageError { pub private: bool, } -#[derive(Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize)] pub struct ConsoleAPI { #[serde(rename = "_type")] pub type_: String, @@ -282,7 +284,7 @@ pub struct ConsoleAPI { pub arguments: Vec<String>, } -#[derive(Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize)] pub enum CachedConsoleMessage { PageError(PageError), ConsoleAPI(ConsoleAPI), @@ -310,6 +312,7 @@ pub struct HttpResponse { pub pipeline_id: PipelineId, } +#[derive(Debug)] pub enum NetworkEvent { HttpRequest(HttpRequest), HttpResponse(HttpResponse), @@ -343,7 +346,7 @@ impl StartedTimelineMarker { /// library, which definitely can't have any dependencies on `serde`. But `serde` can't implement /// `Deserialize` and `Serialize` itself, because `time::PreciseTime` is opaque! A Catch-22. So I'm /// duplicating the definition here. -#[derive(Copy, Clone, Deserialize, Serialize)] +#[derive(Debug, Copy, Clone, Deserialize, Serialize)] pub struct PreciseTime(u64); impl PreciseTime { diff --git a/components/layout/block.rs b/components/layout/block.rs index 7702783bf4c..45de8786778 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -41,6 +41,7 @@ use flow::{ImmutableFlowUtils, LateAbsolutePositionInfo, MutableFlowUtils, Opaqu use flow::IS_ABSOLUTELY_POSITIONED; use flow_list::FlowList; use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow}; +use fragment::{IS_INLINE_FLEX_ITEM, IS_BLOCK_FLEX_ITEM}; use fragment::SpecificFragmentInfo; use gfx::display_list::{ClippingRegion, StackingContext}; use gfx_traits::ScrollRootId; @@ -484,7 +485,7 @@ pub enum BlockType { FloatNonReplaced, InlineBlockReplaced, InlineBlockNonReplaced, - FlexItem, + InlineFlexItem, } #[derive(Clone, PartialEq)] @@ -520,8 +521,6 @@ bitflags! { flags BlockFlowFlags: u8 { #[doc = "If this is set, then this block flow is the root flow."] const IS_ROOT = 0b0000_0001, - #[doc = "Whether this block flow is a child of a flex container."] - const IS_FLEX = 0b0001_0000, } } @@ -561,8 +560,8 @@ impl BlockFlow { } else { BlockType::AbsoluteNonReplaced } - } else if self.is_flex() { - BlockType::FlexItem + } else if self.is_inline_flex_item() { + BlockType::InlineFlexItem } else if self.base.flags.is_float() { if self.is_replaced_content() { BlockType::FloatReplaced @@ -638,8 +637,8 @@ impl BlockFlow { shared_context, containing_block_inline_size); } - BlockType::FlexItem => { - let inline_size_computer = FlexItem; + BlockType::InlineFlexItem => { + let inline_size_computer = InlineFlexItem; inline_size_computer.compute_used_inline_size(self, shared_context, containing_block_inline_size); @@ -1506,7 +1505,7 @@ impl BlockFlow { } // If you remove the might_have_floats_in conditional, this will go off. - debug_assert!(!self.is_flex()); + debug_assert!(!self.is_inline_flex_item()); // Compute the available space for us, based on the actual floats. let rect = self.base.floats.available_rect(Au(0), @@ -1778,12 +1777,12 @@ impl BlockFlow { padding.block_start.is_definitely_zero() && padding.block_end.is_definitely_zero() } - pub fn mark_as_flex(&mut self) { - self.flags.insert(IS_FLEX) + pub fn is_inline_flex_item(&self) -> bool { + self.fragment.flags.contains(IS_INLINE_FLEX_ITEM) } - pub fn is_flex(&self) -> bool { - self.flags.contains(IS_FLEX) + pub fn is_block_flex_item(&self) -> bool { + self.fragment.flags.contains(IS_BLOCK_FLEX_ITEM) } } @@ -2589,7 +2588,7 @@ pub struct FloatNonReplaced; pub struct FloatReplaced; pub struct InlineBlockNonReplaced; pub struct InlineBlockReplaced; -pub struct FlexItem; +pub struct InlineFlexItem; impl ISizeAndMarginsComputer for AbsoluteNonReplaced { /// Solve the horizontal constraint equation for absolute non-replaced elements. @@ -3080,7 +3079,7 @@ impl ISizeAndMarginsComputer for InlineBlockReplaced { } } -impl ISizeAndMarginsComputer for FlexItem { +impl ISizeAndMarginsComputer for InlineFlexItem { // Replace the default method directly to prevent recalculating and setting margins again // which has already been set by its parent. fn compute_used_inline_size(&self, diff --git a/components/layout/construct.rs b/components/layout/construct.rs index 0b489459352..086b323e878 100644 --- a/components/layout/construct.rs +++ b/components/layout/construct.rs @@ -25,14 +25,16 @@ use flow::{MutableFlowUtils, MutableOwnedFlowUtils}; use flow_ref::FlowRef; use fragment::{CanvasFragmentInfo, ImageFragmentInfo, InlineAbsoluteFragmentInfo, SvgFragmentInfo}; use fragment::{Fragment, GeneratedContentInfo, IframeFragmentInfo}; +use fragment::{IS_INLINE_FLEX_ITEM, IS_BLOCK_FLEX_ITEM}; use fragment::{InlineAbsoluteHypotheticalFragmentInfo, TableColumnFragmentInfo}; use fragment::{InlineBlockFragmentInfo, SpecificFragmentInfo, UnscannedTextFragmentInfo}; use fragment::WhitespaceStrippingResult; use gfx::display_list::OpaqueNode; -use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, InlineFragmentNodeFlags}; +use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow}; use inline::{InlineFragmentNodeInfo, LAST_FRAGMENT_OF_ELEMENT}; use linked_list::prepend_from; use list_item::{ListItemFlow, ListStyleTypeContent}; +use model::Direction; use multicol::{MulticolColumnFlow, MulticolFlow}; use parallel; use script_layout_interface::{LayoutElementType, LayoutNodeType, is_image_data}; @@ -159,6 +161,32 @@ pub struct InlineBlockSplit { pub flow: FlowRef, } +impl InlineBlockSplit { + /// Flushes the given accumulator to the new split and makes a new accumulator to hold any + /// subsequent fragments. + fn new<ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>(fragment_accumulator: &mut InlineFragmentsAccumulator, + node: &ConcreteThreadSafeLayoutNode, + style_context: &SharedStyleContext, + flow: FlowRef) + -> InlineBlockSplit { + fragment_accumulator.enclosing_node.as_mut().expect( + "enclosing_node is None; Are {ib} splits being generated outside of an inline node?" + ).flags.remove(LAST_FRAGMENT_OF_ELEMENT); + + let split = InlineBlockSplit { + predecessors: mem::replace( + fragment_accumulator, + InlineFragmentsAccumulator::from_inline_node( + node, style_context)).to_intermediate_inline_fragments(), + flow: flow, + }; + + fragment_accumulator.enclosing_node.as_mut().unwrap().flags.remove(FIRST_FRAGMENT_OF_ELEMENT); + + split + } +} + /// Holds inline fragments and absolute descendants. #[derive(Clone)] pub struct IntermediateInlineFragments { @@ -192,8 +220,14 @@ struct InlineFragmentsAccumulator { /// The list of fragments. fragments: IntermediateInlineFragments, - /// Whether we've created a range to enclose all the fragments. This will be Some() if the - /// outer node is an inline and None otherwise. + /// Information about the inline box directly enclosing the fragments being gathered, if any. + /// + /// `inline::InlineFragmentNodeInfo` also stores flags indicating whether a fragment is the + /// first and/or last of the corresponding inline box. This `InlineFragmentsAccumulator` may + /// represent only one side of an {ib} split, so we store these flags as if it represented only + /// one fragment. `to_intermediate_inline_fragments` later splits this hypothetical fragment + /// into pieces, leaving the `FIRST_FRAGMENT_OF_ELEMENT` and `LAST_FRAGMENT_OF_ELEMENT` flags, + /// if present, on the first and last fragments of the output. enclosing_node: Option<InlineFragmentNodeInfo>, /// Restyle damage to use for fragments created in this node. @@ -222,7 +256,7 @@ impl InlineFragmentsAccumulator { pseudo: node.get_pseudo_element_type().strip(), style: node.style(style_context), selected_style: node.selected_style(), - flags: InlineFragmentNodeFlags::empty(), + flags: FIRST_FRAGMENT_OF_ELEMENT | LAST_FRAGMENT_OF_ELEMENT, }), bidi_control_chars: None, restyle_damage: node.restyle_damage(), @@ -245,21 +279,23 @@ impl InlineFragmentsAccumulator { bidi_control_chars, restyle_damage, } = self; - if let Some(enclosing_node) = enclosing_node { + if let Some(mut enclosing_node) = enclosing_node { let fragment_count = fragments.fragments.len(); for (index, fragment) in fragments.fragments.iter_mut().enumerate() { let mut enclosing_node = enclosing_node.clone(); - if index == 0 { - enclosing_node.flags.insert(FIRST_FRAGMENT_OF_ELEMENT) + if index != 0 { + enclosing_node.flags.remove(FIRST_FRAGMENT_OF_ELEMENT) } - if index == fragment_count - 1 { - enclosing_node.flags.insert(LAST_FRAGMENT_OF_ELEMENT) + if index != fragment_count - 1 { + enclosing_node.flags.remove(LAST_FRAGMENT_OF_ELEMENT) } fragment.add_inline_context_style(enclosing_node); } // Control characters are later discarded in transform_text, so they don't affect the // is_first/is_last styles above. + enclosing_node.flags.remove(FIRST_FRAGMENT_OF_ELEMENT | LAST_FRAGMENT_OF_ELEMENT); + if let Some((start, end)) = bidi_control_chars { fragments.fragments.push_front( control_chars_to_fragment(&enclosing_node, start, restyle_damage)); @@ -715,14 +751,8 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> } = split; fragment_accumulator.push_all(predecessors); - let split = InlineBlockSplit { - predecessors: mem::replace( - fragment_accumulator, - InlineFragmentsAccumulator::from_inline_node( - node, self.style_context())).to_intermediate_inline_fragments(), - flow: kid_flow, - }; - opt_inline_block_splits.push_back(split) + opt_inline_block_splits.push_back( + InlineBlockSplit::new(fragment_accumulator, node, self.style_context(), kid_flow)); } } @@ -749,17 +779,8 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> ConstructionResult::None => {} ConstructionResult::Flow(flow, kid_abs_descendants) => { if !flow::base(&*flow).flags.contains(IS_ABSOLUTELY_POSITIONED) { - // {ib} split. Flush the accumulator to our new split and make a new - // accumulator to hold any subsequent fragments we come across. - let split = InlineBlockSplit { - predecessors: - mem::replace( - &mut fragment_accumulator, - InlineFragmentsAccumulator::from_inline_node( - node, self.style_context())).to_intermediate_inline_fragments(), - flow: flow, - }; - opt_inline_block_splits.push_back(split); + opt_inline_block_splits.push_back(InlineBlockSplit::new( + &mut fragment_accumulator, node, self.style_context(), flow)); abs_descendants.push_descendants(kid_abs_descendants); } else { // Push the absolutely-positioned kid as an inline containing block. @@ -1928,9 +1949,16 @@ impl Legalizer { &[PseudoElement::ServoAnonymousBlock], SpecificFragmentInfo::Generic, BlockFlow::from_fragment); - flow::mut_base(FlowRef::deref_mut(&mut - block_wrapper)).flags - .insert(MARGINS_CANNOT_COLLAPSE); + { + let flag = if parent.as_flex().main_mode() == Direction::Inline { + IS_INLINE_FLEX_ITEM + } else { + IS_BLOCK_FLEX_ITEM + }; + let mut block = FlowRef::deref_mut(&mut block_wrapper).as_mut_block(); + block.base.flags.insert(MARGINS_CANNOT_COLLAPSE); + block.fragment.flags.insert(flag); + } block_wrapper.add_new_child((*child).clone()); block_wrapper.finish(); parent.add_new_child(block_wrapper); @@ -1938,7 +1966,16 @@ impl Legalizer { } (FlowClass::Flex, _) => { - flow::mut_base(FlowRef::deref_mut(child)).flags.insert(MARGINS_CANNOT_COLLAPSE); + { + let flag = if parent.as_flex().main_mode() == Direction::Inline { + IS_INLINE_FLEX_ITEM + } else { + IS_BLOCK_FLEX_ITEM + }; + let mut block = FlowRef::deref_mut(child).as_mut_block(); + block.base.flags.insert(MARGINS_CANNOT_COLLAPSE); + block.fragment.flags.insert(flag); + } parent.add_new_child((*child).clone()); true } diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index 3e5328afc27..ec881ea9bcb 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -52,9 +52,8 @@ use style::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize, WritingMod use style::properties::{self, ServoComputedValues}; use style::properties::style_structs; use style::servo::restyle_damage::REPAINT; -use style::values::RGBA; -use style::values::computed; -use style::values::computed::{Gradient, GradientKind, LengthOrNone, LengthOrPercentage, LengthOrPercentageOrAuto}; +use style::values::{self, Either, RGBA, computed}; +use style::values::computed::{Gradient, GradientKind, LengthOrPercentage, LengthOrPercentageOrAuto}; use style::values::specified::{AngleOrCorner, HorizontalDirection, VerticalDirection}; use style_traits::cursor::Cursor; use table_cell::CollapsedBordersForCell; @@ -1563,7 +1562,7 @@ impl FragmentDisplayListBuilding for Fragment { let transform = self.transform_matrix(&border_box); let perspective = match self.style().get_effects().perspective { - LengthOrNone::Length(d) => { + Either::First(length) => { let perspective_origin = self.style().get_effects().perspective_origin; let perspective_origin = Point2D::new(model::specified(perspective_origin.horizontal, @@ -1578,11 +1577,11 @@ impl FragmentDisplayListBuilding for Fragment { -perspective_origin.y, 0.0); - let perspective_matrix = create_perspective_matrix(d); + let perspective_matrix = create_perspective_matrix(length); pre_transform.pre_mul(&perspective_matrix).pre_mul(&post_transform) } - LengthOrNone::None => { + Either::Second(values::None_) => { Matrix4D::identity() } }; diff --git a/components/layout/flex.rs b/components/layout/flex.rs index 337abc3227a..b2ee3555857 100644 --- a/components/layout/flex.rs +++ b/components/layout/flex.rs @@ -395,6 +395,10 @@ impl FlexFlow { } } + pub fn main_mode(&self) -> Direction { + self.main_mode + } + /// Returns a line start after the last item that is already in a line. /// Note that when the container main size is infinite(i.e. A column flexbox with auto height), /// we do not need to do flex resolving and this can be considered as a fast-path, so the @@ -613,8 +617,6 @@ impl FlexFlow { // // TODO(#2265, pcwalton): Do this in the cascade instead. block.base.flags.set_text_align(containing_block_text_align); - // FIXME(stshine): should this be done during construction? - block.mark_as_flex(); let margin = block.fragment.style().logical_margin(); let auto_len = @@ -810,6 +812,14 @@ impl Flow for FlexFlow { FlowClass::Flex } + fn as_mut_flex(&mut self) -> &mut FlexFlow { + self + } + + fn as_flex(&self) -> &FlexFlow { + self + } + fn as_block(&self) -> &BlockFlow { &self.block_flow } diff --git a/components/layout/flow.rs b/components/layout/flow.rs index 3da277d924d..fae309d2ae2 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -30,6 +30,7 @@ use block::{BlockFlow, FormattingContextType}; use context::{LayoutContext, SharedLayoutContext}; use display_list_builder::DisplayListBuildState; use euclid::{Point2D, Size2D}; +use flex::FlexFlow; use floats::{Floats, SpeculatedFloatPlacement}; use flow_list::{FlowList, MutFlowListIterator}; use flow_ref::{FlowRef, WeakFlowRef}; @@ -86,6 +87,16 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static { panic!("called as_mut_block() on a non-block flow") } + /// If this is a flex flow, returns the underlying object. Fails otherwise. + fn as_flex(&self) -> &FlexFlow { + panic!("called as_flex() on a non-flex flow") + } + + /// If this is a flex flow, returns the underlying object, borrowed mutably. Fails otherwise. + fn as_mut_flex(&mut self) -> &mut FlexFlow { + panic!("called as_mut_flex() on a non-flex flow") + } + /// If this is an inline flow, returns the underlying object. Fails otherwise. fn as_inline(&self) -> &InlineFlow { panic!("called as_inline() on a non-inline flow") diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index 1fa3ae0612a..2c193d09e41 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -49,7 +49,8 @@ use style::properties::ServoComputedValues; use style::selector_impl::RestyleDamage; use style::servo::restyle_damage::RECONSTRUCT_FLOW; use style::str::char_is_whitespace; -use style::values::computed::{LengthOrNone, LengthOrPercentage, LengthOrPercentageOrAuto}; +use style::values::Either; +use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto}; use style::values::computed::LengthOrPercentageOrNone; use text; use text::TextRunScanner; @@ -123,6 +124,9 @@ pub struct Fragment { /// The pseudo-element that this fragment represents. pub pseudo: PseudoElementType<()>, + /// Various flags for this fragment. + pub flags: FragmentFlags, + /// A debug ID that is consistent for the life of this fragment (via transform etc). /// This ID should not be considered stable across multiple layouts or fragment /// manipulations. @@ -917,6 +921,7 @@ impl Fragment { specific: specific, inline_context: None, pseudo: node.get_pseudo_element_type().strip(), + flags: FragmentFlags::empty(), debug_id: DebugId::new(), stacking_context_id: StackingContextId::new(0), } @@ -945,6 +950,7 @@ impl Fragment { specific: specific, inline_context: None, pseudo: pseudo, + flags: FragmentFlags::empty(), debug_id: DebugId::new(), stacking_context_id: StackingContextId::new(0), } @@ -969,6 +975,7 @@ impl Fragment { specific: specific, inline_context: None, pseudo: self.pseudo, + flags: FragmentFlags::empty(), debug_id: DebugId::new(), stacking_context_id: StackingContextId::new(0), } @@ -996,6 +1003,7 @@ impl Fragment { specific: info, inline_context: self.inline_context.clone(), pseudo: self.pseudo.clone(), + flags: FragmentFlags::empty(), debug_id: self.debug_id.clone(), stacking_context_id: StackingContextId::new(0), } @@ -1029,12 +1037,15 @@ impl Fragment { } /// Transforms this fragment into an ellipsis fragment, preserving all the other data. - pub fn transform_into_ellipsis(&self, layout_context: &LayoutContext) -> Fragment { + pub fn transform_into_ellipsis(&self, + layout_context: &LayoutContext, + text_overflow_string: String) + -> Fragment { let mut unscanned_ellipsis_fragments = LinkedList::new(); unscanned_ellipsis_fragments.push_back(self.transform( self.border_box.size, SpecificFragmentInfo::UnscannedText( - box UnscannedTextFragmentInfo::new("…".to_owned(), None)))); + box UnscannedTextFragmentInfo::new(text_overflow_string, None)))); let ellipsis_fragments = TextRunScanner::new().scan_for_runs(&mut layout_context.font_context(), unscanned_ellipsis_fragments); debug_assert!(ellipsis_fragments.len() == 1); @@ -2579,7 +2590,7 @@ impl Fragment { // TODO(mrobinson): Determine if this is necessary, since blocks with // transformations already create stacking contexts. - if self.style().get_effects().perspective != LengthOrNone::None { + if let Either::First(ref _length) = self.style().get_effects().perspective { return true } @@ -3111,6 +3122,16 @@ impl Overflow { } } +bitflags! { + pub flags FragmentFlags: u8 { + // TODO(stshine): find a better name since these flags can also be used for grid item. + /// Whether this fragment represents a child in a row flex container. + const IS_INLINE_FLEX_ITEM = 0b0000_0001, + /// Whether this fragment represents a child in a column flex container. + const IS_BLOCK_FLEX_ITEM = 0b0000_0010, + } +} + /// Specified distances from the margin edge of a block to its content in the inline direction. /// These are returned by `guess_inline_content_edge_offsets()` and are used in the float placement /// speculation logic. diff --git a/components/layout/inline.rs b/components/layout/inline.rs index 735ee0acf90..57eb16f1b84 100644 --- a/components/layout/inline.rs +++ b/components/layout/inline.rs @@ -31,10 +31,10 @@ use std::collections::VecDeque; use std::sync::Arc; use style::arc_ptr_eq; use style::computed_values::{display, overflow_x, position, text_align, text_justify}; -use style::computed_values::{text_overflow, vertical_align, white_space}; +use style::computed_values::{vertical_align, white_space}; use style::context::{SharedStyleContext, StyleContext}; use style::logical_geometry::{LogicalRect, LogicalSize, WritingMode}; -use style::properties::ServoComputedValues; +use style::properties::{longhands, ServoComputedValues}; use style::servo::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPOSITION, RESOLVE_GENERATED_CONTENT}; use text; use unicode_bidi; @@ -684,21 +684,30 @@ impl LineBreaker { } // Determine if an ellipsis will be necessary to account for `text-overflow`. - let mut need_ellipsis = false; let available_inline_size = self.pending_line.green_zone.inline - self.pending_line.bounds.size.inline - indentation; - match (fragment.style().get_text().text_overflow, - fragment.style().get_box().overflow_x) { - (text_overflow::T::clip, _) | (_, overflow_x::T::visible) => {} - (text_overflow::T::ellipsis, _) => { - need_ellipsis = fragment.margin_box_inline_size() > available_inline_size; + + let ellipsis = match (&fragment.style().get_text().text_overflow.first, + fragment.style().get_box().overflow_x) { + (&longhands::text_overflow::Side::Clip, _) | (_, overflow_x::T::visible) => None, + (&longhands::text_overflow::Side::Ellipsis, _) => { + if fragment.margin_box_inline_size() > available_inline_size { + Some("…".to_string()) + } else { + None + } + }, + (&longhands::text_overflow::Side::String(ref string), _) => { + if fragment.margin_box_inline_size() > available_inline_size { + Some(string.to_string()) + } else { + None + } } - } + }; - if !need_ellipsis { - self.push_fragment_to_line_ignoring_text_overflow(fragment, layout_context); - } else { - let ellipsis = fragment.transform_into_ellipsis(layout_context); + if let Some(string) = ellipsis { + let ellipsis = fragment.transform_into_ellipsis(layout_context, string); if let Some(truncation_info) = fragment.truncate_to_inline_size(available_inline_size - ellipsis.margin_box_inline_size()) { @@ -707,6 +716,8 @@ impl LineBreaker { self.push_fragment_to_line_ignoring_text_overflow(fragment, layout_context); } self.push_fragment_to_line_ignoring_text_overflow(ellipsis, layout_context); + } else { + self.push_fragment_to_line_ignoring_text_overflow(fragment, layout_context); } if line_flush_mode == LineFlushMode::Flush { diff --git a/components/layout/model.rs b/components/layout/model.rs index 4d2ef8e8c87..d57bb2628fa 100644 --- a/components/layout/model.rs +++ b/components/layout/model.rs @@ -505,7 +505,7 @@ impl ToGfxMatrix for ComputedMatrix { } // Used to specify the logical direction. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq)] pub enum Direction { Inline, Block diff --git a/components/net/image_cache_thread.rs b/components/net/image_cache_thread.rs index 440ebd32100..5929100e2a1 100644 --- a/components/net/image_cache_thread.rs +++ b/components/net/image_cache_thread.rs @@ -323,7 +323,11 @@ fn get_placeholder_image(webrender_api: &webrender_traits::RenderApi) -> io::Res let format = convert_format(image.format); let mut bytes = Vec::new(); bytes.extend_from_slice(&*image.bytes); - image.id = Some(webrender_api.add_image(image.width, image.height, format, bytes)); + image.id = Some(webrender_api.add_image(image.width, + image.height, + None, + format, + bytes)); Ok(Arc::new(image)) } @@ -478,7 +482,11 @@ impl ImageCache { let format = convert_format(image.format); let mut bytes = Vec::new(); bytes.extend_from_slice(&*image.bytes); - image.id = Some(self.webrender_api.add_image(image.width, image.height, format, bytes)); + image.id = Some(self.webrender_api.add_image(image.width, + image.height, + None, + format, + bytes)); } LoadResult::PlaceholderLoaded(..) | LoadResult::None => {} } diff --git a/components/net_traits/request.rs b/components/net_traits/request.rs index 0e820a2728c..ef905ebccd8 100644 --- a/components/net_traits/request.rs +++ b/components/net_traits/request.rs @@ -81,7 +81,7 @@ pub enum CacheMode { } /// [Redirect mode](https://fetch.spec.whatwg.org/#concept-request-redirect-mode) -#[derive(Copy, Clone, PartialEq, HeapSizeOf)] +#[derive(Copy, Clone, PartialEq, Serialize, Deserialize, HeapSizeOf)] pub enum RedirectMode { Follow, Error, @@ -137,6 +137,7 @@ pub struct RequestInit { pub referrer_url: Option<Url>, pub referrer_policy: Option<ReferrerPolicy>, pub pipeline_id: Option<PipelineId>, + pub redirect_mode: RedirectMode, } impl Default for RequestInit { @@ -158,6 +159,7 @@ impl Default for RequestInit { referrer_url: None, referrer_policy: None, pipeline_id: None, + redirect_mode: RedirectMode::Follow, } } } @@ -266,6 +268,7 @@ impl Request { }; req.referrer_policy.set(init.referrer_policy); req.pipeline_id.set(init.pipeline_id); + req.redirect_mode.set(init.redirect_mode); req } diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs index 9fb5a5609f1..90499388153 100644 --- a/components/script/dom/htmllinkelement.rs +++ b/components/script/dom/htmllinkelement.rs @@ -359,8 +359,7 @@ impl FetchResponseListener for StylesheetContext { Some(environment_encoding), Origin::Author, win.css_error_reporter(), ParserContextExtraData::default()); - let media = self.media.take().unwrap(); - sheet.set_media(Some(media)); + sheet.set_media(self.media.take().unwrap()); let sheet = Arc::new(sheet); let win = window_from_node(&*elem); diff --git a/components/script/dom/htmlmetaelement.rs b/components/script/dom/htmlmetaelement.rs index 14f9cd78555..7ddca9f2f8a 100644 --- a/components/script/dom/htmlmetaelement.rs +++ b/components/script/dom/htmlmetaelement.rs @@ -83,7 +83,7 @@ impl HTMLMetaElement { *self.stylesheet.borrow_mut() = Some(Arc::new(Stylesheet { rules: vec![CSSRule::Viewport(Arc::new(RwLock::new(translated_rule)))], origin: Origin::Author, - media: None, + media: Default::default(), // Viewport constraints are always recomputed on resize; they don't need to // force all styles to be recomputed. dirty_on_viewport_size_change: false, diff --git a/components/script/dom/htmlstyleelement.rs b/components/script/dom/htmlstyleelement.rs index 34d5ba79ec9..8c1bc031dc0 100644 --- a/components/script/dom/htmlstyleelement.rs +++ b/components/script/dom/htmlstyleelement.rs @@ -65,8 +65,7 @@ impl HTMLStyleElement { let mut sheet = Stylesheet::from_str(&data, url, Origin::Author, win.css_error_reporter(), ParserContextExtraData::default()); let mut css_parser = CssParser::new(&mq_str); - let media = parse_media_query_list(&mut css_parser); - sheet.set_media(Some(media)); + sheet.set_media(parse_media_query_list(&mut css_parser)); let sheet = Arc::new(sheet); win.layout_chan().send(Msg::AddStylesheet(sheet.clone())).unwrap(); diff --git a/components/script/dom/request.rs b/components/script/dom/request.rs index e9cee6da938..fa649702259 100644 --- a/components/script/dom/request.rs +++ b/components/script/dom/request.rs @@ -308,21 +308,31 @@ impl Request { // Step 27 let mut headers_copy = r.Headers(); - // This is equivalent to the specification's concept of - // "associated headers list". - if let RequestInfo::Request(ref input_request) = input { - headers_copy = input_request.Headers(); - } - // Step 28 if let Some(possible_header) = init.headers.as_ref() { - if let &HeadersInit::Headers(ref init_headers) = possible_header { - headers_copy = init_headers.clone(); + match possible_header { + &HeadersInit::Headers(ref init_headers) => { + headers_copy = init_headers.clone(); + } + &HeadersInit::ByteStringSequenceSequence(ref init_sequence) => { + try!(headers_copy.fill(Some( + HeadersInit::ByteStringSequenceSequence(init_sequence.clone())))); + }, + &HeadersInit::ByteStringMozMap(ref init_map) => { + try!(headers_copy.fill(Some( + HeadersInit::ByteStringMozMap(init_map.clone())))); + }, } } // Step 29 - r.Headers().empty_header_list(); + // We cannot empty `r.Headers().header_list` because + // we would undo the Step 27 above. One alternative is to set + // `headers_copy` as a deep copy of `r.Headers()`. However, + // `r.Headers()` is a `Root<T>`, and therefore it is difficult + // to obtain a mutable reference to `r.Headers()`. Without the + // mutable reference, we cannot mutate `r.Headers()` to be the + // deep copied headers in Step 27. // Step 30 if r.request.borrow().mode == NetTraitsRequestMode::NoCORS { @@ -341,7 +351,19 @@ impl Request { } // Step 31 - try!(r.Headers().fill(Some(HeadersInit::Headers(headers_copy)))); + match init.headers { + None => { + // This is equivalent to the specification's concept of + // "associated headers list". If an init headers is not given, + // but an input with headers is given, set request's + // headers as the input's Headers. + if let RequestInfo::Request(ref input_request) = input { + try!(r.Headers().fill(Some(HeadersInit::Headers(input_request.Headers())))); + } + }, + Some(HeadersInit::Headers(_)) => try!(r.Headers().fill(Some(HeadersInit::Headers(headers_copy)))), + _ => {}, + } // Step 32 let mut input_body = if let RequestInfo::Request(ref input_request) = input { @@ -368,7 +390,6 @@ impl Request { } // Step 34 - // TODO: `ReadableStream` object is not implemented in Servo yet. if let Some(Some(ref init_body)) = init.body { // Step 34.2 let extracted_body_tmp = init_body.extract(); diff --git a/components/script/dom/webglframebuffer.rs b/components/script/dom/webglframebuffer.rs index 8e22f17d079..25026dac22d 100644 --- a/components/script/dom/webglframebuffer.rs +++ b/components/script/dom/webglframebuffer.rs @@ -21,7 +21,7 @@ use webrender_traits::{WebGLCommand, WebGLFramebufferBindingRequest, WebGLFrameb #[derive(JSTraceable, Clone, HeapSizeOf)] enum WebGLFramebufferAttachment { Renderbuffer(JS<WebGLRenderbuffer>), - Texture(JS<WebGLTexture>), + Texture { texture: JS<WebGLTexture>, level: i32 }, } impl HeapGCValue for WebGLFramebufferAttachment {} @@ -33,6 +33,7 @@ pub struct WebGLFramebuffer { /// target can only be gl::FRAMEBUFFER at the moment target: Cell<Option<u32>>, is_deleted: Cell<bool>, + size: Cell<Option<(i32, i32)>>, status: Cell<u32>, #[ignore_heap_size_of = "Defined in ipc-channel"] renderer: IpcSender<CanvasMsg>, @@ -55,6 +56,7 @@ impl WebGLFramebuffer { target: Cell::new(None), is_deleted: Cell::new(false), renderer: renderer, + size: Cell::new(None), status: Cell::new(constants::FRAMEBUFFER_UNSUPPORTED), color: DOMRefCell::new(None), depth: DOMRefCell::new(None), @@ -110,11 +112,20 @@ impl WebGLFramebuffer { self.is_deleted.get() } + pub fn size(&self) -> Option<(i32, i32)> { + self.size.get() + } + fn update_status(&self) { - let has_c = self.color.borrow().is_some(); - let has_z = self.depth.borrow().is_some(); - let has_s = self.stencil.borrow().is_some(); - let has_zs = self.depthstencil.borrow().is_some(); + let c = self.color.borrow(); + let z = self.depth.borrow(); + let s = self.stencil.borrow(); + let zs = self.depthstencil.borrow(); + let has_c = c.is_some(); + let has_z = z.is_some(); + let has_s = s.is_some(); + let has_zs = zs.is_some(); + let attachments = [&*c, &*z, &*s, &*zs]; // From the WebGL spec, 6.6 ("Framebuffer Object Attachments"): // @@ -135,6 +146,33 @@ impl WebGLFramebuffer { return; } + let mut fb_size = None; + for attachment in &attachments { + // Get the size of this attachment. + let size = match **attachment { + Some(WebGLFramebufferAttachment::Renderbuffer(ref att_rb)) => { + att_rb.size() + } + Some(WebGLFramebufferAttachment::Texture { texture: ref att_tex, level } ) => { + let info = att_tex.image_info_at_face(0, level as u32); + Some((info.width() as i32, info.height() as i32)) + } + None => None, + }; + + // Make sure that, if we've found any other attachment, + // that the size matches. + if size.is_some() { + if fb_size.is_some() && size != fb_size { + self.status.set(constants::FRAMEBUFFER_INCOMPLETE_DIMENSIONS); + return; + } else { + fb_size = size; + } + } + } + self.size.set(fb_size); + if has_c || has_z || has_zs || has_s { self.status.set(constants::FRAMEBUFFER_COMPLETE); } else { @@ -190,8 +228,6 @@ impl WebGLFramebuffer { // Note, from the GLES 2.0.25 spec, page 113: // "If texture is zero, then textarget and level are ignored." Some(texture) => { - *binding.borrow_mut() = Some(WebGLFramebufferAttachment::Texture(JS::from_ref(texture))); - // From the GLES 2.0.25 spec, page 113: // // "level specifies the mipmap level of the texture image @@ -231,12 +267,16 @@ impl WebGLFramebuffer { _ => return Err(WebGLError::InvalidOperation), } + *binding.borrow_mut() = Some(WebGLFramebufferAttachment::Texture { + texture: JS::from_ref(texture), + level: level } + ); + Some(texture.id()) } _ => { *binding.borrow_mut() = None; - self.update_status(); None } }; @@ -251,7 +291,9 @@ impl WebGLFramebuffer { Ok(()) } - pub fn detach_renderbuffer(&self, rb: &WebGLRenderbuffer) { + fn with_matching_renderbuffers<F>(&self, rb: &WebGLRenderbuffer, mut closure: F) + where F: FnMut(&DOMRefCell<Option<WebGLFramebufferAttachment>>) + { let attachments = [&self.color, &self.depth, &self.stencil, @@ -267,13 +309,14 @@ impl WebGLFramebuffer { }; if matched { - *attachment.borrow_mut() = None; - self.update_status(); + closure(attachment); } } } - pub fn detach_texture(&self, texture: &WebGLTexture) { + fn with_matching_textures<F>(&self, texture: &WebGLTexture, mut closure: F) + where F: FnMut(&DOMRefCell<Option<WebGLFramebufferAttachment>>) + { let attachments = [&self.color, &self.depth, &self.stencil, @@ -282,18 +325,44 @@ impl WebGLFramebuffer { for attachment in &attachments { let matched = { match *attachment.borrow() { - Some(WebGLFramebufferAttachment::Texture(ref att_texture)) + Some(WebGLFramebufferAttachment::Texture { texture: ref att_texture, .. }) if texture.id() == att_texture.id() => true, _ => false, } }; if matched { - *attachment.borrow_mut() = None; + closure(attachment); } } } + pub fn detach_renderbuffer(&self, rb: &WebGLRenderbuffer) { + self.with_matching_renderbuffers(rb, |att| { + *att.borrow_mut() = None; + self.update_status(); + }); + } + + pub fn detach_texture(&self, texture: &WebGLTexture) { + self.with_matching_textures(texture, |att| { + *att.borrow_mut() = None; + self.update_status(); + }); + } + + pub fn invalidate_renderbuffer(&self, rb: &WebGLRenderbuffer) { + self.with_matching_renderbuffers(rb, |_att| { + self.update_status(); + }); + } + + pub fn invalidate_texture(&self, texture: &WebGLTexture) { + self.with_matching_textures(texture, |_att| { + self.update_status(); + }); + } + pub fn target(&self) -> Option<u32> { self.target.get() } diff --git a/components/script/dom/webglrenderbuffer.rs b/components/script/dom/webglrenderbuffer.rs index 9e3c516cfbd..186b2aedf5a 100644 --- a/components/script/dom/webglrenderbuffer.rs +++ b/components/script/dom/webglrenderbuffer.rs @@ -20,6 +20,7 @@ pub struct WebGLRenderbuffer { id: WebGLRenderbufferId, ever_bound: Cell<bool>, is_deleted: Cell<bool>, + size: Cell<Option<(i32, i32)>>, internal_format: Cell<Option<u32>>, #[ignore_heap_size_of = "Defined in ipc-channel"] renderer: IpcSender<CanvasMsg>, @@ -36,6 +37,7 @@ impl WebGLRenderbuffer { is_deleted: Cell::new(false), renderer: renderer, internal_format: Cell::new(None), + size: Cell::new(None), } } @@ -64,6 +66,10 @@ impl WebGLRenderbuffer { self.id } + pub fn size(&self) -> Option<(i32, i32)> { + self.size.get() + } + pub fn bind(&self, target: u32) { self.ever_bound.set(true); let msg = CanvasMsg::WebGL(WebGLCommand::BindRenderbuffer(target, Some(self.id))); @@ -106,6 +112,8 @@ impl WebGLRenderbuffer { internal_format, width, height)); self.renderer.send(msg).unwrap(); + self.size.set(Some((width, height))); + Ok(()) } } diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index b67f524825f..c5af5f4c39d 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -283,6 +283,16 @@ impl WebGLRenderingContext { .unwrap(); } + fn get_current_framebuffer_size(&self) -> Option<(i32, i32)> { + match self.bound_framebuffer.get() { + Some(fb) => return fb.size(), + + // The window system framebuffer is bound + None => return Some((self.DrawingBufferWidth(), + self.DrawingBufferHeight())), + } + } + fn validate_stencil_actions(&self, action: u32) -> bool { match action { 0 | constants::KEEP | constants::REPLACE | constants::INCR | constants::DECR | @@ -465,7 +475,11 @@ impl WebGLRenderingContext { self.ipc_renderer .send(CanvasMsg::WebGL(msg)) - .unwrap() + .unwrap(); + + if let Some(fb) = self.bound_framebuffer.get() { + fb.invalidate_texture(&*texture); + } } fn tex_sub_image_2d(&self, @@ -645,6 +659,26 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { return object_binding_to_js_or_null!(cx, &self.bound_texture_2d), constants::TEXTURE_BINDING_CUBE_MAP => return object_binding_to_js_or_null!(cx, &self.bound_texture_cube_map), + + // In readPixels we currently support RGBA/UBYTE only. If + // we wanted to support other formats, we could ask the + // driver, but we would need to check for + // GL_OES_read_format support (assuming an underlying GLES + // driver. Desktop is happy to format convert for us). + constants::IMPLEMENTATION_COLOR_READ_FORMAT => { + if !self.validate_framebuffer_complete() { + return NullValue(); + } else { + return Int32Value(constants::RGBA as i32); + } + } + constants::IMPLEMENTATION_COLOR_READ_TYPE => { + if !self.validate_framebuffer_complete() { + return NullValue(); + } else { + return Int32Value(constants::UNSIGNED_BYTE as i32); + } + } _ => {} } @@ -1773,6 +1807,80 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { _ => return Ok(self.webgl_error(InvalidOperation)), } + // From the WebGL specification, 5.14.12 Reading back pixels + // + // "Only two combinations of format and type are + // accepted. The first is format RGBA and type + // UNSIGNED_BYTE. The second is an implementation-chosen + // format. The values of format and type for this format + // may be determined by calling getParameter with the + // symbolic constants IMPLEMENTATION_COLOR_READ_FORMAT + // and IMPLEMENTATION_COLOR_READ_TYPE, respectively. The + // implementation-chosen format may vary depending on the + // format of the currently bound rendering + // surface. Unsupported combinations of format and type + // will generate an INVALID_OPERATION error." + // + // To avoid having to support general format packing math, we + // always report RGBA/UNSIGNED_BYTE as our only supported + // format. + if format != constants::RGBA || pixel_type != constants::UNSIGNED_BYTE { + return Ok(self.webgl_error(InvalidOperation)); + } + let cpp = 4; + + // "If pixels is non-null, but is not large enough to + // retrieve all of the pixels in the specified rectangle + // taking into account pixel store modes, an + // INVALID_OPERATION error is generated." + let stride = match width.checked_mul(cpp) { + Some(stride) => stride, + _ => return Ok(self.webgl_error(InvalidOperation)), + }; + + match height.checked_mul(stride) { + Some(size) if size <= data.len() as i32 => {} + _ => return Ok(self.webgl_error(InvalidOperation)), + } + + // "For any pixel lying outside the frame buffer, the + // corresponding destination buffer range remains + // untouched; see Reading Pixels Outside the + // Framebuffer." + let mut x = x; + let mut y = y; + let mut width = width; + let mut height = height; + let mut dst_offset = 0; + + if x < 0 { + dst_offset += cpp * -x; + width += x; + x = 0; + } + + if y < 0 { + dst_offset += stride * -y; + height += y; + y = 0; + } + + if width < 0 || height < 0 { + return Ok(self.webgl_error(InvalidValue)); + } + + match self.get_current_framebuffer_size() { + Some((fb_width, fb_height)) => { + if x + width > fb_width { + width = fb_width - x; + } + if y + height > fb_height { + height = fb_height - y; + } + } + _ => return Ok(self.webgl_error(InvalidOperation)), + }; + let (sender, receiver) = ipc::channel().unwrap(); self.ipc_renderer .send(CanvasMsg::WebGL(WebGLCommand::ReadPixels(x, y, width, height, format, pixel_type, sender))) @@ -1780,12 +1888,11 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { let result = receiver.recv().unwrap(); - if result.len() > data.len() { - return Ok(self.webgl_error(InvalidOperation)); - } - - for i in 0..result.len() { - data[i] = result[i] + for i in 0..height { + for j in 0..(width * cpp) { + data[(dst_offset + i * stride + j) as usize] = + result[(i * width * cpp + j) as usize]; + } } Ok(()) @@ -2621,7 +2728,12 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } match self.bound_renderbuffer.get() { - Some(rb) => handle_potential_webgl_error!(self, rb.storage(internal_format, width, height)), + Some(rb) => { + handle_potential_webgl_error!(self, rb.storage(internal_format, width, height)); + if let Some(fb) = self.bound_framebuffer.get() { + fb.invalidate_renderbuffer(&*rb); + } + } None => self.webgl_error(InvalidOperation), }; diff --git a/components/script/dom/webgltexture.rs b/components/script/dom/webgltexture.rs index 31fdaafcffd..3ba8eefca85 100644 --- a/components/script/dom/webgltexture.rs +++ b/components/script/dom/webgltexture.rs @@ -332,7 +332,7 @@ impl WebGLTexture { self.image_info_at_face(face_index, level) } - fn image_info_at_face(&self, face: u8, level: u32) -> ImageInfo { + pub fn image_info_at_face(&self, face: u8, level: u32) -> ImageInfo { let pos = (level * self.face_count.get() as u32) + face as u32; self.image_info_array.borrow()[pos as usize] } diff --git a/components/script/fetch.rs b/components/script/fetch.rs index b73be89b71a..ed1a66fc683 100644 --- a/components/script/fetch.rs +++ b/components/script/fetch.rs @@ -61,6 +61,7 @@ fn request_init_from_request(request: NetTraitsRequest) -> NetTraitsRequestInit referrer_url: from_referrer_to_referrer_url(&request), referrer_policy: request.referrer_policy.get(), pipeline_id: request.pipeline_id.get(), + redirect_mode: request.redirect_mode.get(), } } diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 45077325cbd..49c10625db3 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -2877,11 +2877,12 @@ dependencies = [ [[package]] name = "webrender" version = "0.8.0" -source = "git+https://github.com/servo/webrender#13e06df7906b71aaa2aa621a012678cae1f88052" +source = "git+https://github.com/servo/webrender#a0b6ea0b51a170caf591fb281f5aba25e566158f" dependencies = [ "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "core-graphics 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "core-text 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2902,7 +2903,7 @@ dependencies = [ [[package]] name = "webrender_traits" version = "0.8.0" -source = "git+https://github.com/servo/webrender#13e06df7906b71aaa2aa621a012678cae1f88052" +source = "git+https://github.com/servo/webrender#a0b6ea0b51a170caf591fb281f5aba25e566158f" dependencies = [ "app_units 0.3.0 (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/gecko_bindings/structs_debug.rs b/components/style/gecko_bindings/structs_debug.rs index f09f413df7a..be9627a71e6 100644 --- a/components/style/gecko_bindings/structs_debug.rs +++ b/components/style/gecko_bindings/structs_debug.rs @@ -5546,7 +5546,7 @@ pub struct FragmentOrElement_nsDOMSlots { /** * Holds any SMIL override style declaration for this element. */ - pub mSMILOverrideStyleDeclaration: RefPtr<Declaration>, + pub mSMILOverrideStyleDeclaration: RefPtr<DeclarationBlock>, /** * An object implementing nsIDOMMozNamedAttrMap for this content (attributes) * @see FragmentOrElement::GetAttributes @@ -7410,6 +7410,14 @@ fn bindgen_test_layout_nsAttrName() { assert_eq!(::std::mem::align_of::<nsAttrName>() , 8usize); } #[repr(C)] +#[derive(Debug, Copy)] +pub struct DeclarationBlock { + pub _address: u8, +} +impl Clone for DeclarationBlock { + fn clone(&self) -> Self { *self } +} +#[repr(C)] #[derive(Debug)] pub struct URLValue { pub _base: URLValueData, @@ -7559,14 +7567,6 @@ pub struct nsDOMStringMap { impl Clone for nsDOMStringMap { fn clone(&self) -> Self { *self } } -#[repr(C)] -#[derive(Debug, Copy)] -pub struct Declaration { - pub _address: u8, -} -impl Clone for Declaration { - fn clone(&self) -> Self { *self } -} /** * Interface used for handling clicks on links */ @@ -8904,7 +8904,7 @@ pub enum nsCSSPropertyID { eCSSProperty_flex_grow = 106, eCSSProperty_flex_shrink = 107, eCSSProperty_flex_wrap = 108, - eCSSProperty_float = 109, + eCSSProperty_float_ = 109, eCSSProperty_float_edge = 110, eCSSProperty_flood_color = 111, eCSSProperty_flood_opacity = 112, diff --git a/components/style/gecko_bindings/structs_release.rs b/components/style/gecko_bindings/structs_release.rs index a5767000604..414bc984720 100644 --- a/components/style/gecko_bindings/structs_release.rs +++ b/components/style/gecko_bindings/structs_release.rs @@ -5506,7 +5506,7 @@ pub struct FragmentOrElement_nsDOMSlots { /** * Holds any SMIL override style declaration for this element. */ - pub mSMILOverrideStyleDeclaration: RefPtr<Declaration>, + pub mSMILOverrideStyleDeclaration: RefPtr<DeclarationBlock>, /** * An object implementing nsIDOMMozNamedAttrMap for this content (attributes) * @see FragmentOrElement::GetAttributes @@ -7368,6 +7368,14 @@ fn bindgen_test_layout_nsAttrName() { assert_eq!(::std::mem::align_of::<nsAttrName>() , 8usize); } #[repr(C)] +#[derive(Debug, Copy)] +pub struct DeclarationBlock { + pub _address: u8, +} +impl Clone for DeclarationBlock { + fn clone(&self) -> Self { *self } +} +#[repr(C)] #[derive(Debug)] pub struct URLValue { pub _base: URLValueData, @@ -7516,14 +7524,6 @@ pub struct nsDOMStringMap { impl Clone for nsDOMStringMap { fn clone(&self) -> Self { *self } } -#[repr(C)] -#[derive(Debug, Copy)] -pub struct Declaration { - pub _address: u8, -} -impl Clone for Declaration { - fn clone(&self) -> Self { *self } -} /** * Interface used for handling clicks on links */ @@ -8861,7 +8861,7 @@ pub enum nsCSSPropertyID { eCSSProperty_flex_grow = 106, eCSSProperty_flex_shrink = 107, eCSSProperty_flex_wrap = 108, - eCSSProperty_float = 109, + eCSSProperty_float_ = 109, eCSSProperty_float_edge = 110, eCSSProperty_flood_color = 111, eCSSProperty_flood_opacity = 112, diff --git a/components/style/gecko_string_cache/atom_macro.rs b/components/style/gecko_string_cache/atom_macro.rs index fc6f22948be..061d8f8acb5 100644 --- a/components/style/gecko_string_cache/atom_macro.rs +++ b/components/style/gecko_string_cache/atom_macro.rs @@ -5348,8 +5348,6 @@ cfg_if! { pub static nsCSSProps_marker_end: *mut nsICSSProperty; #[link_name = "_ZN10nsCSSProps10marker_midE"] pub static nsCSSProps_marker_mid: *mut nsICSSProperty; - #[link_name = "_ZN10nsCSSProps13marker_offsetE"] - pub static nsCSSProps_marker_offset: *mut nsICSSProperty; #[link_name = "_ZN10nsCSSProps12marker_startE"] pub static nsCSSProps_marker_start: *mut nsICSSProperty; #[link_name = "_ZN10nsCSSProps4maskE"] @@ -10987,8 +10985,6 @@ cfg_if! { pub static nsCSSProps_marker_end: *mut nsICSSProperty; #[link_name = "?marker_mid@nsCSSProps@@2PEAVnsICSSProperty@@EA"] pub static nsCSSProps_marker_mid: *mut nsICSSProperty; - #[link_name = "?marker_offset@nsCSSProps@@2PEAVnsICSSProperty@@EA"] - pub static nsCSSProps_marker_offset: *mut nsICSSProperty; #[link_name = "?marker_start@nsCSSProps@@2PEAVnsICSSProperty@@EA"] pub static nsCSSProps_marker_start: *mut nsICSSProperty; #[link_name = "?mask@nsCSSProps@@2PEAVnsICSSProperty@@EA"] @@ -16626,8 +16622,6 @@ cfg_if! { pub static nsCSSProps_marker_end: *mut nsICSSProperty; #[link_name = "\x01?marker_mid@nsCSSProps@@2PAVnsICSSProperty@@A"] pub static nsCSSProps_marker_mid: *mut nsICSSProperty; - #[link_name = "\x01?marker_offset@nsCSSProps@@2PAVnsICSSProperty@@A"] - pub static nsCSSProps_marker_offset: *mut nsICSSProperty; #[link_name = "\x01?marker_start@nsCSSProps@@2PAVnsICSSProperty@@A"] pub static nsCSSProps_marker_start: *mut nsICSSProperty; #[link_name = "\x01?mask@nsCSSProps@@2PAVnsICSSProperty@@A"] @@ -22268,8 +22262,6 @@ macro_rules! atom { { unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSProps_marker_end as *mut _) } }; ("marker-mid") => { unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSProps_marker_mid as *mut _) } }; -("marker-offset") => - { unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSProps_marker_offset as *mut _) } }; ("marker-start") => { unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSProps_marker_start as *mut _) } }; ("mask") => diff --git a/components/style/media_queries.rs b/components/style/media_queries.rs index 4970ef8b2c2..28fc662d126 100644 --- a/components/style/media_queries.rs +++ b/components/style/media_queries.rs @@ -31,6 +31,12 @@ impl ToCss for MediaList { } } +impl Default for MediaList { + fn default() -> MediaList { + MediaList { media_queries: vec![] } + } +} + #[derive(PartialEq, Eq, Copy, Clone, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum Range<T> { @@ -253,8 +259,8 @@ impl MediaQuery { } pub fn parse_media_query_list(input: &mut Parser) -> MediaList { - let queries = if input.is_exhausted() { - vec![MediaQuery::new(None, MediaQueryType::All, vec!())] + if input.is_exhausted() { + Default::default() } else { let mut media_queries = vec![]; loop { @@ -269,17 +275,17 @@ pub fn parse_media_query_list(input: &mut Parser) -> MediaList { Err(()) => break, } } - media_queries - }; - MediaList { media_queries: queries } + MediaList { media_queries: media_queries } + } } impl MediaList { pub fn evaluate(&self, device: &Device) -> bool { let viewport_size = device.au_viewport_size(); - // Check if any queries match (OR condition) - self.media_queries.iter().any(|mq| { + // Check if it is an empty media query list or any queries match (OR condition) + // https://drafts.csswg.org/mediaqueries-4/#mq-list + self.media_queries.is_empty() || self.media_queries.iter().any(|mq| { // Check if media matches. Unknown media never matches. let media_match = match mq.media_type { MediaQueryType::MediaType(MediaType::Unknown(_)) => false, diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index fe7bac7efe9..9c0aa616136 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -178,7 +178,7 @@ use parser::{ParserContext, ParserContextExtraData}; use properties::{CSSWideKeyword, DeclaredValue, Shorthand}; % endif - #[allow(unused_imports)] + use values::{Auto, Either, None_, Normal}; use cascade_info::CascadeInfo; use error_reporting::ParseErrorReporter; use parser::Parse; diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index 8b8e3c0b92f..39f9abaf29b 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -22,6 +22,7 @@ use std::cmp; use std::fmt; use style_traits::ToCss; use super::ComputedValues; +use values::Either; use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone}; use values::computed::{BorderRadiusSize, LengthOrNone}; use values::computed::{CalcLengthOrPercentage, LengthOrPercentage}; @@ -682,8 +683,8 @@ impl Interpolate for BoxShadow { impl Interpolate for LengthOrNone { fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> { match (*self, *other) { - (LengthOrNone::Length(ref len), LengthOrNone::Length(ref other)) => - len.interpolate(&other, progress).map(LengthOrNone::Length), + (Either::First(ref length), Either::First(ref other)) => + length.interpolate(&other, progress).map(Either::First), _ => Err(()), } } diff --git a/components/style/properties/longhand/effects.mako.rs b/components/style/properties/longhand/effects.mako.rs index 5949bc48704..87595133b91 100644 --- a/components/style/properties/longhand/effects.mako.rs +++ b/components/style/properties/longhand/effects.mako.rs @@ -1395,7 +1395,7 @@ ${helpers.single_keyword("transform-style", ${helpers.predefined_type("perspective", "LengthOrNone", - "computed::LengthOrNone::None", + "Either::Second(None_)", products="servo", animatable=True)} diff --git a/components/style/properties/longhand/text.mako.rs b/components/style/properties/longhand/text.mako.rs index d10850400fa..2923948ed1c 100644 --- a/components/style/properties/longhand/text.mako.rs +++ b/components/style/properties/longhand/text.mako.rs @@ -12,9 +12,6 @@ Method("has_overline", "bool"), Method("has_line_through", "bool")]) %> -% if product == "servo": - ${helpers.single_keyword("text-overflow", "clip ellipsis", animatable=False)} -% else: <%helpers:longhand name="text-overflow" animatable="False"> use std::fmt; use style_traits::ToCss; @@ -93,7 +90,6 @@ } } </%helpers:longhand> -% endif ${helpers.single_keyword("unicode-bidi", "normal embed isolate bidi-override isolate-override plaintext", diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index ca72c0c38aa..dfa2593e1cb 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -30,6 +30,7 @@ use logical_geometry::WritingMode; use parser::{ParserContext, ParserContextExtraData}; use style_traits::ToCss; use stylesheets::Origin; +#[cfg(feature = "servo")] use values::Either; use values::{HasViewportPercentage, computed}; use cascade_info::CascadeInfo; use rule_tree::StrongRuleNode; @@ -1249,7 +1250,7 @@ impl ComputedValues { if effects.transform.0.is_some() { return transform_style::T::flat; } - if effects.perspective != computed::LengthOrNone::None { + if let Either::First(ref _length) = effects.perspective { return transform_style::T::flat; } } diff --git a/components/style/stylesheets.rs b/components/style/stylesheets.rs index 2f37415351c..d8ccc754315 100644 --- a/components/style/stylesheets.rs +++ b/components/style/stylesheets.rs @@ -45,8 +45,8 @@ pub struct Stylesheet { /// List of rules in the order they were found (important for /// cascading order) pub rules: Vec<CSSRule>, - /// List of media associated with the Stylesheet, if any. - pub media: Option<MediaList>, + /// List of media associated with the Stylesheet. + pub media: MediaList, pub origin: Origin, pub dirty_on_viewport_size_change: bool, } @@ -181,14 +181,14 @@ impl Stylesheet { Stylesheet { origin: origin, rules: rules, - media: None, + media: Default::default(), dirty_on_viewport_size_change: input.seen_viewport_percentages(), } } /// Set the MediaList associated with the style-sheet. - pub fn set_media(&mut self, media: Option<MediaList>) { + pub fn set_media(&mut self, media: MediaList) { self.media = media; } @@ -197,7 +197,7 @@ impl Stylesheet { /// /// Always true if no associated MediaList exists. pub fn is_effective_for_device(&self, device: &Device) -> bool { - self.media.as_ref().map_or(true, |ref media| media.evaluate(device)) + self.media.evaluate(device) } /// Return an iterator over the effective rules within the style-sheet, as diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs index 5d3044c3ac7..b08c3806ceb 100644 --- a/components/style/values/computed/length.rs +++ b/components/style/values/computed/length.rs @@ -7,7 +7,7 @@ use ordered_float::NotNaN; use std::fmt; use style_traits::ToCss; use super::{Number, ToComputedValue, Context}; -use values::{CSSFloat, specified}; +use values::{CSSFloat, Either, None_, specified}; pub use cssparser::Color as CSSColor; pub use super::image::{EndingShape as GradientShape, Gradient, GradientKind, Image}; @@ -452,61 +452,7 @@ impl ToCss for LengthOrPercentageOrNone { } } -#[derive(PartialEq, Clone, Copy)] -#[cfg_attr(feature = "servo", derive(HeapSizeOf))] -pub enum LengthOrNone { - Length(Au), - None, -} - -impl fmt::Debug for LengthOrNone { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - LengthOrNone::Length(length) => write!(f, "{:?}", length), - LengthOrNone::None => write!(f, "none"), - } - } -} - -impl ToComputedValue for specified::LengthOrNone { - type ComputedValue = LengthOrNone; - - #[inline] - fn to_computed_value(&self, context: &Context) -> LengthOrNone { - match *self { - specified::LengthOrNone::Length(specified::Length::Calc(calc, range)) => { - LengthOrNone::Length(range.clamp(calc.to_computed_value(context).length())) - } - specified::LengthOrNone::Length(value) => { - LengthOrNone::Length(value.to_computed_value(context)) - } - specified::LengthOrNone::None => { - LengthOrNone::None - } - } - } - - #[inline] - fn from_computed_value(computed: &LengthOrNone) -> Self { - match *computed { - LengthOrNone::Length(au) => { - specified::LengthOrNone::Length(ToComputedValue::from_computed_value(&au)) - } - LengthOrNone::None => { - specified::LengthOrNone::None - } - } - } -} - -impl ToCss for LengthOrNone { - fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match *self { - LengthOrNone::Length(length) => length.to_css(dest), - LengthOrNone::None => dest.write_str("none"), - } - } -} +pub type LengthOrNone = Either<Length, None_>; #[derive(Clone, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index c73fcd73e83..14e4f49d76c 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -12,6 +12,7 @@ use super::{CSSFloat, specified}; pub use cssparser::Color as CSSColor; pub use self::image::{EndingShape as GradientShape, Gradient, GradientKind, Image}; pub use self::image::{LengthOrKeyword, LengthOrPercentageOrKeyword}; +pub use super::{Either, None_}; pub use super::specified::{Angle, BorderStyle, Time, UrlExtraData, UrlOrNone}; pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrAuto}; pub use self::length::{LengthOrPercentageOrAutoOrContent, LengthOrPercentageOrNone, LengthOrNone}; diff --git a/components/style/values/mod.rs b/components/style/values/mod.rs index 46d7b304d0b..485b46c82a2 100644 --- a/components/style/values/mod.rs +++ b/components/style/values/mod.rs @@ -6,7 +6,11 @@ //! //! [values]: https://drafts.csswg.org/css-values/ -pub use cssparser::RGBA; +pub use cssparser::{RGBA, Parser}; + +use parser::Parse; +use std::fmt::{self, Debug}; +use style_traits::ToCss; macro_rules! define_numbered_css_keyword_enum { ($name: ident: $( $css: expr => $variant: ident = $value: expr ),+,) => { @@ -59,3 +63,102 @@ impl<T> HasViewportPercentage for T where T: NoViewportPercentage { } } +use self::computed::ComputedValueAsSpecified; + +macro_rules! define_keyword_type { + ($name: ident, $css: expr) => { + #[derive(Clone, PartialEq, Copy)] + #[cfg_attr(feature = "servo", derive(HeapSizeOf))] + pub struct $name; + + impl ::style_traits::ToCss for $name { + fn to_css<W>(&self, dest: &mut W) -> ::std::fmt::Result where W: ::std::fmt::Write { + write!(dest, $css) + } + } + + impl fmt::Debug for $name { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, $css) + } + } + + impl Parse for $name { + fn parse(input: &mut ::cssparser::Parser) -> Result<$name, ()> { + input.expect_ident_matching($css).map(|_| $name) + } + } + + impl ComputedValueAsSpecified for $name {} + impl NoViewportPercentage for $name {} + }; +} + +define_keyword_type!(None_, "none"); +define_keyword_type!(Auto, "auto"); +define_keyword_type!(Normal, "normal"); + +#[derive(Clone, PartialEq, Copy)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +pub enum Either<A, B> { + First(A), + Second(B), +} + +impl<A: Debug, B: Debug> Debug for Either<A, B> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Either::First(ref v) => v.fmt(f), + Either::Second(ref v) => v.fmt(f), + } + } +} + +impl<A: ToCss, B: ToCss> ToCss for Either<A, B> { + fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + match *self { + Either::First(ref v) => v.to_css(dest), + Either::Second(ref v) => v.to_css(dest), + } + } +} + +impl<A: HasViewportPercentage, B: HasViewportPercentage> HasViewportPercentage for Either<A, B> { + fn has_viewport_percentage(&self) -> bool { + match *self { + Either::First(ref v) => v.has_viewport_percentage(), + Either::Second(ref v) => v.has_viewport_percentage(), + } + } +} + +impl<A: Parse, B: Parse> Parse for Either<A, B> { + fn parse(input: &mut Parser) -> Result<Either<A, B>, ()> { + if let Ok(v) = input.try(|i| A::parse(i)) { + Ok(Either::First(v)) + } else { + B::parse(input).map(Either::Second) + } + } +} + +use self::computed::{Context, ToComputedValue}; + +impl<A: ToComputedValue, B: ToComputedValue> ToComputedValue for Either<A, B> { + type ComputedValue = Either<A::ComputedValue, B::ComputedValue>; + + fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { + match *self { + Either::First(ref a) => Either::First(a.to_computed_value(context)), + Either::Second(ref a) => Either::Second(a.to_computed_value(context)), + } + } + + #[inline] + fn from_computed_value(computed: &Self::ComputedValue) -> Self { + match *computed { + Either::First(ref a) => Either::First(ToComputedValue::from_computed_value(a)), + Either::Second(ref a) => Either::Second(ToComputedValue::from_computed_value(a)), + } + } +} diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs index a0ed172cab1..a8b33cb041e 100644 --- a/components/style/values/specified/length.rs +++ b/components/style/values/specified/length.rs @@ -13,7 +13,7 @@ use std::ops::Mul; use style_traits::ToCss; use style_traits::values::specified::AllowedNumericType; use super::{Angle, Number, SimplifiedValueNode, SimplifiedSumNode, Time}; -use values::{CSSFloat, FONT_MEDIUM_PX, HasViewportPercentage, computed}; +use values::{CSSFloat, Either, FONT_MEDIUM_PX, HasViewportPercentage, None_, computed}; pub use super::image::{AngleOrCorner, ColorStop, EndingShape as GradientEndingShape, Gradient}; pub use super::image::{GradientKind, HorizontalDirection, Image, LengthOrKeyword, LengthOrPercentageOrKeyword}; @@ -908,55 +908,12 @@ impl LengthOrPercentageOrNone { } } -#[derive(Clone, PartialEq, Copy, Debug)] -#[cfg_attr(feature = "servo", derive(HeapSizeOf))] -pub enum LengthOrNone { - Length(Length), - None, -} - -impl HasViewportPercentage for LengthOrNone { - fn has_viewport_percentage(&self) -> bool { - match *self { - LengthOrNone::Length(ref length) => length.has_viewport_percentage(), - _ => false - } - } -} +pub type LengthOrNone = Either<Length, None_>; -impl ToCss for LengthOrNone { - fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match *self { - LengthOrNone::Length(length) => length.to_css(dest), - LengthOrNone::None => dest.write_str("none"), - } - } -} impl LengthOrNone { - fn parse_internal(input: &mut Parser, context: AllowedNumericType) - -> Result<LengthOrNone, ()> - { - match try!(input.next()) { - Token::Dimension(ref value, ref unit) if context.is_ok(value.value) => - Length::parse_dimension(value.value, unit).map(LengthOrNone::Length), - Token::Number(ref value) if value.value == 0. => - Ok(LengthOrNone::Length(Length::Absolute(Au(0)))), - Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => - input.parse_nested_block(|input| { - CalcLengthOrPercentage::parse_length(input, context) - }).map(LengthOrNone::Length), - Token::Ident(ref value) if value.eq_ignore_ascii_case("none") => - Ok(LengthOrNone::None), - _ => Err(()) - } - } - #[inline] - pub fn parse(input: &mut Parser) -> Result<LengthOrNone, ()> { - LengthOrNone::parse_internal(input, AllowedNumericType::All) - } #[inline] pub fn parse_non_negative(input: &mut Parser) -> Result<LengthOrNone, ()> { - LengthOrNone::parse_internal(input, AllowedNumericType::NonNegative) + Length::parse_internal(input, AllowedNumericType::NonNegative).map(Either::First) } } diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 92a8532f52d..339c565a240 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -83,7 +83,6 @@ impl ToCss for CSSRGBA { } } - #[derive(Clone, Debug)] pub struct SimplifiedSumNode { values: Vec<SimplifiedValueNode>, diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index 980958d0a99..8e94b56ce50 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -2691,11 +2691,12 @@ dependencies = [ [[package]] name = "webrender" version = "0.8.0" -source = "git+https://github.com/servo/webrender#13e06df7906b71aaa2aa621a012678cae1f88052" +source = "git+https://github.com/servo/webrender#a0b6ea0b51a170caf591fb281f5aba25e566158f" dependencies = [ "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "core-graphics 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "core-text 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2716,7 +2717,7 @@ dependencies = [ [[package]] name = "webrender_traits" version = "0.8.0" -source = "git+https://github.com/servo/webrender#13e06df7906b71aaa2aa621a012678cae1f88052" +source = "git+https://github.com/servo/webrender#a0b6ea0b51a170caf591fb281f5aba25e566158f" dependencies = [ "app_units 0.3.0 (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/python/servo/testing_commands.py b/python/servo/testing_commands.py index fdb471a437d..f24750df245 100644 --- a/python/servo/testing_commands.py +++ b/python/servo/testing_commands.py @@ -408,19 +408,17 @@ class MachCommands(CommandBase): def run_test_list_or_dispatch(self, requested_paths, correct_suite, correct_function, **kwargs): if not requested_paths: return correct_function(**kwargs) - else: - # Paths specified on command line. Ensure they can be handled, re-dispatch otherwise. - all_handled = True - for test_path in requested_paths: - suite = self.suite_for_path(test_path) - if suite is not None and correct_suite != suite: - all_handled = False - print("Warning: %s is not a %s test. Delegating to test-%s." % (test_path, correct_suite, suite)) - if all_handled: - return correct_function(**kwargs) - else: - # Dispatch each test to the correct suite via test() - Registrar.dispatch("test", context=self.context, params=requested_paths) + # Paths specified on command line. Ensure they can be handled, re-dispatch otherwise. + all_handled = True + for test_path in requested_paths: + suite = self.suite_for_path(test_path) + if suite is not None and correct_suite != suite: + all_handled = False + print("Warning: %s is not a %s test. Delegating to test-%s." % (test_path, correct_suite, suite)) + if all_handled: + return correct_function(**kwargs) + # Dispatch each test to the correct suite via test() + Registrar.dispatch("test", context=self.context, params=requested_paths) # Helper for test_css and test_wpt: def wptrunner(self, run_file, **kwargs): diff --git a/resources/shaders/blend.fs.glsl b/resources/shaders/blend.fs.glsl deleted file mode 100644 index 8dc29cf4d8f..00000000000 --- a/resources/shaders/blend.fs.glsl +++ /dev/null @@ -1,193 +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/. */ - -vec3 Multiply(vec3 Cb, vec3 Cs) { - return Cb * Cs; -} - -vec3 Screen(vec3 Cb, vec3 Cs) { - return Cb + Cs - (Cb * Cs); -} - -vec3 HardLight(vec3 Cb, vec3 Cs) { - vec3 m = Multiply(Cb, 2.0 * Cs); - vec3 s = Screen(Cb, 2.0 * Cs - 1.0); - vec3 edge = vec3(0.5, 0.5, 0.5); - return mix(m, s, step(edge, Cs)); -} - -// TODO: Worth doing with mix/step? Check GLSL output. -float ColorDodge(float Cb, float Cs) { - if (Cb == 0.0) - return 0.0; - else if (Cs == 1.0) - return 1.0; - else - return min(1.0, Cb / (1.0 - Cs)); -} - -// TODO: Worth doing with mix/step? Check GLSL output. -float ColorBurn(float Cb, float Cs) { - if (Cb == 1.0) - return 1.0; - else if (Cs == 0.0) - return 0.0; - else - return 1.0 - min(1.0, (1.0 - Cb) / Cs); -} - -float SoftLight(float Cb, float Cs) { - if (Cs <= 0.5) { - return Cb - (1.0 - 2.0 * Cs) * Cb * (1.0 - Cb); - } else { - float D; - - if (Cb <= 0.25) - D = ((16.0 * Cb - 12.0) * Cb + 4.0) * Cb; - else - D = sqrt(Cb); - - return Cb + (2.0 * Cs - 1.0) * (D - Cb); - } -} - -vec3 Difference(vec3 Cb, vec3 Cs) { - return abs(Cb - Cs); -} - -vec3 Exclusion(vec3 Cb, vec3 Cs) { - return Cb + Cs - 2.0 * Cb * Cs; -} - -// These functions below are taken from the spec. -// There's probably a much quicker way to implement -// them in GLSL... -float Sat(vec3 c) { - return max(c.r, max(c.g, c.b)) - min(c.r, min(c.g, c.b)); -} - -float Lum(vec3 c) { - vec3 f = vec3(0.3, 0.59, 0.11); - return dot(c, f); -} - -vec3 ClipColor(vec3 C) { - float L = Lum(C); - float n = min(C.r, min(C.g, C.b)); - float x = max(C.r, max(C.g, C.b)); - - if (n < 0.0) - C = L + (((C - L) * L) / (L - n)); - - if (x > 1.0) - C = L + (((C - L) * (1.0 - L)) / (x - L)); - - return C; -} - -vec3 SetLum(vec3 C, float l) { - float d = l - Lum(C); - return ClipColor(C + d); -} - -void SetSatInner(inout float Cmin, inout float Cmid, inout float Cmax, float s) { - if (Cmax > Cmin) { - Cmid = (((Cmid - Cmin) * s) / (Cmax - Cmin)); - Cmax = s; - } else { - Cmid = 0.0; - Cmax = 0.0; - } - Cmin = 0.0; -} - -vec3 SetSat(vec3 C, float s) { - if (C.r <= C.g) { - if (C.g <= C.b) { - SetSatInner(C.r, C.g, C.b, s); - } else { - if (C.r <= C.b) { - SetSatInner(C.r, C.b, C.g, s); - } else { - SetSatInner(C.b, C.r, C.g, s); - } - } - } else { - if (C.r <= C.b) { - SetSatInner(C.g, C.r, C.b, s); - } else { - if (C.g <= C.b) { - SetSatInner(C.g, C.b, C.r, s); - } else { - SetSatInner(C.b, C.g, C.r, s); - } - } - } - return C; -} - -vec3 Hue(vec3 Cb, vec3 Cs) { - return SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb)); -} - -vec3 Saturation(vec3 Cb, vec3 Cs) { - return SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb)); -} - -vec3 Color(vec3 Cb, vec3 Cs) { - return SetLum(Cs, Lum(Cb)); -} - -vec3 Luminosity(vec3 Cb, vec3 Cs) { - return SetLum(Cb, Lum(Cs)); -} - -void main(void) -{ - vec3 Cs = Texture(sDiffuse, vColorTexCoord).xyz; - vec3 Cb = Texture(sMask, vMaskTexCoord).xyz; - - // TODO: Relies on the ordering of MixBlendMode enum! - // TODO: May be best to have separate shaders (esp. on Tegra) - int blend_mode = int(uBlendParams.x); - - // Return yellow if none of the branches match (shouldn't happen). - vec3 result = vec3(1.0, 1.0, 0.0); - - if (blend_mode == 2) { - result = Screen(Cb, Cs); - } else if (blend_mode == 3) { - result = HardLight(Cs, Cb); // Overlay is inverse of Hardlight - } else if (blend_mode == 6) { - result.r = ColorDodge(Cb.r, Cs.r); - result.g = ColorDodge(Cb.g, Cs.g); - result.b = ColorDodge(Cb.b, Cs.b); - } else if (blend_mode == 7) { - result.r = ColorBurn(Cb.r, Cs.r); - result.g = ColorBurn(Cb.g, Cs.g); - result.b = ColorBurn(Cb.b, Cs.b); - } else if (blend_mode == 8) { - result = HardLight(Cb, Cs); - } else if (blend_mode == 9) { - result.r = SoftLight(Cb.r, Cs.r); - result.g = SoftLight(Cb.g, Cs.g); - result.b = SoftLight(Cb.b, Cs.b); - } else if (blend_mode == 10) { - result = Difference(Cb, Cs); - } else if (blend_mode == 11) { - result = Exclusion(Cb, Cs); - } else if (blend_mode == 12) { - result = Hue(Cb, Cs); - } else if (blend_mode == 13) { - result = Saturation(Cb, Cs); - } else if (blend_mode == 14) { - result = Color(Cb, Cs); - } else if (blend_mode == 15) { - result = Luminosity(Cb, Cs); - } - - // TODO: Handle output alpha correctly. - SetFragColor(vec4(result, 1.0)); -} - diff --git a/resources/shaders/blend.vs.glsl b/resources/shaders/blend.vs.glsl deleted file mode 100644 index 031ccacdc1b..00000000000 --- a/resources/shaders/blend.vs.glsl +++ /dev/null @@ -1,10 +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/. */ - -void main(void) -{ - vColorTexCoord = aColorTexCoordRectTop.xy; - vMaskTexCoord = aMaskTexCoordRectTop.xy / 65535.0; - gl_Position = uTransform * vec4(aPosition, 1.0); -} diff --git a/resources/shaders/box_shadow.fs.glsl b/resources/shaders/box_shadow.fs.glsl deleted file mode 100644 index e71ba6a193b..00000000000 --- a/resources/shaders/box_shadow.fs.glsl +++ /dev/null @@ -1,148 +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/. */ - -// See http://asciimath.org to render the equations here. - -// The Gaussian function used for blurring: -// -// G_sigma(x) = 1/sqrt(2 pi sigma^2) e^(-x^2/(2 sigma^2)) -float gauss(float x, float sigma) { - float sigmaPow2 = sigma * sigma; - return 1.0 / sqrt(6.283185307179586 * sigmaPow2) * exp(-(x * x) / (2.0 * sigmaPow2)); -} - -// An approximation of the error function, which is related to the integral of the Gaussian -// function: -// -// "erf"(x) = 2/sqrt(pi) int_0^x e^(-t^2) dt -// ~~ 1 - 1 / (1 + a_1 x + a_2 x^2 + a_3 x^3 + a_4 x^4)^4 -// -// where: -// -// a_1 = 0.278393, a_2 = 0.230389, a_3 = 0.000972, a_4 = 0.078108 -// -// This approximation is accurate to `5 xx 10^-4`, more than accurate enough for our purposes. -// -// See: https://en.wikipedia.org/wiki/Error_function#Approximation_with_elementary_functions -float erf(float x) { - bool negative = x < 0.0; - if (negative) - x = -x; - float x2 = x * x; - float x3 = x2 * x; - float x4 = x2 * x2; - float denom = 1.0 + 0.278393 * x + 0.230389 * x2 + 0.000972 * x3 + 0.078108 * x4; - float result = 1.0 - 1.0 / (denom * denom * denom * denom); - return negative ? -result : result; -} - -// A useful helper for calculating integrals of the Gaussian function via the error function: -// -// "erf"_sigma(x) = 2 int 1/sqrt(2 pi sigma^2) e^(-x^2/(2 sigma^2)) dx -// = "erf"(x/(sigma sqrt(2))) -float erfSigma(float x, float sigma) { - return erf(x / (sigma * 1.4142135623730951)); -} - -// Returns the blurred color value from the box itself (not counting any rounded corners). `p_0` is -// the vector distance to the top left corner of the box; `p_1` is the vector distance to its -// bottom right corner. -// -// "colorFromRect"_sigma(p_0, p_1) -// = int_{p_{0_y}}^{p_{1_y}} int_{p_{1_x}}^{p_{0_x}} G_sigma(y) G_sigma(x) dx dy -// = 1/4 ("erf"_sigma(p_{1_x}) - "erf"_sigma(p_{0_x})) -// ("erf"_sigma(p_{1_y}) - "erf"_sigma(p_{0_y})) -float colorFromRect(vec2 p0, vec2 p1, float sigma) { - return (erfSigma(p1.x, sigma) - erfSigma(p0.x, sigma)) * - (erfSigma(p1.y, sigma) - erfSigma(p0.y, sigma)) / 4.0; -} - -// Returns the `x` coordinate on the ellipse with the given radii for the given `y` coordinate: -// -// "ellipsePoint"(y, y_0, a, b) = a sqrt(1 - ((y - y_0) / b)^2) -float ellipsePoint(float y, float y0, vec2 radii) { - float bStep = (y - y0) / radii.y; - return radii.x * sqrt(1.0 - bStep * bStep); -} - -// A helper function to compute the value that needs to be subtracted to accommodate the border -// corners. -// -// "colorCutout"_sigma(x_{0_l}, x_{0_r}, y_0, y_{min}, y_{max}, a, b) -// = int_{y_{min}}^{y_{max}} -// int_{x_{0_r} + "ellipsePoint"(y, y_0, a, b)}^{x_{0_r} + a} G_sigma(y) G_sigma(x) dx -// + int_{x_{0_l} - a}^{x_{0_l} - "ellipsePoint"(y, y_0, a, b)} G_sigma(y) G_sigma(x) -// dx dy -// = int_{y_{min}}^{y_{max}} 1/2 G_sigma(y) -// ("erf"_sigma(x_{0_r} + a) - "erf"_sigma(x_{0_r} + "ellipsePoint"(y, y_0, a, b)) + -// "erf"_sigma(x_{0_l} - "ellipsePoint"(y, y_0, a, b)) - "erf"_sigma(x_{0_l} - a)) -// -// with the outer integral evaluated numerically. -float colorCutoutGeneral(float x0l, - float x0r, - float y0, - float yMin, - float yMax, - vec2 radii, - float sigma) { - float sum = 0.0; - for (float y = yMin; y <= yMax; y += 1.0) { - float xEllipsePoint = ellipsePoint(y, y0, radii); - sum += gauss(y, sigma) * - (erfSigma(x0r + radii.x, sigma) - erfSigma(x0r + xEllipsePoint, sigma) + - erfSigma(x0l - xEllipsePoint, sigma) - erfSigma(x0l - radii.x, sigma)); - } - return sum / 2.0; -} - -// The value that needs to be subtracted to accommodate the top border corners. -float colorCutoutTop(float x0l, float x0r, float y0, vec2 radii, float sigma) { - return colorCutoutGeneral(x0l, x0r, y0, y0, y0 + radii.y, radii, sigma); -} - -// The value that needs to be subtracted to accommodate the bottom border corners. -float colorCutoutBottom(float x0l, float x0r, float y0, vec2 radii, float sigma) { - return colorCutoutGeneral(x0l, x0r, y0, y0 - radii.y, y0, radii, sigma); -} - -// The blurred color value for the point at `pos` with the top left corner of the box at -// `p_{0_"rect"}` and the bottom right corner of the box at `p_{1_"rect"}`. -float color(vec2 pos, vec2 p0Rect, vec2 p1Rect, vec2 radii, float sigma) { - // Compute the vector distances `p_0` and `p_1`. - vec2 p0 = p0Rect - pos, p1 = p1Rect - pos; - - // Compute the basic color `"colorFromRect"_sigma(p_0, p_1)`. This is all we have to do if - // the box is unrounded. - float cRect = colorFromRect(p0, p1, sigma); - if (radii.x == 0.0 || radii.y == 0.0) - return cRect; - - // Compute the inner corners of the box, taking border radii into account: `x_{0_l}`, - // `y_{0_t}`, `x_{0_r}`, and `y_{0_b}`. - float x0l = p0.x + radii.x; - float y0t = p1.y - radii.y; - float x0r = p1.x - radii.x; - float y0b = p0.y + radii.y; - - // Compute the final color: - // - // "colorFromRect"_sigma(p_0, p_1) - - // ("colorCutoutTop"_sigma(x_{0_l}, x_{0_r}, y_{0_t}, a, b) + - // "colorCutoutBottom"_sigma(x_{0_l}, x_{0_r}, y_{0_b}, a, b)) - float cCutoutTop = colorCutoutTop(x0l, x0r, y0t, radii, sigma); - float cCutoutBottom = colorCutoutBottom(x0l, x0r, y0b, radii, sigma); - return cRect - (cCutoutTop + cCutoutBottom); -} - -void main(void) { - vec2 pos = vPosition.xy; - vec2 p0Rect = vBorderPosition.xy, p1Rect = vBorderPosition.zw; - vec2 radii = vBorderRadii.xy; - float sigma = vBlurRadius / 2.0; - float value = color(pos, p0Rect, p1Rect, radii, sigma); - - value = max(value, 0.0); - SetFragColor(vec4(vColor.rgb, vColor.a == 0.0 ? 1.0 - value : value)); -} - diff --git a/resources/shaders/box_shadow.vs.glsl b/resources/shaders/box_shadow.vs.glsl deleted file mode 100644 index de3793c211e..00000000000 --- a/resources/shaders/box_shadow.vs.glsl +++ /dev/null @@ -1,14 +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/. */ - -void main(void) -{ - vPosition = aPosition.xy; - vColor = aColorRectTL; - vBorderPosition = aBorderPosition; - vBorderRadii = aBorderRadii; - vBlurRadius = aBlurRadius; - gl_Position = uTransform * vec4(aPosition, 1.0); -} - diff --git a/resources/shaders/es2_common.fs.glsl b/resources/shaders/es2_common.fs.glsl deleted file mode 100644 index 088bc670036..00000000000 --- a/resources/shaders/es2_common.fs.glsl +++ /dev/null @@ -1,42 +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/. */ - -#version 110 - -#define SERVO_ES2 - -precision highp float; - -uniform sampler2D sDiffuse; -uniform sampler2D sMask; -uniform vec4 uBlendParams; -uniform vec4 uAtlasParams; -uniform vec2 uDirection; -uniform vec4 uFilterParams; - -varying vec2 vPosition; -varying vec4 vColor; -varying vec2 vColorTexCoord; -varying vec2 vMaskTexCoord; -varying vec4 vBorderPosition; -varying vec4 vBorderRadii; -varying vec2 vDestTextureSize; -varying vec2 vSourceTextureSize; -varying float vBlurRadius; -varying vec4 vTileParams; -varying vec4 vClipInRect; -varying vec4 vClipOutRect; - -vec4 Texture(sampler2D sampler, vec2 texCoord) { - return texture2D(sampler, texCoord); -} - -float GetAlphaFromMask(vec4 mask) { - return mask.a; -} - -void SetFragColor(vec4 color) { - gl_FragColor = color; -} - diff --git a/resources/shaders/es2_common.vs.glsl b/resources/shaders/es2_common.vs.glsl deleted file mode 100644 index ccb8c3dcec5..00000000000 --- a/resources/shaders/es2_common.vs.glsl +++ /dev/null @@ -1,70 +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/. */ - -#version 110 - -#define SERVO_ES2 - -uniform mat4 uTransform; -uniform vec4 uOffsets[32]; -uniform vec4 uClipRects[64]; -uniform mat4 uMatrixPalette[32]; -uniform vec2 uDirection; -uniform vec4 uBlendParams; -uniform vec4 uFilterParams; -uniform float uDevicePixelRatio; -uniform vec4 uTileParams[64]; - -attribute vec3 aPosition; -attribute vec4 aPositionRect; // Width can be negative to flip horizontally (for border corners). -attribute vec4 aColorRectTL; -attribute vec4 aColorRectTR; -attribute vec4 aColorRectBR; -attribute vec4 aColorRectBL; -attribute vec4 aColorTexCoordRectTop; -attribute vec4 aColorTexCoordRectBottom; -attribute vec4 aMaskTexCoordRectTop; -attribute vec4 aMaskTexCoordRectBottom; -attribute vec4 aBorderPosition; -attribute vec4 aBorderRadii; -attribute vec2 aSourceTextureSize; -attribute vec2 aDestTextureSize; -attribute float aBlurRadius; -// x = matrix index; y = clip-in rect; z = clip-out rect; w = tile params index. -// -// A negative w value activates border corner mode. In this mode, the TR and BL colors are ignored, -// the color of the top left corner applies to all vertices of the top left triangle, and the color -// of the bottom right corner applies to all vertices of the bottom right triangle. -attribute vec4 aMisc; - -varying vec2 vPosition; -varying vec4 vColor; -varying vec2 vColorTexCoord; -varying vec2 vMaskTexCoord; -varying vec4 vBorderPosition; -varying vec4 vBorderRadii; -varying vec2 vDestTextureSize; -varying vec2 vSourceTextureSize; -varying float vBlurRadius; -varying vec4 vTileParams; -varying vec4 vClipInRect; -varying vec4 vClipOutRect; - -int Bottom7Bits(int value) { - return value % 0x80; -} - -bool IsBottomTriangle() { - // FIXME(pcwalton): No gl_VertexID in OpenGL ES 2. We'll need some extra data. - return false; -} - -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? - return floor(0.5 + pos * uDevicePixelRatio) / uDevicePixelRatio; -} diff --git a/resources/shaders/filter.fs.glsl b/resources/shaders/filter.fs.glsl deleted file mode 100644 index b4b5b707d5f..00000000000 --- a/resources/shaders/filter.fs.glsl +++ /dev/null @@ -1,148 +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/. */ - -vec3 rgbToHsv(vec3 c) { - float value = max(max(c.r, c.g), c.b); - - float chroma = value - min(min(c.r, c.g), c.b); - if (chroma == 0.0) { - return vec3(0.0); - } - float saturation = chroma / value; - - float hue; - if (c.r == value) - hue = (c.g - c.b) / chroma; - else if (c.g == value) - hue = 2.0 + (c.b - c.r) / chroma; - else // if (c.b == value) - hue = 4.0 + (c.r - c.g) / chroma; - - hue *= 1.0/6.0; - if (hue < 0.0) - hue += 1.0; - return vec3(hue, saturation, value); -} - -vec3 hsvToRgb(vec3 c) { - if (c.s == 0.0) { - return vec3(c.z); - } - - float hue = c.x * 6.0; - int sector = int(hue); - float residualHue = hue - float(sector); - - vec3 pqt = c.z * vec3(1.0 - c.y, 1.0 - c.y * residualHue, 1.0 - c.y * (1.0 - residualHue)); - if (sector == 0) - return vec3(c.z, pqt.z, pqt.x); - if (sector == 1) - return vec3(pqt.y, c.z, pqt.x); - if (sector == 2) - return vec3(pqt.x, c.z, pqt.z); - if (sector == 3) - return vec3(pqt.x, pqt.y, c.z); - if (sector == 4) - return vec3(pqt.z, pqt.x, c.z); - return vec3(c.z, pqt.x, pqt.y); -} - -float gauss(float x, float sigma) { - if (sigma == 0.0) - return 1.0; - return (1.0 / sqrt(6.283185307179586 * sigma * sigma)) * exp(-(x * x) / (2.0 * sigma * sigma)); -} - -vec4 Blur(float radius, vec2 direction) { -#ifdef SERVO_ES2 - // TODO(gw): for loops have to be unrollable on es2. - return vec4(1.0, 0.0, 0.0, 1.0); -#else - int range = int(radius) * 3; - float sigma = radius / 2.0; - vec4 color = vec4(0.0); - for (int offset = -range; offset <= range; offset++) { - float offsetF = float(offset); - - // Here, we use the vMaskTexCoord.xy (i.e. the muv) to store the texture size. - vec2 texCoord = vColorTexCoord.xy + vec2(offsetF) / vMaskTexCoord.xy * direction; - vec4 x = texCoord.x >= 0.0 && - texCoord.x <= 1.0 && - texCoord.y >= 0.0 && - texCoord.y <= 1.0 ? - Texture(sDiffuse, texCoord) : - vec4(0.0); - color += x * gauss(offsetF, sigma); - } - return color; -#endif -} - -vec4 Contrast(vec4 Cs, float amount) { - return vec4(Cs.rgb * amount - 0.5 * amount + 0.5, 1.0); -} - -vec4 Grayscale(vec4 Cs, float amount) { - float ia = 1.0 - amount; - return mat4(vec4(0.2126 + 0.7874 * ia, 0.2126 - 0.2126 * ia, 0.2126 - 0.2126 * ia, 0.0), - vec4(0.7152 - 0.7152 * ia, 0.7152 + 0.2848 * ia, 0.7152 - 0.7152 * ia, 0.0), - vec4(0.0722 - 0.0722 * ia, 0.0722 - 0.0722 * ia, 0.0722 + 0.9278 * ia, 0.0), - vec4(0.0, 0.0, 0.0, 1.0)) * Cs; -} - -vec4 HueRotate(vec4 Cs, float amount) { - vec3 CsHsv = rgbToHsv(Cs.rgb); - CsHsv.x = mod(CsHsv.x + amount / 6.283185307179586, 1.0); - return vec4(hsvToRgb(CsHsv), Cs.a); -} - -vec4 Invert(vec4 Cs, float amount) { - return mix(Cs, vec4(1.0, 1.0, 1.0, Cs.a) - vec4(Cs.rgb, 0.0), amount); -} - -vec4 Saturate(vec4 Cs, float amount) { - return vec4(hsvToRgb(min(vec3(1.0, amount, 1.0) * rgbToHsv(Cs.rgb), vec3(1.0))), Cs.a); -} - -vec4 Sepia(vec4 Cs, float amount) { - float ia = 1.0 - amount; - return mat4(vec4(0.393 + 0.607 * ia, 0.349 - 0.349 * ia, 0.272 - 0.272 * ia, 0.0), - vec4(0.769 - 0.769 * ia, 0.686 + 0.314 * ia, 0.534 - 0.534 * ia, 0.0), - vec4(0.189 - 0.189 * ia, 0.168 - 0.168 * ia, 0.131 + 0.869 * ia, 0.0), - vec4(0.0, 0.0, 0.0, 1.0)) * Cs; -} - -void main(void) -{ - // TODO: May be best to have separate shaders (esp. on Tegra) - int filterOp = int(uFilterParams.x); - float amount = uFilterParams.y; - - // Return yellow if none of the branches match (shouldn't happen). - vec4 result = vec4(1.0, 1.0, 0.0, 1.0); - - if (filterOp == 0) { - // Gaussian blur is specially handled: - result = Blur(amount, uFilterParams.zw); - } else { - vec4 Cs = Texture(sDiffuse, vColorTexCoord); - - if (filterOp == 1) { - result = Contrast(Cs, amount); - } else if (filterOp == 2) { - result = Grayscale(Cs, amount); - } else if (filterOp == 3) { - result = HueRotate(Cs, amount); - } else if (filterOp == 4) { - result = Invert(Cs, amount); - } else if (filterOp == 5) { - result = Saturate(Cs, amount); - } else if (filterOp == 6) { - result = Sepia(Cs, amount); - } - } - - SetFragColor(result); -} - diff --git a/resources/shaders/filter.vs.glsl b/resources/shaders/filter.vs.glsl deleted file mode 100644 index a8d526383bc..00000000000 --- a/resources/shaders/filter.vs.glsl +++ /dev/null @@ -1,12 +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/. */ - -void main(void) -{ - vColorTexCoord = aColorTexCoordRectTop.xy; - vMaskTexCoord = aMaskTexCoordRectTop.xy; - vec4 pos = vec4(aPosition, 1.0); - pos.xy = SnapToPixels(pos.xy); - gl_Position = uTransform * pos; -} diff --git a/resources/shaders/gl3_common.fs.glsl b/resources/shaders/gl3_common.fs.glsl deleted file mode 100644 index e88e921f65f..00000000000 --- a/resources/shaders/gl3_common.fs.glsl +++ /dev/null @@ -1,41 +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/. */ - -#define SERVO_GL3 - -precision highp float; - -uniform sampler2D sDiffuse; -uniform sampler2D sMask; -uniform vec4 uBlendParams; -uniform vec2 uDirection; -uniform vec4 uFilterParams; - -in vec2 vPosition; -in vec4 vColor; -in vec2 vColorTexCoord; -in vec2 vMaskTexCoord; -in vec4 vBorderPosition; -in vec4 vBorderRadii; -in vec2 vDestTextureSize; -in vec2 vSourceTextureSize; -in float vBlurRadius; -in vec4 vTileParams; -in vec4 vClipInRect; -in vec4 vClipOutRect; - -out vec4 oFragColor; - -vec4 Texture(sampler2D sampler, vec2 texCoord) { - return texture(sampler, texCoord); -} - -float GetAlphaFromMask(vec4 mask) { - return mask.r; -} - -void SetFragColor(vec4 color) { - oFragColor = color; -} - diff --git a/resources/shaders/gl3_common.vs.glsl b/resources/shaders/gl3_common.vs.glsl deleted file mode 100644 index cffcfc80eb7..00000000000 --- a/resources/shaders/gl3_common.vs.glsl +++ /dev/null @@ -1,66 +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/. */ - -#define SERVO_GL3 - -uniform mat4 uTransform; -uniform vec4 uOffsets[32]; -uniform vec4 uClipRects[64]; -uniform mat4 uMatrixPalette[32]; -uniform vec2 uDirection; -uniform vec4 uBlendParams; -uniform vec4 uFilterParams; -uniform float uDevicePixelRatio; -uniform vec4 uTileParams[64]; -uniform vec4 uAtlasParams; - -in vec3 aPosition; -in vec4 aPositionRect; // Width can be negative to flip horizontally (for border corners). -in vec4 aColorRectTL; -in vec4 aColorRectTR; -in vec4 aColorRectBR; -in vec4 aColorRectBL; -in vec4 aColorTexCoordRectTop; -in vec4 aColorTexCoordRectBottom; -in vec4 aMaskTexCoordRectTop; -in vec4 aMaskTexCoordRectBottom; -in vec4 aBorderPosition; -in vec4 aBorderRadii; -in vec2 aSourceTextureSize; -in vec2 aDestTextureSize; -in float aBlurRadius; -// x = matrix index; y = clip-in rect; z = clip-out rect; w = tile params index. -// -// A negative w value activates border corner mode. In this mode, the TR and BL colors are ignored, -// the color of the top left corner applies to all vertices of the top left triangle, and the color -// of the bottom right corner applies to all vertices of the bottom right triangle. -in vec4 aMisc; - -out vec2 vPosition; -out vec4 vColor; -out vec2 vColorTexCoord; -out vec2 vMaskTexCoord; -out vec4 vBorderPosition; -out vec4 vBorderRadii; -out vec2 vDestTextureSize; -out vec2 vSourceTextureSize; -out float vBlurRadius; -out vec4 vTileParams; -out vec4 vClipInRect; -out vec4 vClipOutRect; - -int Bottom7Bits(int value) { - return value & 0x7f; -} - -bool IsBottomTriangle() { - return gl_VertexID > 2; -} - -vec2 SnapToPixels(vec2 pos) -{ - // Snap the vertex to pixel position to guarantee correct texture - // sampling when using bilinear filtering. - return round(pos * uDevicePixelRatio) / uDevicePixelRatio; -} diff --git a/resources/shaders/ps_text.fs.glsl b/resources/shaders/ps_text.fs.glsl deleted file mode 100644 index 79051beb583..00000000000 --- a/resources/shaders/ps_text.fs.glsl +++ /dev/null @@ -1,13 +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/. */ - -void main(void) { - float a = texture(sDiffuse, vUv).a; -#ifdef WR_FEATURE_TRANSFORM - float alpha = 0.0; - init_transform_fs(vLocalPos, vLocalRect, alpha); - a *= alpha; -#endif - oFragColor = vec4(vColor.rgb, vColor.a * a); -} diff --git a/resources/shaders/ps_text.glsl b/resources/shaders/ps_text.glsl deleted file mode 100644 index d58ff7d14bb..00000000000 --- a/resources/shaders/ps_text.glsl +++ /dev/null @@ -1,11 +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/. */ - -flat varying vec4 vColor; -varying vec2 vUv; - -#ifdef WR_FEATURE_TRANSFORM -varying vec3 vLocalPos; -flat varying vec4 vLocalRect; -#endif diff --git a/resources/shaders/ps_text.vs.glsl b/resources/shaders/ps_text.vs.glsl deleted file mode 100644 index 18d5f5530fa..00000000000 --- a/resources/shaders/ps_text.vs.glsl +++ /dev/null @@ -1,25 +0,0 @@ -#line 1 -/* 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/. */ - -void main(void) { - Glyph glyph = fetch_glyph(gl_InstanceID); - -#ifdef WR_FEATURE_TRANSFORM - TransformVertexInfo vi = write_transform_vertex(glyph.info); - vLocalRect = vi.clipped_local_rect; - vLocalPos = vi.local_pos; - vec2 f = (vi.local_pos.xy / vi.local_pos.z - glyph.info.local_rect.xy) / glyph.info.local_rect.zw; -#else - VertexInfo vi = write_vertex(glyph.info); - vec2 f = (vi.local_clamped_pos - vi.local_rect.p0) / (vi.local_rect.p1 - vi.local_rect.p0); -#endif - - vec2 texture_size = vec2(textureSize(sDiffuse, 0)); - vec2 st0 = glyph.uv_rect.xy / texture_size; - vec2 st1 = glyph.uv_rect.zw / texture_size; - - vColor = glyph.color; - vUv = mix(st0, st1, f); -} diff --git a/tests/unit/net/http_loader.rs b/tests/unit/net/http_loader.rs index fccef5000fb..9508d36a8f5 100644 --- a/tests/unit/net/http_loader.rs +++ b/tests/unit/net/http_loader.rs @@ -24,6 +24,7 @@ use make_server; use msg::constellation_msg::{PipelineId, TEST_PIPELINE_ID}; use net::cookie::Cookie; use net::cookie_storage::CookieStorage; +use net::fetch::methods::fetch; use net::hsts::HstsEntry; use net::resource_thread::{AuthCacheEntry, CancellationListener}; use net::test::{HttpRequest, HttpRequestFactory, HttpState, LoadError, UIProvider, load}; @@ -31,8 +32,11 @@ use net::test::{HttpResponse, LoadErrorType}; use net_traits::{CookieSource, IncludeSubdomains, LoadContext, LoadData}; use net_traits::{CustomResponse, LoadOrigin, Metadata, ReferrerPolicy}; use net_traits::request::{Request, RequestInit, Destination}; +use net_traits::response::ResponseBody; +use new_fetch_context; use std::borrow::Cow; use std::io::{self, Cursor, Read, Write}; +use std::rc::Rc; use std::sync::{Arc, Mutex, RwLock, mpsc}; use std::sync::mpsc::Receiver; use std::thread; @@ -303,27 +307,6 @@ impl HttpRequestFactory for AssertMustNotIncludeHeadersRequestFactory { } } -struct AssertMustHaveBodyRequest { - expected_body: Option<Vec<u8>>, - t: ResponseType -} - -impl AssertMustHaveBodyRequest { - fn new(t: ResponseType, expected_body: Option<Vec<u8>>) -> Self { - AssertMustHaveBodyRequest { expected_body: expected_body, t: t } - } -} - -impl HttpRequest for AssertMustHaveBodyRequest { - type R = MockResponse; - - fn send(self, body: &Option<Vec<u8>>) -> Result<MockResponse, LoadError> { - assert_eq!(self.expected_body, *body); - - response_for_request_type(self.t) - } -} - pub fn expect_devtools_http_request(devtools_port: &Receiver<DevtoolsControlMsg>) -> DevtoolsHttpRequest { match devtools_port.recv().unwrap() { DevtoolsControlMsg::FromChrome( @@ -618,179 +601,156 @@ fn test_redirected_request_to_devtools() { #[test] fn test_load_when_redirecting_from_a_post_should_rewrite_next_request_as_get() { - struct Factory; - - impl HttpRequestFactory for Factory { - type R = MockRequest; - - fn create(&self, url: Url, method: Method, _: Headers) -> Result<MockRequest, LoadError> { - if url.domain().unwrap() == "mozilla.com" { - assert_eq!(Method::Post, method); - Ok(MockRequest::new(ResponseType::Redirect("http://mozilla.org".to_owned()))) - } else { - assert_eq!(Method::Get, method); - Ok(MockRequest::new(ResponseType::Text(<[_]>::to_vec("Yay!".as_bytes())))) - } - } - } + let post_handler = move |request: HyperRequest, response: HyperResponse| { + assert_eq!(request.method, Method::Get); + response.send(b"Yay!").unwrap(); + }; + let (mut post_server, post_url) = make_server(post_handler); - let url = Url::parse("http://mozilla.com").unwrap(); - let mut load_data = LoadData::new(LoadContext::Browsing, url.clone(), &HttpTest); + let post_redirect_url = post_url.clone(); + let pre_handler = move |request: HyperRequest, mut response: HyperResponse| { + assert_eq!(request.method, Method::Post); + response.headers_mut().set(Location(post_redirect_url.to_string())); + *response.status_mut() = StatusCode::MovedPermanently; + response.send(b"").unwrap(); + }; + let (mut pre_server, pre_url) = make_server(pre_handler); - load_data.method = Method::Post; + let request = Request::from_init(RequestInit { + url: pre_url.clone(), + method: Method::Post, + destination: Destination::Document, + origin: pre_url.clone(), + pipeline_id: Some(TEST_PIPELINE_ID), + .. RequestInit::default() + }); + let response = fetch_sync(request, None); - let http_state = HttpState::new(); - let ui_provider = TestProvider::new(); + let _ = pre_server.close(); + let _ = post_server.close(); - let _ = load(&load_data, &ui_provider, &http_state, None, &Factory, - DEFAULT_USER_AGENT.into(), &CancellationListener::new(None), None); + assert!(response.to_actual().status.unwrap().is_success()); } #[test] fn test_load_should_decode_the_response_as_deflate_when_response_headers_have_content_encoding_deflate() { - struct Factory; - - impl HttpRequestFactory for Factory { - type R = MockRequest; - - fn create(&self, _: Url, _: Method, _: Headers) -> Result<MockRequest, LoadError> { - let mut e = DeflateEncoder::new(Vec::new(), Compression::Default); - e.write(b"Yay!").unwrap(); - let encoded_content = e.finish().unwrap(); - - let mut headers = Headers::new(); - headers.set(ContentEncoding(vec![Encoding::Deflate])); - Ok(MockRequest::new(ResponseType::WithHeaders(encoded_content, headers))) - } - } - - let url = Url::parse("http://mozilla.com").unwrap(); - let load_data = LoadData::new(LoadContext::Browsing, url.clone(), &HttpTest); + let handler = move |_: HyperRequest, mut response: HyperResponse| { + response.headers_mut().set(ContentEncoding(vec![Encoding::Deflate])); + let mut e = DeflateEncoder::new(Vec::new(), Compression::Default); + e.write(b"Yay!").unwrap(); + let encoded_content = e.finish().unwrap(); + response.send(&encoded_content).unwrap(); + }; + let (mut server, url) = make_server(handler); - let http_state = HttpState::new(); - let ui_provider = TestProvider::new(); + let request = Request::from_init(RequestInit { + url: url.clone(), + method: Method::Get, + body: None, + destination: Destination::Document, + origin: url.clone(), + pipeline_id: Some(TEST_PIPELINE_ID), + .. RequestInit::default() + }); + let response = fetch_sync(request, None); - let mut response = load( - &load_data, &ui_provider, &http_state, None, - &Factory, - DEFAULT_USER_AGENT.into(), - &CancellationListener::new(None), - None) - .unwrap(); + let _ = server.close(); - assert_eq!(read_response(&mut response), "Yay!"); + assert!(response.status.unwrap().is_success()); + assert_eq!(*response.body.lock().unwrap(), + ResponseBody::Done(b"Yay!".to_vec())); } #[test] fn test_load_should_decode_the_response_as_gzip_when_response_headers_have_content_encoding_gzip() { - struct Factory; - - impl HttpRequestFactory for Factory { - type R = MockRequest; - - fn create(&self, _: Url, _: Method, _: Headers) -> Result<MockRequest, LoadError> { - let mut e = GzEncoder::new(Vec::new(), Compression::Default); - e.write(b"Yay!").unwrap(); - let encoded_content = e.finish().unwrap(); - - let mut headers = Headers::new(); - headers.set(ContentEncoding(vec![Encoding::Gzip])); - Ok(MockRequest::new(ResponseType::WithHeaders(encoded_content, headers))) - } - } - - let url = Url::parse("http://mozilla.com").unwrap(); - let load_data = LoadData::new(LoadContext::Browsing, url.clone(), &HttpTest); + let handler = move |_: HyperRequest, mut response: HyperResponse| { + response.headers_mut().set(ContentEncoding(vec![Encoding::Gzip])); + let mut e = GzEncoder::new(Vec::new(), Compression::Default); + e.write(b"Yay!").unwrap(); + let encoded_content = e.finish().unwrap(); + response.send(&encoded_content).unwrap(); + }; + let (mut server, url) = make_server(handler); - let http_state = HttpState::new(); - let ui_provider = TestProvider::new(); + let request = Request::from_init(RequestInit { + url: url.clone(), + method: Method::Get, + body: None, + destination: Destination::Document, + origin: url.clone(), + pipeline_id: Some(TEST_PIPELINE_ID), + .. RequestInit::default() + }); + let response = fetch_sync(request, None); - let mut response = load( - &load_data, - &ui_provider, &http_state, - None, &Factory, - DEFAULT_USER_AGENT.into(), - &CancellationListener::new(None), - None) - .unwrap(); + let _ = server.close(); - assert_eq!(read_response(&mut response), "Yay!"); + assert!(response.status.unwrap().is_success()); + assert_eq!(*response.body.lock().unwrap(), + ResponseBody::Done(b"Yay!".to_vec())); } #[test] fn test_load_doesnt_send_request_body_on_any_redirect() { - struct Factory; - - impl HttpRequestFactory for Factory { - type R = AssertMustHaveBodyRequest; - - fn create(&self, url: Url, _: Method, _: Headers) -> Result<AssertMustHaveBodyRequest, LoadError> { - if url.domain().unwrap() == "mozilla.com" { - Ok( - AssertMustHaveBodyRequest::new( - ResponseType::Redirect("http://mozilla.org".to_owned()), - Some(<[_]>::to_vec("Body on POST!".as_bytes())) - ) - ) - } else { - Ok( - AssertMustHaveBodyRequest::new( - ResponseType::Text(<[_]>::to_vec("Yay!".as_bytes())), - None - ) - ) - } - } - } + let post_handler = move |mut request: HyperRequest, response: HyperResponse| { + assert_eq!(request.method, Method::Get); + let data = read_response(&mut request); + assert_eq!(data, ""); + response.send(b"Yay!").unwrap(); + }; + let (mut post_server, post_url) = make_server(post_handler); - let url = Url::parse("http://mozilla.com").unwrap(); - let mut load_data = LoadData::new(LoadContext::Browsing, url.clone(), &HttpTest); + let post_redirect_url = post_url.clone(); + let pre_handler = move |mut request: HyperRequest, mut response: HyperResponse| { + let data = read_response(&mut request); + assert_eq!(data, "Body on POST!"); + response.headers_mut().set(Location(post_redirect_url.to_string())); + *response.status_mut() = StatusCode::MovedPermanently; + response.send(b"").unwrap(); + }; + let (mut pre_server, pre_url) = make_server(pre_handler); - load_data.data = Some(<[_]>::to_vec("Body on POST!".as_bytes())); + let request = Request::from_init(RequestInit { + url: pre_url.clone(), + body: Some(b"Body on POST!".to_vec()), + method: Method::Post, + destination: Destination::Document, + origin: pre_url.clone(), + pipeline_id: Some(TEST_PIPELINE_ID), + .. RequestInit::default() + }); + let response = fetch_sync(request, None); - let http_state = HttpState::new(); - let ui_provider = TestProvider::new(); + let _ = pre_server.close(); + let _ = post_server.close(); - let _ = load( - &load_data, &ui_provider, &http_state, - None, - &Factory, - DEFAULT_USER_AGENT.into(), - &CancellationListener::new(None), - None); + assert!(response.to_actual().status.unwrap().is_success()); } #[test] fn test_load_doesnt_add_host_to_sts_list_when_url_is_http_even_if_sts_headers_are_present() { - struct Factory; - - impl HttpRequestFactory for Factory { - type R = MockRequest; - - fn create(&self, _: Url, _: Method, _: Headers) -> Result<MockRequest, LoadError> { - let content = <[_]>::to_vec("Yay!".as_bytes()); - let mut headers = Headers::new(); - headers.set(StrictTransportSecurity::excluding_subdomains(31536000)); - Ok(MockRequest::new(ResponseType::WithHeaders(content, headers))) - } - } - - let url = Url::parse("http://mozilla.com").unwrap(); - - let load_data = LoadData::new(LoadContext::Browsing, url.clone(), &HttpTest); + let handler = move |_: HyperRequest, mut response: HyperResponse| { + response.headers_mut().set(StrictTransportSecurity::excluding_subdomains(31536000)); + response.send(b"Yay!").unwrap(); + }; + let (mut server, url) = make_server(handler); - let http_state = HttpState::new(); - let ui_provider = TestProvider::new(); + let request = Request::from_init(RequestInit { + url: url.clone(), + method: Method::Get, + body: None, + destination: Destination::Document, + origin: url.clone(), + pipeline_id: Some(TEST_PIPELINE_ID), + .. RequestInit::default() + }); + let context = new_fetch_context(None); + let response = fetch(Rc::new(request), &mut None, &context); - let _ = load(&load_data, - &ui_provider, &http_state, - None, - &Factory, - DEFAULT_USER_AGENT.into(), - &CancellationListener::new(None), - None); + let _ = server.close(); - assert_eq!(http_state.hsts_list.read().unwrap().is_host_secure("mozilla.com"), false); + assert!(response.status.unwrap().is_success()); + assert_eq!(context.state.hsts_list.read().unwrap().is_host_secure(url.host_str().unwrap()), false); } #[test] diff --git a/tests/unit/style/media_queries.rs b/tests/unit/style/media_queries.rs index 7cc55c412c4..7c9d0439051 100644 --- a/tests/unit/style/media_queries.rs +++ b/tests/unit/style/media_queries.rs @@ -59,11 +59,7 @@ fn media_query_test(device: &Device, css: &str, expected_rule_count: usize) { #[test] fn test_mq_empty() { test_media_rule("@media { }", |list, css| { - assert!(list.media_queries.len() == 1, css.to_owned()); - let q = &list.media_queries[0]; - assert!(q.qualifier == None, css.to_owned()); - assert!(q.media_type == MediaQueryType::All, css.to_owned()); - assert!(q.expressions.len() == 0, css.to_owned()); + assert!(list.media_queries.len() == 0, css.to_owned()); }); } diff --git a/tests/unit/style/stylesheets.rs b/tests/unit/style/stylesheets.rs index 4ec9388d4c2..6a3e299f6c7 100644 --- a/tests/unit/style/stylesheets.rs +++ b/tests/unit/style/stylesheets.rs @@ -54,7 +54,7 @@ fn test_parse_stylesheet() { ParserContextExtraData::default()); let expected = Stylesheet { origin: Origin::UserAgent, - media: None, + media: Default::default(), dirty_on_viewport_size_change: false, rules: vec![ CSSRule::Namespace(Arc::new(RwLock::new(NamespaceRule { diff --git a/tests/wpt/metadata-css/css21_dev/html4/block-in-inline-insert-017.htm.ini b/tests/wpt/metadata-css/css21_dev/html4/block-in-inline-insert-017.htm.ini deleted file mode 100644 index 8bec273fdbe..00000000000 --- a/tests/wpt/metadata-css/css21_dev/html4/block-in-inline-insert-017.htm.ini +++ /dev/null @@ -1,3 +0,0 @@ -[block-in-inline-insert-017.htm] - type: reftest - expected: FAIL diff --git a/tests/wpt/metadata-css/css21_dev/html4/inline-box-001.htm.ini b/tests/wpt/metadata-css/css21_dev/html4/inline-box-001.htm.ini deleted file mode 100644 index db058c8e51c..00000000000 --- a/tests/wpt/metadata-css/css21_dev/html4/inline-box-001.htm.ini +++ /dev/null @@ -1,3 +0,0 @@ -[inline-box-001.htm] - type: reftest - expected: FAIL diff --git a/tests/wpt/metadata-css/css21_dev/html4/ltr-ib.htm.ini b/tests/wpt/metadata-css/css21_dev/html4/ltr-ib.htm.ini deleted file mode 100644 index 8c04c3abae4..00000000000 --- a/tests/wpt/metadata-css/css21_dev/html4/ltr-ib.htm.ini +++ /dev/null @@ -1,3 +0,0 @@ -[ltr-ib.htm] - type: reftest - expected: FAIL diff --git a/tests/wpt/metadata-css/css21_dev/html4/rtl-ib.htm.ini b/tests/wpt/metadata-css/css21_dev/html4/rtl-ib.htm.ini deleted file mode 100644 index b698c88f880..00000000000 --- a/tests/wpt/metadata-css/css21_dev/html4/rtl-ib.htm.ini +++ /dev/null @@ -1,3 +0,0 @@ -[rtl-ib.htm] - type: reftest - expected: FAIL diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json index 2f106202838..24b1a75c495 100644 --- a/tests/wpt/metadata/MANIFEST.json +++ b/tests/wpt/metadata/MANIFEST.json @@ -37753,6 +37753,12 @@ "url": "/cookies/path/match.html" } ], + "cssom-view/MediaQueryList-with-empty-string.html": [ + { + "path": "cssom-view/MediaQueryList-with-empty-string.html", + "url": "/cssom-view/MediaQueryList-with-empty-string.html" + } + ], "html/semantics/forms/the-form-element/form-action-url.html": [ { "path": "html/semantics/forms/the-form-element/form-action-url.html", diff --git a/tests/wpt/metadata/fetch/api/redirect/redirect-mode-worker.html.ini b/tests/wpt/metadata/fetch/api/redirect/redirect-mode-worker.html.ini index 3b1d82612e7..c2a2bb20543 100644 --- a/tests/wpt/metadata/fetch/api/redirect/redirect-mode-worker.html.ini +++ b/tests/wpt/metadata/fetch/api/redirect/redirect-mode-worker.html.ini @@ -1,32 +1,17 @@ [redirect-mode-worker.html] type: testharness - [Redirect 301 in "error" mode ] - expected: FAIL - [Redirect 301 in "manual" mode ] expected: FAIL - [Redirect 302 in "error" mode ] - expected: FAIL - [Redirect 302 in "manual" mode ] expected: FAIL - [Redirect 303 in "error" mode ] - expected: FAIL - [Redirect 303 in "manual" mode ] expected: FAIL - [Redirect 307 in "error" mode ] - expected: FAIL - [Redirect 307 in "manual" mode ] expected: FAIL - [Redirect 308 in "error" mode ] - expected: FAIL - [Redirect 308 in "manual" mode ] expected: FAIL diff --git a/tests/wpt/metadata/fetch/api/redirect/redirect-mode.html.ini b/tests/wpt/metadata/fetch/api/redirect/redirect-mode.html.ini index 8c1254256d1..d39b314c9bb 100644 --- a/tests/wpt/metadata/fetch/api/redirect/redirect-mode.html.ini +++ b/tests/wpt/metadata/fetch/api/redirect/redirect-mode.html.ini @@ -1,32 +1,17 @@ [redirect-mode.html] type: testharness - [Redirect 301 in "error" mode ] - expected: FAIL - [Redirect 301 in "manual" mode ] expected: FAIL - [Redirect 302 in "error" mode ] - expected: FAIL - [Redirect 302 in "manual" mode ] expected: FAIL - [Redirect 303 in "error" mode ] - expected: FAIL - [Redirect 303 in "manual" mode ] expected: FAIL - [Redirect 307 in "error" mode ] - expected: FAIL - [Redirect 307 in "manual" mode ] expected: FAIL - [Redirect 308 in "error" mode ] - expected: FAIL - [Redirect 308 in "manual" mode ] expected: FAIL diff --git a/tests/wpt/metadata/fetch/api/request/request-headers.html.ini b/tests/wpt/metadata/fetch/api/request/request-headers.html.ini index 3f2673c143d..58f805ae0c8 100644 --- a/tests/wpt/metadata/fetch/api/request/request-headers.html.ini +++ b/tests/wpt/metadata/fetch/api/request/request-headers.html.ini @@ -1,8 +1,5 @@ [request-headers.html] type: testharness - [Testing request header creations with various objects] - expected: FAIL - [Testing empty Request Content-Type header] expected: FAIL diff --git a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/misc/object-deletion-behaviour.html.ini b/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/misc/object-deletion-behaviour.html.ini index 8e2be3e1863..8cb6c72e03d 100644 --- a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/misc/object-deletion-behaviour.html.ini +++ b/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/misc/object-deletion-behaviour.html.ini @@ -174,9 +174,6 @@ [WebGL test #171: gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) threw exception TypeError: gl.getFramebufferAttachmentParameter is not a function] expected: FAIL - [WebGL test #187: gl.checkFramebufferStatus(gl.FRAMEBUFFER) should not be 36053.] - expected: FAIL - [WebGL test #196: gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) should be [object WebGLTexture\]. Threw exception TypeError: gl.getFramebufferAttachmentParameter is not a function] expected: FAIL diff --git a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/more/functions/readPixelsBadArgs.html.ini b/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/more/functions/readPixelsBadArgs.html.ini deleted file mode 100644 index e85893ee2a5..00000000000 --- a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/more/functions/readPixelsBadArgs.html.ini +++ /dev/null @@ -1,8 +0,0 @@ -[readPixelsBadArgs.html] - type: testharness - expected: - if os == "linux": CRASH - if os == "mac": TIMEOUT - [WebGL test #0: testReadPixels] - expected: FAIL - diff --git a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/reading/read-pixels-pack-alignment.html.ini b/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/reading/read-pixels-pack-alignment.html.ini index 3704c6c4f1b..d5b3c59a27d 100644 --- a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/reading/read-pixels-pack-alignment.html.ini +++ b/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/reading/read-pixels-pack-alignment.html.ini @@ -1,8 +1,14 @@ [read-pixels-pack-alignment.html] type: testharness - expected: - if os == "linux": CRASH - if os == "mac": TIMEOUT - [WebGL test #3: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).] + [WebGL test #17: pixel should be 255,102,0,255. Was 0,0,0,0.] + expected: FAIL + + [WebGL test #33: pixel should be 255,102,0,255. Was 0,0,0,0.] + expected: FAIL + + [WebGL test #53: pixel should be 255,102,0,255. Was 0,0,0,0.] + expected: FAIL + + [WebGL test #61: pixel should be 255,102,0,255. Was 0,0,0,0.] expected: FAIL diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index b0b62309839..4752ad4381f 100644 --- a/tests/wpt/mozilla/meta/MANIFEST.json +++ b/tests/wpt/mozilla/meta/MANIFEST.json @@ -5496,28 +5496,40 @@ "url": "/_mozilla/css/text_node_opacity.html" } ], - "css/text_overflow_a.html": [ + "css/text_overflow_basic_a.html": [ { - "path": "css/text_overflow_a.html", + "path": "css/text_overflow_basic_a.html", + "references": [ + [ + "/_mozilla/css/text_overflow_basic_ref.html", + "==" + ] + ], + "url": "/_mozilla/css/text_overflow_basic_a.html" + } + ], + "css/text_overflow_ellipsis.html": [ + { + "path": "css/text_overflow_ellipsis.html", "references": [ [ "/_mozilla/css/text_overflow_ref.html", "!=" ] ], - "url": "/_mozilla/css/text_overflow_a.html" + "url": "/_mozilla/css/text_overflow_ellipsis.html" } ], - "css/text_overflow_basic_a.html": [ + "css/text_overflow_string.html": [ { - "path": "css/text_overflow_basic_a.html", + "path": "css/text_overflow_string.html", "references": [ [ - "/_mozilla/css/text_overflow_basic_ref.html", - "==" + "/_mozilla/css/text_overflow_ref.html", + "!=" ] ], - "url": "/_mozilla/css/text_overflow_basic_a.html" + "url": "/_mozilla/css/text_overflow_string.html" } ], "css/text_shadow_blur_a.html": [ @@ -20364,28 +20376,40 @@ "url": "/_mozilla/css/text_node_opacity.html" } ], - "css/text_overflow_a.html": [ + "css/text_overflow_basic_a.html": [ { - "path": "css/text_overflow_a.html", + "path": "css/text_overflow_basic_a.html", + "references": [ + [ + "/_mozilla/css/text_overflow_basic_ref.html", + "==" + ] + ], + "url": "/_mozilla/css/text_overflow_basic_a.html" + } + ], + "css/text_overflow_ellipsis.html": [ + { + "path": "css/text_overflow_ellipsis.html", "references": [ [ "/_mozilla/css/text_overflow_ref.html", "!=" ] ], - "url": "/_mozilla/css/text_overflow_a.html" + "url": "/_mozilla/css/text_overflow_ellipsis.html" } ], - "css/text_overflow_basic_a.html": [ + "css/text_overflow_string.html": [ { - "path": "css/text_overflow_basic_a.html", + "path": "css/text_overflow_string.html", "references": [ [ - "/_mozilla/css/text_overflow_basic_ref.html", - "==" + "/_mozilla/css/text_overflow_ref.html", + "!=" ] ], - "url": "/_mozilla/css/text_overflow_basic_a.html" + "url": "/_mozilla/css/text_overflow_string.html" } ], "css/text_shadow_blur_a.html": [ diff --git a/tests/wpt/mozilla/tests/css/text_overflow_a.html b/tests/wpt/mozilla/tests/css/text_overflow_ellipsis.html index 2a3ca5be0f7..70de0992fee 100644 --- a/tests/wpt/mozilla/tests/css/text_overflow_a.html +++ b/tests/wpt/mozilla/tests/css/text_overflow_ellipsis.html @@ -8,14 +8,13 @@ p { background: gold; text-overflow: ellipsis; } -#hideme { +p.hidden { overflow: hidden; } </style> </head> <body> -<p id=hideme>mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm</p> <p>mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm</p> +<p class="hidden">mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm</p> </body> </html> - diff --git a/tests/wpt/mozilla/tests/css/text_overflow_ref.html b/tests/wpt/mozilla/tests/css/text_overflow_ref.html index 19adf5d9104..0e19e6e3f07 100644 --- a/tests/wpt/mozilla/tests/css/text_overflow_ref.html +++ b/tests/wpt/mozilla/tests/css/text_overflow_ref.html @@ -13,5 +13,3 @@ p { <p>mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm</p> </body> </html> - - diff --git a/tests/wpt/mozilla/tests/css/text_overflow_string.html b/tests/wpt/mozilla/tests/css/text_overflow_string.html new file mode 100644 index 00000000000..3249b8b224f --- /dev/null +++ b/tests/wpt/mozilla/tests/css/text_overflow_string.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<html> +<head> +<link rel=mismatch href=text_overflow_ref.html> +<style> +p { + width: 128px; + background: gold; + text-overflow: "[..]"; +} +p.hidden { + overflow: hidden; +} +</style> +</head> +<body> +<p>mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm</p> +<p class="hidden">mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm</p> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/cssom-view/MediaQueryList-with-empty-string.html b/tests/wpt/web-platform-tests/cssom-view/MediaQueryList-with-empty-string.html new file mode 100644 index 00000000000..3d5a5316566 --- /dev/null +++ b/tests/wpt/web-platform-tests/cssom-view/MediaQueryList-with-empty-string.html @@ -0,0 +1,12 @@ +<!doctype html> +<meta charset="utf-8"> +<title>cssom-view - MediaQueryList with empty string</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(function () { + var mql = window.matchMedia(''); + assert_equals(mql.media, '', "This should be an empty media query list"); + assert_equals(mql.matches, true, "Empty media query list should evaluate to true"); +}); +</script> |