Move non-gfx things out of gfx_traits and create a base crate (#32296)

For a long time, `gfx_traits` has held a lot of things unrelated to graphics
and also unrelated to the `gfx` crate (which is mostly about fonts).
This is a cleanup which does a few things:

1. Move non `gfx` crate things out of `gfx_traits`. This is important in
   order to prevent dependency cycles with a different integration between
   layout, script, and fonts.
2. Rename the `msg` crate to `base`. It didn't really contain anything
   to do with messages and instead mostly holds ids, which are used
   across many different crates in Servo. This new crate will hold the
   *rare* data types that are widely used.

Details:

 - All BackgroundHangMonitor-related things from base to a new
   `background_hang_monitor_api` crate.
 - Moved `TraversalDirection` to `script_traits`
 - Moved `Epoch`-related things from `gfx_traits` to `base`.
 - Moved `PrintTree` to base. This should be widely useful in Servo.
 - Moved `WebrenderApi` from `base` to `webrender_traits` and renamed it
   to `WebRenderFontApi`.
This commit is contained in:
Martin Robinson 2024-05-17 14:28:58 +02:00 committed by GitHub
parent 1017533297
commit 3398fc017b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
163 changed files with 709 additions and 632 deletions

View file

@ -0,0 +1,24 @@
[package]
name = "background_hang_monitor_api"
version = "0.0.1"
authors = ["The Servo Project Developers"]
license = "MPL-2.0"
edition = "2018"
publish = false
[lib]
name = "background_hang_monitor_api"
path = "lib.rs"
test = false
doctest = false
[dependencies]
base = { workspace = true }
ipc-channel = { workspace = true }
lazy_static = { workspace = true }
malloc_size_of = { workspace = true }
malloc_size_of_derive = { workspace = true }
parking_lot = { workspace = true }
serde = { workspace = true }
size_of_test = { workspace = true }
webrender_api = { workspace = true }

View file

@ -0,0 +1,212 @@
/* 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 https://mozilla.org/MPL/2.0/. */
#![deny(unsafe_code)]
//! An API interface to the BackgroundHangMonitor.
use std::time::Duration;
use std::{fmt, mem};
use base::id::PipelineId;
use ipc_channel::ipc::IpcSender;
use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
/// The equivalent of script::script_runtime::ScriptEventCategory
pub enum ScriptHangAnnotation {
AttachLayout,
ConstellationMsg,
DevtoolsMsg,
DocumentEvent,
DomEvent,
FileRead,
FormPlannedNavigation,
ImageCacheMsg,
InputEvent,
HistoryEvent,
NetworkEvent,
Resize,
ScriptEvent,
SetScrollState,
SetViewport,
StylesheetLoad,
TimerEvent,
UpdateReplacedElement,
WebSocketEvent,
WorkerEvent,
WorkletEvent,
ServiceWorkerEvent,
EnterFullscreen,
ExitFullscreen,
WebVREvent,
PerformanceTimelineTask,
PortMessage,
WebGPUMsg,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub enum HangAnnotation {
Script(ScriptHangAnnotation),
}
/// Hang-alerts are sent by the monitor to the constellation.
#[derive(Deserialize, Serialize)]
pub enum HangMonitorAlert {
/// A component hang has been detected.
Hang(HangAlert),
/// Report a completed sampled profile.
Profile(Vec<u8>),
}
impl fmt::Debug for HangMonitorAlert {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
HangMonitorAlert::Hang(..) => write!(fmt, "Hang"),
HangMonitorAlert::Profile(..) => write!(fmt, "Profile"),
}
}
}
/// Hang-alerts are sent by the monitor to the constellation.
#[derive(Deserialize, Serialize)]
pub enum HangAlert {
/// Report a transient hang.
Transient(MonitoredComponentId, HangAnnotation),
/// Report a permanent hang.
Permanent(MonitoredComponentId, HangAnnotation, Option<HangProfile>),
}
impl fmt::Debug for HangAlert {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let (annotation, profile) = match self {
HangAlert::Transient(component_id, annotation) => {
write!(
fmt,
"\n The following component is experiencing a transient hang: \n {:?}",
component_id
)?;
(*annotation, None)
},
HangAlert::Permanent(component_id, annotation, profile) => {
write!(
fmt,
"\n The following component is experiencing a permanent hang: \n {:?}",
component_id
)?;
(*annotation, profile.clone())
},
};
write!(fmt, "\n Annotation for the hang:\n{:?}", annotation)?;
if let Some(profile) = profile {
write!(fmt, "\n {:?}", profile)?;
}
Ok(())
}
}
#[derive(Clone, Deserialize, Serialize)]
pub struct HangProfileSymbol {
pub name: Option<String>,
pub filename: Option<String>,
pub lineno: Option<u32>,
}
#[derive(Clone, Deserialize, Serialize)]
/// Info related to the activity of an hanging component.
pub struct HangProfile {
pub backtrace: Vec<HangProfileSymbol>,
}
impl fmt::Debug for HangProfile {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let hex_width = mem::size_of::<usize>() * 2 + 2;
write!(fmt, "HangProfile backtrace:")?;
if self.backtrace.is_empty() {
write!(fmt, "backtrace failed to resolve")?;
return Ok(());
}
for symbol in self.backtrace.iter() {
write!(fmt, "\n {:1$}", "", hex_width)?;
if let Some(ref name) = symbol.name {
write!(fmt, " - {}", name)?;
} else {
write!(fmt, " - <unknown>")?;
}
if let (Some(ref file), Some(ref line)) = (symbol.filename.as_ref(), symbol.lineno) {
write!(fmt, "\n {:3$}at {}:{}", "", file, line, hex_width)?;
}
}
Ok(())
}
}
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum MonitoredComponentType {
Script,
}
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct MonitoredComponentId(pub PipelineId, pub MonitoredComponentType);
/// A handle to register components for hang monitoring,
/// and to receive a means to communicate with the underlying hang monitor worker.
pub trait BackgroundHangMonitorRegister: BackgroundHangMonitorClone + Send {
/// Register a component for hang monitoring:
/// to be called from within the thread to be monitored for hangs.
fn register_component(
&self,
component: MonitoredComponentId,
transient_hang_timeout: Duration,
permanent_hang_timeout: Duration,
exit_signal: Option<Box<dyn BackgroundHangMonitorExitSignal>>,
) -> Box<dyn BackgroundHangMonitor>;
}
impl Clone for Box<dyn BackgroundHangMonitorRegister> {
fn clone(&self) -> Box<dyn BackgroundHangMonitorRegister> {
self.clone_box()
}
}
pub trait BackgroundHangMonitorClone {
fn clone_box(&self) -> Box<dyn BackgroundHangMonitorRegister>;
}
/// Proxy methods to communicate with the background hang monitor
pub trait BackgroundHangMonitor {
/// Notify the start of handling an event.
fn notify_activity(&self, annotation: HangAnnotation);
/// Notify the start of waiting for a new event to come in.
fn notify_wait(&self);
/// Unregister the component from monitor.
fn unregister(&self);
}
/// A means for the BHM to signal a monitored component to exit.
/// Useful when the component is hanging, and cannot be notified via the usual way.
/// The component should implement this in a way allowing for the signal to be received when hanging,
/// if at all.
pub trait BackgroundHangMonitorExitSignal: Send {
/// Called by the BHM, to notify the monitored component to exit.
fn signal_to_exit(&self);
}
/// Messages to control the sampling profiler.
#[derive(Deserialize, Serialize)]
pub enum BackgroundHangMonitorControlMsg {
/// Enable the sampler, with a given sampling rate and max total sampling duration.
EnableSampler(Duration, Duration),
DisableSampler,
/// Exit, and propagate the signal to monitored components.
Exit(IpcSender<()>),
}

