Resvoled merge conflict

This commit is contained in:
Peter 2015-04-09 16:07:10 -04:00
commit 1511d7a2ad
143 changed files with 1834 additions and 2075 deletions

View file

@ -1,7 +1,7 @@
# The Servo Parallel Browser Project
Servo is a prototype web browser engine written in the
[Rust](https://github.com/mozilla/rust) language. It is currently developed on
[Rust](https://github.com/rust-lang/rust) language. It is currently developed on
64bit OS X, 64bit Linux, Android, and Gonk (Firefox OS).
Servo welcomes contribution from everyone. See

View file

@ -39,6 +39,7 @@ pub enum CanvasMsg {
SetFillStyle(FillOrStrokeStyle),
SetStrokeStyle(FillOrStrokeStyle),
SetLineWidth(f32),
SetMiterLimit(f32),
SetTransform(Matrix2D<f32>),
SetGlobalAlpha(f32),
Recreate(Size2D<i32>),
@ -202,7 +203,7 @@ impl<'a> CanvasPaintTask<'a> {
draw_options: DrawOptions::new(1.0, 0),
fill_style: Pattern::Color(ColorPattern::new(color::black())),
stroke_style: Pattern::Color(ColorPattern::new(color::black())),
stroke_opts: StrokeOptions::new(1.0, JoinStyle::MiterOrBevel, CapStyle::Butt, 1.0, &[]),
stroke_opts: StrokeOptions::new(1.0, JoinStyle::MiterOrBevel, CapStyle::Butt, 10.0, &[]),
path_builder: path_builder,
transform: Matrix2D::identity(),
}
@ -245,6 +246,7 @@ impl<'a> CanvasPaintTask<'a> {
CanvasMsg::SetFillStyle(style) => painter.set_fill_style(style),
CanvasMsg::SetStrokeStyle(style) => painter.set_stroke_style(style),
CanvasMsg::SetLineWidth(width) => painter.set_line_width(width),
CanvasMsg::SetMiterLimit(limit) => painter.set_miter_limit(limit),
CanvasMsg::SetTransform(ref matrix) => painter.set_transform(matrix),
CanvasMsg::SetGlobalAlpha(alpha) => painter.set_global_alpha(alpha),
CanvasMsg::Recreate(size) => painter.recreate(size),
@ -425,6 +427,10 @@ impl<'a> CanvasPaintTask<'a> {
self.stroke_opts.line_width = width;
}
fn set_miter_limit(&mut self, limit: f32) {
self.stroke_opts.miter_limit = limit;
}
fn set_transform(&mut self, transform: &Matrix2D<f32>) {
self.transform = *transform;
self.drawtarget.set_transform(transform)

View file

@ -76,8 +76,7 @@ impl FontHandleMethods for FontHandle {
let ft_ctx: FT_Library = fctx.ctx.ctx;
if ft_ctx.is_null() { return Err(()); }
let bytes = &template.bytes;
let face_result = create_face_from_buffer(ft_ctx, bytes.as_ptr(), bytes.len(), pt_size);
let face_result = create_face_from_buffer(ft_ctx, &template.bytes, pt_size);
// TODO: this could be more simply written as result::chain
// and moving buf into the struct ctor, but cant' move out of
@ -94,12 +93,12 @@ impl FontHandleMethods for FontHandle {
Err(()) => Err(())
};
fn create_face_from_buffer(lib: FT_Library, cbuf: *const u8, cbuflen: uint, pt_size: Option<Au>)
fn create_face_from_buffer(lib: FT_Library, buffer: &[u8], pt_size: Option<Au>)
-> Result<FT_Face, ()> {
unsafe {
let mut face: FT_Face = ptr::null_mut();
let face_index = 0 as FT_Long;
let result = FT_New_Memory_Face(lib, cbuf, cbuflen as FT_Long,
let result = FT_New_Memory_Face(lib, buffer.as_ptr(), buffer.len() as FT_Long,
face_index, &mut face);
if !result.succeeded() || face.is_null() {

View file

@ -36,7 +36,7 @@ pub fn get_available_families<F>(mut callback: F) where F: FnMut(String) {
unsafe {
let config = FcConfigGetCurrent();
let fontSet = FcConfigGetFonts(config, FcSetSystem);
for i in 0..((*fontSet).nfont as int) {
for i in 0..((*fontSet).nfont as isize) {
let font = (*fontSet).fonts.offset(i);
let mut family: *mut FcChar8 = ptr::null_mut();
let mut v: c_int = 0;
@ -74,7 +74,7 @@ pub fn get_variations_for_family<F>(family_name: &str, mut callback: F)
debug!("found {} variations", (*matches).nfont);
for i in 0..((*matches).nfont as int) {
for i in 0..((*matches).nfont as isize) {
let font = (*matches).fonts.offset(i);
let mut file: *mut FcChar8 = ptr::null_mut();
let file = if FcPatternGetString(*font, FC_FILE.as_ptr() as *mut c_char, 0, &mut file) == FcResultMatch {

View file

@ -16,6 +16,7 @@ use text::glyph::{CharIndex, GlyphStore};
/// A single "paragraph" of text in one font size and style.
#[derive(Clone)]
pub struct TextRun {
/// The UTF-8 string represented by this text run.
pub text: Arc<String>,
pub font_template: Arc<FontTemplateData>,
pub actual_pt_size: Au,
@ -310,7 +311,8 @@ impl<'a> TextRun {
self.font_metrics.descent)
}
pub fn metrics_for_slice(&self, glyphs: &GlyphStore, slice_range: &Range<CharIndex>) -> RunMetrics {
pub fn metrics_for_slice(&self, glyphs: &GlyphStore, slice_range: &Range<CharIndex>)
-> RunMetrics {
RunMetrics::new(glyphs.advance_for_char_range(slice_range),
self.font_metrics.ascent,
self.font_metrics.descent)

View file

@ -2,8 +2,6 @@
* 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 text::glyph::CharIndex;
#[derive(PartialEq, Eq, Copy)]
pub enum CompressionMode {
CompressNone,
@ -25,12 +23,10 @@ pub enum CompressionMode {
pub fn transform_text(text: &str,
mode: CompressionMode,
incoming_whitespace: bool,
output_text: &mut String,
new_line_pos: &mut Vec<CharIndex>)
output_text: &mut String)
-> bool {
let out_whitespace = match mode {
CompressionMode::CompressNone | CompressionMode::DiscardNewline => {
let mut new_line_index = CharIndex(0);
for ch in text.chars() {
if is_discardable_char(ch, mode) {
// TODO: record skipped char
@ -38,15 +34,6 @@ pub fn transform_text(text: &str,
// TODO: record kept char
if ch == '\t' {
// TODO: set "has tab" flag
} else if ch == '\n' {
// Save new-line's position for line-break
// This value is relative(not absolute)
new_line_pos.push(new_line_index);
new_line_index = CharIndex(0);
}
if ch != '\n' {
new_line_index = new_line_index + CharIndex(1);
}
output_text.push(ch);
}
@ -124,6 +111,6 @@ pub fn fixed_to_rounded_int(before: isize, f: i32) -> isize {
if f > 0i32 {
((half + f) >> before) as isize
} else {
-((half - f) >> before) as isize
-((half - f) >> before as usize) as isize
}
}

View file

@ -1994,7 +1994,8 @@ pub struct ISizeConstraintSolution {
}
impl ISizeConstraintSolution {
pub fn new(inline_size: Au, margin_inline_start: Au, margin_inline_end: Au) -> ISizeConstraintSolution {
pub fn new(inline_size: Au, margin_inline_start: Au, margin_inline_end: Au)
-> ISizeConstraintSolution {
ISizeConstraintSolution {
inline_start: Au(0),
inline_end: Au(0),

View file

@ -27,16 +27,11 @@ use geom::{Point2D, Rect, Size2D};
use gfx::display_list::{BLUR_INFLATION_FACTOR, OpaqueNode};
use gfx::text::glyph::CharIndex;
use gfx::text::text_run::{TextRun, TextRunSlice};
use script_traits::UntrustedNodeAddress;
use rustc_serialize::{Encodable, Encoder};
use msg::constellation_msg::{ConstellationChan, Msg, PipelineId, SubpageId};
use net_traits::image::holder::ImageHolder;
use net_traits::local_image_cache::LocalImageCache;
use util::geometry::{self, Au, ZERO_POINT};
use util::logical_geometry::{LogicalRect, LogicalSize, LogicalMargin, WritingMode};
use util::range::*;
use util::smallvec::SmallVec;
use util::str::is_whitespace;
use rustc_serialize::{Encodable, Encoder};
use script_traits::UntrustedNodeAddress;
use std::borrow::ToOwned;
use std::cmp::{max, min};
use std::collections::LinkedList;
@ -56,6 +51,12 @@ use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
use style::values::computed::{LengthOrPercentageOrNone};
use text::TextRunScanner;
use url::Url;
use util::geometry::{self, Au, ZERO_POINT};
use util::logical_geometry::{LogicalRect, LogicalSize, LogicalMargin, WritingMode};
use util::range::*;
use util::smallvec::SmallVec;
use util::str::is_whitespace;
use util;
/// Fragments (`struct Fragment`) are the leaves of the layout tree. They cannot position
/// themselves. In general, fragments do not have a simple correspondence with CSS fragments in the
@ -580,36 +581,27 @@ pub struct ScannedTextFragmentInfo {
/// The text run that this represents.
pub run: Arc<Box<TextRun>>,
/// The intrinsic size of the text fragment.
pub content_size: LogicalSize<Au>,
/// The range within the above text run that this represents.
pub range: Range<CharIndex>,
/// The positions of newlines within this scanned text fragment.
///
/// FIXME(#2260, pcwalton): Can't this go somewhere else, like in the text run or something?
/// Or can we just remove it?
pub new_line_pos: Vec<CharIndex>,
/// The new_line_pos is eaten during line breaking. If we need to re-merge
/// fragments, it will have to be restored.
pub original_new_line_pos: Option<Vec<CharIndex>>,
/// The intrinsic size of the text fragment.
pub content_size: LogicalSize<Au>,
/// The endpoint of the above range, including whitespace that was stripped out. This exists
/// so that we can restore the range to its original value (before line breaking occurred) when
/// performing incremental reflow.
pub range_end_including_stripped_whitespace: CharIndex,
}
impl ScannedTextFragmentInfo {
/// Creates the information specific to a scanned text fragment from a range and a text run.
pub fn new(run: Arc<Box<TextRun>>,
range: Range<CharIndex>,
new_line_positions: Vec<CharIndex>,
content_size: LogicalSize<Au>)
pub fn new(run: Arc<Box<TextRun>>, range: Range<CharIndex>, content_size: LogicalSize<Au>)
-> ScannedTextFragmentInfo {
ScannedTextFragmentInfo {
run: run,
range: range,
new_line_pos: new_line_positions,
original_new_line_pos: None,
content_size: content_size,
range_end_including_stripped_whitespace: range.end(),
}
}
}
@ -769,32 +761,6 @@ impl Fragment {
self.margin = LogicalMargin::zero(self.style.writing_mode);
}
/// Saves the new_line_pos vector into a `SpecificFragmentInfo::ScannedText`. This will fail
/// if called on any other type of fragment.
pub fn save_new_line_pos(&mut self) {
match &mut self.specific {
&mut SpecificFragmentInfo::ScannedText(ref mut info) => {
if !info.new_line_pos.is_empty() {
info.original_new_line_pos = Some(info.new_line_pos.clone());
}
}
_ => {}
}
}
pub fn restore_new_line_pos(&mut self) {
match &mut self.specific {
&mut SpecificFragmentInfo::ScannedText(ref mut info) => {
match info.original_new_line_pos.take() {
None => {}
Some(new_line_pos) => info.new_line_pos = new_line_pos,
}
return
}
_ => {}
}
}
/// Returns a debug ID of this fragment. This ID should not be considered stable across
/// multiple layouts or fragment manipulations.
pub fn debug_id(&self) -> u16 {
@ -823,14 +789,12 @@ impl Fragment {
}
/// Transforms this fragment using the given `SplitInfo`, preserving all the other data.
pub fn transform_with_split_info(&self,
split: &SplitInfo,
text_run: Arc<Box<TextRun>>)
pub fn transform_with_split_info(&self, split: &SplitInfo, text_run: Arc<Box<TextRun>>)
-> Fragment {
let size = LogicalSize::new(self.style.writing_mode,
split.inline_size,
self.border_box.size.block);
let info = box ScannedTextFragmentInfo::new(text_run, split.range, Vec::new(), size);
let info = box ScannedTextFragmentInfo::new(text_run, split.range, size);
self.transform(size, SpecificFragmentInfo::ScannedText(info))
}
@ -857,7 +821,6 @@ impl Fragment {
style: Arc<ComputedValues>,
first_frag: bool,
last_frag: bool) {
if self.inline_context.is_none() {
self.inline_context = Some(InlineFragmentContext::new());
}
@ -1179,25 +1142,11 @@ impl Fragment {
}
}
/// Returns true if this element can be split. This is true for text fragments.
/// Returns true if this element can be split. This is true for text fragments, unless
/// `white-space: pre` is set.
pub fn can_split(&self) -> bool {
self.is_scanned_text_fragment()
}
/// Returns the newline positions of this fragment, if it's a scanned text fragment.
pub fn newline_positions(&self) -> Option<&Vec<CharIndex>> {
match self.specific {
SpecificFragmentInfo::ScannedText(ref info) => Some(&info.new_line_pos),
_ => None,
}
}
/// Returns the newline positions of this fragment, if it's a scanned text fragment.
pub fn newline_positions_mut(&mut self) -> Option<&mut Vec<CharIndex>> {
match self.specific {
SpecificFragmentInfo::ScannedText(ref mut info) => Some(&mut info.new_line_pos),
_ => None,
}
self.is_scanned_text_fragment() &&
self.style.get_inheritedtext().white_space != white_space::T::pre
}
/// Returns true if and only if this fragment is a generated content fragment.
@ -1359,64 +1308,6 @@ impl Fragment {
self.border_box - self.border_padding
}
/// Find the split of a fragment that includes a new-line character.
///
/// A return value of `None` indicates that the fragment is not splittable.
/// Otherwise the split information is returned. The right information is
/// optional due to the possibility of it being whitespace.
//
// TODO(bjz): The text run should be removed in the future, but it is currently needed for
// the current method of fragment splitting in the `inline::try_append_*` functions.
pub fn find_split_info_by_new_line(&self)
-> Option<(SplitInfo, Option<SplitInfo>, Arc<Box<TextRun>> /* TODO(bjz): remove */)> {
match self.specific {
SpecificFragmentInfo::Canvas(_) |
SpecificFragmentInfo::Generic |
SpecificFragmentInfo::GeneratedContent(_) |
SpecificFragmentInfo::Iframe(_) |
SpecificFragmentInfo::Image(_) |
SpecificFragmentInfo::Table |
SpecificFragmentInfo::TableCell |
SpecificFragmentInfo::TableRow |
SpecificFragmentInfo::TableWrapper => {
None
}
SpecificFragmentInfo::TableColumn(_) => {
panic!("Table column fragments do not need to split")
}
SpecificFragmentInfo::UnscannedText(_) => {
panic!("Unscanned text fragments should have been scanned by now!")
}
SpecificFragmentInfo::InlineBlock(_) |
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => {
panic!("Inline blocks or inline absolute hypothetical fragments do not get split")
}
SpecificFragmentInfo::ScannedText(ref text_fragment_info) => {
let mut new_line_pos = text_fragment_info.new_line_pos.clone();
let cur_new_line_pos = new_line_pos.remove(0);
let inline_start_range = Range::new(text_fragment_info.range.begin(),
cur_new_line_pos);
let inline_end_range = Range::new(
text_fragment_info.range.begin() + cur_new_line_pos + CharIndex(1),
text_fragment_info.range.length() - (cur_new_line_pos + CharIndex(1)));
// Left fragment is for inline-start text of first founded new-line character.
let inline_start_fragment = SplitInfo::new(inline_start_range,
&**text_fragment_info);
// Right fragment is for inline-end text of first founded new-line character.
let inline_end_fragment = if inline_end_range.length() > CharIndex(0) {
Some(SplitInfo::new(inline_end_range, &**text_fragment_info))
} else {
None
};
Some((inline_start_fragment, inline_end_fragment, text_fragment_info.run.clone()))
}
}
}
/// Attempts to find the split positions of a text fragment so that its inline-size is no more
/// than `max_inline_size`.
///
@ -1495,13 +1386,13 @@ impl Fragment {
/// A helper method that uses the breaking strategy described by `slice_iterator` (at present,
/// either natural word breaking or character breaking) to split this fragment.
fn calculate_split_position_using_breaking_strategy<'a,I>(&self,
fn calculate_split_position_using_breaking_strategy<'a,I>(
&self,
slice_iterator: I,
max_inline_size: Au,
flags: SplitOptions)
-> Option<SplitResult>
where I: Iterator<Item=
TextRunSlice<'a>> {
where I: Iterator<Item=TextRunSlice<'a>> {
let text_fragment_info =
if let SpecificFragmentInfo::ScannedText(ref text_fragment_info) = self.specific {
text_fragment_info
@ -1515,31 +1406,35 @@ impl Fragment {
let mut inline_end_range = None;
let mut overflowing = false;
debug!("calculate_split_position: splitting text fragment (strlen={}, range={:?}, \
max_inline_size={:?})",
debug!("calculate_split_position_using_breaking_strategy: splitting text fragment \
(strlen={}, range={:?}, max_inline_size={:?})",
text_fragment_info.run.text.len(),
text_fragment_info.range,
max_inline_size);
for slice in slice_iterator {
debug!("calculate_split_position: considering slice (offset={:?}, slice range={:?}, \
remaining_inline_size={:?})",
debug!("calculate_split_position_using_breaking_strategy: considering slice \
(offset={:?}, slice range={:?}, remaining_inline_size={:?})",
slice.offset,
slice.range,
remaining_inline_size);
// Use the `remaining_inline_size` to find a split point if possible. If not, go around
// the loop again with the next slice.
let metrics = text_fragment_info.run.metrics_for_slice(slice.glyphs, &slice.range);
let advance = metrics.advance_width;
// Have we found the split point?
if advance <= remaining_inline_size || slice.glyphs.is_whitespace() {
// Keep going; we haven't found the split point yet.
if flags.contains(STARTS_LINE) && pieces_processed_count == 0 &&
if flags.contains(STARTS_LINE) &&
pieces_processed_count == 0 &&
slice.glyphs.is_whitespace() {
debug!("calculate_split_position: skipping leading trimmable whitespace");
debug!("calculate_split_position_using_breaking_strategy: skipping \
leading trimmable whitespace");
inline_start_range.shift_by(slice.range.length());
} else {
debug!("split_to_inline_size: enlarging span");
debug!("calculate_split_position_using_breaking_strategy: enlarging span");
remaining_inline_size = remaining_inline_size - advance;
inline_start_range.extend_by(slice.range.length());
}
@ -1570,16 +1465,15 @@ impl Fragment {
inline_end);
}
break
}
// If we failed to find a suitable split point, we're on the verge of overflowing the line.
// If we failed to find a suitable split point, we're on the verge of overflowing the
// line.
if inline_start_range.is_empty() || overflowing {
// If we've been instructed to retry at character boundaries (probably via
// `overflow-wrap: break-word`), do so.
if flags.contains(RETRY_AT_CHARACTER_BOUNDARIES) {
let character_breaking_strategy =
text_fragment_info.run.character_slices_in_range(&text_fragment_info.range);
text_fragment_info.run
.character_slices_in_range(&text_fragment_info.range);
let mut flags = flags;
flags.remove(RETRY_AT_CHARACTER_BOUNDARIES);
return self.calculate_split_position_using_breaking_strategy(
@ -1588,43 +1482,15 @@ impl Fragment {
flags)
}
// We aren't at the start of the line, so don't overflow. Let inline layout wrap to the
// next line instead.
// We aren't at the start of the line, so don't overflow. Let inline layout wrap to
// the next line instead.
if !flags.contains(STARTS_LINE) {
return None
}
}
// Remove trailing whitespace from the inline-start split, if necessary.
//
// FIXME(pcwalton): Is there a more clever (i.e. faster) way to do this?
strip_trailing_whitespace(&**text_fragment_info.run, &mut inline_start_range);
// Remove leading whitespace from the inline-end split, if necessary.
//
// FIXME(pcwalton): Is there a more clever (i.e. faster) way to do this?
if let Some(ref mut inline_end_range) = inline_end_range {
let inline_end_fragment_text =
text_fragment_info.run.text.slice_chars(inline_end_range.begin().to_usize(),
inline_end_range.end().to_usize());
let mut leading_whitespace_character_count = 0;
for ch in inline_end_fragment_text.chars() {
if ch.is_whitespace() {
leading_whitespace_character_count += 1
} else {
break
}
}
inline_end_range.adjust_by(CharIndex(leading_whitespace_character_count),
-CharIndex(leading_whitespace_character_count));
}
// Normalize our split so that the inline-end fragment will never be `Some` while the
// inline-start fragment is `None`.
if inline_start_range.is_empty() && inline_end_range.is_some() {
inline_start_range = inline_end_range.unwrap();
inline_end_range = None
}
let inline_start = if !inline_start_range.is_empty() {
Some(SplitInfo::new(inline_start_range, &**text_fragment_info))
@ -1642,22 +1508,21 @@ impl Fragment {
})
}
/// Attempts to strip trailing whitespace from this fragment by adjusting the text run range.
/// Returns true if any modifications were made.
pub fn strip_trailing_whitespace_if_necessary(&mut self) -> bool {
let text_fragment_info =
if let SpecificFragmentInfo::ScannedText(ref mut text_fragment_info) = self.specific {
text_fragment_info
} else {
return false
};
let run = text_fragment_info.run.clone();
if strip_trailing_whitespace(&**run, &mut text_fragment_info.range) {
self.border_box.size.inline = run.advance_for_range(&text_fragment_info.range);
return true
/// The opposite of `calculate_split_position_using_breaking_strategy`: merges this fragment
/// with the next one.
pub fn merge_with(&mut self, next_fragment: Fragment) {
match (&mut self.specific, &next_fragment.specific) {
(&mut SpecificFragmentInfo::ScannedText(ref mut this_info),
&SpecificFragmentInfo::ScannedText(ref other_info)) => {
debug_assert!(util::arc_ptr_eq(&this_info.run, &other_info.run));
this_info.range.extend_to(other_info.range_end_including_stripped_whitespace);
this_info.content_size.inline =
this_info.run.metrics_for_range(&this_info.range).advance_width;
self.border_box.size.inline = this_info.content_size.inline +
self.border_padding.inline_start_end();
}
_ => panic!("Can only merge two scanned-text fragments!"),
}
false
}
/// Returns true if this fragment is an unscanned text fragment that consists entirely of
@ -1669,7 +1534,7 @@ impl Fragment {
}
match self.specific {
SpecificFragmentInfo::UnscannedText(ref text_fragment_info) => {
is_whitespace(text_fragment_info.text.as_slice())
util::str::is_whitespace(text_fragment_info.text.as_slice())
}
_ => false,
}
@ -1890,11 +1755,14 @@ impl Fragment {
/// Returns true if this fragment can merge with another adjacent fragment or false otherwise.
pub fn can_merge_with_fragment(&self, other: &Fragment) -> bool {
match (&self.specific, &other.specific) {
(&SpecificFragmentInfo::UnscannedText(_), &SpecificFragmentInfo::UnscannedText(_)) => {
(&SpecificFragmentInfo::UnscannedText(ref first_unscanned_text),
&SpecificFragmentInfo::UnscannedText(_)) => {
// FIXME: Should probably use a whitelist of styles that can safely differ (#3165)
let length = first_unscanned_text.text.len();
self.style().get_font() == other.style().get_font() &&
self.text_decoration() == other.text_decoration() &&
self.white_space() == other.white_space()
self.white_space() == other.white_space() &&
(length == 0 || first_unscanned_text.text.char_at_reverse(length) != '\n')
}
_ => false,
}
@ -2076,14 +1944,57 @@ impl Fragment {
_ => {}
}
}
pub fn requires_line_break_afterward_if_wrapping_on_newlines(&self) -> bool {
match self.specific {
SpecificFragmentInfo::ScannedText(ref scanned_text) => {
!scanned_text.range.is_empty() &&
scanned_text.run.text.char_at_reverse(scanned_text.range
.end()
.get() as usize) == '\n'
}
_ => false,
}
}
pub fn strip_leading_whitespace_if_necessary(&mut self) {
let mut scanned_text_fragment_info = match self.specific {
SpecificFragmentInfo::ScannedText(ref mut scanned_text_fragment_info) => {
scanned_text_fragment_info
}
_ => return,
};
if self.style.get_inheritedtext().white_space == white_space::T::pre {
return
}
let mut leading_whitespace_character_count = 0;
{
let text = scanned_text_fragment_info.run.text.slice_chars(
scanned_text_fragment_info.range.begin().to_usize(),
scanned_text_fragment_info.range.end().to_usize());
for character in text.chars() {
if util::str::char_is_whitespace(character) {
leading_whitespace_character_count += 1
} else {
break
}
}
}
scanned_text_fragment_info.range.adjust_by(CharIndex(leading_whitespace_character_count),
-CharIndex(leading_whitespace_character_count));
}
}
impl fmt::Debug for Fragment {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "({} {} ", self.debug_id(), self.specific.get_type()));
try!(write!(f, "bp {:?}", self.border_padding));
try!(write!(f, " "));
try!(write!(f, "m {:?}", self.margin));
try!(write!(f, "bb {:?} bp {:?} m {:?}",
self.border_box,
self.border_padding,
self.margin));
write!(f, ")")
}
}
@ -2105,7 +2016,7 @@ bitflags! {
const STARTS_LINE = 0x01,
#[doc="True if we should attempt to split at character boundaries if this split fails. \
This is used to implement `overflow-wrap: break-word`."]
const RETRY_AT_CHARACTER_BOUNDARIES = 0x02
const RETRY_AT_CHARACTER_BOUNDARIES = 0x02,
}
}
@ -2129,25 +2040,3 @@ pub enum CoordinateSystem {
Own,
}
/// Given a range and a text run, adjusts the range to eliminate trailing whitespace. Returns true
/// if any modifications were made.
fn strip_trailing_whitespace(text_run: &TextRun, range: &mut Range<CharIndex>) -> bool {
// FIXME(pcwalton): Is there a more clever (i.e. faster) way to do this?
let text = text_run.text.slice_chars(range.begin().to_usize(), range.end().to_usize());
let mut trailing_whitespace_character_count = 0;
for ch in text.chars().rev() {
if ch.is_whitespace() {
trailing_whitespace_character_count += 1
} else {
break
}
}
if trailing_whitespace_character_count == 0 {
return false
}
range.extend_by(-CharIndex(trailing_whitespace_character_count));
return true
}

View file

@ -8,11 +8,9 @@ use css::node_style::StyledNode;
use context::LayoutContext;
use display_list_builder::{FragmentDisplayListBuilding, InlineFlowDisplayListBuilding};
use floats::{FloatKind, Floats, PlacementInfo};
use flow::{BaseFlow, FlowClass, Flow, MutableFlowUtils, ForceNonfloatedFlag};
use flow::{self, BaseFlow, FlowClass, Flow, MutableFlowUtils, ForceNonfloatedFlag};
use flow::{IS_ABSOLUTELY_POSITIONED};
use flow;
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, ScannedTextFragmentInfo};
use fragment::{SpecificFragmentInfo, SplitInfo};
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo};
use incremental::{REFLOW, REFLOW_OUT_OF_FLOW, RESOLVE_GENERATED_CONTENT};
use layout_debug;
use model::IntrinsicISizesContribution;
@ -23,20 +21,21 @@ use geom::{Point2D, Rect};
use gfx::font::FontMetrics;
use gfx::font_context::FontContext;
use gfx::text::glyph::CharIndex;
use util::arc_ptr_eq;
use util::geometry::{Au, ZERO_RECT};
use util::logical_geometry::{LogicalRect, LogicalSize, WritingMode};
use util::range::{Range, RangeIndex};
use gfx::text::text_run::TextRun;
use std::cmp::max;
use std::fmt;
use std::mem;
use std::num::ToPrimitive;
use std::ops::{Add, Sub, Mul, Div, Rem, Neg, Shl, Shr, Not, BitOr, BitAnd, BitXor};
use std::sync::Arc;
use std::u16;
use style::computed_values::{overflow_x, text_align, text_justify, text_overflow, vertical_align};
use style::computed_values::{white_space};
use style::properties::ComputedValues;
use std::sync::Arc;
use util::geometry::{Au, MAX_AU, ZERO_RECT};
use util::logical_geometry::{LogicalRect, LogicalSize, WritingMode};
use util::range::{Range, RangeIndex};
use util;
// From gfxFontConstants.h in Firefox
static FONT_SUBSCRIPT_OFFSET_RATIO: f64 = 0.20;
@ -160,7 +159,9 @@ int_range_index! {
bitflags! {
flags InlineReflowFlags: u8 {
#[doc="The `white-space: nowrap` property from CSS 2.1 § 16.6 is in effect."]
const NO_WRAP_INLINE_REFLOW_FLAG = 0x01
const NO_WRAP_INLINE_REFLOW_FLAG = 0x01,
#[doc="The `white-space: pre` property from CSS 2.1 § 16.6 is in effect."]
const WRAP_ON_NEWLINE_INLINE_REFLOW_FLAG = 0x02
}
}
@ -191,7 +192,7 @@ impl LineBreaker {
pending_line: Line {
range: Range::empty(),
bounds: LogicalRect::zero(float_context.writing_mode),
green_zone: LogicalSize::zero(float_context.writing_mode)
green_zone: LogicalSize::zero(float_context.writing_mode),
},
floats: float_context,
lines: Vec::new(),
@ -216,7 +217,7 @@ impl LineBreaker {
self.cur_b,
Au(0),
Au(0));
self.pending_line.green_zone = LogicalSize::zero(self.floats.writing_mode)
self.pending_line.green_zone = LogicalSize::zero(self.floats.writing_mode);
}
/// Reflows fragments for the given inline flow.
@ -226,23 +227,13 @@ impl LineBreaker {
// Create our fragment iterator.
debug!("LineBreaker: scanning for lines, {} fragments", flow.fragments.len());
let mut old_fragments = mem::replace(&mut flow.fragments, InlineFragments::new());
let mut old_fragment_iter = old_fragments.fragments.into_iter();
let old_fragment_iter = old_fragments.fragments.into_iter();
// Set up our initial line state with the clean lines from a previous reflow.
//
// TODO(pcwalton): This would likely be better as a list of dirty line indices. That way we
// could resynchronize if we discover during reflow that all subsequent fragments must have
// the same position as they had in the previous reflow. I don't know how common this case
// really is in practice, but it's probably worth handling.
self.lines = mem::replace(&mut flow.lines, Vec::new());
match self.lines.as_slice().last() {
None => {}
Some(last_line) => {
for _ in range(FragmentIndex(0), last_line.range.end()) {
self.new_fragments.push(old_fragment_iter.next().unwrap())
}
}
}
self.lines = Vec::new();
// Do the reflow.
self.reflow_fragments(old_fragment_iter, flow, layout_context);
@ -270,30 +261,14 @@ impl LineBreaker {
// Set up our reflow flags.
let flags = match fragment.style().get_inheritedtext().white_space {
white_space::T::normal => InlineReflowFlags::empty(),
white_space::T::pre | white_space::T::nowrap => NO_WRAP_INLINE_REFLOW_FLAG,
white_space::T::nowrap => NO_WRAP_INLINE_REFLOW_FLAG,
white_space::T::pre => {
WRAP_ON_NEWLINE_INLINE_REFLOW_FLAG | NO_WRAP_INLINE_REFLOW_FLAG
}
};
// Try to append the fragment, and commit the line (so we can try again with the next
// line) if we couldn't.
match fragment.style().get_inheritedtext().white_space {
white_space::T::normal | white_space::T::nowrap => {
if !self.append_fragment_to_line_if_possible(fragment,
flow,
layout_context,
flags) {
self.flush_current_line()
}
}
white_space::T::pre => {
// FIXME(pcwalton): Surely we can unify
// `append_fragment_to_line_if_possible` and
// `try_append_to_line_by_new_line` by adding another bit in the reflow
// flags.
if !self.try_append_to_line_by_new_line(layout_context, fragment) {
self.flush_current_line()
}
}
}
// Try to append the fragment.
self.reflow_fragment(fragment, flow, layout_context, flags);
}
if !self.pending_line_is_empty() {
@ -301,37 +276,25 @@ impl LineBreaker {
self.lines.len());
self.flush_current_line()
}
// Strip trailing whitespace from the last line if necessary.
if let Some(ref mut last_line) = self.lines.last_mut() {
if let Some(ref mut last_fragment) = self.new_fragments.last_mut() {
let previous_inline_size = last_line.bounds.size.inline -
last_fragment.border_box.size.inline;
if last_fragment.strip_trailing_whitespace_if_necessary() {
last_line.bounds.size.inline = previous_inline_size +
last_fragment.border_box.size.inline;
}
}
}
}
/// Acquires a new fragment to lay out from the work list or fragment list as appropriate.
/// Note that you probably don't want to call this method directly in order to be
/// incremental-reflow-safe; try `next_unbroken_fragment` instead.
/// If the fragment was at the end of an old line, undoes the line break for that fragment.
/// Note that you probably don't want to call this method directly in order to be incremental-
/// reflow-safe; try `next_unbroken_fragment` instead.
fn next_fragment<I>(&mut self, old_fragment_iter: &mut I) -> Option<Fragment>
where I: Iterator<Item=Fragment> {
let mut fragment;
if self.work_list.is_empty() {
return match old_fragment_iter.next() {
None => None,
Some(fragment) => {
debug!("LineBreaker: working with fragment from flow: {:?}", fragment);
Some(fragment)
}
match old_fragment_iter.next() {
None => return None,
Some(this_fragment) => fragment = this_fragment,
}
} else {
return self.work_list.pop_front()
}
debug!("LineBreaker: working with fragment from work list: {:?}", self.work_list.front());
self.work_list.pop_front()
Some(fragment)
}
/// Acquires a new fragment to lay out from the work list or fragment list, merging it with any
@ -346,10 +309,6 @@ impl LineBreaker {
};
loop {
// FIXME(pcwalton): Yuck! I hate this `new_line_pos` stuff. Can we avoid having to do
// this?
result.restore_new_line_pos();
let candidate = match self.next_fragment(old_fragment_iter) {
None => return Some(result),
Some(fragment) => fragment,
@ -357,31 +316,58 @@ impl LineBreaker {
let need_to_merge = match (&mut result.specific, &candidate.specific) {
(&mut SpecificFragmentInfo::ScannedText(ref mut result_info),
&SpecificFragmentInfo::ScannedText(ref candidate_info))
if arc_ptr_eq(&result_info.run, &candidate_info.run) &&
result_info.range.end() + CharIndex(1) == candidate_info.range.begin() => {
// We found a previously-broken fragment. Merge it up.
result_info.range.extend_by(candidate_info.range.length() + CharIndex(1));
true
&SpecificFragmentInfo::ScannedText(ref candidate_info)) => {
util::arc_ptr_eq(&result_info.run, &candidate_info.run) &&
inline_contexts_are_equal(&result.inline_context,
&candidate.inline_context)
}
_ => false,
};
if !need_to_merge {
if need_to_merge {
result.merge_with(candidate);
continue
}
self.work_list.push_front(candidate);
return Some(result)
}
}
}
/// Commits a line to the list.
fn flush_current_line(&mut self) {
debug!("LineBreaker: flushing line {}: {:?}", self.lines.len(), self.pending_line);
self.strip_trailing_whitespace_from_pending_line_if_necessary();
self.lines.push(self.pending_line);
self.cur_b = self.pending_line.bounds.start.b + self.pending_line.bounds.size.block;
self.reset_line();
}
/// Removes trailing whitespace from the pending line if necessary. This is done right before
/// flushing it.
fn strip_trailing_whitespace_from_pending_line_if_necessary(&mut self) {
if self.pending_line.range.is_empty() {
return
}
let last_fragment_index = self.pending_line.range.end() - FragmentIndex(1);
let mut fragment = &mut self.new_fragments[last_fragment_index.get() as usize];
if let SpecificFragmentInfo::ScannedText(ref mut scanned_text_fragment_info) =
fragment.specific {
let scanned_text_fragment_info = &mut **scanned_text_fragment_info;
let mut range = &mut scanned_text_fragment_info.range;
strip_trailing_whitespace_if_necessary(&**scanned_text_fragment_info.run, range);
let old_fragment_inline_size = fragment.border_box.size.inline;
scanned_text_fragment_info.content_size.inline =
scanned_text_fragment_info.run.metrics_for_range(range).advance_width;
fragment.border_box.size.inline = scanned_text_fragment_info.content_size.inline +
fragment.border_padding.inline_start_end();
self.pending_line.bounds.size.inline = self.pending_line.bounds.size.inline -
(old_fragment_inline_size - fragment.border_box.size.inline)
}
}
// FIXME(eatkinson): this assumes that the tallest fragment in the line determines the line
// block-size. This might not be the case with some weird text fonts.
fn new_block_size_for_line(&self, new_fragment: &Fragment, layout_context: &LayoutContext)
@ -488,71 +474,16 @@ impl LineBreaker {
false
}
/// Tries to append the given fragment to the line for `pre`-formatted text, splitting it if
/// necessary. Returns true if we successfully pushed the fragment to the line or false if we
/// couldn't.
fn try_append_to_line_by_new_line(&mut self,
layout_context: &LayoutContext,
in_fragment: Fragment)
-> bool {
let should_push = match in_fragment.newline_positions() {
None => true,
Some(ref positions) => positions.is_empty(),
};
if should_push {
debug!("LineBreaker: did not find a newline character; pushing the fragment to \
the line without splitting");
self.push_fragment_to_line(layout_context, in_fragment);
return true
}
debug!("LineBreaker: Found a new-line character, so splitting the line.");
let (inline_start, inline_end, run) =
in_fragment.find_split_info_by_new_line()
.expect("LineBreaker: this split case makes no sense!");
let writing_mode = self.floats.writing_mode;
let split_fragment = |split: SplitInfo| {
let size = LogicalSize::new(writing_mode,
split.inline_size,
in_fragment.border_box.size.block);
let info = box ScannedTextFragmentInfo::new(run.clone(),
split.range,
(*in_fragment.newline_positions()
.unwrap()).clone(),
size);
in_fragment.transform(size, SpecificFragmentInfo::ScannedText(info))
};
debug!("LineBreaker: Pushing the fragment to the inline_start of the new-line character \
to the line.");
let mut inline_start = split_fragment(inline_start);
inline_start.save_new_line_pos();
*inline_start.newline_positions_mut().unwrap() = vec![];
self.push_fragment_to_line(layout_context, inline_start);
for inline_end in inline_end.into_iter() {
debug!("LineBreaker: Deferring the fragment to the inline_end of the new-line \
character to the line.");
let mut inline_end = split_fragment(inline_end);
inline_end.newline_positions_mut().unwrap().remove(0);
self.work_list.push_front(inline_end);
}
false
}
/// Tries to append the given fragment to the line, splitting it if necessary. Returns true if
/// we successfully pushed the fragment to the line or false if we couldn't.
fn append_fragment_to_line_if_possible(&mut self,
fragment: Fragment,
/// Tries to append the given fragment to the line, splitting it if necessary. Commits the
/// current line if needed.
fn reflow_fragment(&mut self,
mut fragment: Fragment,
flow: &InlineFlow,
layout_context: &LayoutContext,
flags: InlineReflowFlags)
-> bool {
flags: InlineReflowFlags) {
// Determine initial placement for the fragment if we need to.
if self.pending_line_is_empty() {
fragment.strip_leading_whitespace_if_necessary();
let (line_bounds, _) = self.initial_line_placement(flow, &fragment, self.cur_b);
self.pending_line.bounds.start = line_bounds.start;
self.pending_line.green_zone = line_bounds.size;
@ -572,8 +503,21 @@ impl LineBreaker {
let new_block_size = self.new_block_size_for_line(&fragment, layout_context);
if new_block_size > green_zone.block {
// Uh-oh. Float collision imminent. Enter the float collision avoider!
return self.avoid_floats(flow, fragment, new_block_size)
if !self.avoid_floats(flow, fragment, new_block_size) {
self.flush_current_line();
}
return
}
// If we must flush the line after finishing this fragment due to `white-space: pre`,
// detect that.
let line_flush_mode =
if flags.contains(WRAP_ON_NEWLINE_INLINE_REFLOW_FLAG) &&
fragment.requires_line_break_afterward_if_wrapping_on_newlines() {
LineFlushMode::Flush
} else {
LineFlushMode::No
};
// If we're not going to overflow the green zone vertically, we might still do so
// horizontally. We'll try to place the whole fragment on this line and break somewhere if
@ -583,23 +527,27 @@ impl LineBreaker {
fragment.border_box.size.inline + indentation;
if new_inline_size <= green_zone.inline {
debug!("LineBreaker: fragment fits without splitting");
self.push_fragment_to_line(layout_context, fragment);
return true
self.push_fragment_to_line(layout_context, fragment, line_flush_mode);
return
}
// If we can't split the fragment or aren't allowed to because of the wrapping mode, then
// just overflow.
if (!fragment.can_split() && self.pending_line_is_empty()) ||
flags.contains(NO_WRAP_INLINE_REFLOW_FLAG) {
(flags.contains(NO_WRAP_INLINE_REFLOW_FLAG) &&
!flags.contains(WRAP_ON_NEWLINE_INLINE_REFLOW_FLAG)) {
debug!("LineBreaker: fragment can't split and line {} is empty, so overflowing",
self.lines.len());
self.push_fragment_to_line(layout_context, fragment);
return false
self.push_fragment_to_line(layout_context, fragment, LineFlushMode::No);
return
}
// Split it up!
let available_inline_size = green_zone.inline - self.pending_line.bounds.size.inline -
indentation;
let available_inline_size = if !flags.contains(NO_WRAP_INLINE_REFLOW_FLAG) {
green_zone.inline - self.pending_line.bounds.size.inline - indentation
} else {
MAX_AU
};
let inline_start_fragment;
let inline_end_fragment;
let split_result = match fragment.calculate_split_position(available_inline_size,
@ -607,7 +555,8 @@ impl LineBreaker {
None => {
debug!("LineBreaker: fragment was unsplittable; deferring to next line");
self.work_list.push_front(fragment);
return false
self.flush_current_line();
return
}
Some(split_result) => split_result,
};
@ -623,23 +572,30 @@ impl LineBreaker {
// the second fragment. If there's no second fragment, the next line will start off empty.
match (inline_start_fragment, inline_end_fragment) {
(Some(inline_start_fragment), Some(inline_end_fragment)) => {
self.push_fragment_to_line(layout_context, inline_start_fragment);
self.flush_current_line();
self.push_fragment_to_line(layout_context,
inline_start_fragment,
LineFlushMode::Flush);
self.work_list.push_front(inline_end_fragment)
},
(Some(fragment), None) => {
self.push_fragment_to_line(layout_context, fragment);
self.push_fragment_to_line(layout_context, fragment, line_flush_mode);
}
(None, Some(fragment)) => {
// Yes, this can happen!
self.flush_current_line();
self.work_list.push_front(fragment)
}
(None, Some(_)) => debug_assert!(false, "un-normalized split result"),
(None, None) => {}
}
true
}
/// Pushes a fragment to the current line unconditionally, possibly truncating it and placing
/// an ellipsis based on the value of `text-overflow`.
fn push_fragment_to_line(&mut self, layout_context: &LayoutContext, fragment: Fragment) {
/// an ellipsis based on the value of `text-overflow`. If `flush_line` is `Flush`, then flushes
/// the line afterward;
fn push_fragment_to_line(&mut self,
layout_context: &LayoutContext,
fragment: Fragment,
line_flush_mode: LineFlushMode) {
let indentation = self.indentation_for_pending_fragment();
if self.pending_line_is_empty() {
assert!(self.new_fragments.len() <= (u16::MAX as usize));
@ -661,9 +617,7 @@ impl LineBreaker {
if !need_ellipsis {
self.push_fragment_to_line_ignoring_text_overflow(fragment);
return
}
} else {
let ellipsis = fragment.transform_into_ellipsis(layout_context);
if let Some(truncation_info) =
fragment.truncate_to_inline_size(available_inline_size -
@ -675,11 +629,15 @@ impl LineBreaker {
self.push_fragment_to_line_ignoring_text_overflow(ellipsis);
}
if line_flush_mode == LineFlushMode::Flush {
self.flush_current_line()
}
}
/// Pushes a fragment to the current line unconditionally, without placing an ellipsis in the
/// case of `text-overflow: ellipsis`.
fn push_fragment_to_line_ignoring_text_overflow(&mut self, fragment: Fragment) {
let indentation = self.indentation_for_pending_fragment();
self.pending_line.range.extend_by(FragmentIndex(1));
self.pending_line.bounds.size.inline = self.pending_line.bounds.size.inline +
fragment.border_box.size.inline +
@ -813,7 +771,7 @@ impl InlineFlow {
///
/// The extra boolean is set if and only if `largest_block_size_for_top_fragments` and/or
/// `largest_block_size_for_bottom_fragments` were updated. That is, if the box has a `top` or
/// `bottom` value for `vertical-align, true is returned.
/// `bottom` value for `vertical-align`, true is returned.
fn distance_from_baseline(fragment: &Fragment,
ascent: Au,
parent_text_block_start: Au,
@ -1180,7 +1138,7 @@ impl Flow for InlineFlow {
// Reset our state, so that we handle incremental reflow correctly.
//
// TODO(pcwalton): Do something smarter, like Gecko and WebKit?
self.lines = Vec::new();
self.lines.clear();
// Determine how much indentation the first line wants.
let mut indentation = if self.fragments.is_empty() {
@ -1431,6 +1389,30 @@ impl InlineFragmentContext {
styles: vec!()
}
}
fn ptr_eq(&self, other: &InlineFragmentContext) -> bool {
if self.styles.len() != other.styles.len() {
return false
}
for (this_style, other_style) in self.styles.iter().zip(other.styles.iter()) {
if !util::arc_ptr_eq(this_style, other_style) {
return false
}
}
true
}
}
fn inline_contexts_are_equal(inline_context_a: &Option<InlineFragmentContext>,
inline_context_b: &Option<InlineFragmentContext>)
-> bool {
match (inline_context_a, inline_context_b) {
(&Some(ref inline_context_a), &Some(ref inline_context_b)) => {
inline_context_a.ptr_eq(inline_context_b)
}
(&None, &None) => true,
(&Some(_), &None) | (&None, &Some(_)) => false,
}
}
/// Block-size above the baseline, depth below the baseline, and ascent for a fragment. See CSS 2.1
@ -1464,3 +1446,31 @@ impl InlineMetrics {
}
}
}
#[derive(Copy, Clone, PartialEq)]
enum LineFlushMode {
No,
Flush,
}
/// Given a range and a text run, adjusts the range to eliminate trailing whitespace.
fn strip_trailing_whitespace_if_necessary(text_run: &TextRun, range: &mut Range<CharIndex>) {
// FIXME(pcwalton): Is there a more clever (i.e. faster) way to do this?
debug!("stripping trailing whitespace: range={:?}, len={}",
range,
text_run.text.chars().count());
let text = text_run.text.slice_chars(range.begin().to_usize(), range.end().to_usize());
let mut trailing_whitespace_character_count = 0;
for ch in text.chars().rev() {
if util::str::char_is_whitespace(ch) {
trailing_whitespace_character_count += 1
} else {
break
}
}
if trailing_whitespace_character_count != 0 {
range.extend_by(CharIndex(-trailing_whitespace_character_count));
}
}

View file

@ -174,7 +174,12 @@ impl MarginCollapseInfo {
pub fn current_float_ceiling(&mut self) -> Au {
match self.state {
MarginCollapseState::AccumulatingCollapsibleTopMargin => self.block_start_margin.collapse(),
MarginCollapseState::AccumulatingCollapsibleTopMargin => {
// We do not include the top margin in the float ceiling, because the float flow
// needs to be positioned relative to our *border box*, not our margin box. See
// `tests/ref/float_under_top_margin_a.html`.
Au(0)
}
MarginCollapseState::AccumulatingMarginIn => self.margin_in.collapse(),
}
}
@ -182,18 +187,22 @@ impl MarginCollapseInfo {
/// Adds the child's potentially collapsible block-start margin to the current margin state and
/// advances the Y offset by the appropriate amount to handle that margin. Returns the amount
/// that should be added to the Y offset during block layout.
pub fn advance_block_start_margin(&mut self, child_collapsible_margins: &CollapsibleMargins) -> Au {
pub fn advance_block_start_margin(&mut self, child_collapsible_margins: &CollapsibleMargins)
-> Au {
match (self.state, *child_collapsible_margins) {
(MarginCollapseState::AccumulatingCollapsibleTopMargin, CollapsibleMargins::None(block_start, _)) => {
(MarginCollapseState::AccumulatingCollapsibleTopMargin,
CollapsibleMargins::None(block_start, _)) => {
self.state = MarginCollapseState::AccumulatingMarginIn;
block_start
}
(MarginCollapseState::AccumulatingCollapsibleTopMargin, CollapsibleMargins::Collapse(block_start, _)) => {
(MarginCollapseState::AccumulatingCollapsibleTopMargin,
CollapsibleMargins::Collapse(block_start, _)) => {
self.block_start_margin.union(block_start);
self.state = MarginCollapseState::AccumulatingMarginIn;
Au(0)
}
(MarginCollapseState::AccumulatingMarginIn, CollapsibleMargins::None(block_start, _)) => {
(MarginCollapseState::AccumulatingMarginIn,
CollapsibleMargins::None(block_start, _)) => {
let previous_margin_value = self.margin_in.collapse();
self.margin_in = AdjoiningMargins::new();
previous_margin_value + block_start

View file

@ -6,7 +6,7 @@
#![deny(unsafe_code)]
use fragment::{Fragment, SpecificFragmentInfo, ScannedTextFragmentInfo};
use fragment::{Fragment, SpecificFragmentInfo, ScannedTextFragmentInfo, UnscannedTextFragmentInfo};
use inline::InlineFragments;
use gfx::font::{DISABLE_KERNING_SHAPING_FLAG, FontMetrics, IGNORE_LIGATURES_SHAPING_FLAG};
@ -15,18 +15,19 @@ use gfx::font_context::FontContext;
use gfx::text::glyph::CharIndex;
use gfx::text::text_run::TextRun;
use gfx::text::util::{self, CompressionMode};
use util::linked_list::split_off_head;
use util::geometry::Au;
use util::logical_geometry::{LogicalSize, WritingMode};
use util::range::Range;
use util::smallvec::{SmallVec, SmallVec1};
use std::borrow::ToOwned;
use std::collections::LinkedList;
use std::mem;
use std::sync::Arc;
use style::computed_values::{line_height, text_orientation, text_rendering, text_transform};
use style::computed_values::{white_space};
use style::properties::ComputedValues;
use style::properties::style_structs::Font as FontStyle;
use std::sync::Arc;
use util::geometry::Au;
use util::linked_list::split_off_head;
use util::logical_geometry::{LogicalSize, WritingMode};
use util::range::Range;
use util::smallvec::{SmallVec, SmallVec1};
/// A stack-allocated object for scanning an inline flow into `TextRun`-containing `TextFragment`s.
pub struct TextRunScanner {
@ -40,7 +41,9 @@ impl TextRunScanner {
}
}
pub fn scan_for_runs(&mut self, font_context: &mut FontContext, mut fragments: LinkedList<Fragment>)
pub fn scan_for_runs(&mut self,
font_context: &mut FontContext,
mut fragments: LinkedList<Fragment>)
-> InlineFragments {
debug!("TextRunScanner: scanning {} fragments for text runs...", fragments.len());
@ -50,12 +53,14 @@ impl TextRunScanner {
let mut last_whitespace = true;
while !fragments.is_empty() {
// Create a clump.
split_first_fragment_at_newline_if_necessary(&mut fragments);
self.clump.append(&mut split_off_head(&mut fragments));
while !fragments.is_empty() && self.clump
.back()
.unwrap()
.can_merge_with_fragment(fragments.front()
.unwrap()) {
split_first_fragment_at_newline_if_necessary(&mut fragments);
self.clump.append(&mut split_off_head(&mut fragments));
}
@ -101,7 +106,6 @@ impl TextRunScanner {
//
// Concatenate all of the transformed strings together, saving the new character indices.
let mut new_ranges: SmallVec1<Range<CharIndex>> = SmallVec1::new();
let mut new_line_positions: SmallVec1<NewLinePositions> = SmallVec1::new();
let mut char_total = CharIndex(0);
let run = {
let fontgroup;
@ -137,14 +141,11 @@ impl TextRunScanner {
_ => panic!("Expected an unscanned text fragment!"),
};
let mut new_line_pos = Vec::new();
let old_length = CharIndex(run_text.chars().count() as isize);
last_whitespace = util::transform_text(in_fragment.as_slice(),
compression,
last_whitespace,
&mut run_text,
&mut new_line_pos);
new_line_positions.push(NewLinePositions(new_line_pos));
&mut run_text);
let added_chars = CharIndex(run_text.chars().count() as isize) - old_length;
new_ranges.push(Range::new(char_total, added_chars));
@ -200,13 +201,8 @@ impl TextRunScanner {
}
let text_size = old_fragment.border_box.size;
let &mut NewLinePositions(ref mut new_line_positions) =
new_line_positions.get_mut(logical_offset);
let mut new_text_fragment_info =
box ScannedTextFragmentInfo::new(run.clone(),
range,
mem::replace(new_line_positions, Vec::new()),
text_size);
box ScannedTextFragmentInfo::new(run.clone(), range, text_size);
let new_metrics = new_text_fragment_info.run.metrics_for_range(&range);
let bounding_box_size = bounding_box_for_run_metrics(&new_metrics,
old_fragment.style.writing_mode);
@ -270,8 +266,6 @@ impl TextRunScanner {
}
}
struct NewLinePositions(Vec<CharIndex>);
#[inline]
fn bounding_box_for_run_metrics(metrics: &RunMetrics, writing_mode: WritingMode)
-> LogicalSize<Au> {
@ -318,3 +312,45 @@ pub fn line_height_from_style(style: &ComputedValues, metrics: &FontMetrics) ->
line_height::T::Length(l) => l
}
}
fn split_first_fragment_at_newline_if_necessary(fragments: &mut LinkedList<Fragment>) {
if fragments.len() < 1 {
return
}
let new_fragment = {
let mut first_fragment = fragments.front_mut().unwrap();
let string_before;
{
let unscanned_text_fragment_info = match first_fragment.specific {
SpecificFragmentInfo::UnscannedText(ref mut unscanned_text_fragment_info) => {
unscanned_text_fragment_info
}
_ => return,
};
if first_fragment.style.get_inheritedtext().white_space != white_space::T::pre {
return
}
let position = match unscanned_text_fragment_info.text.find('\n') {
Some(position) if position < unscanned_text_fragment_info.text.len() - 1 => {
position
}
Some(_) | None => return,
};
string_before =
box unscanned_text_fragment_info.text[..(position + 1)].to_owned();
unscanned_text_fragment_info.text =
box unscanned_text_fragment_info.text[(position + 1)..].to_owned();
}
first_fragment.transform(first_fragment.border_box.size,
SpecificFragmentInfo::UnscannedText(UnscannedTextFragmentInfo {
text: string_before,
}))
};
fragments.push_front(new_fragment);
}

View file

@ -41,11 +41,12 @@ use opaque_node::OpaqueNodeMethods;
use cssparser::RGBA;
use gfx::display_list::OpaqueNode;
use script::dom::bindings::codegen::InheritTypes::{ElementCast, HTMLIFrameElementCast};
use script::dom::bindings::codegen::InheritTypes::{HTMLCanvasElementCast, HTMLImageElementCast};
use script::dom::bindings::codegen::InheritTypes::{HTMLInputElementCast, HTMLTextAreaElementCast};
use script::dom::bindings::codegen::InheritTypes::{NodeCast, TextCast};
use script::dom::bindings::codegen::InheritTypes::{CharacterDataCast, ElementCast};
use script::dom::bindings::codegen::InheritTypes::{HTMLIFrameElementCast, HTMLCanvasElementCast};
use script::dom::bindings::codegen::InheritTypes::{HTMLImageElementCast, HTMLInputElementCast};
use script::dom::bindings::codegen::InheritTypes::{HTMLTextAreaElementCast, NodeCast, TextCast};
use script::dom::bindings::js::LayoutJS;
use script::dom::characterdata::LayoutCharacterDataHelpers;
use script::dom::element::{Element, ElementTypeId};
use script::dom::element::{LayoutElementHelpers, RawLayoutElementHelpers};
use script::dom::htmlelement::HTMLElementTypeId;
@ -222,9 +223,8 @@ impl<'ln> TLayoutNode for LayoutNode<'ln> {
let text: Option<LayoutJS<Text>> = TextCast::to_layout_js(self.get_jsmanaged());
if let Some(text) = text {
return vec![
ContentItem::String((*text.unsafe_get()).characterdata()
.data_for_layout()
.to_owned())
ContentItem::String(
CharacterDataCast::from_layout_js(&text).data_for_layout().to_owned())
];
}
let input: Option<LayoutJS<HTMLInputElement>> =
@ -961,7 +961,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
None => return false
};
if !is_whitespace((*text.unsafe_get()).characterdata().data_for_layout()) {
if !is_whitespace(CharacterDataCast::from_layout_js(&text).data_for_layout()) {
return false
}

View file

@ -111,7 +111,7 @@ impl MIMEClassifier {
self.binary_or_plaintext.classify(data)
}
fn is_xml(tp: &str, sub_tp: &str) -> bool {
let suffix = &sub_tp[(max((sub_tp.len() as int) - ("+xml".len() as int), 0i) as uint)..];
let suffix = &sub_tp[(max(sub_tp.len() as isize - "+xml".len() as isize, 0) as usize)..];
match (tp, sub_tp, suffix) {
(_, _, "+xml") | ("application", "xml",_) | ("text", "xml",_) => {true}
_ => {false}
@ -170,13 +170,13 @@ struct ByteMatcher {
}
impl ByteMatcher {
fn matches(&self, data: &Vec<u8>) -> Option<uint> {
fn matches(&self, data: &Vec<u8>) -> Option<usize> {
if data.len() < self.pattern.len() {
return None;
}
//TODO replace with iterators if I ever figure them out...
let mut i = 0u;
let mut i: usize = 0;
let max_i = data.len()-self.pattern.len();
loop {
@ -184,12 +184,12 @@ impl ByteMatcher {
break;
}
i=i + 1;
i = i + 1;
if i > max_i {
return None;
}
}
for j in range(0u,self.pattern.len()) {
for j in 0..self.pattern.len() {
if (data[i] & self.mask[j]) != (self.pattern[j] & self.mask[j]) {
return None;
}
@ -231,7 +231,7 @@ impl Mp4Matcher {
return false;
}
let box_size = ((data[0] as u32) << 3 | (data[1] as u32) << 2 |
(data[2] as u32) << 1 | (data[3] as u32)) as uint;
(data[2] as u32) << 1 | (data[3] as u32)) as usize;
if (data.len() < box_size) || (box_size % 4 != 0) {
return false;
}
@ -239,14 +239,14 @@ impl Mp4Matcher {
let ftyp = [0x66, 0x74, 0x79, 0x70];
let mp4 = [0x6D, 0x70, 0x34];
for i in range(4u,8u) {
for i in 4..8 {
if data[i] != ftyp[i - 4] {
return false;
}
}
let mut all_match = true;
for i in range(8u,11u) {
if data[i]!=mp4[i - 8u] {
for i in 8..11 {
if data[i]!=mp4[i - 8] {
all_match = false;
break;
}
@ -255,11 +255,11 @@ impl Mp4Matcher {
return true;
}
let mut bytes_read = 16u;
let mut bytes_read: usize = 16;
while bytes_read < box_size {
all_match = true;
for i in range(0u,3u) {
for i in 0..3 {
if mp4[i] != data[i + bytes_read] {
all_match = false;
break;

View file

@ -5427,6 +5427,12 @@ impl ${name}Cast {
unsafe { derived.transmute_borrowed() }
}
#[inline(always)]
#[allow(unrooted_must_root)]
pub fn from_layout_js<T: ${fromBound}+Reflectable>(derived: &LayoutJS<T>) -> LayoutJS<${name}> {
unsafe { derived.transmute_copy() }
}
#[inline(always)]
pub fn from_temporary<T: ${fromBound}+Reflectable>(derived: Temporary<T>) -> Temporary<${name}> {
unsafe { derived.transmute() }

View file

@ -71,10 +71,9 @@ pub type Fallible<T> = Result<T, Error>;
/// return `()`.
pub type ErrorResult = Fallible<()>;
/// Set a pending DOM exception for the given `result` on `cx`.
/// Set a pending exception for the given `result` on `cx`.
pub fn throw_dom_exception(cx: *mut JSContext, global: GlobalRef,
result: Error) {
assert!(unsafe { JS_IsExceptionPending(cx) } == 0);
let code = match result {
Error::IndexSize => DOMErrorName::IndexSizeError,
Error::NotFound => DOMErrorName::NotFoundError,
@ -93,11 +92,17 @@ pub fn throw_dom_exception(cx: *mut JSContext, global: GlobalRef,
Error::DataClone => DOMErrorName::DataCloneError,
Error::NoModificationAllowed => DOMErrorName::NoModificationAllowedError,
Error::Type(message) => {
assert!(unsafe { JS_IsExceptionPending(cx) } == 0);
throw_type_error(cx, &message);
return;
}
Error::JSFailed => panic!(),
Error::JSFailed => {
assert!(unsafe { JS_IsExceptionPending(cx) } == 1);
return;
}
};
assert!(unsafe { JS_IsExceptionPending(cx) } == 0);
let exception = DOMException::new(global, code).root();
let thrown = exception.to_jsval(cx);
unsafe {

View file

@ -7,14 +7,17 @@
use dom::bindings::codegen::PrototypeList;
use dom::bindings::codegen::PrototypeList::MAX_PROTO_CHAIN_LENGTH;
use dom::bindings::conversions::{native_from_reflector_jsmanaged, is_dom_class};
use dom::bindings::error::throw_type_error;
use dom::bindings::error::{Error, ErrorResult, Fallible, throw_type_error};
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{Temporary, Root};
use dom::browsercontext;
use dom::window;
use util::namespace;
use util::str::DOMString;
use libc;
use libc::c_uint;
use std::borrow::ToOwned;
use std::boxed;
use std::cell::Cell;
use std::ffi::CString;
@ -43,6 +46,7 @@ use js::rust::with_compartment;
use js::{JSPROP_ENUMERATE, JSPROP_READONLY, JSPROP_PERMANENT};
use js::JSFUN_CONSTRUCTOR;
use js;
use string_cache::{Atom, Namespace};
/// Proxy handler for a WindowProxy.
pub struct WindowProxyHandler(pub *const libc::c_void);
@ -604,6 +608,68 @@ pub unsafe fn delete_property_by_id(cx: *mut JSContext, object: *mut JSObject,
return true;
}
/// Validate a qualified name. See https://dom.spec.whatwg.org/#validate for details.
pub fn validate_qualified_name(qualified_name: &str) -> ErrorResult {
match xml_name_type(qualified_name) {
XMLName::InvalidXMLName => {
// Step 1.
return Err(Error::InvalidCharacter);
},
XMLName::Name => {
// Step 2.
return Err(Error::Namespace);
},
XMLName::QName => Ok(())
}
}
/// Validate a namespace and qualified name and extract their parts.
/// See https://dom.spec.whatwg.org/#validate-and-extract for details.
pub fn validate_and_extract(namespace: Option<DOMString>, qualified_name: &str)
-> Fallible<(Namespace, Option<DOMString>, Atom)> {
// Step 1.
let namespace = namespace::from_domstring(namespace);
// Step 2.
try!(validate_qualified_name(qualified_name));
let (prefix, local_name) = if qualified_name.contains(":") {
// Step 5.
let mut parts = qualified_name.splitn(1, ':');
let prefix = parts.next().unwrap();
debug_assert!(!prefix.is_empty());
let local_name = parts.next().unwrap();
debug_assert!(!local_name.contains(":"));
(Some(prefix), local_name)
} else {
(None, qualified_name)
};
match (namespace, prefix) {
(ns!(""), Some(_)) => {
// Step 6.
Err(Error::Namespace)
},
(ref ns, Some("xml")) if ns != &ns!(XML) => {
// Step 7.
Err(Error::Namespace)
},
(ref ns, p) if ns != &ns!(XMLNS) &&
(qualified_name == "xmlns" || p == Some("xmlns")) => {
// Step 8.
Err(Error::Namespace)
},
(ns!(XMLNS), p) if qualified_name != "xmlns" && p != Some("xmlns") => {
// Step 9.
Err(Error::Namespace)
},
(ns, p) => {
// Step 10.
Ok((ns, p.map(|s| s.to_owned()), Atom::from_slice(local_name)))
}
}
}
/// Results of `xml_name_type`.
#[derive(PartialEq)]
#[allow(missing_docs)]

View file

@ -53,6 +53,7 @@ pub struct CanvasRenderingContext2D {
image_smoothing_enabled: Cell<bool>,
stroke_color: Cell<RGBA>,
line_width: Cell<f64>,
miter_limit: Cell<f64>,
fill_color: Cell<RGBA>,
transform: Cell<Matrix2D<f32>>,
}
@ -75,6 +76,7 @@ impl CanvasRenderingContext2D {
image_smoothing_enabled: Cell::new(true),
stroke_color: Cell::new(black),
line_width: Cell::new(1.0),
miter_limit: Cell::new(10.0),
fill_color: Cell::new(black),
transform: Cell::new(Matrix2D::identity()),
}
@ -258,6 +260,18 @@ impl CanvasRenderingContext2D {
_ => panic!("Image Cache: Unknown Result")
}
}
fn create_drawable_rect(&self, x: f64, y: f64, w: f64, h: f64) -> Option<Rect<f32>> {
if !([x, y, w, h].iter().all(|val| val.is_finite())) {
return None;
}
if w == 0.0 && h == 0.0 {
return None;
}
Some(Rect(Point2D(x as f32, y as f32), Size2D(w as f32, h as f32)))
}
}
pub trait CanvasRenderingContext2DHelpers {
@ -358,34 +372,22 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
}
fn FillRect(self, x: f64, y: f64, width: f64, height: f64) {
if !(x.is_finite() && y.is_finite() &&
width.is_finite() && height.is_finite()) {
return;
}
let rect = Rect(Point2D(x as f32, y as f32), Size2D(width as f32, height as f32));
if let Some(rect) = self.create_drawable_rect(x, y, width, height) {
self.renderer.send(CanvasMsg::FillRect(rect)).unwrap();
}
}
fn ClearRect(self, x: f64, y: f64, width: f64, height: f64) {
if !(x.is_finite() && y.is_finite() &&
width.is_finite() && height.is_finite()) {
return;
}
let rect = Rect(Point2D(x as f32, y as f32), Size2D(width as f32, height as f32));
if let Some(rect) = self.create_drawable_rect(x, y, width, height) {
self.renderer.send(CanvasMsg::ClearRect(rect)).unwrap();
}
}
fn StrokeRect(self, x: f64, y: f64, width: f64, height: f64) {
if !(x.is_finite() && y.is_finite() &&
width.is_finite() && height.is_finite()) {
return;
}
let rect = Rect(Point2D(x as f32, y as f32), Size2D(width as f32, height as f32));
if let Some(rect) = self.create_drawable_rect(x, y, width, height) {
self.renderer.send(CanvasMsg::StrokeRect(rect)).unwrap();
}
}
fn BeginPath(self) {
self.renderer.send(CanvasMsg::BeginPath).unwrap();
@ -816,6 +818,19 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
self.line_width.set(width);
self.renderer.send(CanvasMsg::SetLineWidth(width as f32)).unwrap()
}
fn MiterLimit(self) -> f64 {
self.miter_limit.get()
}
fn SetMiterLimit(self, limit: f64) {
if !limit.is_finite() || limit <= 0.0 {
return;
}
self.miter_limit.set(limit);
self.renderer.send(CanvasMsg::SetMiterLimit(limit as f32)).unwrap()
}
}
#[unsafe_destructor]

View file

@ -6,11 +6,13 @@
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods;
use dom::bindings::codegen::InheritTypes::{CharacterDataDerived, NodeCast};
use dom::bindings::codegen::InheritTypes::{CharacterDataDerived, ElementCast};
use dom::bindings::codegen::InheritTypes::NodeCast;
use dom::bindings::error::{Fallible, ErrorResult};
use dom::bindings::error::Error::IndexSize;
use dom::bindings::js::JSRef;
use dom::bindings::js::{JSRef, LayoutJS, Temporary};
use dom::document::Document;
use dom::element::Element;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::node::{Node, NodeHelpers, NodeTypeId};
@ -18,6 +20,7 @@ use util::str::DOMString;
use std::borrow::ToOwned;
use std::cell::Ref;
use std::cmp;
#[dom_struct]
pub struct CharacterData {
@ -43,67 +46,59 @@ impl CharacterData {
data: DOMRefCell::new(data),
}
}
#[inline]
pub fn node<'a>(&'a self) -> &'a Node {
&self.node
}
#[inline]
pub fn data(&self) -> Ref<DOMString> {
self.data.borrow()
}
#[inline]
pub fn set_data(&self, data: DOMString) {
*self.data.borrow_mut() = data;
}
#[inline]
#[allow(unsafe_code)]
pub unsafe fn data_for_layout<'a>(&'a self) -> &'a str {
self.data.borrow_for_layout().as_slice()
}
}
impl<'a> CharacterDataMethods for JSRef<'a, CharacterData> {
// https://dom.spec.whatwg.org/#dom-characterdata-data
fn Data(self) -> DOMString {
// FIXME(https://github.com/rust-lang/rust/issues/23338)
let data = self.data.borrow();
data.clone()
}
fn SetData(self, arg: DOMString) -> ErrorResult {
*self.data.borrow_mut() = arg;
Ok(())
// https://dom.spec.whatwg.org/#dom-characterdata-data
fn SetData(self, data: DOMString) {
*self.data.borrow_mut() = data;
}
// https://dom.spec.whatwg.org/#dom-characterdata-length
fn Length(self) -> u32 {
// FIXME(https://github.com/rust-lang/rust/issues/23338)
let data = self.data.borrow();
data.chars().count() as u32
}
// https://dom.spec.whatwg.org/#dom-characterdata-substringdata
fn SubstringData(self, offset: u32, count: u32) -> Fallible<DOMString> {
// FIXME(https://github.com/rust-lang/rust/issues/23338)
let data = self.data.borrow();
Ok(data.slice_chars(offset as usize, (offset + count) as usize).to_owned())
// Step 1.
let len = data.chars().count();
if len > offset as usize {
// Step 2.
return Err(IndexSize);
}
// Step 3.
let end = cmp::min((offset + count) as usize, len);
// Step 4.
Ok(data.slice_chars(offset as usize, end).to_owned())
}
fn AppendData(self, arg: DOMString) -> ErrorResult {
self.data.borrow_mut().push_str(arg.as_slice());
Ok(())
// https://dom.spec.whatwg.org/#dom-characterdata-appenddata
fn AppendData(self, data: DOMString) {
self.data.borrow_mut().push_str(&data);
}
// https://dom.spec.whatwg.org/#dom-characterdata-insertdata
fn InsertData(self, offset: u32, arg: DOMString) -> ErrorResult {
self.ReplaceData(offset, 0, arg)
}
// https://dom.spec.whatwg.org/#dom-characterdata-deletedata
fn DeleteData(self, offset: u32, count: u32) -> ErrorResult {
self.ReplaceData(offset, count, "".to_owned())
}
// https://dom.spec.whatwg.org/#dom-characterdata-replacedata
fn ReplaceData(self, offset: u32, count: u32, arg: DOMString) -> ErrorResult {
let length = self.data.borrow().chars().count() as u32;
if offset > length {
@ -127,5 +122,40 @@ impl<'a> CharacterDataMethods for JSRef<'a, CharacterData> {
let node: JSRef<Node> = NodeCast::from_ref(self);
node.remove_self();
}
// https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-previouselementsibling
fn GetPreviousElementSibling(self) -> Option<Temporary<Element>> {
NodeCast::from_ref(self).preceding_siblings()
.filter_map(ElementCast::to_temporary).next()
}
// https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-nextelementsibling
fn GetNextElementSibling(self) -> Option<Temporary<Element>> {
NodeCast::from_ref(self).following_siblings()
.filter_map(ElementCast::to_temporary).next()
}
}
pub trait CharacterDataHelpers<'a> {
fn data(self) -> Ref<'a, DOMString>;
}
impl<'a> CharacterDataHelpers<'a> for JSRef<'a, CharacterData> {
#[inline]
fn data(self) -> Ref<'a, DOMString> {
self.extended_deref().data.borrow()
}
}
#[allow(unsafe_code)]
pub trait LayoutCharacterDataHelpers {
unsafe fn data_for_layout<'a>(&'a self) -> &'a str;
}
#[allow(unsafe_code)]
impl LayoutCharacterDataHelpers for LayoutJS<CharacterData> {
#[inline]
unsafe fn data_for_layout<'a>(&'a self) -> &'a str {
&(*self.unsafe_get()).data.borrow_for_layout()
}
}

View file

@ -42,10 +42,5 @@ impl Comment {
let document = global.as_window().Document().root();
Ok(Comment::new(data, document.r()))
}
#[inline]
pub fn characterdata<'a>(&'a self) -> &'a CharacterData {
&self.characterdata
}
}

View file

@ -18,23 +18,24 @@ use dom::bindings::codegen::InheritTypes::{EventTargetCast, HTMLAnchorElementCas
use dom::bindings::codegen::InheritTypes::{HTMLAnchorElementDerived, HTMLAppletElementDerived};
use dom::bindings::codegen::InheritTypes::{HTMLAreaElementDerived, HTMLEmbedElementDerived};
use dom::bindings::codegen::InheritTypes::{HTMLFormElementDerived, HTMLImageElementDerived};
use dom::bindings::codegen::InheritTypes::{HTMLScriptElementDerived};
use dom::bindings::codegen::InheritTypes::{HTMLScriptElementDerived, CharacterDataCast};
use dom::bindings::error::{ErrorResult, Fallible};
use dom::bindings::error::Error::{NotSupported, InvalidCharacter, Security};
use dom::bindings::error::Error::{HierarchyRequest, Namespace};
use dom::bindings::error::Error::HierarchyRequest;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{MutNullableJS, JS, JSRef, LayoutJS, Temporary, TemporaryPushable};
use dom::bindings::js::{OptionalRootable, RootedReference};
use dom::bindings::refcounted::Trusted;
use dom::bindings::utils::reflect_dom_object;
use dom::bindings::utils::xml_name_type;
use dom::bindings::utils::XMLName::{QName, Name, InvalidXMLName};
use dom::bindings::utils::{xml_name_type, validate_and_extract};
use dom::bindings::utils::XMLName::InvalidXMLName;
use dom::characterdata::CharacterDataHelpers;
use dom::comment::Comment;
use dom::customevent::CustomEvent;
use dom::documentfragment::DocumentFragment;
use dom::documenttype::DocumentType;
use dom::domimplementation::DOMImplementation;
use dom::element::{Element, ElementCreator, AttributeHandlers, get_attribute_parts};
use dom::element::{Element, ElementCreator, AttributeHandlers};
use dom::element::{ElementTypeId, ActivationElementHelpers};
use dom::event::{Event, EventBubbles, EventCancelable, EventHelpers};
use dom::eventtarget::{EventTarget, EventTargetTypeId, EventTargetHelpers};
@ -67,7 +68,7 @@ use net_traits::CookieSource::NonHTTP;
use net_traits::ControlMsg::{SetCookiesForUrl, GetCookiesForUrl};
use script_task::Runnable;
use script_traits::{MouseButton, UntrustedNodeAddress};
use util::{opts, namespace};
use util::opts;
use util::str::{DOMString, split_html_space_chars};
use layout_interface::{ReflowGoal, ReflowQueryType};
@ -975,45 +976,10 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
fn CreateElementNS(self,
namespace: Option<DOMString>,
qualified_name: DOMString) -> Fallible<Temporary<Element>> {
let ns = namespace::from_domstring(namespace);
match xml_name_type(&qualified_name) {
InvalidXMLName => {
debug!("Not a valid element name");
return Err(InvalidCharacter);
},
Name => {
debug!("Not a valid qualified element name");
return Err(Namespace);
},
QName => {}
}
let (prefix_from_qname, local_name_from_qname) = get_attribute_parts(&qualified_name);
match (&ns, prefix_from_qname, local_name_from_qname) {
// throw if prefix is not null and namespace is null
(&ns!(""), Some(_), _) => {
debug!("Namespace can't be null with a non-null prefix");
return Err(Namespace);
},
// throw if prefix is "xml" and namespace is not the XML namespace
(_, Some(ref prefix), _) if "xml" == *prefix && ns != ns!(XML) => {
debug!("Namespace must be the xml namespace if the prefix is 'xml'");
return Err(Namespace);
},
// throw if namespace is the XMLNS namespace and neither qualifiedName nor prefix is
// "xmlns"
(&ns!(XMLNS), Some(ref prefix), _) if "xmlns" == *prefix => {},
(&ns!(XMLNS), _, "xmlns") => {},
(&ns!(XMLNS), _, _) => {
debug!("The prefix or the qualified name must be 'xmlns' if namespace is the XMLNS namespace ");
return Err(Namespace);
},
_ => {}
}
let name = QualName::new(ns, Atom::from_slice(local_name_from_qname));
Ok(Element::create(name, prefix_from_qname.map(|s| s.to_owned()), self,
ElementCreator::ScriptCreated))
let (namespace, prefix, local_name) =
try!(validate_and_extract(namespace, &qualified_name));
let name = QualName::new(namespace, local_name);
Ok(Element::create(name, prefix, self, ElementCreator::ScriptCreated))
}
// http://dom.spec.whatwg.org/#dom-document-createattribute
@ -1032,6 +998,18 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
Ok(Attr::new(window.r(), name, value, l_name, ns!(""), None, None))
}
// http://dom.spec.whatwg.org/#dom-document-createattributens
fn CreateAttributeNS(self, namespace: Option<DOMString>, qualified_name: DOMString)
-> Fallible<Temporary<Attr>> {
let (namespace, prefix, local_name) =
try!(validate_and_extract(namespace, &qualified_name));
let window = self.window.root();
let value = AttrValue::String("".to_owned());
let qualified_name = Atom::from_slice(&qualified_name);
Ok(Attr::new(window.r(), local_name, value, qualified_name,
namespace, prefix, None))
}
// http://dom.spec.whatwg.org/#dom-document-createdocumentfragment
fn CreateDocumentFragment(self) -> Temporary<DocumentFragment> {
DocumentFragment::new(self)
@ -1148,7 +1126,7 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
for child in title_element.children() {
let child = child.root();
if let Some(text) = TextCast::to_ref(child.r()) {
title.push_str(&text.characterdata().data());
title.push_str(&CharacterDataCast::from_ref(text).data());
}
}
}

View file

@ -8,12 +8,10 @@ use dom::bindings::codegen::Bindings::DOMImplementationBinding::DOMImplementatio
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::codegen::InheritTypes::NodeCast;
use dom::bindings::error::Fallible;
use dom::bindings::error::Error::{InvalidCharacter, Namespace};
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, Root, Temporary, OptionalRootable};
use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::bindings::utils::xml_name_type;
use dom::bindings::utils::XMLName::{QName, Name, InvalidXMLName};
use dom::bindings::utils::validate_qualified_name;
use dom::document::{Document, DocumentHelpers, IsHTMLDocument};
use dom::document::DocumentSource;
use dom::documenttype::DocumentType;
@ -52,18 +50,11 @@ impl DOMImplementation {
// http://dom.spec.whatwg.org/#domimplementation
impl<'a> DOMImplementationMethods for JSRef<'a, DOMImplementation> {
// http://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype
fn CreateDocumentType(self, qname: DOMString, pubid: DOMString, sysid: DOMString) -> Fallible<Temporary<DocumentType>> {
match xml_name_type(&qname) {
// Step 1.
InvalidXMLName => Err(InvalidCharacter),
// Step 2.
Name => Err(Namespace),
// Step 3.
QName => {
fn CreateDocumentType(self, qualified_name: DOMString, pubid: DOMString, sysid: DOMString)
-> Fallible<Temporary<DocumentType>> {
try!(validate_qualified_name(&qualified_name));
let document = self.document.root();
Ok(DocumentType::new(qname, Some(pubid), Some(sysid), document.r()))
}
}
Ok(DocumentType::new(qualified_name, Some(pubid), Some(sysid), document.r()))
}
// http://dom.spec.whatwg.org/#dom-domimplementation-createdocument

View file

@ -24,14 +24,13 @@ use dom::bindings::codegen::InheritTypes::{HTMLTableRowElementDerived, HTMLTextA
use dom::bindings::codegen::InheritTypes::{HTMLTableSectionElementDerived, NodeCast};
use dom::bindings::codegen::InheritTypes::HTMLAnchorElementCast;
use dom::bindings::error::{ErrorResult, Fallible};
use dom::bindings::error::Error;
use dom::bindings::error::Error::{InvalidCharacter, Syntax};
use dom::bindings::error::Error::NoModificationAllowed;
use dom::bindings::js::{MutNullableJS, JS, JSRef, LayoutJS, Temporary, TemporaryPushable};
use dom::bindings::js::{OptionalRootable, RootedReference};
use dom::bindings::trace::RootedVec;
use dom::bindings::utils::xml_name_type;
use dom::bindings::utils::XMLName::{QName, Name, InvalidXMLName};
use dom::bindings::utils::{xml_name_type, validate_and_extract};
use dom::bindings::utils::XMLName::InvalidXMLName;
use dom::create::create_element;
use dom::domrect::DOMRect;
use dom::domrectlist::DOMRectList;
@ -1037,58 +1036,14 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
// http://dom.spec.whatwg.org/#dom-element-setattributens
fn SetAttributeNS(self,
namespace_url: Option<DOMString>,
name: DOMString,
namespace: Option<DOMString>,
qualified_name: DOMString,
value: DOMString) -> ErrorResult {
// Step 1.
let namespace = namespace::from_domstring(namespace_url);
let name_type = xml_name_type(&name);
match name_type {
// Step 2.
InvalidXMLName => return Err(InvalidCharacter),
// Step 3.
Name => return Err(Error::Namespace),
QName => {}
}
// Step 4.
let (prefix, local_name) = get_attribute_parts(&name);
if let Some(ref prefix_str) = prefix {
// Step 5.
if namespace == ns!("") {
return Err(Error::Namespace);
}
// Step 6.
if "xml" == *prefix_str && namespace != ns!(XML) {
return Err(Error::Namespace);
}
// Step 7b.
if "xmlns" == *prefix_str && namespace != ns!(XMLNS) {
return Err(Error::Namespace);
}
}
let name = Atom::from_slice(&name);
let local_name = Atom::from_slice(local_name);
let xmlns = atom!("xmlns");
// Step 7a.
if xmlns == name && namespace != ns!(XMLNS) {
return Err(Error::Namespace);
}
// Step 8.
if namespace == ns!(XMLNS) && xmlns != name && Some("xmlns") != prefix {
return Err(Error::Namespace);
}
// Step 9.
let (namespace, prefix, local_name) =
try!(validate_and_extract(namespace, &qualified_name));
let qualified_name = Atom::from_slice(&qualified_name);
let value = self.parse_attribute(&namespace, &local_name, value);
self.do_set_attribute(local_name.clone(), value, name,
self.do_set_attribute(local_name.clone(), value, qualified_name,
namespace.clone(), prefix.map(|s| s.to_owned()),
|attr| {
*attr.local_name() == local_name &&
@ -1223,6 +1178,18 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
Ok(())
}
// https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-previouselementsibling
fn GetPreviousElementSibling(self) -> Option<Temporary<Element>> {
NodeCast::from_ref(self).preceding_siblings()
.filter_map(ElementCast::to_temporary).next()
}
// https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-nextelementsibling
fn GetNextElementSibling(self) -> Option<Temporary<Element>> {
NodeCast::from_ref(self).following_siblings()
.filter_map(ElementCast::to_temporary).next()
}
// http://dom.spec.whatwg.org/#dom-parentnode-children
fn Children(self) -> Temporary<HTMLCollection> {
let window = window_from_node(self).root();
@ -1293,17 +1260,6 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
}
}
pub fn get_attribute_parts<'a>(name: &'a str) -> (Option<&'a str>, &'a str) {
//FIXME: Throw for XML-invalid names
//FIXME: Throw for XMLNS-invalid names
if name.contains(":") {
let mut parts = name.splitn(1, ':');
(Some(parts.next().unwrap()), parts.next().unwrap())
} else {
(None, name)
}
}
impl<'a> VirtualMethods for JSRef<'a, Element> {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let node: &JSRef<Node> = NodeCast::from_borrowed_ref(self);

View file

@ -524,8 +524,7 @@ impl<'a> HTMLScriptElementMethods for JSRef<'a, HTMLScriptElement> {
// http://www.whatwg.org/html/#dom-script-text
fn Text(self) -> DOMString {
let node: JSRef<Node> = NodeCast::from_ref(self);
Node::collect_text_contents(node.children().map(|c| c.root()).map(|c| c.get_unsound_ref_forever()))
Node::collect_text_contents(NodeCast::from_ref(self).children())
}
// http://www.whatwg.org/html/#dom-script-text

View file

@ -6,8 +6,9 @@ use dom::bindings::codegen::Bindings::HTMLTitleElementBinding;
use dom::bindings::codegen::Bindings::HTMLTitleElementBinding::HTMLTitleElementMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLTitleElementDerived, NodeCast};
use dom::bindings::codegen::InheritTypes::{TextCast};
use dom::bindings::codegen::InheritTypes::{CharacterDataCast, TextCast};
use dom::bindings::js::{JSRef, Temporary};
use dom::characterdata::CharacterDataHelpers;
use dom::document::{Document, DocumentHelpers};
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId;
@ -51,7 +52,7 @@ impl<'a> HTMLTitleElementMethods for JSRef<'a, HTMLTitleElement> {
let child = child.root();
let text: Option<JSRef<Text>> = TextCast::to_ref(child.r());
match text {
Some(text) => content.push_str(text.characterdata().data().as_slice()),
Some(text) => content.push_str(&CharacterDataCast::from_ref(text).data()),
None => (),
}
}

View file

@ -315,6 +315,7 @@ pub mod servohtmlparser;
pub mod storage;
pub mod storageevent;
pub mod text;
pub mod textdecoder;
pub mod textencoder;
pub mod treewalker;
pub mod uievent;

View file

@ -13,12 +13,11 @@ use dom::bindings::codegen::Bindings::NamedNodeMapBinding::NamedNodeMapMethods;
use dom::bindings::codegen::Bindings::NodeBinding::{NodeConstants, NodeMethods};
use dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods;
use dom::bindings::codegen::Bindings::ProcessingInstructionBinding::ProcessingInstructionMethods;
use dom::bindings::codegen::InheritTypes::{CommentCast, DocumentCast, DocumentTypeCast};
use dom::bindings::codegen::InheritTypes::{ElementCast, TextCast, NodeCast, ElementDerived};
use dom::bindings::codegen::InheritTypes::{CharacterDataCast, NodeBase, NodeDerived};
use dom::bindings::codegen::InheritTypes::{ProcessingInstructionCast, EventTargetCast};
use dom::bindings::codegen::InheritTypes::{CharacterDataCast, DocumentCast, DocumentTypeCast};
use dom::bindings::codegen::InheritTypes::{ElementCast, NodeCast, ElementDerived, EventTargetCast};
use dom::bindings::codegen::InheritTypes::{HTMLLegendElementDerived, HTMLFieldSetElementDerived};
use dom::bindings::codegen::InheritTypes::HTMLOptGroupElementDerived;
use dom::bindings::codegen::InheritTypes::{HTMLOptGroupElementDerived, NodeBase, NodeDerived};
use dom::bindings::codegen::InheritTypes::{ProcessingInstructionCast, TextCast};
use dom::bindings::conversions;
use dom::bindings::error::Fallible;
use dom::bindings::error::Error::{NotFound, HierarchyRequest, Syntax};
@ -29,7 +28,7 @@ use dom::bindings::js::{ResultRootable, OptionalRootable, MutNullableJS};
use dom::bindings::trace::JSTraceable;
use dom::bindings::trace::RootedVec;
use dom::bindings::utils::{Reflectable, reflect_dom_object};
use dom::characterdata::CharacterData;
use dom::characterdata::{CharacterData, CharacterDataHelpers};
use dom::comment::Comment;
use dom::document::{Document, DocumentHelpers, IsHTMLDocument, DocumentSource};
use dom::documentfragment::DocumentFragment;
@ -415,6 +414,7 @@ pub trait NodeHelpers<'a> {
fn rev_children(self) -> ReverseChildrenIterator;
fn child_elements(self) -> ChildElementIterator;
fn following_siblings(self) -> NodeSiblingIterator;
fn preceding_siblings(self) -> ReverseChildrenIterator;
fn is_in_doc(self) -> bool;
fn is_inclusive_ancestor_of(self, parent: JSRef<Node>) -> bool;
fn is_parent_of(self, child: JSRef<Node>) -> bool;
@ -764,6 +764,12 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
}
}
fn preceding_siblings(self) -> ReverseChildrenIterator {
ReverseChildrenIterator {
current: self.prev_sibling(),
}
}
fn is_parent_of(self, child: JSRef<Node>) -> bool {
match child.parent_node() {
Some(ref parent) if parent == &Temporary::from_rooted(self) => true,
@ -1594,8 +1600,8 @@ impl Node {
NodeCast::from_temporary(doc_fragment)
},
NodeTypeId::Comment => {
let comment: JSRef<Comment> = CommentCast::to_ref(node).unwrap();
let comment = Comment::new(comment.characterdata().data().clone(), document.r());
let cdata = CharacterDataCast::to_ref(node).unwrap();
let comment = Comment::new(cdata.Data(), document.r());
NodeCast::from_temporary(comment)
},
NodeTypeId::Document => {
@ -1622,14 +1628,14 @@ impl Node {
NodeCast::from_temporary(element)
},
NodeTypeId::Text => {
let text: JSRef<Text> = TextCast::to_ref(node).unwrap();
let text = Text::new(text.characterdata().data().clone(), document.r());
let cdata = CharacterDataCast::to_ref(node).unwrap();
let text = Text::new(cdata.Data(), document.r());
NodeCast::from_temporary(text)
},
NodeTypeId::ProcessingInstruction => {
let pi: JSRef<ProcessingInstruction> = ProcessingInstructionCast::to_ref(node).unwrap();
let pi = ProcessingInstruction::new(pi.target().clone(),
pi.characterdata().data().clone(), document.r());
CharacterDataCast::from_ref(pi).Data(), document.r());
NodeCast::from_temporary(pi)
},
}.root();
@ -1683,12 +1689,13 @@ impl Node {
Temporary::from_rooted(copy.r())
}
pub fn collect_text_contents<'a, T: Iterator<Item=JSRef<'a, Node>>>(iterator: T) -> String {
pub fn collect_text_contents<T: Iterator<Item=Temporary<Node>>>(iterator: T) -> String {
let mut content = String::new();
for node in iterator {
let text: Option<JSRef<Text>> = TextCast::to_ref(node);
let node = node.root();
let text = TextCast::to_ref(node.r());
match text {
Some(text) => content.push_str(text.characterdata().data().as_slice()),
Some(text) => content.push_str(&CharacterDataCast::from_ref(text).Data()),
None => (),
}
}
@ -1834,7 +1841,8 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
match self.type_id {
NodeTypeId::DocumentFragment |
NodeTypeId::Element(..) => {
let content = Node::collect_text_contents(self.traverse_preorder());
let content = Node::collect_text_contents(
self.traverse_preorder().map(Temporary::from_rooted));
Some(content)
}
NodeTypeId::Comment |
@ -1871,7 +1879,7 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
NodeTypeId::Text |
NodeTypeId::ProcessingInstruction => {
let characterdata: JSRef<CharacterData> = CharacterDataCast::to_ref(self).unwrap();
characterdata.set_data(value);
characterdata.SetData(value);
// Notify the document that the content of this node is different
let document = self.owner_doc().root();
@ -2114,7 +2122,7 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
let pi: JSRef<ProcessingInstruction> = ProcessingInstructionCast::to_ref(node).unwrap();
let other_pi: JSRef<ProcessingInstruction> = ProcessingInstructionCast::to_ref(other).unwrap();
(*pi.target() == *other_pi.target()) &&
(*pi.characterdata().data() == *other_pi.characterdata().data())
(*CharacterDataCast::from_ref(pi).data() == *CharacterDataCast::from_ref(other_pi).data())
}
fn is_equal_characterdata(node: JSRef<Node>, other: JSRef<Node>) -> bool {
let characterdata: JSRef<CharacterData> = CharacterDataCast::to_ref(node).unwrap();

View file

@ -38,10 +38,6 @@ impl ProcessingInstruction {
document, ProcessingInstructionBinding::Wrap)
}
pub fn characterdata<'a>(&'a self) -> &'a CharacterData {
&self.characterdata
}
pub fn target<'a>(&'a self) -> &'a DOMString {
&self.target
}

View file

@ -42,10 +42,5 @@ impl Text {
let document = global.as_window().Document().root();
Ok(Text::new(text, document.r()))
}
#[inline]
pub fn characterdata<'a>(&'a self) -> &'a CharacterData {
&self.characterdata
}
}

View file

@ -0,0 +1,99 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::codegen::Bindings::TextDecoderBinding;
use dom::bindings::codegen::Bindings::TextDecoderBinding::TextDecoderMethods;
use dom::bindings::error::{Error, Fallible};
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::str::USVString;
use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::{Reflector, reflect_dom_object};
use util::str::DOMString;
use encoding::Encoding;
use encoding::types::{EncodingRef, DecoderTrap};
use encoding::label::encoding_from_whatwg_label;
use js::jsapi::{JSContext, JSObject};
use js::jsfriendapi::bindgen::JS_GetObjectAsArrayBufferView;
use std::borrow::ToOwned;
use std::ptr;
use std::slice;
#[dom_struct]
pub struct TextDecoder {
reflector_: Reflector,
encoding: EncodingRef,
fatal: bool,
}
impl TextDecoder {
fn new_inherited(encoding: EncodingRef, fatal: bool) -> TextDecoder {
TextDecoder {
reflector_: Reflector::new(),
encoding: encoding,
fatal: fatal,
}
}
pub fn new(global: GlobalRef, encoding: EncodingRef, fatal: bool) -> Temporary<TextDecoder> {
reflect_dom_object(box TextDecoder::new_inherited(encoding, fatal),
global,
TextDecoderBinding::Wrap)
}
/// https://encoding.spec.whatwg.org/#dom-textdecoder
pub fn Constructor(global: GlobalRef,
label: DOMString,
options: &TextDecoderBinding::TextDecoderOptions)
-> Fallible<Temporary<TextDecoder>> {
let encoding = match encoding_from_whatwg_label(&label) {
Some(enc) => enc,
// FIXME: Should throw a RangeError as per spec
None => return Err(Error::Syntax),
};
Ok(TextDecoder::new(global, encoding, options.fatal))
}
}
impl<'a> TextDecoderMethods for JSRef<'a, TextDecoder> {
fn Encoding(self) -> DOMString {
self.encoding.whatwg_name().unwrap().to_owned()
}
fn Fatal(self) -> bool {
self.fatal
}
#[allow(unsafe_code)]
fn Decode(self, cx: *mut JSContext, input: Option<*mut JSObject>)
-> Fallible<USVString> {
let input = match input {
Some(input) => input,
None => return Ok(USVString("".to_owned())),
};
let mut length = 0;
let mut data = ptr::null_mut();
if unsafe { JS_GetObjectAsArrayBufferView(cx, input, &mut length, &mut data).is_null() } {
return Err(Error::Type("Argument to TextDecoder.decode is not an ArrayBufferView".to_owned()));
}
let buffer = unsafe {
slice::from_raw_parts(data as *const _, length as usize)
};
let trap = if self.fatal {
DecoderTrap::Strict
} else {
DecoderTrap::Replace
};
match self.encoding.decode(buffer, trap) {
Ok(s) => Ok(USVString(s)),
Err(_) => Err(Error::Type("Decoding failed".to_owned())),
}
}
}

View file

@ -136,7 +136,7 @@ interface CanvasDrawingStyles {
attribute unrestricted double lineWidth; // (default 1)
//attribute DOMString lineCap; // "butt", "round", "square" (default "butt")
//attribute DOMString lineJoin; // "round", "bevel", "miter" (default "miter")
//attribute unrestricted double miterLimit; // (default 10)
attribute unrestricted double miterLimit; // (default 10)
// dashed lines
//void setLineDash(sequence<unrestricted double> segments); // default empty

View file

@ -11,11 +11,10 @@
*/
interface CharacterData : Node {
[TreatNullAs=EmptyString,SetterThrows] attribute DOMString data;
[TreatNullAs=EmptyString] attribute DOMString data;
readonly attribute unsigned long length;
[Throws]
DOMString substringData(unsigned long offset, unsigned long count);
[Throws]
void appendData(DOMString data);
[Throws]
void insertData(unsigned long offset, DOMString data);
@ -26,3 +25,4 @@ interface CharacterData : Node {
};
CharacterData implements ChildNode;
CharacterData implements NonDocumentTypeChildNode;

View file

@ -16,10 +16,10 @@ interface ChildNode {
void remove();
};
// [NoInterfaceObject]
// interface NonDocumentTypeChildNode {
// [Pure]
// readonly attribute Element? previousElementSibling;
// [Pure]
// readonly attribute Element? nextElementSibling;
// };
[NoInterfaceObject]
interface NonDocumentTypeChildNode {
[Pure]
readonly attribute Element? previousElementSibling;
[Pure]
readonly attribute Element? nextElementSibling;
};

View file

@ -27,27 +27,33 @@ interface Document : Node {
HTMLCollection getElementsByClassName(DOMString classNames);
Element? getElementById(DOMString elementId);
[Throws]
[NewObject, Throws]
Element createElement(DOMString localName);
[Throws]
[NewObject, Throws]
Element createElementNS(DOMString? namespace, DOMString qualifiedName);
[NewObject]
DocumentFragment createDocumentFragment();
[NewObject]
Text createTextNode(DOMString data);
[NewObject]
Comment createComment(DOMString data);
[Throws]
[NewObject, Throws]
ProcessingInstruction createProcessingInstruction(DOMString target, DOMString data);
[Throws]
Attr createAttribute(DOMString localName);
[Throws]
[NewObject, Throws]
Node importNode(Node node, optional boolean deep = false);
[Throws]
Node adoptNode(Node node);
[Throws]
[NewObject, Throws]
Attr createAttribute(DOMString localName);
[NewObject, Throws]
Attr createAttributeNS(DOMString? namespace, DOMString localName);
[NewObject, Throws]
Event createEvent(DOMString interface_);
[NewObject]
Range createRange();
// NodeFilter.SHOW_ALL = 0xFFFFFFFF

View file

@ -70,4 +70,5 @@ partial interface Element {
};
Element implements ChildNode;
Element implements NonDocumentTypeChildNode;
Element implements ParentNode;

View file

@ -0,0 +1,21 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
// https://encoding.spec.whatwg.org/#interface-textdecoder
dictionary TextDecoderOptions {
boolean fatal = false;
//boolean ignoreBOM = false;
};
[Constructor(optional DOMString label = "utf-8", optional TextDecoderOptions options)/*,
Exposed=Window,Worker*/]
interface TextDecoder {
readonly attribute DOMString encoding;
readonly attribute boolean fatal;
//readonly attribute boolean ignoreBOM;
//USVString decode(optional BufferSource input, optional TextDecodeOptions options);
[Throws]
USVString decode(optional object input);
};

View file

@ -7,13 +7,14 @@
use dom::attr::AttrHelpers;
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, HTMLScriptElementCast};
use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, TextCast, CommentCast};
use dom::bindings::codegen::InheritTypes::{CharacterDataCast, DocumentTypeCast};
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLScriptElementCast};
use dom::bindings::codegen::InheritTypes::{HTMLFormElementDerived, NodeCast};
use dom::bindings::codegen::InheritTypes::ProcessingInstructionCast;
use dom::bindings::codegen::InheritTypes::HTMLFormElementDerived;
use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable, Root};
use dom::bindings::js::RootedReference;
use dom::bindings::trace::RootedVec;
use dom::characterdata::CharacterDataHelpers;
use dom::comment::Comment;
use dom::document::{Document, DocumentHelpers};
use dom::document::{DocumentSource, IsHTMLDocument};
@ -234,22 +235,19 @@ impl<'a> Serializable for JSRef<'a, Node> {
},
(IncludeNode, NodeTypeId::Text) => {
let text: JSRef<Text> = TextCast::to_ref(node).unwrap();
let data = text.characterdata().data();
serializer.write_text(data.as_slice())
let cdata = CharacterDataCast::to_ref(node).unwrap();
serializer.write_text(&cdata.data())
},
(IncludeNode, NodeTypeId::Comment) => {
let comment: JSRef<Comment> = CommentCast::to_ref(node).unwrap();
let data = comment.characterdata().data();
serializer.write_comment(data.as_slice())
let cdata = CharacterDataCast::to_ref(node).unwrap();
serializer.write_comment(&cdata.data())
},
(IncludeNode, NodeTypeId::ProcessingInstruction) => {
let pi: JSRef<ProcessingInstruction> = ProcessingInstructionCast::to_ref(node).unwrap();
let data = pi.characterdata().data();
serializer.write_processing_instruction(pi.target().as_slice(),
data.as_slice())
let data = CharacterDataCast::from_ref(pi).data();
serializer.write_processing_instruction(&pi.target(), &data)
},
(IncludeNode, NodeTypeId::DocumentFragment) => Ok(()),

View file

@ -479,7 +479,7 @@ dependencies = [
[[package]]
name = "js"
version = "0.1.0"
source = "git+https://github.com/servo/rust-mozjs#879b256e6bc5b38f792b68da130eb7a70633769b"
source = "git+https://github.com/servo/rust-mozjs#9512c3c770774ed73a2fdcc635eee178cbd02ab1"
dependencies = [
"libc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"mozjs_sys 0.0.0 (git+https://github.com/servo/mozjs)",
@ -617,7 +617,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "mozjs_sys"
version = "0.0.0"
source = "git+https://github.com/servo/mozjs#40e0680008cb129ddf9ccf40c6b0095e14d1cd97"
source = "git+https://github.com/servo/mozjs#19edb950930f03f0ad305ffbd9548b92fdb0a250"
[[package]]
name = "msg"

View file

@ -39,7 +39,12 @@ pub fn null_str_as_empty_ref<'a>(s: &'a Option<DOMString>) -> &'a str {
const WHITESPACE: &'static [char] = &[' ', '\t', '\x0a', '\x0c', '\x0d'];
pub fn is_whitespace(s: &str) -> bool {
s.chars().all(|c| WHITESPACE.contains(&c))
s.chars().all(char_is_whitespace)
}
#[inline]
pub fn char_is_whitespace(c: char) -> bool {
WHITESPACE.contains(&c)
}
/// A "space character" according to:

4
ports/cef/Cargo.lock generated
View file

@ -482,7 +482,7 @@ dependencies = [
[[package]]
name = "js"
version = "0.1.0"
source = "git+https://github.com/servo/rust-mozjs#879b256e6bc5b38f792b68da130eb7a70633769b"
source = "git+https://github.com/servo/rust-mozjs#9512c3c770774ed73a2fdcc635eee178cbd02ab1"
dependencies = [
"libc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"mozjs_sys 0.0.0 (git+https://github.com/servo/mozjs)",
@ -620,7 +620,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "mozjs_sys"
version = "0.0.0"
source = "git+https://github.com/servo/mozjs#40e0680008cb129ddf9ccf40c6b0095e14d1cd97"
source = "git+https://github.com/servo/mozjs#19edb950930f03f0ad305ffbd9548b92fdb0a250"
[[package]]
name = "msg"

View file

@ -32,9 +32,11 @@ use types::{cef_window_info_t, cef_xml_encoding_type_t, cef_xml_node_type_t};
use unicode::str::Utf16Encoder;
use libc::{self, c_char, c_int, c_ushort, c_void};
use std::boxed;
use std::collections::HashMap;
use std::mem;
use std::ptr;
use std::raw;
pub trait CefWrap<CObject> {
fn to_c(rust_object: Self) -> CObject;
@ -61,7 +63,7 @@ macro_rules! cef_pointer_wrapper(
rust_object
}
unsafe fn to_rust(c_object: *const $ty) -> &'a $ty {
mem::transmute::<*const $ty,&'a $ty>(c_object)
&*c_object
}
}
impl<'a> CefWrap<*mut $ty> for &'a mut $ty {
@ -69,7 +71,7 @@ macro_rules! cef_pointer_wrapper(
rust_object
}
unsafe fn to_rust(c_object: *mut $ty) -> &'a mut $ty {
mem::transmute::<*mut $ty,&'a mut $ty>(c_object)
&mut *c_object
}
}
cef_noop_wrapper!(*const $ty);
@ -187,19 +189,18 @@ impl<'a> CefWrap<*const cef_string_t> for &'a [u16] {
// FIXME(pcwalton): This leaks!! We should instead have the caller pass some scratch
// stack space to create the object in. What a botch.
let boxed_string = box cef_string_utf16 {
boxed::into_raw(box cef_string_utf16 {
str: ptr,
length: buffer.len() as u64,
dtor: Some(free_boxed_utf16_string as extern "C" fn(*mut c_ushort)),
};
let result: *const cef_string_utf16 = &*boxed_string;
mem::forget(boxed_string);
result
}) as *const _
}
}
unsafe fn to_rust(cef_string: *const cef_string_t) -> &'a [u16] {
let (ptr, len): (*mut c_ushort, uint) = ((*cef_string).str, (*cef_string).length as uint);
mem::transmute((ptr, len))
mem::transmute(raw::Slice {
data: (*cef_string).str,
len: (*cef_string).length as usize,
})
}
}
@ -214,8 +215,7 @@ impl<'a> CefWrap<*mut cef_string_t> for &'a mut [u16] {
panic!("unimplemented CEF type conversion: &'a str")
}
unsafe fn to_rust(_: *mut cef_string_t) -> &'a mut [u16] {
mem::transmute::<(int,int),_>(panic!("unimplemented CEF type conversion: *mut \
cef_string_t"))
panic!("unimplemented CEF type conversion: *mut cef_string_t")
}
}
@ -245,19 +245,18 @@ impl<'a> CefWrap<cef_string_userfree_t> for String {
let boxed_string;
unsafe {
let buffer = libc::malloc((mem::size_of::<c_ushort>() as u64) *
((utf16_chars.len() + 1) as u64 + 1)) as *mut u16;
let buffer = libc::malloc((mem::size_of::<c_ushort>() as libc::size_t) *
((utf16_chars.len() + 1) as libc::size_t)) as *mut u16;
for (i, ch) in utf16_chars.iter().enumerate() {
*buffer.offset(i as int) = *ch
}
*buffer.offset(utf16_chars.len() as int) = 0;
boxed_string = libc::malloc(mem::size_of::<cef_string_utf16>() as u64) as
boxed_string = libc::malloc(mem::size_of::<cef_string_utf16>() as libc::size_t) as
*mut cef_string_utf16;
ptr::write(&mut (*boxed_string).str, buffer);
ptr::write(&mut (*boxed_string).length, utf16_chars.len() as u64);
ptr::write(&mut (*boxed_string).dtor, Some(free_utf16_buffer as extern "C" fn(*mut c_ushort)));
mem::forget(utf16_chars);
}
boxed_string
}

4
ports/gonk/Cargo.lock generated
View file

@ -415,7 +415,7 @@ dependencies = [
[[package]]
name = "js"
version = "0.1.0"
source = "git+https://github.com/servo/rust-mozjs#879b256e6bc5b38f792b68da130eb7a70633769b"
source = "git+https://github.com/servo/rust-mozjs#9512c3c770774ed73a2fdcc635eee178cbd02ab1"
dependencies = [
"libc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"mozjs_sys 0.0.0 (git+https://github.com/servo/mozjs)",
@ -545,7 +545,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "mozjs_sys"
version = "0.0.0"
source = "git+https://github.com/servo/mozjs#40e0680008cb129ddf9ccf40c6b0095e14d1cd97"
source = "git+https://github.com/servo/mozjs#19edb950930f03f0ad305ffbd9548b92fdb0a250"
[[package]]
name = "msg"

View file

@ -114,6 +114,7 @@ flaky_cpu == append_style_a.html append_style_b.html
== float_intrinsic_width_a.html float_intrinsic_width_ref.html
== float_right_intrinsic_width_a.html float_right_intrinsic_width_ref.html
== float_table_a.html float_table_ref.html
== float_under_top_margin_a.html float_under_top_margin_ref.html
== floated_generated_content_a.html floated_generated_content_b.html
== floated_list_item_a.html floated_list_item_ref.html
== floated_table_with_margin_a.html floated_table_with_margin_ref.html
@ -151,6 +152,7 @@ flaky_cpu == append_style_a.html append_style_b.html
!= img_simple.html img_simple_ref.html
== img_size_a.html img_size_b.html
== incremental_float_a.html incremental_float_ref.html
== incremental_inline_layout_a.html incremental_inline_layout_ref.html
!= inline_background_a.html inline_background_ref.html
== inline_block_baseline_a.html inline_block_baseline_ref.html
== inline_block_border_a.html inline_block_border_ref.html
@ -184,6 +186,7 @@ flaky_cpu == append_style_a.html append_style_b.html
== legacy_td_bgcolor_attribute_a.html legacy_td_bgcolor_attribute_ref.html
== legacy_td_width_attribute_a.html legacy_td_width_attribute_ref.html
== letter_spacing_a.html letter_spacing_ref.html
== line_breaking_whitespace_collapse_a.html line_breaking_whitespace_collapse_ref.html
== line_height_a.html line_height_ref.html
!= linear_gradients_corners_a.html linear_gradients_corners_ref.html
== linear_gradients_lengths_a.html linear_gradients_lengths_ref.html

View file

@ -19,6 +19,6 @@
<div class="otherprojects">
<div class="otherprojects-item">
</div>
</div>
</div>&nbsp;
</body>
</html>

View file

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<style>
* {
margin: 0;
padding: 0;
}
body {
margin-top: 64px;
}
#foo, #bar {
height: 35px;
width: 35px;
}
#foo {
background: blue;
float: right;
}
#bar {
background: gold;
}
</style>
</head>
<body>
<div id=foo></div><div id=bar></div>
</body>
</html>

View file

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<style>
* {
margin: 0;
padding: 0;
}
body {
padding-top: 64px;
}
#foo, #bar {
height: 35px;
width: 35px;
}
#foo {
background: blue;
float: right;
}
#bar {
background: gold;
}
</style>
</head>
<body>
<div id=foo></div><div id=bar></div>
</body>
</html>

View file

@ -0,0 +1,32 @@
<!DOCTYPE html>
<html>
<head>
<style>
h1 {
font-size: 72px;
}
</style>
</head>
<body>
<h1 id=h1>
Incremental Inline Layout
Incremental Inline Layout
Incremental Inline Layout
Incremental Inline Layout
Incremental Inline Layout
Incremental Inline Layout
Incremental Inline Layout
Incremental Inline Layout
Incremental Inline Layout
Incremental Inline Layout
Incremental Inline Layout
Incremental Inline Layout
Incremental Inline Layout
</h1>
<script>
document.getElementById('h1').getBoundingClientRect(); // Trigger one layout.
document.getElementById('h1').getBoundingClientRect(); // Trigger another layout.
</script>
</body>
</html>

View file

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<style>
h1 {
font-size: 72px;
}
</style>
</head>
<body>
<h1 id=h1>
Incremental Inline Layout
Incremental Inline Layout
Incremental Inline Layout
Incremental Inline Layout
Incremental Inline Layout
Incremental Inline Layout
Incremental Inline Layout
Incremental Inline Layout
Incremental Inline Layout
Incremental Inline Layout
Incremental Inline Layout
Incremental Inline Layout
Incremental Inline Layout
</h1>
</body>
</html>

View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="css/ahem.css">
<style>
p {
font-size: 10px;
font-family: Ahem, monospace;
width: 300px;
}
a {
color: blue;
}
</style>
</head>
<body>
<p>xxxxx xxxxx <a>xxxxx xxx xxxxx</a> xxxxxxxxxxx</p>
</body>

View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="css/ahem.css">
<style>
p {
font-size: 10px;
font-family: Ahem, monospace;
width: 300px;
}
a {
color: blue;
}
</style>
</head>
<body>
<p>xxxxx xxxxx <a>xxxxx xxx xxxxx</a><br>xxxxxxxxxxx</p>
</body>

View file

@ -4,7 +4,7 @@
<div style="float: left;">
<div style="margin-bottom: 64px;">Must be this tall</div>
<div style="margin-top: 64px;">to write multi-threaded code.</div>
</div>
</div>&nbsp;
</body>
</html>

View file

@ -18,9 +18,8 @@ fn test_transform_compress_none() {
let mode = CompressionMode::CompressNone;
for &test in test_strs.iter() {
let mut new_line_pos = vec![];
let mut trimmed_str = String::new();
transform_text(test, mode, true, &mut trimmed_str, &mut new_line_pos);
transform_text(test, mode, true, &mut trimmed_str);
assert_eq!(trimmed_str, test)
}
}
@ -52,9 +51,8 @@ fn test_transform_discard_newline() {
let mode = CompressionMode::DiscardNewline;
for &(test, oracle) in test_strs.iter() {
let mut new_line_pos = vec![];
let mut trimmed_str = String::new();
transform_text(test, mode, true, &mut trimmed_str, &mut new_line_pos);
transform_text(test, mode, true, &mut trimmed_str);
assert_eq!(trimmed_str, oracle)
}
}
@ -86,9 +84,8 @@ fn test_transform_compress_whitespace() {
let mode = CompressionMode::CompressWhitespace;
for &(test, oracle) in test_strs.iter() {
let mut new_line_pos = vec![];
let mut trimmed_str = String::new();
transform_text(test, mode, true, &mut trimmed_str, &mut new_line_pos);
transform_text(test, mode, true, &mut trimmed_str);
assert_eq!(&*trimmed_str, oracle)
}
}
@ -120,9 +117,8 @@ fn test_transform_compress_whitespace_newline() {
let mode = CompressionMode::CompressWhitespaceNewline;
for &(test, oracle) in test_strs.iter() {
let mut new_line_pos = vec![];
let mut trimmed_str = String::new();
transform_text(test, mode, true, &mut trimmed_str, &mut new_line_pos);
transform_text(test, mode, true, &mut trimmed_str);
assert_eq!(&*trimmed_str, oracle)
}
}
@ -157,9 +153,8 @@ fn test_transform_compress_whitespace_newline_no_incoming() {
let mode = CompressionMode::CompressWhitespaceNewline;
for &(test, oracle) in test_strs.iter() {
let mut new_line_pos = vec![];
let mut trimmed_str = String::new();
transform_text(test, mode, false, &mut trimmed_str, &mut new_line_pos);
transform_text(test, mode, false, &mut trimmed_str);
assert_eq!(trimmed_str, oracle)
}
}

View file

@ -64,7 +64,7 @@ first adding the following to the system's hosts file:
127.0.0.1 xn--n8j6ds53lwwkrqhv28a.web-platform.test
127.0.0.1 xn--lve-6lad.web-platform.test
and then running `python serve.py` from `tests/wpt/web-platform-tests`.
and then running `python serve` from `tests/wpt/web-platform-tests`.
Then navigate Servo to `http://web-platform.test:8000/path/to/test`.
Updating test expectations

View file

@ -0,0 +1,5 @@
[2d.strokeRect.zero.4.html]
type: testharness
[strokeRect of Nx0 pixels draws a closed line with no caps]
expected: FAIL

View file

@ -1,5 +0,0 @@
[2d.strokeRect.zero.5.html]
type: testharness
[strokeRect of Nx0 pixels draws a closed line with joins]
expected: FAIL

View file

@ -0,0 +1,5 @@
[2d.line.cap.closed.html]
type: testharness
[Line caps are not drawn at the corners of an unclosed rectangle]
expected: FAIL

View file

@ -0,0 +1,5 @@
[2d.line.join.bevel.html]
type: testharness
[lineJoin \'bevel\' is rendered correctly]
expected: FAIL

View file

@ -1,5 +0,0 @@
[2d.line.join.closed.html]
type: testharness
[Line joins are drawn at the corner of a closed rectangle]
expected: FAIL

View file

@ -1,5 +0,0 @@
[2d.line.join.miter.html]
type: testharness
[lineJoin \'miter\' is rendered correctly]
expected: FAIL

View file

@ -1,5 +0,0 @@
[2d.line.miter.acute.html]
type: testharness
[Miter joins are drawn correctly with acute angles]
expected: FAIL

View file

@ -1,5 +0,0 @@
[2d.line.miter.invalid.html]
type: testharness
[Setting miterLimit to invalid values is ignored]
expected: FAIL

View file

@ -1,5 +0,0 @@
[2d.line.miter.obtuse.html]
type: testharness
[Miter joins are drawn correctly with obtuse angles]
expected: FAIL

View file

@ -1,5 +0,0 @@
[2d.line.miter.valid.html]
type: testharness
[Setting miterLimit to valid values works]
expected: FAIL

View file

@ -1,5 +0,0 @@
[2d.line.miter.within.html]
type: testharness
[Miter joins are drawn when the miter limit is not quite exceeded]
expected: FAIL

View file

@ -2,3 +2,4 @@
type: testharness
[Shadows are not drawn for transparent parts of canvases]
expected: FAIL

View file

@ -2,3 +2,4 @@
type: testharness
[Shadows are not drawn for transparent parts of images]
expected: FAIL

View file

@ -8955,10 +8955,6 @@
"path": "IndexedDB/key_invalid.htm",
"url": "/IndexedDB/key_invalid.htm"
},
{
"path": "IndexedDB/key_valid.html",
"url": "/IndexedDB/key_valid.html"
},
{
"path": "IndexedDB/keygenerator-constrainterror.htm",
"url": "/IndexedDB/keygenerator-constrainterror.htm"
@ -9819,38 +9815,6 @@
"path": "content-security-policy/img-src/img-src-4_1.html",
"url": "/content-security-policy/img-src/img-src-4_1.html"
},
{
"path": "content-security-policy/media-src/media-src-7_1.html",
"url": "/content-security-policy/media-src/media-src-7_1.html"
},
{
"path": "content-security-policy/media-src/media-src-7_1_2.html",
"url": "/content-security-policy/media-src/media-src-7_1_2.html"
},
{
"path": "content-security-policy/media-src/media-src-7_2.html",
"url": "/content-security-policy/media-src/media-src-7_2.html"
},
{
"path": "content-security-policy/media-src/media-src-7_2_2.html",
"url": "/content-security-policy/media-src/media-src-7_2_2.html"
},
{
"path": "content-security-policy/media-src/media-src-7_3.html",
"url": "/content-security-policy/media-src/media-src-7_3.html"
},
{
"path": "content-security-policy/media-src/media-src-7_3_2.html",
"url": "/content-security-policy/media-src/media-src-7_3_2.html"
},
{
"path": "content-security-policy/object-src/object-src-2_1.html",
"url": "/content-security-policy/object-src/object-src-2_1.html"
},
{
"path": "content-security-policy/object-src/object-src-2_2.html",
"url": "/content-security-policy/object-src/object-src-2_2.html"
},
{
"path": "content-security-policy/script-src/script-src-1_1.html",
"url": "/content-security-policy/script-src/script-src-1_1.html"
@ -10311,6 +10275,10 @@
"path": "dom/nodes/CharacterData-replaceData.html",
"url": "/dom/nodes/CharacterData-replaceData.html"
},
{
"path": "dom/nodes/CharacterData-substringData.html",
"url": "/dom/nodes/CharacterData-substringData.html"
},
{
"path": "dom/nodes/Comment-constructor.html",
"url": "/dom/nodes/Comment-constructor.html"
@ -11271,6 +11239,30 @@
"path": "ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-pubid-1.html",
"url": "/ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-pubid-1.html"
},
{
"path": "fetch/nosniff/image.html",
"url": "/fetch/nosniff/image.html"
},
{
"path": "fetch/nosniff/importscripts.html",
"url": "/fetch/nosniff/importscripts.html"
},
{
"path": "fetch/nosniff/parsing-nosniff.html",
"url": "/fetch/nosniff/parsing-nosniff.html"
},
{
"path": "fetch/nosniff/script.html",
"url": "/fetch/nosniff/script.html"
},
{
"path": "fetch/nosniff/stylesheet.html",
"url": "/fetch/nosniff/stylesheet.html"
},
{
"path": "fetch/nosniff/worker.html",
"url": "/fetch/nosniff/worker.html"
},
{
"path": "gamepad/idlharness.html",
"url": "/gamepad/idlharness.html"
@ -18798,6 +18790,11 @@
"timeout": "long",
"url": "/IndexedDB/idbobjectstore_createIndex8-valid_keys.htm"
},
{
"path": "IndexedDB/key_valid.html",
"timeout": "long",
"url": "/IndexedDB/key_valid.html"
},
{
"path": "IndexedDB/keypath_maxsize.htm",
"timeout": "long",
@ -18823,6 +18820,46 @@
"timeout": "long",
"url": "/ambient-light/AmbientLight_tests.html"
},
{
"path": "content-security-policy/media-src/media-src-7_1.html",
"timeout": "long",
"url": "/content-security-policy/media-src/media-src-7_1.html"
},
{
"path": "content-security-policy/media-src/media-src-7_1_2.html",
"timeout": "long",
"url": "/content-security-policy/media-src/media-src-7_1_2.html"
},
{
"path": "content-security-policy/media-src/media-src-7_2.html",
"timeout": "long",
"url": "/content-security-policy/media-src/media-src-7_2.html"
},
{
"path": "content-security-policy/media-src/media-src-7_2_2.html",
"timeout": "long",
"url": "/content-security-policy/media-src/media-src-7_2_2.html"
},
{
"path": "content-security-policy/media-src/media-src-7_3.html",
"timeout": "long",
"url": "/content-security-policy/media-src/media-src-7_3.html"
},
{
"path": "content-security-policy/media-src/media-src-7_3_2.html",
"timeout": "long",
"url": "/content-security-policy/media-src/media-src-7_3_2.html"
},
{
"path": "content-security-policy/object-src/object-src-2_1.html",
"timeout": "long",
"url": "/content-security-policy/object-src/object-src-2_1.html"
},
{
"path": "content-security-policy/object-src/object-src-2_2.html",
"timeout": "long",
"url": "/content-security-policy/object-src/object-src-2_2.html"
},
{
"path": "cors/status-async.htm",
"timeout": "long",
@ -25034,7 +25071,7 @@
}
]
},
"rev": "0d318188757a9c996e20b82db201fd04de5aa255",
"rev": "2a9fd810bb18610b422dbc3998ab74aa1bffae95",
"url_base": "/",
"version": 2
}

View file

@ -1,5 +0,0 @@
[getresponseheader-chunked-trailer.htm]
type: testharness
[XMLHttpRequest: getResponseHeader() and HTTP trailer]
expected: FAIL

View file

@ -1,6 +1,5 @@
[timeout-cors-async.htm]
type: testharness
expected: OK
[XMLHttpRequest: timeout event and cross-origin request]
expected: FAIL

View file

@ -90,9 +90,6 @@
[Document interface: operation importNode(Node,boolean)]
expected: FAIL
[Document interface: operation createAttributeNS(DOMString,DOMString)]
expected: FAIL
[Document interface: operation createNodeIterator(Node,unsigned long,NodeFilter)]
expected: FAIL
@ -132,9 +129,6 @@
[Document interface: xmlDoc must inherit property "origin" with the proper type (3)]
expected: FAIL
[Document interface: calling createAttributeNS(DOMString,DOMString) on xmlDoc with too few arguments must throw TypeError]
expected: FAIL
[Document interface: calling createNodeIterator(Node,unsigned long,NodeFilter) on xmlDoc with too few arguments must throw TypeError]
expected: FAIL
@ -252,12 +246,6 @@
[Element interface: operation queryAll(DOMString)]
expected: FAIL
[Element interface: attribute previousElementSibling]
expected: FAIL
[Element interface: attribute nextElementSibling]
expected: FAIL
[Element interface: operation before([object Object\],[object Object\])]
expected: FAIL
@ -321,12 +309,6 @@
[Element interface: calling queryAll(DOMString) on element with too few arguments must throw TypeError]
expected: FAIL
[Element interface: element must inherit property "previousElementSibling" with the proper type (37)]
expected: FAIL
[Element interface: element must inherit property "nextElementSibling" with the proper type (38)]
expected: FAIL
[Element interface: element must inherit property "before" with the proper type (39)]
expected: FAIL
@ -345,12 +327,6 @@
[NamedNodeMap interface: operation setNamedItemNS(Attr)]
expected: FAIL
[CharacterData interface: attribute previousElementSibling]
expected: FAIL
[CharacterData interface: attribute nextElementSibling]
expected: FAIL
[CharacterData interface: operation before([object Object\],[object Object\])]
expected: FAIL
@ -375,12 +351,6 @@
[Text interface: document.createTextNode("abc") must inherit property "wholeText" with the proper type (1)]
expected: FAIL
[CharacterData interface: document.createTextNode("abc") must inherit property "previousElementSibling" with the proper type (7)]
expected: FAIL
[CharacterData interface: document.createTextNode("abc") must inherit property "nextElementSibling" with the proper type (8)]
expected: FAIL
[CharacterData interface: document.createTextNode("abc") must inherit property "before" with the proper type (9)]
expected: FAIL
@ -393,12 +363,6 @@
[CharacterData interface: calling after([object Object\],[object Object\]) on document.createTextNode("abc") with too few arguments must throw TypeError]
expected: FAIL
[CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "previousElementSibling" with the proper type (7)]
expected: FAIL
[CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "nextElementSibling" with the proper type (8)]
expected: FAIL
[CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "before" with the proper type (9)]
expected: FAIL
@ -414,12 +378,6 @@
[Comment interface object length]
expected: FAIL
[CharacterData interface: document.createComment("abc") must inherit property "previousElementSibling" with the proper type (7)]
expected: FAIL
[CharacterData interface: document.createComment("abc") must inherit property "nextElementSibling" with the proper type (8)]
expected: FAIL
[CharacterData interface: document.createComment("abc") must inherit property "before" with the proper type (9)]
expected: FAIL
@ -969,9 +927,6 @@
[DOMTokenList interface object length]
expected: FAIL
[Document interface: xmlDoc must inherit property "createAttributeNS" with the proper type (22)]
expected: FAIL
[Document interface: xmlDoc must inherit property "createNodeIterator" with the proper type (25)]
expected: FAIL

View file

@ -0,0 +1,3 @@
[CharacterData-substringData.html]
type: testharness
expected: CRASH

View file

@ -1,35 +0,0 @@
[DOMImplementation-createDocument.html]
type: testharness
[createDocument test 23: null,"xmlns",null,"NAMESPACE_ERR"]
expected: FAIL
[createDocument test 41: undefined,"xmlns",null,"NAMESPACE_ERR"]
expected: FAIL
[createDocument test 64: "http://example.com/","xmlns",null,"NAMESPACE_ERR"]
expected: FAIL
[createDocument test 69: "http://example.com/","xmlns:foo",null,"NAMESPACE_ERR"]
expected: FAIL
[createDocument test 108: "/","xmlns",null,"NAMESPACE_ERR"]
expected: FAIL
[createDocument test 111: "/","xmlns:foo",null,"NAMESPACE_ERR"]
expected: FAIL
[createDocument test 121: "http://www.w3.org/XML/1998/namespace","xmlns",null,"NAMESPACE_ERR"]
expected: FAIL
[createDocument test 124: "http://www.w3.org/XML/1998/namespace","xmlns:foo",null,"NAMESPACE_ERR"]
expected: FAIL
[createDocument test 141: "http://www.w3.org/2000/xmlns/","foo:xmlns",null,"NAMESPACE_ERR"]
expected: FAIL
[createDocument test 150: "foo:","xmlns",null,"NAMESPACE_ERR"]
expected: FAIL
[createDocument test 153: "foo:","xmlns:foo",null,"NAMESPACE_ERR"]
expected: FAIL

View file

@ -1,35 +0,0 @@
[Document-createElementNS.html]
type: testharness
[createElementNS test 23: null,"xmlns","NAMESPACE_ERR"]
expected: FAIL
[createElementNS test 41: undefined,"xmlns","NAMESPACE_ERR"]
expected: FAIL
[createElementNS test 64: "http://example.com/","xmlns","NAMESPACE_ERR"]
expected: FAIL
[createElementNS test 69: "http://example.com/","xmlns:foo","NAMESPACE_ERR"]
expected: FAIL
[createElementNS test 108: "/","xmlns","NAMESPACE_ERR"]
expected: FAIL
[createElementNS test 111: "/","xmlns:foo","NAMESPACE_ERR"]
expected: FAIL
[createElementNS test 121: "http://www.w3.org/XML/1998/namespace","xmlns","NAMESPACE_ERR"]
expected: FAIL
[createElementNS test 124: "http://www.w3.org/XML/1998/namespace","xmlns:foo","NAMESPACE_ERR"]
expected: FAIL
[createElementNS test 141: "http://www.w3.org/2000/xmlns/","foo:xmlns","NAMESPACE_ERR"]
expected: FAIL
[createElementNS test 150: "foo:","xmlns","NAMESPACE_ERR"]
expected: FAIL
[createElementNS test 153: "foo:","xmlns:foo","NAMESPACE_ERR"]
expected: FAIL

View file

@ -1,5 +0,0 @@
[Element-nextElementSibling.html]
type: testharness
[nextElementSibling]
expected: FAIL

View file

@ -1,5 +0,0 @@
[Element-previousElementSibling.html]
type: testharness
[previousElementSibling]
expected: FAIL

View file

@ -1,5 +0,0 @@
[Element-siblingElement-null.html]
type: testharness
[Null test]
expected: FAIL

View file

@ -1,50 +1,5 @@
[Node-properties.html]
type: testharness
[testDiv.previousElementSibling]
expected: FAIL
[detachedDiv.previousElementSibling]
expected: FAIL
[detachedDiv.nextElementSibling]
expected: FAIL
[detachedPara1.previousElementSibling]
expected: FAIL
[detachedPara1.nextElementSibling]
expected: FAIL
[detachedPara2.previousElementSibling]
expected: FAIL
[detachedPara2.nextElementSibling]
expected: FAIL
[foreignPara1.previousElementSibling]
expected: FAIL
[foreignPara1.nextElementSibling]
expected: FAIL
[foreignPara2.previousElementSibling]
expected: FAIL
[foreignPara2.nextElementSibling]
expected: FAIL
[xmlElement.previousElementSibling]
expected: FAIL
[xmlElement.nextElementSibling]
expected: FAIL
[detachedXmlElement.previousElementSibling]
expected: FAIL
[detachedXmlElement.nextElementSibling]
expected: FAIL
[detachedTextNode.wholeText]
expected: FAIL
@ -60,32 +15,3 @@
[detachedXmlTextNode.wholeText]
expected: FAIL
[paras[0\].previousElementSibling]
expected: FAIL
[paras[0\].nextElementSibling]
expected: FAIL
[paras[1\].previousElementSibling]
expected: FAIL
[paras[1\].nextElementSibling]
expected: FAIL
[paras[2\].previousElementSibling]
expected: FAIL
[paras[2\].nextElementSibling]
expected: FAIL
[paras[3\].previousElementSibling]
expected: FAIL
[paras[3\].nextElementSibling]
expected: FAIL
[paras[4\].previousElementSibling]
expected: FAIL
[paras[4\].nextElementSibling]
expected: FAIL

View file

@ -1,8 +1,5 @@
[api-basics.html]
type: testharness
[Default encodings]
expected: FAIL
[Default inputs]
expected: FAIL

View file

@ -1,20 +0,0 @@
[api-surrogates-utf8.html]
type: testharness
[Invalid surrogates encoded into UTF-8: Sanity check]
expected: FAIL
[Invalid surrogates encoded into UTF-8: Surrogate half (low)]
expected: FAIL
[Invalid surrogates encoded into UTF-8: Surrogate half (high)]
expected: FAIL
[Invalid surrogates encoded into UTF-8: Surrogate half (low), in a string]
expected: FAIL
[Invalid surrogates encoded into UTF-8: Surrogate half (high), in a string]
expected: FAIL
[Invalid surrogates encoded into UTF-8: Wrong order]
expected: FAIL

View file

@ -1,50 +1,17 @@
[idlharness.html]
type: testharness
[TextDecoder interface: existence and properties of interface object]
expected: FAIL
[TextDecoder interface object length]
expected: FAIL
[TextDecoder interface: existence and properties of interface prototype object]
expected: FAIL
[TextDecoder interface: existence and properties of interface prototype object\'s "constructor" property]
expected: FAIL
[TextDecoder interface: attribute encoding]
expected: FAIL
[TextDecoder interface: attribute fatal]
expected: FAIL
[TextDecoder interface: attribute ignoreBOM]
expected: FAIL
[TextDecoder interface: operation decode(BufferSource,TextDecodeOptions)]
expected: FAIL
[TextDecoder must be primary interface of new TextDecoder()]
expected: FAIL
[Stringification of new TextDecoder()]
expected: FAIL
[TextDecoder interface: new TextDecoder() must inherit property "encoding" with the proper type (0)]
expected: FAIL
[TextDecoder interface: new TextDecoder() must inherit property "fatal" with the proper type (1)]
expected: FAIL
[TextDecoder interface: new TextDecoder() must inherit property "ignoreBOM" with the proper type (2)]
expected: FAIL
[TextDecoder interface: new TextDecoder() must inherit property "decode" with the proper type (3)]
expected: FAIL
[TextDecoder interface: calling decode(BufferSource,TextDecodeOptions) on new TextDecoder() with too few arguments must throw TypeError]
expected: FAIL
[TextEncoder interface object length]
expected: FAIL

View file

@ -3,21 +3,12 @@
[iso-2022-jp decoder: Error ESC]
expected: FAIL
[iso-2022-jp decoder: Error ESC, character]
expected: FAIL
[iso-2022-jp decoder: ASCII ESC, character]
expected: FAIL
[iso-2022-jp decoder: Double ASCII ESC, character]
expected: FAIL
[iso-2022-jp decoder: character, ASCII ESC, character]
expected: FAIL
[iso-2022-jp decoder: characters]
expected: FAIL
[iso-2022-jp decoder: SO / SI]
expected: FAIL
@ -27,12 +18,6 @@
[iso-2022-jp decoder: Roman ESC, SO / SI]
expected: FAIL
[iso-2022-jp decoder: Roman ESC, error ESC, Katakana ESC]
expected: FAIL
[iso-2022-jp decoder: Katakana ESC, character]
expected: FAIL
[iso-2022-jp decoder: Katakana ESC, multibyte ESC, character]
expected: FAIL
@ -42,18 +27,6 @@
[iso-2022-jp decoder: Katakana ESC, error ESC #2, character]
expected: FAIL
[iso-2022-jp decoder: Katakana ESC, character, Katakana ESC, character]
expected: FAIL
[iso-2022-jp decoder: Katakana ESC, SO / SI]
expected: FAIL
[iso-2022-jp decoder: Multibyte ESC, character]
expected: FAIL
[iso-2022-jp decoder: Multibyte ESC #2, character]
expected: FAIL
[iso-2022-jp decoder: Multibyte ESC, error ESC, character]
expected: FAIL
@ -75,30 +48,6 @@
[iso-2022-jp decoder: Multibyte ESC, lead error byte]
expected: FAIL
[iso-2022-jp decoder: Multibyte ESC, trail error byte]
expected: FAIL
[iso-2022-jp decoder: character, error ESC]
expected: FAIL
[iso-2022-jp decoder: character, error ESC #2]
expected: FAIL
[iso-2022-jp decoder: character, error ESC #3]
expected: FAIL
[iso-2022-jp decoder: character, ASCII ESC]
expected: FAIL
[iso-2022-jp decoder: character, Roman ESC]
expected: FAIL
[iso-2022-jp decoder: character, Katakana ESC]
expected: FAIL
[iso-2022-jp decoder: character, Multibyte ESC]
expected: FAIL
[iso-2022-jp decoder: character, Multibyte ESC #2]
expected: FAIL

View file

@ -1,107 +0,0 @@
[textdecoder-fatal.html]
type: testharness
[Fatal flag: utf-8 - invalid code]
expected: FAIL
[Fatal flag: utf-8 - ends early]
expected: FAIL
[Fatal flag: utf-8 - ends early 2]
expected: FAIL
[Fatal flag: utf-8 - invalid trail]
expected: FAIL
[Fatal flag: utf-8 - invalid trail 2]
expected: FAIL
[Fatal flag: utf-8 - invalid trail 3]
expected: FAIL
[Fatal flag: utf-8 - invalid trail 4]
expected: FAIL
[Fatal flag: utf-8 - invalid trail 5]
expected: FAIL
[Fatal flag: utf-8 - invalid trail 6]
expected: FAIL
[Fatal flag: utf-8 - > 0x10FFFF]
expected: FAIL
[Fatal flag: utf-8 - obsolete lead byte]
expected: FAIL
[Fatal flag: utf-8 - overlong U+0000 - 2 bytes]
expected: FAIL
[Fatal flag: utf-8 - overlong U+0000 - 3 bytes]
expected: FAIL
[Fatal flag: utf-8 - overlong U+0000 - 4 bytes]
expected: FAIL
[Fatal flag: utf-8 - overlong U+0000 - 5 bytes]
expected: FAIL
[Fatal flag: utf-8 - overlong U+0000 - 6 bytes]
expected: FAIL
[Fatal flag: utf-8 - overlong U+007F - 2 bytes]
expected: FAIL
[Fatal flag: utf-8 - overlong U+007F - 3 bytes]
expected: FAIL
[Fatal flag: utf-8 - overlong U+007F - 4 bytes]
expected: FAIL
[Fatal flag: utf-8 - overlong U+007F - 5 bytes]
expected: FAIL
[Fatal flag: utf-8 - overlong U+007F - 6 bytes]
expected: FAIL
[Fatal flag: utf-8 - overlong U+07FF - 3 bytes]
expected: FAIL
[Fatal flag: utf-8 - overlong U+07FF - 4 bytes]
expected: FAIL
[Fatal flag: utf-8 - overlong U+07FF - 5 bytes]
expected: FAIL
[Fatal flag: utf-8 - overlong U+07FF - 6 bytes]
expected: FAIL
[Fatal flag: utf-8 - overlong U+FFFF - 4 bytes]
expected: FAIL
[Fatal flag: utf-8 - overlong U+FFFF - 5 bytes]
expected: FAIL
[Fatal flag: utf-8 - overlong U+FFFF - 6 bytes]
expected: FAIL
[Fatal flag: utf-8 - overlong U+10FFFF - 5 bytes]
expected: FAIL
[Fatal flag: utf-8 - overlong U+10FFFF - 6 bytes]
expected: FAIL
[Fatal flag: utf-8 - lead surrogate]
expected: FAIL
[Fatal flag: utf-8 - trail surrogate]
expected: FAIL
[Fatal flag: utf-8 - surrogate pair]
expected: FAIL
[Fatal flag: utf-16le - truncated code unit]
expected: FAIL
[The fatal attribute of TextDecoder]
expected: FAIL

View file

@ -1,515 +1,5 @@
[textdecoder-labels.html]
type: testharness
[name=utf-8 label=unicode-1-1-utf-8]
expected: FAIL
[name=utf-8 label=utf-8]
expected: FAIL
[name=utf-8 label=utf8]
expected: FAIL
[name=ibm866 label=866]
expected: FAIL
[name=ibm866 label=cp866]
expected: FAIL
[name=ibm866 label=csibm866]
expected: FAIL
[name=ibm866 label=ibm866]
expected: FAIL
[name=iso-8859-2 label=csisolatin2]
expected: FAIL
[name=iso-8859-2 label=iso-8859-2]
expected: FAIL
[name=iso-8859-2 label=iso-ir-101]
expected: FAIL
[name=iso-8859-2 label=iso8859-2]
expected: FAIL
[name=iso-8859-2 label=iso88592]
expected: FAIL
[name=iso-8859-2 label=iso_8859-2]
expected: FAIL
[name=iso-8859-2 label=iso_8859-2:1987]
expected: FAIL
[name=iso-8859-2 label=l2]
expected: FAIL
[name=iso-8859-2 label=latin2]
expected: FAIL
[name=iso-8859-3 label=csisolatin3]
expected: FAIL
[name=iso-8859-3 label=iso-8859-3]
expected: FAIL
[name=iso-8859-3 label=iso-ir-109]
expected: FAIL
[name=iso-8859-3 label=iso8859-3]
expected: FAIL
[name=iso-8859-3 label=iso88593]
expected: FAIL
[name=iso-8859-3 label=iso_8859-3]
expected: FAIL
[name=iso-8859-3 label=iso_8859-3:1988]
expected: FAIL
[name=iso-8859-3 label=l3]
expected: FAIL
[name=iso-8859-3 label=latin3]
expected: FAIL
[name=iso-8859-4 label=csisolatin4]
expected: FAIL
[name=iso-8859-4 label=iso-8859-4]
expected: FAIL
[name=iso-8859-4 label=iso-ir-110]
expected: FAIL
[name=iso-8859-4 label=iso8859-4]
expected: FAIL
[name=iso-8859-4 label=iso88594]
expected: FAIL
[name=iso-8859-4 label=iso_8859-4]
expected: FAIL
[name=iso-8859-4 label=iso_8859-4:1988]
expected: FAIL
[name=iso-8859-4 label=l4]
expected: FAIL
[name=iso-8859-4 label=latin4]
expected: FAIL
[name=iso-8859-5 label=csisolatincyrillic]
expected: FAIL
[name=iso-8859-5 label=cyrillic]
expected: FAIL
[name=iso-8859-5 label=iso-8859-5]
expected: FAIL
[name=iso-8859-5 label=iso-ir-144]
expected: FAIL
[name=iso-8859-5 label=iso8859-5]
expected: FAIL
[name=iso-8859-5 label=iso88595]
expected: FAIL
[name=iso-8859-5 label=iso_8859-5]
expected: FAIL
[name=iso-8859-5 label=iso_8859-5:1988]
expected: FAIL
[name=iso-8859-6 label=arabic]
expected: FAIL
[name=iso-8859-6 label=asmo-708]
expected: FAIL
[name=iso-8859-6 label=csiso88596e]
expected: FAIL
[name=iso-8859-6 label=csiso88596i]
expected: FAIL
[name=iso-8859-6 label=csisolatinarabic]
expected: FAIL
[name=iso-8859-6 label=ecma-114]
expected: FAIL
[name=iso-8859-6 label=iso-8859-6]
expected: FAIL
[name=iso-8859-6 label=iso-8859-6-e]
expected: FAIL
[name=iso-8859-6 label=iso-8859-6-i]
expected: FAIL
[name=iso-8859-6 label=iso-ir-127]
expected: FAIL
[name=iso-8859-6 label=iso8859-6]
expected: FAIL
[name=iso-8859-6 label=iso88596]
expected: FAIL
[name=iso-8859-6 label=iso_8859-6]
expected: FAIL
[name=iso-8859-6 label=iso_8859-6:1987]
expected: FAIL
[name=iso-8859-7 label=csisolatingreek]
expected: FAIL
[name=iso-8859-7 label=ecma-118]
expected: FAIL
[name=iso-8859-7 label=elot_928]
expected: FAIL
[name=iso-8859-7 label=greek]
expected: FAIL
[name=iso-8859-7 label=greek8]
expected: FAIL
[name=iso-8859-7 label=iso-8859-7]
expected: FAIL
[name=iso-8859-7 label=iso-ir-126]
expected: FAIL
[name=iso-8859-7 label=iso8859-7]
expected: FAIL
[name=iso-8859-7 label=iso88597]
expected: FAIL
[name=iso-8859-7 label=iso_8859-7]
expected: FAIL
[name=iso-8859-7 label=iso_8859-7:1987]
expected: FAIL
[name=iso-8859-7 label=sun_eu_greek]
expected: FAIL
[name=iso-8859-8 label=csiso88598e]
expected: FAIL
[name=iso-8859-8 label=csisolatinhebrew]
expected: FAIL
[name=iso-8859-8 label=hebrew]
expected: FAIL
[name=iso-8859-8 label=iso-8859-8]
expected: FAIL
[name=iso-8859-8 label=iso-8859-8-e]
expected: FAIL
[name=iso-8859-8 label=iso-ir-138]
expected: FAIL
[name=iso-8859-8 label=iso8859-8]
expected: FAIL
[name=iso-8859-8 label=iso88598]
expected: FAIL
[name=iso-8859-8 label=iso_8859-8]
expected: FAIL
[name=iso-8859-8 label=iso_8859-8:1988]
expected: FAIL
[name=iso-8859-8 label=visual]
expected: FAIL
[name=iso-8859-8-i label=csiso88598i]
expected: FAIL
[name=iso-8859-8-i label=iso-8859-8-i]
expected: FAIL
[name=iso-8859-8-i label=logical]
expected: FAIL
[name=iso-8859-10 label=csisolatin6]
expected: FAIL
[name=iso-8859-10 label=iso-8859-10]
expected: FAIL
[name=iso-8859-10 label=iso-ir-157]
expected: FAIL
[name=iso-8859-10 label=iso8859-10]
expected: FAIL
[name=iso-8859-10 label=iso885910]
expected: FAIL
[name=iso-8859-10 label=l6]
expected: FAIL
[name=iso-8859-10 label=latin6]
expected: FAIL
[name=iso-8859-13 label=iso-8859-13]
expected: FAIL
[name=iso-8859-13 label=iso8859-13]
expected: FAIL
[name=iso-8859-13 label=iso885913]
expected: FAIL
[name=iso-8859-14 label=iso-8859-14]
expected: FAIL
[name=iso-8859-14 label=iso8859-14]
expected: FAIL
[name=iso-8859-14 label=iso885914]
expected: FAIL
[name=iso-8859-15 label=csisolatin9]
expected: FAIL
[name=iso-8859-15 label=iso-8859-15]
expected: FAIL
[name=iso-8859-15 label=iso8859-15]
expected: FAIL
[name=iso-8859-15 label=iso885915]
expected: FAIL
[name=iso-8859-15 label=iso_8859-15]
expected: FAIL
[name=iso-8859-15 label=l9]
expected: FAIL
[name=iso-8859-16 label=iso-8859-16]
expected: FAIL
[name=koi8-r label=cskoi8r]
expected: FAIL
[name=koi8-r label=koi]
expected: FAIL
[name=koi8-r label=koi8]
expected: FAIL
[name=koi8-r label=koi8-r]
expected: FAIL
[name=koi8-r label=koi8_r]
expected: FAIL
[name=koi8-u label=koi8-u]
expected: FAIL
[name=macintosh label=csmacintosh]
expected: FAIL
[name=macintosh label=mac]
expected: FAIL
[name=macintosh label=macintosh]
expected: FAIL
[name=macintosh label=x-mac-roman]
expected: FAIL
[name=windows-874 label=dos-874]
expected: FAIL
[name=windows-874 label=iso-8859-11]
expected: FAIL
[name=windows-874 label=iso8859-11]
expected: FAIL
[name=windows-874 label=iso885911]
expected: FAIL
[name=windows-874 label=tis-620]
expected: FAIL
[name=windows-874 label=windows-874]
expected: FAIL
[name=windows-1250 label=cp1250]
expected: FAIL
[name=windows-1250 label=windows-1250]
expected: FAIL
[name=windows-1250 label=x-cp1250]
expected: FAIL
[name=windows-1251 label=cp1251]
expected: FAIL
[name=windows-1251 label=windows-1251]
expected: FAIL
[name=windows-1251 label=x-cp1251]
expected: FAIL
[name=windows-1252 label=ansi_x3.4-1968]
expected: FAIL
[name=windows-1252 label=ascii]
expected: FAIL
[name=windows-1252 label=cp1252]
expected: FAIL
[name=windows-1252 label=cp819]
expected: FAIL
[name=windows-1252 label=csisolatin1]
expected: FAIL
[name=windows-1252 label=ibm819]
expected: FAIL
[name=windows-1252 label=iso-8859-1]
expected: FAIL
[name=windows-1252 label=iso-ir-100]
expected: FAIL
[name=windows-1252 label=iso8859-1]
expected: FAIL
[name=windows-1252 label=iso88591]
expected: FAIL
[name=windows-1252 label=iso_8859-1]
expected: FAIL
[name=windows-1252 label=iso_8859-1:1987]
expected: FAIL
[name=windows-1252 label=l1]
expected: FAIL
[name=windows-1252 label=latin1]
expected: FAIL
[name=windows-1252 label=us-ascii]
expected: FAIL
[name=windows-1252 label=windows-1252]
expected: FAIL
[name=windows-1252 label=x-cp1252]
expected: FAIL
[name=windows-1253 label=cp1253]
expected: FAIL
[name=windows-1253 label=windows-1253]
expected: FAIL
[name=windows-1253 label=x-cp1253]
expected: FAIL
[name=windows-1254 label=cp1254]
expected: FAIL
[name=windows-1254 label=csisolatin5]
expected: FAIL
[name=windows-1254 label=iso-8859-9]
expected: FAIL
[name=windows-1254 label=iso-ir-148]
expected: FAIL
[name=windows-1254 label=iso8859-9]
expected: FAIL
[name=windows-1254 label=iso88599]
expected: FAIL
[name=windows-1254 label=iso_8859-9]
expected: FAIL
[name=windows-1254 label=iso_8859-9:1989]
expected: FAIL
[name=windows-1254 label=l5]
expected: FAIL
[name=windows-1254 label=latin5]
expected: FAIL
[name=windows-1254 label=windows-1254]
expected: FAIL
[name=windows-1254 label=x-cp1254]
expected: FAIL
[name=windows-1255 label=cp1255]
expected: FAIL
[name=windows-1255 label=windows-1255]
expected: FAIL
[name=windows-1255 label=x-cp1255]
expected: FAIL
[name=windows-1256 label=cp1256]
expected: FAIL
[name=windows-1256 label=windows-1256]
expected: FAIL
[name=windows-1256 label=x-cp1256]
expected: FAIL
[name=windows-1257 label=cp1257]
expected: FAIL
[name=windows-1257 label=windows-1257]
expected: FAIL
[name=windows-1257 label=x-cp1257]
expected: FAIL
[name=windows-1258 label=cp1258]
expected: FAIL
[name=windows-1258 label=windows-1258]
expected: FAIL
[name=windows-1258 label=x-cp1258]
expected: FAIL
[name=x-mac-cyrillic label=x-mac-cyrillic]
expected: FAIL
[name=x-mac-cyrillic label=x-mac-ukrainian]
expected: FAIL
[name=gbk label=chinese]
expected: FAIL
@ -537,99 +27,9 @@
[name=gbk label=x-gbk]
expected: FAIL
[name=gb18030 label=gb18030]
expected: FAIL
[name=big5 label=big5]
expected: FAIL
[name=big5 label=big5-hkscs]
expected: FAIL
[name=big5 label=cn-big5]
expected: FAIL
[name=big5 label=csbig5]
expected: FAIL
[name=big5 label=x-x-big5]
expected: FAIL
[name=euc-jp label=cseucpkdfmtjapanese]
expected: FAIL
[name=euc-jp label=euc-jp]
expected: FAIL
[name=euc-jp label=x-euc-jp]
expected: FAIL
[name=iso-2022-jp label=csiso2022jp]
expected: FAIL
[name=iso-2022-jp label=iso-2022-jp]
expected: FAIL
[name=shift_jis label=csshiftjis]
expected: FAIL
[name=shift_jis label=ms_kanji]
expected: FAIL
[name=shift_jis label=shift-jis]
expected: FAIL
[name=shift_jis label=shift_jis]
expected: FAIL
[name=shift_jis label=sjis]
expected: FAIL
[name=shift_jis label=windows-31j]
expected: FAIL
[name=shift_jis label=x-sjis]
expected: FAIL
[name=euc-kr label=cseuckr]
expected: FAIL
[name=euc-kr label=csksc56011987]
expected: FAIL
[name=euc-kr label=euc-kr]
expected: FAIL
[name=euc-kr label=iso-ir-149]
expected: FAIL
[name=euc-kr label=korean]
expected: FAIL
[name=euc-kr label=ks_c_5601-1987]
expected: FAIL
[name=euc-kr label=ks_c_5601-1989]
expected: FAIL
[name=euc-kr label=ksc5601]
expected: FAIL
[name=euc-kr label=ksc_5601]
expected: FAIL
[name=euc-kr label=windows-949]
expected: FAIL
[name=utf-16be label=utf-16be]
expected: FAIL
[name=utf-16le label=utf-16]
expected: FAIL
[name=utf-16le label=utf-16le]
expected: FAIL
[name=x-user-defined label=x-user-defined]
expected: FAIL

View file

@ -1,47 +1,20 @@
[textdecoder-streaming.html]
type: testharness
[Streaming decode: utf-8, 1 byte window]
expected: FAIL
[Streaming decode: utf-8, 2 byte window]
expected: FAIL
[Streaming decode: utf-8, 3 byte window]
expected: FAIL
[Streaming decode: utf-8, 4 byte window]
expected: FAIL
[Streaming decode: utf-8, 5 byte window]
expected: FAIL
[Streaming decode: utf-16le, 1 byte window]
expected: FAIL
[Streaming decode: utf-16le, 2 byte window]
expected: FAIL
[Streaming decode: utf-16le, 3 byte window]
expected: FAIL
[Streaming decode: utf-16le, 4 byte window]
expected: FAIL
[Streaming decode: utf-16le, 5 byte window]
expected: FAIL
[Streaming decode: utf-16be, 1 byte window]
expected: FAIL
[Streaming decode: utf-16be, 2 byte window]
expected: FAIL
[Streaming decode: utf-16be, 3 byte window]
expected: FAIL
[Streaming decode: utf-16be, 4 byte window]
expected: FAIL
[Streaming decode: utf-16be, 5 byte window]
expected: FAIL

View file

@ -1,32 +0,0 @@
[textdecoder-utf16-surrogates.html]
type: testharness
[utf-16le - lone surrogate lead]
expected: FAIL
[utf-16le - lone surrogate lead (fatal flag set)]
expected: FAIL
[utf-16le - lone surrogate trail]
expected: FAIL
[utf-16le - lone surrogate trail (fatal flag set)]
expected: FAIL
[utf-16le - unmatched surrogate lead]
expected: FAIL
[utf-16le - unmatched surrogate lead (fatal flag set)]
expected: FAIL
[utf-16le - unmatched surrogate trail]
expected: FAIL
[utf-16le - unmatched surrogate trail (fatal flag set)]
expected: FAIL
[utf-16le - swapped surrogate pair]
expected: FAIL
[utf-16le - swapped surrogate pair (fatal flag set)]
expected: FAIL

View file

@ -1,8 +1,5 @@
[textencoder-constructor-non-utf.html]
type: testharness
[UTF encodings are supported for encode and decode: utf-8]
expected: FAIL
[Non-UTF encodings supported only for decode, not encode: ibm866]
expected: FAIL
@ -108,9 +105,6 @@
[Non-UTF encodings supported only for decode, not encode: euc-kr]
expected: FAIL
[UTF encodings are supported for encode and decode: utf-16be]
expected: FAIL
[UTF encodings are supported for encode and decode: utf-16le]
expected: FAIL

View file

@ -1,20 +0,0 @@
[textencoder-utf16-surrogates.html]
type: testharness
[USVString handling: lone surrogate lead]
expected: FAIL
[USVString handling: lone surrogate trail]
expected: FAIL
[USVString handling: unmatched surrogate lead]
expected: FAIL
[USVString handling: unmatched surrogate trail]
expected: FAIL
[USVString handling: swapped surrogate pair]
expected: FAIL
[USVString handling: properly encoded MUSICAL SYMBOL G CLEF (U+1D11E)]
expected: FAIL

View file

@ -1,6 +1,5 @@
[frameElement.sub.html]
type: testharness
expected: OK
[The window\'s frameElement attribute must return its container element if it is a nested browsing context]
expected: FAIL

View file

@ -1035,12 +1035,6 @@
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "origin" with the proper type (3)]
expected: FAIL
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "createAttributeNS" with the proper type (22)]
expected: FAIL
[Document interface: calling createAttributeNS(DOMString,DOMString) on document.implementation.createDocument(null, "", null) with too few arguments must throw TypeError]
expected: FAIL
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "createNodeIterator" with the proper type (25)]
expected: FAIL
@ -2220,12 +2214,6 @@
[Element interface: calling queryAll(DOMString) on document.createElement("noscript") with too few arguments must throw TypeError]
expected: FAIL
[Element interface: document.createElement("noscript") must inherit property "previousElementSibling" with the proper type (37)]
expected: FAIL
[Element interface: document.createElement("noscript") must inherit property "nextElementSibling" with the proper type (38)]
expected: FAIL
[Element interface: document.createElement("noscript") must inherit property "before" with the proper type (39)]
expected: FAIL
@ -7011,9 +6999,6 @@
[CanvasRenderingContext2D interface: attribute lineJoin]
expected: FAIL
[CanvasRenderingContext2D interface: attribute miterLimit]
expected: FAIL
[CanvasRenderingContext2D interface: operation setLineDash([object Object\])]
expected: FAIL
@ -7221,9 +7206,6 @@
[CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "lineJoin" with the proper type (61)]
expected: FAIL
[CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "miterLimit" with the proper type (62)]
expected: FAIL
[CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "setLineDash" with the proper type (63)]
expected: FAIL

View file

@ -20,3 +20,4 @@
[A disabled <input[type=radio\]> should not be focusable]
expected: FAIL

View file

@ -705,3 +705,6 @@
["data:,a 1w \\x011h" (leading U+0001)]
expected: FAIL
["data:,a 1w"]
expected: FAIL

View file

@ -1,6 +1,5 @@
[WorkerGlobalScope_importScripts_NetworkErr.htm]
type: testharness
expected: TIMEOUT
[ importScripts() with non-existent script file ]
expected: TIMEOUT
expected: FAIL

View file

@ -2,3 +2,4 @@
type: testharness
[members of WorkerLocation]
expected: FAIL

View file

@ -1,6 +1,7 @@
<!DOCTYPE html>
<!-- Submitted from TestTWF Paris -->
<meta charset=utf-8">
<meta name="timeout" content="long">
<title>Valid key</title>
<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-construct">
<link rel=assert title="A value is said to be a valid key if it is one of the following types: Array JavaScript objects [ECMA-262], DOMString [WEBIDL], Date [ECMA-262] or float [WEBIDL]. However Arrays are only valid keys if every item in the array is defined and is a valid key (i.e. sparse arrays can not be valid keys) and if the Array doesn't directly or indirectly contain itself. Any non-numeric properties are ignored, and thus does not affect whether the Array is a valid key. Additionally, if the value is of type float, it is only a valid key if it is not NaN, and if the value is of type Date it is only a valid key if its [[PrimitiveValue]] internal property, as defined by [ECMA-262], is not NaN. Conforming user agents must support all valid keys as keys.">

View file

@ -1,8 +1,16 @@
The Web Platform Tests Project [![IRC chat](https://goo.gl/6nCIks)](http://irc.w3.org/?channels=testing)
==============================
These are test suites for 60+ Web-platform specifications, along
with test-infrastructure code for running the tests.
The Web Platform Tests Project is a W3C-coordinated attempt to build a
cross-browser testsuite for the Web-platform stack. Writing tests in a
way that allows them to be run in all browsers gives browser projects
confidence that they are shipping software that is compatible with other
implementations, and that later implementations will be compatible with
their implementations. This in turn gives Web authors/developers
confidence that they can actually rely on the Web platform to deliver on
the promise of working across browsers and devices without needing extra
layers of abstraction to paper over the gaps left by specification
editors and implementors.
Running the Tests
=================

View file

@ -10,7 +10,7 @@ def main(request, response):
response.write_status_headers()
for value in chunks:
response.writer.write("%d\r\n" % len(value))
response.writer.write("%x\r\n" % len(value))
response.writer.write(value)
response.writer.write("\r\n")
response.writer.write("0\r\n")

View file

@ -2,6 +2,7 @@
<html>
<head>
<title>Video element src attribute must match src list - positive test</title>
<meta name=timeout content=long>
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
</head>

View file

@ -2,6 +2,7 @@
<html>
<head>
<title>Video element src attribute must match src list - negative test</title>
<meta name=timeout content=long>
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
</head>

View file

@ -2,6 +2,7 @@
<html>
<head>
<title>Audio element src attribute must match src list - positive test</title>
<meta name=timeout content=long>
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
</head>

View file

@ -2,6 +2,7 @@
<html>
<head>
<title>Audio element src attribute must match src list - negative test</title>
<meta name=timeout content=long>
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
</head>

View file

@ -2,6 +2,7 @@
<html>
<head>
<title>Video track src attribute must match src list - positive test</title>
<meta name=timeout content=long>
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
</head>

Some files were not shown because too many files have changed in this diff Show more