diff --git a/patches/components/script/dom/html/htmlembeddedwebview.rs.patch b/patches/components/script/dom/html/htmlembeddedwebview.rs.patch
index adead82..3fd34c8 100644
--- a/patches/components/script/dom/html/htmlembeddedwebview.rs.patch
+++ b/patches/components/script/dom/html/htmlembeddedwebview.rs.patch
@@ -1,6 +1,6 @@
--- original
+++ modified
-@@ -0,0 +1,1138 @@
+@@ -0,0 +1,1139 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
@@ -19,6 +19,7 @@
+};
+use js::context::JSContext;
+use js::jsval::UndefinedValue;
++use log::warn;
+use script_bindings::codegen::GenericBindings::CustomEventBinding::CustomEventMethods;
+use script_bindings::conversions::SafeToJSValConvertible;
+use servo_base::Epoch;
@@ -800,13 +801,13 @@
+ global.task_manager().dom_manipulation_task_source(),
+ );
+
-+ // Send the screenshot request to the constellation
-+ global
-+ .script_to_constellation_chan()
-+ .send(ScriptToConstellationMessage::EmbeddedWebViewTakeScreenshot(
++ if let Err(error) = global.script_to_constellation_chan().send(
++ ScriptToConstellationMessage::EmbeddedWebViewTakeScreenshot(
+ webview_id, request, callback,
-+ ))
-+ .unwrap();
++ ),
++ ) {
++ warn!("Failed to send EmbeddedWebViewTakeScreenshot: {error:?}");
++ }
+
+ Ok(promise)
+ }
diff --git a/patches/components/script/dom/window.rs.patch b/patches/components/script/dom/window.rs.patch
index 536cb39..26f134f 100644
--- a/patches/components/script/dom/window.rs.patch
+++ b/patches/components/script/dom/window.rs.patch
@@ -20,7 +20,15 @@
use js::realm::{AutoRealm, CurrentRealm};
use js::rust::wrappers::JS_DefineProperty;
use js::rust::wrappers2::JS_GC;
-@@ -157,6 +159,7 @@
+@@ -48,6 +50,7 @@
+ ReflowStatistics, RestyleReason, ScrollContainerQueryFlags, ScrollContainerResponse,
+ TrustedNodeAddress, combine_id_with_fragment_type,
+ };
++use log::warn;
+ use malloc_size_of::MallocSizeOf;
+ use media::WindowGLContext;
+ use net_traits::image_cache::{
+@@ -157,6 +160,7 @@
use crate::dom::html::htmliframeelement::HTMLIFrameElement;
use crate::dom::idbfactory::IDBFactory;
use crate::dom::inputevent::HitTestResult;
@@ -28,7 +36,7 @@
use crate::dom::location::Location;
use crate::dom::medialist::MediaList;
use crate::dom::mediaquerylist::{MediaQueryList, MediaQueryListMatchState};
-@@ -1145,12 +1148,22 @@
+@@ -1145,12 +1149,22 @@
let (sender, receiver) =
ProfiledGenericChannel::channel(self.global().time_profiler_chan().clone()).unwrap();
@@ -52,7 +60,7 @@
receiver.recv().unwrap_or_else(|_| {
// If the receiver is closed, we assume the dialog was cancelled.
debug!("Alert dialog was cancelled or failed to show.");
-@@ -1178,13 +1191,22 @@
+@@ -1178,13 +1192,22 @@
// the user to respond with a positive or negative response.
let (sender, receiver) =
ProfiledGenericChannel::channel(self.global().time_profiler_chan().clone()).unwrap();
@@ -76,7 +84,7 @@
// Step 5: Let userPromptHandler be WebDriver BiDi user prompt opened with this,
// "confirm", and message.
//
-@@ -1229,6 +1251,7 @@
+@@ -1229,6 +1252,7 @@
// defaulted to the value given by default.
let (sender, receiver) =
ProfiledGenericChannel::channel(self.global().time_profiler_chan().clone()).unwrap();
@@ -84,7 +92,7 @@
let dialog = SimpleDialogRequest::Prompt {
id: self.Document().embedder_controls().next_control_id(),
message: String::from(message),
-@@ -1235,8 +1258,16 @@
+@@ -1235,8 +1259,16 @@
default: String::from(default),
response_sender: sender,
};
@@ -102,7 +110,7 @@
// Step 6: Let userPromptHandler be WebDriver BiDi user prompt opened with this,
// "prompt", and message.
// TODO: Add support for WebDriver BiDi.
-@@ -1719,6 +1750,26 @@
+@@ -1719,6 +1751,26 @@
// https://html.spec.whatwg.org/multipage/#windoweventhandlers
window_event_handlers!();
@@ -129,7 +137,7 @@
///
fn Screen(&self, can_gc: CanGc) -> DomRoot {
self.screen.or_init(|| Screen::new(self, can_gc))
-@@ -3103,9 +3154,33 @@
+@@ -3103,9 +3155,33 @@
&self,
input_event: &ConstellationInputEvent,
) -> Option {
@@ -166,7 +174,7 @@
}
#[expect(unsafe_code)]
-@@ -3124,8 +3199,34 @@
+@@ -3124,8 +3200,34 @@
// SAFETY: This is safe because `Window::query_elements_from_point` has ensured that
// layout has run and any OpaqueNodes that no longer refer to real nodes are gone.
let address = UntrustedNodeAddress(result.node.0 as *const c_void);
@@ -202,7 +210,33 @@
cursor: result.cursor,
point_in_node: result.point_in_target,
point_in_frame,
-@@ -3687,6 +3788,8 @@
+@@ -3494,17 +3596,19 @@
+ }
+
+ pub(crate) fn send_to_embedder(&self, msg: EmbedderMsg) {
+- self.as_global_scope()
+- .script_to_embedder_chan()
+- .send(msg)
+- .unwrap();
++ if let Err(error) = self.as_global_scope().script_to_embedder_chan().send(msg) {
++ warn!("script→embedder send failed during teardown: {error:?}");
++ }
+ }
+
+ pub(crate) fn send_to_constellation(&self, msg: ScriptToConstellationMessage) {
+- self.as_global_scope()
++ if let Err(error) = self
++ .as_global_scope()
+ .script_to_constellation_chan()
+ .send(msg)
+- .unwrap();
++ {
++ warn!("script→constellation send failed during teardown: {error:?}");
++ }
+ }
+
+ #[cfg(feature = "webxr")]
+@@ -3687,6 +3791,8 @@
player_context: WindowGLContext,
#[cfg(feature = "webgpu")] gpu_id_hub: Arc,
inherited_secure_context: Option,
@@ -211,7 +245,7 @@
theme: Theme,
weak_script_thread: Weak,
) -> DomRoot {
-@@ -3713,6 +3816,8 @@
+@@ -3713,6 +3819,8 @@
gpu_id_hub,
inherited_secure_context,
unminify_js,
@@ -220,7 +254,7 @@
Some(font_context),
),
ongoing_navigation: Default::default(),
-@@ -3974,3 +4079,114 @@
+@@ -3974,3 +4082,114 @@
Self::create_named_properties_object(cx, proto, object)
}
}
diff --git a/patches/components/shared/net/lib.rs.patch b/patches/components/shared/net/lib.rs.patch
index 8d59bd4..1bb5315 100644
--- a/patches/components/shared/net/lib.rs.patch
+++ b/patches/components/shared/net/lib.rs.patch
@@ -96,3 +96,14 @@
}
#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
+@@ -894,7 +955,9 @@
+ ),
+ };
+
+- core_resource_thread.send(message).unwrap();
++ if let Err(error) = core_resource_thread.send(message) {
++ warn!("FetchThread send to core resource thread failed: {error:?}");
++ }
+
+ let preexisting_fetch =
+ self.active_fetches.insert(request_builder_id, callback);
diff --git a/patches/components/webdriver_server/lib.rs.patch b/patches/components/webdriver_server/lib.rs.patch
new file mode 100644
index 0000000..33cf864
--- /dev/null
+++ b/patches/components/webdriver_server/lib.rs.patch
@@ -0,0 +1,14 @@
+--- original
++++ modified
+@@ -145,7 +145,10 @@
+ thread::Builder::new()
+ .name("WebDriverHttpServer".to_owned())
+ .spawn(move || {
+- let address = SocketAddrV4::new("0.0.0.0".parse().unwrap(), port);
++ // Bind to loopback only since macOS in blocks non-loopback binds with EPERM
++ // unless the user has granted the "Local Network" permission, which
++ // child processes spawned by test runners don't get prompted for.
++ let address = SocketAddrV4::new("127.0.0.1".parse().unwrap(), port);
+ match server::start(
+ SocketAddr::V4(address),
+ vec![],