View file

@ -1,5 +1,5 @@
[package]
name = "msg"
name = "base"
version = "0.0.1"
authors = ["The Servo Project Developers"]
license = "MPL-2.0"
@ -7,7 +7,7 @@ edition = "2018"
publish = false
[lib]
name = "msg"
name = "base"
path = "lib.rs"
test = false
doctest = false

View file

@ -2,16 +2,14 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
//! The high-level interface from script to constellation. Using this abstract interface helps
//! reduce coupling between these two components.
//! Namespaces and ids shared by many crates in Servo.
#![allow(clippy::new_without_default)]
use std::cell::Cell;
use std::fmt;
use std::num::NonZeroU32;
use std::sync::Arc;
use std::time::Duration;
use std::{fmt, mem};
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use lazy_static::lazy_static;
@ -65,12 +63,6 @@ macro_rules! namespace_id {
};
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum TraversalDirection {
Forward(usize),
Back(usize),
}
#[derive(Debug, Deserialize, Serialize)]
/// Request a pipeline-namespace id from the constellation.
pub struct PipelineNamespaceRequest(pub IpcSender<PipelineNamespaceId>);
@ -444,221 +436,3 @@ pub const TEST_BROWSING_CONTEXT_ID: BrowsingContextId = BrowsingContextId {
namespace_id: TEST_NAMESPACE,
index: TEST_BROWSING_CONTEXT_INDEX,
};
// Used to specify the kind of input method editor appropriate to edit a field.
// This is a subset of htmlinputelement::InputType because some variants of InputType
// don't make sense in this context.
#[derive(Debug, Deserialize, Serialize)]
pub enum InputMethodType {
Color,
Date,
DatetimeLocal,
Email,
Month,
Number,
Password,
Search,
Tel,
Text,
Time,
Url,
Week,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
/// The equivalent of script::script_runtime::ScriptEventCategory
pub enum ScriptHangAnnotation {
AttachLayout,
ConstellationMsg,
DevtoolsMsg,
DocumentEvent,
DomEvent,
FileRead,
FormPlannedNavigation,
ImageCacheMsg,
InputEvent,
HistoryEvent,
NetworkEvent,
Resize,
ScriptEvent,
SetScrollState,
SetViewport,
StylesheetLoad,
TimerEvent,
UpdateReplacedElement,
WebSocketEvent,
WorkerEvent,
WorkletEvent,
ServiceWorkerEvent,
EnterFullscreen,
ExitFullscreen,
WebVREvent,
PerformanceTimelineTask,
PortMessage,
WebGPUMsg,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub enum HangAnnotation {
Script(ScriptHangAnnotation),
}
/// Hang-alerts are sent by the monitor to the constellation.
#[derive(Deserialize, Serialize)]
pub enum HangMonitorAlert {
/// A component hang has been detected.
Hang(HangAlert),
/// Report a completed sampled profile.
Profile(Vec<u8>),
}
impl fmt::Debug for HangMonitorAlert {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
HangMonitorAlert::Hang(..) => write!(fmt, "Hang"),
HangMonitorAlert::Profile(..) => write!(fmt, "Profile"),
}
}
}
/// Hang-alerts are sent by the monitor to the constellation.
#[derive(Deserialize, Serialize)]
pub enum HangAlert {
/// Report a transient hang.
Transient(MonitoredComponentId, HangAnnotation),
/// Report a permanent hang.
Permanent(MonitoredComponentId, HangAnnotation, Option<HangProfile>),
}
impl fmt::Debug for HangAlert {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let (annotation, profile) = match self {
HangAlert::Transient(component_id, annotation) => {
write!(
fmt,
"\n The following component is experiencing a transient hang: \n {:?}",
component_id
)?;
(*annotation, None)
},
HangAlert::Permanent(component_id, annotation, profile) => {
write!(
fmt,
"\n The following component is experiencing a permanent hang: \n {:?}",
component_id
)?;
(*annotation, profile.clone())
},
};
write!(fmt, "\n Annotation for the hang:\n{:?}", annotation)?;
if let Some(profile) = profile {
write!(fmt, "\n {:?}", profile)?;
}
Ok(())
}
}
#[derive(Clone, Deserialize, Serialize)]
pub struct HangProfileSymbol {
pub name: Option<String>,
pub filename: Option<String>,
pub lineno: Option<u32>,
}
#[derive(Clone, Deserialize, Serialize)]
/// Info related to the activity of an hanging component.
pub struct HangProfile {
pub backtrace: Vec<HangProfileSymbol>,
}
impl fmt::Debug for HangProfile {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let hex_width = mem::size_of::<usize>() * 2 + 2;
write!(fmt, "HangProfile backtrace:")?;
if self.backtrace.is_empty() {
write!(fmt, "backtrace failed to resolve")?;
return Ok(());
}
for symbol in self.backtrace.iter() {
write!(fmt, "\n {:1$}", "", hex_width)?;
if let Some(ref name) = symbol.name {
write!(fmt, " - {}", name)?;
} else {
write!(fmt, " - <unknown>")?;
}
if let (Some(ref file), Some(ref line)) = (symbol.filename.as_ref(), symbol.lineno) {
write!(fmt, "\n {:3$}at {}:{}", "", file, line, hex_width)?;
}
}
Ok(())
}
}
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum MonitoredComponentType {
Script,
}
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct MonitoredComponentId(pub PipelineId, pub MonitoredComponentType);
/// A handle to register components for hang monitoring,
/// and to receive a means to communicate with the underlying hang monitor worker.
pub trait BackgroundHangMonitorRegister: BackgroundHangMonitorClone + Send {
/// Register a component for hang monitoring:
/// to be called from within the thread to be monitored for hangs.
fn register_component(
&self,
component: MonitoredComponentId,
transient_hang_timeout: Duration,
permanent_hang_timeout: Duration,
exit_signal: Option<Box<dyn BackgroundHangMonitorExitSignal>>,
) -> Box<dyn BackgroundHangMonitor>;
}
impl Clone for Box<dyn BackgroundHangMonitorRegister> {
fn clone(&self) -> Box<dyn BackgroundHangMonitorRegister> {
self.clone_box()
}
}
pub trait BackgroundHangMonitorClone {
fn clone_box(&self) -> Box<dyn BackgroundHangMonitorRegister>;
}
/// Proxy methods to communicate with the background hang monitor
pub trait BackgroundHangMonitor {
/// Notify the start of handling an event.
fn notify_activity(&self, annotation: HangAnnotation);
/// Notify the start of waiting for a new event to come in.
fn notify_wait(&self);
/// Unregister the component from monitor.
fn unregister(&self);
}
/// A means for the BHM to signal a monitored component to exit.
/// Useful when the component is hanging, and cannot be notified via the usual way.
/// The component should implement this in a way allowing for the signal to be received when hanging,
/// if at all.
pub trait BackgroundHangMonitorExitSignal: Send {
/// Called by the BHM, to notify the monitored component to exit.
fn signal_to_exit(&self);
}
/// Messages to control the sampling profiler.
#[derive(Deserialize, Serialize)]
pub enum BackgroundHangMonitorControlMsg {
/// Enable the sampler, with a given sampling rate and max total sampling duration.
EnableSampler(Duration, Duration),
DisableSampler,
/// Exit, and propagate the signal to monitored components.
Exit(IpcSender<()>),
}

