aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/messageport.rs
diff options
context:
space:
mode:
authorGregory Terzian <2792687+gterzian@users.noreply.github.com>2025-04-15 15:39:26 +0800
committerGitHub <noreply@github.com>2025-04-15 07:39:26 +0000
commitf8b6b9f7b63756d13e8a86d988c93b521acc6966 (patch)
treef77d98c10cfcabd6434217a9e8126d9265a8629f /components/script/dom/messageport.rs
parentc9489ca04fa4b5462e788f55df33cbbc0e911db0 (diff)
downloadservo-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.rs85
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 {