aboutsummaryrefslogtreecommitdiffstats
path: root/components/constellation/constellation.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/constellation/constellation.rs')
-rw-r--r--components/constellation/constellation.rs171
1 files changed, 73 insertions, 98 deletions
diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs
index 2f9345c416f..ad89c435717 100644
--- a/components/constellation/constellation.rs
+++ b/components/constellation/constellation.rs
@@ -115,9 +115,10 @@ use constellation_traits::{
AuxiliaryWebViewCreationRequest, AuxiliaryWebViewCreationResponse, BroadcastMsg, DocumentState,
EmbedderToConstellationMessage, IFrameLoadInfo, IFrameLoadInfoWithData, IFrameSandboxState,
IFrameSizeMsg, Job, LoadData, LoadOrigin, LogEntry, MessagePortMsg, NavigationHistoryBehavior,
- PaintMetricEvent, PortMessageTask, SWManagerMsg, SWManagerSenders, ScriptToConstellationChan,
- ScriptToConstellationMessage, ScrollState, ServiceWorkerManagerFactory, ServiceWorkerMsg,
- StructuredSerializedData, TraversalDirection, WindowSizeType,
+ PaintMetricEvent, PortMessageTask, PortTransferInfo, SWManagerMsg, SWManagerSenders,
+ ScriptToConstellationChan, ScriptToConstellationMessage, ScrollState,
+ ServiceWorkerManagerFactory, ServiceWorkerMsg, StructuredSerializedData, TraversalDirection,
+ WindowSizeType,
};
use crossbeam_channel::{Receiver, Select, Sender, unbounded};
use devtools_traits::{
@@ -202,9 +203,6 @@ enum TransferState {
/// While a completion failed, another global requested to complete the transfer.
/// We are still buffering messages, and awaiting the return of the buffer from the global who failed.
CompletionRequested(MessagePortRouterId, VecDeque<PortMessageTask>),
- /// The entangled port has been removed while the port was in-transfer,
- /// the current port should be removed as well once it is managed again.
- EntangledRemoved,
}
#[derive(Debug)]
@@ -1524,12 +1522,12 @@ where
ScriptToConstellationMessage::NewMessagePort(router_id, port_id) => {
self.handle_new_messageport(router_id, port_id);
},
- ScriptToConstellationMessage::RemoveMessagePort(port_id) => {
- self.handle_remove_messageport(port_id);
- },
ScriptToConstellationMessage::EntanglePorts(port1, port2) => {
self.handle_entangle_messageports(port1, port2);
},
+ ScriptToConstellationMessage::DisentanglePorts(port1, port2) => {
+ self.handle_disentangle_messageports(port1, port2);
+ },
ScriptToConstellationMessage::NewBroadcastChannelRouter(
router_id,
response_sender,
@@ -2117,17 +2115,6 @@ where
Entry::Occupied(entry) => entry,
};
match entry.get().state {
- TransferState::EntangledRemoved => {
- // If the entangled port has been removed while this one was in-transfer,
- // remove it now.
- if let Some(ipc_sender) = self.message_port_routers.get(&router_id) {
- let _ = ipc_sender.send(MessagePortMsg::RemoveMessagePort(port_id));
- } else {
- warn!("No message-port sender for {:?}", router_id);
- }
- entry.remove_entry();
- continue;
- },
TransferState::CompletionInProgress(expected_router_id) => {
// Here, the transfer was normally completed.
@@ -2151,9 +2138,9 @@ where
fn handle_message_port_transfer_failed(
&mut self,
- ports: HashMap<MessagePortId, VecDeque<PortMessageTask>>,
+ ports: HashMap<MessagePortId, PortTransferInfo>,
) {
- for (port_id, mut previous_buffer) in ports.into_iter() {
+ for (port_id, mut transfer_info) in ports.into_iter() {
let entry = match self.message_ports.remove(&port_id) {
None => {
warn!(
@@ -2165,11 +2152,6 @@ where
Some(entry) => entry,
};
let new_info = match entry.state {
- TransferState::EntangledRemoved => {
- // If the entangled port has been removed while this one was in-transfer,
- // just drop it.
- continue;
- },
TransferState::CompletionFailed(mut current_buffer) => {
// The transfer failed,
// and now the global has returned us the buffer we previously sent.
@@ -2177,7 +2159,7 @@ where
// Tasks in the previous buffer are older,
// hence need to be added to the front of the current one.
- while let Some(task) = previous_buffer.pop_back() {
+ while let Some(task) = transfer_info.port_message_queue.pop_back() {
current_buffer.push_front(task);
}
// Update the state to transfer-in-progress.
@@ -2196,7 +2178,7 @@ where
// Tasks in the previous buffer are older,
// hence need to be added to the front of the current one.
- while let Some(task) = previous_buffer.pop_back() {
+ while let Some(task) = transfer_info.port_message_queue.pop_back() {
current_buffer.push_front(task);
}
// Forward the buffered message-queue to complete the current transfer.
@@ -2204,7 +2186,10 @@ where
if ipc_sender
.send(MessagePortMsg::CompletePendingTransfer(
port_id,
- current_buffer,
+ PortTransferInfo {
+ port_message_queue: current_buffer,
+ disentangled: entry.entangled_with.is_none(),
+ },
))
.is_err()
{
@@ -2251,18 +2236,14 @@ where
Some(entry) => entry,
};
let new_info = match entry.state {
- TransferState::EntangledRemoved => {
- // If the entangled port has been removed while this one was in-transfer,
- // remove it now.
- if let Some(ipc_sender) = self.message_port_routers.get(&router_id) {
- let _ = ipc_sender.send(MessagePortMsg::RemoveMessagePort(port_id));
- } else {
- warn!("No message-port sender for {:?}", router_id);
- }
- continue;
- },
TransferState::TransferInProgress(buffer) => {
- response.insert(port_id, buffer);
+ response.insert(
+ port_id,
+ PortTransferInfo {
+ port_message_queue: buffer,
+ disentangled: entry.entangled_with.is_none(),
+ },
+ );
// If the port was in transfer, and a global is requesting completion,
// we note the start of the completion.
@@ -2341,10 +2322,6 @@ where
TransferState::TransferInProgress(queue) => queue.push_back(task),
TransferState::CompletionFailed(queue) => queue.push_back(task),
TransferState::CompletionRequested(_, queue) => queue.push_back(task),
- TransferState::EntangledRemoved => warn!(
- "Messageport received a message, but entangled has alread been removed {:?}",
- port_id
- ),
}
}
@@ -2410,59 +2387,6 @@ where
feature = "tracing",
tracing::instrument(skip_all, fields(servo_profiling = true), level = "trace")
)]
- fn handle_remove_messageport(&mut self, port_id: MessagePortId) {
- let entangled = match self.message_ports.remove(&port_id) {
- Some(info) => info.entangled_with,
- None => {
- return warn!(
- "Constellation asked to remove unknown messageport {:?}",
- port_id
- );
- },
- };
- let entangled_id = match entangled {
- Some(id) => id,
- None => return,
- };
- let info = match self.message_ports.get_mut(&entangled_id) {
- Some(info) => info,
- None => {
- return warn!(
- "Constellation asked to remove unknown entangled messageport {:?}",
- entangled_id
- );
- },
- };
- let router_id = match info.state {
- TransferState::EntangledRemoved => {
- return warn!(
- "Constellation asked to remove entangled messageport by a port that was already removed {:?}",
- port_id
- );
- },
- TransferState::TransferInProgress(_) |
- TransferState::CompletionInProgress(_) |
- TransferState::CompletionFailed(_) |
- TransferState::CompletionRequested(_, _) => {
- // Note: since the port is in-transer, we don't have a router to send it a message
- // to let it know that its entangled port has been removed.
- // Hence we mark it so that it will be messaged and removed once the transfer completes.
- info.state = TransferState::EntangledRemoved;
- return;
- },
- TransferState::Managed(router_id) => router_id,
- };
- if let Some(sender) = self.message_port_routers.get(&router_id) {
- let _ = sender.send(MessagePortMsg::RemoveMessagePort(entangled_id));
- } else {
- warn!("No message-port sender for {:?}", router_id);
- }
- }
-
- #[cfg_attr(
- feature = "tracing",
- tracing::instrument(skip_all, fields(servo_profiling = true), level = "trace")
- )]
fn handle_entangle_messageports(&mut self, port1: MessagePortId, port2: MessagePortId) {
if let Some(info) = self.message_ports.get_mut(&port1) {
info.entangled_with = Some(port2);
@@ -2482,6 +2406,57 @@ where
}
}
+ #[cfg_attr(
+ feature = "tracing",
+ tracing::instrument(skip_all, fields(servo_profiling = true), level = "trace")
+ )]
+ /// <https://html.spec.whatwg.org/multipage/#disentangle>
+ fn handle_disentangle_messageports(
+ &mut self,
+ port1: MessagePortId,
+ port2: Option<MessagePortId>,
+ ) {
+ // Disentangle initiatorPort and otherPort,
+ // so that they are no longer entangled or associated with each other.
+ // Note: If `port2` is some, then this is the first message
+ // and `port1` is the initiatorPort, `port2` is the otherPort.
+ // We can immediately remove the initiator.
+ let _ = self.message_ports.remove(&port1);
+
+ // Note: the none case is when otherPort sent this message
+ // in response to completing its own local disentanglement.
+ let Some(port2) = port2 else {
+ return;
+ };
+
+ // Start disentanglement of the other port.
+ if let Some(info) = self.message_ports.get_mut(&port2) {
+ info.entangled_with = None;
+ match &mut info.state {
+ TransferState::Managed(router_id) |
+ TransferState::CompletionInProgress(router_id) => {
+ // We try to disentangle the other port now,
+ // and if it has been transfered out by the time the message is received,
+ // it will be ignored,
+ // and disentanglement will be completed as part of the transfer.
+ if let Some(ipc_sender) = self.message_port_routers.get(router_id) {
+ let _ = ipc_sender.send(MessagePortMsg::CompleteDisentanglement(port2));
+ } else {
+ warn!("No message-port sender for {:?}", router_id);
+ }
+ },
+ _ => {
+ // Note: the port is in transfer, disentanglement will complete along with it.
+ },
+ }
+ } else {
+ warn!(
+ "Constellation asked to disentangle unknown messageport: {:?}",
+ port2
+ );
+ }
+ }
+
/// <https://w3c.github.io/ServiceWorker/#schedule-job-algorithm>
/// and
/// <https://w3c.github.io/ServiceWorker/#dfn-job-queue>