View file

@ -0,0 +1,45 @@
/* 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 https://mozilla.org/MPL/2.0/. */
#![deny(unsafe_code)]
//! A crate to hold very common types in Servo.
//!
//! You should almost never need to add a data type to this crate. Instead look for
//! a more shared crate that has fewer dependents.
use serde::{Deserialize, Serialize};
pub mod id;
pub mod print_tree;
use webrender_api::Epoch as WebRenderEpoch;
/// A struct for denoting the age of messages; prevents race conditions.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct Epoch(pub u32);
impl Epoch {
pub fn next(&mut self) {
self.0 += 1;
}
}
impl From<Epoch> for WebRenderEpoch {
fn from(val: Epoch) -> Self {
WebRenderEpoch(val.0)
}
}
pub trait WebRenderEpochToU16 {
fn as_u16(&self) -> u16;
}
impl WebRenderEpochToU16 for WebRenderEpoch {
/// The value of this [`Epoch`] as a u16 value. Note that if this Epoch's
/// value is more than u16::MAX, then the return value will be modulo
/// u16::MAX.
fn as_u16(&self) -> u16 {
(self.0 % u16::MAX as u32) as u16
}
}

View file

@ -11,6 +11,7 @@ name = "compositing_traits"
path = "lib.rs"
[dependencies]
base = { workspace = true }
canvas = { path = "../../canvas" }
crossbeam-channel = { workspace = true }
embedder_traits = { workspace = true }
@ -19,7 +20,6 @@ gfx_traits = { workspace = true }
ipc-channel = { workspace = true }
keyboard-types = { workspace = true }
log = { workspace = true }
msg = { workspace = true }
net_traits = { workspace = true }
script_traits = { workspace = true }
servo_url = { path = "../../url" }

