diff options
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/element.rs | 47 | ||||
-rw-r--r-- | components/script/dom/globalscope.rs | 196 | ||||
-rw-r--r-- | components/script/dom/htmlelement.rs | 2 | ||||
-rw-r--r-- | components/script/dom/htmlmediaelement.rs | 4 | ||||
-rw-r--r-- | components/script/dom/htmlvideoelement.rs | 6 | ||||
-rw-r--r-- | components/script/dom/imagebitmap.rs | 6 | ||||
-rw-r--r-- | components/script/dom/imagedata.rs | 5 | ||||
-rw-r--r-- | components/script/dom/node.rs | 9 | ||||
-rw-r--r-- | components/script/dom/offscreencanvas.rs | 4 | ||||
-rw-r--r-- | components/script/dom/raredata.rs | 7 | ||||
-rw-r--r-- | components/script/dom/webglrenderingcontext.rs | 17 | ||||
-rw-r--r-- | components/script/dom/window.rs | 27 | ||||
-rw-r--r-- | components/script/dom/windowproxy.rs | 37 | ||||
-rw-r--r-- | components/script/dom/workerglobalscope.rs | 27 |
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 } |