aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
Diffstat (limited to 'components/script')
-rw-r--r--components/script/canvas_state.rs4
-rw-r--r--components/script/dom/bindings/structuredclone.rs8
-rw-r--r--components/script/dom/readablestream.rs46
-rw-r--r--components/script/dom/transformstream.rs104
-rw-r--r--components/script/dom/webglrenderingcontext.rs3
5 files changed, 114 insertions, 51 deletions
diff --git a/components/script/canvas_state.rs b/components/script/canvas_state.rs
index dabe6a5728b..d4840a5b470 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};
+use ipc_channel::ipc::{self, IpcSender, IpcSharedMemory};
use net_traits::image_cache::{ImageCache, ImageResponse};
use net_traits::request::CorsSettings;
use pixels::PixelFormat;
@@ -350,7 +350,7 @@ impl CanvasState {
size.cast(),
format,
alpha_mode,
- img.bytes(),
+ IpcSharedMemory::from_bytes(img.first_frame().bytes),
))
}
diff --git a/components/script/dom/bindings/structuredclone.rs b/components/script/dom/bindings/structuredclone.rs
index 70638238123..c23156817cb 100644
--- a/components/script/dom/bindings/structuredclone.rs
+++ b/components/script/dom/bindings/structuredclone.rs
@@ -14,7 +14,7 @@ use base::id::{
};
use constellation_traits::{
BlobImpl, DomException, DomPoint, MessagePortImpl, Serializable as SerializableInterface,
- StructuredSerializedData, Transferrable as TransferrableInterface,
+ StructuredSerializedData, Transferrable as TransferrableInterface, TransformStreamData,
};
use js::gc::RootedVec;
use js::glue::{
@@ -517,6 +517,8 @@ pub(crate) struct StructuredDataReader<'a> {
/// used as part of the "transfer-receiving" steps of ports,
/// to produce the DOM ports stored in `message_ports` above.
pub(crate) port_impls: Option<HashMap<MessagePortId, MessagePortImpl>>,
+ /// A map of transform stream implementations,
+ pub(crate) transform_streams_port_impls: Option<HashMap<MessagePortId, TransformStreamData>>,
/// A map of blob implementations,
/// used as part of the "deserialize" steps of blobs,
/// to produce the DOM blobs stored in `blobs` above.
@@ -535,6 +537,8 @@ pub(crate) struct StructuredDataWriter {
pub(crate) errors: DOMErrorRecord,
/// Transferred ports.
pub(crate) ports: Option<HashMap<MessagePortId, MessagePortImpl>>,
+ /// Transferred transform streams.
+ pub(crate) transform_streams_port: Option<HashMap<MessagePortId, TransformStreamData>>,
/// Serialized points.
pub(crate) points: Option<HashMap<DomPointId, DomPoint>>,
/// Serialized exceptions.
@@ -591,6 +595,7 @@ pub(crate) fn write(
let data = StructuredSerializedData {
serialized: data,
ports: sc_writer.ports.take(),
+ transform_streams: sc_writer.transform_streams_port.take(),
points: sc_writer.points.take(),
exceptions: sc_writer.exceptions.take(),
blobs: sc_writer.blobs.take(),
@@ -613,6 +618,7 @@ pub(crate) fn read(
let mut sc_reader = StructuredDataReader {
roots,
port_impls: data.ports.take(),
+ transform_streams_port_impls: data.transform_streams.take(),
blob_impls: data.blobs.take(),
points: data.points.take(),
exceptions: data.exceptions.take(),
diff --git a/components/script/dom/readablestream.rs b/components/script/dom/readablestream.rs
index d631a01e1e7..d2c1d853f86 100644
--- a/components/script/dom/readablestream.rs
+++ b/components/script/dom/readablestream.rs
@@ -24,7 +24,7 @@ use js::typedarray::ArrayBufferViewU8;
use crate::dom::bindings::codegen::Bindings::QueuingStrategyBinding::QueuingStrategy;
use crate::dom::bindings::codegen::Bindings::ReadableStreamBinding::{
ReadableStreamGetReaderOptions, ReadableStreamMethods, ReadableStreamReaderMode,
- StreamPipeOptions,
+ ReadableWritablePair, StreamPipeOptions,
};
use script_bindings::str::DOMString;
@@ -2006,6 +2006,50 @@ impl ReadableStreamMethods<crate::DomTypeHolder> for ReadableStream {
can_gc,
)
}
+
+ /// <https://streams.spec.whatwg.org/#rs-pipe-through>
+ fn PipeThrough(
+ &self,
+ transform: &ReadableWritablePair,
+ options: &StreamPipeOptions,
+ realm: InRealm,
+ can_gc: CanGc,
+ ) -> Fallible<DomRoot<ReadableStream>> {
+ let global = self.global();
+ let cx = GlobalScope::get_cx();
+
+ // If ! IsReadableStreamLocked(this) is true, throw a TypeError exception.
+ if self.is_locked() {
+ return Err(Error::Type("Source stream is locked".to_owned()));
+ }
+
+ // If ! IsWritableStreamLocked(transform["writable"]) is true, throw a TypeError exception.
+ if transform.writable.is_locked() {
+ return Err(Error::Type("Destination stream is locked".to_owned()));
+ }
+
+ // Let signal be options["signal"] if it exists, or undefined otherwise.
+ // TODO: implement AbortSignal.
+
+ // Let promise be ! ReadableStreamPipeTo(this, transform["writable"],
+ // options["preventClose"], options["preventAbort"], options["preventCancel"], signal).
+ let promise = self.pipe_to(
+ cx,
+ &global,
+ &transform.writable,
+ options.preventAbort,
+ options.preventCancel,
+ options.preventClose,
+ realm,
+ can_gc,
+ );
+
+ // Set promise.[[PromiseIsHandled]] to true.
+ promise.set_promise_is_handled();
+
+ // Return transform["readable"].
+ Ok(transform.readable.clone())
+ }
}
#[allow(unsafe_code)]
diff --git a/components/script/dom/transformstream.rs b/components/script/dom/transformstream.rs
index 0251498980d..446bf71f172 100644
--- a/components/script/dom/transformstream.rs
+++ b/components/script/dom/transformstream.rs
@@ -8,7 +8,7 @@ use std::ptr::{self};
use std::rc::Rc;
use base::id::{MessagePortId, MessagePortIndex};
-use constellation_traits::MessagePortImpl;
+use constellation_traits::TransformStreamData;
use dom_struct::dom_struct;
use js::jsapi::{Heap, IsPromiseObject, JSObject};
use js::jsval::{JSVal, ObjectValue, UndefinedValue};
@@ -1007,9 +1007,9 @@ impl TransformStreamMethods<crate::DomTypeHolder> for TransformStream {
/// <https://streams.spec.whatwg.org/#ts-transfer>
impl Transferable for TransformStream {
type Index = MessagePortIndex;
- type Data = MessagePortImpl;
+ type Data = TransformStreamData;
- fn transfer(&self) -> Result<(MessagePortId, MessagePortImpl), ()> {
+ fn transfer(&self) -> Result<(MessagePortId, TransformStreamData), ()> {
let global = self.global();
let realm = enter_realm(&*global);
let comp = InRealm::Entered(&realm);
@@ -1023,73 +1023,85 @@ impl Transferable for TransformStream {
let writable = self.get_writable();
// If ! IsReadableStreamLocked(readable) is true, throw a "DataCloneError" DOMException.
- if readable.is_locked() {
- return Err(());
- }
-
// If ! IsWritableStreamLocked(writable) is true, throw a "DataCloneError" DOMException.
- if writable.is_locked() {
+ if readable.is_locked() || writable.is_locked() {
return Err(());
}
- // Create the shared port pair
- let port_1 = MessagePort::new(&global, can_gc);
- global.track_message_port(&port_1, None);
- let port_2 = MessagePort::new(&global, can_gc);
- global.track_message_port(&port_2, None);
- global.entangle_ports(*port_1.message_port_id(), *port_2.message_port_id());
+ // First port pair (readable → proxy writable)
+ let port1 = MessagePort::new(&global, can_gc);
+ global.track_message_port(&port1, None);
+ let port1_peer = MessagePort::new(&global, can_gc);
+ global.track_message_port(&port1_peer, None);
+ global.entangle_ports(*port1.message_port_id(), *port1_peer.message_port_id());
+
+ let proxy_readable = ReadableStream::new_with_proto(&global, None, can_gc);
+ proxy_readable.setup_cross_realm_transform_readable(cx, &port1, can_gc);
+ proxy_readable
+ .pipe_to(cx, &global, &writable, false, false, false, comp, can_gc)
+ .set_promise_is_handled();
+
+ // Second port pair (proxy readable → writable)
+ let port2 = MessagePort::new(&global, can_gc);
+ global.track_message_port(&port2, None);
+ let port2_peer = MessagePort::new(&global, can_gc);
+ global.track_message_port(&port2_peer, None);
+ global.entangle_ports(*port2.message_port_id(), *port2_peer.message_port_id());
- // Create a proxy WritableStream wired to port_1
let proxy_writable = WritableStream::new_with_proto(&global, None, can_gc);
- proxy_writable.setup_cross_realm_transform_writable(cx, &port_1, can_gc);
+ proxy_writable.setup_cross_realm_transform_writable(cx, &port2, can_gc);
// Pipe readable into the proxy writable (→ port_1)
- let pipe1 = readable.pipe_to(
- cx,
- &global,
- &proxy_writable,
- false,
- false,
- false,
- comp,
- can_gc,
- );
- pipe1.set_promise_is_handled();
-
- // Create a proxy ReadableStream wired to port_1
- let proxy_readable = ReadableStream::new_with_proto(&global, None, can_gc);
- proxy_readable.setup_cross_realm_transform_readable(cx, &port_1, can_gc);
-
- // Pipe proxy readable (← port_1) into writable
- let pipe2 =
- proxy_readable.pipe_to(cx, &global, &writable, false, false, false, comp, can_gc);
- pipe2.set_promise_is_handled();
+ readable
+ .pipe_to(
+ cx,
+ &global,
+ &proxy_writable,
+ false,
+ false,
+ false,
+ comp,
+ can_gc,
+ )
+ .set_promise_is_handled();
// Set dataHolder.[[readable]] to ! StructuredSerializeWithTransfer(readable, « readable »).
// Set dataHolder.[[writable]] to ! StructuredSerializeWithTransfer(writable, « writable »).
- port_2.transfer()
+ Ok((
+ *port1_peer.message_port_id(),
+ TransformStreamData {
+ readable: port1_peer.transfer()?,
+ writable: port2_peer.transfer()?,
+ },
+ ))
}
fn transfer_receive(
owner: &GlobalScope,
- id: MessagePortId,
- port_impl: MessagePortImpl,
+ _id: MessagePortId,
+ data: TransformStreamData,
) -> Result<DomRoot<Self>, ()> {
let can_gc = CanGc::note();
+ let cx = GlobalScope::get_cx();
+
+ let port1 = MessagePort::transfer_receive(owner, data.readable.0, data.readable.1)?;
+ let port2 = MessagePort::transfer_receive(owner, data.writable.0, data.writable.1)?;
// Let readableRecord be ! StructuredDeserializeWithTransfer(dataHolder.[[readable]], the current Realm).
// Set value.[[readable]] to readableRecord.[[Deserialized]].
- let readable = ReadableStream::transfer_receive(owner, id, port_impl.clone())?;
-
// Let writableRecord be ! StructuredDeserializeWithTransfer(dataHolder.[[writable]], the current Realm).
- let writable = WritableStream::transfer_receive(owner, id, port_impl)?;
+ let proxy_readable = ReadableStream::new_with_proto(owner, None, can_gc);
+ proxy_readable.setup_cross_realm_transform_readable(cx, &port2, can_gc);
+
+ let proxy_writable = WritableStream::new_with_proto(owner, None, can_gc);
+ proxy_writable.setup_cross_realm_transform_writable(cx, &port1, can_gc);
// Set value.[[readable]] to readableRecord.[[Deserialized]].
// Set value.[[writable]] to writableRecord.[[Deserialized]].
// Set value.[[backpressure]], value.[[backpressureChangePromise]], and value.[[controller]] to undefined.
let stream = TransformStream::new_with_proto(owner, None, can_gc);
- stream.readable.set(Some(&readable));
- stream.writable.set(Some(&writable));
+ stream.readable.set(Some(&proxy_readable));
+ stream.writable.set(Some(&proxy_writable));
Ok(stream)
}
@@ -1098,8 +1110,8 @@ impl Transferable for TransformStream {
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,
+ StructuredData::Reader(r) => &mut r.transform_streams_port_impls,
+ StructuredData::Writer(w) => &mut w.transform_streams_port,
}
}
}
diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs
index 98170f9655b..b82051b3b12 100644
--- a/components/script/dom/webglrenderingcontext.rs
+++ b/components/script/dom/webglrenderingcontext.rs
@@ -619,7 +619,8 @@ impl WebGLRenderingContext {
let size = Size2D::new(img.width, img.height);
- TexPixels::new(img.bytes(), size, img.format, false)
+ let data = IpcSharedMemory::from_bytes(img.first_frame().bytes);
+ TexPixels::new(data, size, img.format, false)
},
// TODO(emilio): Getting canvas data is implemented in CanvasRenderingContext2D,
// but we need to refactor it moving it to `HTMLCanvasElement` and support