View file

@ -6,16 +6,14 @@ use std::collections::HashMap;
use std::fmt;
use std::time::Duration;
use base::id::{BrowsingContextId, PipelineId, TopLevelBrowsingContextId, WebViewId};
use base::Epoch;
use embedder_traits::Cursor;
use gfx_traits::Epoch;
use ipc_channel::ipc::IpcSender;
use keyboard_types::KeyboardEvent;
use msg::constellation_msg::{
BrowsingContextId, PipelineId, TopLevelBrowsingContextId, TraversalDirection, WebViewId,
};
use script_traits::{
AnimationTickType, CompositorEvent, GamepadEvent, LogEntry, MediaSessionActionType,
WebDriverCommandMsg, WindowSizeData, WindowSizeType,
TraversalDirection, WebDriverCommandMsg, WindowSizeData, WindowSizeType,
};
use servo_url::ServoUrl;

View file

@ -8,15 +8,15 @@ mod constellation_msg;
use std::fmt::{Debug, Error, Formatter};
use base::id::{PipelineId, TopLevelBrowsingContextId};
use base::Epoch;
use canvas::canvas_paint_thread::ImageUpdate;
pub use constellation_msg::ConstellationMsg;
use crossbeam_channel::{Receiver, Sender};
use embedder_traits::EventLoopWaker;
use euclid::Rect;
use gfx_traits::Epoch;
use ipc_channel::ipc::IpcSender;
use log::warn;
use msg::constellation_msg::{PipelineId, TopLevelBrowsingContextId};
use net_traits::image::base::Image;
use net_traits::NetToCompositorMsg;
use script_traits::{

View file

@ -11,12 +11,12 @@ name = "devtools_traits"
path = "lib.rs"
[dependencies]
base = { workspace = true }
bitflags = { workspace = true }
http = { workspace = true }
ipc-channel = { workspace = true }
malloc_size_of = { workspace = true }
malloc_size_of_derive = { workspace = true }
msg = { workspace = true }
serde = { workspace = true }
servo_url = { path = "../../url" }
time = { workspace = true }

View file

@ -14,11 +14,11 @@
use std::net::TcpStream;
use std::time::{Duration, SystemTime};
use base::id::{BrowsingContextId, PipelineId};
use bitflags::bitflags;
use http::{HeaderMap, Method};
use ipc_channel::ipc::IpcSender;
use malloc_size_of_derive::MallocSizeOf;
use msg::constellation_msg::{BrowsingContextId, PipelineId};
use serde::{Deserialize, Serialize};
use servo_url::ServoUrl;
use uuid::Uuid;

View file

@ -11,13 +11,13 @@ name = "embedder_traits"
path = "lib.rs"
[dependencies]
base = { workspace = true }
cfg-if = { workspace = true }
crossbeam-channel = { workspace = true }
ipc-channel = { workspace = true }
keyboard-types = { workspace = true }
lazy_static = { workspace = true }
log = { workspace = true }
msg = { workspace = true }
num-derive = "0.4"
num-traits = { workspace = true }
serde = { workspace = true }

View file

@ -6,11 +6,11 @@ pub mod resources;
use std::fmt::{Debug, Error, Formatter};
use base::id::{PipelineId, TopLevelBrowsingContextId, WebViewId};
use crossbeam_channel::{Receiver, Sender};
use ipc_channel::ipc::IpcSender;
use keyboard_types::KeyboardEvent;
use log::warn;
use msg::constellation_msg::{InputMethodType, PipelineId, TopLevelBrowsingContextId, WebViewId};
use num_derive::FromPrimitive;
use serde::{Deserialize, Serialize};
use servo_url::ServoUrl;
@ -368,3 +368,23 @@ pub enum PermissionRequest {
Granted,
Denied,
}
/// Used to specify the kind of input method editor appropriate to edit a field.
/// This is a subset of htmlinputelement::InputType because some variants of InputType
/// don't make sense in this context.
#[derive(Debug, Deserialize, Serialize)]
pub enum InputMethodType {
Color,
Date,
DatetimeLocal,
Email,
Month,
Number,
Password,
Search,
Tel,
Text,
Time,
Url,
Week,
}

View file

@ -2,71 +2,11 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
#![crate_name = "gfx_traits"]
#![crate_type = "rlib"]
#![deny(unsafe_code)]
pub mod print_tree;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use malloc_size_of_derive::MallocSizeOf;
use range::{int_range_index, RangeIndex};
use serde::{Deserialize, Serialize};
use webrender_api::{
Epoch as WebRenderEpoch, FontInstanceFlags, FontInstanceKey, FontKey, NativeFontHandle,
};
/// A newtype struct for denoting the age of messages; prevents race conditions.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct Epoch(pub u32);
impl Epoch {
pub fn next(&mut self) {
self.0 += 1;
}
}
impl From<Epoch> for WebRenderEpoch {
fn from(val: Epoch) -> Self {
WebRenderEpoch(val.0)
}
}
pub trait WebRenderEpochToU16 {
fn as_u16(&self) -> u16;
}
impl WebRenderEpochToU16 for WebRenderEpoch {
/// The value of this [`Epoch`] as a u16 value. Note that if this Epoch's
/// value is more than u16::MAX, then the return value will be modulo
/// u16::MAX.
fn as_u16(&self) -> u16 {
(self.0 % u16::MAX as u32) as u16
}
}
/// A unique ID for every stacking context.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
pub struct StackingContextId(
/// The identifier for this StackingContext, derived from the Flow's memory address
/// and fragment type. As a space optimization, these are combined into a single word.
pub u64,
);
impl StackingContextId {
/// Returns the stacking context ID for the outer document/layout root.
#[inline]
pub fn root() -> StackingContextId {
StackingContextId(0)
}
pub fn next(&self) -> StackingContextId {
let StackingContextId(id) = *self;
StackingContextId(id + 1)
}
}
int_range_index! {
#[derive(Deserialize, MallocSizeOf, Serialize)]
@ -74,61 +14,3 @@ int_range_index! {
/// the middle of a glyph.
struct ByteIndex(isize)
}
/// The type of fragment that a scroll root is created for.
///
/// This can only ever grow to maximum 4 entries. That's because we cram the value of this enum
/// into the lower 2 bits of the `ScrollRootId`, which otherwise contains a 32-bit-aligned
/// heap address.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
pub enum FragmentType {
/// A StackingContext for the fragment body itself.
FragmentBody,
/// A StackingContext created to contain ::before pseudo-element content.
BeforePseudoContent,
/// A StackingContext created to contain ::after pseudo-element content.
AfterPseudoContent,
}
/// The next ID that will be used for a special scroll root id.
///
/// A special scroll root is a scroll root that is created for generated content.
static NEXT_SPECIAL_SCROLL_ROOT_ID: AtomicU64 = AtomicU64::new(0);
/// If none of the bits outside this mask are set, the scroll root is a special scroll root.
/// Note that we assume that the top 16 bits of the address space are unused on the platform.
const SPECIAL_SCROLL_ROOT_ID_MASK: u64 = 0xffff;
/// Returns a new scroll root ID for a scroll root.
fn next_special_id() -> u64 {
// We shift this left by 2 to make room for the fragment type ID.
((NEXT_SPECIAL_SCROLL_ROOT_ID.fetch_add(1, Ordering::SeqCst) + 1) << 2) &
SPECIAL_SCROLL_ROOT_ID_MASK
}
pub fn combine_id_with_fragment_type(id: usize, fragment_type: FragmentType) -> u64 {
debug_assert_eq!(id & (fragment_type as usize), 0);
if fragment_type == FragmentType::FragmentBody {
id as u64
} else {
next_special_id() | (fragment_type as u64)
}
}
pub fn node_id_from_scroll_id(id: usize) -> Option<usize> {
if (id as u64 & !SPECIAL_SCROLL_ROOT_ID_MASK) != 0 {
return Some(id & !3);
}
None
}
pub trait WebrenderApi {
fn add_font_instance(
&self,
font_key: FontKey,
size: f32,
flags: FontInstanceFlags,
) -> FontInstanceKey;
fn add_font(&self, data: Arc<Vec<u8>>, index: u32) -> FontKey;
fn add_system_font(&self, handle: NativeFontHandle) -> FontKey;
}

View file

@ -1,7 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
#![deny(unsafe_code)]
pub mod constellation_msg;

View file

@ -13,6 +13,7 @@ test = false
doctest = false
[dependencies]
base = { workspace = true }
content-security-policy = { workspace = true }
cookie = { workspace = true }
embedder_traits = { workspace = true }
@ -27,7 +28,6 @@ log = { workspace = true }
malloc_size_of = { workspace = true }
malloc_size_of_derive = { workspace = true }
mime = { workspace = true }
msg = { workspace = true }
num-traits = { workspace = true }
percent-encoding = { workspace = true }
pixels = { path = "../../pixels" }

View file

@ -6,6 +6,7 @@
use std::time::{SystemTime, UNIX_EPOCH};
use base::id::HistoryStateId;
use cookie::Cookie;
use headers::{ContentType, HeaderMapExt, ReferrerPolicy as ReferrerPolicyHeader};
use http::{Error as HttpError, HeaderMap, StatusCode};
@ -19,7 +20,6 @@ use log::warn;
use malloc_size_of::malloc_size_of_is_0;
use malloc_size_of_derive::MallocSizeOf;
use mime::Mime;
use msg::constellation_msg::HistoryStateId;
use num_traits::Zero;
use rustls::Certificate;
use serde::{Deserialize, Serialize};

View file

@ -4,13 +4,13 @@
use std::sync::{Arc, Mutex};
use base::id::PipelineId;
use content_security_policy::{self as csp, CspList};
use http::header::{HeaderName, AUTHORIZATION};
use http::{HeaderMap, Method};
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use malloc_size_of_derive::MallocSizeOf;
use mime::Mime;
use msg::constellation_msg::PipelineId;
use serde::{Deserialize, Serialize};
use servo_url::{ImmutableOrigin, ServoUrl};

View file

@ -11,6 +11,8 @@ name = "script_traits"
path = "lib.rs"
[dependencies]
background_hang_monitor_api = { workspace = true }
base = { workspace = true }
bitflags = { workspace = true }
bluetooth_traits = { workspace = true }
canvas_traits = { workspace = true }
@ -29,7 +31,6 @@ log = { workspace = true }
malloc_size_of = { workspace = true }
malloc_size_of_derive = { workspace = true }
media = { path = "../../media" }
msg = { workspace = true }
net_traits = { workspace = true }
pixels = { path = "../../pixels" }
profile_traits = { workspace = true }

View file

@ -20,6 +20,12 @@ use std::collections::{HashMap, VecDeque};
use std::fmt;
use std::sync::Arc;
use background_hang_monitor_api::BackgroundHangMonitorRegister;
use base::id::{
BlobId, BrowsingContextId, HistoryStateId, MessagePortId, PipelineId, PipelineNamespaceId,
TopLevelBrowsingContextId,
};
use base::Epoch;
use bitflags::bitflags;
use bluetooth_traits::BluetoothRequest;
use canvas_traits::webgl::WebGLPipeline;
@ -29,7 +35,6 @@ use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, Worke
use embedder_traits::{CompositorEventVariant, Cursor};
use euclid::default::Point2D;
use euclid::{Length, Rect, Scale, Size2D, UnknownUnit, Vector2D};
use gfx_traits::Epoch;
use http::{HeaderMap, Method};
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use ipc_channel::Error as IpcError;
@ -40,10 +45,6 @@ use log::warn;
use malloc_size_of::malloc_size_of_is_0;
use malloc_size_of_derive::MallocSizeOf;
use media::WindowGLContext;
use msg::constellation_msg::{
BackgroundHangMonitorRegister, BlobId, BrowsingContextId, HistoryStateId, MessagePortId,
PipelineId, PipelineNamespaceId, TopLevelBrowsingContextId,
};
use net_traits::image::base::Image;
use net_traits::image_cache::ImageCache;
use net_traits::request::{Referrer, RequestBody};
@ -66,7 +67,7 @@ use crate::compositor::CompositorDisplayListInfo;
pub use crate::script_msg::{
DOMMessage, EventResult, HistoryEntryReplacement, IFrameSizeMsg, Job, JobError, JobResult,
JobResultValue, JobType, LayoutMsg, LogEntry, SWManagerMsg, SWManagerSenders, ScopeThings,
ScriptMsg, ServiceWorkerMsg,
ScriptMsg, ServiceWorkerMsg, TraversalDirection,
};
use crate::serializable::{BlobData, BlobImpl};
use crate::transferable::MessagePortImpl;

View file

@ -5,18 +5,18 @@
use std::collections::{HashMap, VecDeque};
use std::fmt;
use base::id::{
BroadcastChannelRouterId, BrowsingContextId, HistoryStateId, MessagePortId,
MessagePortRouterId, PipelineId, ServiceWorkerId, ServiceWorkerRegistrationId,
TopLevelBrowsingContextId,
};
use base::Epoch;
use canvas_traits::canvas::{CanvasId, CanvasMsg};
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
use embedder_traits::{EmbedderMsg, MediaSessionEvent};
use euclid::default::Size2D as UntypedSize2D;
use euclid::Size2D;
use gfx_traits::Epoch;
use ipc_channel::ipc::{IpcReceiver, IpcSender};
use msg::constellation_msg::{
BroadcastChannelRouterId, BrowsingContextId, HistoryStateId, MessagePortId,
MessagePortRouterId, PipelineId, ServiceWorkerId, ServiceWorkerRegistrationId,
TopLevelBrowsingContextId, TraversalDirection,
};
use net_traits::request::RequestBuilder;
use net_traits::storage_thread::StorageType;
use net_traits::CoreResourceMsg;
@ -492,3 +492,12 @@ pub enum SWManagerMsg {
/// <https://github.com/servo/servo/issues/24660>
PostMessageToClient,
}
/// The direction of a history traversal
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum TraversalDirection {
/// Travel forward the given number of documents.
Forward(usize),
/// Travel backward the given number of documents.
Back(usize),
}

View file

@ -11,8 +11,8 @@
use std::cell::RefCell;
use std::path::PathBuf;
use base::id::BlobId;
use malloc_size_of_derive::MallocSizeOf;
use msg::constellation_msg::BlobId;
use net_traits::filemanager_thread::RelativePos;
use serde::{Deserialize, Serialize};
use uuid::Uuid;

View file

@ -9,8 +9,8 @@
use std::collections::VecDeque;
use base::id::MessagePortId;
use malloc_size_of_derive::MallocSizeOf;
use msg::constellation_msg::MessagePortId;
use serde::{Deserialize, Serialize};
use crate::PortMessageTask;

View file

@ -6,11 +6,11 @@
use std::collections::HashMap;
use base::id::BrowsingContextId;
use cookie::Cookie;
use euclid::default::Rect;
use hyper_serde::Serde;
use ipc_channel::ipc::IpcSender;
use msg::constellation_msg::BrowsingContextId;
use serde::{Deserialize, Serialize};
use servo_url::ServoUrl;
use webdriver::common::{WebElement, WebFrame, WebWindow};

View file

@ -11,6 +11,7 @@ name = "script_layout_interface"
path = "lib.rs"
[dependencies]
base = { workspace = true }
app_units = { workspace = true }
atomic_refcell = { workspace = true }
canvas_traits = { workspace = true }
@ -24,12 +25,12 @@ libc = { workspace = true }
malloc_size_of = { workspace = true }
malloc_size_of_derive = { workspace = true }
metrics = { path = "../../metrics" }
msg = { workspace = true }
net_traits = { workspace = true }
profile_traits = { workspace = true }
range = { path = "../../range" }
script_traits = { workspace = true }
selectors = { workspace = true }
serde = { workspace = true }
servo_arc = { workspace = true }
servo_atoms = { workspace = true }
servo_url = { path = "../../url" }

View file

@ -12,22 +12,22 @@ pub mod wrapper_traits;
use std::any::Any;
use std::borrow::Cow;
use std::sync::atomic::AtomicIsize;
use std::sync::atomic::{AtomicIsize, AtomicU64, Ordering};
use std::sync::Arc;
use app_units::Au;
use atomic_refcell::AtomicRefCell;
use base::id::{BrowsingContextId, PipelineId};
use base::Epoch;
use canvas_traits::canvas::{CanvasId, CanvasMsg};
use crossbeam_channel::Sender;
use euclid::default::{Point2D, Rect};
use euclid::Size2D;
use gfx::font_cache_thread::FontCacheThread;
use gfx_traits::Epoch;
use ipc_channel::ipc::IpcSender;
use libc::c_void;
use malloc_size_of_derive::MallocSizeOf;
use metrics::PaintTimeMetrics;
use msg::constellation_msg::{BrowsingContextId, PipelineId};
use net_traits::image_cache::{ImageCache, PendingImageId};
use profile_traits::mem::Report;
use profile_traits::time;
@ -35,6 +35,7 @@ use script_traits::{
ConstellationControlMsg, InitialScriptState, LayoutControlMsg, LayoutMsg, LoadData, Painter,
ScrollState, UntrustedNodeAddress, WebrenderIpcSender, WindowSizeData,
};
use serde::{Deserialize, Serialize};
use servo_arc::Arc as ServoArc;
use servo_url::{ImmutableOrigin, ServoUrl};
use style::animation::DocumentAnimationSet;
@ -413,3 +414,50 @@ pub struct PendingRestyle {
/// Any explicit restyles damage that have been accumulated for this element.
pub damage: RestyleDamage,
}
/// The type of fragment that a scroll root is created for.
///
/// This can only ever grow to maximum 4 entries. That's because we cram the value of this enum
/// into the lower 2 bits of the `ScrollRootId`, which otherwise contains a 32-bit-aligned
/// heap address.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
pub enum FragmentType {
/// A StackingContext for the fragment body itself.
FragmentBody,
/// A StackingContext created to contain ::before pseudo-element content.
BeforePseudoContent,
/// A StackingContext created to contain ::after pseudo-element content.
AfterPseudoContent,
}
/// The next ID that will be used for a special scroll root id.
///
/// A special scroll root is a scroll root that is created for generated content.
static NEXT_SPECIAL_SCROLL_ROOT_ID: AtomicU64 = AtomicU64::new(0);
/// If none of the bits outside this mask are set, the scroll root is a special scroll root.
/// Note that we assume that the top 16 bits of the address space are unused on the platform.
const SPECIAL_SCROLL_ROOT_ID_MASK: u64 = 0xffff;
/// Returns a new scroll root ID for a scroll root.
fn next_special_id() -> u64 {
// We shift this left by 2 to make room for the fragment type ID.
((NEXT_SPECIAL_SCROLL_ROOT_ID.fetch_add(1, Ordering::SeqCst) + 1) << 2) &
SPECIAL_SCROLL_ROOT_ID_MASK
}
pub fn combine_id_with_fragment_type(id: usize, fragment_type: FragmentType) -> u64 {
debug_assert_eq!(id & (fragment_type as usize), 0);
if fragment_type == FragmentType::FragmentBody {
id as u64
} else {
next_special_id() | (fragment_type as u64)
}
}
pub fn node_id_from_scroll_id(id: usize) -> Option<usize> {
if (id as u64 & !SPECIAL_SCROLL_ROOT_ID_MASK) != 0 {
return Some(id & !3);
}
None
}

View file

@ -9,9 +9,9 @@ use std::fmt::Debug;
use std::sync::Arc as StdArc;
use atomic_refcell::AtomicRef;
use gfx_traits::{ByteIndex, FragmentType};
use base::id::{BrowsingContextId, PipelineId};
use gfx_traits::ByteIndex;
use html5ever::{local_name, namespace_url, ns, LocalName, Namespace};
use msg::constellation_msg::{BrowsingContextId, PipelineId};
use net_traits::image::base::{Image, ImageMetadata};
use range::Range;
use servo_arc::Arc;
@ -25,7 +25,8 @@ use style::selector_parser::{PseudoElement, PseudoElementCascadeType, SelectorIm
use style::stylist::RuleInclusion;
use crate::{
GenericLayoutData, HTMLCanvasData, HTMLMediaData, LayoutNodeType, SVGSVGData, StyleData,
FragmentType, GenericLayoutData, HTMLCanvasData, HTMLMediaData, LayoutNodeType, SVGSVGData,
StyleData,
};
pub trait LayoutDataTrait: Default + Send + Sync + 'static {}

View file

@ -9,7 +9,10 @@ use std::sync::{Arc, Mutex};
use euclid::default::Size2D;
use webrender_api::units::TexelRect;
use webrender_api::{ExternalImage, ExternalImageHandler, ExternalImageId, ExternalImageSource};
use webrender_api::{
ExternalImage, ExternalImageHandler, ExternalImageId, ExternalImageSource, FontInstanceFlags,
FontInstanceKey, FontKey, NativeFontHandle,
};
/// This trait is used as a bridge between the different GL clients
/// in Servo that handles WebRender ExternalImages and the WebRender
@ -164,3 +167,14 @@ impl ExternalImageHandler for WebrenderExternalImageHandlers {
};
}
}
pub trait WebRenderFontApi {
fn add_font_instance(
&self,
font_key: FontKey,
size: f32,
flags: FontInstanceFlags,
) -> FontInstanceKey;
fn add_font(&self, data: Arc<Vec<u8>>, index: u32) -> FontKey;
fn add_system_font(&self, handle: NativeFontHandle) -> FontKey;
}