aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/element.rs47
-rw-r--r--components/script/dom/globalscope.rs196
-rw-r--r--components/script/dom/htmlelement.rs2
-rw-r--r--components/script/dom/htmlmediaelement.rs4
-rw-r--r--components/script/dom/htmlvideoelement.rs6
-rw-r--r--components/script/dom/imagebitmap.rs6
-rw-r--r--components/script/dom/imagedata.rs5
-rw-r--r--components/script/dom/node.rs9
-rw-r--r--components/script/dom/offscreencanvas.rs4
-rw-r--r--components/script/dom/raredata.rs7
-rw-r--r--components/script/dom/webglrenderingcontext.rs17
-rw-r--r--components/script/dom/window.rs27
-rw-r--r--components/script/dom/windowproxy.rs37
-rw-r--r--components/script/dom/workerglobalscope.rs27
14 files changed, 338 insertions, 56 deletions
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs
index 961fb92121d..1fe51407638 100644
--- a/components/script/dom/element.rs
+++ b/components/script/dom/element.rs
@@ -861,8 +861,14 @@ pub(crate) fn get_attr_for_layout<'dom>(
pub(crate) trait LayoutElementHelpers<'dom> {
fn attrs(self) -> &'dom [LayoutDom<'dom, Attr>];
- fn has_class_for_layout(self, name: &AtomIdent, case_sensitivity: CaseSensitivity) -> bool;
+ fn has_class_or_part_for_layout(
+ self,
+ name: &AtomIdent,
+ attr_name: &LocalName,
+ case_sensitivity: CaseSensitivity,
+ ) -> bool;
fn get_classes_for_layout(self) -> Option<&'dom [Atom]>;
+ fn get_parts_for_layout(self) -> Option<&'dom [Atom]>;
fn synthesize_presentational_hints_for_legacy_attributes<V>(self, hints: &mut V)
where
@@ -905,8 +911,13 @@ impl<'dom> LayoutElementHelpers<'dom> for LayoutDom<'dom, Element> {
}
#[inline]
- fn has_class_for_layout(self, name: &AtomIdent, case_sensitivity: CaseSensitivity) -> bool {
- get_attr_for_layout(self, &ns!(), &local_name!("class")).is_some_and(|attr| {
+ fn has_class_or_part_for_layout(
+ self,
+ name: &AtomIdent,
+ attr_name: &LocalName,
+ case_sensitivity: CaseSensitivity,
+ ) -> bool {
+ get_attr_for_layout(self, &ns!(), attr_name).is_some_and(|attr| {
attr.to_tokens()
.unwrap()
.iter()
@@ -920,6 +931,11 @@ impl<'dom> LayoutElementHelpers<'dom> for LayoutDom<'dom, Element> {
.map(|attr| attr.to_tokens().unwrap())
}
+ fn get_parts_for_layout(self) -> Option<&'dom [Atom]> {
+ get_attr_for_layout(self, &ns!(), &local_name!("part"))
+ .map(|attr| attr.to_tokens().unwrap())
+ }
+
fn synthesize_presentational_hints_for_legacy_attributes<V>(self, hints: &mut V)
where
V: Push<ApplicableDeclarationBlock>,
@@ -1995,6 +2011,16 @@ impl Element {
})
}
+ pub(crate) fn is_part(&self, name: &Atom, case_sensitivity: CaseSensitivity) -> bool {
+ self.get_attribute(&ns!(), &LocalName::from("part"))
+ .is_some_and(|attr| {
+ attr.value()
+ .as_tokens()
+ .iter()
+ .any(|atom| case_sensitivity.eq_atom(name, atom))
+ })
+ }
+
pub(crate) fn set_atomic_attribute(
&self,
local_name: &LocalName,
@@ -4051,6 +4077,13 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
rooted!(in(*cx) let slottable = Slottable(Dom::from_ref(self.upcast::<Node>())));
slottable.find_a_slot(true)
}
+
+ /// <https://drafts.csswg.org/css-shadow-parts/#dom-element-part>
+ fn Part(&self) -> DomRoot<DOMTokenList> {
+ self.ensure_rare_data()
+ .part
+ .or_init(|| DOMTokenList::new(self, &local_name!("part"), None, CanGc::note()))
+ }
}
impl VirtualMethods for Element {
@@ -4190,7 +4223,9 @@ impl VirtualMethods for Element {
match *name {
local_name!("id") => AttrValue::from_atomic(value.into()),
local_name!("name") => AttrValue::from_atomic(value.into()),
- local_name!("class") => AttrValue::from_serialized_tokenlist(value.into()),
+ local_name!("class") | local_name!("part") => {
+ AttrValue::from_serialized_tokenlist(value.into())
+ },
_ => self
.super_type()
.unwrap()
@@ -4564,8 +4599,8 @@ impl SelectorsElement for SelectorWrapper<'_> {
.is_some_and(|atom| case_sensitivity.eq_atom(id, atom))
}
- fn is_part(&self, _name: &AtomIdent) -> bool {
- false
+ fn is_part(&self, name: &AtomIdent) -> bool {
+ Element::is_part(self, name, CaseSensitivity::CaseSensitive)
}
fn imported_part(&self, _: &AtomIdent) -> Option<AtomIdent> {
diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs
index 9bec85afe5b..ade7b86caa8 100644
--- a/components/script/dom/globalscope.rs
+++ b/components/script/dom/globalscope.rs
@@ -29,9 +29,10 @@ use crossbeam_channel::Sender;
use devtools_traits::{PageError, ScriptToDevtoolsControlMsg};
use dom_struct::dom_struct;
use embedder_traits::EmbedderMsg;
+use euclid::default::Size2D;
use http::HeaderMap;
use hyper_serde::Serde;
-use ipc_channel::ipc::{self, IpcSender};
+use ipc_channel::ipc::{self, IpcSender, IpcSharedMemory};
use ipc_channel::router::ROUTER;
use js::glue::{IsWrapper, UnwrapObjectDynamic};
use js::jsapi::{
@@ -59,9 +60,11 @@ use net_traits::{
CoreResourceMsg, CoreResourceThread, FetchResponseListener, IpcSend, ReferrerPolicy,
ResourceThreads, fetch_async,
};
+use pixels::PixelFormat;
use profile_traits::{ipc as profile_ipc, mem as profile_mem, time as profile_time};
use script_bindings::interfaces::GlobalScopeHelpers;
use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
+use snapshot::Snapshot;
use timers::{TimerEventId, TimerEventRequest, TimerSource};
use url::Origin;
use uuid::Uuid;
@@ -2956,64 +2959,209 @@ impl GlobalScope {
result == CheckResult::Blocked
}
+ /// <https://html.spec.whatwg.org/multipage/#dom-createimagebitmap>
+ #[allow(clippy::too_many_arguments)]
pub(crate) fn create_image_bitmap(
&self,
image: ImageBitmapSource,
+ _sx: i32,
+ _sy: i32,
+ sw: Option<i32>,
+ sh: Option<i32>,
options: &ImageBitmapOptions,
can_gc: CanGc,
) -> Rc<Promise> {
let in_realm_proof = AlreadyInRealm::assert::<crate::DomTypeHolder>();
let p = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), can_gc);
+
+ // Step 1. If either sw or sh is given and is 0, then return a promise rejected with a RangeError.
+ if sw.is_some_and(|w| w == 0) {
+ p.reject_error(
+ Error::Range("'sw' must be a non-zero value".to_owned()),
+ can_gc,
+ );
+ return p;
+ }
+
+ if sh.is_some_and(|h| h == 0) {
+ p.reject_error(
+ Error::Range("'sh' must be a non-zero value".to_owned()),
+ can_gc,
+ );
+ return p;
+ }
+
+ // Step 2. If either options's resizeWidth or options's resizeHeight is present and is 0,
+ // then return a promise rejected with an "InvalidStateError" DOMException.
if options.resizeWidth.is_some_and(|w| w == 0) {
p.reject_error(Error::InvalidState, can_gc);
return p;
}
- if options.resizeHeight.is_some_and(|w| w == 0) {
+ if options.resizeHeight.is_some_and(|h| h == 0) {
p.reject_error(Error::InvalidState, can_gc);
return p;
}
+ // Step 3. Check the usability of the image argument. If this throws an exception or returns bad,
+ // then return a promise rejected with an "InvalidStateError" DOMException.
+ // Step 6. Switch on image:
match image {
- ImageBitmapSource::HTMLCanvasElement(ref canvas) => {
- // https://html.spec.whatwg.org/multipage/#check-the-usability-of-the-image-argument
- if !canvas.is_valid() {
+ ImageBitmapSource::HTMLImageElement(ref image) => {
+ // <https://html.spec.whatwg.org/multipage/#check-the-usability-of-the-image-argument>
+ if !image.is_usable().is_ok_and(|u| u) {
p.reject_error(Error::InvalidState, can_gc);
return p;
}
- match canvas.get_image_data() {
- Some(snapshot) => {
- let image_bitmap = ImageBitmap::new(self, snapshot, can_gc);
- image_bitmap.set_origin_clean(canvas.origin_is_clean());
- p.resolve_native(&(image_bitmap), can_gc);
+ // If no ImageBitmap object can be constructed, then the promise is rejected instead.
+ let Some(img) = image.image_data() else {
+ p.reject_error(Error::InvalidState, can_gc);
+ return p;
+ };
+
+ let Some(img) = img.as_raster_image() else {
+ // Vector HTMLImageElement are not yet supported.
+ p.reject_error(Error::InvalidState, can_gc);
+ return p;
+ };
+
+ let size = Size2D::new(img.metadata.width, img.metadata.height);
+ let format = match img.format {
+ PixelFormat::BGRA8 => snapshot::PixelFormat::BGRA,
+ PixelFormat::RGBA8 => snapshot::PixelFormat::RGBA,
+ pixel_format => {
+ unimplemented!("unsupported pixel format ({:?})", pixel_format)
},
- None => p.reject_error(Error::InvalidState, can_gc),
+ };
+ let alpha_mode = snapshot::AlphaMode::Transparent {
+ premultiplied: false,
+ };
+
+ let snapshot = Snapshot::from_shared_memory(
+ size.cast(),
+ format,
+ alpha_mode,
+ IpcSharedMemory::from_bytes(img.first_frame().bytes),
+ );
+
+ let image_bitmap = ImageBitmap::new(self, snapshot, can_gc);
+ image_bitmap.set_origin_clean(image.same_origin(GlobalScope::entry().origin()));
+
+ p.resolve_native(&image_bitmap, can_gc);
+ },
+ ImageBitmapSource::HTMLVideoElement(ref video) => {
+ // <https://html.spec.whatwg.org/multipage/#check-the-usability-of-the-image-argument>
+ if !video.is_usable() {
+ p.reject_error(Error::InvalidState, can_gc);
+ return p;
+ }
+
+ if video.is_network_state_empty() {
+ p.reject_error(Error::InvalidState, can_gc);
+ return p;
+ }
+
+ // If no ImageBitmap object can be constructed, then the promise is rejected instead.
+ let Some(snapshot) = video.get_current_frame_data() else {
+ p.reject_error(Error::InvalidState, can_gc);
+ return p;
+ };
+
+ let image_bitmap = ImageBitmap::new(self, snapshot, can_gc);
+ image_bitmap.set_origin_clean(video.origin_is_clean());
+
+ p.resolve_native(&image_bitmap, can_gc);
+ },
+ ImageBitmapSource::HTMLCanvasElement(ref canvas) => {
+ // <https://html.spec.whatwg.org/multipage/#check-the-usability-of-the-image-argument>
+ if canvas.get_size().is_empty() {
+ p.reject_error(Error::InvalidState, can_gc);
+ return p;
}
- p
+
+ // If no ImageBitmap object can be constructed, then the promise is rejected instead.
+ let Some(snapshot) = canvas.get_image_data() else {
+ p.reject_error(Error::InvalidState, can_gc);
+ return p;
+ };
+
+ let image_bitmap = ImageBitmap::new(self, snapshot, can_gc);
+ image_bitmap.set_origin_clean(canvas.origin_is_clean());
+
+ p.resolve_native(&image_bitmap, can_gc);
+ },
+ ImageBitmapSource::ImageBitmap(ref bitmap) => {
+ // <https://html.spec.whatwg.org/multipage/#check-the-usability-of-the-image-argument>
+ if bitmap.is_detached() {
+ p.reject_error(Error::InvalidState, can_gc);
+ return p;
+ }
+
+ // If no ImageBitmap object can be constructed, then the promise is rejected instead.
+ let Some(snapshot) = bitmap.bitmap_data().clone() else {
+ p.reject_error(Error::InvalidState, can_gc);
+ return p;
+ };
+
+ let image_bitmap = ImageBitmap::new(self, snapshot, can_gc);
+ image_bitmap.set_origin_clean(bitmap.origin_is_clean());
+
+ p.resolve_native(&image_bitmap, can_gc);
},
ImageBitmapSource::OffscreenCanvas(ref canvas) => {
- // https://html.spec.whatwg.org/multipage/#check-the-usability-of-the-image-argument
- if !canvas.is_valid() {
+ // <https://html.spec.whatwg.org/multipage/#check-the-usability-of-the-image-argument>
+ if canvas.get_size().is_empty() {
p.reject_error(Error::InvalidState, can_gc);
return p;
}
- match canvas.get_image_data() {
- Some(snapshot) => {
- let image_bitmap = ImageBitmap::new(self, snapshot, can_gc);
- image_bitmap.set_origin_clean(canvas.origin_is_clean());
- p.resolve_native(&(image_bitmap), can_gc);
- },
- None => p.reject_error(Error::InvalidState, can_gc),
+ // If no ImageBitmap object can be constructed, then the promise is rejected instead.
+ let Some(snapshot) = canvas.get_image_data() else {
+ p.reject_error(Error::InvalidState, can_gc);
+ return p;
+ };
+
+ let image_bitmap = ImageBitmap::new(self, snapshot, can_gc);
+ image_bitmap.set_origin_clean(canvas.origin_is_clean());
+
+ p.resolve_native(&image_bitmap, can_gc);
+ },
+ ImageBitmapSource::Blob(_) => {
+ // TODO: implement support of Blob object as ImageBitmapSource
+ p.reject_error(Error::InvalidState, can_gc);
+ },
+ ImageBitmapSource::ImageData(ref image_data) => {
+ // <https://html.spec.whatwg.org/multipage/#the-imagebitmap-interface:imagedata-4>
+ if image_data.is_detached() {
+ p.reject_error(Error::InvalidState, can_gc);
+ return p;
}
- p
+
+ let alpha_mode = snapshot::AlphaMode::Transparent {
+ premultiplied: false,
+ };
+
+ let snapshot = Snapshot::from_shared_memory(
+ image_data.get_size().cast(),
+ snapshot::PixelFormat::RGBA,
+ alpha_mode,
+ image_data.to_shared_memory(),
+ );
+
+ let image_bitmap = ImageBitmap::new(self, snapshot, can_gc);
+
+ p.resolve_native(&image_bitmap, can_gc);
},
- _ => {
+ ImageBitmapSource::CSSStyleValue(_) => {
+ // TODO: CSSStyleValue is not part of ImageBitmapSource
+ // <https://html.spec.whatwg.org/multipage/#imagebitmapsource>
p.reject_error(Error::NotSupported, can_gc);
- p
},
}
+
+ // Step 7. Return promise.
+ p
}
pub(crate) fn fire_timer(&self, handle: TimerEventId, can_gc: CanGc) {
diff --git a/components/script/dom/htmlelement.rs b/components/script/dom/htmlelement.rs
index f41370386e9..f47a40d3cdb 100644
--- a/components/script/dom/htmlelement.rs
+++ b/components/script/dom/htmlelement.rs
@@ -437,7 +437,7 @@ impl HTMLElementMethods<crate::DomTypeHolder> for HTMLElement {
document.request_focus(None, FocusInitiator::Local, can_gc);
}
- // https://drafts.csswg.org/cssom-view/#dom-htmlelement-offsetparent
+ /// <https://drafts.csswg.org/cssom-view/#dom-htmlelement-offsetparent>
fn GetOffsetParent(&self, can_gc: CanGc) -> Option<DomRoot<Element>> {
if self.is::<HTMLBodyElement>() || self.is::<HTMLHtmlElement>() {
return None;
diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs
index 0d54d188e59..e483504cceb 100644
--- a/components/script/dom/htmlmediaelement.rs
+++ b/components/script/dom/htmlmediaelement.rs
@@ -520,6 +520,10 @@ impl HTMLMediaElement {
}
}
+ pub(crate) fn network_state(&self) -> NetworkState {
+ self.network_state.get()
+ }
+
pub(crate) fn get_ready_state(&self) -> ReadyState {
self.ready_state.get()
}
diff --git a/components/script/dom/htmlvideoelement.rs b/components/script/dom/htmlvideoelement.rs
index c5699014ee2..622e5079ee9 100644
--- a/components/script/dom/htmlvideoelement.rs
+++ b/components/script/dom/htmlvideoelement.rs
@@ -37,7 +37,7 @@ use crate::dom::bindings::str::DOMString;
use crate::dom::document::Document;
use crate::dom::element::{AttributeMutation, Element, LayoutElementHelpers};
use crate::dom::globalscope::GlobalScope;
-use crate::dom::htmlmediaelement::{HTMLMediaElement, ReadyState};
+use crate::dom::htmlmediaelement::{HTMLMediaElement, NetworkState, ReadyState};
use crate::dom::node::{Node, NodeTraits};
use crate::dom::performanceresourcetiming::InitiatorType;
use crate::dom::virtualmethods::VirtualMethods;
@@ -294,6 +294,10 @@ impl HTMLVideoElement {
pub(crate) fn origin_is_clean(&self) -> bool {
self.htmlmediaelement.origin_is_clean()
}
+
+ pub(crate) fn is_network_state_empty(&self) -> bool {
+ self.htmlmediaelement.network_state() == NetworkState::Empty
+ }
}
impl HTMLVideoElementMethods<crate::DomTypeHolder> for HTMLVideoElement {
diff --git a/components/script/dom/imagebitmap.rs b/components/script/dom/imagebitmap.rs
index cddd8cf1188..0a43bf4f176 100644
--- a/components/script/dom/imagebitmap.rs
+++ b/components/script/dom/imagebitmap.rs
@@ -68,7 +68,7 @@ impl ImageBitmap {
/// Return the value of the [`[[Detached]]`](https://html.spec.whatwg.org/multipage/#detached)
/// internal slot
- fn is_detached(&self) -> bool {
+ pub(crate) fn is_detached(&self) -> bool {
self.bitmap_data.borrow().is_none()
}
}
@@ -109,9 +109,9 @@ impl Serializable for ImageBitmap {
}
fn serialized_storage<'a>(
- reader: StructuredData<'a, '_>,
+ data: StructuredData<'a, '_>,
) -> &'a mut Option<HashMap<ImageBitmapId, Self::Data>> {
- match reader {
+ match data {
StructuredData::Reader(r) => &mut r.image_bitmaps,
StructuredData::Writer(w) => &mut w.image_bitmaps,
}
diff --git a/components/script/dom/imagedata.rs b/components/script/dom/imagedata.rs
index a834abdae78..907561cdda4 100644
--- a/components/script/dom/imagedata.rs
+++ b/components/script/dom/imagedata.rs
@@ -148,6 +148,11 @@ impl ImageData {
imagedata, global, proto, can_gc,
))
}
+
+ pub(crate) fn is_detached(&self) -> bool {
+ self.data.is_detached_buffer(GlobalScope::get_cx())
+ }
+
#[allow(unsafe_code)]
pub(crate) fn to_shared_memory(&self) -> IpcSharedMemory {
IpcSharedMemory::from_bytes(unsafe { self.as_slice() })
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index bf36242572f..6d4a0d2529e 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -1583,6 +1583,7 @@ pub(crate) unsafe fn from_untrusted_node_address(candidate: UntrustedNodeAddress
pub(crate) trait LayoutNodeHelpers<'dom> {
fn type_id_for_layout(self) -> NodeTypeId;
+ fn parent_node_ref(self) -> Option<LayoutDom<'dom, Node>>;
fn composed_parent_node_ref(self) -> Option<LayoutDom<'dom, Node>>;
fn first_child_ref(self) -> Option<LayoutDom<'dom, Node>>;
fn last_child_ref(self) -> Option<LayoutDom<'dom, Node>>;
@@ -1645,7 +1646,7 @@ pub(crate) trait LayoutNodeHelpers<'dom> {
impl<'dom> LayoutDom<'dom, Node> {
#[inline]
#[allow(unsafe_code)]
- fn parent_node_ref(self) -> Option<LayoutDom<'dom, Node>> {
+ pub(crate) fn parent_node_ref(self) -> Option<LayoutDom<'dom, Node>> {
unsafe { self.unsafe_get().parent_node.get_inner_as_layout() }
}
}
@@ -1662,6 +1663,12 @@ impl<'dom> LayoutNodeHelpers<'dom> for LayoutDom<'dom, Node> {
}
#[inline]
+ #[allow(unsafe_code)]
+ fn parent_node_ref(self) -> Option<LayoutDom<'dom, Node>> {
+ unsafe { self.unsafe_get().parent_node.get_inner_as_layout() }
+ }
+
+ #[inline]
fn composed_parent_node_ref(self) -> Option<LayoutDom<'dom, Node>> {
let parent = self.parent_node_ref();
if let Some(parent) = parent {
diff --git a/components/script/dom/offscreencanvas.rs b/components/script/dom/offscreencanvas.rs
index cbcffb40e3e..391c83f3a84 100644
--- a/components/script/dom/offscreencanvas.rs
+++ b/components/script/dom/offscreencanvas.rs
@@ -126,10 +126,6 @@ impl OffscreenCanvas {
Some(context)
}
- pub(crate) fn is_valid(&self) -> bool {
- self.Width() != 0 && self.Height() != 0
- }
-
pub(crate) fn placeholder(&self) -> Option<&HTMLCanvasElement> {
self.placeholder.as_deref()
}
diff --git a/components/script/dom/raredata.rs b/components/script/dom/raredata.rs
index 0c048956217..2c303d6874f 100644
--- a/components/script/dom/raredata.rs
+++ b/components/script/dom/raredata.rs
@@ -11,6 +11,7 @@ use crate::dom::bindings::root::{Dom, MutNullableDom};
use crate::dom::customelementregistry::{
CustomElementDefinition, CustomElementReaction, CustomElementState,
};
+use crate::dom::domtokenlist::DOMTokenList;
use crate::dom::elementinternals::ElementInternals;
use crate::dom::htmlslotelement::SlottableData;
use crate::dom::intersectionobserver::IntersectionObserverRegistration;
@@ -76,4 +77,10 @@ pub(crate) struct ElementRareData {
/// > which is initialized to an empty list. This list holds IntersectionObserverRegistration records, which have:
pub(crate) registered_intersection_observers: Vec<IntersectionObserverRegistration>,
pub(crate) cryptographic_nonce: String,
+
+ /// <https://drafts.csswg.org/css-shadow-parts/#element-forwarded-part-name-list>
+ pub(crate) forwarded_part_names: Vec<(String, String)>,
+
+ /// <https://drafts.csswg.org/css-shadow-parts/#dom-element-part>
+ pub(crate) part: MutNullableDom<DOMTokenList>,
}
diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs
index 9b8ee461979..aee785b0e12 100644
--- a/components/script/dom/webglrenderingcontext.rs
+++ b/components/script/dom/webglrenderingcontext.rs
@@ -575,6 +575,23 @@ impl WebGLRenderingContext {
pub(crate) fn get_image_pixels(&self, source: TexImageSource) -> Fallible<Option<TexPixels>> {
Ok(Some(match source {
+ TexImageSource::ImageBitmap(bitmap) => {
+ if !bitmap.origin_is_clean() {
+ return Err(Error::Security);
+ }
+ let Some(snapshot) = bitmap.bitmap_data().clone() else {
+ return Ok(None);
+ };
+
+ let snapshot = snapshot.as_ipc();
+ let size = snapshot.size().cast();
+ let format = match snapshot.format() {
+ snapshot::PixelFormat::RGBA => PixelFormat::RGBA8,
+ snapshot::PixelFormat::BGRA => PixelFormat::BGRA8,
+ };
+ let premultiply = snapshot.alpha_mode().is_premultiplied();
+ TexPixels::new(snapshot.to_ipc_shared_memory(), size, format, premultiply)
+ },
TexImageSource::ImageData(image_data) => TexPixels::new(
image_data.to_shared_memory(),
image_data.get_size(),
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index dcaa025c778..fca40987898 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -1214,7 +1214,7 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
self.as_global_scope().queue_function_as_microtask(callback);
}
- // https://html.spec.whatwg.org/multipage/#dom-createimagebitmap
+ /// <https://html.spec.whatwg.org/multipage/#dom-createimagebitmap>
fn CreateImageBitmap(
&self,
image: ImageBitmapSource,
@@ -1223,7 +1223,30 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
) -> Rc<Promise> {
let p = self
.as_global_scope()
- .create_image_bitmap(image, options, can_gc);
+ .create_image_bitmap(image, 0, 0, None, None, options, can_gc);
+ p
+ }
+
+ /// <https://html.spec.whatwg.org/multipage/#dom-createimagebitmap>
+ fn CreateImageBitmap_(
+ &self,
+ image: ImageBitmapSource,
+ sx: i32,
+ sy: i32,
+ sw: i32,
+ sh: i32,
+ options: &ImageBitmapOptions,
+ can_gc: CanGc,
+ ) -> Rc<Promise> {
+ let p = self.as_global_scope().create_image_bitmap(
+ image,
+ sx,
+ sy,
+ Some(sw),
+ Some(sh),
+ options,
+ can_gc,
+ );
p
}
diff --git a/components/script/dom/windowproxy.rs b/components/script/dom/windowproxy.rs
index a8decee24ed..648146ac2e9 100644
--- a/components/script/dom/windowproxy.rs
+++ b/components/script/dom/windowproxy.rs
@@ -466,26 +466,40 @@ impl WindowProxy {
features: DOMString,
can_gc: CanGc,
) -> Fallible<Option<DomRoot<WindowProxy>>> {
- // Step 4.
+ // Step 5. If target is the empty string, then set target to "_blank".
let non_empty_target = match target.as_ref() {
"" => DOMString::from("_blank"),
_ => target,
};
- // Step 5
+ // Step 6. Let tokenizedFeatures be the result of tokenizing features.
let tokenized_features = tokenize_open_features(features);
- // Step 7-9
+ // Step 7 - 8.
+ // If tokenizedFeatures["noreferrer"] exists, then set noreferrer to
+ // the result of parsing tokenizedFeatures["noreferrer"] as a boolean feature.
let noreferrer = parse_open_feature_boolean(&tokenized_features, "noreferrer");
+
+ // Step 9. Let noopener be the result of getting noopener for window
+ // open with sourceDocument, tokenizedFeatures, and urlRecord.
let noopener = if noreferrer {
true
} else {
parse_open_feature_boolean(&tokenized_features, "noopener")
};
- // Step 10, 11
+ // (TODO) Step 10. Remove tokenizedFeatures["noopener"] and tokenizedFeatures["noreferrer"].
+
+ // (TODO) Step 11. Let referrerPolicy be the empty string.
+ // (TODO) Step 12. If noreferrer is true, then set referrerPolicy to "no-referrer".
+
+ // Step 13 - 14
+ // Let targetNavigable and windowType be the result of applying the rules for
+ // choosing a navigable given target, sourceDocument's node navigable, and noopener.
+ // If targetNavigable is null, then return null.
let (chosen, new) = match self.choose_browsing_context(non_empty_target, noopener) {
(Some(chosen), new) => (chosen, new),
(None, _) => return Ok(None),
};
- // TODO Step 12, set up browsing context features.
+ // TODO Step 15.2, Set up browsing context features for targetNavigable's
+ // active browsing context given tokenizedFeatures.
let target_document = match chosen.document() {
Some(target_document) => target_document,
None => return Ok(None),
@@ -496,7 +510,7 @@ impl WindowProxy {
false
};
let target_window = target_document.window();
- // Step 13, and 14.4, will have happened elsewhere,
+ // Step 15.3 and 15.4 will have happened elsewhere,
// since we've created a new browsing context and loaded it with about:blank.
if !url.is_empty() {
let existing_document = self
@@ -504,18 +518,18 @@ impl WindowProxy {
.get()
.and_then(ScriptThread::find_document)
.unwrap();
- // Step 14.1
let url = match existing_document.url().join(&url) {
Ok(url) => url,
Err(_) => return Err(Error::Syntax),
};
- // Step 14.3
let referrer = if noreferrer {
Referrer::NoReferrer
} else {
target_window.as_global_scope().get_referrer()
};
- // Step 14.5
+ // Step 15.5 Otherwise, navigate targetNavigable to urlRecord using sourceDocument,
+ // with referrerPolicy set to referrerPolicy and exceptionsEnabled set to true.
+ // FIXME: referrerPolicy may not be used properly here. exceptionsEnabled not used.
let referrer_policy = target_document.get_referrer_policy();
let pipeline_id = target_window.pipeline_id();
let secure = target_window.as_global_scope().is_secure_context();
@@ -534,14 +548,13 @@ impl WindowProxy {
} else {
NavigationHistoryBehavior::Push
};
-
target_window.load_url(history_handling, false, load_data, can_gc);
}
+ // Step 17 (Dis-owning has been done in create_auxiliary_browsing_context).
if noopener {
- // Step 15 (Dis-owning has been done in create_auxiliary_browsing_context).
return Ok(None);
}
- // Step 17.
+ // Step 18
Ok(target_document.browsing_context())
}
diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs
index fa94dcc1d04..7912e90cdcf 100644
--- a/components/script/dom/workerglobalscope.rs
+++ b/components/script/dom/workerglobalscope.rs
@@ -446,7 +446,7 @@ impl WorkerGlobalScopeMethods<crate::DomTypeHolder> for WorkerGlobalScope {
.queue_function_as_microtask(callback);
}
- // https://html.spec.whatwg.org/multipage/#dom-createimagebitmap
+ /// <https://html.spec.whatwg.org/multipage/#dom-createimagebitmap>
fn CreateImageBitmap(
&self,
image: ImageBitmapSource,
@@ -455,7 +455,30 @@ impl WorkerGlobalScopeMethods<crate::DomTypeHolder> for WorkerGlobalScope {
) -> Rc<Promise> {
let p = self
.upcast::<GlobalScope>()
- .create_image_bitmap(image, options, can_gc);
+ .create_image_bitmap(image, 0, 0, None, None, options, can_gc);
+ p
+ }
+
+ /// <https://html.spec.whatwg.org/multipage/#dom-createimagebitmap>
+ fn CreateImageBitmap_(
+ &self,
+ image: ImageBitmapSource,
+ sx: i32,
+ sy: i32,
+ sw: i32,
+ sh: i32,
+ options: &ImageBitmapOptions,
+ can_gc: CanGc,
+ ) -> Rc<Promise> {
+ let p = self.upcast::<GlobalScope>().create_image_bitmap(
+ image,
+ sx,
+ sy,
+ Some(sw),
+ Some(sh),
+ options,
+ can_gc,
+ );
p
}