aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
Diffstat (limited to 'components/script')
-rw-r--r--components/script/Cargo.toml1
-rw-r--r--components/script/canvas_context.rs11
-rw-r--r--components/script/canvas_state.rs64
-rw-r--r--components/script/dom/bindings/error.rs1
-rw-r--r--components/script/dom/bindings/serializable.rs14
-rw-r--r--components/script/dom/bindings/structuredclone.rs78
-rw-r--r--components/script/dom/bindings/transferable.rs9
-rw-r--r--components/script/dom/blob.rs14
-rw-r--r--components/script/dom/canvasrenderingcontext2d.rs16
-rw-r--r--components/script/dom/cssstylesheet.rs30
-rw-r--r--components/script/dom/domexception.rs22
-rw-r--r--components/script/dom/dompoint.rs16
-rw-r--r--components/script/dom/dompointreadonly.rs16
-rw-r--r--components/script/dom/globalscope.rs19
-rw-r--r--components/script/dom/htmlcanvaselement.rs78
-rw-r--r--components/script/dom/messageport.rs12
-rw-r--r--components/script/dom/node.rs1
-rw-r--r--components/script/dom/offscreencanvas.rs27
-rw-r--r--components/script/dom/offscreencanvasrenderingcontext2d.rs6
-rw-r--r--components/script/dom/readablestream.rs12
-rw-r--r--components/script/dom/webgl2renderingcontext.rs11
-rw-r--r--components/script/dom/webglrenderingcontext.rs36
-rw-r--r--components/script/dom/webgpu/gpucanvascontext.rs9
-rw-r--r--components/script/dom/window.rs5
-rw-r--r--components/script/dom/writablestream.rs12
-rw-r--r--components/script/layout_image.rs5
-rw-r--r--components/script/script_thread.rs5
27 files changed, 255 insertions, 275 deletions
diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml
index 37e80d0e748..1aa821cdbd3 100644
--- a/components/script/Cargo.toml
+++ b/components/script/Cargo.toml
@@ -114,6 +114,7 @@ servo_config = { path = "../config" }
servo_geometry = { path = "../geometry" }
servo_rand = { path = "../rand" }
servo_url = { path = "../url" }
+snapshot = { workspace = true }
smallvec = { workspace = true, features = ["union"] }
strum = { workspace = true }
strum_macros = { workspace = true }
diff --git a/components/script/canvas_context.rs b/components/script/canvas_context.rs
index 8bf188a5aa9..d49d31997e1 100644
--- a/components/script/canvas_context.rs
+++ b/components/script/canvas_context.rs
@@ -5,8 +5,8 @@
//! Common interfaces for Canvas Contexts
use euclid::default::Size2D;
-use ipc_channel::ipc::IpcSharedMemory;
use script_layout_interface::{HTMLCanvasData, HTMLCanvasDataSource};
+use snapshot::Snapshot;
use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas;
use crate::dom::bindings::inheritance::Castable;
@@ -30,11 +30,10 @@ pub(crate) trait CanvasContext {
fn resize(&self);
- fn get_image_data_as_shared_memory(&self) -> Option<IpcSharedMemory>;
-
- fn get_image_data(&self) -> Option<Vec<u8>> {
- self.get_image_data_as_shared_memory().map(|sm| sm.to_vec())
- }
+ /// Returns none if area of canvas is zero.
+ ///
+ /// In case of other errors it returns cleared snapshot
+ fn get_image_data(&self) -> Option<Snapshot>;
fn origin_is_clean(&self) -> bool {
true
diff --git a/components/script/canvas_state.rs b/components/script/canvas_state.rs
index aea3012b365..408c94c124a 100644
--- a/components/script/canvas_state.rs
+++ b/components/script/canvas_state.rs
@@ -17,7 +17,7 @@ use cssparser::color::clamp_unit_f32;
use cssparser::{Parser, ParserInput};
use euclid::default::{Point2D, Rect, Size2D, Transform2D};
use euclid::vec2;
-use ipc_channel::ipc::{self, IpcSender, IpcSharedMemory};
+use ipc_channel::ipc::{self, IpcSender};
use net_traits::image_cache::{ImageCache, ImageResponse};
use net_traits::request::CorsSettings;
use pixels::PixelFormat;
@@ -298,7 +298,7 @@ impl CanvasState {
&self,
url: ServoUrl,
cors_setting: Option<CorsSettings>,
- ) -> Option<(IpcSharedMemory, Size2D<u32>)> {
+ ) -> Option<snapshot::Snapshot> {
let img = match self.request_image_from_cache(url, cors_setting) {
ImageResponse::Loaded(img, _) => img,
ImageResponse::PlaceholderLoaded(_, _) |
@@ -308,13 +308,22 @@ impl CanvasState {
},
};
- let image_size = Size2D::new(img.width, img.height);
- let image_data = match img.format {
- PixelFormat::BGRA8 => img.bytes(),
+ let size = Size2D::new(img.width, img.height);
+ let format = match img.format {
+ PixelFormat::BGRA8 => snapshot::PixelFormat::BGRA,
+ PixelFormat::RGBA8 => snapshot::PixelFormat::RGBA,
pixel_format => unimplemented!("unsupported pixel format ({:?})", pixel_format),
};
+ let alpha_mode = snapshot::AlphaMode::Transparent {
+ premultiplied: false,
+ };
- Some((image_data, image_size))
+ Some(snapshot::Snapshot::from_shared_memory(
+ size.cast(),
+ format,
+ alpha_mode,
+ img.bytes(),
+ ))
}
fn request_image_from_cache(
@@ -341,13 +350,16 @@ impl CanvasState {
assert!(Rect::from_size(canvas_size).contains_rect(&rect));
- let (sender, receiver) = ipc::bytes_channel().unwrap();
+ let (sender, receiver) = ipc::channel().unwrap();
self.send_canvas_2d_msg(Canvas2dMsg::GetImageData(rect, canvas_size, sender));
- let mut pixels = receiver.recv().unwrap().to_vec();
-
- pixels::unmultiply_inplace::<true>(&mut pixels);
-
- pixels
+ let mut snapshot = receiver.recv().unwrap().to_owned();
+ snapshot.transform(
+ snapshot::AlphaMode::Transparent {
+ premultiplied: false,
+ },
+ snapshot::PixelFormat::RGBA,
+ );
+ snapshot.to_vec()
}
///
@@ -594,10 +606,10 @@ impl CanvasState {
dh: Option<f64>,
) -> ErrorResult {
debug!("Fetching image {}.", url);
- let (image_data, image_size) = self
+ let snapshot = self
.fetch_image_data(url, cors_setting)
.ok_or(Error::InvalidState)?;
- let image_size = image_size.to_f64();
+ let image_size = snapshot.size().to_f64();
let dw = dw.unwrap_or(image_size.width);
let dh = dh.unwrap_or(image_size.height);
@@ -614,8 +626,7 @@ impl CanvasState {
let smoothing_enabled = self.state.borrow().image_smoothing_enabled;
self.send_canvas_2d_msg(Canvas2dMsg::DrawImage(
- image_data,
- image_size,
+ snapshot.as_ipc(),
dest_rect,
source_rect,
smoothing_enabled,
@@ -929,7 +940,7 @@ impl CanvasState {
mut repetition: DOMString,
can_gc: CanGc,
) -> Fallible<Option<DomRoot<CanvasPattern>>> {
- let (image_data, image_size) = match image {
+ let snapshot = match image {
CanvasImageSource::HTMLImageElement(ref image) => {
// https://html.spec.whatwg.org/multipage/#check-the-usability-of-the-image-argument
if !image.is_usable()? {
@@ -941,27 +952,17 @@ impl CanvasState {
.and_then(|url| {
self.fetch_image_data(url, cors_setting_for_element(image.upcast()))
})
- .map(|data| (data.0.to_vec(), data.1))
.ok_or(Error::InvalidState)?
},
CanvasImageSource::HTMLCanvasElement(ref canvas) => {
- let (data, size) = canvas.fetch_all_data().ok_or(Error::InvalidState)?;
- let data = data
- .map(|data| data.to_vec())
- .unwrap_or_else(|| vec![0; size.area() as usize * 4]);
- (data, size)
+ canvas.get_image_data().ok_or(Error::InvalidState)?
},
CanvasImageSource::OffscreenCanvas(ref canvas) => {
- let (data, size) = canvas.fetch_all_data().ok_or(Error::InvalidState)?;
- let data = data
- .map(|data| data.to_vec())
- .unwrap_or_else(|| vec![0; size.area() as usize * 4]);
- (data, size)
+ canvas.get_image_data().ok_or(Error::InvalidState)?
},
CanvasImageSource::CSSStyleValue(ref value) => value
.get_url(self.base_url.clone())
.and_then(|url| self.fetch_image_data(url, None))
- .map(|data| (data.0.to_vec(), data.1))
.ok_or(Error::InvalidState)?,
};
@@ -970,10 +971,11 @@ impl CanvasState {
}
if let Ok(rep) = RepetitionStyle::from_str(&repetition) {
+ let size = snapshot.size();
Ok(Some(CanvasPattern::new(
global,
- image_data,
- image_size,
+ snapshot.to_vec(),
+ size.cast(),
rep,
self.is_origin_clean(image),
can_gc,
diff --git a/components/script/dom/bindings/error.rs b/components/script/dom/bindings/error.rs
index b0fd301df6a..f5bd03cd8d7 100644
--- a/components/script/dom/bindings/error.rs
+++ b/components/script/dom/bindings/error.rs
@@ -93,6 +93,7 @@ pub(crate) fn throw_dom_exception(
Error::NotReadable => DOMErrorName::NotReadableError,
Error::Data => DOMErrorName::DataError,
Error::Operation => DOMErrorName::OperationError,
+ Error::NotAllowed => DOMErrorName::NotAllowedError,
Error::Type(message) => unsafe {
assert!(!JS_IsExceptionPending(*cx));
throw_type_error(*cx, &message);
diff --git a/components/script/dom/bindings/serializable.rs b/components/script/dom/bindings/serializable.rs
index 4aa1a94a0a4..d0e851b4799 100644
--- a/components/script/dom/bindings/serializable.rs
+++ b/components/script/dom/bindings/serializable.rs
@@ -11,7 +11,7 @@ use base::id::{Index, NamespaceIndex, PipelineNamespaceId};
use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::root::DomRoot;
-use crate::dom::bindings::structuredclone::{StructuredData, StructuredDataReader};
+use crate::dom::bindings::structuredclone::StructuredData;
use crate::dom::globalscope::GlobalScope;
use crate::script_runtime::CanGc;
@@ -65,13 +65,7 @@ where
/// Returns the field of [StructuredDataReader]/[StructuredDataWriter] that
/// should be used to read/store serialized instances of this type.
- fn serialized_storage(
- data: StructuredData<'_>,
- ) -> &mut Option<HashMap<NamespaceIndex<Self::Index>, Self::Data>>;
-
- /// Returns the field of [StructuredDataReader] that should be used to store
- /// deserialized instances of this type.
- fn deserialized_storage(
- reader: &mut StructuredDataReader,
- ) -> &mut Option<HashMap<StorageKey, DomRoot<Self>>>;
+ fn serialized_storage<'a>(
+ data: StructuredData<'a, '_>,
+ ) -> &'a mut Option<HashMap<NamespaceIndex<Self::Index>, Self::Data>>;
}
diff --git a/components/script/dom/bindings/structuredclone.rs b/components/script/dom/bindings/structuredclone.rs
index 915a4951bb5..c9a49ba00c9 100644
--- a/components/script/dom/bindings/structuredclone.rs
+++ b/components/script/dom/bindings/structuredclone.rs
@@ -16,13 +16,14 @@ use constellation_traits::{
BlobImpl, DomException, DomPoint, MessagePortImpl, Serializable as SerializableInterface,
StructuredSerializedData, Transferrable as TransferrableInterface,
};
+use js::gc::RootedVec;
use js::glue::{
CopyJSStructuredCloneData, DeleteJSAutoStructuredCloneBuffer, GetLengthOfJSStructuredCloneData,
NewJSAutoStructuredCloneBuffer, WriteBytesToJSStructuredCloneData,
};
use js::jsapi::{
- CloneDataPolicy, HandleObject as RawHandleObject, JS_ClearPendingException, JS_ReadUint32Pair,
- JS_STRUCTURED_CLONE_VERSION, JS_WriteUint32Pair, JSContext, JSObject,
+ CloneDataPolicy, HandleObject as RawHandleObject, Heap, JS_ClearPendingException,
+ JS_ReadUint32Pair, JS_STRUCTURED_CLONE_VERSION, JS_WriteUint32Pair, JSContext, JSObject,
JSStructuredCloneCallbacks, JSStructuredCloneReader, JSStructuredCloneWriter,
MutableHandleObject as RawMutableHandleObject, StructuredCloneScope, TransferableOwnership,
};
@@ -93,7 +94,7 @@ fn reader_for_type(
) -> unsafe fn(
&GlobalScope,
*mut JSStructuredCloneReader,
- &mut StructuredDataReader,
+ &mut StructuredDataReader<'_>,
CanGc,
) -> *mut JSObject {
match val {
@@ -107,7 +108,7 @@ fn reader_for_type(
unsafe fn read_object<T: Serializable>(
owner: &GlobalScope,
r: *mut JSStructuredCloneReader,
- sc_reader: &mut StructuredDataReader,
+ sc_reader: &mut StructuredDataReader<'_>,
can_gc: CanGc,
) -> *mut JSObject {
let mut name_space: u32 = 0;
@@ -136,9 +137,8 @@ unsafe fn read_object<T: Serializable>(
}
if let Ok(obj) = T::deserialize(owner, serialized, can_gc) {
- let destination = T::deserialized_storage(sc_reader).get_or_insert_with(HashMap::new);
let reflector = obj.reflector().get_jsobject().get();
- destination.insert(storage_key, obj);
+ sc_reader.roots.push(Heap::boxed(reflector));
return reflector;
}
warn!("Reading structured data failed in {:?}.", owner.get_url());
@@ -191,7 +191,7 @@ unsafe extern "C" fn read_callback(
"tag should be higher than StructuredCloneTags::Min"
);
- let sc_reader = &mut *(closure as *mut StructuredDataReader);
+ let sc_reader = &mut *(closure as *mut StructuredDataReader<'_>);
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
let global = GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof));
for serializable in SerializableInterface::iter() {
@@ -259,7 +259,8 @@ unsafe extern "C" fn write_callback(
fn receiver_for_type(
val: TransferrableInterface,
-) -> fn(&GlobalScope, &mut StructuredDataReader, u64, RawMutableHandleObject) -> Result<(), ()> {
+) -> fn(&GlobalScope, &mut StructuredDataReader<'_>, u64, RawMutableHandleObject) -> Result<(), ()>
+{
match val {
TransferrableInterface::MessagePort => receive_object::<MessagePort>,
TransferrableInterface::ReadableStream => receive_object::<ReadableStream>,
@@ -269,7 +270,7 @@ fn receiver_for_type(
fn receive_object<T: Transferable>(
owner: &GlobalScope,
- sc_reader: &mut StructuredDataReader,
+ sc_reader: &mut StructuredDataReader<'_>,
extra_data: u64,
return_object: RawMutableHandleObject,
) -> Result<(), ()> {
@@ -305,13 +306,12 @@ fn receive_object<T: Transferable>(
);
};
- if let Ok(received) = T::transfer_receive(owner, id, serialized) {
- return_object.set(received.reflector().rootable().get());
- let storage = T::deserialized_storage(sc_reader).get_or_insert_with(Vec::new);
- storage.push(received);
- return Ok(());
- }
- Err(())
+ let Ok(received) = T::transfer_receive(owner, id, serialized) else {
+ return Err(());
+ };
+ return_object.set(received.reflector().rootable().get());
+ sc_reader.roots.push(Heap::boxed(return_object.get()));
+ Ok(())
}
unsafe extern "C" fn read_transfer_callback(
@@ -324,7 +324,7 @@ unsafe extern "C" fn read_transfer_callback(
closure: *mut raw::c_void,
return_object: RawMutableHandleObject,
) -> bool {
- let sc_reader = &mut *(closure as *mut StructuredDataReader);
+ let sc_reader = &mut *(closure as *mut StructuredDataReader<'_>);
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
let owner = GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof));
@@ -489,8 +489,8 @@ static STRUCTURED_CLONE_CALLBACKS: JSStructuredCloneCallbacks = JSStructuredClon
sabCloned: Some(sab_cloned_callback),
};
-pub(crate) enum StructuredData<'a> {
- Reader(&'a mut StructuredDataReader),
+pub(crate) enum StructuredData<'a, 'b> {
+ Reader(&'a mut StructuredDataReader<'b>),
Writer(&'a mut StructuredDataWriter),
}
@@ -503,19 +503,11 @@ pub(crate) struct DOMErrorRecord {
/// Reader and writer structs for results from, and inputs to, structured-data read/write operations.
/// <https://html.spec.whatwg.org/multipage/#safe-passing-of-structured-data>
#[repr(C)]
-pub(crate) struct StructuredDataReader {
+pub(crate) struct StructuredDataReader<'a> {
/// A struct of error message.
- pub(crate) errors: DOMErrorRecord,
- /// A map of deserialized blobs, stored temporarily here to keep them rooted.
- pub(crate) blobs: Option<HashMap<StorageKey, DomRoot<Blob>>>,
- /// A map of deserialized points, stored temporarily here to keep them rooted.
- pub(crate) points_read_only: Option<HashMap<StorageKey, DomRoot<DOMPointReadOnly>>>,
- pub(crate) dom_points: Option<HashMap<StorageKey, DomRoot<DOMPoint>>>,
- /// A map of deserialized exceptions, stored temporarily here to keep them rooted.
- pub(crate) dom_exceptions: Option<HashMap<StorageKey, DomRoot<DOMException>>>,
- /// A vec of transfer-received DOM ports,
- /// to be made available to script through a message event.
- pub(crate) message_ports: Option<Vec<DomRoot<MessagePort>>>,
+ errors: DOMErrorRecord,
+ /// Rooted copies of every deserialized object to ensure they are not garbage collected.
+ roots: RootedVec<'a, Box<Heap<*mut JSObject>>>,
/// A map of port implementations,
/// used as part of the "transfer-receiving" steps of ports,
/// to produce the DOM ports stored in `message_ports` above.
@@ -528,12 +520,6 @@ pub(crate) struct StructuredDataReader {
pub(crate) points: Option<HashMap<DomPointId, DomPoint>>,
/// A map of serialized exceptions.
pub(crate) exceptions: Option<HashMap<DomExceptionId, DomException>>,
-
- /// <https://streams.spec.whatwg.org/#rs-transfer>
- pub(crate) readable_streams: Option<Vec<DomRoot<ReadableStream>>>,
-
- /// <https://streams.spec.whatwg.org/#ws-transfer>
- pub(crate) writable_streams: Option<Vec<DomRoot<WritableStream>>>,
}
/// A data holder for transferred and serialized objects.
@@ -618,19 +604,14 @@ pub(crate) fn read(
) -> Fallible<Vec<DomRoot<MessagePort>>> {
let cx = GlobalScope::get_cx();
let _ac = enter_realm(global);
+ rooted_vec!(let mut roots);
let mut sc_reader = StructuredDataReader {
- blobs: None,
- message_ports: None,
- points_read_only: None,
- dom_points: None,
- dom_exceptions: None,
+ roots,
port_impls: data.ports.take(),
blob_impls: data.blobs.take(),
points: data.points.take(),
exceptions: data.exceptions.take(),
errors: DOMErrorRecord { message: None },
- readable_streams: None,
- writable_streams: None,
};
let sc_reader_ptr = &mut sc_reader as *mut _;
unsafe {
@@ -666,8 +647,15 @@ pub(crate) fn read(
DeleteJSAutoStructuredCloneBuffer(scbuf);
+ let mut message_ports = vec![];
+ for reflector in sc_reader.roots.iter() {
+ let Ok(message_port) = root_from_object::<MessagePort>(reflector.get(), *cx) else {
+ continue;
+ };
+ message_ports.push(message_port);
+ }
// Any transfer-received port-impls should have been taken out.
assert!(sc_reader.port_impls.is_none());
- Ok(sc_reader.message_ports.take().unwrap_or_default())
+ Ok(message_ports)
}
}
diff --git a/components/script/dom/bindings/transferable.rs b/components/script/dom/bindings/transferable.rs
index b720c05ae37..e6b2f000f3a 100644
--- a/components/script/dom/bindings/transferable.rs
+++ b/components/script/dom/bindings/transferable.rs
@@ -12,7 +12,7 @@ use base::id::NamespaceIndex;
use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::root::DomRoot;
-use crate::dom::bindings::structuredclone::{StructuredData, StructuredDataReader};
+use crate::dom::bindings::structuredclone::StructuredData;
use crate::dom::globalscope::GlobalScope;
pub(crate) trait Transferable: DomObject
where
@@ -32,8 +32,7 @@ where
serialized: Self::Data,
) -> Result<DomRoot<Self>, ()>;
- fn serialized_storage(
- data: StructuredData<'_>,
- ) -> &mut Option<HashMap<NamespaceIndex<Self::Index>, Self::Data>>;
- fn deserialized_storage(reader: &mut StructuredDataReader) -> &mut Option<Vec<DomRoot<Self>>>;
+ fn serialized_storage<'a>(
+ data: StructuredData<'a, '_>,
+ ) -> &'a mut Option<HashMap<NamespaceIndex<Self::Index>, Self::Data>>;
}
diff --git a/components/script/dom/blob.rs b/components/script/dom/blob.rs
index df2afafd698..27aa382c3fc 100644
--- a/components/script/dom/blob.rs
+++ b/components/script/dom/blob.rs
@@ -24,9 +24,9 @@ use crate::dom::bindings::codegen::UnionTypes::ArrayBufferOrArrayBufferViewOrBlo
use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object_with_proto};
use crate::dom::bindings::root::DomRoot;
-use crate::dom::bindings::serializable::{Serializable, StorageKey};
+use crate::dom::bindings::serializable::Serializable;
use crate::dom::bindings::str::DOMString;
-use crate::dom::bindings::structuredclone::{StructuredData, StructuredDataReader};
+use crate::dom::bindings::structuredclone::StructuredData;
use crate::dom::globalscope::GlobalScope;
use crate::dom::promise::Promise;
use crate::dom::readablestream::ReadableStream;
@@ -119,18 +119,14 @@ impl Serializable for Blob {
Ok(deserialized_blob)
}
- fn serialized_storage(reader: StructuredData<'_>) -> &mut Option<HashMap<BlobId, Self::Data>> {
+ fn serialized_storage<'a>(
+ reader: StructuredData<'a, '_>,
+ ) -> &'a mut Option<HashMap<BlobId, Self::Data>> {
match reader {
StructuredData::Reader(r) => &mut r.blob_impls,
StructuredData::Writer(w) => &mut w.blobs,
}
}
-
- fn deserialized_storage(
- data: &mut StructuredDataReader,
- ) -> &mut Option<HashMap<StorageKey, DomRoot<Self>>> {
- &mut data.blobs
- }
}
/// Extract bytes from BlobParts, used by Blob and File constructor
diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs
index f6bf432de69..73052e6906e 100644
--- a/components/script/dom/canvasrenderingcontext2d.rs
+++ b/components/script/dom/canvasrenderingcontext2d.rs
@@ -5,11 +5,11 @@
use canvas_traits::canvas::{Canvas2dMsg, CanvasId, CanvasMsg, FromScriptMsg};
use dom_struct::dom_struct;
use euclid::default::{Point2D, Rect, Size2D};
-use ipc_channel::ipc::IpcSharedMemory;
use profile_traits::ipc;
use script_bindings::inheritance::Castable;
use script_layout_interface::HTMLCanvasDataSource;
use servo_url::ServoUrl;
+use snapshot::Snapshot;
use crate::canvas_context::{CanvasContext, CanvasHelpers, LayoutCanvasRenderingContextHelpers};
use crate::canvas_state::CanvasState;
@@ -142,16 +142,18 @@ impl CanvasContext for CanvasRenderingContext2D {
self.set_bitmap_dimensions(self.size().cast())
}
- fn get_image_data_as_shared_memory(&self) -> Option<IpcSharedMemory> {
+ fn get_image_data(&self) -> Option<Snapshot> {
+ let size = self.size();
+
+ if size.is_empty() {
+ return None;
+ }
+
let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap();
let msg = CanvasMsg::FromScript(FromScriptMsg::SendPixels(sender), self.get_canvas_id());
self.canvas_state.get_ipc_renderer().send(msg).unwrap();
- Some(receiver.recv().unwrap())
- }
-
- fn get_image_data(&self) -> Option<Vec<u8>> {
- Some(self.get_rect(Rect::from_size(self.size().cast())))
+ Some(receiver.recv().unwrap().to_owned())
}
fn origin_is_clean(&self) -> bool {
diff --git a/components/script/dom/cssstylesheet.rs b/components/script/dom/cssstylesheet.rs
index 421e8f45523..a367c9943de 100644
--- a/components/script/dom/cssstylesheet.rs
+++ b/components/script/dom/cssstylesheet.rs
@@ -24,7 +24,7 @@ use crate::dom::bindings::reflector::{
DomGlobal, reflect_dom_object, reflect_dom_object_with_proto,
};
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
-use crate::dom::bindings::str::DOMString;
+use crate::dom::bindings::str::{DOMString, USVString};
use crate::dom::cssrulelist::{CSSRuleList, RulesSource};
use crate::dom::element::Element;
use crate::dom::medialist::MediaList;
@@ -290,4 +290,32 @@ impl CSSStyleSheetMethods<crate::DomTypeHolder> for CSSStyleSheet {
// > 8. Return -1.
Ok(-1)
}
+
+ /// <https://drafts.csswg.org/cssom/#synchronously-replace-the-rules-of-a-cssstylesheet>
+ fn ReplaceSync(&self, text: USVString) -> Result<(), Error> {
+ // Step 1. If the constructed flag is not set throw a NotAllowedError
+ if !self.is_constructed {
+ return Err(Error::NotAllowed);
+ }
+
+ // Step 2. Let rules be the result of running parse a stylesheet’s contents from text.
+ let global = self.global();
+ let window = global.as_window();
+
+ StyleStyleSheet::update_from_str(
+ &self.style_stylesheet,
+ &text,
+ UrlExtraData(window.get_url().get_arc()),
+ None,
+ window.css_error_reporter(),
+ AllowImportRules::No, // Step 3.If rules contains one or more @import rules, remove those rules from rules.
+ );
+
+ // Step 4. Set sheet’s CSS rules to rules.
+ // We reset our rule list, which will be initialized properly
+ // at the next getter access.
+ self.rulelist.set(None);
+
+ Ok(())
+ }
}
diff --git a/components/script/dom/domexception.rs b/components/script/dom/domexception.rs
index e63c3ff1f53..fbb807b7a95 100644
--- a/components/script/dom/domexception.rs
+++ b/components/script/dom/domexception.rs
@@ -17,9 +17,9 @@ use crate::dom::bindings::reflector::{
Reflector, reflect_dom_object, reflect_dom_object_with_proto,
};
use crate::dom::bindings::root::DomRoot;
-use crate::dom::bindings::serializable::{Serializable, StorageKey};
+use crate::dom::bindings::serializable::Serializable;
use crate::dom::bindings::str::DOMString;
-use crate::dom::bindings::structuredclone::{StructuredData, StructuredDataReader};
+use crate::dom::bindings::structuredclone::StructuredData;
use crate::dom::globalscope::GlobalScope;
use crate::script_runtime::CanGc;
@@ -53,6 +53,7 @@ pub(crate) enum DOMErrorName {
NotReadableError,
DataError,
OperationError,
+ NotAllowedError,
}
impl DOMErrorName {
@@ -84,6 +85,7 @@ impl DOMErrorName {
"NotReadableError" => Some(DOMErrorName::NotReadableError),
"DataError" => Some(DOMErrorName::DataError),
"OperationError" => Some(DOMErrorName::OperationError),
+ "NotAllowedError" => Some(DOMErrorName::NotAllowedError),
_ => None,
}
}
@@ -135,6 +137,10 @@ impl DOMException {
DOMErrorName::OperationError => {
"The operation failed for an operation-specific reason."
},
+ DOMErrorName::NotAllowedError => {
+ r#"The request is not allowed by the user agent or the platform in the current context,
+ possibly because the user denied permission."#
+ },
};
(
@@ -252,18 +258,12 @@ impl Serializable for DOMException {
))
}
- fn serialized_storage(
- data: StructuredData<'_>,
- ) -> &mut Option<HashMap<DomExceptionId, Self::Data>> {
+ fn serialized_storage<'a>(
+ data: StructuredData<'a, '_>,
+ ) -> &'a mut Option<HashMap<DomExceptionId, Self::Data>> {
match data {
StructuredData::Reader(reader) => &mut reader.exceptions,
StructuredData::Writer(writer) => &mut writer.exceptions,
}
}
-
- fn deserialized_storage(
- reader: &mut StructuredDataReader,
- ) -> &mut Option<HashMap<StorageKey, DomRoot<Self>>> {
- &mut reader.dom_exceptions
- }
}
diff --git a/components/script/dom/dompoint.rs b/components/script/dom/dompoint.rs
index 006abb50def..5e848c43c47 100644
--- a/components/script/dom/dompoint.rs
+++ b/components/script/dom/dompoint.rs
@@ -14,8 +14,8 @@ use crate::dom::bindings::codegen::Bindings::DOMPointReadOnlyBinding::DOMPointRe
use crate::dom::bindings::error::Fallible;
use crate::dom::bindings::reflector::reflect_dom_object_with_proto;
use crate::dom::bindings::root::DomRoot;
-use crate::dom::bindings::serializable::{Serializable, StorageKey};
-use crate::dom::bindings::structuredclone::{StructuredData, StructuredDataReader};
+use crate::dom::bindings::serializable::Serializable;
+use crate::dom::bindings::structuredclone::StructuredData;
use crate::dom::dompointreadonly::{DOMPointReadOnly, DOMPointWriteMethods};
use crate::dom::globalscope::GlobalScope;
use crate::script_runtime::CanGc;
@@ -163,18 +163,12 @@ impl Serializable for DOMPoint {
))
}
- fn serialized_storage(
- data: StructuredData<'_>,
- ) -> &mut Option<HashMap<DomPointId, Self::Data>> {
+ fn serialized_storage<'a>(
+ data: StructuredData<'a, '_>,
+ ) -> &'a mut Option<HashMap<DomPointId, Self::Data>> {
match data {
StructuredData::Reader(reader) => &mut reader.points,
StructuredData::Writer(writer) => &mut writer.points,
}
}
-
- fn deserialized_storage(
- reader: &mut StructuredDataReader,
- ) -> &mut Option<HashMap<StorageKey, DomRoot<Self>>> {
- &mut reader.dom_points
- }
}
diff --git a/components/script/dom/dompointreadonly.rs b/components/script/dom/dompointreadonly.rs
index 44e4a70b680..eb6bc9b93a9 100644
--- a/components/script/dom/dompointreadonly.rs
+++ b/components/script/dom/dompointreadonly.rs
@@ -15,8 +15,8 @@ use crate::dom::bindings::codegen::Bindings::DOMPointReadOnlyBinding::DOMPointRe
use crate::dom::bindings::error::Fallible;
use crate::dom::bindings::reflector::{Reflector, reflect_dom_object_with_proto};
use crate::dom::bindings::root::DomRoot;
-use crate::dom::bindings::serializable::{Serializable, StorageKey};
-use crate::dom::bindings::structuredclone::{StructuredData, StructuredDataReader};
+use crate::dom::bindings::serializable::Serializable;
+use crate::dom::bindings::structuredclone::StructuredData;
use crate::dom::globalscope::GlobalScope;
use crate::script_runtime::CanGc;
@@ -172,18 +172,12 @@ impl Serializable for DOMPointReadOnly {
))
}
- fn serialized_storage(
- data: StructuredData<'_>,
- ) -> &mut Option<HashMap<DomPointId, Self::Data>> {
+ fn serialized_storage<'a>(
+ data: StructuredData<'a, '_>,
+ ) -> &'a mut Option<HashMap<DomPointId, Self::Data>> {
match data {
StructuredData::Reader(r) => &mut r.points,
StructuredData::Writer(w) => &mut w.points,
}
}
-
- fn deserialized_storage(
- reader: &mut StructuredDataReader,
- ) -> &mut Option<HashMap<StorageKey, DomRoot<Self>>> {
- &mut reader.points_read_only
- }
}
diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs
index 2658911c795..77d1ee37c03 100644
--- a/components/script/dom/globalscope.rs
+++ b/components/script/dom/globalscope.rs
@@ -2880,15 +2880,11 @@ impl GlobalScope {
return p;
}
- if let Some((data, size)) = canvas.fetch_all_data() {
- let data = data
- .map(|data| data.to_vec())
- .unwrap_or_else(|| vec![0; size.area() as usize * 4]);
-
+ 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();
-
- image_bitmap.set_bitmap_data(data);
+ image_bitmap.set_bitmap_data(snapshot.to_vec());
image_bitmap.set_origin_clean(canvas.origin_is_clean());
p.resolve_native(&(image_bitmap), can_gc);
}
@@ -2901,14 +2897,11 @@ impl GlobalScope {
return p;
}
- if let Some((data, size)) = canvas.fetch_all_data() {
- let data = data
- .map(|data| data.to_vec())
- .unwrap_or_else(|| vec![0; size.area() as usize * 4]);
-
+ 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();
- image_bitmap.set_bitmap_data(data);
+ 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/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs
index 9e20539ceca..303c781c8b3 100644
--- a/components/script/dom/htmlcanvaselement.rs
+++ b/components/script/dom/htmlcanvaselement.rs
@@ -17,7 +17,6 @@ use image::codecs::jpeg::JpegEncoder;
use image::codecs::png::PngEncoder;
use image::codecs::webp::WebPEncoder;
use image::{ColorType, ImageEncoder};
-use ipc_channel::ipc::IpcSharedMemory;
#[cfg(feature = "webgpu")]
use ipc_channel::ipc::{self as ipcchan};
use js::error::throw_type_error;
@@ -25,6 +24,7 @@ use js::rust::{HandleObject, HandleValue};
use script_layout_interface::{HTMLCanvasData, HTMLCanvasDataSource};
use servo_media::streams::MediaStreamType;
use servo_media::streams::registry::MediaStreamId;
+use snapshot::Snapshot;
use style::attr::AttrValue;
use crate::canvas_context::CanvasContext as _;
@@ -69,6 +69,7 @@ use crate::script_runtime::{CanGc, JSContext};
const DEFAULT_WIDTH: u32 = 300;
const DEFAULT_HEIGHT: u32 = 150;
+#[derive(PartialEq)]
enum EncodedImageType {
Png,
Jpeg,
@@ -375,42 +376,21 @@ impl HTMLCanvasElement {
self.Height() != 0 && self.Width() != 0
}
- pub(crate) fn fetch_all_data(&self) -> Option<(Option<IpcSharedMemory>, Size2D<u32>)> {
- let size = self.get_size();
-
- if size.width == 0 || size.height == 0 {
- return None;
- }
-
- let data = match self.context.borrow().as_ref() {
- Some(CanvasContext::Context2d(context)) => context.get_image_data_as_shared_memory(),
- Some(CanvasContext::WebGL(_context)) => {
- // TODO: add a method in WebGLRenderingContext to get the pixels.
- return None;
- },
- Some(CanvasContext::WebGL2(_context)) => {
- // TODO: add a method in WebGL2RenderingContext to get the pixels.
- return None;
- },
- #[cfg(feature = "webgpu")]
- Some(CanvasContext::WebGPU(context)) => context.get_image_data_as_shared_memory(),
- Some(CanvasContext::Placeholder(context)) => return context.fetch_all_data(),
- None => None,
- };
-
- Some((data, size))
- }
-
- fn get_content(&self) -> Option<Vec<u8>> {
- match *self.context.borrow() {
- Some(CanvasContext::Context2d(ref context)) => context.get_image_data(),
- Some(CanvasContext::WebGL(ref context)) => context.get_image_data(),
- Some(CanvasContext::WebGL2(ref context)) => context.get_image_data(),
+ pub(crate) fn get_image_data(&self) -> Option<Snapshot> {
+ match self.context.borrow().as_ref() {
+ Some(CanvasContext::Context2d(context)) => context.get_image_data(),
+ Some(CanvasContext::WebGL(context)) => context.get_image_data(),
+ Some(CanvasContext::WebGL2(context)) => context.get_image_data(),
#[cfg(feature = "webgpu")]
- Some(CanvasContext::WebGPU(ref context)) => context.get_image_data(),
- Some(CanvasContext::Placeholder(_)) | None => {
- // Each pixel is fully-transparent black.
- Some(vec![0; (self.Width() * self.Height() * 4) as usize])
+ Some(CanvasContext::WebGPU(context)) => context.get_image_data(),
+ Some(CanvasContext::Placeholder(context)) => context.get_image_data(),
+ None => {
+ let size = self.get_size();
+ if size.width == 0 || size.height == 0 {
+ None
+ } else {
+ Some(Snapshot::cleared(size.cast()))
+ }
},
}
}
@@ -560,11 +540,23 @@ impl HTMLCanvasElementMethods<crate::DomTypeHolder> for HTMLCanvasElement {
}
// Step 3.
- let Some(file) = self.get_content() else {
+ let Some(mut snapshot) = self.get_image_data() else {
return Ok(USVString("data:,".into()));
};
let image_type = EncodedImageType::from(mime_type);
+ snapshot.transform(
+ if image_type == EncodedImageType::Jpeg {
+ snapshot::AlphaMode::AsOpaque {
+ premultiplied: true,
+ }
+ } else {
+ snapshot::AlphaMode::Transparent {
+ premultiplied: false,
+ }
+ },
+ snapshot::PixelFormat::RGBA,
+ );
let mut url = format!("data:{};base64,", image_type.as_mime_type());
let mut encoder = base64::write::EncoderStringWriter::from_consumer(
@@ -575,7 +567,7 @@ impl HTMLCanvasElementMethods<crate::DomTypeHolder> for HTMLCanvasElement {
self.encode_for_mime_type(
&image_type,
Self::maybe_quality(quality),
- &file,
+ snapshot.data(),
&mut encoder,
);
encoder.into_inner();
@@ -604,7 +596,7 @@ impl HTMLCanvasElementMethods<crate::DomTypeHolder> for HTMLCanvasElement {
let result = if self.Width() == 0 || self.Height() == 0 {
None
} else {
- self.get_content()
+ self.get_image_data()
};
let this = Trusted::new(self);
@@ -625,13 +617,17 @@ impl HTMLCanvasElementMethods<crate::DomTypeHolder> for HTMLCanvasElement {
return error!("Expected blob callback, but found none!");
};
- if let Some(bytes) = result {
+ if let Some(mut snapshot) = result {
+ snapshot.transform(
+ snapshot::AlphaMode::Transparent{ premultiplied: false },
+ snapshot::PixelFormat::RGBA
+ );
// Step 4.1
// If result is non-null, then set result to a serialization of result as a file with
// type and quality if given.
let mut encoded: Vec<u8> = vec![];
- this.encode_for_mime_type(&image_type, quality, &bytes, &mut encoded);
+ this.encode_for_mime_type(&image_type, quality, snapshot.data(), &mut encoded);
let blob_impl = BlobImpl::new_from_bytes(encoded, image_type.as_mime_type());
// Step 4.2.1 & 4.2.2
// Set result to a new Blob object, created in the relevant realm of this canvas element
diff --git a/components/script/dom/messageport.rs b/components/script/dom/messageport.rs
index fe590052db4..85d94c1aa7a 100644
--- a/components/script/dom/messageport.rs
+++ b/components/script/dom/messageport.rs
@@ -23,7 +23,7 @@ use crate::dom::bindings::error::{Error, ErrorResult, ErrorToJsval};
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::{DomGlobal, reflect_dom_object};
use crate::dom::bindings::root::DomRoot;
-use crate::dom::bindings::structuredclone::{self, StructuredData, StructuredDataReader};
+use crate::dom::bindings::structuredclone::{self, StructuredData};
use crate::dom::bindings::trace::RootedTraceableBox;
use crate::dom::bindings::transferable::Transferable;
use crate::dom::bindings::utils::set_dictionary_property;
@@ -268,18 +268,14 @@ impl Transferable for MessagePort {
Ok(transferred_port)
}
- fn serialized_storage(
- data: StructuredData<'_>,
- ) -> &mut Option<HashMap<MessagePortId, Self::Data>> {
+ fn serialized_storage<'a>(
+ data: StructuredData<'a, '_>,
+ ) -> &'a mut Option<HashMap<MessagePortId, Self::Data>> {
match data {
StructuredData::Reader(r) => &mut r.port_impls,
StructuredData::Writer(w) => &mut w.ports,
}
}
-
- fn deserialized_storage(reader: &mut StructuredDataReader) -> &mut Option<Vec<DomRoot<Self>>> {
- &mut reader.message_ports
- }
}
impl MessagePortMethods<crate::DomTypeHolder> for MessagePort {
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index 2a01370085a..45a107ae673 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -167,7 +167,6 @@ pub struct Node {
/// Layout data for this node. This is populated during layout and can
/// be used for incremental relayout and script queries.
- #[ignore_malloc_size_of = "trait object"]
#[no_trace]
layout_data: DomRefCell<Option<Box<GenericLayoutData>>>,
}
diff --git a/components/script/dom/offscreencanvas.rs b/components/script/dom/offscreencanvas.rs
index 0587fbad12b..aabe5955e12 100644
--- a/components/script/dom/offscreencanvas.rs
+++ b/components/script/dom/offscreencanvas.rs
@@ -6,8 +6,8 @@ use std::cell::Cell;
use dom_struct::dom_struct;
use euclid::default::Size2D;
-use ipc_channel::ipc::IpcSharedMemory;
use js::rust::{HandleObject, HandleValue};
+use snapshot::Snapshot;
use crate::dom::bindings::cell::{DomRefCell, Ref, ref_filter_map};
use crate::dom::bindings::codegen::Bindings::OffscreenCanvasBinding::{
@@ -88,21 +88,18 @@ impl OffscreenCanvas {
ref_filter_map(self.context.borrow(), |ctx| ctx.as_ref())
}
- pub(crate) fn fetch_all_data(&self) -> Option<(Option<IpcSharedMemory>, Size2D<u32>)> {
- let size = self.get_size();
-
- if size.width == 0 || size.height == 0 {
- return None;
- }
-
- let data = match self.context.borrow().as_ref() {
- Some(OffscreenCanvasContext::OffscreenContext2d(context)) => {
- context.get_image_data_as_shared_memory()
+ pub(crate) fn get_image_data(&self) -> Option<Snapshot> {
+ match self.context.borrow().as_ref() {
+ Some(OffscreenCanvasContext::OffscreenContext2d(context)) => context.get_image_data(),
+ None => {
+ let size = self.get_size();
+ if size.width == 0 || size.height == 0 {
+ None
+ } else {
+ Some(Snapshot::cleared(size))
+ }
},
- None => None,
- };
-
- Some((data, size.to_u32()))
+ }
}
pub(crate) fn get_or_init_2d_context(
diff --git a/components/script/dom/offscreencanvasrenderingcontext2d.rs b/components/script/dom/offscreencanvasrenderingcontext2d.rs
index 69a1d41af2e..2f9b52640e6 100644
--- a/components/script/dom/offscreencanvasrenderingcontext2d.rs
+++ b/components/script/dom/offscreencanvasrenderingcontext2d.rs
@@ -8,7 +8,7 @@ use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanva
use canvas_traits::canvas::Canvas2dMsg;
use dom_struct::dom_struct;
use euclid::default::Size2D;
-use ipc_channel::ipc::IpcSharedMemory;
+use snapshot::Snapshot;
use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::{
CanvasDirection, CanvasFillRule, CanvasImageSource, CanvasLineCap, CanvasLineJoin,
@@ -76,8 +76,8 @@ impl OffscreenCanvasRenderingContext2D {
self.context.origin_is_clean()
}
- pub(crate) fn get_image_data_as_shared_memory(&self) -> Option<IpcSharedMemory> {
- self.context.get_image_data_as_shared_memory()
+ pub(crate) fn get_image_data(&self) -> Option<Snapshot> {
+ self.context.get_image_data()
}
}
diff --git a/components/script/dom/readablestream.rs b/components/script/dom/readablestream.rs
index b445fb4b9fc..37899f18fec 100644
--- a/components/script/dom/readablestream.rs
+++ b/components/script/dom/readablestream.rs
@@ -59,7 +59,7 @@ use crate::realms::{enter_realm, InRealm};
use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
use crate::dom::promisenativehandler::{Callback, PromiseNativeHandler};
use crate::dom::bindings::transferable::Transferable;
-use crate::dom::bindings::structuredclone::{StructuredData, StructuredDataReader};
+use crate::dom::bindings::structuredclone::StructuredData;
use super::bindings::buffer_source::HeapBufferSource;
use super::bindings::codegen::Bindings::ReadableStreamBYOBReaderBinding::ReadableStreamBYOBReaderReadOptions;
@@ -2247,16 +2247,12 @@ impl Transferable for ReadableStream {
}
/// Note: we are relying on the port transfer, so the data returned here are related to the port.
- fn serialized_storage(
- data: StructuredData<'_>,
- ) -> &mut Option<HashMap<MessagePortId, Self::Data>> {
+ fn serialized_storage<'a>(
+ data: StructuredData<'a, '_>,
+ ) -> &'a mut Option<HashMap<MessagePortId, Self::Data>> {
match data {
StructuredData::Reader(r) => &mut r.port_impls,
StructuredData::Writer(w) => &mut w.ports,
}
}
-
- fn deserialized_storage(reader: &mut StructuredDataReader) -> &mut Option<Vec<DomRoot<Self>>> {
- &mut reader.readable_streams
- }
}
diff --git a/components/script/dom/webgl2renderingcontext.rs b/components/script/dom/webgl2renderingcontext.rs
index bb6ffa11849..416454d8719 100644
--- a/components/script/dom/webgl2renderingcontext.rs
+++ b/components/script/dom/webgl2renderingcontext.rs
@@ -24,6 +24,7 @@ use js::typedarray::{ArrayBufferView, CreateWith, Float32, Int32Array, Uint32, U
use script_bindings::interfaces::WebGL2RenderingContextHelpers;
use script_layout_interface::HTMLCanvasDataSource;
use servo_config::pref;
+use snapshot::Snapshot;
use url::Host;
use crate::canvas_context::CanvasContext;
@@ -549,11 +550,11 @@ impl WebGL2RenderingContext {
return
);
- let (sender, receiver) = ipc::bytes_channel().unwrap();
+ let (sender, receiver) = ipc::channel().unwrap();
self.base.send_command(WebGLCommand::ReadPixels(
src_rect, format, pixel_type, sender,
));
- let src = receiver.recv().unwrap();
+ let (src, _) = receiver.recv().unwrap();
for i in 0..src_rect.size.height as usize {
let src_start = i * src_row_bytes as usize;
@@ -916,11 +917,7 @@ impl CanvasContext for WebGL2RenderingContext {
self.base.resize();
}
- fn get_image_data_as_shared_memory(&self) -> Option<IpcSharedMemory> {
- self.base.get_image_data_as_shared_memory()
- }
-
- fn get_image_data(&self) -> Option<Vec<u8>> {
+ fn get_image_data(&self) -> Option<Snapshot> {
self.base.get_image_data()
}
diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs
index 1e51ac4baf9..9996a3cf504 100644
--- a/components/script/dom/webglrenderingcontext.rs
+++ b/components/script/dom/webglrenderingcontext.rs
@@ -34,6 +34,7 @@ use pixels::{self, PixelFormat};
use script_layout_interface::HTMLCanvasDataSource;
use serde::{Deserialize, Serialize};
use servo_config::pref;
+use snapshot::Snapshot;
use webrender_api::ImageKey;
use crate::canvas_context::CanvasContext;
@@ -628,11 +629,15 @@ impl WebGLRenderingContext {
if !canvas.origin_is_clean() {
return Err(Error::Security);
}
- if let Some((data, size)) = canvas.fetch_all_data() {
- let data = data.unwrap_or_else(|| {
- IpcSharedMemory::from_bytes(&vec![0; size.area() as usize * 4])
- });
- TexPixels::new(data, size, PixelFormat::BGRA8, true)
+ if let Some(snapshot) = canvas.get_image_data() {
+ 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)
} else {
return Ok(None);
}
@@ -1922,18 +1927,13 @@ impl CanvasContext for WebGLRenderingContext {
}
}
- fn get_image_data_as_shared_memory(&self) -> Option<IpcSharedMemory> {
- // TODO: add a method in WebGLRenderingContext to get the pixels.
- None
- }
-
// Used by HTMLCanvasElement.toDataURL
//
// This emits errors quite liberally, but the spec says that this operation
// can fail and that it is UB what happens in that case.
//
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#2.2
- fn get_image_data(&self) -> Option<Vec<u8>> {
+ fn get_image_data(&self) -> Option<Snapshot> {
handle_potential_webgl_error!(self, self.validate_framebuffer(), return None);
let mut size = self.size().cast();
@@ -1945,14 +1945,20 @@ impl CanvasContext for WebGLRenderingContext {
size.width = cmp::min(size.width, fb_width as u32);
size.height = cmp::min(size.height, fb_height as u32);
- let (sender, receiver) = ipc::bytes_channel().unwrap();
+ let (sender, receiver) = ipc::channel().unwrap();
self.send_command(WebGLCommand::ReadPixels(
Rect::from_size(size),
constants::RGBA,
constants::UNSIGNED_BYTE,
sender,
));
- Some(receiver.recv().unwrap())
+ let (data, alpha_mode) = receiver.recv().unwrap();
+ Some(Snapshot::from_vec(
+ size.cast(),
+ snapshot::PixelFormat::RGBA,
+ alpha_mode,
+ data.to_vec(),
+ ))
}
fn mark_as_dirty(&self) {
@@ -3826,11 +3832,11 @@ impl WebGLRenderingContextMethods<crate::DomTypeHolder> for WebGLRenderingContex
dest_offset += -y * row_len;
}
- let (sender, receiver) = ipc::bytes_channel().unwrap();
+ let (sender, receiver) = ipc::channel().unwrap();
self.send_command(WebGLCommand::ReadPixels(
src_rect, format, pixel_type, sender,
));
- let src = receiver.recv().unwrap();
+ let (src, _) = receiver.recv().unwrap();
let src_row_len = src_rect.size.width as usize * bytes_per_pixel as usize;
for i in 0..src_rect.size.height {
diff --git a/components/script/dom/webgpu/gpucanvascontext.rs b/components/script/dom/webgpu/gpucanvascontext.rs
index 595b54c58d7..c81f96f651f 100644
--- a/components/script/dom/webgpu/gpucanvascontext.rs
+++ b/components/script/dom/webgpu/gpucanvascontext.rs
@@ -7,8 +7,9 @@ use std::cell::RefCell;
use arrayvec::ArrayVec;
use dom_struct::dom_struct;
-use ipc_channel::ipc::{self, IpcSharedMemory};
+use ipc_channel::ipc::{self};
use script_layout_interface::HTMLCanvasDataSource;
+use snapshot::Snapshot;
use webgpu_traits::{
ContextConfiguration, PRESENTATION_BUFFER_COUNT, WebGPU, WebGPUContextId, WebGPURequest,
WebGPUTexture,
@@ -277,10 +278,10 @@ impl CanvasContext for GPUCanvasContext {
}
/// <https://gpuweb.github.io/gpuweb/#ref-for-abstract-opdef-get-a-copy-of-the-image-contents-of-a-context%E2%91%A5>
- fn get_image_data_as_shared_memory(&self) -> Option<IpcSharedMemory> {
+ fn get_image_data(&self) -> Option<Snapshot> {
// 1. Return a copy of the image contents of context.
Some(if self.drawing_buffer.borrow().cleared {
- IpcSharedMemory::from_byte(0, self.size().area() as usize * 4)
+ Snapshot::cleared(self.size())
} else {
let (sender, receiver) = ipc::channel().unwrap();
self.channel
@@ -290,7 +291,7 @@ impl CanvasContext for GPUCanvasContext {
sender,
})
.unwrap();
- receiver.recv().unwrap()
+ receiver.recv().unwrap().to_owned()
})
}
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index 96176132b6b..efe61007ef8 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -2281,11 +2281,12 @@ impl Window {
node: Option<&Node>,
can_gc: CanGc,
) -> UntypedRect<i32> {
- let opaque = node.map(|node| node.to_opaque());
if !self.layout_reflow(QueryMsg::ScrollingAreaQuery, can_gc) {
return Rect::zero();
}
- self.layout.borrow().query_scrolling_area(opaque)
+ self.layout
+ .borrow()
+ .query_scrolling_area(node.map(Node::to_trusted_node_address))
}
pub(crate) fn scroll_offset_query(&self, node: &Node) -> Vector2D<f32, LayoutPixel> {
diff --git a/components/script/dom/writablestream.rs b/components/script/dom/writablestream.rs
index 1490fc694ef..e7e9ce906a6 100644
--- a/components/script/dom/writablestream.rs
+++ b/components/script/dom/writablestream.rs
@@ -27,7 +27,7 @@ use crate::dom::bindings::conversions::ConversionResult;
use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object_with_proto};
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
-use crate::dom::bindings::structuredclone::{StructuredData, StructuredDataReader};
+use crate::dom::bindings::structuredclone::StructuredData;
use crate::dom::bindings::transferable::Transferable;
use crate::dom::countqueuingstrategy::{extract_high_water_mark, extract_size_algorithm};
use crate::dom::domexception::{DOMErrorName, DOMException};
@@ -1182,16 +1182,12 @@ impl Transferable for WritableStream {
}
/// Note: we are relying on the port transfer, so the data returned here are related to the port.
- fn serialized_storage(
- data: StructuredData<'_>,
- ) -> &mut Option<HashMap<MessagePortId, Self::Data>> {
+ fn serialized_storage<'a>(
+ data: StructuredData<'a, '_>,
+ ) -> &'a mut Option<HashMap<MessagePortId, Self::Data>> {
match data {
StructuredData::Reader(r) => &mut r.port_impls,
StructuredData::Writer(w) => &mut w.ports,
}
}
-
- fn deserialized_storage(reader: &mut StructuredDataReader) -> &mut Option<Vec<DomRoot<Self>>> {
- &mut reader.writable_streams
- }
}
diff --git a/components/script/layout_image.rs b/components/script/layout_image.rs
index 7fd23804ffd..df542b4b759 100644
--- a/components/script/layout_image.rs
+++ b/components/script/layout_image.rs
@@ -119,7 +119,10 @@ pub(crate) fn fetch_image_for_layout(
)
.origin(document.origin().immutable().clone())
.destination(Destination::Image)
- .pipeline_id(Some(document.global().pipeline_id()));
+ .pipeline_id(Some(document.global().pipeline_id()))
+ .insecure_requests_policy(document.insecure_requests_policy())
+ .has_trustworthy_ancestor_origin(document.has_trustworthy_ancestor_origin())
+ .policy_container(document.policy_container().to_owned());
// Layout image loads do not delay the document load event.
document.fetch_background(request, context);
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index c9b27bb6c56..231de76df1d 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -2439,8 +2439,6 @@ impl ScriptThread {
let mut reports = vec![];
perform_memory_report(|ops| {
- let prefix = format!("url({urls})");
- reports.extend(self.get_cx().get_reports(prefix.clone(), ops));
for (_, document) in documents.iter() {
document
.window()
@@ -2448,6 +2446,9 @@ impl ScriptThread {
.collect_reports(&mut reports, ops);
}
+ let prefix = format!("url({urls})");
+ reports.extend(self.get_cx().get_reports(prefix.clone(), ops));
+
reports.push(self.image_cache.memory_report(&prefix, ops));
});