diff options
author | Gregory Terzian <2792687+gterzian@users.noreply.github.com> | 2025-04-15 15:39:26 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-04-15 07:39:26 +0000 |
commit | f8b6b9f7b63756d13e8a86d988c93b521acc6966 (patch) | |
tree | f77d98c10cfcabd6434217a9e8126d9265a8629f /components/script/dom/messageport.rs | |
parent | c9489ca04fa4b5462e788f55df33cbbc0e911db0 (diff) | |
download | servo-f8b6b9f7b63756d13e8a86d988c93b521acc6966.tar.gz servo-f8b6b9f7b63756d13e8a86d988c93b521acc6966.zip |
Transfer ReadableStream (#36181)
<!-- Please describe your changes on the following line: -->
Add transfer support to ReadableStream. Part of
https://github.com/servo/servo/issues/34676
---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by
`[X]` when the step is complete, and replace `___` with appropriate
data: -->
- [ ] `./mach build -d` does not report any errors
- [ ] `./mach test-tidy` does not report any errors
- [ ] These changes fix #___ (GitHub issue number if applicable)
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because ___
<!-- Also, please make sure that "Allow edits from maintainers" checkbox
is checked, so that we can help you if you get stuck somewhere along the
way.-->
<!-- Pull requests that do not address these steps are welcome, but they
will require additional verification as part of the review process. -->
---------
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Diffstat (limited to 'components/script/dom/messageport.rs')
-rw-r--r-- | components/script/dom/messageport.rs | 85 |
1 files changed, 83 insertions, 2 deletions
diff --git a/components/script/dom/messageport.rs b/components/script/dom/messageport.rs index d299ab8156f..3e25602b365 100644 --- a/components/script/dom/messageport.rs +++ b/components/script/dom/messageport.rs @@ -5,12 +5,14 @@ use std::cell::{Cell, RefCell}; use std::collections::HashMap; use std::num::NonZeroU32; +use std::ptr; use std::rc::Rc; use base::id::{MessagePortId, MessagePortIndex, PipelineNamespaceId}; use constellation_traits::{MessagePortImpl, PortMessageTask}; use dom_struct::dom_struct; -use js::jsapi::{Heap, JSObject}; +use js::jsapi::{Heap, JS_NewObject, JSObject}; +use js::jsval::UndefinedValue; use js::rust::{CustomAutoRooter, CustomAutoRooterGuard, HandleValue}; use crate::dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; @@ -25,8 +27,10 @@ use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::structuredclone::{self, StructuredData, StructuredDataReader}; use crate::dom::bindings::trace::RootedTraceableBox; use crate::dom::bindings::transferable::{ExtractComponents, IdFromComponents, Transferable}; +use crate::dom::bindings::utils::set_dictionary_property; use crate::dom::eventtarget::EventTarget; use crate::dom::globalscope::GlobalScope; +use crate::js::conversions::ToJSValConvertible; use crate::script_runtime::{CanGc, JSContext as SafeJSContext}; #[dom_struct] @@ -57,7 +61,7 @@ impl MessagePort { } /// Create a new port for an incoming transfer-received one. - fn new_transferred( + pub(crate) fn new_transferred( owner: &GlobalScope, transferred_port: MessagePortId, entangled_port: Option<MessagePortId>, @@ -156,6 +160,83 @@ impl MessagePort { .post_messageport_msg(*self.message_port_id(), task); Ok(()) } + + /// <https://streams.spec.whatwg.org/#abstract-opdef-crossrealmtransformsenderror> + pub(crate) fn cross_realm_transform_send_error(&self, error: HandleValue, can_gc: CanGc) { + // Perform PackAndPostMessage(port, "error", error), + // discarding the result. + let _ = self.pack_and_post_message("error", error, can_gc); + } + + /// <https://streams.spec.whatwg.org/#abstract-opdef-packandpostmessagehandlingerror> + #[allow(unsafe_code)] + pub(crate) fn pack_and_post_message_handling_error( + &self, + type_: &str, + value: HandleValue, + can_gc: CanGc, + ) -> ErrorResult { + // Let result be PackAndPostMessage(port, type, value). + let result = self.pack_and_post_message(type_, value, can_gc); + + // If result is an abrupt completion, + if result.is_err() { + // Perform ! CrossRealmTransformSendError(port, result.[[Value]]). + // Note: we send UndefinedValue across, + // because somehow sending an error results in another error. + // The Error::DataClone, which is the only one that is sent across, + // will be created upon receipt. + let cx = GlobalScope::get_cx(); + rooted!(in(*cx) let mut rooted_error = UndefinedValue()); + self.cross_realm_transform_send_error(rooted_error.handle(), can_gc); + } + + result + } + + /// <https://streams.spec.whatwg.org/#abstract-opdef-packandpostmessage> + #[allow(unsafe_code)] + pub(crate) fn pack_and_post_message( + &self, + type_: &str, + value: HandleValue, + _can_gc: CanGc, + ) -> ErrorResult { + let cx = GlobalScope::get_cx(); + + // Let message be OrdinaryObjectCreate(null). + rooted!(in(*cx) let mut message = unsafe { JS_NewObject(*cx, ptr::null()) }); + rooted!(in(*cx) let mut type_string = UndefinedValue()); + unsafe { + type_.to_jsval(*cx, type_string.handle_mut()); + } + + // Perform ! CreateDataProperty(message, "type", type). + unsafe { + set_dictionary_property(*cx, message.handle(), "type", type_string.handle()) + .expect("Setting the message type should not fail."); + } + + // Perform ! CreateDataProperty(message, "value", value). + unsafe { + set_dictionary_property(*cx, message.handle(), "value", value) + .expect("Setting the message value should not fail."); + } + + // Let targetPort be the port with which port is entangled, if any; otherwise let it be null. + // Done in `global.post_messageport_msg`. + + // Let options be «[ "transfer" → « » ]». + let mut rooted = CustomAutoRooter::new(vec![]); + let transfer = CustomAutoRooterGuard::new(*cx, &mut rooted); + + // Run the message port post message steps providing targetPort, message, and options. + rooted!(in(*cx) let mut message_val = UndefinedValue()); + unsafe { + message.to_jsval(*cx, message_val.handle_mut()); + } + self.post_message_impl(cx, message_val.handle(), transfer) + } } impl Transferable for MessagePort { |