aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/app_units/Cargo.toml4
-rw-r--r--components/compositing/constellation.rs3
-rw-r--r--components/compositing/headless.rs8
-rw-r--r--components/gfx/paint_context.rs2
-rw-r--r--components/gfx/text/glyph.rs94
-rw-r--r--components/gfx/text/shaping/harfbuzz.rs7
-rw-r--r--components/layout/block.rs12
-rw-r--r--components/layout/display_list_builder.rs135
-rw-r--r--components/layout/fragment.rs14
-rw-r--r--components/script/dom/htmlbuttonelement.rs6
-rw-r--r--components/script/dom/htmlfieldsetelement.rs8
-rw-r--r--components/script/dom/htmlformelement.rs14
-rw-r--r--components/script/dom/htmlinputelement.rs6
-rw-r--r--components/script/dom/htmllabelelement.rs9
-rw-r--r--components/script/dom/htmlobjectelement.rs8
-rw-r--r--components/script/dom/htmloutputelement.rs9
-rw-r--r--components/script/dom/htmlselectelement.rs10
-rw-r--r--components/script/dom/htmltextareaelement.rs8
-rw-r--r--components/util/str.rs4
-rw-r--r--python/servo/testing_commands.py35
-rw-r--r--tests/unit/util/str.rs26
21 files changed, 196 insertions, 226 deletions
diff --git a/components/app_units/Cargo.toml b/components/app_units/Cargo.toml
index d324f7cb27f..b019f842603 100644
--- a/components/app_units/Cargo.toml
+++ b/components/app_units/Cargo.toml
@@ -2,6 +2,10 @@
name = "app_units"
version = "0.1.0"
authors = ["The Servo Project Developers"]
+description = "Servo app units type (Au)"
+documentation = "http://doc.servo.org/app_units/"
+repository = "https://github.com/servo/app_units"
+license = "MIT / Apache-2.0"
[dependencies]
serde = "0.6"
diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs
index ffd898934cc..540267cc408 100644
--- a/components/compositing/constellation.rs
+++ b/components/compositing/constellation.rs
@@ -271,7 +271,8 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
ScaleFactor::new(1.0),
initial_viewport: opts::get().initial_window_size.as_f32() *
ScaleFactor::new(1.0),
- device_pixel_ratio: ScaleFactor::new(1.0),
+ device_pixel_ratio:
+ ScaleFactor::new(opts::get().device_pixels_per_px.unwrap_or(1.0)),
},
phantom: PhantomData,
clipboard_ctx: if state.supports_clipboard {
diff --git a/components/compositing/headless.rs b/components/compositing/headless.rs
index 92b445a4476..3a0ab67ea21 100644
--- a/components/compositing/headless.rs
+++ b/components/compositing/headless.rs
@@ -11,6 +11,7 @@ use msg::constellation_msg::Msg as ConstellationMsg;
use msg::constellation_msg::{ConstellationChan, WindowSizeData};
use profile_traits::mem;
use profile_traits::time;
+use util::opts;
use windowing::WindowEvent;
/// Starts the compositor, which listens for messages on the specified port.
@@ -45,9 +46,10 @@ impl NullCompositor {
{
let ConstellationChan(ref chan) = compositor.constellation_chan;
chan.send(ConstellationMsg::ResizedWindow(WindowSizeData {
- initial_viewport: Size2D::typed(640_f32, 480_f32),
- visible_viewport: Size2D::typed(640_f32, 480_f32),
- device_pixel_ratio: ScaleFactor::new(1.0),
+ initial_viewport: Size2D::typed(800_f32, 600_f32),
+ visible_viewport: Size2D::typed(800_f32, 600_f32),
+ device_pixel_ratio:
+ ScaleFactor::new(opts::get().device_pixels_per_px.unwrap_or(1.0)),
})).unwrap();
}
diff --git a/components/gfx/paint_context.rs b/components/gfx/paint_context.rs
index 8ac75733061..d73d9013a05 100644
--- a/components/gfx/paint_context.rs
+++ b/components/gfx/paint_context.rs
@@ -1792,7 +1792,7 @@ impl ScaledFontExtensionMethods for ScaledFont {
azglyphs.reserve(range.length().to_usize());
for slice in run.natural_word_slices_in_visual_order(range) {
- for (_i, glyph) in slice.glyphs.iter_glyphs_for_char_range(&slice.range) {
+ for glyph in slice.glyphs.iter_glyphs_for_char_range(&slice.range) {
let glyph_advance = glyph.advance();
let glyph_offset = glyph.offset().unwrap_or(Point2D::zero());
let azglyph = struct__AzGlyph {
diff --git a/components/gfx/text/glyph.rs b/components/gfx/text/glyph.rs
index 700a44e3d95..31a1c850d00 100644
--- a/components/gfx/text/glyph.rs
+++ b/components/gfx/text/glyph.rs
@@ -62,14 +62,6 @@ impl GlyphEntry {
GlyphEntry::new(glyph_count as u32)
}
- /// Create a GlyphEntry for the case where glyphs couldn't be found for the specified
- /// character.
- fn missing(glyph_count: usize) -> GlyphEntry {
- assert!(glyph_count <= u16::MAX as usize);
-
- GlyphEntry::new(glyph_count as u32)
- }
-
fn is_initial(&self) -> bool {
*self == GlyphEntry::initial()
}
@@ -129,8 +121,8 @@ impl GlyphEntry {
}
#[inline(always)]
- fn set_char_is_space(&self) -> GlyphEntry {
- GlyphEntry::new(self.value | FLAG_CHAR_IS_SPACE)
+ fn set_char_is_space(&mut self) {
+ self.value |= FLAG_CHAR_IS_SPACE;
}
fn glyph_count(&self) -> u16 {
@@ -147,11 +139,6 @@ impl GlyphEntry {
fn has_flag(&self, flag: u32) -> bool {
(self.value & flag) != 0
}
-
- #[inline(always)]
- fn adapt_character_flags_of_entry(&self, other: GlyphEntry) -> GlyphEntry {
- GlyphEntry { value: self.value | other.value }
- }
}
// Stores data for a detailed glyph, in the case that several glyphs
@@ -322,7 +309,6 @@ pub struct GlyphData {
id: GlyphId,
advance: Au,
offset: Point2D<Au>,
- is_missing: bool,
cluster_start: bool,
ligature_start: bool,
}
@@ -332,7 +318,6 @@ impl GlyphData {
pub fn new(id: GlyphId,
advance: Au,
offset: Option<Point2D<Au>>,
- is_missing: bool,
cluster_start: bool,
ligature_start: bool)
-> GlyphData {
@@ -340,7 +325,6 @@ impl GlyphData {
id: id,
advance: advance,
offset: offset.unwrap_or(Point2D::zero()),
- is_missing: is_missing,
cluster_start: cluster_start,
ligature_start: ligature_start,
}
@@ -465,31 +449,27 @@ impl<'a> GlyphStore {
/// otherwise, this glyph represents multiple characters.
pub fn add_glyph_for_char_index(&mut self,
i: CharIndex,
- character: Option<char>,
+ character: char,
data: &GlyphData) {
- fn glyph_is_compressible(data: &GlyphData) -> bool {
- is_simple_glyph_id(data.id)
- && is_simple_advance(data.advance)
+ let glyph_is_compressible = is_simple_glyph_id(data.id) &&
+ is_simple_advance(data.advance)
&& data.offset == Point2D::zero()
- && data.cluster_start // others are stored in detail buffer
- }
+ && data.cluster_start; // others are stored in detail buffer
debug_assert!(data.ligature_start); // can't compress ligature continuation glyphs.
debug_assert!(i < self.char_len());
- let mut entry = match (data.is_missing, glyph_is_compressible(data)) {
- (true, _) => GlyphEntry::missing(1),
- (false, true) => GlyphEntry::simple(data.id, data.advance),
- (false, false) => {
- let glyph = &[DetailedGlyph::new(data.id, data.advance, data.offset)];
- self.has_detailed_glyphs = true;
- self.detail_store.add_detailed_glyphs_for_entry(i, glyph);
- GlyphEntry::complex(data.cluster_start, data.ligature_start, 1)
- }
+ let mut entry = if glyph_is_compressible {
+ GlyphEntry::simple(data.id, data.advance)
+ } else {
+ let glyph = &[DetailedGlyph::new(data.id, data.advance, data.offset)];
+ self.has_detailed_glyphs = true;
+ self.detail_store.add_detailed_glyphs_for_entry(i, glyph);
+ GlyphEntry::complex(data.cluster_start, data.ligature_start, 1)
};
- if character == Some(' ') {
- entry = entry.set_char_is_space()
+ if character == ' ' {
+ entry.set_char_is_space()
}
self.entry_buffer[i.to_usize()] = entry;
@@ -502,22 +482,18 @@ impl<'a> GlyphStore {
let glyph_count = data_for_glyphs.len();
let first_glyph_data = data_for_glyphs[0];
- let entry = match first_glyph_data.is_missing {
- true => GlyphEntry::missing(glyph_count),
- false => {
- let glyphs_vec: Vec<DetailedGlyph> = (0..glyph_count).map(|i| {
- DetailedGlyph::new(data_for_glyphs[i].id,
- data_for_glyphs[i].advance,
- data_for_glyphs[i].offset)
- }).collect();
-
- self.has_detailed_glyphs = true;
- self.detail_store.add_detailed_glyphs_for_entry(i, &glyphs_vec);
- GlyphEntry::complex(first_glyph_data.cluster_start,
- first_glyph_data.ligature_start,
- glyph_count)
- }
- }.adapt_character_flags_of_entry(self.entry_buffer[i.to_usize()]);
+ let glyphs_vec: Vec<DetailedGlyph> = (0..glyph_count).map(|i| {
+ DetailedGlyph::new(data_for_glyphs[i].id,
+ data_for_glyphs[i].advance,
+ data_for_glyphs[i].offset)
+ }).collect();
+
+ self.has_detailed_glyphs = true;
+ self.detail_store.add_detailed_glyphs_for_entry(i, &glyphs_vec);
+
+ let entry = GlyphEntry::complex(first_glyph_data.cluster_start,
+ first_glyph_data.ligature_start,
+ glyph_count);
debug!("Adding multiple glyphs[idx={:?}, count={}]: {:?}", i, glyph_count, entry);
@@ -566,7 +542,7 @@ impl<'a> GlyphStore {
#[inline]
pub fn advance_for_char_range_slow_path(&self, rang: &Range<CharIndex>) -> Au {
self.iter_glyphs_for_char_range(rang)
- .fold(Au(0), |advance, (_, glyph)| advance + glyph.advance())
+ .fold(Au(0), |advance, glyph| advance + glyph.advance())
}
#[inline]
@@ -688,11 +664,10 @@ pub struct GlyphIterator<'a> {
impl<'a> GlyphIterator<'a> {
// Slow path when there is a glyph range.
#[inline(never)]
- fn next_glyph_range(&mut self) -> Option<(CharIndex, GlyphInfo<'a>)> {
+ fn next_glyph_range(&mut self) -> Option<GlyphInfo<'a>> {
match self.glyph_range.as_mut().unwrap().next() {
Some(j) => {
- Some((self.char_index,
- GlyphInfo::Detail(self.store, self.char_index, j.get() as u16 /* ??? */)))
+ Some(GlyphInfo::Detail(self.store, self.char_index, j.get() as u16 /* ??? */))
}
None => {
// No more glyphs for current character. Try to get another.
@@ -704,8 +679,7 @@ impl<'a> GlyphIterator<'a> {
// Slow path when there is a complex glyph.
#[inline(never)]
- fn next_complex_glyph(&mut self, entry: &GlyphEntry, i: CharIndex)
- -> Option<(CharIndex, GlyphInfo<'a>)> {
+ fn next_complex_glyph(&mut self, entry: &GlyphEntry, i: CharIndex) -> Option<GlyphInfo<'a>> {
let glyphs = self.store.detail_store.detailed_glyphs_for_entry(i, entry.glyph_count());
self.glyph_range = Some(range::each_index(CharIndex(0), CharIndex(glyphs.len() as isize)));
self.next()
@@ -713,7 +687,7 @@ impl<'a> GlyphIterator<'a> {
}
impl<'a> Iterator for GlyphIterator<'a> {
- type Item = (CharIndex, GlyphInfo<'a>);
+ type Item = GlyphInfo<'a>;
// I tried to start with something simpler and apply FlatMap, but the
// inability to store free variables in the FlatMap struct was problematic.
@@ -722,7 +696,7 @@ impl<'a> Iterator for GlyphIterator<'a> {
// slow paths, which should not be inlined, are `next_glyph_range()` and
// `next_complex_glyph()`.
#[inline(always)]
- fn next(&mut self) -> Option<(CharIndex, GlyphInfo<'a>)> {
+ fn next(&mut self) -> Option<GlyphInfo<'a>> {
// Would use 'match' here but it borrows contents in a way that interferes with mutation.
if self.glyph_range.is_some() {
return self.next_glyph_range()
@@ -741,7 +715,7 @@ impl<'a> Iterator for GlyphIterator<'a> {
debug_assert!(i < self.store.char_len());
let entry = self.store.entry_buffer[i.to_usize()];
if entry.is_simple() {
- Some((i, GlyphInfo::Simple(self.store, i)))
+ Some(GlyphInfo::Simple(self.store, i))
} else {
// Fall back to the slow path.
self.next_complex_glyph(&entry, i)
diff --git a/components/gfx/text/shaping/harfbuzz.rs b/components/gfx/text/shaping/harfbuzz.rs
index d4b05221be0..800ba9f2557 100644
--- a/components/gfx/text/shaping/harfbuzz.rs
+++ b/components/gfx/text/shaping/harfbuzz.rs
@@ -453,20 +453,18 @@ impl Shaper {
let data = GlyphData::new(space_glyph_id,
advance,
Default::default(),
- false,
true,
true);
- glyphs.add_glyph_for_char_index(char_idx, Some(character), &data);
+ glyphs.add_glyph_for_char_index(char_idx, character, &data);
} else {
let shape = glyph_data.entry_for_glyph(glyph_span.begin(), &mut y_pos);
let advance = self.advance_for_shaped_glyph(shape.advance, character, options);
let data = GlyphData::new(shape.codepoint,
advance,
shape.offset,
- false,
true,
true);
- glyphs.add_glyph_for_char_index(char_idx, Some(character), &data);
+ glyphs.add_glyph_for_char_index(char_idx, character, &data);
}
} else {
// collect all glyphs to be assigned to the first character.
@@ -477,7 +475,6 @@ impl Shaper {
datas.push(GlyphData::new(shape.codepoint,
shape.advance,
shape.offset,
- false, // not missing
true, // treat as cluster start
glyph_i > glyph_span.begin()));
// all but first are ligature continuations
diff --git a/components/layout/block.rs b/components/layout/block.rs
index 8203acaf850..a0768b9d9aa 100644
--- a/components/layout/block.rs
+++ b/components/layout/block.rs
@@ -51,7 +51,7 @@ use layout_debug;
use layout_task::DISPLAY_PORT_SIZE_FACTOR;
use model::{CollapsibleMargins, MaybeAuto, specified, specified_or_none};
use model::{IntrinsicISizes, MarginCollapseInfo};
-use msg::compositor_msg::{LayerId, LayerType};
+use msg::compositor_msg::LayerId;
use rustc_serialize::{Encodable, Encoder};
use std::cmp::{max, min};
use std::fmt;
@@ -64,7 +64,6 @@ use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
use util::geometry::MAX_RECT;
use util::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize, WritingMode};
use util::opts;
-use wrapper::PseudoElementType;
/// Information specific to floated blocks.
#[derive(Clone, RustcEncodable)]
@@ -2077,16 +2076,11 @@ impl Flow for BlockFlow {
}
fn layer_id(&self) -> LayerId {
- let layer_type = match self.fragment.pseudo {
- PseudoElementType::Normal => LayerType::FragmentBody,
- PseudoElementType::Before(_) => LayerType::BeforePseudoContent,
- PseudoElementType::After(_) => LayerType::AfterPseudoContent
- };
- LayerId::new_of_type(layer_type, self.fragment.node.id() as usize)
+ self.fragment.layer_id()
}
fn layer_id_for_overflow_scroll(&self) -> LayerId {
- LayerId::new_of_type(LayerType::OverflowScroll, self.fragment.node.id() as usize)
+ self.fragment.layer_id_for_overflow_scroll()
}
fn is_absolute_containing_block(&self) -> bool {
diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs
index 94b911cae00..49c140cbedb 100644
--- a/components/layout/display_list_builder.rs
+++ b/components/layout/display_list_builder.rs
@@ -35,7 +35,7 @@ use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, LAST_FRAGMENT_OF_ELEMENT};
use ipc_channel::ipc::{self, IpcSharedMemory};
use list_item::ListItemFlow;
use model::{self, MaybeAuto, ToGfxMatrix};
-use msg::compositor_msg::{LayerId, ScrollPolicy, SubpageLayerInfo};
+use msg::compositor_msg::{ScrollPolicy, SubpageLayerInfo};
use net_traits::image::base::{Image, PixelFormat};
use net_traits::image_cache_task::UsePlaceholder;
use std::default::Default;
@@ -65,12 +65,6 @@ use util::range::Range;
/// The logical width of an insertion point: at the moment, a one-pixel-wide line.
const INSERTION_POINT_LOGICAL_WIDTH: Au = Au(1 * AU_PER_PX);
-/// Whether a stacking context needs a layer or not.
-pub enum StackingContextLayerNecessity {
- Always(LayerId, ScrollPolicy),
- IfCanvasOrIframe(LayerId),
-}
-
/// The results of display list building for a single flow.
pub enum DisplayListBuildingResult {
None,
@@ -258,7 +252,7 @@ pub trait FragmentDisplayListBuilding {
base_flow: &BaseFlow,
display_list: Box<DisplayList>,
layout_context: &LayoutContext,
- needs_layer: StackingContextLayerNecessity,
+ scroll_policy: ScrollPolicy,
mode: StackingContextCreationMode)
-> Arc<StackingContext>;
}
@@ -1172,7 +1166,7 @@ impl FragmentDisplayListBuilding for Fragment {
base_flow: &BaseFlow,
display_list: Box<DisplayList>,
layout_context: &LayoutContext,
- needs_layer: StackingContextLayerNecessity,
+ scroll_policy: ScrollPolicy,
mode: StackingContextCreationMode)
-> Arc<StackingContext> {
let border_box = match mode {
@@ -1285,24 +1279,23 @@ impl FragmentDisplayListBuilding for Fragment {
filters.push(Filter::Opacity(effects.opacity))
}
- // Ensure every canvas or iframe has a layer.
- let (scroll_policy, layer_id) = match needs_layer {
- StackingContextLayerNecessity::Always(layer_id, scroll_policy) => {
- (scroll_policy, Some(layer_id))
- }
- StackingContextLayerNecessity::IfCanvasOrIframe(layer_id) => {
- // FIXME(pcwalton): So so bogus :(
- match self.specific {
- SpecificFragmentInfo::Canvas(_) | SpecificFragmentInfo::Iframe(_) => {
- (ScrollPolicy::Scrollable, Some(layer_id))
- }
- _ => (ScrollPolicy::Scrollable, None),
- }
- }
+ let canvas_or_iframe = match self.specific {
+ SpecificFragmentInfo::Canvas(_) | SpecificFragmentInfo::Iframe(_) => true,
+ _ => false
+ };
+
+ // There are three situations that need layers: when the fragment has the HAS_LAYER
+ // flag, when this is a canvas or iframe fragment, and when we are building a layer
+ // tree for overflow scrolling.
+ let layer_id = if mode == StackingContextCreationMode::InnerScrollWrapper {
+ Some(self.layer_id_for_overflow_scroll())
+ } else if self.flags.contains(HAS_LAYER) || canvas_or_iframe {
+ Some(self.layer_id())
+ } else {
+ None
};
- // If it's a canvas we must propagate the layer and the renderer to the paint
- // task
+ // If it's a canvas we must propagate the layer and the renderer to the paint task.
if let SpecificFragmentInfo::Canvas(ref fragment_info) = self.specific {
let layer_id = layer_id.unwrap();
if let Some(ref ipc_renderer) = fragment_info.ipc_renderer {
@@ -1586,27 +1579,19 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
border_painting_mode,
background_border_level);
- self.base.display_list_building_result = if self.fragment.flags.contains(HAS_LAYER) {
+ self.base.display_list_building_result = if self.fragment.establishes_stacking_context() {
let scroll_policy = if self.is_fixed() {
ScrollPolicy::FixedPosition
} else {
ScrollPolicy::Scrollable
};
- let stacking_context = self.fragment.create_stacking_context(
- &self.base,
- display_list,
- layout_context,
- StackingContextLayerNecessity::Always(self.layer_id(), scroll_policy),
- StackingContextCreationMode::Normal);
- DisplayListBuildingResult::StackingContext(stacking_context)
- } else if self.fragment.establishes_stacking_context() {
DisplayListBuildingResult::StackingContext(
self.fragment.create_stacking_context(
&self.base,
display_list,
layout_context,
- StackingContextLayerNecessity::IfCanvasOrIframe(self.layer_id()),
+ scroll_policy,
StackingContextCreationMode::Normal))
} else {
match self.fragment.style.get_box().position {
@@ -1671,22 +1656,11 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
}
};
- if !self.fragment.flags.contains(HAS_LAYER) {
- if !self.fragment.establishes_stacking_context() {
- display_list.form_pseudo_stacking_context_for_positioned_content();
- self.base.display_list_building_result =
- DisplayListBuildingResult::Normal(display_list);
- } else {
- self.base.display_list_building_result =
- DisplayListBuildingResult::StackingContext(
- self.fragment.create_stacking_context(
- &self.base,
- display_list,
- layout_context,
- StackingContextLayerNecessity::IfCanvasOrIframe(self.layer_id()),
- StackingContextCreationMode::Normal));
- }
- return
+ if !self.fragment.flags.contains(HAS_LAYER) && !self.fragment.establishes_stacking_context() {
+ display_list.form_pseudo_stacking_context_for_positioned_content();
+ self.base.display_list_building_result =
+ DisplayListBuildingResult::Normal(display_list);
+ return;
}
// If we got here, then we need a new layer.
@@ -1696,40 +1670,33 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
ScrollPolicy::Scrollable
};
- let stacking_context_creation_mode = if outer_display_list_for_overflow_scroll.is_some() {
- StackingContextCreationMode::InnerScrollWrapper
- } else {
- StackingContextCreationMode::Normal
- };
-
- let layer_id = if outer_display_list_for_overflow_scroll.is_some() {
- self.layer_id_for_overflow_scroll()
- } else {
- self.layer_id()
- };
- let stacking_context = self.fragment.create_stacking_context(
- &self.base,
- display_list,
- layout_context,
- StackingContextLayerNecessity::Always(layer_id, scroll_policy),
- stacking_context_creation_mode);
-
- let outermost_stacking_context = match outer_display_list_for_overflow_scroll {
- Some(mut outer_display_list_for_overflow_scroll) => {
- outer_display_list_for_overflow_scroll.children.push_back(stacking_context);
-
+ let stacking_context = match outer_display_list_for_overflow_scroll {
+ Some(mut outer_display_list) => {
+ outer_display_list.children.push_back(self.fragment.create_stacking_context(
+ &self.base,
+ display_list,
+ layout_context,
+ scroll_policy,
+ StackingContextCreationMode::InnerScrollWrapper));
self.fragment.create_stacking_context(
&self.base,
- outer_display_list_for_overflow_scroll,
+ outer_display_list,
layout_context,
- StackingContextLayerNecessity::Always(self.layer_id(), scroll_policy),
+ scroll_policy,
StackingContextCreationMode::OuterScrollWrapper)
}
- None => stacking_context,
+ None => {
+ self.fragment.create_stacking_context(
+ &self.base,
+ display_list,
+ layout_context,
+ scroll_policy,
+ StackingContextCreationMode::Normal)
+ }
};
self.base.display_list_building_result =
- DisplayListBuildingResult::StackingContext(outermost_stacking_context)
+ DisplayListBuildingResult::StackingContext(stacking_context)
}
fn build_display_list_for_floating_block(&mut self,
@@ -1744,12 +1711,11 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
self.base.display_list_building_result = if self.fragment.establishes_stacking_context() {
DisplayListBuildingResult::StackingContext(
- self.fragment.create_stacking_context(
- &self.base,
- display_list,
- layout_context,
- StackingContextLayerNecessity::IfCanvasOrIframe(self.layer_id()),
- StackingContextCreationMode::Normal))
+ self.fragment.create_stacking_context(&self.base,
+ display_list,
+ layout_context,
+ ScrollPolicy::Scrollable,
+ StackingContextCreationMode::Normal))
} else {
DisplayListBuildingResult::Normal(display_list)
}
@@ -1852,8 +1818,7 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
&self.base,
display_list,
layout_context,
- StackingContextLayerNecessity::Always(self.layer_id(),
- ScrollPolicy::Scrollable),
+ ScrollPolicy::Scrollable,
StackingContextCreationMode::Normal))
} else {
DisplayListBuildingResult::Normal(display_list)
diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs
index 13cf107227e..63fec117a8c 100644
--- a/components/layout/fragment.rs
+++ b/components/layout/fragment.rs
@@ -23,6 +23,7 @@ use inline::{InlineMetrics, LAST_FRAGMENT_OF_ELEMENT};
use ipc_channel::ipc::IpcSender;
use layout_debug;
use model::{self, IntrinsicISizes, IntrinsicISizesContribution, MaybeAuto, specified};
+use msg::compositor_msg::{LayerId, LayerType};
use msg::constellation_msg::{PipelineId, SubpageId};
use net_traits::image::base::Image;
use net_traits::image_cache_task::UsePlaceholder;
@@ -2424,6 +2425,19 @@ impl Fragment {
}
}
}
+
+ pub fn layer_id(&self) -> LayerId {
+ let layer_type = match self.pseudo {
+ PseudoElementType::Normal => LayerType::FragmentBody,
+ PseudoElementType::Before(_) => LayerType::BeforePseudoContent,
+ PseudoElementType::After(_) => LayerType::AfterPseudoContent
+ };
+ LayerId::new_of_type(layer_type, self.node.id() as usize)
+ }
+
+ pub fn layer_id_for_overflow_scroll(&self) -> LayerId {
+ LayerId::new_of_type(LayerType::OverflowScroll, self.node.id() as usize)
+ }
}
impl fmt::Debug for Fragment {
diff --git a/components/script/dom/htmlbuttonelement.rs b/components/script/dom/htmlbuttonelement.rs
index 7023a8ffdfe..8406fa2f895 100644
--- a/components/script/dom/htmlbuttonelement.rs
+++ b/components/script/dom/htmlbuttonelement.rs
@@ -191,11 +191,7 @@ impl VirtualMethods for HTMLButtonElement {
}
}
-impl<'a> FormControl<'a> for &'a HTMLButtonElement {
- fn to_element(self) -> &'a Element {
- ElementCast::from_ref(self)
- }
-}
+impl FormControl for HTMLButtonElement {}
impl<'a> Activatable for &'a HTMLButtonElement {
fn as_element<'b>(&'b self) -> &'b Element {
diff --git a/components/script/dom/htmlfieldsetelement.rs b/components/script/dom/htmlfieldsetelement.rs
index a38c6e9a7b2..c4c2f5a86f9 100644
--- a/components/script/dom/htmlfieldsetelement.rs
+++ b/components/script/dom/htmlfieldsetelement.rs
@@ -5,7 +5,7 @@
use dom::attr::Attr;
use dom::bindings::codegen::Bindings::HTMLFieldSetElementBinding;
use dom::bindings::codegen::Bindings::HTMLFieldSetElementBinding::HTMLFieldSetElementMethods;
-use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, HTMLLegendElementDerived};
+use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLLegendElementDerived};
use dom::bindings::codegen::InheritTypes::{HTMLFieldSetElementDerived, NodeCast};
use dom::bindings::js::{Root, RootedReference};
use dom::document::Document;
@@ -157,8 +157,4 @@ impl VirtualMethods for HTMLFieldSetElement {
}
}
-impl<'a> FormControl<'a> for &'a HTMLFieldSetElement {
- fn to_element(self) -> &'a Element {
- ElementCast::from_ref(self)
- }
-}
+impl FormControl for HTMLFieldSetElement {}
diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs
index b16b2ec5609..632b084c293 100644
--- a/components/script/dom/htmlformelement.rs
+++ b/components/script/dom/htmlformelement.rs
@@ -15,9 +15,11 @@ use dom::bindings::codegen::InheritTypes::HTMLElementCast;
use dom::bindings::codegen::InheritTypes::HTMLFormElementCast;
use dom::bindings::codegen::InheritTypes::HTMLFormElementDerived;
use dom::bindings::codegen::InheritTypes::HTMLInputElementCast;
+use dom::bindings::codegen::InheritTypes::{ElementBase, ElementCast};
use dom::bindings::codegen::InheritTypes::{HTMLTextAreaElementCast, NodeCast};
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{Root};
+use dom::bindings::utils::Reflectable;
use dom::document::Document;
use dom::element::{Element, ElementTypeId};
use dom::event::{Event, EventBubbles, EventCancelable};
@@ -515,10 +517,10 @@ impl<'a> FormSubmitter<'a> {
}
}
-pub trait FormControl<'a> : Copy + Sized {
+pub trait FormControl: ElementBase + Reflectable {
// FIXME: This is wrong (https://github.com/servo/servo/issues/3553)
// but we need html5ever to do it correctly
- fn form_owner(self) -> Option<Root<HTMLFormElement>> {
+ fn form_owner(&self) -> Option<Root<HTMLFormElement>> {
// https://html.spec.whatwg.org/multipage/#reset-the-form-owner
let elem = self.to_element();
let owner = elem.get_string_attribute(&atom!("form"));
@@ -544,12 +546,12 @@ pub trait FormControl<'a> : Copy + Sized {
None
}
- fn get_form_attribute<InputFn, OwnerFn>(self,
+ fn get_form_attribute<InputFn, OwnerFn>(&self,
attr: &Atom,
input: InputFn,
owner: OwnerFn)
-> DOMString
- where InputFn: Fn(Self) -> DOMString,
+ where InputFn: Fn(&Self) -> DOMString,
OwnerFn: Fn(&HTMLFormElement) -> DOMString
{
if self.to_element().has_attribute(attr) {
@@ -559,7 +561,9 @@ pub trait FormControl<'a> : Copy + Sized {
}
}
- fn to_element(self) -> &'a Element;
+ fn to_element(&self) -> &Element {
+ ElementCast::from_ref(self)
+ }
}
impl VirtualMethods for HTMLFormElement {
diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs
index a07529ebbec..1ae235ea316 100644
--- a/components/script/dom/htmlinputelement.rs
+++ b/components/script/dom/htmlinputelement.rs
@@ -633,11 +633,7 @@ impl VirtualMethods for HTMLInputElement {
}
}
-impl<'a> FormControl<'a> for &'a HTMLInputElement {
- fn to_element(self) -> &'a Element {
- ElementCast::from_ref(self)
- }
-}
+impl FormControl for HTMLInputElement {}
impl Activatable for HTMLInputElement {
fn as_element<'b>(&'b self) -> &'b Element {
diff --git a/components/script/dom/htmllabelelement.rs b/components/script/dom/htmllabelelement.rs
index ec3f1fa7865..624d0e3f722 100644
--- a/components/script/dom/htmllabelelement.rs
+++ b/components/script/dom/htmllabelelement.rs
@@ -4,11 +4,10 @@
use dom::bindings::codegen::Bindings::HTMLLabelElementBinding;
use dom::bindings::codegen::Bindings::HTMLLabelElementBinding::HTMLLabelElementMethods;
-use dom::bindings::codegen::InheritTypes::ElementCast;
use dom::bindings::codegen::InheritTypes::HTMLLabelElementDerived;
use dom::bindings::js::Root;
use dom::document::Document;
-use dom::element::{Element, ElementTypeId};
+use dom::element::ElementTypeId;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
use dom::htmlformelement::{FormControl, HTMLFormElement};
@@ -54,8 +53,4 @@ impl HTMLLabelElementMethods for HTMLLabelElement {
}
}
-impl<'a> FormControl<'a> for &'a HTMLLabelElement {
- fn to_element(self) -> &'a Element {
- ElementCast::from_ref(self)
- }
-}
+impl FormControl for HTMLLabelElement {}
diff --git a/components/script/dom/htmlobjectelement.rs b/components/script/dom/htmlobjectelement.rs
index e197f1d60c4..fb6c7a39860 100644
--- a/components/script/dom/htmlobjectelement.rs
+++ b/components/script/dom/htmlobjectelement.rs
@@ -10,7 +10,7 @@ use dom::bindings::codegen::InheritTypes::HTMLObjectElementDerived;
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast};
use dom::bindings::js::Root;
use dom::document::Document;
-use dom::element::{AttributeMutation, Element, ElementTypeId};
+use dom::element::{AttributeMutation, ElementTypeId};
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
use dom::htmlformelement::{FormControl, HTMLFormElement};
@@ -119,8 +119,4 @@ impl VirtualMethods for HTMLObjectElement {
}
}
-impl<'a> FormControl<'a> for &'a HTMLObjectElement {
- fn to_element(self) -> &'a Element {
- ElementCast::from_ref(self)
- }
-}
+impl FormControl for HTMLObjectElement {}
diff --git a/components/script/dom/htmloutputelement.rs b/components/script/dom/htmloutputelement.rs
index 781ba2f9e83..c0e98571358 100644
--- a/components/script/dom/htmloutputelement.rs
+++ b/components/script/dom/htmloutputelement.rs
@@ -4,11 +4,10 @@
use dom::bindings::codegen::Bindings::HTMLOutputElementBinding;
use dom::bindings::codegen::Bindings::HTMLOutputElementBinding::HTMLOutputElementMethods;
-use dom::bindings::codegen::InheritTypes::ElementCast;
use dom::bindings::codegen::InheritTypes::HTMLOutputElementDerived;
use dom::bindings::js::Root;
use dom::document::Document;
-use dom::element::{Element, ElementTypeId};
+use dom::element::ElementTypeId;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
use dom::htmlformelement::{FormControl, HTMLFormElement};
@@ -61,8 +60,4 @@ impl HTMLOutputElementMethods for HTMLOutputElement {
}
}
-impl<'a> FormControl<'a> for &'a HTMLOutputElement {
- fn to_element(self) -> &'a Element {
- ElementCast::from_ref(self)
- }
-}
+impl FormControl for HTMLOutputElement {}
diff --git a/components/script/dom/htmlselectelement.rs b/components/script/dom/htmlselectelement.rs
index 48aea7422ee..8c6b73c564b 100644
--- a/components/script/dom/htmlselectelement.rs
+++ b/components/script/dom/htmlselectelement.rs
@@ -5,13 +5,13 @@
use dom::attr::{Attr, AttrValue};
use dom::bindings::codegen::Bindings::HTMLSelectElementBinding;
use dom::bindings::codegen::Bindings::HTMLSelectElementBinding::HTMLSelectElementMethods;
-use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast};
+use dom::bindings::codegen::InheritTypes::{HTMLElementCast, NodeCast};
use dom::bindings::codegen::InheritTypes::{HTMLFieldSetElementDerived, HTMLSelectElementDerived};
use dom::bindings::codegen::UnionTypes::HTMLElementOrLong;
use dom::bindings::codegen::UnionTypes::HTMLOptionElementOrHTMLOptGroupElement;
use dom::bindings::js::Root;
use dom::document::Document;
-use dom::element::{AttributeMutation, Element, ElementTypeId};
+use dom::element::{AttributeMutation, ElementTypeId};
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
use dom::htmlformelement::{FormControl, HTMLFormElement};
@@ -161,8 +161,4 @@ impl VirtualMethods for HTMLSelectElement {
}
}
-impl<'a> FormControl<'a> for &'a HTMLSelectElement {
- fn to_element(self) -> &'a Element {
- ElementCast::from_ref(self)
- }
-}
+impl FormControl for HTMLSelectElement {}
diff --git a/components/script/dom/htmltextareaelement.rs b/components/script/dom/htmltextareaelement.rs
index 9c20b4ad2b2..c2231b070b7 100644
--- a/components/script/dom/htmltextareaelement.rs
+++ b/components/script/dom/htmltextareaelement.rs
@@ -15,7 +15,7 @@ use dom::bindings::global::GlobalRef;
use dom::bindings::js::{LayoutJS, Root};
use dom::bindings::refcounted::Trusted;
use dom::document::Document;
-use dom::element::{AttributeMutation, Element, ElementTypeId};
+use dom::element::{AttributeMutation, ElementTypeId};
use dom::event::{Event, EventBubbles, EventCancelable};
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
@@ -363,11 +363,7 @@ impl VirtualMethods for HTMLTextAreaElement {
}
}
-impl<'a> FormControl<'a> for &'a HTMLTextAreaElement {
- fn to_element(self) -> &'a Element {
- ElementCast::from_ref(self)
- }
-}
+impl FormControl for HTMLTextAreaElement {}
pub struct ChangeEventRunnable {
element: Trusted<HTMLTextAreaElement>,
diff --git a/components/util/str.rs b/components/util/str.rs
index 78a444be094..e2759e936d6 100644
--- a/components/util/str.rs
+++ b/components/util/str.rs
@@ -329,8 +329,8 @@ pub unsafe fn c_str_to_string(s: *const c_char) -> String {
pub fn str_join<I, T>(strs: I, join: &str) -> String
where I: IntoIterator<Item=T>, T: AsRef<str>,
{
- strs.into_iter().fold(String::new(), |mut acc, s| {
- if !acc.is_empty() { acc.push_str(join); }
+ strs.into_iter().enumerate().fold(String::new(), |mut acc, (i, s)| {
+ if i > 0 { acc.push_str(join); }
acc.push_str(s.as_ref());
acc
})
diff --git a/python/servo/testing_commands.py b/python/servo/testing_commands.py
index a1f0899b7c3..e4c36236bd0 100644
--- a/python/servo/testing_commands.py
+++ b/python/servo/testing_commands.py
@@ -10,6 +10,7 @@
from __future__ import print_function, unicode_literals
import argparse
+import re
import sys
import os
import os.path as path
@@ -90,7 +91,9 @@ class MachCommands(CommandBase):
("css", {"kwargs": {"release": release},
"paths": [path.abspath(path.join("tests", "wpt", "css-tests"))],
"include_arg": "include"}),
- ("unit", {}),
+ ("unit", {"kwargs": {},
+ "paths": [path.abspath(path.join("tests", "unit"))],
+ "include_arg": "test_name"})
])
suites_by_prefix = {path: k for k, v in suites.iteritems() if "paths" in v for path in v["paths"]}
@@ -138,7 +141,7 @@ class MachCommands(CommandBase):
category='testing')
@CommandArgument('--package', '-p', default=None, help="Specific package to test")
@CommandArgument('test_name', nargs=argparse.REMAINDER,
- help="Only run tests that match this pattern")
+ help="Only run tests that match this pattern or file path")
def test_unit(self, test_name=None, package=None):
if test_name is None:
test_name = []
@@ -146,13 +149,35 @@ class MachCommands(CommandBase):
self.ensure_bootstrapped()
if package:
- packages = [package]
+ packages = {package}
else:
- packages = os.listdir(path.join(self.context.topdir, "tests", "unit"))
+ packages = set()
+
+ test_patterns = []
+ for test in test_name:
+ # add package if 'tests/unit/<package>'
+ match = re.search("tests/unit/(\\w+)/?$", test)
+ if match:
+ packages.add(match.group(1))
+ # add package & test if '<package>/<test>', 'tests/unit/<package>/<test>.rs', or similar
+ elif re.search("\\w/\\w", test):
+ tokens = test.split("/")
+ packages.add(tokens[-2])
+ test_prefix = tokens[-1]
+ if test_prefix.endswith(".rs"):
+ test_prefix = test_prefix[:-3]
+ test_prefix += "::"
+ test_patterns.append(test_prefix)
+ # add test as-is otherwise
+ else:
+ test_patterns.append(test)
+
+ if not packages:
+ packages = set(os.listdir(path.join(self.context.topdir, "tests", "unit")))
for crate in packages:
result = subprocess.call(
- ["cargo", "test", "-p", "%s_tests" % crate] + test_name,
+ ["cargo", "test", "-p", "%s_tests" % crate] + test_patterns,
env=self.build_env(), cwd=self.servo_crate())
if result != 0:
return result
diff --git a/tests/unit/util/str.rs b/tests/unit/util/str.rs
index 63f8fbd8881..c03d8c8086c 100644
--- a/tests/unit/util/str.rs
+++ b/tests/unit/util/str.rs
@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-use util::str::split_html_space_chars;
+use util::str::{split_html_space_chars, str_join};
#[test]
@@ -10,3 +10,27 @@ pub fn split_html_space_chars_whitespace() {
assert!(split_html_space_chars("").collect::<Vec<_>>().is_empty());
assert!(split_html_space_chars("\u{0020}\u{0009}\u{000a}\u{000c}\u{000d}").collect::<Vec<_>>().is_empty());
}
+
+#[test]
+pub fn test_str_join_empty() {
+ let slice = [] as [&str; 0];
+ let actual = str_join(&slice, "-");
+ let expected = "";
+ assert_eq!(actual, expected);
+}
+
+#[test]
+pub fn test_str_join_one() {
+ let slice = ["alpha"];
+ let actual = str_join(&slice, "-");
+ let expected = "alpha";
+ assert_eq!(actual, expected);
+}
+
+#[test]
+pub fn test_str_join_many() {
+ let slice = ["", "alpha", "", "beta", "gamma", ""];
+ let actual = str_join(&slice, "-");
+ let expected = "-alpha--beta-gamma-";
+ assert_eq!(actual, expected);
+}