diff options
Diffstat (limited to 'components')
31 files changed, 298 insertions, 105 deletions
diff --git a/components/canvas/Cargo.toml b/components/canvas/Cargo.toml index 6084fc6e434..7aadc8a9bb5 100644 --- a/components/canvas/Cargo.toml +++ b/components/canvas/Cargo.toml @@ -24,7 +24,6 @@ ipc-channel = { workspace = true } log = { workspace = true } lyon_geom = "1.0.4" net_traits = { workspace = true } -num-traits = { workspace = true } pixels = { path = "../pixels" } range = { path = "../range" } raqote = "0.8.5" diff --git a/components/compositing/Cargo.toml b/components/compositing/Cargo.toml index 8e788e58734..9b4ff54d29e 100644 --- a/components/compositing/Cargo.toml +++ b/components/compositing/Cargo.toml @@ -34,11 +34,9 @@ log = { workspace = true } net = { path = "../net" } pixels = { path = "../pixels" } profile_traits = { workspace = true } -script_traits = { workspace = true } servo_allocator = { path = "../allocator" } servo_config = { path = "../config" } servo_geometry = { path = "../geometry" } -smallvec = { workspace = true } stylo_traits = { workspace = true } tracing = { workspace = true, optional = true } webrender = { workspace = true } diff --git a/components/layout/Cargo.toml b/components/layout/Cargo.toml index 0505581fba7..0e4cd0b79fd 100644 --- a/components/layout/Cargo.toml +++ b/components/layout/Cargo.toml @@ -21,7 +21,6 @@ app_units = { workspace = true } atomic_refcell = { workspace = true } base = { workspace = true } bitflags = { workspace = true } -canvas_traits = { workspace = true } compositing_traits = { workspace = true } constellation_traits = { workspace = true } data-url = { workspace = true } diff --git a/components/layout/display_list/background.rs b/components/layout/display_list/background.rs index 563bce28450..f1099fdab2b 100644 --- a/components/layout/display_list/background.rs +++ b/components/layout/display_list/background.rs @@ -3,7 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use app_units::Au; -use euclid::{Point2D, Size2D, Vector2D}; +use euclid::{Size2D, Vector2D}; use style::computed_values::background_attachment::SingleComputedValue as BackgroundAttachment; use style::computed_values::background_clip::single_value::T as Clip; use style::computed_values::background_origin::single_value::T as Origin; @@ -15,7 +15,6 @@ use style::values::specified::background::{ }; use webrender_api::{self as wr, units}; use wr::ClipChainId; -use wr::units::LayoutSize; use crate::replaced::NaturalSizes; @@ -66,8 +65,7 @@ impl<'a> BackgroundPainter<'a> { if &BackgroundAttachment::Fixed == get_cyclic(&background.background_attachment.0, layer_index) { - let viewport_size = builder.compositor_info.viewport_size; - return units::LayoutRect::from_origin_and_size(Point2D::origin(), viewport_size); + return builder.compositor_info.viewport_size.into(); } match get_cyclic(&background.background_clip.0, layer_index) { @@ -132,6 +130,7 @@ impl<'a> BackgroundPainter<'a> { pub(super) fn positioning_area( &self, fragment_builder: &'a super::BuilderForBoxFragment, + builder: &mut super::DisplayListBuilder, layer_index: usize, ) -> units::LayoutRect { if let Some(positioning_area_override) = self.positioning_area_override { @@ -150,14 +149,7 @@ impl<'a> BackgroundPainter<'a> { Origin::PaddingBox => *fragment_builder.padding_rect(), Origin::BorderBox => fragment_builder.border_rect, }, - BackgroundAttachment::Fixed => { - // This isn't the viewport size because that rects larger than the viewport might be - // transformed down into areas smaller than the viewport. - units::LayoutRect::from_origin_and_size( - Point2D::origin(), - LayoutSize::new(f32::MAX, f32::MAX), - ) - }, + BackgroundAttachment::Fixed => builder.compositor_info.viewport_size.into(), } } } @@ -170,7 +162,7 @@ pub(super) fn layout_layer( natural_sizes: NaturalSizes, ) -> Option<BackgroundLayer> { let painting_area = painter.painting_area(fragment_builder, builder, layer_index); - let positioning_area = painter.positioning_area(fragment_builder, layer_index); + let positioning_area = painter.positioning_area(fragment_builder, builder, layer_index); let common = painter.common_properties(fragment_builder, builder, layer_index, painting_area); // https://drafts.csswg.org/css-backgrounds/#background-size diff --git a/components/layout/flow/root.rs b/components/layout/flow/root.rs index 8ad3671032e..fb9884a4f01 100644 --- a/components/layout/flow/root.rs +++ b/components/layout/flow/root.rs @@ -5,6 +5,8 @@ use app_units::Au; use atomic_refcell::AtomicRef; use compositing_traits::display_list::AxesScrollSensitivity; +use euclid::Rect; +use euclid::default::Size2D as UntypedSize2D; use malloc_size_of_derive::MallocSizeOf; use script::layout_dom::ServoLayoutNode; use script_layout_interface::wrapper_traits::{ @@ -27,7 +29,7 @@ use crate::flow::inline::InlineItem; use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox}; use crate::formatting_contexts::IndependentFormattingContext; use crate::fragment_tree::FragmentTree; -use crate::geom::{LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSize}; +use crate::geom::{LogicalVec2, PhysicalRect, PhysicalSize}; use crate::positioned::{AbsolutelyPositionedBox, PositioningContext}; use crate::replaced::ReplacedContents; use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside}; @@ -348,7 +350,7 @@ impl BoxTree { pub fn layout( &self, layout_context: &LayoutContext, - viewport: euclid::Size2D<f32, CSSPixel>, + viewport: UntypedSize2D<Au>, ) -> FragmentTree { let style = layout_context .style_context @@ -358,13 +360,8 @@ impl BoxTree { // FIXME: use the document’s mode: // https://drafts.csswg.org/css-writing-modes/#principal-flow - let physical_containing_block = PhysicalRect::new( - PhysicalPoint::zero(), - PhysicalSize::new( - Au::from_f32_px(viewport.width), - Au::from_f32_px(viewport.height), - ), - ); + let physical_containing_block: Rect<Au, CSSPixel> = + PhysicalSize::from_untyped(viewport).into(); let initial_containing_block = DefiniteContainingBlock { size: LogicalVec2 { inline: physical_containing_block.size.width, diff --git a/components/layout/layout_impl.rs b/components/layout/layout_impl.rs index 8162ed1dd0b..3452c9a6e4c 100644 --- a/components/layout/layout_impl.rs +++ b/components/layout/layout_impl.rs @@ -16,7 +16,7 @@ use base::id::{PipelineId, WebViewId}; use compositing_traits::CrossProcessCompositorApi; use constellation_traits::ScrollState; use embedder_traits::{UntrustedNodeAddress, ViewportDetails}; -use euclid::default::{Point2D as UntypedPoint2D, Rect as UntypedRect, Size2D as UntypedSize2D}; +use euclid::default::{Point2D as UntypedPoint2D, Rect as UntypedRect}; use euclid::{Point2D, Scale, Size2D, Vector2D}; use fnv::FnvHashMap; use fonts::{FontContext, FontContextWebFontMethods}; @@ -150,10 +150,6 @@ pub struct LayoutThread { /// A counter for epoch messages epoch: Cell<Epoch>, - /// The size of the viewport. This may be different from the size of the screen due to viewport - /// constraints. - viewport_size: UntypedSize2D<Au>, - /// Scroll offsets of nodes that scroll. scroll_offsets: RefCell<HashMap<ExternalScrollId, Vector2D<f32, LayoutPixel>>>, @@ -527,10 +523,6 @@ impl LayoutThread { stacking_context_tree: Default::default(), // Epoch starts at 1 because of the initial display list for epoch 0 that we send to WR epoch: Cell::new(Epoch(1)), - viewport_size: Size2D::new( - Au::from_f32_px(config.viewport_details.size.width), - Au::from_f32_px(config.viewport_details.size.height), - ), compositor_api: config.compositor_api, scroll_offsets: Default::default(), stylist: Stylist::new(device, QuirksMode::NoQuirks), @@ -611,7 +603,8 @@ impl LayoutThread { ua_or_user: &ua_or_user_guard, }; - if self.update_device_if_necessary(&reflow_request, &guards) { + let viewport_changed = self.viewport_did_change(reflow_request.viewport_details); + if self.update_device_if_necessary(&reflow_request, viewport_changed, &guards) { if let Some(mut data) = root_element.mutate_data() { data.hint.insert(RestyleHint::recascade_subtree()); } @@ -653,14 +646,15 @@ impl LayoutThread { highlighted_dom_node: reflow_request.highlighted_dom_node, }; - let did_reflow = self.restyle_and_build_trees( + let damage = self.restyle_and_build_trees( &reflow_request, root_element, rayon_pool, &mut layout_context, + viewport_changed, ); - self.build_stacking_context_tree(&reflow_request, did_reflow); + self.build_stacking_context_tree(&reflow_request, damage); self.build_display_list(&reflow_request, &mut layout_context); self.first_reflow.set(false); @@ -683,12 +677,12 @@ impl LayoutThread { fn update_device_if_necessary( &mut self, reflow_request: &ReflowRequest, + viewport_changed: bool, guards: &StylesheetGuards, ) -> bool { let had_used_viewport_units = self.stylist.device().used_viewport_units(); - let viewport_size_changed = self.viewport_did_change(reflow_request.viewport_details); let theme_changed = self.theme_did_change(reflow_request.theme); - if !viewport_size_changed && !theme_changed { + if !viewport_changed && !theme_changed { return false; } self.update_device( @@ -696,7 +690,7 @@ impl LayoutThread { reflow_request.theme, guards, ); - (viewport_size_changed && had_used_viewport_units) || theme_changed + (viewport_changed && had_used_viewport_units) || theme_changed } fn prepare_stylist_for_reflow<'dom>( @@ -749,7 +743,8 @@ impl LayoutThread { root_element: ServoLayoutElement<'_>, rayon_pool: Option<&ThreadPool>, layout_context: &mut LayoutContext<'_>, - ) -> bool { + viewport_changed: bool, + ) -> RestyleDamage { let dirty_root = unsafe { ServoLayoutNode::new(&reflow_request.dirty_root.unwrap()) .as_element() @@ -765,7 +760,7 @@ impl LayoutThread { if !token.should_traverse() { layout_context.style_context.stylist.rule_tree().maybe_gc(); - return false; + return RestyleDamage::empty(); } let dirty_root: ServoLayoutNode = @@ -773,9 +768,9 @@ impl LayoutThread { let root_node = root_element.as_node(); let damage = compute_damage_and_repair_style(layout_context.shared_context(), root_node); - if damage.is_empty() || damage == RestyleDamage::REPAINT { + if !viewport_changed && !damage.contains(RestyleDamage::REBUILD_BOX) { layout_context.style_context.stylist.rule_tree().maybe_gc(); - return false; + return damage; } let mut box_tree = self.box_tree.borrow_mut(); @@ -794,10 +789,7 @@ impl LayoutThread { build_box_tree() }; - let viewport_size = Size2D::new( - self.viewport_size.width.to_f32_px(), - self.viewport_size.height.to_f32_px(), - ); + let viewport_size = self.stylist.device().au_viewport_size(); let run_layout = || { box_tree .as_ref() @@ -836,10 +828,10 @@ impl LayoutThread { // GC the rule tree if some heuristics are met. layout_context.style_context.stylist.rule_tree().maybe_gc(); - true + damage } - fn build_stacking_context_tree(&self, reflow_request: &ReflowRequest, did_reflow: bool) { + fn build_stacking_context_tree(&self, reflow_request: &ReflowRequest, damage: RestyleDamage) { if !reflow_request.reflow_goal.needs_display_list() && !reflow_request.reflow_goal.needs_display() { @@ -848,14 +840,17 @@ impl LayoutThread { let Some(fragment_tree) = &*self.fragment_tree.borrow() else { return; }; - if !did_reflow && self.stacking_context_tree.borrow().is_some() { + if !damage.contains(RestyleDamage::REBUILD_STACKING_CONTEXT) && + self.stacking_context_tree.borrow().is_some() + { return; } - let viewport_size = LayoutSize::from_untyped(Size2D::new( - self.viewport_size.width.to_f32_px(), - self.viewport_size.height.to_f32_px(), - )); + let viewport_size = self.stylist.device().au_viewport_size(); + let viewport_size = LayoutSize::new( + viewport_size.width.to_f32_px(), + viewport_size.height.to_f32_px(), + ); // Build the StackingContextTree. This turns the `FragmentTree` into a // tree of fragments in CSS painting order and also creates all @@ -949,9 +944,6 @@ impl LayoutThread { Au::from_f32_px(viewport_details.size.height), ); - // TODO: eliminate self.viewport_size in favour of using self.device.au_viewport_size() - self.viewport_size = new_viewport_size; - let device = self.stylist.device(); let size_did_change = device.au_viewport_size() != new_viewport_size; let pixel_ratio_did_change = device.device_pixel_ratio().get() != new_pixel_ratio; diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs index faf25dc170d..22faa4b1191 100644 --- a/components/layout/traversal.rs +++ b/components/layout/traversal.rs @@ -131,7 +131,9 @@ pub(crate) fn compute_damage_and_repair_style_inner( } } - if propagated_damage == RestyleDamage::REPAINT && original_damage == RestyleDamage::REPAINT { + if !propagated_damage.contains(RestyleDamage::REBUILD_BOX) && + !original_damage.contains(RestyleDamage::REBUILD_BOX) + { node.repair_style(context); } diff --git a/components/metrics/Cargo.toml b/components/metrics/Cargo.toml index 3888b41bb29..a62ff8c98dc 100644 --- a/components/metrics/Cargo.toml +++ b/components/metrics/Cargo.toml @@ -13,7 +13,6 @@ path = "lib.rs" [dependencies] base = { workspace = true } -constellation_traits = { workspace = true } ipc-channel = { workspace = true } log = { workspace = true } malloc_size_of = { workspace = true } diff --git a/components/net/Cargo.toml b/components/net/Cargo.toml index 1945165b8c1..33d5826978b 100644 --- a/components/net/Cargo.toml +++ b/components/net/Cargo.toml @@ -58,7 +58,6 @@ rustls-pemfile = { workspace = true } rustls-pki-types = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } -servo_allocator = { path = "../allocator" } servo_arc = { workspace = true } servo_config = { path = "../config" } servo_url = { path = "../url" } diff --git a/components/profile/Cargo.toml b/components/profile/Cargo.toml index 8a8d0775711..73c7924d863 100644 --- a/components/profile/Cargo.toml +++ b/components/profile/Cargo.toml @@ -15,7 +15,6 @@ path = "lib.rs" base = { workspace = true } ipc-channel = { workspace = true } log = { workspace = true } -parking_lot = { workspace = true } profile_traits = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index 6d588a3984e..09dab3471df 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -94,7 +94,6 @@ net_traits = { workspace = true } nom = "7.1.3" num-traits = { workspace = true } num_cpus = { workspace = true } -parking_lot = { workspace = true } percent-encoding = { workspace = true } phf = "0.11" pixels = { path = "../pixels" } diff --git a/components/script/dom/bindings/structuredclone.rs b/components/script/dom/bindings/structuredclone.rs index c23156817cb..73974abe714 100644 --- a/components/script/dom/bindings/structuredclone.rs +++ b/components/script/dom/bindings/structuredclone.rs @@ -10,11 +10,13 @@ use std::os::raw; use std::ptr; use base::id::{ - BlobId, DomExceptionId, DomPointId, Index, MessagePortId, NamespaceIndex, PipelineNamespaceId, + BlobId, DomExceptionId, DomPointId, ImageBitmapId, Index, MessagePortId, NamespaceIndex, + PipelineNamespaceId, }; use constellation_traits::{ BlobImpl, DomException, DomPoint, MessagePortImpl, Serializable as SerializableInterface, - StructuredSerializedData, Transferrable as TransferrableInterface, TransformStreamData, + SerializableImageBitmap, StructuredSerializedData, Transferrable as TransferrableInterface, + TransformStreamData, }; use js::gc::RootedVec; use js::glue::{ @@ -42,6 +44,7 @@ use crate::dom::blob::Blob; use crate::dom::dompoint::DOMPoint; use crate::dom::dompointreadonly::DOMPointReadOnly; use crate::dom::globalscope::GlobalScope; +use crate::dom::imagebitmap::ImageBitmap; use crate::dom::messageport::MessagePort; use crate::dom::readablestream::ReadableStream; use crate::dom::types::{DOMException, TransformStream}; @@ -66,6 +69,7 @@ pub(super) enum StructuredCloneTags { DomException = 0xFFFF8007, WritableStream = 0xFFFF8008, TransformStream = 0xFFFF8009, + ImageBitmap = 0xFFFF800A, Max = 0xFFFFFFFF, } @@ -76,6 +80,7 @@ impl From<SerializableInterface> for StructuredCloneTags { SerializableInterface::DomPointReadOnly => StructuredCloneTags::DomPointReadOnly, SerializableInterface::DomPoint => StructuredCloneTags::DomPoint, SerializableInterface::DomException => StructuredCloneTags::DomException, + SerializableInterface::ImageBitmap => StructuredCloneTags::ImageBitmap, } } } @@ -83,6 +88,7 @@ impl From<SerializableInterface> for StructuredCloneTags { impl From<TransferrableInterface> for StructuredCloneTags { fn from(v: TransferrableInterface) -> Self { match v { + TransferrableInterface::ImageBitmap => StructuredCloneTags::ImageBitmap, TransferrableInterface::MessagePort => StructuredCloneTags::MessagePort, TransferrableInterface::ReadableStream => StructuredCloneTags::ReadableStream, TransferrableInterface::WritableStream => StructuredCloneTags::WritableStream, @@ -104,6 +110,7 @@ fn reader_for_type( SerializableInterface::DomPointReadOnly => read_object::<DOMPointReadOnly>, SerializableInterface::DomPoint => read_object::<DOMPoint>, SerializableInterface::DomException => read_object::<DOMException>, + SerializableInterface::ImageBitmap => read_object::<ImageBitmap>, } } @@ -237,6 +244,7 @@ fn serialize_for_type(val: SerializableInterface) -> SerializeOperation { SerializableInterface::DomPointReadOnly => try_serialize::<DOMPointReadOnly>, SerializableInterface::DomPoint => try_serialize::<DOMPoint>, SerializableInterface::DomException => try_serialize::<DOMException>, + SerializableInterface::ImageBitmap => try_serialize::<ImageBitmap>, } } @@ -264,6 +272,7 @@ fn receiver_for_type( ) -> fn(&GlobalScope, &mut StructuredDataReader<'_>, u64, RawMutableHandleObject) -> Result<(), ()> { match val { + TransferrableInterface::ImageBitmap => receive_object::<ImageBitmap>, TransferrableInterface::MessagePort => receive_object::<MessagePort>, TransferrableInterface::ReadableStream => receive_object::<ReadableStream>, TransferrableInterface::WritableStream => receive_object::<WritableStream>, @@ -390,6 +399,7 @@ type TransferOperation = unsafe fn( fn transfer_for_type(val: TransferrableInterface) -> TransferOperation { match val { + TransferrableInterface::ImageBitmap => try_transfer::<ImageBitmap>, TransferrableInterface::MessagePort => try_transfer::<MessagePort>, TransferrableInterface::ReadableStream => try_transfer::<ReadableStream>, TransferrableInterface::WritableStream => try_transfer::<WritableStream>, @@ -439,6 +449,7 @@ unsafe fn can_transfer_for_type( root_from_object::<T>(*obj, cx).map(|o| Transferable::can_transfer(&*o)) } match transferable { + TransferrableInterface::ImageBitmap => can_transfer::<ImageBitmap>(obj, cx), TransferrableInterface::MessagePort => can_transfer::<MessagePort>(obj, cx), TransferrableInterface::ReadableStream => can_transfer::<ReadableStream>(obj, cx), TransferrableInterface::WritableStream => can_transfer::<WritableStream>(obj, cx), @@ -527,6 +538,10 @@ pub(crate) struct StructuredDataReader<'a> { pub(crate) points: Option<HashMap<DomPointId, DomPoint>>, /// A map of serialized exceptions. pub(crate) exceptions: Option<HashMap<DomExceptionId, DomException>>, + // A map of serialized image bitmaps. + pub(crate) image_bitmaps: Option<HashMap<ImageBitmapId, SerializableImageBitmap>>, + /// A map of transferred image bitmaps. + pub(crate) transferred_image_bitmaps: Option<HashMap<ImageBitmapId, SerializableImageBitmap>>, } /// A data holder for transferred and serialized objects. @@ -545,6 +560,10 @@ pub(crate) struct StructuredDataWriter { pub(crate) exceptions: Option<HashMap<DomExceptionId, DomException>>, /// Serialized blobs. pub(crate) blobs: Option<HashMap<BlobId, BlobImpl>>, + /// Serialized image bitmaps. + pub(crate) image_bitmaps: Option<HashMap<ImageBitmapId, SerializableImageBitmap>>, + /// Transferred image bitmaps. + pub(crate) transferred_image_bitmaps: Option<HashMap<ImageBitmapId, SerializableImageBitmap>>, } /// Writes a structured clone. Returns a `DataClone` error if that fails. @@ -599,6 +618,8 @@ pub(crate) fn write( points: sc_writer.points.take(), exceptions: sc_writer.exceptions.take(), blobs: sc_writer.blobs.take(), + image_bitmaps: sc_writer.image_bitmaps.take(), + transferred_image_bitmaps: sc_writer.transferred_image_bitmaps.take(), }; Ok(data) @@ -623,6 +644,8 @@ pub(crate) fn read( points: data.points.take(), exceptions: data.exceptions.take(), errors: DOMErrorRecord { message: None }, + image_bitmaps: data.image_bitmaps.take(), + transferred_image_bitmaps: data.transferred_image_bitmaps.take(), }; let sc_reader_ptr = &mut sc_reader as *mut _; unsafe { diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index 55db2e4d248..ec2ed70dd15 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -2992,8 +2992,7 @@ impl GlobalScope { if let Some(snapshot) = canvas.get_image_data() { let size = snapshot.size().cast(); - let image_bitmap = - ImageBitmap::new(self, size.width, size.height, can_gc).unwrap(); + let image_bitmap = ImageBitmap::new(self, size.width, size.height, can_gc); image_bitmap.set_bitmap_data(snapshot.to_vec()); image_bitmap.set_origin_clean(canvas.origin_is_clean()); p.resolve_native(&(image_bitmap), can_gc); @@ -3009,8 +3008,7 @@ impl GlobalScope { if let Some(snapshot) = canvas.get_image_data() { let size = snapshot.size().cast(); - let image_bitmap = - ImageBitmap::new(self, size.width, size.height, can_gc).unwrap(); + let image_bitmap = ImageBitmap::new(self, size.width, size.height, can_gc); image_bitmap.set_bitmap_data(snapshot.to_vec()); image_bitmap.set_origin_clean(canvas.origin_is_clean()); p.resolve_native(&(image_bitmap), can_gc); diff --git a/components/script/dom/htmlareaelement.rs b/components/script/dom/htmlareaelement.rs index a9d94cbd7b2..535d296a29f 100644 --- a/components/script/dom/htmlareaelement.rs +++ b/components/script/dom/htmlareaelement.rs @@ -46,6 +46,8 @@ pub enum Area { bottom_right: (f32, f32), }, Polygon { + /// Stored as a flat array of coordinates + /// e.g. [x1, y1, x2, y2, x3, y3] for a triangle points: Vec<f32>, }, } @@ -203,8 +205,28 @@ impl Area { p.y >= top_left.1 }, - //TODO polygon hit_test - _ => false, + Area::Polygon { ref points } => { + // Ray-casting algorithm to determine if point is inside polygon + // https://en.wikipedia.org/wiki/Point_in_polygon#Ray_casting_algorithm + let mut inside = false; + + debug_assert!(points.len() % 2 == 0); + let vertices = points.len() / 2; + + for i in 0..vertices { + let next_i = if i + 1 == vertices { 0 } else { i + 1 }; + + let xi = points[2 * i]; + let yi = points[2 * i + 1]; + let xj = points[2 * next_i]; + let yj = points[2 * next_i + 1]; + + if (yi > p.y) != (yj > p.y) && p.x < (xj - xi) * (p.y - yi) / (yj - yi) + xi { + inside = !inside; + } + } + inside + }, } } diff --git a/components/script/dom/imagebitmap.rs b/components/script/dom/imagebitmap.rs index ef6538e7451..97a1a54bba7 100644 --- a/components/script/dom/imagebitmap.rs +++ b/components/script/dom/imagebitmap.rs @@ -3,15 +3,20 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use std::cell::Cell; +use std::collections::HashMap; use std::vec::Vec; +use base::id::{ImageBitmapId, ImageBitmapIndex}; +use constellation_traits::SerializableImageBitmap; use dom_struct::dom_struct; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::ImageBitmapBinding::ImageBitmapMethods; -use crate::dom::bindings::error::Fallible; use crate::dom::bindings::reflector::{Reflector, reflect_dom_object}; use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::serializable::Serializable; +use crate::dom::bindings::structuredclone::StructuredData; +use crate::dom::bindings::transferable::Transferable; use crate::dom::globalscope::GlobalScope; use crate::script_runtime::CanGc; @@ -29,33 +34,36 @@ pub(crate) struct ImageBitmap { } impl ImageBitmap { - fn new_inherited(width_arg: u32, height_arg: u32) -> ImageBitmap { + fn new_inherited(width: u32, height: u32) -> ImageBitmap { ImageBitmap { reflector_: Reflector::new(), - width: width_arg, - height: height_arg, + width, + height, bitmap_data: DomRefCell::new(Some(vec![])), origin_clean: Cell::new(true), } } - #[allow(dead_code)] pub(crate) fn new( global: &GlobalScope, width: u32, height: u32, can_gc: CanGc, - ) -> Fallible<DomRoot<ImageBitmap>> { + ) -> DomRoot<ImageBitmap> { //assigning to a variable the return object of new_inherited let imagebitmap = Box::new(ImageBitmap::new_inherited(width, height)); - Ok(reflect_dom_object(imagebitmap, global, can_gc)) + reflect_dom_object(imagebitmap, global, can_gc) } pub(crate) fn set_bitmap_data(&self, data: Vec<u8>) { *self.bitmap_data.borrow_mut() = Some(data); } + pub(crate) fn origin_is_clean(&self) -> bool { + self.origin_clean.get() + } + pub(crate) fn set_origin_clean(&self, origin_is_clean: bool) { self.origin_clean.set(origin_is_clean); } @@ -67,6 +75,117 @@ impl ImageBitmap { } } +impl Serializable for ImageBitmap { + type Index = ImageBitmapIndex; + type Data = SerializableImageBitmap; + + /// <https://html.spec.whatwg.org/multipage/#the-imagebitmap-interface:serialization-steps> + fn serialize(&self) -> Result<(ImageBitmapId, Self::Data), ()> { + // Step 1. If value's origin-clean flag is not set, then throw a "DataCloneError" DOMException. + if !self.origin_is_clean() { + return Err(()); + } + + // If value has a [[Detached]] internal slot whose value is true, + // then throw a "DataCloneError" DOMException. + if self.is_detached() { + return Err(()); + } + + // Step 2. Set serialized.[[BitmapData]] to a copy of value's bitmap data. + let serialized = SerializableImageBitmap { + width: self.width, + height: self.height, + bitmap_data: self.bitmap_data.borrow().clone().unwrap(), + }; + + Ok((ImageBitmapId::new(), serialized)) + } + + /// <https://html.spec.whatwg.org/multipage/#the-imagebitmap-interface:deserialization-steps> + fn deserialize( + owner: &GlobalScope, + serialized: Self::Data, + can_gc: CanGc, + ) -> Result<DomRoot<Self>, ()> { + let image_bitmap = ImageBitmap::new(owner, serialized.width, serialized.height, can_gc); + + // Step 1. Set value's bitmap data to serialized.[[BitmapData]]. + image_bitmap.set_bitmap_data(serialized.bitmap_data); + + Ok(image_bitmap) + } + + fn serialized_storage<'a>( + reader: StructuredData<'a, '_>, + ) -> &'a mut Option<HashMap<ImageBitmapId, Self::Data>> { + match reader { + StructuredData::Reader(r) => &mut r.image_bitmaps, + StructuredData::Writer(w) => &mut w.image_bitmaps, + } + } +} + +impl Transferable for ImageBitmap { + type Index = ImageBitmapIndex; + type Data = SerializableImageBitmap; + + fn can_transfer(&self) -> bool { + if !self.origin_is_clean() || self.is_detached() { + return false; + } + true + } + + /// <https://html.spec.whatwg.org/multipage/#the-imagebitmap-interface:transfer-steps> + fn transfer(&self) -> Result<(ImageBitmapId, SerializableImageBitmap), ()> { + // Step 1. If value's origin-clean flag is not set, then throw a "DataCloneError" DOMException. + if !self.origin_is_clean() { + return Err(()); + } + + // If value has a [[Detached]] internal slot whose value is true, + // then throw a "DataCloneError" DOMException. + if self.is_detached() { + return Err(()); + } + + // Step 2. Set dataHolder.[[BitmapData]] to value's bitmap data. + // Step 3. Unset value's bitmap data. + let serialized = SerializableImageBitmap { + width: self.width, + height: self.height, + bitmap_data: self.bitmap_data.borrow_mut().take().unwrap(), + }; + + Ok((ImageBitmapId::new(), serialized)) + } + + /// <https://html.spec.whatwg.org/multipage/#the-imagebitmap-interface:transfer-receiving-steps> + fn transfer_receive( + owner: &GlobalScope, + _: ImageBitmapId, + serialized: SerializableImageBitmap, + ) -> Result<DomRoot<Self>, ()> { + let image_bitmap = + ImageBitmap::new(owner, serialized.width, serialized.height, CanGc::note()); + + // Step 1. Set value's bitmap data to serialized.[[BitmapData]]. + image_bitmap.set_bitmap_data(serialized.bitmap_data); + + Ok(image_bitmap) + } + + fn serialized_storage<'a>( + data: StructuredData<'a, '_>, + ) -> &'a mut Option<HashMap<ImageBitmapId, Self::Data>> { + match data { + StructuredData::Reader(r) => &mut r.transferred_image_bitmaps, + StructuredData::Writer(w) => &mut w.transferred_image_bitmaps, + } + } +} + impl ImageBitmapMethods<crate::DomTypeHolder> for ImageBitmap { /// <https://html.spec.whatwg.org/multipage/#dom-imagebitmap-height> fn Height(&self) -> u32 { diff --git a/components/script_bindings/codegen/CodegenRust.py b/components/script_bindings/codegen/CodegenRust.py index 20d6d30681e..37d62ff2e1b 100644 --- a/components/script_bindings/codegen/CodegenRust.py +++ b/components/script_bindings/codegen/CodegenRust.py @@ -39,6 +39,7 @@ from WebIDL import ( from Configuration import ( Configuration, Descriptor, + DescriptorProvider, MakeNativeName, MemberIsLegacyUnforgeable, getModuleFromObject, @@ -617,16 +618,16 @@ class JSToNativeConversionInfo(): def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, - isDefinitelyObject=False, - isMember=False, + isDefinitelyObject: bool = False, + isMember: bool | str = False, isArgument=False, isAutoRooted=False, invalidEnumValueFatal=True, defaultValue=None, exceptionCode=None, - allowTreatNonObjectAsNull=False, + allowTreatNonObjectAsNull: bool = False, isCallbackReturnValue=False, - sourceDescription="value"): + sourceDescription="value") -> JSToNativeConversionInfo: """ Get a template for converting a JS value to a native object based on the given type and descriptor. If failureCode is given, then we're actually @@ -5071,7 +5072,7 @@ class CGConstant(CGThing): return f"pub const {name}: {const_type} = {value};\n" -def getUnionTypeTemplateVars(type, descriptorProvider): +def getUnionTypeTemplateVars(type, descriptorProvider: DescriptorProvider): if type.isGeckoInterface(): name = type.inner.identifier.name typeName = descriptorProvider.getDescriptor(name).returnType @@ -5108,6 +5109,12 @@ def getUnionTypeTemplateVars(type, descriptorProvider): elif type.isCallback(): name = type.name typeName = f"{name}<D>" + elif type.isUndefined(): + return { + "name": type.name, + "typeName": "()", + "jsConversion": CGGeneric("if value.is_undefined() { Ok(Some(())) } else { Ok(None) }") + } else: raise TypeError(f"Can't handle {type} in unions yet") @@ -5173,7 +5180,7 @@ impl{self.generic} Clone for {self.type}{self.genericSuffix} {{ def manualImpl(self, t, templateVars): if t == "Clone": return self.manualImplClone(templateVars) - raise f"Don't know how to impl {t} for union" + raise ValueError(f"Don't know how to impl {t} for union") def define(self): def getTypeWrapper(t): @@ -5330,31 +5337,44 @@ class CGUnionConversionStruct(CGThing): stringTypes = [t for t in memberTypes if t.isString() or t.isEnum()] numericTypes = [t for t in memberTypes if t.isNumeric()] booleanTypes = [t for t in memberTypes if t.isBoolean()] - if stringTypes or numericTypes or booleanTypes: + numUndefinedVariants = [t.isUndefined() for t in memberTypes].count(True) + if stringTypes or numericTypes or booleanTypes or numUndefinedVariants != 0: assert len(stringTypes) <= 1 assert len(numericTypes) <= 1 assert len(booleanTypes) <= 1 + assert numUndefinedVariants <= 1 def getStringOrPrimitiveConversion(memberType): typename = get_name(memberType) return CGGeneric(get_match(typename)) + other = [] stringConversion = list(map(getStringOrPrimitiveConversion, stringTypes)) numericConversion = list(map(getStringOrPrimitiveConversion, numericTypes)) booleanConversion = list(map(getStringOrPrimitiveConversion, booleanTypes)) + undefinedConversion = CGGeneric("return Ok(ConversionResult::Success(Self::Undefined(())));") + if stringConversion: if booleanConversion: other.append(CGIfWrapper("value.get().is_boolean()", booleanConversion[0])) if numericConversion: other.append(CGIfWrapper("value.get().is_number()", numericConversion[0])) + if numUndefinedVariants != 0: + other.append(CGIfWrapper("value.get().is_undefined()", undefinedConversion)) other.append(stringConversion[0]) elif numericConversion: if booleanConversion: other.append(CGIfWrapper("value.get().is_boolean()", booleanConversion[0])) + if numUndefinedVariants != 0: + other.append(CGIfWrapper("value.get().is_undefined()", undefinedConversion)) other.append(numericConversion[0]) - else: - assert booleanConversion + elif booleanConversion: + if numUndefinedVariants != 0: + other.append(CGIfWrapper("value.get().is_undefined()", undefinedConversion)) other.append(booleanConversion[0]) + else: + assert numUndefinedVariants != 0 + other.append(undefinedConversion) conversions.append(CGList(other, "\n\n")) conversions.append(CGGeneric( f'Ok(ConversionResult::Failure("argument could not be converted to any of: {", ".join(names)}".into()))' @@ -5376,6 +5396,10 @@ class CGUnionConversionStruct(CGThing): post="\n}") def try_method(self, t): + if t.isUndefined(): + # undefined does not require a conversion method, so we don't generate one + return CGGeneric("") + templateVars = getUnionTypeTemplateVars(t, self.descriptorProvider) actualType = templateVars["typeName"] if type_needs_tracing(t): @@ -7151,7 +7175,7 @@ impl{self.generic} Clone for {self.makeClassName(self.dictionary)}{self.genericS def manualImpl(self, t): if t == "Clone": return self.manualImplClone() - raise f"Don't know how to impl {t} for dicts." + raise ValueError(f"Don't know how to impl {t} for dicts.") def struct(self): d = self.dictionary diff --git a/components/script_bindings/webidls/ImageBitmap.webidl b/components/script_bindings/webidls/ImageBitmap.webidl index aaa35c67995..b9b811eb9bd 100644 --- a/components/script_bindings/webidls/ImageBitmap.webidl +++ b/components/script_bindings/webidls/ImageBitmap.webidl @@ -9,8 +9,7 @@ * You are granted a license to use, reproduce and create derivative works of this document. */ -//[Exposed=(Window,Worker), Serializable, Transferable] -[Exposed=(Window,Worker), Pref="dom_imagebitmap_enabled"] +[Exposed=(Window,Worker), Serializable, Transferable, Pref="dom_imagebitmap_enabled"] interface ImageBitmap { readonly attribute unsigned long width; readonly attribute unsigned long height; diff --git a/components/script_bindings/webidls/TestBinding.webidl b/components/script_bindings/webidls/TestBinding.webidl index f2c45313228..33ba2f41fbb 100644 --- a/components/script_bindings/webidls/TestBinding.webidl +++ b/components/script_bindings/webidls/TestBinding.webidl @@ -627,3 +627,6 @@ dictionary NotUsedAnyWhereElse {}; dictionary RecordFieldWithUnionInside { record<USVString, (USVString or NotUsedAnyWhereElse)> recordWithUnionField; }; + +// https://github.com/servo/servo/issues/28679 +typedef (USVString or undefined) UnionWithUndefinedVariant; diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml index 687cdd6a5a2..5988dbdc4b9 100644 --- a/components/servo/Cargo.toml +++ b/components/servo/Cargo.toml @@ -72,7 +72,6 @@ bluetooth_traits = { workspace = true, optional = true } canvas = { path = "../canvas" } webgl = { path = "../webgl", default-features = false } canvas_traits = { workspace = true } -cfg-if = { workspace = true } compositing = { path = "../compositing" } compositing_traits = { workspace = true } constellation = { path = "../constellation" } diff --git a/components/shared/base/id.rs b/components/shared/base/id.rs index b6ad1b3de9b..a091311d237 100644 --- a/components/shared/base/id.rs +++ b/components/shared/base/id.rs @@ -371,6 +371,8 @@ namespace_id! {DomExceptionId, DomExceptionIndex, "DomException"} namespace_id! {HistoryStateId, HistoryStateIndex, "HistoryState"} +namespace_id! {ImageBitmapId, ImageBitmapIndex, "ImageBitmap"} + // We provide ids just for unit testing. pub const TEST_NAMESPACE: PipelineNamespaceId = PipelineNamespaceId(1234); #[allow(unsafe_code)] diff --git a/components/shared/constellation/Cargo.toml b/components/shared/constellation/Cargo.toml index 53a4307df60..3b093b3f684 100644 --- a/components/shared/constellation/Cargo.toml +++ b/components/shared/constellation/Cargo.toml @@ -17,7 +17,6 @@ webgpu = ["wgpu-core"] [dependencies] base = { workspace = true } -bitflags = { workspace = true } canvas_traits = { workspace = true } devtools_traits = { workspace = true } embedder_traits = { workspace = true } diff --git a/components/shared/constellation/structured_data/mod.rs b/components/shared/constellation/structured_data/mod.rs index 81e3849e476..3ea0d78eaf3 100644 --- a/components/shared/constellation/structured_data/mod.rs +++ b/components/shared/constellation/structured_data/mod.rs @@ -10,7 +10,7 @@ mod transferable; use std::collections::HashMap; -use base::id::{BlobId, DomExceptionId, DomPointId, MessagePortId}; +use base::id::{BlobId, DomExceptionId, DomPointId, ImageBitmapId, MessagePortId}; use log::warn; use malloc_size_of_derive::MallocSizeOf; use serde::{Deserialize, Serialize}; @@ -34,6 +34,10 @@ pub struct StructuredSerializedData { pub ports: Option<HashMap<MessagePortId, MessagePortImpl>>, /// Transform streams transferred objects. pub transform_streams: Option<HashMap<MessagePortId, TransformStreamData>>, + /// Serialized image bitmap objects. + pub image_bitmaps: Option<HashMap<ImageBitmapId, SerializableImageBitmap>>, + /// Transferred image bitmap objects. + pub transferred_image_bitmaps: Option<HashMap<ImageBitmapId, SerializableImageBitmap>>, } impl StructuredSerializedData { @@ -42,6 +46,7 @@ impl StructuredSerializedData { field.as_ref().is_some_and(|h| h.is_empty()) } match val { + Transferrable::ImageBitmap => is_field_empty(&self.transferred_image_bitmaps), Transferrable::MessagePort => is_field_empty(&self.ports), Transferrable::ReadableStream => is_field_empty(&self.ports), Transferrable::WritableStream => is_field_empty(&self.ports), diff --git a/components/shared/constellation/structured_data/serializable.rs b/components/shared/constellation/structured_data/serializable.rs index 22370087665..cbb932c52ec 100644 --- a/components/shared/constellation/structured_data/serializable.rs +++ b/components/shared/constellation/structured_data/serializable.rs @@ -11,7 +11,7 @@ use std::cell::RefCell; use std::collections::HashMap; use std::path::PathBuf; -use base::id::{BlobId, DomExceptionId, DomPointId}; +use base::id::{BlobId, DomExceptionId, DomPointId, ImageBitmapId}; use malloc_size_of_derive::MallocSizeOf; use net_traits::filemanager_thread::RelativePos; use serde::{Deserialize, Serialize}; @@ -47,6 +47,8 @@ pub enum Serializable { DomPointReadOnly, /// The `DOMException` interface. DomException, + /// The `ImageBitmap` interface. + ImageBitmap, } impl Serializable { @@ -62,6 +64,9 @@ impl Serializable { Serializable::DomException => { StructuredSerializedData::clone_all_of_type::<DomException> }, + Serializable::ImageBitmap => { + StructuredSerializedData::clone_all_of_type::<SerializableImageBitmap> + }, } } } @@ -312,3 +317,31 @@ impl BroadcastClone for DomException { Some(self.clone()) } } + +#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)] +/// A serializable version of the ImageBitmap interface. +pub struct SerializableImageBitmap { + pub width: u32, + pub height: u32, + pub bitmap_data: Vec<u8>, +} + +impl BroadcastClone for SerializableImageBitmap { + type Id = ImageBitmapId; + + fn source( + data: &StructuredSerializedData, + ) -> &Option<std::collections::HashMap<Self::Id, Self>> { + &data.image_bitmaps + } + + fn destination( + data: &mut StructuredSerializedData, + ) -> &mut Option<std::collections::HashMap<Self::Id, Self>> { + &mut data.image_bitmaps + } + + fn clone_for_broadcast(&self) -> Option<Self> { + Some(self.clone()) + } +} diff --git a/components/shared/constellation/structured_data/transferable.rs b/components/shared/constellation/structured_data/transferable.rs index 3210a41a538..bce10420182 100644 --- a/components/shared/constellation/structured_data/transferable.rs +++ b/components/shared/constellation/structured_data/transferable.rs @@ -24,6 +24,8 @@ pub struct TransformStreamData { /// All the DOM interfaces that can be transferred. #[derive(Clone, Copy, Debug, EnumIter)] pub enum Transferrable { + /// The `ImageBitmap` interface. + ImageBitmap, /// The `MessagePort` interface. MessagePort, /// The `ReadableStream` interface. diff --git a/components/shared/embedder/Cargo.toml b/components/shared/embedder/Cargo.toml index d938169d37a..4904adf6447 100644 --- a/components/shared/embedder/Cargo.toml +++ b/components/shared/embedder/Cargo.toml @@ -18,7 +18,6 @@ baked-default-resources = [] [dependencies] base = { workspace = true } -cfg-if = { workspace = true } cookie = { workspace = true } crossbeam-channel = { workspace = true } euclid = { workspace = true } diff --git a/components/shared/profile/Cargo.toml b/components/shared/profile/Cargo.toml index 8086bf17ba2..68a7df28c00 100644 --- a/components/shared/profile/Cargo.toml +++ b/components/shared/profile/Cargo.toml @@ -25,6 +25,5 @@ serde = { workspace = true } servo_allocator = { path = "../../allocator" } servo_config = { path = "../../config" } signpost = { git = "https://github.com/pcwalton/signpost.git" } -strum_macros = { workspace = true } time = { workspace = true } tracing = { workspace = true, optional = true } diff --git a/components/shared/script/Cargo.toml b/components/shared/script/Cargo.toml index 0d3690188fe..69438867cc0 100644 --- a/components/shared/script/Cargo.toml +++ b/components/shared/script/Cargo.toml @@ -26,7 +26,6 @@ crossbeam-channel = { workspace = true } devtools_traits = { workspace = true } embedder_traits = { workspace = true } euclid = { workspace = true } -http = { workspace = true } ipc-channel = { workspace = true } keyboard-types = { workspace = true } malloc_size_of = { workspace = true } diff --git a/components/shared/script_layout/Cargo.toml b/components/shared/script_layout/Cargo.toml index 06690192f73..167606f7247 100644 --- a/components/shared/script_layout/Cargo.toml +++ b/components/shared/script_layout/Cargo.toml @@ -15,7 +15,6 @@ path = "lib.rs" base = { workspace = true } app_units = { workspace = true } atomic_refcell = { workspace = true } -canvas_traits = { workspace = true } compositing_traits = { workspace = true } constellation_traits = { workspace = true } embedder_traits = { workspace = true } @@ -29,7 +28,6 @@ ipc-channel = { workspace = true } libc = { workspace = true } malloc_size_of = { workspace = true } malloc_size_of_derive = { workspace = true } -metrics = { path = "../../metrics" } net_traits = { workspace = true } pixels = { path = "../../pixels" } profile_traits = { workspace = true } @@ -40,5 +38,4 @@ serde = { workspace = true } servo_arc = { workspace = true } servo_url = { path = "../../url" } stylo = { workspace = true } -stylo_traits = { workspace = true } webrender_api = { workspace = true } diff --git a/components/webdriver_server/Cargo.toml b/components/webdriver_server/Cargo.toml index 70de7f0fc50..47c77e0e9a0 100644 --- a/components/webdriver_server/Cargo.toml +++ b/components/webdriver_server/Cargo.toml @@ -24,9 +24,7 @@ image = { workspace = true } ipc-channel = { workspace = true } keyboard-types = { workspace = true } log = { workspace = true } -net_traits = { workspace = true } pixels = { path = "../pixels" } -script_traits = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } servo_config = { path = "../config" } diff --git a/components/webgpu/Cargo.toml b/components/webgpu/Cargo.toml index 39ca562affe..39b2e952679 100644 --- a/components/webgpu/Cargo.toml +++ b/components/webgpu/Cargo.toml @@ -18,7 +18,6 @@ compositing_traits = { workspace = true } euclid = { workspace = true } ipc-channel = { workspace = true } log = { workspace = true } -malloc_size_of = { workspace = true } serde = { workspace = true, features = ["serde_derive"] } servo_config = { path = "../config" } webgpu_traits = { workspace = true } diff --git a/components/webxr/Cargo.toml b/components/webxr/Cargo.toml index 49315ac41db..809e8483bd4 100644 --- a/components/webxr/Cargo.toml +++ b/components/webxr/Cargo.toml @@ -26,7 +26,6 @@ openxr-api = ["angle", "openxr", "winapi", "wio", "surfman/sm-angle-default"] [dependencies] crossbeam-channel = { workspace = true } -embedder_traits = { workspace = true } euclid = { workspace = true } glow = { workspace = true } log = { workspace = true } |