mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Auto merge of #18854 - servo:servo-unstable-feature, r=nox
Make optional the usage of some unstable features With `--no-default-features --features default-except-unstable`, more crates can now be compiled on stable Rust. This will help integrate them in rustc’s regression testing and compiler performance benchmarking. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/18854) <!-- Reviewable:end -->
This commit is contained in:
commit
78aaa85aec
40 changed files with 549 additions and 236 deletions
13
Cargo.lock
generated
13
Cargo.lock
generated
|
@ -326,6 +326,7 @@ dependencies = [
|
|||
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nonzero 0.0.1",
|
||||
"offscreen_gl_context 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"servo_config 0.0.1",
|
||||
|
@ -472,6 +473,7 @@ dependencies = [
|
|||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
"net_traits 0.0.1",
|
||||
"nonzero 0.0.1",
|
||||
"profile_traits 0.0.1",
|
||||
"script_traits 0.0.1",
|
||||
"servo_config 0.0.1",
|
||||
|
@ -1564,6 +1566,7 @@ dependencies = [
|
|||
"metrics 0.0.1",
|
||||
"msg 0.0.1",
|
||||
"net_traits 0.0.1",
|
||||
"nonzero 0.0.1",
|
||||
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"profile_traits 0.0.1",
|
||||
"range 0.0.1",
|
||||
|
@ -1906,6 +1909,7 @@ dependencies = [
|
|||
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nonzero 0.0.1",
|
||||
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"webrender_api 0.52.1 (git+https://github.com/servo/webrender)",
|
||||
]
|
||||
|
@ -2045,6 +2049,13 @@ name = "nom"
|
|||
version = "1.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "nonzero"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nsstring_vendor"
|
||||
version = "0.1.0"
|
||||
|
@ -2664,6 +2675,7 @@ dependencies = [
|
|||
"metrics 0.0.1",
|
||||
"msg 0.0.1",
|
||||
"net_traits 0.0.1",
|
||||
"nonzero 0.0.1",
|
||||
"profile_traits 0.0.1",
|
||||
"range 0.0.1",
|
||||
"script_traits 0.0.1",
|
||||
|
@ -2982,6 +2994,7 @@ version = "0.0.1"
|
|||
dependencies = [
|
||||
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nonzero 0.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -16,6 +16,7 @@ heapsize = "0.4"
|
|||
heapsize_derive = "0.1"
|
||||
ipc-channel = "0.8"
|
||||
lazy_static = "0.2"
|
||||
nonzero = {path = "../nonzero"}
|
||||
offscreen_gl_context = { version = "0.11", features = ["serde"] }
|
||||
serde = "1.0"
|
||||
servo_config = {path = "../config"}
|
||||
|
|
|
@ -4,17 +4,16 @@
|
|||
|
||||
#![crate_name = "canvas_traits"]
|
||||
#![crate_type = "rlib"]
|
||||
#![feature(nonzero)]
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
|
||||
extern crate core;
|
||||
extern crate cssparser;
|
||||
extern crate euclid;
|
||||
extern crate heapsize;
|
||||
#[macro_use] extern crate heapsize_derive;
|
||||
extern crate ipc_channel;
|
||||
#[macro_use] extern crate lazy_static;
|
||||
extern crate nonzero;
|
||||
extern crate offscreen_gl_context;
|
||||
#[macro_use] extern crate serde;
|
||||
extern crate servo_config;
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
* 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 core::nonzero::NonZero;
|
||||
use euclid::Size2D;
|
||||
use nonzero::NonZeroU32;
|
||||
use offscreen_gl_context::{GLContextAttributes, GLLimits};
|
||||
use std::fmt;
|
||||
use webrender_api;
|
||||
|
@ -242,13 +242,13 @@ pub enum WebGLCommand {
|
|||
macro_rules! define_resource_id_struct {
|
||||
($name:ident) => {
|
||||
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
|
||||
pub struct $name(NonZero<u32>);
|
||||
pub struct $name(NonZeroU32);
|
||||
|
||||
impl $name {
|
||||
#[allow(unsafe_code)]
|
||||
#[inline]
|
||||
pub unsafe fn new(id: u32) -> Self {
|
||||
$name(NonZero::new_unchecked(id))
|
||||
$name(NonZeroU32::new_unchecked(id))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -18,10 +18,11 @@ ipc-channel = "0.8"
|
|||
log = "0.3.5"
|
||||
msg = {path = "../msg"}
|
||||
net_traits = {path = "../net_traits"}
|
||||
nonzero = {path = "../nonzero"}
|
||||
profile_traits = {path = "../profile_traits"}
|
||||
script_traits = {path = "../script_traits"}
|
||||
servo_config = {path = "../config"}
|
||||
servo_geometry = {path = "../geometry", features = ["servo"]}
|
||||
servo_geometry = {path = "../geometry"}
|
||||
servo_url = {path = "../url"}
|
||||
style_traits = {path = "../style_traits"}
|
||||
time = "0.1.17"
|
||||
|
|
|
@ -6,7 +6,6 @@ use CompositionPipeline;
|
|||
use SendableFrameTree;
|
||||
use compositor_thread::{CompositorProxy, CompositorReceiver};
|
||||
use compositor_thread::{InitialCompositorState, Msg, RenderListener};
|
||||
use core::nonzero::NonZero;
|
||||
use euclid::{Point2D, TypedPoint2D, TypedVector2D, ScaleFactor};
|
||||
use gfx_traits::Epoch;
|
||||
use gleam::gl;
|
||||
|
@ -14,6 +13,7 @@ use image::{DynamicImage, ImageFormat, RgbImage};
|
|||
use ipc_channel::ipc::{self, IpcSharedMemory};
|
||||
use msg::constellation_msg::{PipelineId, PipelineIndex, PipelineNamespaceId};
|
||||
use net_traits::image::base::{Image, PixelFormat};
|
||||
use nonzero::NonZeroU32;
|
||||
use profile_traits::time::{self, ProfilerCategory, profile};
|
||||
use script_traits::{AnimationState, AnimationTickType, ConstellationControlMsg};
|
||||
use script_traits::{ConstellationMsg, LayoutControlMsg, MouseButton};
|
||||
|
@ -62,7 +62,7 @@ impl ConvertPipelineIdFromWebRender for webrender_api::PipelineId {
|
|||
fn from_webrender(&self) -> PipelineId {
|
||||
PipelineId {
|
||||
namespace_id: PipelineNamespaceId(self.0),
|
||||
index: PipelineIndex(NonZero::new(self.1).expect("Webrender pipeline zero?")),
|
||||
index: PipelineIndex(NonZeroU32::new(self.1).expect("Webrender pipeline zero?")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![feature(nonzero)]
|
||||
|
||||
extern crate core;
|
||||
extern crate euclid;
|
||||
extern crate gfx_traits;
|
||||
extern crate gleam;
|
||||
|
@ -15,6 +13,7 @@ extern crate ipc_channel;
|
|||
extern crate log;
|
||||
extern crate msg;
|
||||
extern crate net_traits;
|
||||
extern crate nonzero;
|
||||
extern crate profile_traits;
|
||||
extern crate script_traits;
|
||||
extern crate servo_config;
|
||||
|
|
|
@ -772,6 +772,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
self.all_descendant_browsing_contexts_iter(BrowsingContextId::from(top_level_browsing_context_id))
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
/// The joint session future is the merge of the session future of every
|
||||
/// browsing_context, sorted chronologically.
|
||||
fn joint_session_future<'a>(&'a self, top_level_browsing_context_id: TopLevelBrowsingContextId)
|
||||
|
@ -782,12 +783,26 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
.kmerge_by(|a, b| a.instant.cmp(&b.instant) == Ordering::Less)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "unstable"))]
|
||||
/// The joint session future is the merge of the session future of every
|
||||
/// browsing_context, sorted chronologically.
|
||||
fn joint_session_future<'a>(&'a self, top_level_browsing_context_id: TopLevelBrowsingContextId)
|
||||
-> Box<Iterator<Item = &'a SessionHistoryEntry> + 'a>
|
||||
{
|
||||
Box::new(
|
||||
self.all_browsing_contexts_iter(top_level_browsing_context_id)
|
||||
.map(|browsing_context| browsing_context.next.iter().rev())
|
||||
.kmerge_by(|a, b| a.instant.cmp(&b.instant) == Ordering::Less)
|
||||
)
|
||||
}
|
||||
|
||||
/// Is the joint session future empty?
|
||||
fn joint_session_future_is_empty(&self, top_level_browsing_context_id: TopLevelBrowsingContextId) -> bool {
|
||||
self.all_browsing_contexts_iter(top_level_browsing_context_id)
|
||||
.all(|browsing_context| browsing_context.next.is_empty())
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
/// The joint session past is the merge of the session past of every
|
||||
/// browsing_context, sorted reverse chronologically.
|
||||
fn joint_session_past<'a>(&'a self, top_level_browsing_context_id: TopLevelBrowsingContextId)
|
||||
|
@ -804,6 +819,25 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
|||
.map(|(_, entry)| entry)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "unstable"))]
|
||||
/// The joint session past is the merge of the session past of every
|
||||
/// browsing_context, sorted reverse chronologically.
|
||||
fn joint_session_past<'a>(&'a self, top_level_browsing_context_id: TopLevelBrowsingContextId)
|
||||
-> Box<Iterator<Item = &'a SessionHistoryEntry> + 'a>
|
||||
{
|
||||
Box::new(
|
||||
self.all_browsing_contexts_iter(top_level_browsing_context_id)
|
||||
.map(|browsing_context| browsing_context.prev.iter().rev()
|
||||
.scan(browsing_context.instant, |prev_instant, entry| {
|
||||
let instant = *prev_instant;
|
||||
*prev_instant = entry.instant;
|
||||
Some((instant, entry))
|
||||
}))
|
||||
.kmerge_by(|a, b| a.0.cmp(&b.0) == Ordering::Greater)
|
||||
.map(|(_, entry)| entry)
|
||||
)
|
||||
}
|
||||
|
||||
/// Is the joint session past empty?
|
||||
fn joint_session_past_is_empty(&self, top_level_browsing_context_id: TopLevelBrowsingContextId) -> bool {
|
||||
self.all_browsing_contexts_iter(top_level_browsing_context_id)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![feature(conservative_impl_trait)]
|
||||
#![cfg_attr(feature = "unstable", feature(conservative_impl_trait))]
|
||||
#![feature(mpsc_select)]
|
||||
|
||||
extern crate backtrace;
|
||||
|
|
|
@ -9,10 +9,6 @@ publish = false
|
|||
name = "servo_geometry"
|
||||
path = "lib.rs"
|
||||
|
||||
[features]
|
||||
# servo as opposed to geckolib
|
||||
servo = ["euclid/unstable"]
|
||||
|
||||
[dependencies]
|
||||
app_units = "0.5"
|
||||
euclid = "0.15"
|
||||
|
|
|
@ -10,6 +10,9 @@ publish = false
|
|||
name = "gfx"
|
||||
path = "lib.rs"
|
||||
|
||||
[features]
|
||||
unstable = ["simd"]
|
||||
|
||||
[dependencies]
|
||||
app_units = "0.5"
|
||||
bitflags = "0.7"
|
||||
|
@ -58,7 +61,7 @@ servo-fontconfig = "0.2.1"
|
|||
xml5ever = {version = "0.10"}
|
||||
|
||||
[target.'cfg(any(target_feature = "sse2", target_feature = "neon"))'.dependencies]
|
||||
simd = "0.2.0"
|
||||
simd = {version = "0.2.0", optional = true}
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
dwrote = "0.4"
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// For SIMD
|
||||
#![cfg_attr(any(target_os = "linux", target_os = "android"), feature(allocator_api))]
|
||||
#![feature(cfg_target_feature)]
|
||||
#![cfg_attr(feature = "unstable", feature(cfg_target_feature))]
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
|
||||
|
@ -53,6 +52,7 @@ extern crate servo_arc;
|
|||
extern crate servo_geometry;
|
||||
extern crate servo_url;
|
||||
#[macro_use] extern crate servo_atoms;
|
||||
#[cfg(feature = "unstable")]
|
||||
#[cfg(any(target_feature = "sse2", target_feature = "neon"))]
|
||||
extern crate simd;
|
||||
extern crate smallvec;
|
||||
|
|
|
@ -9,7 +9,7 @@ use freetype::freetype::FT_Memory;
|
|||
use freetype::freetype::FT_MemoryRec_;
|
||||
use freetype::freetype::FT_New_Library;
|
||||
use heapsize::{HeapSizeOf, heap_size_of};
|
||||
use std::heap::{Heap, Alloc, Layout};
|
||||
use std::mem;
|
||||
use std::os::raw::{c_long, c_void};
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
|
@ -25,46 +25,59 @@ pub struct User {
|
|||
const FT_ALIGNMENT: usize = 1;
|
||||
|
||||
extern fn ft_alloc(mem: FT_Memory, req_size: c_long) -> *mut c_void {
|
||||
unsafe {
|
||||
let layout = Layout::from_size_align(req_size as usize, FT_ALIGNMENT).unwrap();
|
||||
let ptr = Heap.alloc(layout).unwrap() as *mut c_void;
|
||||
let actual_size = heap_size_of(ptr as *const _);
|
||||
assert!(FT_ALIGNMENT == 1);
|
||||
let mut vec = Vec::<u8>::with_capacity(req_size as usize);
|
||||
let ptr = vec.as_mut_ptr() as *mut c_void;
|
||||
mem::forget(vec);
|
||||
|
||||
unsafe {
|
||||
let actual_size = heap_size_of(ptr as *const _);
|
||||
let user = (*mem).user as *mut User;
|
||||
(*user).size += actual_size;
|
||||
|
||||
ptr
|
||||
}
|
||||
|
||||
ptr
|
||||
}
|
||||
|
||||
extern fn ft_free(mem: FT_Memory, ptr: *mut c_void) {
|
||||
unsafe {
|
||||
let actual_size = heap_size_of(ptr as *const _);
|
||||
|
||||
let user = (*mem).user as *mut User;
|
||||
(*user).size -= actual_size;
|
||||
|
||||
let layout = Layout::from_size_align(actual_size, FT_ALIGNMENT).unwrap();
|
||||
Heap.dealloc(ptr as *mut u8, layout);
|
||||
assert!(FT_ALIGNMENT == 1);
|
||||
mem::drop(Vec::<u8>::from_raw_parts(ptr as *mut u8, actual_size, 0))
|
||||
}
|
||||
}
|
||||
|
||||
extern fn ft_realloc(mem: FT_Memory, _cur_size: c_long, new_req_size: c_long,
|
||||
old_ptr: *mut c_void) -> *mut c_void {
|
||||
let old_actual_size;
|
||||
let mut vec;
|
||||
unsafe {
|
||||
let old_actual_size = heap_size_of(old_ptr as *const _);
|
||||
let old_layout = Layout::from_size_align(old_actual_size, FT_ALIGNMENT).unwrap();
|
||||
let new_layout = Layout::from_size_align(new_req_size as usize, FT_ALIGNMENT).unwrap();
|
||||
let result = Heap.realloc(old_ptr as *mut u8, old_layout, new_layout);
|
||||
let new_ptr = result.unwrap() as *mut c_void;
|
||||
let new_actual_size = heap_size_of(new_ptr as *const _);
|
||||
old_actual_size = heap_size_of(old_ptr as *const _);
|
||||
vec = Vec::<u8>::from_raw_parts(old_ptr as *mut u8, old_actual_size, old_actual_size);
|
||||
};
|
||||
|
||||
let new_req_size = new_req_size as usize;
|
||||
if new_req_size > old_actual_size {
|
||||
vec.reserve_exact(new_req_size - old_actual_size)
|
||||
} else if new_req_size < old_actual_size {
|
||||
vec.truncate(new_req_size);
|
||||
vec.shrink_to_fit()
|
||||
}
|
||||
|
||||
let new_ptr = vec.as_mut_ptr() as *mut c_void;
|
||||
mem::forget(vec);
|
||||
|
||||
unsafe {
|
||||
let new_actual_size = heap_size_of(new_ptr as *const _);
|
||||
let user = (*mem).user as *mut User;
|
||||
(*user).size += new_actual_size;
|
||||
(*user).size -= old_actual_size;
|
||||
|
||||
new_ptr
|
||||
}
|
||||
|
||||
new_ptr
|
||||
}
|
||||
|
||||
// A |*mut User| field in a struct triggers a "use of `#[derive]` with a raw pointer" warning from
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
use app_units::Au;
|
||||
use euclid::Point2D;
|
||||
use range::{self, EachIndex, Range, RangeIndex};
|
||||
#[cfg(any(target_feature = "sse2", target_feature = "neon"))]
|
||||
#[cfg(all(feature = "unstable", any(target_feature = "sse2", target_feature = "neon")))]
|
||||
use simd::u32x4;
|
||||
use std::{fmt, mem, u16};
|
||||
use std::cmp::{Ordering, PartialOrd};
|
||||
|
@ -74,6 +74,7 @@ pub type GlyphId = u32;
|
|||
// TODO: make this more type-safe.
|
||||
|
||||
const FLAG_CHAR_IS_SPACE: u32 = 0x40000000;
|
||||
#[cfg(feature = "unstable")]
|
||||
#[cfg(any(target_feature = "sse2", target_feature = "neon"))]
|
||||
const FLAG_CHAR_IS_SPACE_SHIFT: u32 = 30;
|
||||
const FLAG_IS_SIMPLE_GLYPH: u32 = 0x80000000;
|
||||
|
@ -591,6 +592,7 @@ impl<'a> GlyphStore {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "unstable")]
|
||||
#[cfg(any(target_feature = "sse2", target_feature = "neon"))]
|
||||
fn advance_for_byte_range_simple_glyphs(&self, range: &Range<ByteIndex>, extra_word_spacing: Au) -> Au {
|
||||
let advance_mask = u32x4::splat(GLYPH_ADVANCE_MASK);
|
||||
|
@ -634,13 +636,14 @@ impl<'a> GlyphStore {
|
|||
|
||||
/// When SIMD isn't available, fallback to the slow path.
|
||||
#[inline]
|
||||
#[cfg(not(any(target_feature = "sse2", target_feature = "neon")))]
|
||||
#[cfg(not(all(feature = "unstable", any(target_feature = "sse2", target_feature = "neon"))))]
|
||||
fn advance_for_byte_range_simple_glyphs(&self, range: &Range<ByteIndex>, extra_word_spacing: Au) -> Au {
|
||||
self.advance_for_byte_range_slow_path(range, extra_word_spacing)
|
||||
}
|
||||
|
||||
/// Used for SIMD.
|
||||
#[inline]
|
||||
#[cfg(feature = "unstable")]
|
||||
#[cfg(any(target_feature = "sse2", target_feature = "neon"))]
|
||||
#[allow(unsafe_code)]
|
||||
fn transmute_entry_buffer_to_u32_buffer(&self) -> &[u32] {
|
||||
|
|
|
@ -21,7 +21,7 @@ use flow::{BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED};
|
|||
use flow_ref::FlowRef;
|
||||
use fnv::FnvHashMap;
|
||||
use fragment::{CanvasFragmentSource, CoordinateSystem, Fragment, ImageFragmentInfo, ScannedTextFragmentInfo};
|
||||
use fragment::{SpecificFragmentInfo, TruncatedFragmentInfo};
|
||||
use fragment::SpecificFragmentInfo;
|
||||
use gfx::display_list;
|
||||
use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDetails, BorderDisplayItem};
|
||||
use gfx::display_list::{BorderRadii, BoxShadowClipMode, BoxShadowDisplayItem, ClipScrollNode};
|
||||
|
@ -2012,14 +2012,12 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
};
|
||||
|
||||
match self.specific {
|
||||
SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo {
|
||||
text_info: Some(ref text_fragment),
|
||||
..
|
||||
}) |
|
||||
SpecificFragmentInfo::ScannedText(box ref text_fragment) => {
|
||||
SpecificFragmentInfo::TruncatedFragment(ref truncated_fragment)
|
||||
if truncated_fragment.text_info.is_some() => {
|
||||
let text_fragment = truncated_fragment.text_info.as_ref().unwrap();
|
||||
// Create the main text display item.
|
||||
self.build_display_list_for_text_fragment(state,
|
||||
&*text_fragment,
|
||||
&text_fragment,
|
||||
&stacking_relative_content_box,
|
||||
&self.style.get_inheritedtext().text_shadow.0,
|
||||
clip);
|
||||
|
@ -2029,7 +2027,24 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
self.style(),
|
||||
stacking_relative_border_box,
|
||||
&stacking_relative_content_box,
|
||||
&*text_fragment,
|
||||
&text_fragment,
|
||||
clip);
|
||||
}
|
||||
}
|
||||
SpecificFragmentInfo::ScannedText(ref text_fragment) => {
|
||||
// Create the main text display item.
|
||||
self.build_display_list_for_text_fragment(state,
|
||||
&text_fragment,
|
||||
&stacking_relative_content_box,
|
||||
&self.style.get_inheritedtext().text_shadow.0,
|
||||
clip);
|
||||
|
||||
if opts::get().show_debug_fragment_borders {
|
||||
self.build_debug_borders_around_text_fragments(state,
|
||||
self.style(),
|
||||
stacking_relative_border_box,
|
||||
&stacking_relative_content_box,
|
||||
&text_fragment,
|
||||
clip);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ use display_list_builder::{DisplayListBuildState, StackingContextCollectionState
|
|||
use euclid::{Transform3D, Point2D, Vector2D, Rect, Size2D};
|
||||
use flex::FlexFlow;
|
||||
use floats::{Floats, SpeculatedFloatPlacement};
|
||||
use flow_list::{FlowList, MutFlowListIterator};
|
||||
use flow_list::{FlowList, FlowListIterator, MutFlowListIterator};
|
||||
use flow_ref::{FlowRef, WeakFlowRef};
|
||||
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow};
|
||||
use gfx_traits::StackingContextId;
|
||||
|
@ -44,7 +44,7 @@ use multicol::MulticolFlow;
|
|||
use parallel::FlowParallelInfo;
|
||||
use serde::ser::{Serialize, SerializeStruct, Serializer};
|
||||
use servo_geometry::{au_rect_to_f32_rect, f32_rect_to_au_rect, max_rect};
|
||||
use std::{fmt, mem, raw};
|
||||
use std::{fmt, mem};
|
||||
use std::iter::Zip;
|
||||
use std::slice::IterMut;
|
||||
use std::sync::Arc;
|
||||
|
@ -453,13 +453,13 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static {
|
|||
#[allow(unsafe_code)]
|
||||
pub fn base<T: ?Sized + Flow>(this: &T) -> &BaseFlow {
|
||||
unsafe {
|
||||
let obj = mem::transmute::<&&T, &raw::TraitObject>(&this);
|
||||
let obj = mem::transmute::<&&T, &::TraitObject>(&this);
|
||||
mem::transmute::<*mut (), &BaseFlow>(obj.data)
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterates over the children of this immutable flow.
|
||||
pub fn child_iter<'a>(flow: &'a Flow) -> impl Iterator<Item = &'a Flow> {
|
||||
pub fn child_iter<'a>(flow: &'a Flow) -> FlowListIterator {
|
||||
base(flow).children.iter()
|
||||
}
|
||||
|
||||
|
@ -467,7 +467,7 @@ pub fn child_iter<'a>(flow: &'a Flow) -> impl Iterator<Item = &'a Flow> {
|
|||
#[allow(unsafe_code)]
|
||||
pub fn mut_base<T: ?Sized + Flow>(this: &mut T) -> &mut BaseFlow {
|
||||
unsafe {
|
||||
let obj = mem::transmute::<&&mut T, &raw::TraitObject>(&this);
|
||||
let obj = mem::transmute::<&&mut T, &::TraitObject>(&this);
|
||||
mem::transmute::<*mut (), &mut BaseFlow>(obj.data)
|
||||
}
|
||||
}
|
||||
|
@ -1422,7 +1422,7 @@ impl OpaqueFlow {
|
|||
#[allow(unsafe_code)]
|
||||
pub fn from_flow(flow: &Flow) -> OpaqueFlow {
|
||||
unsafe {
|
||||
let object = mem::transmute::<&Flow, raw::TraitObject>(flow);
|
||||
let object = mem::transmute::<&Flow, ::TraitObject>(flow);
|
||||
OpaqueFlow(object.data as usize)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ use flow_ref::FlowRef;
|
|||
use serde::ser::{Serialize, SerializeSeq, Serializer};
|
||||
use serde_json::{Map, Value, to_value};
|
||||
use std::collections::{LinkedList, linked_list};
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// This needs to be reworked now that we have dynamically-sized types in Rust.
|
||||
|
@ -53,6 +54,10 @@ pub struct MutFlowListIterator<'a> {
|
|||
it: linked_list::IterMut<'a, FlowRef>,
|
||||
}
|
||||
|
||||
pub struct FlowListIterator<'a> {
|
||||
it: linked_list::Iter<'a, FlowRef>,
|
||||
}
|
||||
|
||||
impl FlowList {
|
||||
/// Add an element last in the list
|
||||
///
|
||||
|
@ -101,8 +106,10 @@ impl FlowList {
|
|||
/// SECURITY-NOTE(pcwalton): This does not hand out `FlowRef`s by design. Do not add a method
|
||||
/// to do so! See the comment above in `FlowList`.
|
||||
#[inline]
|
||||
pub fn iter<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a Flow> {
|
||||
self.flows.iter().map(|flow| &**flow)
|
||||
pub fn iter<'a>(&'a self) -> FlowListIterator {
|
||||
FlowListIterator {
|
||||
it: self.flows.iter(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Provide a forward iterator with mutable references
|
||||
|
@ -150,12 +157,31 @@ impl FlowList {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> DoubleEndedIterator for FlowListIterator<'a> {
|
||||
fn next_back(&mut self) -> Option<&'a Flow> {
|
||||
self.it.next_back().map(Deref::deref)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> DoubleEndedIterator for MutFlowListIterator<'a> {
|
||||
fn next_back(&mut self) -> Option<&'a mut Flow> {
|
||||
self.it.next_back().map(FlowRef::deref_mut)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for FlowListIterator<'a> {
|
||||
type Item = &'a Flow;
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<&'a Flow> {
|
||||
self.it.next().map(Deref::deref)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.it.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for MutFlowListIterator<'a> {
|
||||
type Item = &'a mut Flow;
|
||||
#[inline]
|
||||
|
|
|
@ -1460,8 +1460,10 @@ impl Fragment {
|
|||
/// Returns true if and only if this fragment is a generated content fragment.
|
||||
pub fn is_unscanned_generated_content(&self) -> bool {
|
||||
match self.specific {
|
||||
SpecificFragmentInfo::GeneratedContent(box GeneratedContentInfo::Empty) => false,
|
||||
SpecificFragmentInfo::GeneratedContent(..) => true,
|
||||
SpecificFragmentInfo::GeneratedContent(ref content) => match **content {
|
||||
GeneratedContentInfo::Empty => false,
|
||||
_ => true,
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -1536,41 +1538,45 @@ impl Fragment {
|
|||
});
|
||||
}
|
||||
|
||||
SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo {
|
||||
text_info: Some(ref text_fragment_info),
|
||||
..
|
||||
}) |
|
||||
SpecificFragmentInfo::ScannedText(box ref text_fragment_info) => {
|
||||
let range = &text_fragment_info.range;
|
||||
|
||||
// See http://dev.w3.org/csswg/css-sizing/#max-content-inline-size.
|
||||
// TODO: Account for soft wrap opportunities.
|
||||
let max_line_inline_size = text_fragment_info.run
|
||||
.metrics_for_range(range)
|
||||
.advance_width;
|
||||
|
||||
let min_line_inline_size = if self.white_space().allow_wrap() {
|
||||
text_fragment_info.run.min_width_for_range(range)
|
||||
} else {
|
||||
max_line_inline_size
|
||||
};
|
||||
|
||||
result.union_block(&IntrinsicISizes {
|
||||
minimum_inline_size: min_line_inline_size,
|
||||
preferred_inline_size: max_line_inline_size,
|
||||
})
|
||||
SpecificFragmentInfo::TruncatedFragment(ref t) if t.text_info.is_some() => {
|
||||
let text_fragment_info = t.text_info.as_ref().unwrap();
|
||||
handle_text(text_fragment_info, self, &mut result)
|
||||
}
|
||||
SpecificFragmentInfo::ScannedText(ref text_fragment_info) => {
|
||||
handle_text(text_fragment_info, self, &mut result)
|
||||
}
|
||||
|
||||
SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo {
|
||||
text_info: None,
|
||||
..
|
||||
}) => return IntrinsicISizesContribution::new(),
|
||||
SpecificFragmentInfo::TruncatedFragment(_) => {
|
||||
return IntrinsicISizesContribution::new()
|
||||
}
|
||||
|
||||
SpecificFragmentInfo::UnscannedText(..) => {
|
||||
panic!("Unscanned text fragments should have been scanned by now!")
|
||||
}
|
||||
};
|
||||
|
||||
fn handle_text(text_fragment_info: &ScannedTextFragmentInfo, self_: &Fragment,
|
||||
result: &mut IntrinsicISizesContribution) {
|
||||
let range = &text_fragment_info.range;
|
||||
|
||||
// See http://dev.w3.org/csswg/css-sizing/#max-content-inline-size.
|
||||
// TODO: Account for soft wrap opportunities.
|
||||
let max_line_inline_size = text_fragment_info.run
|
||||
.metrics_for_range(range)
|
||||
.advance_width;
|
||||
|
||||
let min_line_inline_size = if self_.white_space().allow_wrap() {
|
||||
text_fragment_info.run.min_width_for_range(range)
|
||||
} else {
|
||||
max_line_inline_size
|
||||
};
|
||||
|
||||
result.union_block(&IntrinsicISizes {
|
||||
minimum_inline_size: min_line_inline_size,
|
||||
preferred_inline_size: max_line_inline_size,
|
||||
})
|
||||
}
|
||||
|
||||
// Take borders and padding for parent inline fragments into account.
|
||||
let writing_mode = self.style.writing_mode;
|
||||
if let Some(ref context) = self.inline_context {
|
||||
|
@ -1605,11 +1611,11 @@ impl Fragment {
|
|||
/// this fragment.)
|
||||
pub fn minimum_splittable_inline_size(&self) -> Au {
|
||||
match self.specific {
|
||||
SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo {
|
||||
text_info: Some(ref text),
|
||||
..
|
||||
}) |
|
||||
SpecificFragmentInfo::ScannedText(box ref text) => {
|
||||
SpecificFragmentInfo::TruncatedFragment(ref t) if t.text_info.is_some() => {
|
||||
let text = t.text_info.as_ref().unwrap();
|
||||
text.run.minimum_splittable_inline_size(&text.range)
|
||||
}
|
||||
SpecificFragmentInfo::ScannedText(ref text) => {
|
||||
text.run.minimum_splittable_inline_size(&text.range)
|
||||
}
|
||||
_ => Au(0),
|
||||
|
@ -1914,10 +1920,7 @@ impl Fragment {
|
|||
container_inline_size: Au,
|
||||
container_block_size: Option<Au>) {
|
||||
match self.specific {
|
||||
SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo {
|
||||
text_info: None,
|
||||
..
|
||||
}) |
|
||||
SpecificFragmentInfo::TruncatedFragment(ref t) if t.text_info.is_none() => return,
|
||||
SpecificFragmentInfo::Generic |
|
||||
SpecificFragmentInfo::GeneratedContent(_) |
|
||||
SpecificFragmentInfo::Table |
|
||||
|
@ -1971,11 +1974,14 @@ impl Fragment {
|
|||
}
|
||||
|
||||
// Text
|
||||
SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo {
|
||||
text_info: Some(ref info),
|
||||
..
|
||||
}) |
|
||||
SpecificFragmentInfo::ScannedText(box ref info) => {
|
||||
SpecificFragmentInfo::TruncatedFragment(ref t) if t.text_info.is_some() => {
|
||||
let info = t.text_info.as_ref().unwrap();
|
||||
// Scanned text fragments will have already had their content inline-sizes assigned
|
||||
// by this point.
|
||||
self.border_box.size.inline = info.content_size.inline +
|
||||
self.border_padding.inline_start_end();
|
||||
}
|
||||
SpecificFragmentInfo::ScannedText(ref info) => {
|
||||
// Scanned text fragments will have already had their content inline-sizes assigned
|
||||
// by this point.
|
||||
self.border_box.size.inline = info.content_size.inline +
|
||||
|
@ -2000,10 +2006,7 @@ impl Fragment {
|
|||
/// Ideally, this should follow CSS 2.1 § 10.6.2.
|
||||
pub fn assign_replaced_block_size_if_necessary(&mut self) {
|
||||
match self.specific {
|
||||
SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo {
|
||||
text_info: None,
|
||||
..
|
||||
}) |
|
||||
SpecificFragmentInfo::TruncatedFragment(ref t) if t.text_info.is_none() => return,
|
||||
SpecificFragmentInfo::Generic |
|
||||
SpecificFragmentInfo::GeneratedContent(_) |
|
||||
SpecificFragmentInfo::Table |
|
||||
|
@ -2025,20 +2028,20 @@ impl Fragment {
|
|||
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) |
|
||||
SpecificFragmentInfo::InlineAbsolute(_) |
|
||||
SpecificFragmentInfo::ScannedText(_) |
|
||||
SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo {
|
||||
text_info: Some(_),
|
||||
..
|
||||
}) |
|
||||
SpecificFragmentInfo::TruncatedFragment(_) |
|
||||
SpecificFragmentInfo::Svg(_) => {}
|
||||
}
|
||||
|
||||
match self.specific {
|
||||
// Text
|
||||
SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo {
|
||||
text_info: Some(ref info),
|
||||
..
|
||||
}) |
|
||||
SpecificFragmentInfo::ScannedText(box ref info) => {
|
||||
SpecificFragmentInfo::TruncatedFragment(ref t) if t.text_info.is_some() => {
|
||||
let info = t.text_info.as_ref().unwrap();
|
||||
// Scanned text fragments' content block-sizes are calculated by the text run
|
||||
// scanner during flow construction.
|
||||
self.border_box.size.block = info.content_size.block +
|
||||
self.border_padding.block_start_end();
|
||||
}
|
||||
SpecificFragmentInfo::ScannedText(ref info) => {
|
||||
// Scanned text fragments' content block-sizes are calculated by the text run
|
||||
// scanner during flow construction.
|
||||
self.border_box.size.block = info.content_size.block +
|
||||
|
@ -2115,22 +2118,12 @@ impl Fragment {
|
|||
ascent: ascent,
|
||||
}
|
||||
}
|
||||
SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo {
|
||||
text_info: Some(ref info),
|
||||
..
|
||||
}) |
|
||||
SpecificFragmentInfo::ScannedText(box ref info) => {
|
||||
// Fragments with no glyphs don't contribute any inline metrics.
|
||||
// TODO: Filter out these fragments during flow construction?
|
||||
if info.insertion_point.is_none() && info.content_size.inline == Au(0) {
|
||||
return InlineMetrics::new(Au(0), Au(0), Au(0));
|
||||
}
|
||||
// See CSS 2.1 § 10.8.1.
|
||||
let font_metrics = with_thread_local_font_context(layout_context, |font_context| {
|
||||
text::font_metrics_for_style(font_context, self.style.clone_font())
|
||||
});
|
||||
let line_height = text::line_height_from_style(&*self.style, &font_metrics);
|
||||
InlineMetrics::from_font_metrics(&info.run.font_metrics, line_height)
|
||||
SpecificFragmentInfo::TruncatedFragment(ref t) if t.text_info.is_some() => {
|
||||
let info = t.text_info.as_ref().unwrap();
|
||||
inline_metrics_of_text(info, self, layout_context)
|
||||
}
|
||||
SpecificFragmentInfo::ScannedText(ref info) => {
|
||||
inline_metrics_of_text(info, self, layout_context)
|
||||
}
|
||||
SpecificFragmentInfo::InlineBlock(ref info) => {
|
||||
inline_metrics_of_block(&info.flow_ref, &*self.style)
|
||||
|
@ -2138,10 +2131,7 @@ impl Fragment {
|
|||
SpecificFragmentInfo::InlineAbsoluteHypothetical(ref info) => {
|
||||
inline_metrics_of_block(&info.flow_ref, &*self.style)
|
||||
}
|
||||
SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo {
|
||||
text_info: None,
|
||||
..
|
||||
}) |
|
||||
SpecificFragmentInfo::TruncatedFragment(..) |
|
||||
SpecificFragmentInfo::InlineAbsolute(_) => {
|
||||
InlineMetrics::new(Au(0), Au(0), Au(0))
|
||||
}
|
||||
|
@ -2158,6 +2148,21 @@ impl Fragment {
|
|||
};
|
||||
return inline_metrics;
|
||||
|
||||
fn inline_metrics_of_text(info: &ScannedTextFragmentInfo, self_: &Fragment,
|
||||
layout_context: &LayoutContext) -> InlineMetrics {
|
||||
// Fragments with no glyphs don't contribute any inline metrics.
|
||||
// TODO: Filter out these fragments during flow construction?
|
||||
if info.insertion_point.is_none() && info.content_size.inline == Au(0) {
|
||||
return InlineMetrics::new(Au(0), Au(0), Au(0));
|
||||
}
|
||||
// See CSS 2.1 § 10.8.1.
|
||||
let font_metrics = with_thread_local_font_context(layout_context, |font_context| {
|
||||
text::font_metrics_for_style(font_context, self_.style.clone_font())
|
||||
});
|
||||
let line_height = text::line_height_from_style(&*self_.style, &font_metrics);
|
||||
InlineMetrics::from_font_metrics(&info.run.font_metrics, line_height)
|
||||
}
|
||||
|
||||
fn inline_metrics_of_block(flow: &FlowRef, style: &ComputedValues) -> InlineMetrics {
|
||||
// CSS 2.1 § 10.8: "The height of each inline-level box in the line box is calculated.
|
||||
// For replaced elements, inline-block elements, and inline-table elements, this is the
|
||||
|
@ -2612,12 +2617,12 @@ impl Fragment {
|
|||
|
||||
pub fn requires_line_break_afterward_if_wrapping_on_newlines(&self) -> bool {
|
||||
match self.specific {
|
||||
SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo {
|
||||
text_info: Some(ref scanned_text),
|
||||
..
|
||||
}) |
|
||||
SpecificFragmentInfo::ScannedText(box ref scanned_text) => {
|
||||
scanned_text.requires_line_break_afterward_if_wrapping_on_newlines()
|
||||
SpecificFragmentInfo::TruncatedFragment(ref t) if t.text_info.is_some() => {
|
||||
let text = t.text_info.as_ref().unwrap();
|
||||
text.requires_line_break_afterward_if_wrapping_on_newlines()
|
||||
}
|
||||
SpecificFragmentInfo::ScannedText(ref text) => {
|
||||
text.requires_line_break_afterward_if_wrapping_on_newlines()
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
|
@ -2628,28 +2633,13 @@ impl Fragment {
|
|||
return WhitespaceStrippingResult::RetainFragment
|
||||
}
|
||||
|
||||
match self.specific {
|
||||
SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo {
|
||||
text_info: Some(ref mut scanned_text_fragment_info),
|
||||
..
|
||||
}) |
|
||||
SpecificFragmentInfo::ScannedText(box ref mut scanned_text_fragment_info) => {
|
||||
let leading_whitespace_byte_count = scanned_text_fragment_info.text()
|
||||
.find(|c| !char_is_whitespace(c))
|
||||
.unwrap_or(scanned_text_fragment_info.text().len());
|
||||
|
||||
let whitespace_len = ByteIndex(leading_whitespace_byte_count as isize);
|
||||
let whitespace_range = Range::new(scanned_text_fragment_info.range.begin(),
|
||||
whitespace_len);
|
||||
let text_bounds =
|
||||
scanned_text_fragment_info.run.metrics_for_range(&whitespace_range).bounding_box;
|
||||
self.border_box.size.inline = self.border_box.size.inline - text_bounds.size.width;
|
||||
scanned_text_fragment_info.content_size.inline =
|
||||
scanned_text_fragment_info.content_size.inline - text_bounds.size.width;
|
||||
|
||||
scanned_text_fragment_info.range.adjust_by(whitespace_len, -whitespace_len);
|
||||
|
||||
WhitespaceStrippingResult::RetainFragment
|
||||
return match self.specific {
|
||||
SpecificFragmentInfo::TruncatedFragment(ref mut t) if t.text_info.is_some() => {
|
||||
let scanned_text_fragment_info = t.text_info.as_mut().unwrap();
|
||||
scanned_text(scanned_text_fragment_info, &mut self.border_box)
|
||||
}
|
||||
SpecificFragmentInfo::ScannedText(ref mut scanned_text_fragment_info) => {
|
||||
scanned_text(scanned_text_fragment_info, &mut self.border_box)
|
||||
}
|
||||
SpecificFragmentInfo::UnscannedText(ref mut unscanned_text_fragment_info) => {
|
||||
let mut new_text_string = String::new();
|
||||
|
@ -2677,6 +2667,27 @@ impl Fragment {
|
|||
&unscanned_text_fragment_info)
|
||||
}
|
||||
_ => WhitespaceStrippingResult::RetainFragment,
|
||||
};
|
||||
|
||||
fn scanned_text(scanned_text_fragment_info: &mut ScannedTextFragmentInfo,
|
||||
border_box: &mut LogicalRect<Au>)
|
||||
-> WhitespaceStrippingResult {
|
||||
let leading_whitespace_byte_count = scanned_text_fragment_info.text()
|
||||
.find(|c| !char_is_whitespace(c))
|
||||
.unwrap_or(scanned_text_fragment_info.text().len());
|
||||
|
||||
let whitespace_len = ByteIndex(leading_whitespace_byte_count as isize);
|
||||
let whitespace_range = Range::new(scanned_text_fragment_info.range.begin(),
|
||||
whitespace_len);
|
||||
let text_bounds =
|
||||
scanned_text_fragment_info.run.metrics_for_range(&whitespace_range).bounding_box;
|
||||
border_box.size.inline = border_box.size.inline - text_bounds.size.width;
|
||||
scanned_text_fragment_info.content_size.inline =
|
||||
scanned_text_fragment_info.content_size.inline - text_bounds.size.width;
|
||||
|
||||
scanned_text_fragment_info.range.adjust_by(whitespace_len, -whitespace_len);
|
||||
|
||||
WhitespaceStrippingResult::RetainFragment
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2686,32 +2697,13 @@ impl Fragment {
|
|||
return WhitespaceStrippingResult::RetainFragment
|
||||
}
|
||||
|
||||
match self.specific {
|
||||
SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo {
|
||||
text_info: Some(ref mut scanned_text_fragment_info),
|
||||
..
|
||||
}) |
|
||||
SpecificFragmentInfo::ScannedText(box ref mut scanned_text_fragment_info) => {
|
||||
let mut trailing_whitespace_start_byte = 0;
|
||||
for (i, c) in scanned_text_fragment_info.text().char_indices().rev() {
|
||||
if !char_is_whitespace(c) {
|
||||
trailing_whitespace_start_byte = i + c.len_utf8();
|
||||
break;
|
||||
}
|
||||
}
|
||||
let whitespace_start = ByteIndex(trailing_whitespace_start_byte as isize);
|
||||
let whitespace_len = scanned_text_fragment_info.range.length() - whitespace_start;
|
||||
let mut whitespace_range = Range::new(whitespace_start, whitespace_len);
|
||||
whitespace_range.shift_by(scanned_text_fragment_info.range.begin());
|
||||
|
||||
let text_bounds = scanned_text_fragment_info.run
|
||||
.metrics_for_range(&whitespace_range)
|
||||
.bounding_box;
|
||||
self.border_box.size.inline -= text_bounds.size.width;
|
||||
scanned_text_fragment_info.content_size.inline -= text_bounds.size.width;
|
||||
|
||||
scanned_text_fragment_info.range.extend_by(-whitespace_len);
|
||||
WhitespaceStrippingResult::RetainFragment
|
||||
return match self.specific {
|
||||
SpecificFragmentInfo::TruncatedFragment(ref mut t) if t.text_info.is_some() => {
|
||||
let scanned_text_fragment_info = t.text_info.as_mut().unwrap();
|
||||
scanned_text(scanned_text_fragment_info, &mut self.border_box)
|
||||
}
|
||||
SpecificFragmentInfo::ScannedText(ref mut scanned_text_fragment_info) => {
|
||||
scanned_text(scanned_text_fragment_info, &mut self.border_box)
|
||||
}
|
||||
SpecificFragmentInfo::UnscannedText(ref mut unscanned_text_fragment_info) => {
|
||||
let mut trailing_bidi_control_characters_to_retain = Vec::new();
|
||||
|
@ -2741,6 +2733,31 @@ impl Fragment {
|
|||
&unscanned_text_fragment_info)
|
||||
}
|
||||
_ => WhitespaceStrippingResult::RetainFragment,
|
||||
};
|
||||
|
||||
fn scanned_text(scanned_text_fragment_info: &mut ScannedTextFragmentInfo,
|
||||
border_box: &mut LogicalRect<Au>)
|
||||
-> WhitespaceStrippingResult {
|
||||
let mut trailing_whitespace_start_byte = 0;
|
||||
for (i, c) in scanned_text_fragment_info.text().char_indices().rev() {
|
||||
if !char_is_whitespace(c) {
|
||||
trailing_whitespace_start_byte = i + c.len_utf8();
|
||||
break;
|
||||
}
|
||||
}
|
||||
let whitespace_start = ByteIndex(trailing_whitespace_start_byte as isize);
|
||||
let whitespace_len = scanned_text_fragment_info.range.length() - whitespace_start;
|
||||
let mut whitespace_range = Range::new(whitespace_start, whitespace_len);
|
||||
whitespace_range.shift_by(scanned_text_fragment_info.range.begin());
|
||||
|
||||
let text_bounds = scanned_text_fragment_info.run
|
||||
.metrics_for_range(&whitespace_range)
|
||||
.bounding_box;
|
||||
border_box.size.inline -= text_bounds.size.width;
|
||||
scanned_text_fragment_info.content_size.inline -= text_bounds.size.width;
|
||||
|
||||
scanned_text_fragment_info.range.extend_by(-whitespace_len);
|
||||
WhitespaceStrippingResult::RetainFragment
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,10 +3,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(conservative_impl_trait)]
|
||||
#![feature(nonzero)]
|
||||
#![feature(raw)]
|
||||
|
||||
extern crate app_units;
|
||||
extern crate atomic_refcell;
|
||||
|
@ -94,3 +90,12 @@ pub use self::data::LayoutData;
|
|||
// We can't use servo_arc for everything in layout, because the Flow stuff uses
|
||||
// weak references.
|
||||
use servo_arc::Arc as ServoArc;
|
||||
|
||||
/// Stable copy of std::raw::TraitObject
|
||||
/// test/unit/layout/lib.rs asserts that the memory layout matches.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct TraitObject {
|
||||
pub data: *mut (),
|
||||
pub vtable: *mut (),
|
||||
}
|
||||
|
|
|
@ -9,6 +9,9 @@ publish = false
|
|||
name = "layout_thread"
|
||||
path = "lib.rs"
|
||||
|
||||
[features]
|
||||
unstable = ["parking_lot/nightly", "nonzero/unstable"]
|
||||
|
||||
[dependencies]
|
||||
app_units = "0.5"
|
||||
atomic_refcell = "0.1"
|
||||
|
@ -26,7 +29,8 @@ log = "0.3.5"
|
|||
metrics = {path = "../metrics"}
|
||||
msg = {path = "../msg"}
|
||||
net_traits = {path = "../net_traits"}
|
||||
parking_lot = {version = "0.4", features = ["nightly"]}
|
||||
nonzero = {path = "../nonzero"}
|
||||
parking_lot = "0.4"
|
||||
profile_traits = {path = "../profile_traits"}
|
||||
range = {path = "../range"}
|
||||
rayon = "0.8"
|
||||
|
|
|
@ -31,12 +31,12 @@
|
|||
#![allow(unsafe_code)]
|
||||
|
||||
use atomic_refcell::{AtomicRef, AtomicRefMut, AtomicRefCell};
|
||||
use core::nonzero::NonZero;
|
||||
use gfx_traits::ByteIndex;
|
||||
use html5ever::{LocalName, Namespace};
|
||||
use layout::data::StyleAndLayoutData;
|
||||
use layout::wrapper::GetRawData;
|
||||
use msg::constellation_msg::{BrowsingContextId, PipelineId};
|
||||
use nonzero::NonZeroUsize;
|
||||
use range::Range;
|
||||
use script::layout_exports::{CAN_BE_FRAGMENTED, HAS_DIRTY_DESCENDANTS, IS_IN_DOC};
|
||||
use script::layout_exports::{CharacterDataTypeId, ElementTypeId, HTMLElementTypeId, NodeTypeId};
|
||||
|
@ -79,7 +79,7 @@ use style::shared_lock::{SharedRwLock as StyleSharedRwLock, Locked as StyleLocke
|
|||
use style::str::is_whitespace;
|
||||
|
||||
pub unsafe fn drop_style_and_layout_data(data: OpaqueStyleAndLayoutData) {
|
||||
let ptr: *mut StyleData = data.ptr.get();
|
||||
let ptr = data.ptr.get() as *mut StyleData;
|
||||
let non_opaque: *mut StyleAndLayoutData = ptr as *mut _;
|
||||
let _ = Box::from_raw(non_opaque);
|
||||
}
|
||||
|
@ -235,7 +235,8 @@ impl<'ln> LayoutNode for ServoLayoutNode<'ln> {
|
|||
let ptr: *mut StyleAndLayoutData =
|
||||
Box::into_raw(Box::new(StyleAndLayoutData::new()));
|
||||
let opaque = OpaqueStyleAndLayoutData {
|
||||
ptr: NonZero::new_unchecked(ptr as *mut StyleData),
|
||||
ptr: NonZeroUsize::new_unchecked(ptr as usize),
|
||||
phantom: PhantomData,
|
||||
};
|
||||
self.init_style_and_layout_data(opaque);
|
||||
};
|
||||
|
@ -471,7 +472,7 @@ impl<'le> TElement for ServoLayoutElement<'le> {
|
|||
fn get_data(&self) -> Option<&AtomicRefCell<ElementData>> {
|
||||
unsafe {
|
||||
self.get_style_and_layout_data().map(|d| {
|
||||
&(*d.ptr.get()).element_data
|
||||
&(*(d.ptr.get() as *mut StyleData)).element_data
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -583,7 +584,7 @@ impl<'le> ServoLayoutElement<'le> {
|
|||
|
||||
fn get_style_data(&self) -> Option<&StyleData> {
|
||||
unsafe {
|
||||
self.get_style_and_layout_data().map(|d| &*d.ptr.get())
|
||||
self.get_style_and_layout_data().map(|d| &*(d.ptr.get() as *mut StyleData))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,11 +6,9 @@
|
|||
//! painted.
|
||||
|
||||
#![feature(mpsc_select)]
|
||||
#![feature(nonzero)]
|
||||
|
||||
extern crate app_units;
|
||||
extern crate atomic_refcell;
|
||||
extern crate core;
|
||||
extern crate euclid;
|
||||
extern crate fnv;
|
||||
extern crate gfx;
|
||||
|
@ -29,6 +27,7 @@ extern crate log;
|
|||
extern crate metrics;
|
||||
extern crate msg;
|
||||
extern crate net_traits;
|
||||
extern crate nonzero;
|
||||
extern crate parking_lot;
|
||||
#[macro_use]
|
||||
extern crate profile_traits;
|
||||
|
|
|
@ -9,9 +9,13 @@ publish = false
|
|||
name = "msg"
|
||||
path = "lib.rs"
|
||||
|
||||
[features]
|
||||
unstable = ["nonzero/unstable"]
|
||||
|
||||
[dependencies]
|
||||
bitflags = "0.7"
|
||||
heapsize = "0.4"
|
||||
heapsize_derive = "0.1"
|
||||
serde = { version = "1.0.14", features = [ "unstable" ] }
|
||||
nonzero = {path = "../nonzero"}
|
||||
serde = "1.0.14"
|
||||
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
//! The high-level interface from script to constellation. Using this abstract interface helps
|
||||
//! reduce coupling between these two components.
|
||||
|
||||
use core::nonzero::NonZero;
|
||||
use nonzero::NonZeroU32;
|
||||
use std::cell::Cell;
|
||||
use std::fmt;
|
||||
use webrender_api;
|
||||
|
@ -195,9 +195,9 @@ impl PipelineNamespace {
|
|||
});
|
||||
}
|
||||
|
||||
fn next_index(&mut self) -> NonZero<u32> {
|
||||
fn next_index(&mut self) -> NonZeroU32 {
|
||||
self.index += 1;
|
||||
NonZero::new(self.index).expect("pipeline id index wrapped!")
|
||||
NonZeroU32::new(self.index).expect("pipeline id index wrapped!")
|
||||
}
|
||||
|
||||
fn next_pipeline_id(&mut self) -> PipelineId {
|
||||
|
@ -221,7 +221,7 @@ thread_local!(pub static PIPELINE_NAMESPACE: Cell<Option<PipelineNamespace>> = C
|
|||
pub struct PipelineNamespaceId(pub u32);
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
|
||||
pub struct PipelineIndex(pub NonZero<u32>);
|
||||
pub struct PipelineIndex(pub NonZeroU32);
|
||||
known_heap_size!(0, PipelineIndex);
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, HeapSizeOf, Ord, PartialEq, PartialOrd, Serialize)]
|
||||
|
@ -264,7 +264,7 @@ impl fmt::Display for PipelineId {
|
|||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
|
||||
pub struct BrowsingContextIndex(pub NonZero<u32>);
|
||||
pub struct BrowsingContextIndex(pub NonZeroU32);
|
||||
known_heap_size!(0, BrowsingContextIndex);
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, HeapSizeOf, Ord, PartialEq, PartialOrd, Serialize)]
|
||||
|
@ -339,11 +339,15 @@ impl PartialEq<BrowsingContextId> for TopLevelBrowsingContextId {
|
|||
// We provide ids just for unit testing.
|
||||
pub const TEST_NAMESPACE: PipelineNamespaceId = PipelineNamespaceId(1234);
|
||||
#[allow(unsafe_code)]
|
||||
pub const TEST_PIPELINE_INDEX: PipelineIndex = unsafe { PipelineIndex(NonZero::new_unchecked(5678)) };
|
||||
#[cfg(feature = "unstable")]
|
||||
pub const TEST_PIPELINE_INDEX: PipelineIndex = unsafe { PipelineIndex(NonZeroU32::new_unchecked(5678)) };
|
||||
#[cfg(feature = "unstable")]
|
||||
pub const TEST_PIPELINE_ID: PipelineId = PipelineId { namespace_id: TEST_NAMESPACE, index: TEST_PIPELINE_INDEX };
|
||||
#[allow(unsafe_code)]
|
||||
#[cfg(feature = "unstable")]
|
||||
pub const TEST_BROWSING_CONTEXT_INDEX: BrowsingContextIndex =
|
||||
unsafe { BrowsingContextIndex(NonZero::new_unchecked(8765)) };
|
||||
unsafe { BrowsingContextIndex(NonZeroU32::new_unchecked(8765)) };
|
||||
#[cfg(feature = "unstable")]
|
||||
pub const TEST_BROWSING_CONTEXT_ID: BrowsingContextId =
|
||||
BrowsingContextId { namespace_id: TEST_NAMESPACE, index: TEST_BROWSING_CONTEXT_INDEX };
|
||||
|
||||
|
|
|
@ -2,16 +2,13 @@
|
|||
* 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/. */
|
||||
|
||||
#![feature(const_fn)]
|
||||
#![feature(const_nonzero_new)]
|
||||
#![feature(nonzero)]
|
||||
#![deny(unsafe_code)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
extern crate core;
|
||||
#[macro_use] extern crate heapsize;
|
||||
#[macro_use] extern crate heapsize_derive;
|
||||
extern crate nonzero;
|
||||
#[macro_use] extern crate serde;
|
||||
extern crate webrender_api;
|
||||
|
||||
|
|
15
components/nonzero/Cargo.toml
Normal file
15
components/nonzero/Cargo.toml
Normal file
|
@ -0,0 +1,15 @@
|
|||
[package]
|
||||
name = "nonzero"
|
||||
version = "0.0.1"
|
||||
authors = ["The Servo Project Developers"]
|
||||
license = "MPL-2.0"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
[features]
|
||||
unstable = ["serde/unstable"]
|
||||
|
||||
[dependencies]
|
||||
serde = "1.0.14"
|
121
components/nonzero/lib.rs
Normal file
121
components/nonzero/lib.rs
Normal file
|
@ -0,0 +1,121 @@
|
|||
/* 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/. */
|
||||
|
||||
//! `NonZero*` types that are either `core::nonzero::NonZero<_>`
|
||||
//! or some stable types with an equivalent API (but no memory layout optimization).
|
||||
|
||||
#![cfg_attr(feature = "unstable", feature(nonzero))]
|
||||
#![cfg_attr(feature = "unstable", feature(const_fn))]
|
||||
#![cfg_attr(feature = "unstable", feature(const_nonzero_new))]
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde;
|
||||
|
||||
pub use imp::*;
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
mod imp {
|
||||
extern crate core;
|
||||
use self::core::nonzero::NonZero;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
|
||||
pub struct NonZeroU32(NonZero<u32>);
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
|
||||
pub struct NonZeroUsize(NonZero<usize>);
|
||||
|
||||
impl NonZeroU32 {
|
||||
#[inline] pub const unsafe fn new_unchecked(x: u32) -> Self { NonZeroU32(NonZero::new_unchecked(x)) }
|
||||
#[inline] pub fn new(x: u32) -> Option<Self> { NonZero::new(x).map(NonZeroU32) }
|
||||
#[inline] pub fn get(self) -> u32 { self.0.get() }
|
||||
}
|
||||
|
||||
impl NonZeroUsize {
|
||||
#[inline] pub const unsafe fn new_unchecked(x: usize) -> Self { NonZeroUsize(NonZero::new_unchecked(x)) }
|
||||
#[inline] pub fn new(x: usize) -> Option<Self> { NonZero::new(x).map(NonZeroUsize) }
|
||||
#[inline] pub fn get(self) -> usize { self.0.get() }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "unstable"))]
|
||||
mod imp {
|
||||
use std::cmp;
|
||||
use std::hash;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
|
||||
pub struct NonZeroU32(u32);
|
||||
|
||||
impl NonZeroU32 {
|
||||
#[inline]
|
||||
pub fn new(x: u32) -> Option<Self> {
|
||||
if x != 0 {
|
||||
Some(NonZeroU32(x))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn new_unchecked(x: u32) -> Self {
|
||||
NonZeroU32(x)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get(self) -> u32 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq)]
|
||||
pub struct NonZeroUsize(&'static ());
|
||||
|
||||
impl NonZeroUsize {
|
||||
#[inline]
|
||||
pub fn new(x: usize) -> Option<Self> {
|
||||
if x != 0 {
|
||||
Some(unsafe { Self::new_unchecked(x) })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn new_unchecked(x: usize) -> Self {
|
||||
NonZeroUsize(&*(x as *const ()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get(self) -> usize {
|
||||
self.0 as *const () as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for NonZeroUsize {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.get() == other.get()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for NonZeroUsize {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
|
||||
self.get().partial_cmp(&other.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for NonZeroUsize {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &Self) -> cmp::Ordering {
|
||||
self.get().cmp(&other.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl hash::Hash for NonZeroUsize {
|
||||
#[inline]
|
||||
fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
|
||||
self.get().hash(hasher)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,6 +9,9 @@ publish = false
|
|||
name = "profile"
|
||||
path = "lib.rs"
|
||||
|
||||
[features]
|
||||
unstable = []
|
||||
|
||||
[dependencies]
|
||||
profile_traits = {path = "../profile_traits"}
|
||||
influent = "0.4"
|
||||
|
|
|
@ -2,16 +2,17 @@
|
|||
* 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/. */
|
||||
|
||||
#![cfg_attr(not(target_os = "windows"), feature(alloc_jemalloc))]
|
||||
#![cfg_attr(all(feature = "unstable", not(target_os = "windows")), feature(alloc_jemalloc))]
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
|
||||
#[allow(unused_extern_crates)]
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
#[cfg(all(feature = "unstable", not(target_os = "windows")))]
|
||||
extern crate alloc_jemalloc;
|
||||
extern crate heartbeats_simple;
|
||||
extern crate influent;
|
||||
extern crate ipc_channel;
|
||||
#[allow(unused_extern_crates)]
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
extern crate libc;
|
||||
#[macro_use]
|
||||
|
|
|
@ -353,14 +353,16 @@ impl ReportsForest {
|
|||
//---------------------------------------------------------------------------
|
||||
|
||||
mod system_reporter {
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
use libc::{c_char, c_int, c_void, size_t};
|
||||
#[cfg(all(feature = "unstable", not(target_os = "windows")))]
|
||||
use libc::{c_char, c_void, size_t};
|
||||
#[cfg(target_os = "linux")]
|
||||
use libc::c_int;
|
||||
use profile_traits::mem::{Report, ReportKind, ReporterRequest};
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
#[cfg(all(feature = "unstable", not(target_os = "windows")))]
|
||||
use std::ffi::CString;
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
#[cfg(all(feature = "unstable", not(target_os = "windows")))]
|
||||
use std::mem::size_of;
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
#[cfg(all(feature = "unstable", not(target_os = "windows")))]
|
||||
use std::ptr::null_mut;
|
||||
use super::{JEMALLOC_HEAP_ALLOCATED_STR, SYSTEM_HEAP_ALLOCATED_STR};
|
||||
#[cfg(target_os = "macos")]
|
||||
|
@ -457,14 +459,14 @@ mod system_reporter {
|
|||
None
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
#[cfg(all(feature = "unstable", not(target_os = "windows")))]
|
||||
extern {
|
||||
#[cfg_attr(any(target_os = "macos", target_os = "android"), link_name = "je_mallctl")]
|
||||
fn mallctl(name: *const c_char, oldp: *mut c_void, oldlenp: *mut size_t,
|
||||
newp: *mut c_void, newlen: size_t) -> c_int;
|
||||
newp: *mut c_void, newlen: size_t) -> ::libc::c_int;
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
#[cfg(all(feature = "unstable", not(target_os = "windows")))]
|
||||
fn jemalloc_stat(value_name: &str) -> Option<usize> {
|
||||
// Before we request the measurement of interest, we first send an "epoch"
|
||||
// request. Without that jemalloc gives cached statistics(!) which can be
|
||||
|
@ -500,7 +502,7 @@ mod system_reporter {
|
|||
Some(value as usize)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
#[cfg(any(target_os = "windows", not(feature = "unstable")))]
|
||||
fn jemalloc_stat(_value_name: &str) -> Option<usize> {
|
||||
None
|
||||
}
|
||||
|
|
|
@ -12,3 +12,4 @@ path = "lib.rs"
|
|||
[dependencies]
|
||||
lazy_static = "0.2"
|
||||
log = "0.3.5"
|
||||
nonzero = {path = "../nonzero"}
|
||||
|
|
|
@ -10,13 +10,11 @@
|
|||
//! It provides the same interface as https://github.com/rust-lang/rust/blob/master/src/libstd/sys/common/remutex.rs
|
||||
//! so if those types are ever exported, we should be able to replace this implemtation.
|
||||
|
||||
#![feature(nonzero)]
|
||||
|
||||
extern crate core;
|
||||
extern crate nonzero;
|
||||
#[macro_use] extern crate lazy_static;
|
||||
#[macro_use] extern crate log;
|
||||
|
||||
use core::nonzero::NonZero;
|
||||
use nonzero::NonZeroUsize;
|
||||
use std::cell::{Cell, UnsafeCell};
|
||||
use std::ops::Deref;
|
||||
use std::sync::{LockResult, Mutex, MutexGuard, PoisonError, TryLockError, TryLockResult};
|
||||
|
@ -27,7 +25,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
|
|||
// TODO: can we use the thread-id crate for this?
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
pub struct ThreadId(NonZero<usize>);
|
||||
pub struct ThreadId(NonZeroUsize);
|
||||
|
||||
lazy_static!{ static ref THREAD_COUNT: AtomicUsize = AtomicUsize::new(1); }
|
||||
|
||||
|
@ -35,7 +33,7 @@ impl ThreadId {
|
|||
#[allow(unsafe_code)]
|
||||
fn new() -> ThreadId {
|
||||
let number = THREAD_COUNT.fetch_add(1, Ordering::SeqCst);
|
||||
ThreadId(NonZero::new(number).unwrap())
|
||||
ThreadId(NonZeroUsize::new(number).unwrap())
|
||||
}
|
||||
pub fn current() -> ThreadId {
|
||||
THREAD_ID.with(|tls| tls.clone())
|
||||
|
@ -59,13 +57,13 @@ impl AtomicOptThreadId {
|
|||
#[allow(unsafe_code)]
|
||||
pub fn load(&self, ordering: Ordering) -> Option<ThreadId> {
|
||||
let number = self.0.load(ordering);
|
||||
NonZero::new(number).map(ThreadId)
|
||||
NonZeroUsize::new(number).map(ThreadId)
|
||||
}
|
||||
#[allow(unsafe_code)]
|
||||
pub fn swap(&self, value: Option<ThreadId>, ordering: Ordering) -> Option<ThreadId> {
|
||||
let number = value.map(|id| id.0.get()).unwrap_or(0);
|
||||
let number = self.0.swap(number, ordering);
|
||||
NonZero::new(number).map(ThreadId)
|
||||
NonZeroUsize::new(number).map(ThreadId)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ log = "0.3.5"
|
|||
metrics = {path = "../metrics"}
|
||||
msg = {path = "../msg"}
|
||||
net_traits = {path = "../net_traits"}
|
||||
nonzero = {path = "../nonzero"}
|
||||
profile_traits = {path = "../profile_traits"}
|
||||
range = {path = "../range"}
|
||||
script_traits = {path = "../script_traits"}
|
||||
|
|
|
@ -7,12 +7,10 @@
|
|||
//! to depend on script.
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![feature(nonzero)]
|
||||
|
||||
extern crate app_units;
|
||||
extern crate atomic_refcell;
|
||||
extern crate canvas_traits;
|
||||
extern crate core;
|
||||
extern crate cssparser;
|
||||
extern crate euclid;
|
||||
extern crate gfx_traits;
|
||||
|
@ -26,6 +24,7 @@ extern crate log;
|
|||
extern crate metrics;
|
||||
extern crate msg;
|
||||
extern crate net_traits;
|
||||
extern crate nonzero;
|
||||
extern crate profile_traits;
|
||||
extern crate range;
|
||||
extern crate script_traits;
|
||||
|
@ -43,12 +42,13 @@ pub mod wrapper_traits;
|
|||
|
||||
use atomic_refcell::AtomicRefCell;
|
||||
use canvas_traits::canvas::CanvasMsg;
|
||||
use core::nonzero::NonZero;
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use libc::c_void;
|
||||
use net_traits::image_cache::PendingImageId;
|
||||
use nonzero::NonZeroUsize;
|
||||
use script_traits::UntrustedNodeAddress;
|
||||
use servo_url::ServoUrl;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::atomic::AtomicIsize;
|
||||
use style::data::ElementData;
|
||||
|
||||
|
@ -78,7 +78,8 @@ pub struct OpaqueStyleAndLayoutData {
|
|||
// NB: We really store a `StyleAndLayoutData` here, so be careful!
|
||||
#[ignore_heap_size_of = "TODO(#6910) Box value that should be counted but \
|
||||
the type lives in layout"]
|
||||
pub ptr: NonZero<*mut StyleData>
|
||||
pub ptr: NonZeroUsize,
|
||||
pub phantom: PhantomData<*mut StyleData>,
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
|
|
|
@ -20,7 +20,7 @@ doctest = false
|
|||
|
||||
[features]
|
||||
gecko_like_types = []
|
||||
unstable = []
|
||||
bench = []
|
||||
|
||||
[dependencies]
|
||||
bitflags = "0.7"
|
||||
|
|
|
@ -346,7 +346,7 @@ fn create_and_insert_some_stuff() {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
#[cfg(feature = "bench")]
|
||||
#[cfg(test)]
|
||||
mod bench {
|
||||
extern crate test;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Make |cargo bench| work.
|
||||
#![cfg_attr(feature = "unstable", feature(test))]
|
||||
#![cfg_attr(feature = "bench", feature(test))]
|
||||
|
||||
#[macro_use] extern crate bitflags;
|
||||
#[macro_use] extern crate cssparser;
|
||||
|
|
|
@ -12,13 +12,18 @@ path = "lib.rs"
|
|||
crate-type = ["rlib"]
|
||||
|
||||
[features]
|
||||
default = ["webdriver", "max_log_level"]
|
||||
max_log_level = ["log/release_max_level_info"]
|
||||
webdriver = ["webdriver_server"]
|
||||
energy-profiling = ["profile_traits/energy-profiling"]
|
||||
debugmozjs = ["script/debugmozjs"]
|
||||
googlevr = ["webvr/googlevr"]
|
||||
oculusvr = ["webvr/oculusvr"]
|
||||
unstable = [
|
||||
"euclid/unstable",
|
||||
"gfx/unstable",
|
||||
"msg/unstable",
|
||||
"profile/unstable",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
bluetooth_traits = {path = "../bluetooth_traits"}
|
||||
|
|
|
@ -29,13 +29,15 @@ servo_remutex_tests = {path = "../../tests/unit/servo_remutex"}
|
|||
style_tests = {path = "../../tests/unit/style"}
|
||||
|
||||
[features]
|
||||
default = ["webdriver", "max_log_level"]
|
||||
default = ["unstable", "default-except-unstable"]
|
||||
default-except-unstable = ["webdriver", "max_log_level"]
|
||||
max_log_level = ["log/release_max_level_info"]
|
||||
webdriver = ["libservo/webdriver_server"]
|
||||
energy-profiling = ["libservo/energy-profiling"]
|
||||
debugmozjs = ["libservo/debugmozjs"]
|
||||
googlevr = ["libservo/googlevr"]
|
||||
oculusvr = ["libservo/oculusvr"]
|
||||
unstable = ["libservo/unstable"]
|
||||
|
||||
[dependencies]
|
||||
backtrace = "0.3"
|
||||
|
|
|
@ -2,7 +2,36 @@
|
|||
* 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/. */
|
||||
|
||||
#![feature(raw)]
|
||||
|
||||
extern crate layout;
|
||||
#[macro_use] extern crate size_of_test;
|
||||
|
||||
#[cfg(all(test, target_pointer_width = "64"))] mod size_of;
|
||||
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
use std::raw;
|
||||
|
||||
#[test]
|
||||
fn test_trait_object_layout() {
|
||||
assert_eq!(mem::size_of::<raw::TraitObject>(), mem::size_of::<layout::TraitObject>());
|
||||
let null: *mut () = ptr::null_mut();
|
||||
let a = raw::TraitObject {
|
||||
data: null,
|
||||
vtable: null,
|
||||
};
|
||||
let b = layout::TraitObject {
|
||||
data: null,
|
||||
vtable: null,
|
||||
};
|
||||
|
||||
fn offset<T, U>(struct_: &T, field: &U) -> usize {
|
||||
let addr_struct = struct_ as *const T as usize;
|
||||
let addr_field = field as *const U as usize;
|
||||
addr_field - addr_struct
|
||||
}
|
||||
|
||||
assert_eq!(offset(&a, &a.data), offset(&b, &b.data));
|
||||
assert_eq!(offset(&a, &a.vtable), offset(&b, &b.vtable));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue