aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/config/prefs.rs5
-rw-r--r--components/layout/display_list/background.rs18
-rw-r--r--components/layout/flow/root.rs15
-rw-r--r--components/layout/layout_impl.rs58
-rw-r--r--components/layout/traversal.rs4
-rw-r--r--components/script/dom/bindings/reflector.rs14
-rw-r--r--components/script/dom/bindings/structuredclone.rs27
-rw-r--r--components/script/dom/globalscope.rs6
-rw-r--r--components/script/dom/htmlareaelement.rs26
-rw-r--r--components/script/dom/imagebitmap.rs133
-rw-r--r--components/script/dom/urlpattern.rs182
-rw-r--r--components/script_bindings/codegen/CodegenRust.py44
-rw-r--r--components/script_bindings/interface.rs18
-rw-r--r--components/script_bindings/record.rs10
-rw-r--r--components/script_bindings/reflector.rs13
-rw-r--r--components/script_bindings/webidls/ImageBitmap.webidl3
-rw-r--r--components/script_bindings/webidls/TestBinding.webidl3
-rw-r--r--components/script_bindings/webidls/URLPattern.webidl40
-rw-r--r--components/shared/base/id.rs2
-rw-r--r--components/shared/constellation/structured_data/mod.rs7
-rw-r--r--components/shared/constellation/structured_data/serializable.rs35
-rw-r--r--components/shared/constellation/structured_data/transferable.rs2
22 files changed, 494 insertions, 171 deletions
diff --git a/components/config/prefs.rs b/components/config/prefs.rs
index 64dd9659e56..896a4fe0bc4 100644
--- a/components/config/prefs.rs
+++ b/components/config/prefs.rs
@@ -116,10 +116,6 @@ pub struct Preferences {
// https://testutils.spec.whatwg.org#availability
pub dom_testutils_enabled: bool,
pub dom_trusted_types_enabled: bool,
- /// Enable the [URLPattern] API.
- ///
- /// [URLPattern]: https://developer.mozilla.org/en-US/docs/Web/API/URLPattern
- pub dom_urlpattern_enabled: bool,
pub dom_xpath_enabled: bool,
/// Enable WebGL2 APIs.
pub dom_webgl2_enabled: bool,
@@ -292,7 +288,6 @@ impl Preferences {
dom_testperf_enabled: false,
dom_testutils_enabled: false,
dom_trusted_types_enabled: false,
- dom_urlpattern_enabled: false,
dom_webgl2_enabled: false,
dom_webgpu_enabled: false,
dom_webgpu_wgpu_backend: String::new(),
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/script/dom/bindings/reflector.rs b/components/script/dom/bindings/reflector.rs
index 0a5afbce487..c888686974e 100644
--- a/components/script/dom/bindings/reflector.rs
+++ b/components/script/dom/bindings/reflector.rs
@@ -11,7 +11,7 @@ use crate::DomTypes;
use crate::dom::bindings::conversions::DerivedFrom;
use crate::dom::bindings::root::DomRoot;
use crate::dom::globalscope::GlobalScope;
-use crate::realms::InRealm;
+use crate::realms::{InRealm, enter_realm};
use crate::script_runtime::CanGc;
/// Create the reflector for a new DOM object and yield ownership to the
@@ -42,7 +42,16 @@ where
}
pub(crate) trait DomGlobal {
+ /// Returns the [relevant global] in whatever realm is currently active.
+ ///
+ /// [relevant global]: https://html.spec.whatwg.org/multipage/#concept-relevant-global
fn global_(&self, realm: InRealm) -> DomRoot<GlobalScope>;
+
+ /// Returns the [relevant global] in the same realm as the callee object.
+ /// If you know the callee's realm is already the current realm, it is
+ /// more efficient to call [DomGlobal::global_] instead.
+ ///
+ /// [relevant global]: https://html.spec.whatwg.org/multipage/#concept-relevant-global
fn global(&self) -> DomRoot<GlobalScope>;
}
@@ -51,7 +60,8 @@ impl<T: DomGlobalGeneric<crate::DomTypeHolder>> DomGlobal for T {
<Self as DomGlobalGeneric<crate::DomTypeHolder>>::global_(self, realm)
}
fn global(&self) -> DomRoot<GlobalScope> {
- <Self as DomGlobalGeneric<crate::DomTypeHolder>>::global(self)
+ let realm = enter_realm(self);
+ <Self as DomGlobalGeneric<crate::DomTypeHolder>>::global_(self, InRealm::entered(&realm))
}
}
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/dom/urlpattern.rs b/components/script/dom/urlpattern.rs
index c811d3a9a70..63665f6df0b 100644
--- a/components/script/dom/urlpattern.rs
+++ b/components/script/dom/urlpattern.rs
@@ -4,6 +4,7 @@
use dom_struct::dom_struct;
use js::rust::HandleObject;
+use script_bindings::codegen::GenericBindings::URLPatternBinding::URLPatternResult;
use script_bindings::codegen::GenericUnionTypes::USVStringOrURLPatternInit;
use script_bindings::error::{Error, Fallible};
use script_bindings::reflector::Reflector;
@@ -46,7 +47,7 @@ impl URLPattern {
) -> Fallible<DomRoot<URLPattern>> {
// The section below converts from servos types to the types used in the urlpattern crate
let base_url = base_url.map(|usv_string| usv_string.0);
- let input = bindings_to_third_party::map_urlpattern_input(input, base_url.clone());
+ let input = bindings_to_third_party::map_urlpattern_input(input);
let options = urlpattern::UrlPatternOptions {
ignore_case: options.ignoreCase,
};
@@ -94,6 +95,50 @@ impl URLPatternMethods<crate::DomTypeHolder> for URLPattern {
URLPattern::initialize(global, proto, input, None, options, can_gc)
}
+ /// <https://urlpattern.spec.whatwg.org/#dom-urlpattern-test>
+ fn Test(
+ &self,
+ input: USVStringOrURLPatternInit,
+ base_url: Option<USVString>,
+ ) -> Fallible<bool> {
+ let input = bindings_to_third_party::map_urlpattern_input(input);
+ let inputs = urlpattern::quirks::process_match_input(input, base_url.as_deref())
+ .map_err(|error| Error::Type(format!("{error}")))?;
+ let Some((match_input, _)) = inputs else {
+ return Ok(false);
+ };
+
+ self.associated_url_pattern
+ .test(match_input)
+ .map_err(|error| Error::Type(format!("{error}")))
+ }
+
+ /// <https://urlpattern.spec.whatwg.org/#dom-urlpattern-exec>
+ fn Exec(
+ &self,
+ input: USVStringOrURLPatternInit,
+ base_url: Option<USVString>,
+ ) -> Fallible<Option<URLPatternResult>> {
+ let input = bindings_to_third_party::map_urlpattern_input(input);
+ let inputs = urlpattern::quirks::process_match_input(input, base_url.as_deref())
+ .map_err(|error| Error::Type(format!("{error}")))?;
+ let Some((match_input, inputs)) = inputs else {
+ return Ok(None);
+ };
+
+ let result = self
+ .associated_url_pattern
+ .exec(match_input)
+ .map_err(|error| Error::Type(format!("{error}")))?;
+ let Some(result) = result else {
+ return Ok(None);
+ };
+
+ Ok(Some(third_party_to_bindings::map_urlpattern_result(
+ result, inputs,
+ )))
+ }
+
/// <https://urlpattern.spec.whatwg.org/#dom-urlpattern-protocol>
fn Protocol(&self) -> USVString {
// Step 1. Return this’s associated URL pattern’s protocol component’s pattern string.
@@ -151,54 +196,115 @@ impl URLPatternMethods<crate::DomTypeHolder> for URLPattern {
}
mod bindings_to_third_party {
+ use script_bindings::codegen::GenericBindings::URLPatternBinding::URLPatternInit;
+
use crate::dom::urlpattern::USVStringOrURLPatternInit;
+ fn map_urlpatterninit(pattern_init: URLPatternInit) -> urlpattern::quirks::UrlPatternInit {
+ urlpattern::quirks::UrlPatternInit {
+ protocol: pattern_init.protocol.map(|protocol| protocol.0),
+ username: pattern_init.username.map(|username| username.0),
+ password: pattern_init.password.map(|password| password.0),
+ hostname: pattern_init.hostname.map(|hostname| hostname.0),
+ port: pattern_init.port.map(|hash| hash.0),
+ pathname: pattern_init
+ .pathname
+ .as_ref()
+ .map(|usv_string| usv_string.to_string()),
+ search: pattern_init.search.map(|search| search.0),
+ hash: pattern_init.hash.map(|hash| hash.0),
+ base_url: pattern_init.baseURL.map(|base_url| base_url.0),
+ }
+ }
+
pub(super) fn map_urlpattern_input(
input: USVStringOrURLPatternInit,
- base_url: Option<String>,
) -> urlpattern::quirks::StringOrInit {
match input {
USVStringOrURLPatternInit::USVString(usv_string) => {
urlpattern::quirks::StringOrInit::String(usv_string.0)
},
USVStringOrURLPatternInit::URLPatternInit(pattern_init) => {
- let pattern_init = urlpattern::quirks::UrlPatternInit {
- protocol: pattern_init
- .protocol
- .as_ref()
- .map(|usv_string| usv_string.to_string()),
- username: pattern_init
- .username
- .as_ref()
- .map(|usv_string| usv_string.to_string()),
- password: pattern_init
- .password
- .as_ref()
- .map(|usv_string| usv_string.to_string()),
- hostname: pattern_init
- .hostname
- .as_ref()
- .map(|usv_string| usv_string.to_string()),
- port: pattern_init
- .port
- .as_ref()
- .map(|usv_string| usv_string.to_string()),
- pathname: pattern_init
- .pathname
- .as_ref()
- .map(|usv_string| usv_string.to_string()),
- search: pattern_init
- .search
- .as_ref()
- .map(|usv_string| usv_string.to_string()),
- hash: pattern_init
- .hash
- .as_ref()
- .map(|usv_string| usv_string.to_string()),
- base_url,
- };
- urlpattern::quirks::StringOrInit::Init(pattern_init)
+ urlpattern::quirks::StringOrInit::Init(map_urlpatterninit(pattern_init))
+ },
+ }
+ }
+}
+
+mod third_party_to_bindings {
+ use script_bindings::codegen::GenericBindings::URLPatternBinding::{
+ URLPatternComponentResult, URLPatternInit, URLPatternResult,
+ };
+ use script_bindings::codegen::GenericUnionTypes::USVStringOrUndefined;
+ use script_bindings::record::Record;
+ use script_bindings::str::USVString;
+
+ use crate::dom::bindings::codegen::UnionTypes::USVStringOrURLPatternInit;
+
+ // FIXME: For some reason codegen puts a lot of options into these types that don't make sense
+
+ fn map_component_result(
+ component_result: urlpattern::UrlPatternComponentResult,
+ ) -> URLPatternComponentResult {
+ let mut groups = Record::new();
+ for (key, value) in component_result.groups.iter() {
+ let value = match value {
+ Some(value) => USVStringOrUndefined::USVString(USVString(value.to_owned())),
+ None => USVStringOrUndefined::Undefined(()),
+ };
+
+ groups.insert(USVString(key.to_owned()), value);
+ }
+
+ URLPatternComponentResult {
+ input: Some(component_result.input.into()),
+ groups: Some(groups),
+ }
+ }
+
+ fn map_urlpatterninit(pattern_init: urlpattern::quirks::UrlPatternInit) -> URLPatternInit {
+ URLPatternInit {
+ baseURL: pattern_init.base_url.map(USVString),
+ protocol: pattern_init.protocol.map(USVString),
+ username: pattern_init.username.map(USVString),
+ password: pattern_init.password.map(USVString),
+ hostname: pattern_init.hostname.map(USVString),
+ port: pattern_init.port.map(USVString),
+ pathname: pattern_init.pathname.map(USVString),
+ search: pattern_init.search.map(USVString),
+ hash: pattern_init.hash.map(USVString),
+ }
+ }
+
+ pub(super) fn map_urlpattern_result(
+ result: urlpattern::UrlPatternResult,
+ (string_or_init, base_url): urlpattern::quirks::Inputs,
+ ) -> URLPatternResult {
+ let string_or_init = match string_or_init {
+ urlpattern::quirks::StringOrInit::String(string) => {
+ USVStringOrURLPatternInit::USVString(USVString(string))
+ },
+ urlpattern::quirks::StringOrInit::Init(pattern_init) => {
+ USVStringOrURLPatternInit::URLPatternInit(map_urlpatterninit(pattern_init))
},
+ };
+
+ let mut inputs = vec![string_or_init];
+
+ if let Some(base_url) = base_url {
+ inputs.push(USVStringOrURLPatternInit::USVString(USVString(base_url)));
+ }
+
+ URLPatternResult {
+ inputs: Some(inputs),
+ protocol: Some(map_component_result(result.protocol)),
+ username: Some(map_component_result(result.username)),
+ password: Some(map_component_result(result.password)),
+ hostname: Some(map_component_result(result.hostname)),
+ port: Some(map_component_result(result.port)),
+ pathname: Some(map_component_result(result.pathname)),
+ search: Some(map_component_result(result.search)),
+ hash: Some(map_component_result(result.hash)),
}
}
}
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/interface.rs b/components/script_bindings/interface.rs
index 08ee0a4f420..e185cfe9cfd 100644
--- a/components/script_bindings/interface.rs
+++ b/components/script_bindings/interface.rs
@@ -16,11 +16,11 @@ use js::jsapi::{
GetFunctionRealm, GetNonCCWObjectGlobal, GetRealmGlobalOrNull, GetWellKnownSymbol,
HandleObject as RawHandleObject, IsSharableCompartment, IsSystemCompartment,
JS_AtomizeAndPinString, JS_GetFunctionObject, JS_GetProperty, JS_IterateCompartments,
- JS_NewFunction, JS_NewGlobalObject, JS_NewObject, JS_NewPlainObject, JS_NewStringCopyN,
- JS_SetReservedSlot, JS_WrapObject, JSAutoRealm, JSClass, JSClassOps, JSContext,
- JSFUN_CONSTRUCTOR, JSFunctionSpec, JSObject, JSPROP_PERMANENT, JSPROP_READONLY,
- JSPROP_RESOLVING, JSPropertySpec, JSString, JSTracer, ObjectOps, OnNewGlobalHookOption,
- SymbolCode, TrueHandleValue, Value, jsid,
+ JS_NewFunction, JS_NewGlobalObject, JS_NewObject, JS_NewStringCopyN, JS_SetReservedSlot,
+ JS_WrapObject, JSAutoRealm, JSClass, JSClassOps, JSContext, JSFUN_CONSTRUCTOR, JSFunctionSpec,
+ JSObject, JSPROP_ENUMERATE, JSPROP_PERMANENT, JSPROP_READONLY, JSPROP_RESOLVING,
+ JSPropertySpec, JSString, JSTracer, ObjectOps, OnNewGlobalHookOption, SymbolCode,
+ TrueHandleValue, Value, jsid,
};
use js::jsval::{JSVal, NullValue, PrivateValue};
use js::rust::wrappers::{
@@ -473,7 +473,11 @@ fn create_unscopable_object(cx: SafeJSContext, names: &[&CStr], mut rval: Mutabl
assert!(!names.is_empty());
assert!(rval.is_null());
unsafe {
- rval.set(JS_NewPlainObject(*cx));
+ rval.set(JS_NewObjectWithGivenProto(
+ *cx,
+ ptr::null(),
+ HandleObject::null(),
+ ));
assert!(!rval.is_null());
for &name in names {
assert!(JS_DefineProperty(
@@ -481,7 +485,7 @@ fn create_unscopable_object(cx: SafeJSContext, names: &[&CStr], mut rval: Mutabl
rval.handle(),
name.as_ptr(),
HandleValue::from_raw(TrueHandleValue),
- JSPROP_READONLY as u32,
+ JSPROP_ENUMERATE as u32,
));
}
}
diff --git a/components/script_bindings/record.rs b/components/script_bindings/record.rs
index 2668a84f42c..d469faefaf2 100644
--- a/components/script_bindings/record.rs
+++ b/components/script_bindings/record.rs
@@ -7,7 +7,7 @@
use std::cmp::Eq;
use std::hash::Hash;
use std::marker::Sized;
-use std::ops::Deref;
+use std::ops::{Deref, DerefMut};
use indexmap::IndexMap;
use js::conversions::{ConversionResult, FromJSValConvertible, ToJSValConvertible};
@@ -94,11 +94,17 @@ impl<K: RecordKey, V> Record<K, V> {
impl<K: RecordKey, V> Deref for Record<K, V> {
type Target = IndexMap<K, V>;
- fn deref(&self) -> &IndexMap<K, V> {
+ fn deref(&self) -> &Self::Target {
&self.map
}
}
+impl<K: RecordKey, V> DerefMut for Record<K, V> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.map
+ }
+}
+
impl<K, V, C> FromJSValConvertible for Record<K, V>
where
K: RecordKey,
diff --git a/components/script_bindings/reflector.rs b/components/script_bindings/reflector.rs
index 6b6ae03cb69..4b91b0536fc 100644
--- a/components/script_bindings/reflector.rs
+++ b/components/script_bindings/reflector.rs
@@ -8,7 +8,7 @@ use malloc_size_of_derive::MallocSizeOf;
use crate::interfaces::GlobalScopeHelpers;
use crate::iterable::{Iterable, IterableIterator};
-use crate::realms::{AlreadyInRealm, InRealm};
+use crate::realms::InRealm;
use crate::root::{Dom, DomRoot, Root};
use crate::script_runtime::{CanGc, JSContext};
use crate::{DomTypes, JSTraceable};
@@ -108,17 +108,6 @@ pub trait DomGlobalGeneric<D: DomTypes>: DomObject {
{
D::GlobalScope::from_reflector(self, realm)
}
-
- /// Returns the [`GlobalScope`] of the realm that the [`DomObject`] was created in. If this
- /// object is a `Node`, this will be different from it's owning `Document` if adopted by. For
- /// `Node`s it's almost always better to use `NodeTraits::owning_global`.
- fn global(&self) -> DomRoot<D::GlobalScope>
- where
- Self: Sized,
- {
- let realm = AlreadyInRealm::assert_for_cx(D::GlobalScope::get_cx());
- D::GlobalScope::from_reflector(self, InRealm::already(&realm))
- }
}
impl<D: DomTypes, T: DomObject> DomGlobalGeneric<D> for T {}
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/script_bindings/webidls/URLPattern.webidl b/components/script_bindings/webidls/URLPattern.webidl
index f61b65702bc..a29cb650c23 100644
--- a/components/script_bindings/webidls/URLPattern.webidl
+++ b/components/script_bindings/webidls/URLPattern.webidl
@@ -6,14 +6,14 @@
typedef (USVString or URLPatternInit) URLPatternInput;
-[Exposed=(Window,Worker), Pref="dom_urlpattern_enabled"]
+[Exposed=(Window,Worker)]
interface URLPattern {
[Throws] constructor(URLPatternInput input, USVString baseURL, optional URLPatternOptions options = {});
[Throws] constructor(optional URLPatternInput input = {}, optional URLPatternOptions options = {});
- // [Throws] boolean test(optional URLPatternInput input = {}, optional USVString baseURL);
+ [Throws] boolean test(optional URLPatternInput input = {}, optional USVString baseURL);
- // [Throws] URLPatternResult? exec(optional URLPatternInput input = {}, optional USVString baseURL);
+ [Throws] URLPatternResult? exec(optional URLPatternInput input = {}, optional USVString baseURL);
readonly attribute USVString protocol;
readonly attribute USVString username;
@@ -43,20 +43,20 @@ dictionary URLPatternOptions {
boolean ignoreCase = false;
};
-// dictionary URLPatternResult {
-// sequence<URLPatternInput> inputs;
-
-// URLPatternComponentResult protocol;
-// URLPatternComponentResult username;
-// URLPatternComponentResult password;
-// URLPatternComponentResult hostname;
-// URLPatternComponentResult port;
-// URLPatternComponentResult pathname;
-// URLPatternComponentResult search;
-// URLPatternComponentResult hash;
-// };
-
-// dictionary URLPatternComponentResult {
-// USVString input;
-// record<USVString, (USVString or undefined)> groups;
-// };
+dictionary URLPatternResult {
+ sequence<URLPatternInput> inputs;
+
+ URLPatternComponentResult protocol;
+ URLPatternComponentResult username;
+ URLPatternComponentResult password;
+ URLPatternComponentResult hostname;
+ URLPatternComponentResult port;
+ URLPatternComponentResult pathname;
+ URLPatternComponentResult search;
+ URLPatternComponentResult hash;
+};
+
+dictionary URLPatternComponentResult {
+ USVString input;
+ record<USVString, (USVString or undefined)> groups;
+};
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/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.