mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
Auto merge of #23637 - gterzian:continue-message-port, r=jdm
Continue message port <!-- Please describe your changes on the following line: --> Fixes #7457. Fixes #12715. Fixes #12717. Fixes #16095. Fixes #18969. --- <!-- 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. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/23637) <!-- Reviewable:end -->
This commit is contained in:
commit
a905916ede
113 changed files with 2792 additions and 787 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -3154,6 +3154,7 @@ dependencies = [
|
||||||
"malloc_size_of_derive",
|
"malloc_size_of_derive",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"serde",
|
"serde",
|
||||||
|
"servo_url",
|
||||||
"size_of_test",
|
"size_of_test",
|
||||||
"webrender_api",
|
"webrender_api",
|
||||||
]
|
]
|
||||||
|
@ -4134,6 +4135,7 @@ dependencies = [
|
||||||
"app_units",
|
"app_units",
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"base64",
|
"base64",
|
||||||
|
"bincode",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"bluetooth_traits",
|
"bluetooth_traits",
|
||||||
"canvas_traits",
|
"canvas_traits",
|
||||||
|
|
|
@ -57,6 +57,7 @@ loadend
|
||||||
loadstart
|
loadstart
|
||||||
message
|
message
|
||||||
message
|
message
|
||||||
|
messageerror
|
||||||
monospace
|
monospace
|
||||||
month
|
month
|
||||||
mousedown
|
mousedown
|
||||||
|
|
|
@ -130,7 +130,8 @@ use msg::constellation_msg::{
|
||||||
TopLevelBrowsingContextId,
|
TopLevelBrowsingContextId,
|
||||||
};
|
};
|
||||||
use msg::constellation_msg::{
|
use msg::constellation_msg::{
|
||||||
PipelineNamespace, PipelineNamespaceId, PipelineNamespaceRequest, TraversalDirection,
|
MessagePortId, MessagePortRouterId, PipelineNamespace, PipelineNamespaceId,
|
||||||
|
PipelineNamespaceRequest, TraversalDirection,
|
||||||
};
|
};
|
||||||
use net_traits::pub_domains::reg_host;
|
use net_traits::pub_domains::reg_host;
|
||||||
use net_traits::request::RequestBuilder;
|
use net_traits::request::RequestBuilder;
|
||||||
|
@ -153,6 +154,7 @@ use script_traits::{
|
||||||
IFrameLoadInfo, IFrameLoadInfoWithData, IFrameSandboxState, TimerSchedulerMsg,
|
IFrameLoadInfo, IFrameLoadInfoWithData, IFrameSandboxState, TimerSchedulerMsg,
|
||||||
};
|
};
|
||||||
use script_traits::{LayoutMsg as FromLayoutMsg, ScriptMsg as FromScriptMsg, ScriptThreadFactory};
|
use script_traits::{LayoutMsg as FromLayoutMsg, ScriptMsg as FromScriptMsg, ScriptThreadFactory};
|
||||||
|
use script_traits::{MessagePortMsg, PortMessageTask, StructuredSerializedData};
|
||||||
use script_traits::{SWManagerMsg, ScopeThings, UpdatePipelineIdReason, WebDriverCommandMsg};
|
use script_traits::{SWManagerMsg, ScopeThings, UpdatePipelineIdReason, WebDriverCommandMsg};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use servo_config::{opts, pref};
|
use servo_config::{opts, pref};
|
||||||
|
@ -175,6 +177,30 @@ use webvr_traits::{WebVREvent, WebVRMsg};
|
||||||
|
|
||||||
type PendingApprovalNavigations = HashMap<PipelineId, (LoadData, HistoryEntryReplacement)>;
|
type PendingApprovalNavigations = HashMap<PipelineId, (LoadData, HistoryEntryReplacement)>;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
/// The state used by MessagePortInfo to represent the various states the port can be in.
|
||||||
|
enum TransferState {
|
||||||
|
/// The port is currently managed by a given global,
|
||||||
|
/// identified by its router id.
|
||||||
|
Managed(MessagePortRouterId),
|
||||||
|
/// The port is currently in-transfer,
|
||||||
|
/// and incoming tasks should be buffered until it becomes managed again.
|
||||||
|
TransferInProgress(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)]
|
||||||
|
/// Info related to a message-port tracked by the constellation.
|
||||||
|
struct MessagePortInfo {
|
||||||
|
/// The current state of the messageport.
|
||||||
|
state: TransferState,
|
||||||
|
|
||||||
|
/// The id of the entangled port, if any.
|
||||||
|
entangled_with: Option<MessagePortId>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Servo supports tabs (referred to as browsers), so `Constellation` needs to
|
/// Servo supports tabs (referred to as browsers), so `Constellation` needs to
|
||||||
/// store browser specific data for bookkeeping.
|
/// store browser specific data for bookkeeping.
|
||||||
struct Browser {
|
struct Browser {
|
||||||
|
@ -340,6 +366,12 @@ pub struct Constellation<Message, LTF, STF> {
|
||||||
/// WebRender thread.
|
/// WebRender thread.
|
||||||
webrender_api_sender: webrender_api::RenderApiSender,
|
webrender_api_sender: webrender_api::RenderApiSender,
|
||||||
|
|
||||||
|
/// A map of message-port Id to info.
|
||||||
|
message_ports: HashMap<MessagePortId, MessagePortInfo>,
|
||||||
|
|
||||||
|
/// A map of router-id to ipc-sender, to route messages to ports.
|
||||||
|
message_port_routers: HashMap<MessagePortRouterId, IpcSender<MessagePortMsg>>,
|
||||||
|
|
||||||
/// The set of all the pipelines in the browser. (See the `pipeline` module
|
/// The set of all the pipelines in the browser. (See the `pipeline` module
|
||||||
/// for more details.)
|
/// for more details.)
|
||||||
pipelines: HashMap<PipelineId, Pipeline>,
|
pipelines: HashMap<PipelineId, Pipeline>,
|
||||||
|
@ -751,6 +783,8 @@ where
|
||||||
swmanager_sender: sw_mgr_clone,
|
swmanager_sender: sw_mgr_clone,
|
||||||
browsing_context_group_set: Default::default(),
|
browsing_context_group_set: Default::default(),
|
||||||
browsing_context_group_next_id: Default::default(),
|
browsing_context_group_next_id: Default::default(),
|
||||||
|
message_ports: HashMap::new(),
|
||||||
|
message_port_routers: HashMap::new(),
|
||||||
pipelines: HashMap::new(),
|
pipelines: HashMap::new(),
|
||||||
browsing_contexts: HashMap::new(),
|
browsing_contexts: HashMap::new(),
|
||||||
pending_changes: vec![],
|
pending_changes: vec![],
|
||||||
|
@ -1487,6 +1521,27 @@ where
|
||||||
};
|
};
|
||||||
|
|
||||||
match content {
|
match content {
|
||||||
|
FromScriptMsg::RerouteMessagePort(port_id, task) => {
|
||||||
|
self.handle_reroute_messageport(port_id, task);
|
||||||
|
},
|
||||||
|
FromScriptMsg::MessagePortShipped(port_id) => {
|
||||||
|
self.handle_messageport_shipped(port_id);
|
||||||
|
},
|
||||||
|
FromScriptMsg::NewMessagePortRouter(router_id, ipc_sender) => {
|
||||||
|
self.handle_new_messageport_router(router_id, ipc_sender);
|
||||||
|
},
|
||||||
|
FromScriptMsg::RemoveMessagePortRouter(router_id) => {
|
||||||
|
self.handle_remove_messageport_router(router_id);
|
||||||
|
},
|
||||||
|
FromScriptMsg::NewMessagePort(router_id, port_id) => {
|
||||||
|
self.handle_new_messageport(router_id, port_id);
|
||||||
|
},
|
||||||
|
FromScriptMsg::RemoveMessagePort(port_id) => {
|
||||||
|
self.handle_remove_messageport(port_id);
|
||||||
|
},
|
||||||
|
FromScriptMsg::EntanglePorts(port1, port2) => {
|
||||||
|
self.handle_entangle_messageports(port1, port2);
|
||||||
|
},
|
||||||
FromScriptMsg::ForwardToEmbedder(embedder_msg) => {
|
FromScriptMsg::ForwardToEmbedder(embedder_msg) => {
|
||||||
self.embedder_proxy
|
self.embedder_proxy
|
||||||
.send((Some(source_top_ctx_id), embedder_msg));
|
.send((Some(source_top_ctx_id), embedder_msg));
|
||||||
|
@ -1563,9 +1618,16 @@ where
|
||||||
target: browsing_context_id,
|
target: browsing_context_id,
|
||||||
source: source_pipeline_id,
|
source: source_pipeline_id,
|
||||||
target_origin: origin,
|
target_origin: origin,
|
||||||
|
source_origin,
|
||||||
data,
|
data,
|
||||||
} => {
|
} => {
|
||||||
self.handle_post_message_msg(browsing_context_id, source_pipeline_id, origin, data);
|
self.handle_post_message_msg(
|
||||||
|
browsing_context_id,
|
||||||
|
source_pipeline_id,
|
||||||
|
origin,
|
||||||
|
source_origin,
|
||||||
|
data,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
FromScriptMsg::Focus => {
|
FromScriptMsg::Focus => {
|
||||||
self.handle_focus_msg(source_pipeline_id);
|
self.handle_focus_msg(source_pipeline_id);
|
||||||
|
@ -1685,6 +1747,163 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_reroute_messageport(&mut self, port_id: MessagePortId, task: PortMessageTask) {
|
||||||
|
let info = match self.message_ports.get_mut(&port_id) {
|
||||||
|
Some(info) => info,
|
||||||
|
None => {
|
||||||
|
return warn!(
|
||||||
|
"Constellation asked to re-route msg to unknown messageport {:?}",
|
||||||
|
port_id
|
||||||
|
)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
match &mut info.state {
|
||||||
|
TransferState::Managed(router_id) => {
|
||||||
|
if let Some(sender) = self.message_port_routers.get(&router_id) {
|
||||||
|
let _ = sender.send(MessagePortMsg::NewTask(port_id, task));
|
||||||
|
} else {
|
||||||
|
warn!("No message-port sender for {:?}", router_id);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
TransferState::TransferInProgress(queue) => queue.push_back(task),
|
||||||
|
TransferState::EntangledRemoved => warn!(
|
||||||
|
"Messageport received a message, but entangled has alread been removed {:?}",
|
||||||
|
port_id
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_messageport_shipped(&mut self, port_id: MessagePortId) {
|
||||||
|
if let Some(info) = self.message_ports.get_mut(&port_id) {
|
||||||
|
if let TransferState::Managed(_) = info.state {
|
||||||
|
info.state = TransferState::TransferInProgress(VecDeque::new());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warn!(
|
||||||
|
"Constellation asked to mark unknown messageport as shipped {:?}",
|
||||||
|
port_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_new_messageport_router(
|
||||||
|
&mut self,
|
||||||
|
router_id: MessagePortRouterId,
|
||||||
|
control_sender: IpcSender<MessagePortMsg>,
|
||||||
|
) {
|
||||||
|
self.message_port_routers.insert(router_id, control_sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_remove_messageport_router(&mut self, router_id: MessagePortRouterId) {
|
||||||
|
self.message_port_routers.remove(&router_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_new_messageport(&mut self, router_id: MessagePortRouterId, port_id: MessagePortId) {
|
||||||
|
match self.message_ports.entry(port_id) {
|
||||||
|
// If we know about this port, it means it was transferred.
|
||||||
|
Entry::Occupied(mut entry) => {
|
||||||
|
if let TransferState::EntangledRemoved = entry.get().state {
|
||||||
|
// If the entangled port has been removed while this one was in-transfer,
|
||||||
|
// remove it now.
|
||||||
|
if let Some(sender) = self.message_port_routers.get(&router_id) {
|
||||||
|
let _ = sender.send(MessagePortMsg::RemoveMessagePort(port_id));
|
||||||
|
} else {
|
||||||
|
warn!("No message-port sender for {:?}", router_id);
|
||||||
|
}
|
||||||
|
entry.remove_entry();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let new_info = MessagePortInfo {
|
||||||
|
state: TransferState::Managed(router_id),
|
||||||
|
entangled_with: entry.get().entangled_with.clone(),
|
||||||
|
};
|
||||||
|
let old_info = entry.insert(new_info);
|
||||||
|
let buffer = match old_info.state {
|
||||||
|
TransferState::TransferInProgress(buffer) => buffer,
|
||||||
|
_ => {
|
||||||
|
return warn!("Completing transfer of a port that did not have a transfer in progress.");
|
||||||
|
},
|
||||||
|
};
|
||||||
|
// Forward the buffered message-queue.
|
||||||
|
if let Some(sender) = self.message_port_routers.get(&router_id) {
|
||||||
|
let _ = sender.send(MessagePortMsg::CompleteTransfer(port_id.clone(), buffer));
|
||||||
|
} else {
|
||||||
|
warn!("No message-port sender for {:?}", router_id);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Entry::Vacant(entry) => {
|
||||||
|
let info = MessagePortInfo {
|
||||||
|
state: TransferState::Managed(router_id),
|
||||||
|
entangled_with: None,
|
||||||
|
};
|
||||||
|
entry.insert(info);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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(_) => {
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
} else {
|
||||||
|
warn!(
|
||||||
|
"Constellation asked to entangle unknow messageport: {:?}",
|
||||||
|
port1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if let Some(info) = self.message_ports.get_mut(&port2) {
|
||||||
|
info.entangled_with = Some(port1);
|
||||||
|
} else {
|
||||||
|
warn!(
|
||||||
|
"Constellation asked to entangle unknow messageport: {:?}",
|
||||||
|
port2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_register_serviceworker(&self, scope_things: ScopeThings, scope: ServoUrl) {
|
fn handle_register_serviceworker(&self, scope_things: ScopeThings, scope: ServoUrl) {
|
||||||
if let Some(ref mgr) = self.swmanager_chan {
|
if let Some(ref mgr) = self.swmanager_chan {
|
||||||
let _ = mgr.send(ServiceWorkerMsg::RegisterServiceWorker(scope_things, scope));
|
let _ = mgr.send(ServiceWorkerMsg::RegisterServiceWorker(scope_things, scope));
|
||||||
|
@ -3203,7 +3422,8 @@ where
|
||||||
browsing_context_id: BrowsingContextId,
|
browsing_context_id: BrowsingContextId,
|
||||||
source_pipeline: PipelineId,
|
source_pipeline: PipelineId,
|
||||||
origin: Option<ImmutableOrigin>,
|
origin: Option<ImmutableOrigin>,
|
||||||
data: Vec<u8>,
|
source_origin: ImmutableOrigin,
|
||||||
|
data: StructuredSerializedData,
|
||||||
) {
|
) {
|
||||||
let pipeline_id = match self.browsing_contexts.get(&browsing_context_id) {
|
let pipeline_id = match self.browsing_contexts.get(&browsing_context_id) {
|
||||||
None => {
|
None => {
|
||||||
|
@ -3223,6 +3443,7 @@ where
|
||||||
source: source_pipeline,
|
source: source_pipeline,
|
||||||
source_browsing_context: source_browsing_context,
|
source_browsing_context: source_browsing_context,
|
||||||
target_origin: origin,
|
target_origin: origin,
|
||||||
|
source_origin,
|
||||||
data,
|
data,
|
||||||
};
|
};
|
||||||
let result = match self.pipelines.get(&pipeline_id) {
|
let result = match self.pipelines.get(&pipeline_id) {
|
||||||
|
|
|
@ -19,6 +19,7 @@ malloc_size_of = { path = "../malloc_size_of" }
|
||||||
malloc_size_of_derive = "0.1"
|
malloc_size_of_derive = "0.1"
|
||||||
parking_lot = "0.9"
|
parking_lot = "0.9"
|
||||||
serde = "1.0.60"
|
serde = "1.0.60"
|
||||||
|
servo_url = {path = "../url"}
|
||||||
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
|
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
@ -156,6 +156,20 @@ impl PipelineNamespace {
|
||||||
index: HistoryStateIndex(self.next_index()),
|
index: HistoryStateIndex(self.next_index()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn next_message_port_id(&mut self) -> MessagePortId {
|
||||||
|
MessagePortId {
|
||||||
|
namespace_id: self.id,
|
||||||
|
index: MessagePortIndex(self.next_index()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_message_port_router_id(&mut self) -> MessagePortRouterId {
|
||||||
|
MessagePortRouterId {
|
||||||
|
namespace_id: self.id,
|
||||||
|
index: MessagePortRouterIndex(self.next_index()),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_local!(pub static PIPELINE_NAMESPACE: Cell<Option<PipelineNamespace>> = Cell::new(None));
|
thread_local!(pub static PIPELINE_NAMESPACE: Cell<Option<PipelineNamespace>> = Cell::new(None));
|
||||||
|
@ -297,6 +311,68 @@ impl PartialEq<BrowsingContextId> for TopLevelBrowsingContextId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
|
||||||
|
pub struct MessagePortIndex(pub NonZeroU32);
|
||||||
|
malloc_size_of_is_0!(MessagePortIndex);
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd, Serialize,
|
||||||
|
)]
|
||||||
|
pub struct MessagePortId {
|
||||||
|
pub namespace_id: PipelineNamespaceId,
|
||||||
|
pub index: MessagePortIndex,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessagePortId {
|
||||||
|
pub fn new() -> MessagePortId {
|
||||||
|
PIPELINE_NAMESPACE.with(|tls| {
|
||||||
|
let mut namespace = tls.get().expect("No namespace set for this thread!");
|
||||||
|
let next_message_port_id = namespace.next_message_port_id();
|
||||||
|
tls.set(Some(namespace));
|
||||||
|
next_message_port_id
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for MessagePortId {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
let PipelineNamespaceId(namespace_id) = self.namespace_id;
|
||||||
|
let MessagePortIndex(index) = self.index;
|
||||||
|
write!(fmt, "({},{})", namespace_id, index.get())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
|
||||||
|
pub struct MessagePortRouterIndex(pub NonZeroU32);
|
||||||
|
malloc_size_of_is_0!(MessagePortRouterIndex);
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd, Serialize,
|
||||||
|
)]
|
||||||
|
pub struct MessagePortRouterId {
|
||||||
|
pub namespace_id: PipelineNamespaceId,
|
||||||
|
pub index: MessagePortRouterIndex,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessagePortRouterId {
|
||||||
|
pub fn new() -> MessagePortRouterId {
|
||||||
|
PIPELINE_NAMESPACE.with(|tls| {
|
||||||
|
let mut namespace = tls.get().expect("No namespace set for this thread!");
|
||||||
|
let next_message_port_router_id = namespace.next_message_port_router_id();
|
||||||
|
tls.set(Some(namespace));
|
||||||
|
next_message_port_router_id
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for MessagePortRouterId {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
let PipelineNamespaceId(namespace_id) = self.namespace_id;
|
||||||
|
let MessagePortRouterIndex(index) = self.index;
|
||||||
|
write!(fmt, "({},{})", namespace_id, index.get())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
|
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
|
||||||
pub struct HistoryStateIndex(pub NonZeroU32);
|
pub struct HistoryStateIndex(pub NonZeroU32);
|
||||||
malloc_size_of_is_0!(HistoryStateIndex);
|
malloc_size_of_is_0!(HistoryStateIndex);
|
||||||
|
@ -419,6 +495,7 @@ pub enum ScriptHangAnnotation {
|
||||||
ExitFullscreen,
|
ExitFullscreen,
|
||||||
WebVREvent,
|
WebVREvent,
|
||||||
PerformanceTimelineTask,
|
PerformanceTimelineTask,
|
||||||
|
PortMessage,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||||
|
|
|
@ -301,9 +301,9 @@ impl ResourceChannelManager {
|
||||||
.send(history_states.get(&history_state_id).cloned())
|
.send(history_states.get(&history_state_id).cloned())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
},
|
},
|
||||||
CoreResourceMsg::SetHistoryState(history_state_id, history_state) => {
|
CoreResourceMsg::SetHistoryState(history_state_id, structured_data) => {
|
||||||
let mut history_states = http_state.history_states.write().unwrap();
|
let mut history_states = http_state.history_states.write().unwrap();
|
||||||
history_states.insert(history_state_id, history_state);
|
history_states.insert(history_state_id, structured_data);
|
||||||
},
|
},
|
||||||
CoreResourceMsg::RemoveHistoryStates(states_to_remove) => {
|
CoreResourceMsg::RemoveHistoryStates(states_to_remove) => {
|
||||||
let mut history_states = http_state.history_states.write().unwrap();
|
let mut history_states = http_state.history_states.write().unwrap();
|
||||||
|
|
|
@ -136,6 +136,7 @@ impl Formattable for ProfilerCategory {
|
||||||
ProfilerCategory::ScriptParseHTML => "Script Parse HTML",
|
ProfilerCategory::ScriptParseHTML => "Script Parse HTML",
|
||||||
ProfilerCategory::ScriptParseXML => "Script Parse XML",
|
ProfilerCategory::ScriptParseXML => "Script Parse XML",
|
||||||
ProfilerCategory::ScriptPlannedNavigation => "Script Planned Navigation",
|
ProfilerCategory::ScriptPlannedNavigation => "Script Planned Navigation",
|
||||||
|
ProfilerCategory::ScriptPortMessage => "Script Port Message",
|
||||||
ProfilerCategory::ScriptResize => "Script Resize",
|
ProfilerCategory::ScriptResize => "Script Resize",
|
||||||
ProfilerCategory::ScriptEvent => "Script Event",
|
ProfilerCategory::ScriptEvent => "Script Event",
|
||||||
ProfilerCategory::ScriptUpdateReplacedElement => "Script Update Replaced Element",
|
ProfilerCategory::ScriptUpdateReplacedElement => "Script Update Replaced Element",
|
||||||
|
|
|
@ -108,6 +108,7 @@ pub enum ProfilerCategory {
|
||||||
ScriptWorkletEvent = 0x7a,
|
ScriptWorkletEvent = 0x7a,
|
||||||
ScriptPerformanceEvent = 0x7b,
|
ScriptPerformanceEvent = 0x7b,
|
||||||
ScriptHistoryEvent = 0x7c,
|
ScriptHistoryEvent = 0x7c,
|
||||||
|
ScriptPortMessage = 0x7d,
|
||||||
TimeToFirstPaint = 0x80,
|
TimeToFirstPaint = 0x80,
|
||||||
TimeToFirstContentfulPaint = 0x81,
|
TimeToFirstContentfulPaint = 0x81,
|
||||||
TimeToInteractive = 0x82,
|
TimeToInteractive = 0x82,
|
||||||
|
|
|
@ -34,6 +34,7 @@ tinyfiledialogs = "3.0"
|
||||||
app_units = "0.7"
|
app_units = "0.7"
|
||||||
backtrace = {version = "0.3", optional = true}
|
backtrace = {version = "0.3", optional = true}
|
||||||
base64 = "0.10.1"
|
base64 = "0.10.1"
|
||||||
|
bincode = "1"
|
||||||
bitflags = "1.0"
|
bitflags = "1.0"
|
||||||
bluetooth_traits = {path = "../bluetooth_traits"}
|
bluetooth_traits = {path = "../bluetooth_traits"}
|
||||||
canvas_traits = {path = "../canvas_traits"}
|
canvas_traits = {path = "../canvas_traits"}
|
||||||
|
|
|
@ -4,15 +4,19 @@
|
||||||
|
|
||||||
use crate::dom::bindings::refcounted::Trusted;
|
use crate::dom::bindings::refcounted::Trusted;
|
||||||
use crate::dom::bindings::reflector::DomObject;
|
use crate::dom::bindings::reflector::DomObject;
|
||||||
use crate::dom::bindings::structuredclone::StructuredCloneData;
|
|
||||||
use crate::script_runtime::CommonScriptMsg;
|
use crate::script_runtime::CommonScriptMsg;
|
||||||
|
use script_traits::StructuredSerializedData;
|
||||||
|
use servo_url::ImmutableOrigin;
|
||||||
|
|
||||||
/// Messages used to control the worker event loops
|
/// Messages used to control the worker event loops
|
||||||
pub enum WorkerScriptMsg {
|
pub enum WorkerScriptMsg {
|
||||||
/// Common variants associated with the script messages
|
/// Common variants associated with the script messages
|
||||||
Common(CommonScriptMsg),
|
Common(CommonScriptMsg),
|
||||||
/// Message sent through Worker.postMessage
|
/// Message sent through Worker.postMessage
|
||||||
DOMMessage(StructuredCloneData),
|
DOMMessage {
|
||||||
|
origin: ImmutableOrigin,
|
||||||
|
data: StructuredSerializedData,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SimpleWorkerErrorHandler<T: DomObject> {
|
pub struct SimpleWorkerErrorHandler<T: DomObject> {
|
||||||
|
|
|
@ -75,7 +75,7 @@ impl ScriptPort for Receiver<DedicatedWorkerScriptMsg> {
|
||||||
};
|
};
|
||||||
match common_msg {
|
match common_msg {
|
||||||
WorkerScriptMsg::Common(script_msg) => Ok(script_msg),
|
WorkerScriptMsg::Common(script_msg) => Ok(script_msg),
|
||||||
WorkerScriptMsg::DOMMessage(_) => panic!("unexpected worker event message!"),
|
WorkerScriptMsg::DOMMessage { .. } => panic!("unexpected worker event message!"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,4 +155,7 @@ pub fn run_worker_event_loop<T, TimerMsg, WorkerMsg, Event>(
|
||||||
.upcast::<GlobalScope>()
|
.upcast::<GlobalScope>()
|
||||||
.perform_a_microtask_checkpoint();
|
.perform_a_microtask_checkpoint();
|
||||||
}
|
}
|
||||||
|
worker_scope
|
||||||
|
.upcast::<GlobalScope>()
|
||||||
|
.perform_a_message_port_garbage_collection_checkpoint();
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,10 @@ DOMInterfaces = {
|
||||||
'weakReferenceable': True,
|
'weakReferenceable': True,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'MessagePort': {
|
||||||
|
'weakReferenceable': True,
|
||||||
|
},
|
||||||
|
|
||||||
#FIXME(jdm): This should be 'register': False, but then we don't generate enum types
|
#FIXME(jdm): This should be 'register': False, but then we don't generate enum types
|
||||||
'TestBinding': {
|
'TestBinding': {
|
||||||
'inCompartments': ['PromiseAttribute', 'PromiseNativeHandler'],
|
'inCompartments': ['PromiseAttribute', 'PromiseNativeHandler'],
|
||||||
|
|
|
@ -154,6 +154,7 @@ pub mod settings_stack;
|
||||||
pub mod str;
|
pub mod str;
|
||||||
pub mod structuredclone;
|
pub mod structuredclone;
|
||||||
pub mod trace;
|
pub mod trace;
|
||||||
|
pub mod transferable;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
pub mod weakref;
|
pub mod weakref;
|
||||||
pub mod xmlname;
|
pub mod xmlname;
|
||||||
|
|
|
@ -6,12 +6,15 @@
|
||||||
//! (https://html.spec.whatwg.org/multipage/#safe-passing-of-structured-data).
|
//! (https://html.spec.whatwg.org/multipage/#safe-passing-of-structured-data).
|
||||||
|
|
||||||
use crate::compartments::enter_realm;
|
use crate::compartments::enter_realm;
|
||||||
use crate::dom::bindings::conversions::root_from_handleobject;
|
use crate::dom::bindings::conversions::{root_from_object, ToJSValConvertible};
|
||||||
use crate::dom::bindings::error::{Error, Fallible};
|
use crate::dom::bindings::error::{Error, Fallible};
|
||||||
use crate::dom::bindings::reflector::DomObject;
|
use crate::dom::bindings::reflector::DomObject;
|
||||||
use crate::dom::bindings::root::DomRoot;
|
use crate::dom::bindings::root::DomRoot;
|
||||||
|
use crate::dom::bindings::transferable::Transferable;
|
||||||
use crate::dom::blob::{Blob, BlobImpl};
|
use crate::dom::blob::{Blob, BlobImpl};
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::dom::messageport::MessagePort;
|
||||||
|
use crate::script_runtime::JSContext as SafeJSContext;
|
||||||
use js::glue::CopyJSStructuredCloneData;
|
use js::glue::CopyJSStructuredCloneData;
|
||||||
use js::glue::DeleteJSAutoStructuredCloneBuffer;
|
use js::glue::DeleteJSAutoStructuredCloneBuffer;
|
||||||
use js::glue::GetLengthOfJSStructuredCloneData;
|
use js::glue::GetLengthOfJSStructuredCloneData;
|
||||||
|
@ -28,12 +31,15 @@ use js::jsapi::{JSObject, JS_ClearPendingException};
|
||||||
use js::jsapi::{JSStructuredCloneCallbacks, JSStructuredCloneReader, JSStructuredCloneWriter};
|
use js::jsapi::{JSStructuredCloneCallbacks, JSStructuredCloneReader, JSStructuredCloneWriter};
|
||||||
use js::jsapi::{JS_ReadBytes, JS_WriteBytes};
|
use js::jsapi::{JS_ReadBytes, JS_WriteBytes};
|
||||||
use js::jsapi::{JS_ReadUint32Pair, JS_WriteUint32Pair};
|
use js::jsapi::{JS_ReadUint32Pair, JS_WriteUint32Pair};
|
||||||
|
use js::jsval::UndefinedValue;
|
||||||
use js::rust::wrappers::{JS_ReadStructuredClone, JS_WriteStructuredClone};
|
use js::rust::wrappers::{JS_ReadStructuredClone, JS_WriteStructuredClone};
|
||||||
use js::rust::{Handle, HandleValue, MutableHandleValue};
|
use js::rust::{CustomAutoRooterGuard, HandleValue, MutableHandleValue};
|
||||||
use libc::size_t;
|
use msg::constellation_msg::MessagePortId;
|
||||||
|
use script_traits::transferable::MessagePortImpl;
|
||||||
|
use script_traits::StructuredSerializedData;
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::os::raw;
|
use std::os::raw;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::slice;
|
|
||||||
|
|
||||||
// TODO: Should we add Min and Max const to https://github.com/servo/rust-mozjs/blob/master/src/consts.rs?
|
// TODO: Should we add Min and Max const to https://github.com/servo/rust-mozjs/blob/master/src/consts.rs?
|
||||||
// TODO: Determine for sure which value Min and Max should have.
|
// TODO: Determine for sure which value Min and Max should have.
|
||||||
|
@ -44,6 +50,7 @@ enum StructuredCloneTags {
|
||||||
/// To support additional types, add new tags with values incremented from the last one before Max.
|
/// To support additional types, add new tags with values incremented from the last one before Max.
|
||||||
Min = 0xFFFF8000,
|
Min = 0xFFFF8000,
|
||||||
DomBlob = 0xFFFF8001,
|
DomBlob = 0xFFFF8001,
|
||||||
|
MessagePort = 0xFFFF8002,
|
||||||
Max = 0xFFFFFFFF,
|
Max = 0xFFFFFFFF,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,19 +133,24 @@ impl StructuredCloneReader {
|
||||||
unsafe fn read_blob(
|
unsafe fn read_blob(
|
||||||
cx: *mut JSContext,
|
cx: *mut JSContext,
|
||||||
r: *mut JSStructuredCloneReader,
|
r: *mut JSStructuredCloneReader,
|
||||||
sc_holder: &mut StructuredCloneHolder,
|
sc_holder: &mut StructuredDataHolder,
|
||||||
) -> *mut JSObject {
|
) -> *mut JSObject {
|
||||||
let structured_reader = StructuredCloneReader { r: r };
|
let structured_reader = StructuredCloneReader { r: r };
|
||||||
let blob_buffer = structured_reader.read_bytes();
|
let blob_buffer = structured_reader.read_bytes();
|
||||||
let type_str = structured_reader.read_str();
|
let type_str = structured_reader.read_str();
|
||||||
let target_global = GlobalScope::from_context(cx);
|
let target_global = GlobalScope::from_context(cx);
|
||||||
let blob = Blob::new(
|
let read_blob = Blob::new(
|
||||||
&target_global,
|
&target_global,
|
||||||
BlobImpl::new_from_bytes(blob_buffer),
|
BlobImpl::new_from_bytes(blob_buffer),
|
||||||
type_str,
|
type_str,
|
||||||
);
|
);
|
||||||
let js_object = blob.reflector().get_jsobject().get();
|
let js_object = read_blob.reflector().get_jsobject().get();
|
||||||
sc_holder.blob = Some(blob);
|
match sc_holder {
|
||||||
|
StructuredDataHolder::Read { blob, .. } => {
|
||||||
|
*blob = Some(read_blob);
|
||||||
|
},
|
||||||
|
_ => panic!("Unexpected variant of StructuredDataHolder"),
|
||||||
|
}
|
||||||
js_object
|
js_object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +183,7 @@ unsafe extern "C" fn read_callback(
|
||||||
"tag should be higher than StructuredCloneTags::Min"
|
"tag should be higher than StructuredCloneTags::Min"
|
||||||
);
|
);
|
||||||
if tag == StructuredCloneTags::DomBlob as u32 {
|
if tag == StructuredCloneTags::DomBlob as u32 {
|
||||||
return read_blob(cx, r, &mut *(closure as *mut StructuredCloneHolder));
|
return read_blob(cx, r, &mut *(closure as *mut StructuredDataHolder));
|
||||||
}
|
}
|
||||||
return ptr::null_mut();
|
return ptr::null_mut();
|
||||||
}
|
}
|
||||||
|
@ -182,33 +194,55 @@ unsafe extern "C" fn write_callback(
|
||||||
obj: RawHandleObject,
|
obj: RawHandleObject,
|
||||||
_closure: *mut raw::c_void,
|
_closure: *mut raw::c_void,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if let Ok(blob) = root_from_handleobject::<Blob>(Handle::from_raw(obj), cx) {
|
if let Ok(blob) = root_from_object::<Blob>(*obj, cx) {
|
||||||
return write_blob(blob, w).is_ok();
|
return write_blob(blob, w).is_ok();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn read_transfer_callback(
|
unsafe extern "C" fn read_transfer_callback(
|
||||||
_cx: *mut JSContext,
|
cx: *mut JSContext,
|
||||||
_r: *mut JSStructuredCloneReader,
|
_r: *mut JSStructuredCloneReader,
|
||||||
_tag: u32,
|
tag: u32,
|
||||||
_content: *mut raw::c_void,
|
_content: *mut raw::c_void,
|
||||||
_extra_data: u64,
|
extra_data: u64,
|
||||||
_closure: *mut raw::c_void,
|
closure: *mut raw::c_void,
|
||||||
_return_object: RawMutableHandleObject,
|
return_object: RawMutableHandleObject,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
if tag == StructuredCloneTags::MessagePort as u32 {
|
||||||
|
let mut sc_holder = &mut *(closure as *mut StructuredDataHolder);
|
||||||
|
let owner = GlobalScope::from_context(cx);
|
||||||
|
if let Ok(_) = <MessagePort as Transferable>::transfer_receive(
|
||||||
|
&owner,
|
||||||
|
&mut sc_holder,
|
||||||
|
extra_data,
|
||||||
|
return_object,
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#structuredserializewithtransfer>
|
||||||
unsafe extern "C" fn write_transfer_callback(
|
unsafe extern "C" fn write_transfer_callback(
|
||||||
_cx: *mut JSContext,
|
cx: *mut JSContext,
|
||||||
_obj: RawHandleObject,
|
obj: RawHandleObject,
|
||||||
_closure: *mut raw::c_void,
|
closure: *mut raw::c_void,
|
||||||
_tag: *mut u32,
|
tag: *mut u32,
|
||||||
_ownership: *mut TransferableOwnership,
|
ownership: *mut TransferableOwnership,
|
||||||
_content: *mut *mut raw::c_void,
|
_content: *mut *mut raw::c_void,
|
||||||
_extra_data: *mut u64,
|
extra_data: *mut u64,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
if let Ok(port) = root_from_object::<MessagePort>(*obj, cx) {
|
||||||
|
*tag = StructuredCloneTags::MessagePort as u32;
|
||||||
|
*ownership = TransferableOwnership::SCTAG_TMO_CUSTOM;
|
||||||
|
let mut sc_holder = &mut *(closure as *mut StructuredDataHolder);
|
||||||
|
if let Ok(data) = port.transfer(&mut sc_holder) {
|
||||||
|
*extra_data = data;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,10 +256,13 @@ unsafe extern "C" fn free_transfer_callback(
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn can_transfer_callback(
|
unsafe extern "C" fn can_transfer_callback(
|
||||||
_cx: *mut JSContext,
|
cx: *mut JSContext,
|
||||||
_obj: RawHandleObject,
|
obj: RawHandleObject,
|
||||||
_closure: *mut raw::c_void,
|
_closure: *mut raw::c_void,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
if let Ok(_port) = root_from_object::<MessagePort>(*obj, cx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,112 +278,143 @@ static STRUCTURED_CLONE_CALLBACKS: JSStructuredCloneCallbacks = JSStructuredClon
|
||||||
canTransfer: Some(can_transfer_callback),
|
canTransfer: Some(can_transfer_callback),
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StructuredCloneHolder {
|
/// A data holder for results from, and inputs to, structured-data read/write operations.
|
||||||
blob: Option<DomRoot<Blob>>,
|
/// https://html.spec.whatwg.org/multipage/#safe-passing-of-structured-data
|
||||||
|
pub enum StructuredDataHolder {
|
||||||
|
Read {
|
||||||
|
/// A deserialized blob, stored temporarily here to keep it rooted.
|
||||||
|
blob: Option<DomRoot<Blob>>,
|
||||||
|
/// A vec of transfer-received DOM ports,
|
||||||
|
/// to be made available to script through a message event.
|
||||||
|
message_ports: Option<Vec<DomRoot<MessagePort>>>,
|
||||||
|
/// A map of port implementations,
|
||||||
|
/// used as part of the "transfer-receiving" steps of ports,
|
||||||
|
/// to produce the DOM ports stored in `message_ports` above.
|
||||||
|
port_impls: Option<HashMap<MessagePortId, MessagePortImpl>>,
|
||||||
|
},
|
||||||
|
/// A data holder into which transferred ports
|
||||||
|
/// can be written as part of their transfer steps.
|
||||||
|
Write(Option<HashMap<MessagePortId, MessagePortImpl>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A buffer for a structured clone.
|
/// Writes a structured clone. Returns a `DataClone` error if that fails.
|
||||||
pub enum StructuredCloneData {
|
pub fn write(
|
||||||
/// A non-serializable (default) variant
|
cx: SafeJSContext,
|
||||||
Struct(*mut u64, size_t),
|
message: HandleValue,
|
||||||
/// A variant that can be serialized
|
transfer: Option<CustomAutoRooterGuard<Vec<*mut JSObject>>>,
|
||||||
Vector(Vec<u8>),
|
) -> Fallible<StructuredSerializedData> {
|
||||||
}
|
unsafe {
|
||||||
|
rooted!(in(*cx) let mut val = UndefinedValue());
|
||||||
impl StructuredCloneData {
|
if let Some(transfer) = transfer {
|
||||||
// TODO: should this be unsafe?
|
transfer.to_jsval(*cx, val.handle_mut());
|
||||||
/// Writes a structured clone. Returns a `DataClone` error if that fails.
|
|
||||||
pub fn write(cx: *mut JSContext, message: HandleValue) -> Fallible<StructuredCloneData> {
|
|
||||||
unsafe {
|
|
||||||
let scbuf = NewJSAutoStructuredCloneBuffer(
|
|
||||||
StructuredCloneScope::DifferentProcess,
|
|
||||||
&STRUCTURED_CLONE_CALLBACKS,
|
|
||||||
);
|
|
||||||
let scdata = &mut ((*scbuf).data_);
|
|
||||||
let policy = CloneDataPolicy {
|
|
||||||
// TODO: SAB?
|
|
||||||
sharedArrayBuffer_: false,
|
|
||||||
};
|
|
||||||
let result = JS_WriteStructuredClone(
|
|
||||||
cx,
|
|
||||||
message,
|
|
||||||
scdata,
|
|
||||||
StructuredCloneScope::DifferentProcess,
|
|
||||||
policy,
|
|
||||||
&STRUCTURED_CLONE_CALLBACKS,
|
|
||||||
ptr::null_mut(),
|
|
||||||
HandleValue::undefined(),
|
|
||||||
);
|
|
||||||
if !result {
|
|
||||||
JS_ClearPendingException(cx);
|
|
||||||
return Err(Error::DataClone);
|
|
||||||
}
|
|
||||||
|
|
||||||
let nbytes = GetLengthOfJSStructuredCloneData(scdata);
|
|
||||||
let mut data = Vec::with_capacity(nbytes);
|
|
||||||
CopyJSStructuredCloneData(scdata, data.as_mut_ptr());
|
|
||||||
data.set_len(nbytes);
|
|
||||||
|
|
||||||
DeleteJSAutoStructuredCloneBuffer(scbuf);
|
|
||||||
|
|
||||||
Ok(StructuredCloneData::Vector(data))
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Converts a StructuredCloneData to Vec<u8> for inter-thread sharing
|
let mut sc_holder = StructuredDataHolder::Write(None);
|
||||||
pub fn move_to_arraybuffer(self) -> Vec<u8> {
|
|
||||||
match self {
|
|
||||||
StructuredCloneData::Struct(data, nbytes) => unsafe {
|
|
||||||
slice::from_raw_parts(data as *mut u8, nbytes).to_vec()
|
|
||||||
},
|
|
||||||
StructuredCloneData::Vector(msg) => msg,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reads a structured clone.
|
|
||||||
///
|
|
||||||
/// Panics if `JS_ReadStructuredClone` fails.
|
|
||||||
fn read_clone(global: &GlobalScope, data: *mut u64, nbytes: size_t, rval: MutableHandleValue) {
|
|
||||||
let cx = global.get_cx();
|
|
||||||
let _ac = enter_realm(&*global);
|
|
||||||
let mut sc_holder = StructuredCloneHolder { blob: None };
|
|
||||||
let sc_holder_ptr = &mut sc_holder as *mut _;
|
let sc_holder_ptr = &mut sc_holder as *mut _;
|
||||||
unsafe {
|
|
||||||
let scbuf = NewJSAutoStructuredCloneBuffer(
|
|
||||||
StructuredCloneScope::DifferentProcess,
|
|
||||||
&STRUCTURED_CLONE_CALLBACKS,
|
|
||||||
);
|
|
||||||
let scdata = &mut ((*scbuf).data_);
|
|
||||||
|
|
||||||
WriteBytesToJSStructuredCloneData(data as *const u8, nbytes, scdata);
|
let scbuf = NewJSAutoStructuredCloneBuffer(
|
||||||
|
StructuredCloneScope::DifferentProcess,
|
||||||
assert!(JS_ReadStructuredClone(
|
&STRUCTURED_CLONE_CALLBACKS,
|
||||||
*cx,
|
);
|
||||||
scdata,
|
let scdata = &mut ((*scbuf).data_);
|
||||||
JS_STRUCTURED_CLONE_VERSION,
|
let policy = CloneDataPolicy {
|
||||||
StructuredCloneScope::DifferentProcess,
|
// TODO: SAB?
|
||||||
rval,
|
sharedArrayBuffer_: false,
|
||||||
&STRUCTURED_CLONE_CALLBACKS,
|
};
|
||||||
sc_holder_ptr as *mut raw::c_void
|
let result = JS_WriteStructuredClone(
|
||||||
));
|
*cx,
|
||||||
|
message,
|
||||||
DeleteJSAutoStructuredCloneBuffer(scbuf);
|
scdata,
|
||||||
|
StructuredCloneScope::DifferentProcess,
|
||||||
|
policy,
|
||||||
|
&STRUCTURED_CLONE_CALLBACKS,
|
||||||
|
sc_holder_ptr as *mut raw::c_void,
|
||||||
|
val.handle(),
|
||||||
|
);
|
||||||
|
if !result {
|
||||||
|
JS_ClearPendingException(*cx);
|
||||||
|
return Err(Error::DataClone);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Thunk for the actual `read_clone` method. Resolves proper variant for read_clone.
|
let nbytes = GetLengthOfJSStructuredCloneData(scdata);
|
||||||
pub fn read(self, global: &GlobalScope, rval: MutableHandleValue) {
|
let mut data = Vec::with_capacity(nbytes);
|
||||||
match self {
|
CopyJSStructuredCloneData(scdata, data.as_mut_ptr());
|
||||||
StructuredCloneData::Vector(mut vec_msg) => {
|
data.set_len(nbytes);
|
||||||
let nbytes = vec_msg.len();
|
|
||||||
let data = vec_msg.as_mut_ptr() as *mut u64;
|
DeleteJSAutoStructuredCloneBuffer(scbuf);
|
||||||
StructuredCloneData::read_clone(global, data, nbytes, rval);
|
|
||||||
},
|
let mut port_impls = match sc_holder {
|
||||||
StructuredCloneData::Struct(data, nbytes) => {
|
StructuredDataHolder::Write(port_impls) => port_impls,
|
||||||
StructuredCloneData::read_clone(global, data, nbytes, rval)
|
_ => panic!("Unexpected variant of StructuredDataHolder"),
|
||||||
},
|
};
|
||||||
}
|
|
||||||
|
let data = StructuredSerializedData {
|
||||||
|
serialized: data,
|
||||||
|
ports: port_impls.take(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for StructuredCloneData {}
|
/// Read structured serialized data, possibly containing transferred objects.
|
||||||
|
/// Returns a vec of rooted transfer-received ports, or an error.
|
||||||
|
pub fn read(
|
||||||
|
global: &GlobalScope,
|
||||||
|
mut data: StructuredSerializedData,
|
||||||
|
rval: MutableHandleValue,
|
||||||
|
) -> Result<Vec<DomRoot<MessagePort>>, ()> {
|
||||||
|
let cx = global.get_cx();
|
||||||
|
let _ac = enter_realm(&*global);
|
||||||
|
let mut sc_holder = StructuredDataHolder::Read {
|
||||||
|
blob: None,
|
||||||
|
message_ports: None,
|
||||||
|
port_impls: data.ports.take(),
|
||||||
|
};
|
||||||
|
let sc_holder_ptr = &mut sc_holder as *mut _;
|
||||||
|
unsafe {
|
||||||
|
let scbuf = NewJSAutoStructuredCloneBuffer(
|
||||||
|
StructuredCloneScope::DifferentProcess,
|
||||||
|
&STRUCTURED_CLONE_CALLBACKS,
|
||||||
|
);
|
||||||
|
let scdata = &mut ((*scbuf).data_);
|
||||||
|
|
||||||
|
WriteBytesToJSStructuredCloneData(
|
||||||
|
data.serialized.as_mut_ptr() as *const u8,
|
||||||
|
data.serialized.len(),
|
||||||
|
scdata,
|
||||||
|
);
|
||||||
|
|
||||||
|
let result = JS_ReadStructuredClone(
|
||||||
|
*cx,
|
||||||
|
scdata,
|
||||||
|
JS_STRUCTURED_CLONE_VERSION,
|
||||||
|
StructuredCloneScope::DifferentProcess,
|
||||||
|
rval,
|
||||||
|
&STRUCTURED_CLONE_CALLBACKS,
|
||||||
|
sc_holder_ptr as *mut raw::c_void,
|
||||||
|
);
|
||||||
|
|
||||||
|
DeleteJSAutoStructuredCloneBuffer(scbuf);
|
||||||
|
|
||||||
|
if result {
|
||||||
|
let (mut message_ports, port_impls) = match sc_holder {
|
||||||
|
StructuredDataHolder::Read {
|
||||||
|
message_ports,
|
||||||
|
port_impls,
|
||||||
|
..
|
||||||
|
} => (message_ports, port_impls),
|
||||||
|
_ => panic!("Unexpected variant of StructuredDataHolder"),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Any transfer-received port-impls should have been taken out.
|
||||||
|
assert!(port_impls.is_none());
|
||||||
|
|
||||||
|
match message_ports.take() {
|
||||||
|
Some(ports) => return Ok(ports),
|
||||||
|
None => return Ok(Vec::with_capacity(0)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -79,7 +79,8 @@ use media::WindowGLContext;
|
||||||
use metrics::{InteractiveMetrics, InteractiveWindow};
|
use metrics::{InteractiveMetrics, InteractiveWindow};
|
||||||
use mime::Mime;
|
use mime::Mime;
|
||||||
use msg::constellation_msg::{
|
use msg::constellation_msg::{
|
||||||
BrowsingContextId, HistoryStateId, PipelineId, TopLevelBrowsingContextId,
|
BrowsingContextId, HistoryStateId, MessagePortId, MessagePortRouterId, PipelineId,
|
||||||
|
TopLevelBrowsingContextId,
|
||||||
};
|
};
|
||||||
use net_traits::filemanager_thread::RelativePos;
|
use net_traits::filemanager_thread::RelativePos;
|
||||||
use net_traits::image::base::{Image, ImageMetadata};
|
use net_traits::image::base::{Image, ImageMetadata};
|
||||||
|
@ -93,6 +94,7 @@ use profile_traits::mem::ProfilerChan as MemProfilerChan;
|
||||||
use profile_traits::time::ProfilerChan as TimeProfilerChan;
|
use profile_traits::time::ProfilerChan as TimeProfilerChan;
|
||||||
use script_layout_interface::rpc::LayoutRPC;
|
use script_layout_interface::rpc::LayoutRPC;
|
||||||
use script_layout_interface::OpaqueStyleAndLayoutData;
|
use script_layout_interface::OpaqueStyleAndLayoutData;
|
||||||
|
use script_traits::transferable::MessagePortImpl;
|
||||||
use script_traits::DrawAPaintImageResult;
|
use script_traits::DrawAPaintImageResult;
|
||||||
use script_traits::{DocumentActivity, ScriptToConstellationChan, TimerEventId, TimerSource};
|
use script_traits::{DocumentActivity, ScriptToConstellationChan, TimerEventId, TimerSource};
|
||||||
use script_traits::{UntrustedNodeAddress, WindowSizeData, WindowSizeType};
|
use script_traits::{UntrustedNodeAddress, WindowSizeData, WindowSizeType};
|
||||||
|
@ -154,6 +156,11 @@ pub unsafe trait JSTraceable {
|
||||||
|
|
||||||
unsafe_no_jsmanaged_fields!(Box<dyn TaskBox>, Box<dyn EventLoopWaker>);
|
unsafe_no_jsmanaged_fields!(Box<dyn TaskBox>, Box<dyn EventLoopWaker>);
|
||||||
|
|
||||||
|
unsafe_no_jsmanaged_fields!(MessagePortImpl);
|
||||||
|
unsafe_no_jsmanaged_fields!(MessagePortId);
|
||||||
|
unsafe_no_jsmanaged_fields!(RefCell<Option<MessagePortId>>);
|
||||||
|
unsafe_no_jsmanaged_fields!(MessagePortRouterId);
|
||||||
|
|
||||||
unsafe_no_jsmanaged_fields!(CSSError);
|
unsafe_no_jsmanaged_fields!(CSSError);
|
||||||
|
|
||||||
unsafe_no_jsmanaged_fields!(&'static Encoding);
|
unsafe_no_jsmanaged_fields!(&'static Encoding);
|
||||||
|
|
22
components/script/dom/bindings/transferable.rs
Normal file
22
components/script/dom/bindings/transferable.rs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/* 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 http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
//! Trait representing the concept of [transferable objects]
|
||||||
|
//! (https://html.spec.whatwg.org/multipage/#transferable-objects).
|
||||||
|
|
||||||
|
use crate::dom::bindings::reflector::DomObject;
|
||||||
|
use crate::dom::bindings::root::DomRoot;
|
||||||
|
use crate::dom::bindings::structuredclone::StructuredDataHolder;
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use js::jsapi::MutableHandleObject;
|
||||||
|
|
||||||
|
pub trait Transferable: DomObject {
|
||||||
|
fn transfer(&self, sc_holder: &mut StructuredDataHolder) -> Result<u64, ()>;
|
||||||
|
fn transfer_receive(
|
||||||
|
owner: &DomRoot<GlobalScope>,
|
||||||
|
sc_holder: &mut StructuredDataHolder,
|
||||||
|
extra_data: u64,
|
||||||
|
return_object: MutableHandleObject,
|
||||||
|
) -> Result<(), ()>;
|
||||||
|
}
|
|
@ -10,10 +10,13 @@ use crate::dom::bindings::codegen::PrototypeList::{MAX_PROTO_CHAIN_LENGTH, PROTO
|
||||||
use crate::dom::bindings::conversions::{jsstring_to_str, private_from_proto_check};
|
use crate::dom::bindings::conversions::{jsstring_to_str, private_from_proto_check};
|
||||||
use crate::dom::bindings::error::throw_invalid_this;
|
use crate::dom::bindings::error::throw_invalid_this;
|
||||||
use crate::dom::bindings::inheritance::TopTypeId;
|
use crate::dom::bindings::inheritance::TopTypeId;
|
||||||
|
use crate::dom::bindings::root::DomRoot;
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::DOMString;
|
||||||
use crate::dom::bindings::trace::trace_object;
|
use crate::dom::bindings::trace::trace_object;
|
||||||
|
use crate::dom::messageport::MessagePort;
|
||||||
use crate::dom::windowproxy;
|
use crate::dom::windowproxy;
|
||||||
use crate::script_runtime::JSContext as SafeJSContext;
|
use crate::script_runtime::JSContext as SafeJSContext;
|
||||||
|
use js::conversions::ToJSValConvertible;
|
||||||
use js::glue::{CallJitGetterOp, CallJitMethodOp, CallJitSetterOp, IsWrapper};
|
use js::glue::{CallJitGetterOp, CallJitMethodOp, CallJitSetterOp, IsWrapper};
|
||||||
use js::glue::{GetCrossCompartmentWrapper, JS_GetReservedSlot, WrapperNew};
|
use js::glue::{GetCrossCompartmentWrapper, JS_GetReservedSlot, WrapperNew};
|
||||||
use js::glue::{UnwrapObjectDynamic, RUST_JSID_TO_INT, RUST_JSID_TO_STRING};
|
use js::glue::{UnwrapObjectDynamic, RUST_JSID_TO_INT, RUST_JSID_TO_STRING};
|
||||||
|
@ -22,7 +25,7 @@ use js::jsapi::HandleId as RawHandleId;
|
||||||
use js::jsapi::HandleObject as RawHandleObject;
|
use js::jsapi::HandleObject as RawHandleObject;
|
||||||
use js::jsapi::MutableHandleObject as RawMutableHandleObject;
|
use js::jsapi::MutableHandleObject as RawMutableHandleObject;
|
||||||
use js::jsapi::{AutoIdVector, CallArgs, DOMCallbacks, GetNonCCWObjectGlobal};
|
use js::jsapi::{AutoIdVector, CallArgs, DOMCallbacks, GetNonCCWObjectGlobal};
|
||||||
use js::jsapi::{Heap, JSAutoRealm, JSContext};
|
use js::jsapi::{Heap, JSAutoRealm, JSContext, JS_FreezeObject};
|
||||||
use js::jsapi::{JSJitInfo, JSObject, JSTracer, JSWrapObjectCallbacks};
|
use js::jsapi::{JSJitInfo, JSObject, JSTracer, JSWrapObjectCallbacks};
|
||||||
use js::jsapi::{JS_EnumerateStandardClasses, JS_GetLatin1StringCharsAndLength};
|
use js::jsapi::{JS_EnumerateStandardClasses, JS_GetLatin1StringCharsAndLength};
|
||||||
use js::jsapi::{JS_IsExceptionPending, JS_IsGlobalObject};
|
use js::jsapi::{JS_IsExceptionPending, JS_IsGlobalObject};
|
||||||
|
@ -117,6 +120,19 @@ impl Clone for DOMJSClass {
|
||||||
}
|
}
|
||||||
unsafe impl Sync for DOMJSClass {}
|
unsafe impl Sync for DOMJSClass {}
|
||||||
|
|
||||||
|
/// Returns a JSVal representing a frozen array of ports
|
||||||
|
pub fn message_ports_to_frozen_array(
|
||||||
|
message_ports: &[DomRoot<MessagePort>],
|
||||||
|
cx: SafeJSContext,
|
||||||
|
) -> JSVal {
|
||||||
|
rooted!(in(*cx) let mut ports = UndefinedValue());
|
||||||
|
unsafe { message_ports.to_jsval(*cx, ports.handle_mut()) };
|
||||||
|
|
||||||
|
rooted!(in(*cx) let obj = ports.to_object());
|
||||||
|
unsafe { JS_FreezeObject(*cx, RawHandleObject::from(obj.handle())) };
|
||||||
|
*ports
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the ProtoOrIfaceArray for the given global object.
|
/// Returns the ProtoOrIfaceArray for the given global object.
|
||||||
/// Fails if `global` is not a DOM global object.
|
/// Fails if `global` is not a DOM global object.
|
||||||
pub fn get_proto_or_iface_array(global: *mut JSObject) -> *mut ProtoOrIfaceArray {
|
pub fn get_proto_or_iface_array(global: *mut JSObject) -> *mut ProtoOrIfaceArray {
|
||||||
|
|
|
@ -10,13 +10,15 @@ use crate::dom::abstractworkerglobalscope::{SendableWorkerScriptChan, WorkerThre
|
||||||
use crate::dom::bindings::cell::DomRefCell;
|
use crate::dom::bindings::cell::DomRefCell;
|
||||||
use crate::dom::bindings::codegen::Bindings::DedicatedWorkerGlobalScopeBinding;
|
use crate::dom::bindings::codegen::Bindings::DedicatedWorkerGlobalScopeBinding;
|
||||||
use crate::dom::bindings::codegen::Bindings::DedicatedWorkerGlobalScopeBinding::DedicatedWorkerGlobalScopeMethods;
|
use crate::dom::bindings::codegen::Bindings::DedicatedWorkerGlobalScopeBinding::DedicatedWorkerGlobalScopeMethods;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::MessagePortBinding::PostMessageOptions;
|
||||||
use crate::dom::bindings::codegen::Bindings::WorkerBinding::WorkerType;
|
use crate::dom::bindings::codegen::Bindings::WorkerBinding::WorkerType;
|
||||||
use crate::dom::bindings::error::{ErrorInfo, ErrorResult};
|
use crate::dom::bindings::error::{ErrorInfo, ErrorResult};
|
||||||
use crate::dom::bindings::inheritance::Castable;
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
use crate::dom::bindings::reflector::DomObject;
|
use crate::dom::bindings::reflector::DomObject;
|
||||||
use crate::dom::bindings::root::{DomRoot, RootCollection, ThreadLocalStackRoots};
|
use crate::dom::bindings::root::{DomRoot, RootCollection, ThreadLocalStackRoots};
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::DOMString;
|
||||||
use crate::dom::bindings::structuredclone::StructuredCloneData;
|
use crate::dom::bindings::structuredclone;
|
||||||
|
use crate::dom::bindings::trace::RootedTraceableBox;
|
||||||
use crate::dom::errorevent::ErrorEvent;
|
use crate::dom::errorevent::ErrorEvent;
|
||||||
use crate::dom::event::{Event, EventBubbles, EventCancelable, EventStatus};
|
use crate::dom::event::{Event, EventBubbles, EventCancelable, EventStatus};
|
||||||
use crate::dom::eventtarget::EventTarget;
|
use crate::dom::eventtarget::EventTarget;
|
||||||
|
@ -36,10 +38,10 @@ use devtools_traits::DevtoolScriptControlMsg;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
||||||
use ipc_channel::router::ROUTER;
|
use ipc_channel::router::ROUTER;
|
||||||
use js::jsapi::JSContext;
|
|
||||||
use js::jsapi::JS_AddInterruptCallback;
|
use js::jsapi::JS_AddInterruptCallback;
|
||||||
|
use js::jsapi::{Heap, JSContext, JSObject};
|
||||||
use js::jsval::UndefinedValue;
|
use js::jsval::UndefinedValue;
|
||||||
use js::rust::HandleValue;
|
use js::rust::{CustomAutoRooter, CustomAutoRooterGuard, HandleValue};
|
||||||
use msg::constellation_msg::{PipelineId, TopLevelBrowsingContextId};
|
use msg::constellation_msg::{PipelineId, TopLevelBrowsingContextId};
|
||||||
use net_traits::image_cache::ImageCache;
|
use net_traits::image_cache::ImageCache;
|
||||||
use net_traits::request::{CredentialsMode, Destination, ParserMetadata};
|
use net_traits::request::{CredentialsMode, Destination, ParserMetadata};
|
||||||
|
@ -462,13 +464,24 @@ impl DedicatedWorkerGlobalScope {
|
||||||
|
|
||||||
fn handle_script_event(&self, msg: WorkerScriptMsg) {
|
fn handle_script_event(&self, msg: WorkerScriptMsg) {
|
||||||
match msg {
|
match msg {
|
||||||
WorkerScriptMsg::DOMMessage(data) => {
|
WorkerScriptMsg::DOMMessage { origin, data } => {
|
||||||
let scope = self.upcast::<WorkerGlobalScope>();
|
let scope = self.upcast::<WorkerGlobalScope>();
|
||||||
let target = self.upcast();
|
let target = self.upcast();
|
||||||
let _ac = enter_realm(self);
|
let _ac = enter_realm(self);
|
||||||
rooted!(in(*scope.get_cx()) let mut message = UndefinedValue());
|
rooted!(in(*scope.get_cx()) let mut message = UndefinedValue());
|
||||||
data.read(scope.upcast(), message.handle_mut());
|
if let Ok(ports) = structuredclone::read(scope.upcast(), data, message.handle_mut())
|
||||||
MessageEvent::dispatch_jsval(target, scope.upcast(), message.handle(), None, None);
|
{
|
||||||
|
MessageEvent::dispatch_jsval(
|
||||||
|
target,
|
||||||
|
scope.upcast(),
|
||||||
|
message.handle(),
|
||||||
|
Some(&origin.ascii_serialization()),
|
||||||
|
None,
|
||||||
|
ports,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
MessageEvent::dispatch_error(target, scope.upcast());
|
||||||
|
}
|
||||||
},
|
},
|
||||||
WorkerScriptMsg::Common(msg) => {
|
WorkerScriptMsg::Common(msg) => {
|
||||||
self.upcast::<WorkerGlobalScope>().process_event(msg);
|
self.upcast::<WorkerGlobalScope>().process_event(msg);
|
||||||
|
@ -547,6 +560,32 @@ impl DedicatedWorkerGlobalScope {
|
||||||
))
|
))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#dom-dedicatedworkerglobalscope-postmessage
|
||||||
|
fn post_message_impl(
|
||||||
|
&self,
|
||||||
|
cx: SafeJSContext,
|
||||||
|
message: HandleValue,
|
||||||
|
transfer: CustomAutoRooterGuard<Vec<*mut JSObject>>,
|
||||||
|
) -> ErrorResult {
|
||||||
|
let data = structuredclone::write(cx, message, Some(transfer))?;
|
||||||
|
let worker = self.worker.borrow().as_ref().unwrap().clone();
|
||||||
|
let global_scope = self.upcast::<GlobalScope>();
|
||||||
|
let pipeline_id = global_scope.pipeline_id();
|
||||||
|
let origin = global_scope.origin().immutable().ascii_serialization();
|
||||||
|
let task = Box::new(task!(post_worker_message: move || {
|
||||||
|
Worker::handle_message(worker, origin, data);
|
||||||
|
}));
|
||||||
|
self.parent_sender
|
||||||
|
.send(CommonScriptMsg::Task(
|
||||||
|
WorkerEvent,
|
||||||
|
task,
|
||||||
|
Some(pipeline_id),
|
||||||
|
TaskSourceName::DOMManipulation,
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
|
@ -560,24 +599,34 @@ unsafe extern "C" fn interrupt_callback(cx: *mut JSContext) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DedicatedWorkerGlobalScopeMethods for DedicatedWorkerGlobalScope {
|
impl DedicatedWorkerGlobalScopeMethods for DedicatedWorkerGlobalScope {
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-dedicatedworkerglobalscope-postmessage
|
/// https://html.spec.whatwg.org/multipage/#dom-dedicatedworkerglobalscope-postmessage
|
||||||
fn PostMessage(&self, cx: SafeJSContext, message: HandleValue) -> ErrorResult {
|
fn PostMessage(
|
||||||
let data = StructuredCloneData::write(*cx, message)?;
|
&self,
|
||||||
let worker = self.worker.borrow().as_ref().unwrap().clone();
|
cx: SafeJSContext,
|
||||||
let pipeline_id = self.upcast::<GlobalScope>().pipeline_id();
|
message: HandleValue,
|
||||||
let task = Box::new(task!(post_worker_message: move || {
|
transfer: CustomAutoRooterGuard<Vec<*mut JSObject>>,
|
||||||
Worker::handle_message(worker, data);
|
) -> ErrorResult {
|
||||||
}));
|
self.post_message_impl(cx, message, transfer)
|
||||||
// TODO: Change this task source to a new `unshipped-port-message-queue` task source
|
}
|
||||||
self.parent_sender
|
|
||||||
.send(CommonScriptMsg::Task(
|
/// https://html.spec.whatwg.org/multipage/#dom-dedicatedworkerglobalscope-postmessage
|
||||||
WorkerEvent,
|
fn PostMessage_(
|
||||||
task,
|
&self,
|
||||||
Some(pipeline_id),
|
cx: SafeJSContext,
|
||||||
TaskSourceName::DOMManipulation,
|
message: HandleValue,
|
||||||
))
|
options: RootedTraceableBox<PostMessageOptions>,
|
||||||
.unwrap();
|
) -> ErrorResult {
|
||||||
Ok(())
|
let mut rooted = CustomAutoRooter::new(
|
||||||
|
options
|
||||||
|
.transfer
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&Vec::with_capacity(0))
|
||||||
|
.iter()
|
||||||
|
.map(|js: &RootedTraceableBox<Heap<*mut JSObject>>| js.get())
|
||||||
|
.collect(),
|
||||||
|
);
|
||||||
|
let guard = CustomAutoRooterGuard::new(*cx, &mut rooted);
|
||||||
|
self.post_message_impl(cx, message, guard)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-dedicatedworkerglobalscope-close
|
// https://html.spec.whatwg.org/multipage/#dom-dedicatedworkerglobalscope-close
|
||||||
|
|
|
@ -4,21 +4,23 @@
|
||||||
|
|
||||||
use crate::dom::bindings::codegen::Bindings::DissimilarOriginWindowBinding;
|
use crate::dom::bindings::codegen::Bindings::DissimilarOriginWindowBinding;
|
||||||
use crate::dom::bindings::codegen::Bindings::DissimilarOriginWindowBinding::DissimilarOriginWindowMethods;
|
use crate::dom::bindings::codegen::Bindings::DissimilarOriginWindowBinding::DissimilarOriginWindowMethods;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowPostMessageOptions;
|
||||||
use crate::dom::bindings::error::{Error, ErrorResult};
|
use crate::dom::bindings::error::{Error, ErrorResult};
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
|
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::USVString;
|
||||||
use crate::dom::bindings::structuredclone::StructuredCloneData;
|
use crate::dom::bindings::structuredclone;
|
||||||
|
use crate::dom::bindings::trace::RootedTraceableBox;
|
||||||
use crate::dom::dissimilaroriginlocation::DissimilarOriginLocation;
|
use crate::dom::dissimilaroriginlocation::DissimilarOriginLocation;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::windowproxy::WindowProxy;
|
use crate::dom::windowproxy::WindowProxy;
|
||||||
use crate::script_runtime::JSContext;
|
use crate::script_runtime::JSContext;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use ipc_channel::ipc;
|
use ipc_channel::ipc;
|
||||||
|
use js::jsapi::{Heap, JSObject};
|
||||||
use js::jsval::{JSVal, UndefinedValue};
|
use js::jsval::{JSVal, UndefinedValue};
|
||||||
use js::rust::HandleValue;
|
use js::rust::{CustomAutoRooter, CustomAutoRooterGuard, HandleValue};
|
||||||
use msg::constellation_msg::PipelineId;
|
use msg::constellation_msg::PipelineId;
|
||||||
use script_traits::ScriptMsg;
|
use script_traits::{ScriptMsg, StructuredSerializedData};
|
||||||
use servo_url::ImmutableOrigin;
|
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
|
|
||||||
/// Represents a dissimilar-origin `Window` that exists in another script thread.
|
/// Represents a dissimilar-origin `Window` that exists in another script thread.
|
||||||
|
@ -133,28 +135,42 @@ impl DissimilarOriginWindowMethods for DissimilarOriginWindow {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-window-postmessage
|
/// https://html.spec.whatwg.org/multipage/#dom-window-postmessage
|
||||||
fn PostMessage(&self, cx: JSContext, message: HandleValue, origin: DOMString) -> ErrorResult {
|
fn PostMessage(
|
||||||
// Step 3-5.
|
&self,
|
||||||
let origin = match &origin[..] {
|
cx: JSContext,
|
||||||
"*" => None,
|
message: HandleValue,
|
||||||
"/" => {
|
target_origin: USVString,
|
||||||
// TODO: Should be the origin of the incumbent settings object.
|
mut transfer: CustomAutoRooterGuard<Option<Vec<*mut JSObject>>>,
|
||||||
None
|
) -> ErrorResult {
|
||||||
},
|
if transfer.is_some() {
|
||||||
url => match ServoUrl::parse(&url) {
|
let mut rooted = CustomAutoRooter::new(transfer.take().unwrap());
|
||||||
Ok(url) => Some(url.origin()),
|
let transfer = Some(CustomAutoRooterGuard::new(*cx, &mut rooted));
|
||||||
Err(_) => return Err(Error::Syntax),
|
self.post_message_impl(&target_origin, cx, message, transfer)
|
||||||
},
|
} else {
|
||||||
};
|
self.post_message_impl(&target_origin, cx, message, None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Step 1-2, 6-8.
|
/// https://html.spec.whatwg.org/multipage/#dom-window-postmessage-options
|
||||||
// TODO(#12717): Should implement the `transfer` argument.
|
fn PostMessage_(
|
||||||
let data = StructuredCloneData::write(*cx, message)?;
|
&self,
|
||||||
|
cx: JSContext,
|
||||||
|
message: HandleValue,
|
||||||
|
options: RootedTraceableBox<WindowPostMessageOptions>,
|
||||||
|
) -> ErrorResult {
|
||||||
|
let mut rooted = CustomAutoRooter::new(
|
||||||
|
options
|
||||||
|
.transfer
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&Vec::with_capacity(0))
|
||||||
|
.iter()
|
||||||
|
.map(|js: &RootedTraceableBox<Heap<*mut JSObject>>| js.get())
|
||||||
|
.collect(),
|
||||||
|
);
|
||||||
|
let transfer = Some(CustomAutoRooterGuard::new(*cx, &mut rooted));
|
||||||
|
|
||||||
// Step 9.
|
self.post_message_impl(&options.targetOrigin, cx, message, transfer)
|
||||||
self.post_message(origin, data);
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-opener
|
// https://html.spec.whatwg.org/multipage/#dom-opener
|
||||||
|
@ -186,17 +202,54 @@ impl DissimilarOriginWindowMethods for DissimilarOriginWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DissimilarOriginWindow {
|
impl DissimilarOriginWindow {
|
||||||
pub fn post_message(&self, origin: Option<ImmutableOrigin>, data: StructuredCloneData) {
|
/// https://html.spec.whatwg.org/multipage/#window-post-message-steps
|
||||||
|
fn post_message_impl(
|
||||||
|
&self,
|
||||||
|
target_origin: &USVString,
|
||||||
|
cx: JSContext,
|
||||||
|
message: HandleValue,
|
||||||
|
transfer: Option<CustomAutoRooterGuard<Vec<*mut JSObject>>>,
|
||||||
|
) -> ErrorResult {
|
||||||
|
// Step 6-7.
|
||||||
|
let data = structuredclone::write(cx, message, transfer)?;
|
||||||
|
|
||||||
|
self.post_message(target_origin, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://html.spec.whatwg.org/multipage/#window-post-message-steps
|
||||||
|
pub fn post_message(
|
||||||
|
&self,
|
||||||
|
target_origin: &USVString,
|
||||||
|
data: StructuredSerializedData,
|
||||||
|
) -> ErrorResult {
|
||||||
|
// Step 1.
|
||||||
|
let target = self.window_proxy.browsing_context_id();
|
||||||
|
// Step 2.
|
||||||
let incumbent = match GlobalScope::incumbent() {
|
let incumbent = match GlobalScope::incumbent() {
|
||||||
None => return warn!("postMessage called with no incumbent global"),
|
None => panic!("postMessage called with no incumbent global"),
|
||||||
Some(incumbent) => incumbent,
|
Some(incumbent) => incumbent,
|
||||||
};
|
};
|
||||||
let msg = ScriptMsg::PostMessage {
|
|
||||||
target: self.window_proxy.browsing_context_id(),
|
let source_origin = incumbent.origin().immutable().clone();
|
||||||
source: incumbent.pipeline_id(),
|
|
||||||
target_origin: origin,
|
// Step 3-5.
|
||||||
data: data.move_to_arraybuffer(),
|
let target_origin = match target_origin.0[..].as_ref() {
|
||||||
|
"*" => None,
|
||||||
|
"/" => Some(source_origin.clone()),
|
||||||
|
url => match ServoUrl::parse(&url) {
|
||||||
|
Ok(url) => Some(url.origin().clone()),
|
||||||
|
Err(_) => return Err(Error::Syntax),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
let msg = ScriptMsg::PostMessage {
|
||||||
|
target,
|
||||||
|
source: incumbent.pipeline_id(),
|
||||||
|
source_origin,
|
||||||
|
target_origin,
|
||||||
|
data: data,
|
||||||
|
};
|
||||||
|
// Step 8
|
||||||
let _ = incumbent.script_to_constellation_chan().send(msg);
|
let _ = incumbent.script_to_constellation_chan().send(msg);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1917,10 +1917,11 @@ impl Document {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let global_scope = self.window.upcast::<GlobalScope>();
|
||||||
// Step 10, 14
|
// Step 10, 14
|
||||||
|
// https://html.spec.whatwg.org/multipage/#unloading-document-cleanup-steps
|
||||||
if !self.salvageable.get() {
|
if !self.salvageable.get() {
|
||||||
// https://html.spec.whatwg.org/multipage/#unloading-document-cleanup-steps
|
|
||||||
let global_scope = self.window.upcast::<GlobalScope>();
|
|
||||||
// Step 1 of clean-up steps.
|
// Step 1 of clean-up steps.
|
||||||
global_scope.close_event_sources();
|
global_scope.close_event_sources();
|
||||||
let msg = ScriptMsg::DiscardDocument;
|
let msg = ScriptMsg::DiscardDocument;
|
||||||
|
|
|
@ -236,6 +236,7 @@ impl EventSourceContext {
|
||||||
DOMString::from(self.origin.clone()),
|
DOMString::from(self.origin.clone()),
|
||||||
None,
|
None,
|
||||||
event_source.last_event_id.borrow().clone(),
|
event_source.last_event_id.borrow().clone(),
|
||||||
|
Vec::with_capacity(0),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
// Step 7
|
// Step 7
|
||||||
|
|
|
@ -10,10 +10,12 @@ use crate::dom::bindings::reflector::reflect_dom_object;
|
||||||
use crate::dom::bindings::root::DomRoot;
|
use crate::dom::bindings::root::DomRoot;
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::DOMString;
|
||||||
use crate::dom::bindings::trace::RootedTraceableBox;
|
use crate::dom::bindings::trace::RootedTraceableBox;
|
||||||
|
use crate::dom::bindings::utils::message_ports_to_frozen_array;
|
||||||
use crate::dom::event::Event;
|
use crate::dom::event::Event;
|
||||||
use crate::dom::eventtarget::EventTarget;
|
use crate::dom::eventtarget::EventTarget;
|
||||||
use crate::dom::extendableevent::ExtendableEvent;
|
use crate::dom::extendableevent::ExtendableEvent;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::dom::messageport::MessagePort;
|
||||||
use crate::dom::serviceworkerglobalscope::ServiceWorkerGlobalScope;
|
use crate::dom::serviceworkerglobalscope::ServiceWorkerGlobalScope;
|
||||||
use crate::script_runtime::JSContext;
|
use crate::script_runtime::JSContext;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
|
@ -29,6 +31,7 @@ pub struct ExtendableMessageEvent {
|
||||||
data: Heap<JSVal>,
|
data: Heap<JSVal>,
|
||||||
origin: DOMString,
|
origin: DOMString,
|
||||||
lastEventId: DOMString,
|
lastEventId: DOMString,
|
||||||
|
ports: Vec<DomRoot<MessagePort>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExtendableMessageEvent {
|
impl ExtendableMessageEvent {
|
||||||
|
@ -40,12 +43,14 @@ impl ExtendableMessageEvent {
|
||||||
data: HandleValue,
|
data: HandleValue,
|
||||||
origin: DOMString,
|
origin: DOMString,
|
||||||
lastEventId: DOMString,
|
lastEventId: DOMString,
|
||||||
|
ports: Vec<DomRoot<MessagePort>>,
|
||||||
) -> DomRoot<ExtendableMessageEvent> {
|
) -> DomRoot<ExtendableMessageEvent> {
|
||||||
let ev = Box::new(ExtendableMessageEvent {
|
let ev = Box::new(ExtendableMessageEvent {
|
||||||
event: ExtendableEvent::new_inherited(),
|
event: ExtendableEvent::new_inherited(),
|
||||||
data: Heap::default(),
|
data: Heap::default(),
|
||||||
origin: origin,
|
origin,
|
||||||
lastEventId: lastEventId,
|
lastEventId,
|
||||||
|
ports,
|
||||||
});
|
});
|
||||||
let ev = reflect_dom_object(ev, global, ExtendableMessageEventBinding::Wrap);
|
let ev = reflect_dom_object(ev, global, ExtendableMessageEventBinding::Wrap);
|
||||||
{
|
{
|
||||||
|
@ -71,13 +76,19 @@ impl ExtendableMessageEvent {
|
||||||
init.data.handle(),
|
init.data.handle(),
|
||||||
init.origin.clone().unwrap(),
|
init.origin.clone().unwrap(),
|
||||||
init.lastEventId.clone().unwrap(),
|
init.lastEventId.clone().unwrap(),
|
||||||
|
vec![],
|
||||||
);
|
);
|
||||||
Ok(ev)
|
Ok(ev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExtendableMessageEvent {
|
impl ExtendableMessageEvent {
|
||||||
pub fn dispatch_jsval(target: &EventTarget, scope: &GlobalScope, message: HandleValue) {
|
pub fn dispatch_jsval(
|
||||||
|
target: &EventTarget,
|
||||||
|
scope: &GlobalScope,
|
||||||
|
message: HandleValue,
|
||||||
|
ports: Vec<DomRoot<MessagePort>>,
|
||||||
|
) {
|
||||||
let Extendablemessageevent = ExtendableMessageEvent::new(
|
let Extendablemessageevent = ExtendableMessageEvent::new(
|
||||||
scope,
|
scope,
|
||||||
atom!("message"),
|
atom!("message"),
|
||||||
|
@ -86,6 +97,7 @@ impl ExtendableMessageEvent {
|
||||||
message,
|
message,
|
||||||
DOMString::new(),
|
DOMString::new(),
|
||||||
DOMString::new(),
|
DOMString::new(),
|
||||||
|
ports,
|
||||||
);
|
);
|
||||||
Extendablemessageevent.upcast::<Event>().fire(target);
|
Extendablemessageevent.upcast::<Event>().fire(target);
|
||||||
}
|
}
|
||||||
|
@ -111,4 +123,9 @@ impl ExtendableMessageEventMethods for ExtendableMessageEvent {
|
||||||
fn IsTrusted(&self) -> bool {
|
fn IsTrusted(&self) -> bool {
|
||||||
self.event.IsTrusted()
|
self.event.IsTrusted()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// https://w3c.github.io/ServiceWorker/#extendablemessage-event-ports
|
||||||
|
fn Ports(&self, cx: JSContext) -> JSVal {
|
||||||
|
message_ports_to_frozen_array(self.ports.as_slice(), cx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,17 +9,21 @@ use crate::dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlo
|
||||||
use crate::dom::bindings::conversions::{root_from_object, root_from_object_static};
|
use crate::dom::bindings::conversions::{root_from_object, root_from_object_static};
|
||||||
use crate::dom::bindings::error::{report_pending_exception, ErrorInfo};
|
use crate::dom::bindings::error::{report_pending_exception, ErrorInfo};
|
||||||
use crate::dom::bindings::inheritance::Castable;
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
|
use crate::dom::bindings::refcounted::Trusted;
|
||||||
use crate::dom::bindings::reflector::DomObject;
|
use crate::dom::bindings::reflector::DomObject;
|
||||||
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
|
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
|
||||||
use crate::dom::bindings::settings_stack::{entry_global, incumbent_global, AutoEntryScript};
|
use crate::dom::bindings::settings_stack::{entry_global, incumbent_global, AutoEntryScript};
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::DOMString;
|
||||||
use crate::dom::bindings::weakref::DOMTracker;
|
use crate::dom::bindings::structuredclone;
|
||||||
|
use crate::dom::bindings::weakref::{DOMTracker, WeakRef};
|
||||||
use crate::dom::crypto::Crypto;
|
use crate::dom::crypto::Crypto;
|
||||||
use crate::dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope;
|
use crate::dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope;
|
||||||
use crate::dom::errorevent::ErrorEvent;
|
use crate::dom::errorevent::ErrorEvent;
|
||||||
use crate::dom::event::{Event, EventBubbles, EventCancelable, EventStatus};
|
use crate::dom::event::{Event, EventBubbles, EventCancelable, EventStatus};
|
||||||
use crate::dom::eventsource::EventSource;
|
use crate::dom::eventsource::EventSource;
|
||||||
use crate::dom::eventtarget::EventTarget;
|
use crate::dom::eventtarget::EventTarget;
|
||||||
|
use crate::dom::messageevent::MessageEvent;
|
||||||
|
use crate::dom::messageport::MessagePort;
|
||||||
use crate::dom::paintworkletglobalscope::PaintWorkletGlobalScope;
|
use crate::dom::paintworkletglobalscope::PaintWorkletGlobalScope;
|
||||||
use crate::dom::performance::Performance;
|
use crate::dom::performance::Performance;
|
||||||
use crate::dom::window::Window;
|
use crate::dom::window::Window;
|
||||||
|
@ -33,36 +37,43 @@ use crate::task_source::dom_manipulation::DOMManipulationTaskSource;
|
||||||
use crate::task_source::file_reading::FileReadingTaskSource;
|
use crate::task_source::file_reading::FileReadingTaskSource;
|
||||||
use crate::task_source::networking::NetworkingTaskSource;
|
use crate::task_source::networking::NetworkingTaskSource;
|
||||||
use crate::task_source::performance_timeline::PerformanceTimelineTaskSource;
|
use crate::task_source::performance_timeline::PerformanceTimelineTaskSource;
|
||||||
|
use crate::task_source::port_message::PortMessageQueue;
|
||||||
use crate::task_source::remote_event::RemoteEventTaskSource;
|
use crate::task_source::remote_event::RemoteEventTaskSource;
|
||||||
use crate::task_source::websocket::WebsocketTaskSource;
|
use crate::task_source::websocket::WebsocketTaskSource;
|
||||||
|
use crate::task_source::TaskSource;
|
||||||
use crate::task_source::TaskSourceName;
|
use crate::task_source::TaskSourceName;
|
||||||
use crate::timers::{IsInterval, OneshotTimerCallback, OneshotTimerHandle};
|
use crate::timers::{IsInterval, OneshotTimerCallback, OneshotTimerHandle};
|
||||||
use crate::timers::{OneshotTimers, TimerCallback};
|
use crate::timers::{OneshotTimers, TimerCallback};
|
||||||
use content_security_policy::CspList;
|
use content_security_policy::CspList;
|
||||||
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
|
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::{self, IpcSender};
|
||||||
|
use ipc_channel::router::ROUTER;
|
||||||
use js::glue::{IsWrapper, UnwrapObjectDynamic};
|
use js::glue::{IsWrapper, UnwrapObjectDynamic};
|
||||||
use js::jsapi::JSObject;
|
use js::jsapi::JSObject;
|
||||||
use js::jsapi::{CurrentGlobalOrNull, GetNonCCWObjectGlobal};
|
use js::jsapi::{CurrentGlobalOrNull, GetNonCCWObjectGlobal};
|
||||||
use js::jsapi::{HandleObject, Heap};
|
use js::jsapi::{HandleObject, Heap};
|
||||||
use js::jsapi::{JSAutoRealm, JSContext};
|
use js::jsapi::{JSAutoRealm, JSContext};
|
||||||
|
use js::jsval::UndefinedValue;
|
||||||
use js::panic::maybe_resume_unwind;
|
use js::panic::maybe_resume_unwind;
|
||||||
use js::rust::wrappers::EvaluateUtf8;
|
use js::rust::wrappers::EvaluateUtf8;
|
||||||
use js::rust::{get_object_class, CompileOptionsWrapper, ParentRuntime, Runtime};
|
use js::rust::{get_object_class, CompileOptionsWrapper, ParentRuntime, Runtime};
|
||||||
use js::rust::{HandleValue, MutableHandleValue};
|
use js::rust::{HandleValue, MutableHandleValue};
|
||||||
use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL};
|
use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL};
|
||||||
use msg::constellation_msg::PipelineId;
|
use msg::constellation_msg::{MessagePortId, MessagePortRouterId, PipelineId};
|
||||||
use net_traits::image_cache::ImageCache;
|
use net_traits::image_cache::ImageCache;
|
||||||
use net_traits::{CoreResourceThread, IpcSend, ResourceThreads};
|
use net_traits::{CoreResourceThread, IpcSend, ResourceThreads};
|
||||||
use profile_traits::{mem as profile_mem, time as profile_time};
|
use profile_traits::{mem as profile_mem, time as profile_time};
|
||||||
use script_traits::{MsDuration, ScriptToConstellationChan, TimerEvent};
|
use script_traits::transferable::MessagePortImpl;
|
||||||
|
use script_traits::{
|
||||||
|
MessagePortMsg, MsDuration, PortMessageTask, ScriptMsg, ScriptToConstellationChan, TimerEvent,
|
||||||
|
};
|
||||||
use script_traits::{TimerEventId, TimerSchedulerMsg, TimerSource};
|
use script_traits::{TimerEventId, TimerSchedulerMsg, TimerSource};
|
||||||
use servo_url::{MutableOrigin, ServoUrl};
|
use servo_url::{MutableOrigin, ServoUrl};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
use std::collections::HashMap;
|
use std::collections::{HashMap, VecDeque};
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
@ -84,6 +95,9 @@ pub struct GlobalScope {
|
||||||
crypto: MutNullableDom<Crypto>,
|
crypto: MutNullableDom<Crypto>,
|
||||||
next_worker_id: Cell<WorkerId>,
|
next_worker_id: Cell<WorkerId>,
|
||||||
|
|
||||||
|
/// The message-port router id for this global, if it is managing ports.
|
||||||
|
message_port_state: DomRefCell<MessagePortState>,
|
||||||
|
|
||||||
/// Pipeline id associated with this global.
|
/// Pipeline id associated with this global.
|
||||||
pipeline_id: PipelineId,
|
pipeline_id: PipelineId,
|
||||||
|
|
||||||
|
@ -167,6 +181,77 @@ pub struct GlobalScope {
|
||||||
user_agent: Cow<'static, str>,
|
user_agent: Cow<'static, str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A wrapper for glue-code between the ipc router and the event-loop.
|
||||||
|
struct MessageListener {
|
||||||
|
canceller: TaskCanceller,
|
||||||
|
task_source: PortMessageQueue,
|
||||||
|
context: Trusted<GlobalScope>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Data representing a message-port managed by this global.
|
||||||
|
#[derive(JSTraceable, MallocSizeOf)]
|
||||||
|
pub enum ManagedMessagePort {
|
||||||
|
/// We keep ports pending when they are first transfer-received,
|
||||||
|
/// and only add them, and ask the constellation to complete the transfer,
|
||||||
|
/// in a subsequent task if the port hasn't been re-transfered.
|
||||||
|
Pending(MessagePortImpl, WeakRef<MessagePort>),
|
||||||
|
/// A port who was transferred into, or initially created in, this realm,
|
||||||
|
/// and that hasn't been re-transferred in the same task it was noted.
|
||||||
|
Added(MessagePortImpl, WeakRef<MessagePort>),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// State representing whether this global is currently managing messageports.
|
||||||
|
#[derive(JSTraceable, MallocSizeOf)]
|
||||||
|
pub enum MessagePortState {
|
||||||
|
/// The message-port router id for this global, and a map of managed ports.
|
||||||
|
Managed(
|
||||||
|
MessagePortRouterId,
|
||||||
|
HashMap<MessagePortId, ManagedMessagePort>,
|
||||||
|
),
|
||||||
|
/// This global is not managing any ports at this time.
|
||||||
|
UnManaged,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageListener {
|
||||||
|
/// A new message came in, handle it via a task enqueued on the event-loop.
|
||||||
|
/// A task is required, since we are using a trusted globalscope,
|
||||||
|
/// and we can only access the root from the event-loop.
|
||||||
|
fn notify(&self, msg: MessagePortMsg) {
|
||||||
|
match msg {
|
||||||
|
MessagePortMsg::CompleteTransfer(port_id, tasks) => {
|
||||||
|
let context = self.context.clone();
|
||||||
|
let _ = self.task_source.queue_with_canceller(
|
||||||
|
task!(process_complete_transfer: move || {
|
||||||
|
let global = context.root();
|
||||||
|
global.complete_port_transfer(port_id, tasks);
|
||||||
|
}),
|
||||||
|
&self.canceller,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
MessagePortMsg::NewTask(port_id, task) => {
|
||||||
|
let context = self.context.clone();
|
||||||
|
let _ = self.task_source.queue_with_canceller(
|
||||||
|
task!(process_new_task: move || {
|
||||||
|
let global = context.root();
|
||||||
|
global.route_task_to_port(port_id, task);
|
||||||
|
}),
|
||||||
|
&self.canceller,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
MessagePortMsg::RemoveMessagePort(port_id) => {
|
||||||
|
let context = self.context.clone();
|
||||||
|
let _ = self.task_source.queue_with_canceller(
|
||||||
|
task!(process_remove_message_port: move || {
|
||||||
|
let global = context.root();
|
||||||
|
global.remove_message_port(&port_id);
|
||||||
|
}),
|
||||||
|
&self.canceller,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl GlobalScope {
|
impl GlobalScope {
|
||||||
pub fn new_inherited(
|
pub fn new_inherited(
|
||||||
pipeline_id: PipelineId,
|
pipeline_id: PipelineId,
|
||||||
|
@ -183,6 +268,7 @@ impl GlobalScope {
|
||||||
user_agent: Cow<'static, str>,
|
user_agent: Cow<'static, str>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
message_port_state: DomRefCell::new(MessagePortState::UnManaged),
|
||||||
eventtarget: EventTarget::new_inherited(),
|
eventtarget: EventTarget::new_inherited(),
|
||||||
crypto: Default::default(),
|
crypto: Default::default(),
|
||||||
next_worker_id: Cell::new(WorkerId(0)),
|
next_worker_id: Cell::new(WorkerId(0)),
|
||||||
|
@ -208,6 +294,397 @@ impl GlobalScope {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Complete the transfer of a message-port.
|
||||||
|
fn complete_port_transfer(&self, port_id: MessagePortId, tasks: VecDeque<PortMessageTask>) {
|
||||||
|
let should_start = if let MessagePortState::Managed(_id, message_ports) =
|
||||||
|
&mut *self.message_port_state.borrow_mut()
|
||||||
|
{
|
||||||
|
match message_ports.get_mut(&port_id) {
|
||||||
|
None => {
|
||||||
|
panic!("CompleteTransfer msg received in a global not managing the port.");
|
||||||
|
},
|
||||||
|
Some(ManagedMessagePort::Pending(_, _)) => {
|
||||||
|
panic!("CompleteTransfer msg received for a pending port.");
|
||||||
|
},
|
||||||
|
Some(ManagedMessagePort::Added(port_impl, _port)) => {
|
||||||
|
port_impl.complete_transfer(tasks);
|
||||||
|
port_impl.enabled()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return warn!("CompleteTransfer msg received in a global not managing any ports.");
|
||||||
|
};
|
||||||
|
if should_start {
|
||||||
|
self.start_message_port(&port_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update our state to un-managed,
|
||||||
|
/// and tell the constellation to drop the sender to our message-port router.
|
||||||
|
pub fn remove_message_ports_router(&self) {
|
||||||
|
if let MessagePortState::Managed(router_id, _message_ports) =
|
||||||
|
&*self.message_port_state.borrow()
|
||||||
|
{
|
||||||
|
let _ = self
|
||||||
|
.script_to_constellation_chan()
|
||||||
|
.send(ScriptMsg::RemoveMessagePortRouter(router_id.clone()));
|
||||||
|
}
|
||||||
|
*self.message_port_state.borrow_mut() = MessagePortState::UnManaged;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#entangle>
|
||||||
|
pub fn entangle_ports(&self, port1: MessagePortId, port2: MessagePortId) {
|
||||||
|
if let MessagePortState::Managed(_id, message_ports) =
|
||||||
|
&mut *self.message_port_state.borrow_mut()
|
||||||
|
{
|
||||||
|
for (port_id, entangled_id) in &[(port1, port2), (port2, port1)] {
|
||||||
|
match message_ports.get_mut(&port_id) {
|
||||||
|
None => {
|
||||||
|
return warn!("entangled_ports called on a global not managing the port.");
|
||||||
|
},
|
||||||
|
Some(ManagedMessagePort::Pending(port_impl, dom_port)) => {
|
||||||
|
dom_port
|
||||||
|
.root()
|
||||||
|
.expect("Port to be entangled to not have been GC'ed")
|
||||||
|
.entangle(entangled_id.clone());
|
||||||
|
port_impl.entangle(entangled_id.clone());
|
||||||
|
},
|
||||||
|
Some(ManagedMessagePort::Added(port_impl, dom_port)) => {
|
||||||
|
dom_port
|
||||||
|
.root()
|
||||||
|
.expect("Port to be entangled to not have been GC'ed")
|
||||||
|
.entangle(entangled_id.clone());
|
||||||
|
port_impl.entangle(entangled_id.clone());
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!("entangled_ports called on a global not managing any ports.");
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = self
|
||||||
|
.script_to_constellation_chan()
|
||||||
|
.send(ScriptMsg::EntanglePorts(port1, port2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove all referrences to a port.
|
||||||
|
pub fn remove_message_port(&self, port_id: &MessagePortId) {
|
||||||
|
let is_empty = if let MessagePortState::Managed(_id, message_ports) =
|
||||||
|
&mut *self.message_port_state.borrow_mut()
|
||||||
|
{
|
||||||
|
match message_ports.remove(&port_id) {
|
||||||
|
None => panic!("remove_message_port called on a global not managing the port."),
|
||||||
|
Some(_) => message_ports.is_empty(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return warn!("remove_message_port called on a global not managing any ports.");
|
||||||
|
};
|
||||||
|
if is_empty {
|
||||||
|
// Remove our port router,
|
||||||
|
// it will be setup again if we start managing ports again.
|
||||||
|
self.remove_message_ports_router();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Handle the transfer of a port in the current task.
|
||||||
|
pub fn mark_port_as_transferred(&self, port_id: &MessagePortId) -> MessagePortImpl {
|
||||||
|
if let MessagePortState::Managed(_id, message_ports) =
|
||||||
|
&mut *self.message_port_state.borrow_mut()
|
||||||
|
{
|
||||||
|
let mut port = match message_ports.remove(&port_id) {
|
||||||
|
None => {
|
||||||
|
panic!("mark_port_as_transferred called on a global not managing the port.")
|
||||||
|
},
|
||||||
|
Some(ManagedMessagePort::Pending(port_impl, _)) => port_impl,
|
||||||
|
Some(ManagedMessagePort::Added(port_impl, _)) => port_impl,
|
||||||
|
};
|
||||||
|
port.set_has_been_shipped();
|
||||||
|
let _ = self
|
||||||
|
.script_to_constellation_chan()
|
||||||
|
.send(ScriptMsg::MessagePortShipped(port_id.clone()));
|
||||||
|
port
|
||||||
|
} else {
|
||||||
|
panic!("mark_port_as_transferred called on a global not managing any ports.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#dom-messageport-start>
|
||||||
|
pub fn start_message_port(&self, port_id: &MessagePortId) {
|
||||||
|
if let MessagePortState::Managed(_id, message_ports) =
|
||||||
|
&mut *self.message_port_state.borrow_mut()
|
||||||
|
{
|
||||||
|
let port = match message_ports.get_mut(&port_id) {
|
||||||
|
None => panic!("start_message_port called on a unknown port."),
|
||||||
|
Some(ManagedMessagePort::Pending(port_impl, _)) => port_impl,
|
||||||
|
Some(ManagedMessagePort::Added(port_impl, _)) => port_impl,
|
||||||
|
};
|
||||||
|
if let Some(message_buffer) = port.start() {
|
||||||
|
for task in message_buffer {
|
||||||
|
let port_id = port_id.clone();
|
||||||
|
let this = Trusted::new(&*self);
|
||||||
|
let _ = self.port_message_queue().queue(
|
||||||
|
task!(process_pending_port_messages: move || {
|
||||||
|
let target_global = this.root();
|
||||||
|
target_global.route_task_to_port(port_id, task);
|
||||||
|
}),
|
||||||
|
&self,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return warn!("start_message_port called on a global not managing any ports.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#dom-messageport-close>
|
||||||
|
pub fn close_message_port(&self, port_id: &MessagePortId) {
|
||||||
|
if let MessagePortState::Managed(_id, message_ports) =
|
||||||
|
&mut *self.message_port_state.borrow_mut()
|
||||||
|
{
|
||||||
|
let port = match message_ports.get_mut(&port_id) {
|
||||||
|
None => panic!("close_message_port called on an unknown port."),
|
||||||
|
Some(ManagedMessagePort::Pending(port_impl, _)) => port_impl,
|
||||||
|
Some(ManagedMessagePort::Added(port_impl, _)) => port_impl,
|
||||||
|
};
|
||||||
|
port.close();
|
||||||
|
} else {
|
||||||
|
return warn!("close_message_port called on a global not managing any ports.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#message-port-post-message-steps>
|
||||||
|
// Steps 6 and 7
|
||||||
|
pub fn post_messageport_msg(&self, port_id: MessagePortId, task: PortMessageTask) {
|
||||||
|
if let MessagePortState::Managed(_id, message_ports) =
|
||||||
|
&mut *self.message_port_state.borrow_mut()
|
||||||
|
{
|
||||||
|
let port = match message_ports.get_mut(&port_id) {
|
||||||
|
None => panic!("post_messageport_msg called on an unknown port."),
|
||||||
|
Some(ManagedMessagePort::Pending(port_impl, _)) => port_impl,
|
||||||
|
Some(ManagedMessagePort::Added(port_impl, _)) => port_impl,
|
||||||
|
};
|
||||||
|
if let Some(entangled_id) = port.entangled_port_id() {
|
||||||
|
// Step 7
|
||||||
|
let this = Trusted::new(&*self);
|
||||||
|
let _ = self.port_message_queue().queue(
|
||||||
|
task!(post_message: move || {
|
||||||
|
let global = this.root();
|
||||||
|
// Note: we do this in a task, as this will ensure the global and constellation
|
||||||
|
// are aware of any transfer that might still take place in the current task.
|
||||||
|
global.route_task_to_port(entangled_id, task);
|
||||||
|
}),
|
||||||
|
self,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return warn!("post_messageport_msg called on a global not managing any ports.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If we don't know about the port,
|
||||||
|
/// send the message to the constellation for routing.
|
||||||
|
fn re_route_port_task(&self, port_id: MessagePortId, task: PortMessageTask) {
|
||||||
|
let _ = self
|
||||||
|
.script_to_constellation_chan()
|
||||||
|
.send(ScriptMsg::RerouteMessagePort(port_id, task));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Route the task to be handled by the relevant port.
|
||||||
|
pub fn route_task_to_port(&self, port_id: MessagePortId, task: PortMessageTask) {
|
||||||
|
let should_dispatch = if let MessagePortState::Managed(_id, message_ports) =
|
||||||
|
&mut *self.message_port_state.borrow_mut()
|
||||||
|
{
|
||||||
|
if !message_ports.contains_key(&port_id) {
|
||||||
|
self.re_route_port_task(port_id, task);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let (port_impl, dom_port) = match message_ports.get_mut(&port_id) {
|
||||||
|
None => panic!("route_task_to_port called for an unknown port."),
|
||||||
|
Some(ManagedMessagePort::Pending(port_impl, dom_port)) => (port_impl, dom_port),
|
||||||
|
Some(ManagedMessagePort::Added(port_impl, dom_port)) => (port_impl, dom_port),
|
||||||
|
};
|
||||||
|
|
||||||
|
// If the port is not enabled yet, or if is awaiting the completion of it's transfer,
|
||||||
|
// the task will be buffered and dispatched upon enablement or completion of the transfer.
|
||||||
|
if let Some(task_to_dispatch) = port_impl.handle_incoming(task) {
|
||||||
|
// Get a corresponding DOM message-port object.
|
||||||
|
let dom_port = match dom_port.root() {
|
||||||
|
Some(dom_port) => dom_port,
|
||||||
|
None => panic!("Messageport Gc'ed too early"),
|
||||||
|
};
|
||||||
|
Some((dom_port, task_to_dispatch))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.re_route_port_task(port_id, task);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if let Some((dom_port, PortMessageTask { origin, data })) = should_dispatch {
|
||||||
|
// Substep 3-4
|
||||||
|
rooted!(in(*self.get_cx()) let mut message_clone = UndefinedValue());
|
||||||
|
if let Ok(ports) = structuredclone::read(self, data, message_clone.handle_mut()) {
|
||||||
|
// Substep 6
|
||||||
|
// Dispatch the event, using the dom message-port.
|
||||||
|
MessageEvent::dispatch_jsval(
|
||||||
|
&dom_port.upcast(),
|
||||||
|
self,
|
||||||
|
message_clone.handle(),
|
||||||
|
Some(&origin.ascii_serialization()),
|
||||||
|
None,
|
||||||
|
ports,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Step 4, fire messageerror event.
|
||||||
|
MessageEvent::dispatch_error(&dom_port.upcast(), self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check all ports that have been transfer-received in the previous task,
|
||||||
|
/// and complete their transfer if they haven't been re-transferred.
|
||||||
|
pub fn maybe_add_pending_ports(&self) {
|
||||||
|
if let MessagePortState::Managed(router_id, message_ports) =
|
||||||
|
&mut *self.message_port_state.borrow_mut()
|
||||||
|
{
|
||||||
|
let to_be_added: Vec<MessagePortId> = message_ports
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(id, port_info)| match port_info {
|
||||||
|
ManagedMessagePort::Pending(_, _) => Some(id.clone()),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
for id in to_be_added {
|
||||||
|
let (id, port_info) = message_ports
|
||||||
|
.remove_entry(&id)
|
||||||
|
.expect("Collected port-id to match an entry");
|
||||||
|
if let ManagedMessagePort::Pending(port_impl, dom_port) = port_info {
|
||||||
|
let _ = self
|
||||||
|
.script_to_constellation_chan()
|
||||||
|
.send(ScriptMsg::NewMessagePort(
|
||||||
|
router_id.clone(),
|
||||||
|
port_impl.message_port_id().clone(),
|
||||||
|
));
|
||||||
|
let new_port_info = ManagedMessagePort::Added(port_impl, dom_port);
|
||||||
|
let present = message_ports.insert(id, new_port_info);
|
||||||
|
assert!(present.is_none());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warn!("maybe_add_pending_ports called on a global not managing any ports.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://html.spec.whatwg.org/multipage/#ports-and-garbage-collection
|
||||||
|
pub fn perform_a_message_port_garbage_collection_checkpoint(&self) {
|
||||||
|
let is_empty = if let MessagePortState::Managed(_id, message_ports) =
|
||||||
|
&mut *self.message_port_state.borrow_mut()
|
||||||
|
{
|
||||||
|
let to_be_removed: Vec<MessagePortId> = message_ports
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(id, port_info)| {
|
||||||
|
if let ManagedMessagePort::Added(_port_impl, dom_port) = port_info {
|
||||||
|
if dom_port.root().is_none() {
|
||||||
|
// Let the constellation know to drop this port and the one it is entangled with,
|
||||||
|
// and to forward this message to the script-process where the entangled is found.
|
||||||
|
let _ = self
|
||||||
|
.script_to_constellation_chan()
|
||||||
|
.send(ScriptMsg::RemoveMessagePort(id.clone()));
|
||||||
|
return Some(id.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
for id in to_be_removed {
|
||||||
|
message_ports.remove(&id);
|
||||||
|
}
|
||||||
|
message_ports.is_empty()
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
if is_empty {
|
||||||
|
self.remove_message_ports_router();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start tracking a message-port
|
||||||
|
pub fn track_message_port(&self, dom_port: &MessagePort, port_impl: Option<MessagePortImpl>) {
|
||||||
|
let mut current_state = self.message_port_state.borrow_mut();
|
||||||
|
|
||||||
|
if let MessagePortState::UnManaged = &*current_state {
|
||||||
|
// Setup a route for IPC, for messages from the constellation to our ports.
|
||||||
|
let (port_control_sender, port_control_receiver) =
|
||||||
|
ipc::channel().expect("ipc channel failure");
|
||||||
|
let context = Trusted::new(self);
|
||||||
|
let (task_source, canceller) = (
|
||||||
|
self.port_message_queue(),
|
||||||
|
self.task_canceller(TaskSourceName::PortMessage),
|
||||||
|
);
|
||||||
|
let listener = MessageListener {
|
||||||
|
canceller,
|
||||||
|
task_source,
|
||||||
|
context,
|
||||||
|
};
|
||||||
|
ROUTER.add_route(
|
||||||
|
port_control_receiver.to_opaque(),
|
||||||
|
Box::new(move |message| {
|
||||||
|
let msg = message.to();
|
||||||
|
match msg {
|
||||||
|
Ok(msg) => listener.notify(msg),
|
||||||
|
Err(err) => warn!("Error receiving a MessagePortMsg: {:?}", err),
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
let router_id = MessagePortRouterId::new();
|
||||||
|
*current_state = MessagePortState::Managed(router_id.clone(), HashMap::new());
|
||||||
|
let _ = self
|
||||||
|
.script_to_constellation_chan()
|
||||||
|
.send(ScriptMsg::NewMessagePortRouter(
|
||||||
|
router_id,
|
||||||
|
port_control_sender,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let MessagePortState::Managed(router_id, message_ports) = &mut *current_state {
|
||||||
|
if let Some(port_impl) = port_impl {
|
||||||
|
// We keep transfer-received ports as "pending",
|
||||||
|
// and only ask the constellation to complete the transfer
|
||||||
|
// if they're not re-shipped in the current task.
|
||||||
|
message_ports.insert(
|
||||||
|
dom_port.message_port_id().clone(),
|
||||||
|
ManagedMessagePort::Pending(port_impl, WeakRef::new(dom_port)),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Queue a task to complete the transfer,
|
||||||
|
// unless the port is re-transferred in the current task.
|
||||||
|
let this = Trusted::new(&*self);
|
||||||
|
let _ = self.port_message_queue().queue(
|
||||||
|
task!(process_pending_port_messages: move || {
|
||||||
|
let target_global = this.root();
|
||||||
|
target_global.maybe_add_pending_ports();
|
||||||
|
}),
|
||||||
|
&self,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// If this is a newly-created port, let the constellation immediately know.
|
||||||
|
let port_impl = MessagePortImpl::new(dom_port.message_port_id().clone());
|
||||||
|
message_ports.insert(
|
||||||
|
dom_port.message_port_id().clone(),
|
||||||
|
ManagedMessagePort::Added(port_impl, WeakRef::new(dom_port)),
|
||||||
|
);
|
||||||
|
let _ = self
|
||||||
|
.script_to_constellation_chan()
|
||||||
|
.send(ScriptMsg::NewMessagePort(
|
||||||
|
router_id.clone(),
|
||||||
|
dom_port.message_port_id().clone(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
panic!("track_message_port should have first switched the state to managed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn track_worker(&self, closing_worker: Arc<AtomicBool>) {
|
pub fn track_worker(&self, closing_worker: Arc<AtomicBool>) {
|
||||||
self.list_auto_close_worker
|
self.list_auto_close_worker
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
|
@ -504,7 +981,7 @@ impl GlobalScope {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `ScriptChan` to send messages to the networking task source of
|
/// `TaskSource` to send messages to the networking task source of
|
||||||
/// this global scope.
|
/// this global scope.
|
||||||
pub fn networking_task_source(&self) -> NetworkingTaskSource {
|
pub fn networking_task_source(&self) -> NetworkingTaskSource {
|
||||||
if let Some(window) = self.downcast::<Window>() {
|
if let Some(window) = self.downcast::<Window>() {
|
||||||
|
@ -516,7 +993,19 @@ impl GlobalScope {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `ScriptChan` to send messages to the remote-event task source of
|
/// `TaskSource` to send messages to the port message queue of
|
||||||
|
/// this global scope.
|
||||||
|
pub fn port_message_queue(&self) -> PortMessageQueue {
|
||||||
|
if let Some(window) = self.downcast::<Window>() {
|
||||||
|
return window.task_manager().port_message_queue();
|
||||||
|
}
|
||||||
|
if let Some(worker) = self.downcast::<WorkerGlobalScope>() {
|
||||||
|
return worker.port_message_queue();
|
||||||
|
}
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `TaskSource` to send messages to the remote-event task source of
|
||||||
/// this global scope.
|
/// this global scope.
|
||||||
pub fn remote_event_task_source(&self) -> RemoteEventTaskSource {
|
pub fn remote_event_task_source(&self) -> RemoteEventTaskSource {
|
||||||
if let Some(window) = self.downcast::<Window>() {
|
if let Some(window) = self.downcast::<Window>() {
|
||||||
|
@ -528,7 +1017,7 @@ impl GlobalScope {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `ScriptChan` to send messages to the websocket task source of
|
/// `TaskSource` to send messages to the websocket task source of
|
||||||
/// this global scope.
|
/// this global scope.
|
||||||
pub fn websocket_task_source(&self) -> WebsocketTaskSource {
|
pub fn websocket_task_source(&self) -> WebsocketTaskSource {
|
||||||
if let Some(window) = self.downcast::<Window>() {
|
if let Some(window) = self.downcast::<Window>() {
|
||||||
|
|
|
@ -11,7 +11,7 @@ use crate::dom::bindings::inheritance::Castable;
|
||||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
|
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot};
|
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||||
use crate::dom::bindings::str::{DOMString, USVString};
|
use crate::dom::bindings::str::{DOMString, USVString};
|
||||||
use crate::dom::bindings::structuredclone::StructuredCloneData;
|
use crate::dom::bindings::structuredclone;
|
||||||
use crate::dom::event::Event;
|
use crate::dom::event::Event;
|
||||||
use crate::dom::eventtarget::EventTarget;
|
use crate::dom::eventtarget::EventTarget;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
@ -27,7 +27,7 @@ use msg::constellation_msg::{HistoryStateId, TraversalDirection};
|
||||||
use net_traits::{CoreResourceMsg, IpcSend};
|
use net_traits::{CoreResourceMsg, IpcSend};
|
||||||
use profile_traits::ipc;
|
use profile_traits::ipc;
|
||||||
use profile_traits::ipc::channel;
|
use profile_traits::ipc::channel;
|
||||||
use script_traits::ScriptMsg;
|
use script_traits::{ScriptMsg, StructuredSerializedData};
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
||||||
|
@ -115,11 +115,16 @@ impl History {
|
||||||
};
|
};
|
||||||
|
|
||||||
match serialized_data {
|
match serialized_data {
|
||||||
Some(serialized_data) => {
|
Some(data) => {
|
||||||
|
let data = StructuredSerializedData {
|
||||||
|
serialized: data,
|
||||||
|
ports: None,
|
||||||
|
};
|
||||||
let global_scope = self.window.upcast::<GlobalScope>();
|
let global_scope = self.window.upcast::<GlobalScope>();
|
||||||
rooted!(in(*global_scope.get_cx()) let mut state = UndefinedValue());
|
rooted!(in(*global_scope.get_cx()) let mut state = UndefinedValue());
|
||||||
StructuredCloneData::Vector(serialized_data)
|
if let Err(_) = structuredclone::read(&global_scope, data, state.handle_mut()) {
|
||||||
.read(&global_scope, state.handle_mut());
|
warn!("Error reading structuredclone data");
|
||||||
|
}
|
||||||
self.state.set(state.get());
|
self.state.set(state.get());
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
|
@ -185,7 +190,7 @@ impl History {
|
||||||
// TODO: Step 4
|
// TODO: Step 4
|
||||||
|
|
||||||
// Step 5
|
// Step 5
|
||||||
let serialized_data = StructuredCloneData::write(*cx, data)?.move_to_arraybuffer();
|
let serialized_data = structuredclone::write(cx, data, None)?;
|
||||||
|
|
||||||
let new_url: ServoUrl = match url {
|
let new_url: ServoUrl = match url {
|
||||||
// Step 6
|
// Step 6
|
||||||
|
@ -254,7 +259,7 @@ impl History {
|
||||||
};
|
};
|
||||||
|
|
||||||
let _ = self.window.upcast::<GlobalScope>().resource_threads().send(
|
let _ = self.window.upcast::<GlobalScope>().resource_threads().send(
|
||||||
CoreResourceMsg::SetHistoryState(state_id, serialized_data.clone()),
|
CoreResourceMsg::SetHistoryState(state_id, serialized_data.serialized.clone()),
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: Step 9 Update current entry to represent a GET request
|
// TODO: Step 9 Update current entry to represent a GET request
|
||||||
|
@ -266,7 +271,9 @@ impl History {
|
||||||
// Step 11
|
// Step 11
|
||||||
let global_scope = self.window.upcast::<GlobalScope>();
|
let global_scope = self.window.upcast::<GlobalScope>();
|
||||||
rooted!(in(*cx) let mut state = UndefinedValue());
|
rooted!(in(*cx) let mut state = UndefinedValue());
|
||||||
StructuredCloneData::Vector(serialized_data).read(&global_scope, state.handle_mut());
|
if let Err(_) = structuredclone::read(&global_scope, serialized_data, state.handle_mut()) {
|
||||||
|
warn!("Error reading structuredclone data");
|
||||||
|
}
|
||||||
|
|
||||||
// Step 12
|
// Step 12
|
||||||
self.state.set(state.get());
|
self.state.set(state.get());
|
||||||
|
|
66
components/script/dom/messagechannel.rs
Normal file
66
components/script/dom/messagechannel.rs
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/* 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 http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use crate::dom::bindings::codegen::Bindings::MessageChannelBinding::{MessageChannelMethods, Wrap};
|
||||||
|
use crate::dom::bindings::error::{Error, Fallible};
|
||||||
|
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
|
||||||
|
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::dom::messageport::MessagePort;
|
||||||
|
use dom_struct::dom_struct;
|
||||||
|
|
||||||
|
#[dom_struct]
|
||||||
|
pub struct MessageChannel {
|
||||||
|
reflector_: Reflector,
|
||||||
|
port1: Dom<MessagePort>,
|
||||||
|
port2: Dom<MessagePort>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageChannel {
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#dom-messagechannel>
|
||||||
|
pub fn Constructor(global: &GlobalScope) -> Fallible<DomRoot<MessageChannel>> {
|
||||||
|
let incumbent = GlobalScope::incumbent().ok_or(Error::InvalidState)?;
|
||||||
|
|
||||||
|
// Step 1
|
||||||
|
let port1 = MessagePort::new(&incumbent);
|
||||||
|
|
||||||
|
// Step 2
|
||||||
|
let port2 = MessagePort::new(&incumbent);
|
||||||
|
|
||||||
|
incumbent.track_message_port(&*port1, None);
|
||||||
|
incumbent.track_message_port(&*port2, None);
|
||||||
|
|
||||||
|
// Step 3
|
||||||
|
incumbent.entangle_ports(
|
||||||
|
port1.message_port_id().clone(),
|
||||||
|
port2.message_port_id().clone(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Steps 4-6
|
||||||
|
let channel = reflect_dom_object(
|
||||||
|
Box::new(MessageChannel {
|
||||||
|
reflector_: Reflector::new(),
|
||||||
|
port1: Dom::from_ref(&port1),
|
||||||
|
port2: Dom::from_ref(&port2),
|
||||||
|
}),
|
||||||
|
global,
|
||||||
|
Wrap,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Step 7
|
||||||
|
Ok(channel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageChannelMethods for MessageChannel {
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#dom-messagechannel-port1>
|
||||||
|
fn Port1(&self) -> DomRoot<MessagePort> {
|
||||||
|
DomRoot::from_ref(&*self.port1)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#dom-messagechannel-port2>
|
||||||
|
fn Port2(&self) -> DomRoot<MessagePort> {
|
||||||
|
DomRoot::from_ref(&*self.port2)
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,9 +11,11 @@ use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot};
|
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::DOMString;
|
||||||
use crate::dom::bindings::trace::RootedTraceableBox;
|
use crate::dom::bindings::trace::RootedTraceableBox;
|
||||||
|
use crate::dom::bindings::utils::message_ports_to_frozen_array;
|
||||||
use crate::dom::event::Event;
|
use crate::dom::event::Event;
|
||||||
use crate::dom::eventtarget::EventTarget;
|
use crate::dom::eventtarget::EventTarget;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::dom::messageport::MessagePort;
|
||||||
use crate::dom::windowproxy::WindowProxy;
|
use crate::dom::windowproxy::WindowProxy;
|
||||||
use crate::script_runtime::JSContext;
|
use crate::script_runtime::JSContext;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
|
@ -31,6 +33,7 @@ pub struct MessageEvent {
|
||||||
origin: DOMString,
|
origin: DOMString,
|
||||||
source: Option<Dom<WindowProxy>>,
|
source: Option<Dom<WindowProxy>>,
|
||||||
lastEventId: DOMString,
|
lastEventId: DOMString,
|
||||||
|
ports: Vec<DomRoot<MessagePort>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MessageEvent {
|
impl MessageEvent {
|
||||||
|
@ -41,6 +44,7 @@ impl MessageEvent {
|
||||||
DOMString::new(),
|
DOMString::new(),
|
||||||
None,
|
None,
|
||||||
DOMString::new(),
|
DOMString::new(),
|
||||||
|
vec![],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,13 +54,15 @@ impl MessageEvent {
|
||||||
origin: DOMString,
|
origin: DOMString,
|
||||||
source: Option<&WindowProxy>,
|
source: Option<&WindowProxy>,
|
||||||
lastEventId: DOMString,
|
lastEventId: DOMString,
|
||||||
|
ports: Vec<DomRoot<MessagePort>>,
|
||||||
) -> DomRoot<MessageEvent> {
|
) -> DomRoot<MessageEvent> {
|
||||||
let ev = Box::new(MessageEvent {
|
let ev = Box::new(MessageEvent {
|
||||||
event: Event::new_inherited(),
|
event: Event::new_inherited(),
|
||||||
data: Heap::default(),
|
data: Heap::default(),
|
||||||
origin: origin,
|
|
||||||
source: source.map(Dom::from_ref),
|
source: source.map(Dom::from_ref),
|
||||||
lastEventId: lastEventId,
|
origin,
|
||||||
|
lastEventId,
|
||||||
|
ports,
|
||||||
});
|
});
|
||||||
let ev = reflect_dom_object(ev, global, MessageEventBinding::Wrap);
|
let ev = reflect_dom_object(ev, global, MessageEventBinding::Wrap);
|
||||||
ev.data.set(data.get());
|
ev.data.set(data.get());
|
||||||
|
@ -73,8 +79,9 @@ impl MessageEvent {
|
||||||
origin: DOMString,
|
origin: DOMString,
|
||||||
source: Option<&WindowProxy>,
|
source: Option<&WindowProxy>,
|
||||||
lastEventId: DOMString,
|
lastEventId: DOMString,
|
||||||
|
ports: Vec<DomRoot<MessagePort>>,
|
||||||
) -> DomRoot<MessageEvent> {
|
) -> DomRoot<MessageEvent> {
|
||||||
let ev = MessageEvent::new_initialized(global, data, origin, source, lastEventId);
|
let ev = MessageEvent::new_initialized(global, data, origin, source, lastEventId, ports);
|
||||||
{
|
{
|
||||||
let event = ev.upcast::<Event>();
|
let event = ev.upcast::<Event>();
|
||||||
event.init_event(type_, bubbles, cancelable);
|
event.init_event(type_, bubbles, cancelable);
|
||||||
|
@ -100,6 +107,7 @@ impl MessageEvent {
|
||||||
init.origin.clone(),
|
init.origin.clone(),
|
||||||
source.as_ref().map(|source| &**source),
|
source.as_ref().map(|source| &**source),
|
||||||
init.lastEventId.clone(),
|
init.lastEventId.clone(),
|
||||||
|
init.ports.clone().unwrap_or(vec![]),
|
||||||
);
|
);
|
||||||
Ok(ev)
|
Ok(ev)
|
||||||
}
|
}
|
||||||
|
@ -112,6 +120,7 @@ impl MessageEvent {
|
||||||
message: HandleValue,
|
message: HandleValue,
|
||||||
origin: Option<&str>,
|
origin: Option<&str>,
|
||||||
source: Option<&WindowProxy>,
|
source: Option<&WindowProxy>,
|
||||||
|
ports: Vec<DomRoot<MessagePort>>,
|
||||||
) {
|
) {
|
||||||
let messageevent = MessageEvent::new(
|
let messageevent = MessageEvent::new(
|
||||||
scope,
|
scope,
|
||||||
|
@ -122,18 +131,39 @@ impl MessageEvent {
|
||||||
DOMString::from(origin.unwrap_or("")),
|
DOMString::from(origin.unwrap_or("")),
|
||||||
source,
|
source,
|
||||||
DOMString::new(),
|
DOMString::new(),
|
||||||
|
ports,
|
||||||
|
);
|
||||||
|
messageevent.upcast::<Event>().fire(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dispatch_error(target: &EventTarget, scope: &GlobalScope) {
|
||||||
|
let init = MessageEventBinding::MessageEventInit::empty();
|
||||||
|
let source = init
|
||||||
|
.source
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|inner| inner.as_ref().map(|source| source.window_proxy()));
|
||||||
|
let messageevent = MessageEvent::new(
|
||||||
|
scope,
|
||||||
|
atom!("messageerror"),
|
||||||
|
init.parent.bubbles,
|
||||||
|
init.parent.cancelable,
|
||||||
|
init.data.handle(),
|
||||||
|
init.origin.clone(),
|
||||||
|
source.as_ref().map(|source| &**source),
|
||||||
|
init.lastEventId.clone(),
|
||||||
|
init.ports.clone().unwrap_or(vec![]),
|
||||||
);
|
);
|
||||||
messageevent.upcast::<Event>().fire(target);
|
messageevent.upcast::<Event>().fire(target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MessageEventMethods for MessageEvent {
|
impl MessageEventMethods for MessageEvent {
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-messageevent-data
|
/// <https://html.spec.whatwg.org/multipage/#dom-messageevent-data>
|
||||||
fn Data(&self, _cx: JSContext) -> JSVal {
|
fn Data(&self, _cx: JSContext) -> JSVal {
|
||||||
self.data.get()
|
self.data.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-messageevent-origin
|
/// <https://html.spec.whatwg.org/multipage/#dom-messageevent-origin>
|
||||||
fn Origin(&self) -> DOMString {
|
fn Origin(&self) -> DOMString {
|
||||||
self.origin.clone()
|
self.origin.clone()
|
||||||
}
|
}
|
||||||
|
@ -145,13 +175,18 @@ impl MessageEventMethods for MessageEvent {
|
||||||
.and_then(|source| NonNull::new(source.reflector().get_jsobject().get()))
|
.and_then(|source| NonNull::new(source.reflector().get_jsobject().get()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-messageevent-lasteventid
|
/// <https://html.spec.whatwg.org/multipage/#dom-messageevent-lasteventid>
|
||||||
fn LastEventId(&self) -> DOMString {
|
fn LastEventId(&self) -> DOMString {
|
||||||
self.lastEventId.clone()
|
self.lastEventId.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#dom-event-istrusted
|
/// <https://dom.spec.whatwg.org/#dom-event-istrusted>
|
||||||
fn IsTrusted(&self) -> bool {
|
fn IsTrusted(&self) -> bool {
|
||||||
self.event.IsTrusted()
|
self.event.IsTrusted()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#dom-messageevent-ports>
|
||||||
|
fn Ports(&self, cx: JSContext) -> JSVal {
|
||||||
|
message_ports_to_frozen_array(self.ports.as_slice(), cx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
345
components/script/dom/messageport.rs
Normal file
345
components/script/dom/messageport.rs
Normal file
|
@ -0,0 +1,345 @@
|
||||||
|
/* 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 http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use crate::dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::MessagePortBinding::{
|
||||||
|
MessagePortMethods, PostMessageOptions, Wrap,
|
||||||
|
};
|
||||||
|
use crate::dom::bindings::conversions::root_from_object;
|
||||||
|
use crate::dom::bindings::error::{Error, ErrorResult};
|
||||||
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
|
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
||||||
|
use crate::dom::bindings::root::DomRoot;
|
||||||
|
use crate::dom::bindings::structuredclone::{self, StructuredDataHolder};
|
||||||
|
use crate::dom::bindings::trace::RootedTraceableBox;
|
||||||
|
use crate::dom::bindings::transferable::Transferable;
|
||||||
|
use crate::dom::eventtarget::EventTarget;
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::script_runtime::JSContext as SafeJSContext;
|
||||||
|
use dom_struct::dom_struct;
|
||||||
|
use js::jsapi::Heap;
|
||||||
|
use js::jsapi::{JSObject, MutableHandleObject};
|
||||||
|
use js::rust::{CustomAutoRooter, CustomAutoRooterGuard, HandleValue};
|
||||||
|
use msg::constellation_msg::{MessagePortId, MessagePortIndex, PipelineNamespaceId};
|
||||||
|
use script_traits::PortMessageTask;
|
||||||
|
use std::cell::{Cell, RefCell};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::convert::TryInto;
|
||||||
|
use std::num::NonZeroU32;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
#[dom_struct]
|
||||||
|
/// The MessagePort used in the DOM.
|
||||||
|
pub struct MessagePort {
|
||||||
|
eventtarget: EventTarget,
|
||||||
|
message_port_id: MessagePortId,
|
||||||
|
entangled_port: RefCell<Option<MessagePortId>>,
|
||||||
|
detached: Cell<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessagePort {
|
||||||
|
fn new_inherited(message_port_id: MessagePortId) -> MessagePort {
|
||||||
|
MessagePort {
|
||||||
|
eventtarget: EventTarget::new_inherited(),
|
||||||
|
entangled_port: RefCell::new(None),
|
||||||
|
detached: Cell::new(false),
|
||||||
|
message_port_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#create-a-new-messageport-object>
|
||||||
|
pub fn new(owner: &GlobalScope) -> DomRoot<MessagePort> {
|
||||||
|
let port_id = MessagePortId::new();
|
||||||
|
reflect_dom_object(Box::new(MessagePort::new_inherited(port_id)), owner, Wrap)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new port for an incoming transfer-received one.
|
||||||
|
fn new_transferred(
|
||||||
|
owner: &GlobalScope,
|
||||||
|
transferred_port: MessagePortId,
|
||||||
|
entangled_port: Option<MessagePortId>,
|
||||||
|
) -> DomRoot<MessagePort> {
|
||||||
|
reflect_dom_object(
|
||||||
|
Box::new(MessagePort {
|
||||||
|
message_port_id: transferred_port,
|
||||||
|
eventtarget: EventTarget::new_inherited(),
|
||||||
|
detached: Cell::new(false),
|
||||||
|
entangled_port: RefCell::new(entangled_port),
|
||||||
|
}),
|
||||||
|
owner,
|
||||||
|
Wrap,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#entangle>
|
||||||
|
pub fn entangle(&self, other_id: MessagePortId) {
|
||||||
|
*self.entangled_port.borrow_mut() = Some(other_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn message_port_id(&self) -> &MessagePortId {
|
||||||
|
&self.message_port_id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn detached(&self) -> bool {
|
||||||
|
self.detached.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#handler-messageport-onmessage>
|
||||||
|
fn set_onmessage(&self, listener: Option<Rc<EventHandlerNonNull>>) {
|
||||||
|
let eventtarget = self.upcast::<EventTarget>();
|
||||||
|
eventtarget.set_event_handler_common("message", listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#message-port-post-message-steps>
|
||||||
|
fn post_message_impl(
|
||||||
|
&self,
|
||||||
|
cx: SafeJSContext,
|
||||||
|
message: HandleValue,
|
||||||
|
transfer: CustomAutoRooterGuard<Vec<*mut JSObject>>,
|
||||||
|
) -> ErrorResult {
|
||||||
|
if self.detached.get() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 1 is the transfer argument.
|
||||||
|
|
||||||
|
let target_port = self.entangled_port.borrow();
|
||||||
|
|
||||||
|
// Step 3
|
||||||
|
let mut doomed = false;
|
||||||
|
|
||||||
|
let ports = transfer
|
||||||
|
.iter()
|
||||||
|
.filter_map(|&obj| root_from_object::<MessagePort>(obj, *cx).ok());
|
||||||
|
for port in ports {
|
||||||
|
// Step 2
|
||||||
|
if port.message_port_id() == self.message_port_id() {
|
||||||
|
return Err(Error::DataClone);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4
|
||||||
|
if let Some(target_id) = target_port.as_ref() {
|
||||||
|
if port.message_port_id() == target_id {
|
||||||
|
doomed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 5
|
||||||
|
let data = structuredclone::write(cx, message, Some(transfer))?;
|
||||||
|
|
||||||
|
if doomed {
|
||||||
|
// TODO: The spec says to optionally report such a case to a dev console.
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 6, done in MessagePortImpl.
|
||||||
|
|
||||||
|
let incumbent = match GlobalScope::incumbent() {
|
||||||
|
None => unreachable!("postMessage called with no incumbent global"),
|
||||||
|
Some(incumbent) => incumbent,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Step 7
|
||||||
|
let task = PortMessageTask {
|
||||||
|
origin: incumbent.origin().immutable().clone(),
|
||||||
|
data,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Have the global proxy this call to the corresponding MessagePortImpl.
|
||||||
|
self.global()
|
||||||
|
.post_messageport_msg(self.message_port_id().clone(), task);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Transferable for MessagePort {
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#message-ports:transfer-steps>
|
||||||
|
fn transfer(&self, sc_holder: &mut StructuredDataHolder) -> Result<u64, ()> {
|
||||||
|
if self.detached.get() {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let port_impls = match sc_holder {
|
||||||
|
StructuredDataHolder::Write(port_impls) => port_impls,
|
||||||
|
_ => panic!("Unexpected variant of StructuredDataHolder"),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.detached.set(true);
|
||||||
|
let id = self.message_port_id();
|
||||||
|
|
||||||
|
// 1. Run local transfer logic, and return the object to be transferred.
|
||||||
|
let transferred_port = self.global().mark_port_as_transferred(id);
|
||||||
|
|
||||||
|
// 2. Store the transferred object at a given key.
|
||||||
|
if let Some(ports) = port_impls.as_mut() {
|
||||||
|
ports.insert(id.clone(), transferred_port);
|
||||||
|
} else {
|
||||||
|
let mut ports = HashMap::new();
|
||||||
|
ports.insert(id.clone(), transferred_port);
|
||||||
|
*port_impls = Some(ports);
|
||||||
|
}
|
||||||
|
|
||||||
|
let PipelineNamespaceId(name_space) = id.clone().namespace_id;
|
||||||
|
let MessagePortIndex(index) = id.clone().index;
|
||||||
|
let index = index.get();
|
||||||
|
|
||||||
|
let mut big: [u8; 8] = [0; 8];
|
||||||
|
let name_space = name_space.to_ne_bytes();
|
||||||
|
let index = index.to_ne_bytes();
|
||||||
|
|
||||||
|
let (left, right) = big.split_at_mut(4);
|
||||||
|
left.copy_from_slice(&name_space);
|
||||||
|
right.copy_from_slice(&index);
|
||||||
|
|
||||||
|
// 3. Return a u64 representation of the key where the object is stored.
|
||||||
|
Ok(u64::from_ne_bytes(big))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://html.spec.whatwg.org/multipage/#message-ports:transfer-receiving-steps
|
||||||
|
fn transfer_receive(
|
||||||
|
owner: &DomRoot<GlobalScope>,
|
||||||
|
sc_holder: &mut StructuredDataHolder,
|
||||||
|
extra_data: u64,
|
||||||
|
return_object: MutableHandleObject,
|
||||||
|
) -> Result<(), ()> {
|
||||||
|
let (message_ports, port_impls) = match sc_holder {
|
||||||
|
StructuredDataHolder::Read {
|
||||||
|
message_ports,
|
||||||
|
port_impls,
|
||||||
|
..
|
||||||
|
} => (message_ports, port_impls),
|
||||||
|
_ => panic!("Unexpected variant of StructuredDataHolder"),
|
||||||
|
};
|
||||||
|
|
||||||
|
// 1. Re-build the key for the storage location
|
||||||
|
// of the transferred object.
|
||||||
|
let big: [u8; 8] = extra_data.to_ne_bytes();
|
||||||
|
let (name_space, index) = big.split_at(4);
|
||||||
|
|
||||||
|
let namespace_id = PipelineNamespaceId(u32::from_ne_bytes(
|
||||||
|
name_space
|
||||||
|
.try_into()
|
||||||
|
.expect("name_space to be a slice of four."),
|
||||||
|
));
|
||||||
|
let index = MessagePortIndex(
|
||||||
|
NonZeroU32::new(u32::from_ne_bytes(
|
||||||
|
index.try_into().expect("index to be a slice of four."),
|
||||||
|
))
|
||||||
|
.expect("Index to be non-zero"),
|
||||||
|
);
|
||||||
|
|
||||||
|
let id = MessagePortId {
|
||||||
|
namespace_id,
|
||||||
|
index,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 2. Get the transferred object from its storage, using the key.
|
||||||
|
// Assign the transfer-received port-impl, and total number of transferred ports.
|
||||||
|
let (ports_len, port_impl) = if let Some(ports) = port_impls.as_mut() {
|
||||||
|
let ports_len = ports.len();
|
||||||
|
let port_impl = ports.remove(&id).expect("Transferred port to be stored");
|
||||||
|
if ports.is_empty() {
|
||||||
|
*port_impls = None;
|
||||||
|
}
|
||||||
|
(ports_len, port_impl)
|
||||||
|
} else {
|
||||||
|
panic!("A messageport was transfer-received, yet the SC holder does not have any port impls");
|
||||||
|
};
|
||||||
|
|
||||||
|
let transferred_port =
|
||||||
|
MessagePort::new_transferred(&**owner, id.clone(), port_impl.entangled_port_id());
|
||||||
|
owner.track_message_port(&transferred_port, Some(port_impl));
|
||||||
|
|
||||||
|
return_object.set(transferred_port.reflector().rootable().get());
|
||||||
|
|
||||||
|
// Store the DOM port where it will be passed along to script in the message-event.
|
||||||
|
if let Some(ports) = message_ports.as_mut() {
|
||||||
|
ports.push(transferred_port);
|
||||||
|
} else {
|
||||||
|
let mut ports = Vec::with_capacity(ports_len);
|
||||||
|
ports.push(transferred_port);
|
||||||
|
*message_ports = Some(ports);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessagePortMethods for MessagePort {
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#dom-messageport-postmessage>
|
||||||
|
fn PostMessage(
|
||||||
|
&self,
|
||||||
|
cx: SafeJSContext,
|
||||||
|
message: HandleValue,
|
||||||
|
transfer: CustomAutoRooterGuard<Vec<*mut JSObject>>,
|
||||||
|
) -> ErrorResult {
|
||||||
|
if self.detached.get() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
self.post_message_impl(cx, message, transfer)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#dom-messageport-postmessage>
|
||||||
|
fn PostMessage_(
|
||||||
|
&self,
|
||||||
|
cx: SafeJSContext,
|
||||||
|
message: HandleValue,
|
||||||
|
options: RootedTraceableBox<PostMessageOptions>,
|
||||||
|
) -> ErrorResult {
|
||||||
|
if self.detached.get() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let mut rooted = CustomAutoRooter::new(
|
||||||
|
options
|
||||||
|
.transfer
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&Vec::with_capacity(0))
|
||||||
|
.iter()
|
||||||
|
.map(|js: &RootedTraceableBox<Heap<*mut JSObject>>| js.get())
|
||||||
|
.collect(),
|
||||||
|
);
|
||||||
|
let guard = CustomAutoRooterGuard::new(*cx, &mut rooted);
|
||||||
|
self.post_message_impl(cx, message, guard)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#dom-messageport-start>
|
||||||
|
fn Start(&self) {
|
||||||
|
if self.detached.get() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.global().start_message_port(self.message_port_id());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#dom-messageport-close>
|
||||||
|
fn Close(&self) {
|
||||||
|
if self.detached.get() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.detached.set(true);
|
||||||
|
self.global().close_message_port(self.message_port_id());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#handler-messageport-onmessage>
|
||||||
|
fn GetOnmessage(&self) -> Option<Rc<EventHandlerNonNull>> {
|
||||||
|
if self.detached.get() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let eventtarget = self.upcast::<EventTarget>();
|
||||||
|
eventtarget.get_event_handler_common("message")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#handler-messageport-onmessage>
|
||||||
|
fn SetOnmessage(&self, listener: Option<Rc<EventHandlerNonNull>>) {
|
||||||
|
if self.detached.get() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.set_onmessage(listener);
|
||||||
|
// Note: we cannot use the event_handler macro, due to the need to start the port.
|
||||||
|
self.global().start_message_port(self.message_port_id());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#handler-messageport-onmessageerror>
|
||||||
|
event_handler!(messageerror, GetOnmessageerror, SetOnmessageerror);
|
||||||
|
}
|
|
@ -401,7 +401,9 @@ pub mod mediaquerylist;
|
||||||
pub mod mediaquerylistevent;
|
pub mod mediaquerylistevent;
|
||||||
pub mod mediastream;
|
pub mod mediastream;
|
||||||
pub mod mediastreamtrack;
|
pub mod mediastreamtrack;
|
||||||
|
pub mod messagechannel;
|
||||||
pub mod messageevent;
|
pub mod messageevent;
|
||||||
|
pub mod messageport;
|
||||||
pub mod mimetype;
|
pub mod mimetype;
|
||||||
pub mod mimetypearray;
|
pub mod mimetypearray;
|
||||||
pub mod mouseevent;
|
pub mod mouseevent;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use crate::dom::abstractworker::SimpleWorkerErrorHandler;
|
use crate::dom::abstractworker::SimpleWorkerErrorHandler;
|
||||||
use crate::dom::bindings::cell::DomRefCell;
|
use crate::dom::bindings::cell::DomRefCell;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::MessagePortBinding::PostMessageOptions;
|
||||||
use crate::dom::bindings::codegen::Bindings::ServiceWorkerBinding::{
|
use crate::dom::bindings::codegen::Bindings::ServiceWorkerBinding::{
|
||||||
ServiceWorkerMethods, ServiceWorkerState, Wrap,
|
ServiceWorkerMethods, ServiceWorkerState, Wrap,
|
||||||
};
|
};
|
||||||
|
@ -13,13 +14,15 @@ use crate::dom::bindings::refcounted::Trusted;
|
||||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
||||||
use crate::dom::bindings::root::DomRoot;
|
use crate::dom::bindings::root::DomRoot;
|
||||||
use crate::dom::bindings::str::USVString;
|
use crate::dom::bindings::str::USVString;
|
||||||
use crate::dom::bindings::structuredclone::StructuredCloneData;
|
use crate::dom::bindings::structuredclone;
|
||||||
|
use crate::dom::bindings::trace::RootedTraceableBox;
|
||||||
use crate::dom::eventtarget::EventTarget;
|
use crate::dom::eventtarget::EventTarget;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::script_runtime::JSContext;
|
use crate::script_runtime::JSContext;
|
||||||
use crate::task::TaskOnce;
|
use crate::task::TaskOnce;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use js::rust::HandleValue;
|
use js::jsapi::{Heap, JSObject};
|
||||||
|
use js::rust::{CustomAutoRooter, CustomAutoRooterGuard, HandleValue};
|
||||||
use script_traits::{DOMMessage, ScriptMsg};
|
use script_traits::{DOMMessage, ScriptMsg};
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
@ -77,6 +80,34 @@ impl ServiceWorker {
|
||||||
pub fn get_script_url(&self) -> ServoUrl {
|
pub fn get_script_url(&self) -> ServoUrl {
|
||||||
ServoUrl::parse(&self.script_url.borrow().clone()).unwrap()
|
ServoUrl::parse(&self.script_url.borrow().clone()).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// https://w3c.github.io/ServiceWorker/#service-worker-postmessage
|
||||||
|
fn post_message_impl(
|
||||||
|
&self,
|
||||||
|
cx: JSContext,
|
||||||
|
message: HandleValue,
|
||||||
|
transfer: CustomAutoRooterGuard<Vec<*mut JSObject>>,
|
||||||
|
) -> ErrorResult {
|
||||||
|
// Step 1
|
||||||
|
if let ServiceWorkerState::Redundant = self.state.get() {
|
||||||
|
return Err(Error::InvalidState);
|
||||||
|
}
|
||||||
|
// Step 7
|
||||||
|
let data = structuredclone::write(cx, message, Some(transfer))?;
|
||||||
|
let incumbent = GlobalScope::incumbent().expect("no incumbent global?");
|
||||||
|
let msg_vec = DOMMessage {
|
||||||
|
origin: incumbent.origin().immutable().clone(),
|
||||||
|
data,
|
||||||
|
};
|
||||||
|
let _ = self
|
||||||
|
.global()
|
||||||
|
.script_to_constellation_chan()
|
||||||
|
.send(ScriptMsg::ForwardDOMMessage(
|
||||||
|
msg_vec,
|
||||||
|
self.scope_url.clone(),
|
||||||
|
));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServiceWorkerMethods for ServiceWorker {
|
impl ServiceWorkerMethods for ServiceWorker {
|
||||||
|
@ -90,23 +121,34 @@ impl ServiceWorkerMethods for ServiceWorker {
|
||||||
USVString(self.script_url.borrow().clone())
|
USVString(self.script_url.borrow().clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/ServiceWorker/#service-worker-postmessage
|
/// https://w3c.github.io/ServiceWorker/#service-worker-postmessage
|
||||||
fn PostMessage(&self, cx: JSContext, message: HandleValue) -> ErrorResult {
|
fn PostMessage(
|
||||||
// Step 1
|
&self,
|
||||||
if let ServiceWorkerState::Redundant = self.state.get() {
|
cx: JSContext,
|
||||||
return Err(Error::InvalidState);
|
message: HandleValue,
|
||||||
}
|
transfer: CustomAutoRooterGuard<Vec<*mut JSObject>>,
|
||||||
// Step 7
|
) -> ErrorResult {
|
||||||
let data = StructuredCloneData::write(*cx, message)?;
|
self.post_message_impl(cx, message, transfer)
|
||||||
let msg_vec = DOMMessage(data.move_to_arraybuffer());
|
}
|
||||||
let _ = self
|
|
||||||
.global()
|
/// https://w3c.github.io/ServiceWorker/#service-worker-postmessage
|
||||||
.script_to_constellation_chan()
|
fn PostMessage_(
|
||||||
.send(ScriptMsg::ForwardDOMMessage(
|
&self,
|
||||||
msg_vec,
|
cx: JSContext,
|
||||||
self.scope_url.clone(),
|
message: HandleValue,
|
||||||
));
|
options: RootedTraceableBox<PostMessageOptions>,
|
||||||
Ok(())
|
) -> ErrorResult {
|
||||||
|
let mut rooted = CustomAutoRooter::new(
|
||||||
|
options
|
||||||
|
.transfer
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&Vec::with_capacity(0))
|
||||||
|
.iter()
|
||||||
|
.map(|js: &RootedTraceableBox<Heap<*mut JSObject>>| js.get())
|
||||||
|
.collect(),
|
||||||
|
);
|
||||||
|
let guard = CustomAutoRooterGuard::new(*cx, &mut rooted);
|
||||||
|
self.post_message_impl(cx, message, guard)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/ServiceWorker/#service-worker-container-onerror-attribute
|
// https://w3c.github.io/ServiceWorker/#service-worker-container-onerror-attribute
|
||||||
|
|
|
@ -12,12 +12,14 @@ use crate::dom::bindings::codegen::Bindings::WorkerBinding::WorkerType;
|
||||||
use crate::dom::bindings::inheritance::Castable;
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
use crate::dom::bindings::root::{DomRoot, RootCollection, ThreadLocalStackRoots};
|
use crate::dom::bindings::root::{DomRoot, RootCollection, ThreadLocalStackRoots};
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::DOMString;
|
||||||
|
use crate::dom::bindings::structuredclone;
|
||||||
use crate::dom::dedicatedworkerglobalscope::AutoWorkerReset;
|
use crate::dom::dedicatedworkerglobalscope::AutoWorkerReset;
|
||||||
use crate::dom::event::Event;
|
use crate::dom::event::Event;
|
||||||
use crate::dom::eventtarget::EventTarget;
|
use crate::dom::eventtarget::EventTarget;
|
||||||
use crate::dom::extendableevent::ExtendableEvent;
|
use crate::dom::extendableevent::ExtendableEvent;
|
||||||
use crate::dom::extendablemessageevent::ExtendableMessageEvent;
|
use crate::dom::extendablemessageevent::ExtendableMessageEvent;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::dom::messageevent::MessageEvent;
|
||||||
use crate::dom::worker::TrustedWorkerAddress;
|
use crate::dom::worker::TrustedWorkerAddress;
|
||||||
use crate::dom::workerglobalscope::WorkerGlobalScope;
|
use crate::dom::workerglobalscope::WorkerGlobalScope;
|
||||||
use crate::fetch::load_whole_resource;
|
use crate::fetch::load_whole_resource;
|
||||||
|
@ -409,13 +411,22 @@ impl ServiceWorkerGlobalScope {
|
||||||
use self::ServiceWorkerScriptMsg::*;
|
use self::ServiceWorkerScriptMsg::*;
|
||||||
|
|
||||||
match msg {
|
match msg {
|
||||||
CommonWorker(WorkerScriptMsg::DOMMessage(data)) => {
|
CommonWorker(WorkerScriptMsg::DOMMessage { data, .. }) => {
|
||||||
let scope = self.upcast::<WorkerGlobalScope>();
|
let scope = self.upcast::<WorkerGlobalScope>();
|
||||||
let target = self.upcast();
|
let target = self.upcast();
|
||||||
let _ac = enter_realm(&*scope);
|
let _ac = enter_realm(&*scope);
|
||||||
rooted!(in(*scope.get_cx()) let mut message = UndefinedValue());
|
rooted!(in(*scope.get_cx()) let mut message = UndefinedValue());
|
||||||
data.read(scope.upcast(), message.handle_mut());
|
if let Ok(ports) = structuredclone::read(scope.upcast(), data, message.handle_mut())
|
||||||
ExtendableMessageEvent::dispatch_jsval(target, scope.upcast(), message.handle());
|
{
|
||||||
|
ExtendableMessageEvent::dispatch_jsval(
|
||||||
|
target,
|
||||||
|
scope.upcast(),
|
||||||
|
message.handle(),
|
||||||
|
ports,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
MessageEvent::dispatch_error(target, scope.upcast());
|
||||||
|
}
|
||||||
},
|
},
|
||||||
CommonWorker(WorkerScriptMsg::Common(msg)) => {
|
CommonWorker(WorkerScriptMsg::Common(msg)) => {
|
||||||
self.upcast::<WorkerGlobalScope>().process_event(msg);
|
self.upcast::<WorkerGlobalScope>().process_event(msg);
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
// https://html.spec.whatwg.org/multipage/#dedicatedworkerglobalscope
|
// https://html.spec.whatwg.org/multipage/#dedicatedworkerglobalscope
|
||||||
[Global=(Worker,DedicatedWorker), Exposed=DedicatedWorker]
|
[Global=(Worker,DedicatedWorker), Exposed=DedicatedWorker]
|
||||||
/*sealed*/ interface DedicatedWorkerGlobalScope : WorkerGlobalScope {
|
/*sealed*/ interface DedicatedWorkerGlobalScope : WorkerGlobalScope {
|
||||||
[Throws]
|
[Throws] void postMessage(any message, sequence<object> transfer);
|
||||||
void postMessage(any message/*, optional sequence<Transferable> transfer*/);
|
[Throws] void postMessage(any message, optional PostMessageOptions options = {});
|
||||||
attribute EventHandler onmessage;
|
attribute EventHandler onmessage;
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,7 +25,8 @@ interface DissimilarOriginWindow : GlobalScope {
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
readonly attribute boolean closed;
|
readonly attribute boolean closed;
|
||||||
[Throws] void postMessage(any message, DOMString targetOrigin);
|
[Throws] void postMessage(any message, USVString targetOrigin, optional sequence<object> transfer /*= []*/);
|
||||||
|
[Throws] void postMessage(any message, optional WindowPostMessageOptions options = {});
|
||||||
attribute any opener;
|
attribute any opener;
|
||||||
void blur();
|
void blur();
|
||||||
void focus();
|
void focus();
|
||||||
|
|
|
@ -12,7 +12,7 @@ interface ExtendableMessageEvent : ExtendableEvent {
|
||||||
readonly attribute DOMString origin;
|
readonly attribute DOMString origin;
|
||||||
readonly attribute DOMString lastEventId;
|
readonly attribute DOMString lastEventId;
|
||||||
// [SameObject] readonly attribute (Client or ServiceWorker /*or MessagePort*/)? source;
|
// [SameObject] readonly attribute (Client or ServiceWorker /*or MessagePort*/)? source;
|
||||||
// readonly attribute FrozenArray<MessagePort>? ports;
|
readonly attribute /*FrozenArray<MessagePort>*/any ports;
|
||||||
};
|
};
|
||||||
|
|
||||||
dictionary ExtendableMessageEventInit : ExtendableEventInit {
|
dictionary ExtendableMessageEventInit : ExtendableEventInit {
|
||||||
|
|
14
components/script/dom/webidls/MessageChannel.webidl
Normal file
14
components/script/dom/webidls/MessageChannel.webidl
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
/* 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 http://mozilla.org/MPL/2.0/. */
|
||||||
|
/*
|
||||||
|
* The origin of this IDL file is:
|
||||||
|
* https://html.spec.whatwg.org/multipage/#messagechannel
|
||||||
|
*/
|
||||||
|
|
||||||
|
[Exposed=(Window,Worker)]
|
||||||
|
interface MessageChannel {
|
||||||
|
[Throws] constructor();
|
||||||
|
readonly attribute MessagePort port1;
|
||||||
|
readonly attribute MessagePort port2;
|
||||||
|
};
|
|
@ -12,7 +12,7 @@ interface MessageEvent : Event {
|
||||||
// FIXME(#22617): WindowProxy is not exposed in Worker globals
|
// FIXME(#22617): WindowProxy is not exposed in Worker globals
|
||||||
readonly attribute object? source;
|
readonly attribute object? source;
|
||||||
//readonly attribute (WindowProxy or MessagePort)? source;
|
//readonly attribute (WindowProxy or MessagePort)? source;
|
||||||
//readonly attribute MessagePort[]? ports;
|
readonly attribute /*FrozenArray<MessagePort>*/any ports;
|
||||||
};
|
};
|
||||||
|
|
||||||
dictionary MessageEventInit : EventInit {
|
dictionary MessageEventInit : EventInit {
|
||||||
|
@ -22,5 +22,7 @@ dictionary MessageEventInit : EventInit {
|
||||||
//DOMString channel;
|
//DOMString channel;
|
||||||
Window? source;
|
Window? source;
|
||||||
//(WindowProxy or MessagePort)? source;
|
//(WindowProxy or MessagePort)? source;
|
||||||
//sequence<MessagePort> ports;
|
sequence<MessagePort> ports;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef (/*WindowProxy or */MessagePort or ServiceWorker) MessageEventSource;
|
||||||
|
|
23
components/script/dom/webidls/MessagePort.webidl
Normal file
23
components/script/dom/webidls/MessagePort.webidl
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/* 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 http://mozilla.org/MPL/2.0/. */
|
||||||
|
/*
|
||||||
|
* The origin of this IDL file is:
|
||||||
|
* https://html.spec.whatwg.org/multipage/#messageport
|
||||||
|
*/
|
||||||
|
|
||||||
|
[Exposed=(Window,Worker)]
|
||||||
|
interface MessagePort : EventTarget {
|
||||||
|
[Throws] void postMessage(any message, sequence<object> transfer /*= []*/);
|
||||||
|
[Throws] void postMessage(any message, optional PostMessageOptions options = {});
|
||||||
|
void start();
|
||||||
|
void close();
|
||||||
|
|
||||||
|
// event handlers
|
||||||
|
attribute EventHandler onmessage;
|
||||||
|
attribute EventHandler onmessageerror;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary PostMessageOptions {
|
||||||
|
sequence<object> transfer;
|
||||||
|
};
|
|
@ -7,7 +7,8 @@
|
||||||
interface ServiceWorker : EventTarget {
|
interface ServiceWorker : EventTarget {
|
||||||
readonly attribute USVString scriptURL;
|
readonly attribute USVString scriptURL;
|
||||||
readonly attribute ServiceWorkerState state;
|
readonly attribute ServiceWorkerState state;
|
||||||
[Throws] void postMessage(any message/*, optional sequence<object> transfer = []*/);
|
[Throws] void postMessage(any message, sequence<object> transfer);
|
||||||
|
[Throws] void postMessage(any message, optional PostMessageOptions options = {});
|
||||||
|
|
||||||
// event
|
// event
|
||||||
attribute EventHandler onstatechange;
|
attribute EventHandler onstatechange;
|
||||||
|
|
|
@ -63,9 +63,10 @@
|
||||||
unsigned long requestAnimationFrame(FrameRequestCallback callback);
|
unsigned long requestAnimationFrame(FrameRequestCallback callback);
|
||||||
void cancelAnimationFrame(unsigned long handle);
|
void cancelAnimationFrame(unsigned long handle);
|
||||||
|
|
||||||
//void postMessage(any message, DOMString targetOrigin, optional sequence<Transferable> transfer);
|
|
||||||
[Throws]
|
[Throws]
|
||||||
void postMessage(any message, DOMString targetOrigin);
|
void postMessage(any message, USVString targetOrigin, optional sequence<object> transfer /*= []*/);
|
||||||
|
[Throws]
|
||||||
|
void postMessage(any message, optional WindowPostMessageOptions options = {});
|
||||||
|
|
||||||
// also has obsolete members
|
// also has obsolete members
|
||||||
};
|
};
|
||||||
|
@ -173,3 +174,8 @@ partial interface Window {
|
||||||
[Pref="css.animations.testing.enabled"]
|
[Pref="css.animations.testing.enabled"]
|
||||||
readonly attribute unsigned long runningAnimationCount;
|
readonly attribute unsigned long runningAnimationCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dictionary WindowPostMessageOptions {
|
||||||
|
USVString targetOrigin = "/";
|
||||||
|
sequence<object> transfer;
|
||||||
|
};
|
||||||
|
|
|
@ -14,8 +14,8 @@ interface Worker : EventTarget {
|
||||||
[Throws] constructor(USVString scriptURL, optional WorkerOptions options = {});
|
[Throws] constructor(USVString scriptURL, optional WorkerOptions options = {});
|
||||||
void terminate();
|
void terminate();
|
||||||
|
|
||||||
[Throws] void postMessage(any message/*, sequence<object> transfer*/);
|
[Throws] void postMessage(any message, sequence<object> transfer);
|
||||||
// void postMessage(any message, optional PostMessageOptions options);
|
[Throws] void postMessage(any message, optional PostMessageOptions options = {});
|
||||||
attribute EventHandler onmessage;
|
attribute EventHandler onmessage;
|
||||||
attribute EventHandler onmessageerror;
|
attribute EventHandler onmessageerror;
|
||||||
};
|
};
|
||||||
|
|
|
@ -598,6 +598,7 @@ impl TaskOnce for MessageReceivedTask {
|
||||||
message.handle(),
|
message.handle(),
|
||||||
Some(&ws.origin().ascii_serialization()),
|
Some(&ws.origin().ascii_serialization()),
|
||||||
None,
|
None,
|
||||||
|
vec![],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ use crate::dom::bindings::codegen::Bindings::MediaQueryListBinding::MediaQueryLi
|
||||||
use crate::dom::bindings::codegen::Bindings::PermissionStatusBinding::PermissionState;
|
use crate::dom::bindings::codegen::Bindings::PermissionStatusBinding::PermissionState;
|
||||||
use crate::dom::bindings::codegen::Bindings::RequestBinding::RequestInit;
|
use crate::dom::bindings::codegen::Bindings::RequestBinding::RequestInit;
|
||||||
use crate::dom::bindings::codegen::Bindings::WindowBinding::{
|
use crate::dom::bindings::codegen::Bindings::WindowBinding::{
|
||||||
self, FrameRequestCallback, WindowMethods,
|
self, FrameRequestCallback, WindowMethods, WindowPostMessageOptions,
|
||||||
};
|
};
|
||||||
use crate::dom::bindings::codegen::Bindings::WindowBinding::{ScrollBehavior, ScrollToOptions};
|
use crate::dom::bindings::codegen::Bindings::WindowBinding::{ScrollBehavior, ScrollToOptions};
|
||||||
use crate::dom::bindings::codegen::UnionTypes::RequestOrUSVString;
|
use crate::dom::bindings::codegen::UnionTypes::RequestOrUSVString;
|
||||||
|
@ -24,7 +24,7 @@ use crate::dom::bindings::refcounted::Trusted;
|
||||||
use crate::dom::bindings::reflector::DomObject;
|
use crate::dom::bindings::reflector::DomObject;
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
|
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
|
||||||
use crate::dom::bindings::str::{DOMString, USVString};
|
use crate::dom::bindings::str::{DOMString, USVString};
|
||||||
use crate::dom::bindings::structuredclone::StructuredCloneData;
|
use crate::dom::bindings::structuredclone;
|
||||||
use crate::dom::bindings::trace::RootedTraceableBox;
|
use crate::dom::bindings::trace::RootedTraceableBox;
|
||||||
use crate::dom::bindings::utils::{GlobalStaticData, WindowProxyHandler};
|
use crate::dom::bindings::utils::{GlobalStaticData, WindowProxyHandler};
|
||||||
use crate::dom::bindings::weakref::DOMTracker;
|
use crate::dom::bindings::weakref::DOMTracker;
|
||||||
|
@ -79,13 +79,15 @@ use euclid::default::{Point2D as UntypedPoint2D, Rect as UntypedRect};
|
||||||
use euclid::{Point2D, Rect, Scale, Size2D, Vector2D};
|
use euclid::{Point2D, Rect, Scale, Size2D, Vector2D};
|
||||||
use ipc_channel::ipc::{channel, IpcSender};
|
use ipc_channel::ipc::{channel, IpcSender};
|
||||||
use ipc_channel::router::ROUTER;
|
use ipc_channel::router::ROUTER;
|
||||||
|
use js::jsapi::Heap;
|
||||||
use js::jsapi::JSAutoRealm;
|
use js::jsapi::JSAutoRealm;
|
||||||
|
use js::jsapi::JSObject;
|
||||||
use js::jsapi::JSPROP_ENUMERATE;
|
use js::jsapi::JSPROP_ENUMERATE;
|
||||||
use js::jsapi::{GCReason, JS_GC};
|
use js::jsapi::{GCReason, JS_GC};
|
||||||
use js::jsval::UndefinedValue;
|
use js::jsval::UndefinedValue;
|
||||||
use js::jsval::{JSVal, NullValue};
|
use js::jsval::{JSVal, NullValue};
|
||||||
use js::rust::wrappers::JS_DefineProperty;
|
use js::rust::wrappers::JS_DefineProperty;
|
||||||
use js::rust::HandleValue;
|
use js::rust::{CustomAutoRooter, CustomAutoRooterGuard, HandleValue};
|
||||||
use media::WindowGLContext;
|
use media::WindowGLContext;
|
||||||
use msg::constellation_msg::PipelineId;
|
use msg::constellation_msg::PipelineId;
|
||||||
use net_traits::image_cache::{ImageCache, ImageResponder, ImageResponse};
|
use net_traits::image_cache::{ImageCache, ImageResponder, ImageResponse};
|
||||||
|
@ -104,7 +106,10 @@ use script_layout_interface::rpc::{
|
||||||
use script_layout_interface::{PendingImageState, TrustedNodeAddress};
|
use script_layout_interface::{PendingImageState, TrustedNodeAddress};
|
||||||
use script_traits::webdriver_msg::{WebDriverJSError, WebDriverJSResult};
|
use script_traits::webdriver_msg::{WebDriverJSError, WebDriverJSResult};
|
||||||
use script_traits::{ConstellationControlMsg, DocumentState, HistoryEntryReplacement, LoadData};
|
use script_traits::{ConstellationControlMsg, DocumentState, HistoryEntryReplacement, LoadData};
|
||||||
use script_traits::{ScriptMsg, ScriptToConstellationChan, ScrollState, TimerEvent, TimerEventId};
|
use script_traits::{
|
||||||
|
ScriptMsg, ScriptToConstellationChan, ScrollState, StructuredSerializedData, TimerEvent,
|
||||||
|
TimerEventId,
|
||||||
|
};
|
||||||
use script_traits::{TimerSchedulerMsg, WindowSizeData, WindowSizeType};
|
use script_traits::{TimerSchedulerMsg, WindowSizeData, WindowSizeType};
|
||||||
use selectors::attr::CaseSensitivity;
|
use selectors::attr::CaseSensitivity;
|
||||||
use servo_geometry::{f32_rect_to_au_rect, MaxRect};
|
use servo_geometry::{f32_rect_to_au_rect, MaxRect};
|
||||||
|
@ -969,27 +974,57 @@ impl WindowMethods for Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-window-postmessage
|
// https://html.spec.whatwg.org/multipage/#dom-window-postmessage
|
||||||
fn PostMessage(&self, cx: JSContext, message: HandleValue, origin: DOMString) -> ErrorResult {
|
fn PostMessage(
|
||||||
let source_global = GlobalScope::incumbent().expect("no incumbent global??");
|
&self,
|
||||||
let source = source_global.as_window();
|
cx: JSContext,
|
||||||
|
message: HandleValue,
|
||||||
|
target_origin: USVString,
|
||||||
|
mut transfer: CustomAutoRooterGuard<Option<Vec<*mut JSObject>>>,
|
||||||
|
) -> ErrorResult {
|
||||||
|
let incumbent = GlobalScope::incumbent().expect("no incumbent global?");
|
||||||
|
let source = incumbent.as_window();
|
||||||
|
let source_origin = source.Document().origin().immutable().clone();
|
||||||
|
|
||||||
// Step 3-5.
|
if transfer.is_some() {
|
||||||
let origin = match &origin[..] {
|
let mut rooted = CustomAutoRooter::new(transfer.take().unwrap());
|
||||||
"*" => None,
|
let transfer = Some(CustomAutoRooterGuard::new(*cx, &mut rooted));
|
||||||
"/" => Some(source.Document().origin().immutable().clone()),
|
self.post_message_impl(&target_origin, source_origin, source, cx, message, transfer)
|
||||||
url => match ServoUrl::parse(&url) {
|
} else {
|
||||||
Ok(url) => Some(url.origin().clone()),
|
self.post_message_impl(&target_origin, source_origin, source, cx, message, None)
|
||||||
Err(_) => return Err(Error::Syntax),
|
}
|
||||||
},
|
}
|
||||||
};
|
|
||||||
|
|
||||||
// Step 1-2, 6-8.
|
/// <https://html.spec.whatwg.org/multipage/#dom-messageport-postmessage>
|
||||||
// TODO(#12717): Should implement the `transfer` argument.
|
fn PostMessage_(
|
||||||
let data = StructuredCloneData::write(*cx, message)?;
|
&self,
|
||||||
|
cx: JSContext,
|
||||||
|
message: HandleValue,
|
||||||
|
options: RootedTraceableBox<WindowPostMessageOptions>,
|
||||||
|
) -> ErrorResult {
|
||||||
|
let mut rooted = CustomAutoRooter::new(
|
||||||
|
options
|
||||||
|
.transfer
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&Vec::with_capacity(0))
|
||||||
|
.iter()
|
||||||
|
.map(|js: &RootedTraceableBox<Heap<*mut JSObject>>| js.get())
|
||||||
|
.collect(),
|
||||||
|
);
|
||||||
|
let transfer = Some(CustomAutoRooterGuard::new(*cx, &mut rooted));
|
||||||
|
|
||||||
// Step 9.
|
let incumbent = GlobalScope::incumbent().expect("no incumbent global?");
|
||||||
self.post_message(origin, &*source.window_proxy(), data);
|
let source = incumbent.as_window();
|
||||||
Ok(())
|
|
||||||
|
let source_origin = source.Document().origin().immutable().clone();
|
||||||
|
|
||||||
|
self.post_message_impl(
|
||||||
|
&options.targetOrigin,
|
||||||
|
source_origin,
|
||||||
|
source,
|
||||||
|
cx,
|
||||||
|
message,
|
||||||
|
transfer,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-window-captureevents
|
// https://html.spec.whatwg.org/multipage/#dom-window-captureevents
|
||||||
|
@ -1287,6 +1322,34 @@ impl WindowMethods for Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
|
/// https://html.spec.whatwg.org/multipage/#window-post-message-steps
|
||||||
|
fn post_message_impl(
|
||||||
|
&self,
|
||||||
|
target_origin: &USVString,
|
||||||
|
source_origin: ImmutableOrigin,
|
||||||
|
source: &Window,
|
||||||
|
cx: JSContext,
|
||||||
|
message: HandleValue,
|
||||||
|
transfer: Option<CustomAutoRooterGuard<Vec<*mut JSObject>>>,
|
||||||
|
) -> ErrorResult {
|
||||||
|
// Step 1-2, 6-8.
|
||||||
|
let data = structuredclone::write(cx, message, transfer)?;
|
||||||
|
|
||||||
|
// Step 3-5.
|
||||||
|
let target_origin = match target_origin.0[..].as_ref() {
|
||||||
|
"*" => None,
|
||||||
|
"/" => Some(source_origin.clone()),
|
||||||
|
url => match ServoUrl::parse(&url) {
|
||||||
|
Ok(url) => Some(url.origin().clone()),
|
||||||
|
Err(_) => return Err(Error::Syntax),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Step 9.
|
||||||
|
self.post_message(target_origin, source_origin, &*source.window_proxy(), data);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
// https://drafts.css-houdini.org/css-paint-api-1/#paint-worklet
|
// https://drafts.css-houdini.org/css-paint-api-1/#paint-worklet
|
||||||
pub fn paint_worklet(&self) -> DomRoot<Worklet> {
|
pub fn paint_worklet(&self) -> DomRoot<Worklet> {
|
||||||
self.paint_worklet.or_init(|| self.new_paint_worklet())
|
self.paint_worklet.or_init(|| self.new_paint_worklet())
|
||||||
|
@ -1333,6 +1396,9 @@ impl Window {
|
||||||
// thread, informing it that it can safely free the memory.
|
// thread, informing it that it can safely free the memory.
|
||||||
self.Document().upcast::<Node>().teardown();
|
self.Document().upcast::<Node>().teardown();
|
||||||
|
|
||||||
|
// Tell the constellation to drop the sender to our message-port router, if there is any.
|
||||||
|
self.upcast::<GlobalScope>().remove_message_ports_router();
|
||||||
|
|
||||||
// Clean up any active promises
|
// Clean up any active promises
|
||||||
// https://github.com/servo/servo/issues/15318
|
// https://github.com/servo/servo/issues/15318
|
||||||
if let Some(custom_elements) = self.custom_element_registry.get() {
|
if let Some(custom_elements) = self.custom_element_registry.get() {
|
||||||
|
@ -2334,18 +2400,20 @@ impl Window {
|
||||||
pub fn post_message(
|
pub fn post_message(
|
||||||
&self,
|
&self,
|
||||||
target_origin: Option<ImmutableOrigin>,
|
target_origin: Option<ImmutableOrigin>,
|
||||||
|
source_origin: ImmutableOrigin,
|
||||||
source: &WindowProxy,
|
source: &WindowProxy,
|
||||||
serialize_with_transfer_result: StructuredCloneData,
|
data: StructuredSerializedData,
|
||||||
) {
|
) {
|
||||||
let this = Trusted::new(self);
|
let this = Trusted::new(self);
|
||||||
let source = Trusted::new(source);
|
let source = Trusted::new(source);
|
||||||
let task = task!(post_serialised_message: move || {
|
let task = task!(post_serialised_message: move || {
|
||||||
let this = this.root();
|
let this = this.root();
|
||||||
let source = source.root();
|
let source = source.root();
|
||||||
|
let document = this.Document();
|
||||||
|
|
||||||
// Step 7.1.
|
// Step 7.1.
|
||||||
if let Some(target_origin) = target_origin {
|
if let Some(ref target_origin) = target_origin {
|
||||||
if !target_origin.same_origin(this.Document().origin()) {
|
if !target_origin.same_origin(document.origin()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2355,23 +2423,23 @@ impl Window {
|
||||||
let obj = this.reflector().get_jsobject();
|
let obj = this.reflector().get_jsobject();
|
||||||
let _ac = JSAutoRealm::new(*cx, obj.get());
|
let _ac = JSAutoRealm::new(*cx, obj.get());
|
||||||
rooted!(in(*cx) let mut message_clone = UndefinedValue());
|
rooted!(in(*cx) let mut message_clone = UndefinedValue());
|
||||||
serialize_with_transfer_result.read(
|
if let Ok(ports) = structuredclone::read(this.upcast(), data, message_clone.handle_mut()) {
|
||||||
this.upcast(),
|
// Step 7.6, 7.7
|
||||||
message_clone.handle_mut(),
|
MessageEvent::dispatch_jsval(
|
||||||
);
|
this.upcast(),
|
||||||
|
this.upcast(),
|
||||||
// Step 7.6.
|
message_clone.handle(),
|
||||||
// TODO: MessagePort array.
|
Some(&source_origin.ascii_serialization()),
|
||||||
|
Some(&*source),
|
||||||
// Step 7.7.
|
ports,
|
||||||
// TODO(#12719): Set the other attributes.
|
);
|
||||||
MessageEvent::dispatch_jsval(
|
} else {
|
||||||
this.upcast(),
|
// Step 4, fire messageerror.
|
||||||
this.upcast(),
|
MessageEvent::dispatch_error(
|
||||||
message_clone.handle(),
|
this.upcast(),
|
||||||
None,
|
this.upcast(),
|
||||||
Some(&*source),
|
);
|
||||||
);
|
}
|
||||||
});
|
});
|
||||||
// FIXME(nox): Why are errors silenced here?
|
// FIXME(nox): Why are errors silenced here?
|
||||||
// TODO(#12718): Use the "posted message task source".
|
// TODO(#12718): Use the "posted message task source".
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
use crate::compartments::enter_realm;
|
use crate::compartments::enter_realm;
|
||||||
use crate::dom::abstractworker::SimpleWorkerErrorHandler;
|
use crate::dom::abstractworker::SimpleWorkerErrorHandler;
|
||||||
use crate::dom::abstractworker::WorkerScriptMsg;
|
use crate::dom::abstractworker::WorkerScriptMsg;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::MessagePortBinding::PostMessageOptions;
|
||||||
use crate::dom::bindings::codegen::Bindings::WorkerBinding;
|
use crate::dom::bindings::codegen::Bindings::WorkerBinding;
|
||||||
use crate::dom::bindings::codegen::Bindings::WorkerBinding::{WorkerMethods, WorkerOptions};
|
use crate::dom::bindings::codegen::Bindings::WorkerBinding::{WorkerMethods, WorkerOptions};
|
||||||
use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
|
use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
|
||||||
|
@ -13,7 +14,8 @@ use crate::dom::bindings::refcounted::Trusted;
|
||||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
||||||
use crate::dom::bindings::root::DomRoot;
|
use crate::dom::bindings::root::DomRoot;
|
||||||
use crate::dom::bindings::str::USVString;
|
use crate::dom::bindings::str::USVString;
|
||||||
use crate::dom::bindings::structuredclone::StructuredCloneData;
|
use crate::dom::bindings::structuredclone;
|
||||||
|
use crate::dom::bindings::trace::RootedTraceableBox;
|
||||||
use crate::dom::dedicatedworkerglobalscope::{
|
use crate::dom::dedicatedworkerglobalscope::{
|
||||||
DedicatedWorkerGlobalScope, DedicatedWorkerScriptMsg,
|
DedicatedWorkerGlobalScope, DedicatedWorkerScriptMsg,
|
||||||
};
|
};
|
||||||
|
@ -27,10 +29,10 @@ use crossbeam_channel::{unbounded, Sender};
|
||||||
use devtools_traits::{DevtoolsPageInfo, ScriptToDevtoolsControlMsg};
|
use devtools_traits::{DevtoolsPageInfo, ScriptToDevtoolsControlMsg};
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use ipc_channel::ipc;
|
use ipc_channel::ipc;
|
||||||
use js::jsapi::JS_RequestInterruptCallback;
|
use js::jsapi::{Heap, JSObject, JS_RequestInterruptCallback};
|
||||||
use js::jsval::UndefinedValue;
|
use js::jsval::UndefinedValue;
|
||||||
use js::rust::HandleValue;
|
use js::rust::{CustomAutoRooter, CustomAutoRooterGuard, HandleValue};
|
||||||
use script_traits::WorkerScriptLoadOrigin;
|
use script_traits::{StructuredSerializedData, WorkerScriptLoadOrigin};
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -137,7 +139,11 @@ impl Worker {
|
||||||
self.terminated.get()
|
self.terminated.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_message(address: TrustedWorkerAddress, data: StructuredCloneData) {
|
pub fn handle_message(
|
||||||
|
address: TrustedWorkerAddress,
|
||||||
|
origin: String,
|
||||||
|
data: StructuredSerializedData,
|
||||||
|
) {
|
||||||
let worker = address.root();
|
let worker = address.root();
|
||||||
|
|
||||||
if worker.is_terminated() {
|
if worker.is_terminated() {
|
||||||
|
@ -148,30 +154,79 @@ impl Worker {
|
||||||
let target = worker.upcast();
|
let target = worker.upcast();
|
||||||
let _ac = enter_realm(target);
|
let _ac = enter_realm(target);
|
||||||
rooted!(in(*global.get_cx()) let mut message = UndefinedValue());
|
rooted!(in(*global.get_cx()) let mut message = UndefinedValue());
|
||||||
data.read(&global, message.handle_mut());
|
if let Ok(ports) = structuredclone::read(&global, data, message.handle_mut()) {
|
||||||
MessageEvent::dispatch_jsval(target, &global, message.handle(), None, None);
|
MessageEvent::dispatch_jsval(
|
||||||
|
target,
|
||||||
|
&global,
|
||||||
|
message.handle(),
|
||||||
|
Some(&origin),
|
||||||
|
None,
|
||||||
|
ports,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Step 4 of the "port post message steps" of the implicit messageport, fire messageerror.
|
||||||
|
MessageEvent::dispatch_error(target, &global);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dispatch_simple_error(address: TrustedWorkerAddress) {
|
pub fn dispatch_simple_error(address: TrustedWorkerAddress) {
|
||||||
let worker = address.root();
|
let worker = address.root();
|
||||||
worker.upcast().fire_event(atom!("error"));
|
worker.upcast().fire_event(atom!("error"));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl WorkerMethods for Worker {
|
/// https://html.spec.whatwg.org/multipage/#dom-dedicatedworkerglobalscope-postmessage
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-worker-postmessage
|
fn post_message_impl(
|
||||||
fn PostMessage(&self, cx: JSContext, message: HandleValue) -> ErrorResult {
|
&self,
|
||||||
let data = StructuredCloneData::write(*cx, message)?;
|
cx: JSContext,
|
||||||
|
message: HandleValue,
|
||||||
|
transfer: CustomAutoRooterGuard<Vec<*mut JSObject>>,
|
||||||
|
) -> ErrorResult {
|
||||||
|
let data = structuredclone::write(cx, message, Some(transfer))?;
|
||||||
let address = Trusted::new(self);
|
let address = Trusted::new(self);
|
||||||
|
|
||||||
// NOTE: step 9 of https://html.spec.whatwg.org/multipage/#dom-messageport-postmessage
|
// NOTE: step 9 of https://html.spec.whatwg.org/multipage/#dom-messageport-postmessage
|
||||||
// indicates that a nonexistent communication channel should result in a silent error.
|
// indicates that a nonexistent communication channel should result in a silent error.
|
||||||
let _ = self.sender.send(DedicatedWorkerScriptMsg::CommonWorker(
|
let _ = self.sender.send(DedicatedWorkerScriptMsg::CommonWorker(
|
||||||
address,
|
address,
|
||||||
WorkerScriptMsg::DOMMessage(data),
|
WorkerScriptMsg::DOMMessage {
|
||||||
|
origin: self.global().origin().immutable().clone(),
|
||||||
|
data,
|
||||||
|
},
|
||||||
));
|
));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WorkerMethods for Worker {
|
||||||
|
/// https://html.spec.whatwg.org/multipage/#dom-worker-postmessage
|
||||||
|
fn PostMessage(
|
||||||
|
&self,
|
||||||
|
cx: JSContext,
|
||||||
|
message: HandleValue,
|
||||||
|
transfer: CustomAutoRooterGuard<Vec<*mut JSObject>>,
|
||||||
|
) -> ErrorResult {
|
||||||
|
self.post_message_impl(cx, message, transfer)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://html.spec.whatwg.org/multipage/#dom-worker-postmessage
|
||||||
|
fn PostMessage_(
|
||||||
|
&self,
|
||||||
|
cx: JSContext,
|
||||||
|
message: HandleValue,
|
||||||
|
options: RootedTraceableBox<PostMessageOptions>,
|
||||||
|
) -> ErrorResult {
|
||||||
|
let mut rooted = CustomAutoRooter::new(
|
||||||
|
options
|
||||||
|
.transfer
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&Vec::with_capacity(0))
|
||||||
|
.iter()
|
||||||
|
.map(|js: &RootedTraceableBox<Heap<*mut JSObject>>| js.get())
|
||||||
|
.collect(),
|
||||||
|
);
|
||||||
|
let guard = CustomAutoRooterGuard::new(*cx, &mut rooted);
|
||||||
|
self.post_message_impl(cx, message, guard)
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
// https://html.spec.whatwg.org/multipage/#terminate-a-worker
|
// https://html.spec.whatwg.org/multipage/#terminate-a-worker
|
||||||
|
|
|
@ -33,6 +33,7 @@ use crate::task_source::dom_manipulation::DOMManipulationTaskSource;
|
||||||
use crate::task_source::file_reading::FileReadingTaskSource;
|
use crate::task_source::file_reading::FileReadingTaskSource;
|
||||||
use crate::task_source::networking::NetworkingTaskSource;
|
use crate::task_source::networking::NetworkingTaskSource;
|
||||||
use crate::task_source::performance_timeline::PerformanceTimelineTaskSource;
|
use crate::task_source::performance_timeline::PerformanceTimelineTaskSource;
|
||||||
|
use crate::task_source::port_message::PortMessageQueue;
|
||||||
use crate::task_source::remote_event::RemoteEventTaskSource;
|
use crate::task_source::remote_event::RemoteEventTaskSource;
|
||||||
use crate::task_source::websocket::WebsocketTaskSource;
|
use crate::task_source::websocket::WebsocketTaskSource;
|
||||||
use crate::timers::{IsInterval, TimerCallback};
|
use crate::timers::{IsInterval, TimerCallback};
|
||||||
|
@ -457,6 +458,10 @@ impl WorkerGlobalScope {
|
||||||
PerformanceTimelineTaskSource(self.script_chan(), self.pipeline_id())
|
PerformanceTimelineTaskSource(self.script_chan(), self.pipeline_id())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn port_message_queue(&self) -> PortMessageQueue {
|
||||||
|
PortMessageQueue(self.script_chan(), self.pipeline_id())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn remote_event_task_source(&self) -> RemoteEventTaskSource {
|
pub fn remote_event_task_source(&self) -> RemoteEventTaskSource {
|
||||||
RemoteEventTaskSource(self.script_chan(), self.pipeline_id())
|
RemoteEventTaskSource(self.script_chan(), self.pipeline_id())
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,6 +115,7 @@ pub enum ScriptThreadEventCategory {
|
||||||
ImageCacheMsg,
|
ImageCacheMsg,
|
||||||
InputEvent,
|
InputEvent,
|
||||||
NetworkEvent,
|
NetworkEvent,
|
||||||
|
PortMessage,
|
||||||
Resize,
|
Resize,
|
||||||
ScriptEvent,
|
ScriptEvent,
|
||||||
SetScrollState,
|
SetScrollState,
|
||||||
|
|
|
@ -38,7 +38,6 @@ use crate::dom::bindings::reflector::DomObject;
|
||||||
use crate::dom::bindings::root::ThreadLocalStackRoots;
|
use crate::dom::bindings::root::ThreadLocalStackRoots;
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom, RootCollection};
|
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom, RootCollection};
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::DOMString;
|
||||||
use crate::dom::bindings::structuredclone::StructuredCloneData;
|
|
||||||
use crate::dom::bindings::trace::JSTraceable;
|
use crate::dom::bindings::trace::JSTraceable;
|
||||||
use crate::dom::bindings::utils::WRAP_CALLBACKS;
|
use crate::dom::bindings::utils::WRAP_CALLBACKS;
|
||||||
use crate::dom::customelementregistry::{
|
use crate::dom::customelementregistry::{
|
||||||
|
@ -81,6 +80,7 @@ use crate::task_source::history_traversal::HistoryTraversalTaskSource;
|
||||||
use crate::task_source::media_element::MediaElementTaskSource;
|
use crate::task_source::media_element::MediaElementTaskSource;
|
||||||
use crate::task_source::networking::NetworkingTaskSource;
|
use crate::task_source::networking::NetworkingTaskSource;
|
||||||
use crate::task_source::performance_timeline::PerformanceTimelineTaskSource;
|
use crate::task_source::performance_timeline::PerformanceTimelineTaskSource;
|
||||||
|
use crate::task_source::port_message::PortMessageQueue;
|
||||||
use crate::task_source::remote_event::RemoteEventTaskSource;
|
use crate::task_source::remote_event::RemoteEventTaskSource;
|
||||||
use crate::task_source::user_interaction::UserInteractionTaskSource;
|
use crate::task_source::user_interaction::UserInteractionTaskSource;
|
||||||
use crate::task_source::websocket::WebsocketTaskSource;
|
use crate::task_source::websocket::WebsocketTaskSource;
|
||||||
|
@ -132,6 +132,7 @@ use script_traits::CompositorEvent::{
|
||||||
CompositionEvent, KeyboardEvent, MouseButtonEvent, MouseMoveEvent, ResizeEvent, TouchEvent,
|
CompositionEvent, KeyboardEvent, MouseButtonEvent, MouseMoveEvent, ResizeEvent, TouchEvent,
|
||||||
WheelEvent,
|
WheelEvent,
|
||||||
};
|
};
|
||||||
|
use script_traits::StructuredSerializedData;
|
||||||
use script_traits::{CompositorEvent, ConstellationControlMsg};
|
use script_traits::{CompositorEvent, ConstellationControlMsg};
|
||||||
use script_traits::{
|
use script_traits::{
|
||||||
DiscardBrowsingContext, DocumentActivity, EventResult, HistoryEntryReplacement,
|
DiscardBrowsingContext, DocumentActivity, EventResult, HistoryEntryReplacement,
|
||||||
|
@ -566,6 +567,8 @@ pub struct ScriptThread {
|
||||||
|
|
||||||
performance_timeline_task_sender: Box<dyn ScriptChan>,
|
performance_timeline_task_sender: Box<dyn ScriptChan>,
|
||||||
|
|
||||||
|
port_message_sender: Box<dyn ScriptChan>,
|
||||||
|
|
||||||
remote_event_task_sender: Box<dyn ScriptChan>,
|
remote_event_task_sender: Box<dyn ScriptChan>,
|
||||||
|
|
||||||
/// A channel to hand out to threads that need to respond to a message from the script thread.
|
/// A channel to hand out to threads that need to respond to a message from the script thread.
|
||||||
|
@ -1296,6 +1299,7 @@ impl ScriptThread {
|
||||||
media_element_task_sender: chan.clone(),
|
media_element_task_sender: chan.clone(),
|
||||||
user_interaction_task_sender: chan.clone(),
|
user_interaction_task_sender: chan.clone(),
|
||||||
networking_task_sender: boxed_script_sender.clone(),
|
networking_task_sender: boxed_script_sender.clone(),
|
||||||
|
port_message_sender: boxed_script_sender.clone(),
|
||||||
file_reading_task_sender: boxed_script_sender.clone(),
|
file_reading_task_sender: boxed_script_sender.clone(),
|
||||||
performance_timeline_task_sender: boxed_script_sender.clone(),
|
performance_timeline_task_sender: boxed_script_sender.clone(),
|
||||||
remote_event_task_sender: boxed_script_sender.clone(),
|
remote_event_task_sender: boxed_script_sender.clone(),
|
||||||
|
@ -1585,6 +1589,11 @@ impl ScriptThread {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let window = document.window();
|
let window = document.window();
|
||||||
|
|
||||||
|
window
|
||||||
|
.upcast::<GlobalScope>()
|
||||||
|
.perform_a_message_port_garbage_collection_checkpoint();
|
||||||
|
|
||||||
let pending_reflows = window.get_pending_reflow_count();
|
let pending_reflows = window.get_pending_reflow_count();
|
||||||
if pending_reflows > 0 {
|
if pending_reflows > 0 {
|
||||||
window.reflow(ReflowGoal::Full, ReflowReason::ImageLoaded);
|
window.reflow(ReflowGoal::Full, ReflowReason::ImageLoaded);
|
||||||
|
@ -1656,6 +1665,7 @@ impl ScriptThread {
|
||||||
ScriptThreadEventCategory::PerformanceTimelineTask => {
|
ScriptThreadEventCategory::PerformanceTimelineTask => {
|
||||||
ScriptHangAnnotation::PerformanceTimelineTask
|
ScriptHangAnnotation::PerformanceTimelineTask
|
||||||
},
|
},
|
||||||
|
ScriptThreadEventCategory::PortMessage => ScriptHangAnnotation::PortMessage,
|
||||||
};
|
};
|
||||||
self.background_hang_monitor
|
self.background_hang_monitor
|
||||||
.notify_activity(HangAnnotation::Script(hang_annotation));
|
.notify_activity(HangAnnotation::Script(hang_annotation));
|
||||||
|
@ -1756,6 +1766,7 @@ impl ScriptThread {
|
||||||
ScriptThreadEventCategory::ImageCacheMsg => ProfilerCategory::ScriptImageCacheMsg,
|
ScriptThreadEventCategory::ImageCacheMsg => ProfilerCategory::ScriptImageCacheMsg,
|
||||||
ScriptThreadEventCategory::InputEvent => ProfilerCategory::ScriptInputEvent,
|
ScriptThreadEventCategory::InputEvent => ProfilerCategory::ScriptInputEvent,
|
||||||
ScriptThreadEventCategory::NetworkEvent => ProfilerCategory::ScriptNetworkEvent,
|
ScriptThreadEventCategory::NetworkEvent => ProfilerCategory::ScriptNetworkEvent,
|
||||||
|
ScriptThreadEventCategory::PortMessage => ProfilerCategory::ScriptPortMessage,
|
||||||
ScriptThreadEventCategory::Resize => ProfilerCategory::ScriptResize,
|
ScriptThreadEventCategory::Resize => ProfilerCategory::ScriptResize,
|
||||||
ScriptThreadEventCategory::ScriptEvent => ProfilerCategory::ScriptEvent,
|
ScriptThreadEventCategory::ScriptEvent => ProfilerCategory::ScriptEvent,
|
||||||
ScriptThreadEventCategory::SetScrollState => ProfilerCategory::ScriptSetScrollState,
|
ScriptThreadEventCategory::SetScrollState => ProfilerCategory::ScriptSetScrollState,
|
||||||
|
@ -1861,12 +1872,14 @@ impl ScriptThread {
|
||||||
source: source_pipeline_id,
|
source: source_pipeline_id,
|
||||||
source_browsing_context,
|
source_browsing_context,
|
||||||
target_origin: origin,
|
target_origin: origin,
|
||||||
|
source_origin,
|
||||||
data,
|
data,
|
||||||
} => self.handle_post_message_msg(
|
} => self.handle_post_message_msg(
|
||||||
target_pipeline_id,
|
target_pipeline_id,
|
||||||
source_pipeline_id,
|
source_pipeline_id,
|
||||||
source_browsing_context,
|
source_browsing_context,
|
||||||
origin,
|
origin,
|
||||||
|
source_origin,
|
||||||
data,
|
data,
|
||||||
),
|
),
|
||||||
ConstellationControlMsg::UpdatePipelineId(
|
ConstellationControlMsg::UpdatePipelineId(
|
||||||
|
@ -2519,7 +2532,8 @@ impl ScriptThread {
|
||||||
source_pipeline_id: PipelineId,
|
source_pipeline_id: PipelineId,
|
||||||
source_browsing_context: TopLevelBrowsingContextId,
|
source_browsing_context: TopLevelBrowsingContextId,
|
||||||
origin: Option<ImmutableOrigin>,
|
origin: Option<ImmutableOrigin>,
|
||||||
data: Vec<u8>,
|
source_origin: ImmutableOrigin,
|
||||||
|
data: StructuredSerializedData,
|
||||||
) {
|
) {
|
||||||
match { self.documents.borrow().find_window(pipeline_id) } {
|
match { self.documents.borrow().find_window(pipeline_id) } {
|
||||||
None => return warn!("postMessage after target pipeline {} closed.", pipeline_id),
|
None => return warn!("postMessage after target pipeline {} closed.", pipeline_id),
|
||||||
|
@ -2541,7 +2555,7 @@ impl ScriptThread {
|
||||||
Some(source) => source,
|
Some(source) => source,
|
||||||
};
|
};
|
||||||
// FIXME(#22512): enqueues a task; unnecessary delay.
|
// FIXME(#22512): enqueues a task; unnecessary delay.
|
||||||
window.post_message(origin, &*source, StructuredCloneData::Vector(data))
|
window.post_message(origin, source_origin, &*source, data)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2780,6 +2794,10 @@ impl ScriptThread {
|
||||||
NetworkingTaskSource(self.networking_task_sender.clone(), pipeline_id)
|
NetworkingTaskSource(self.networking_task_sender.clone(), pipeline_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn port_message_queue(&self, pipeline_id: PipelineId) -> PortMessageQueue {
|
||||||
|
PortMessageQueue(self.port_message_sender.clone(), pipeline_id)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn file_reading_task_source(&self, pipeline_id: PipelineId) -> FileReadingTaskSource {
|
pub fn file_reading_task_source(&self, pipeline_id: PipelineId) -> FileReadingTaskSource {
|
||||||
FileReadingTaskSource(self.file_reading_task_sender.clone(), pipeline_id)
|
FileReadingTaskSource(self.file_reading_task_sender.clone(), pipeline_id)
|
||||||
}
|
}
|
||||||
|
@ -3177,6 +3195,7 @@ impl ScriptThread {
|
||||||
self.networking_task_source(incomplete.pipeline_id),
|
self.networking_task_source(incomplete.pipeline_id),
|
||||||
self.performance_timeline_task_source(incomplete.pipeline_id)
|
self.performance_timeline_task_source(incomplete.pipeline_id)
|
||||||
.clone(),
|
.clone(),
|
||||||
|
self.port_message_queue(incomplete.pipeline_id),
|
||||||
self.user_interaction_task_source(incomplete.pipeline_id),
|
self.user_interaction_task_source(incomplete.pipeline_id),
|
||||||
self.remote_event_task_source(incomplete.pipeline_id),
|
self.remote_event_task_source(incomplete.pipeline_id),
|
||||||
self.websocket_task_source(incomplete.pipeline_id),
|
self.websocket_task_source(incomplete.pipeline_id),
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
//! active_workers map
|
//! active_workers map
|
||||||
|
|
||||||
use crate::dom::abstractworker::WorkerScriptMsg;
|
use crate::dom::abstractworker::WorkerScriptMsg;
|
||||||
use crate::dom::bindings::structuredclone::StructuredCloneData;
|
|
||||||
use crate::dom::serviceworkerglobalscope::{ServiceWorkerGlobalScope, ServiceWorkerScriptMsg};
|
use crate::dom::serviceworkerglobalscope::{ServiceWorkerGlobalScope, ServiceWorkerScriptMsg};
|
||||||
use crate::dom::serviceworkerregistration::longest_prefix_match;
|
use crate::dom::serviceworkerregistration::longest_prefix_match;
|
||||||
use crossbeam_channel::{unbounded, Receiver, RecvError, Sender};
|
use crossbeam_channel::{unbounded, Receiver, RecvError, Sender};
|
||||||
|
@ -135,10 +134,9 @@ impl ServiceWorkerManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn forward_message(&self, msg: DOMMessage, sender: &Sender<ServiceWorkerScriptMsg>) {
|
fn forward_message(&self, msg: DOMMessage, sender: &Sender<ServiceWorkerScriptMsg>) {
|
||||||
let DOMMessage(data) = msg;
|
let DOMMessage { origin, data } = msg;
|
||||||
let data = StructuredCloneData::Vector(data);
|
|
||||||
let _ = sender.send(ServiceWorkerScriptMsg::CommonWorker(
|
let _ = sender.send(ServiceWorkerScriptMsg::CommonWorker(
|
||||||
WorkerScriptMsg::DOMMessage(data),
|
WorkerScriptMsg::DOMMessage { origin, data },
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ use crate::task_source::history_traversal::HistoryTraversalTaskSource;
|
||||||
use crate::task_source::media_element::MediaElementTaskSource;
|
use crate::task_source::media_element::MediaElementTaskSource;
|
||||||
use crate::task_source::networking::NetworkingTaskSource;
|
use crate::task_source::networking::NetworkingTaskSource;
|
||||||
use crate::task_source::performance_timeline::PerformanceTimelineTaskSource;
|
use crate::task_source::performance_timeline::PerformanceTimelineTaskSource;
|
||||||
|
use crate::task_source::port_message::PortMessageQueue;
|
||||||
use crate::task_source::remote_event::RemoteEventTaskSource;
|
use crate::task_source::remote_event::RemoteEventTaskSource;
|
||||||
use crate::task_source::user_interaction::UserInteractionTaskSource;
|
use crate::task_source::user_interaction::UserInteractionTaskSource;
|
||||||
use crate::task_source::websocket::WebsocketTaskSource;
|
use crate::task_source::websocket::WebsocketTaskSource;
|
||||||
|
@ -47,6 +48,8 @@ pub struct TaskManager {
|
||||||
#[ignore_malloc_size_of = "task sources are hard"]
|
#[ignore_malloc_size_of = "task sources are hard"]
|
||||||
performance_timeline_task_source: PerformanceTimelineTaskSource,
|
performance_timeline_task_source: PerformanceTimelineTaskSource,
|
||||||
#[ignore_malloc_size_of = "task sources are hard"]
|
#[ignore_malloc_size_of = "task sources are hard"]
|
||||||
|
port_message_queue: PortMessageQueue,
|
||||||
|
#[ignore_malloc_size_of = "task sources are hard"]
|
||||||
user_interaction_task_source: UserInteractionTaskSource,
|
user_interaction_task_source: UserInteractionTaskSource,
|
||||||
#[ignore_malloc_size_of = "task sources are hard"]
|
#[ignore_malloc_size_of = "task sources are hard"]
|
||||||
remote_event_task_source: RemoteEventTaskSource,
|
remote_event_task_source: RemoteEventTaskSource,
|
||||||
|
@ -62,6 +65,7 @@ impl TaskManager {
|
||||||
media_element_task_source: MediaElementTaskSource,
|
media_element_task_source: MediaElementTaskSource,
|
||||||
networking_task_source: NetworkingTaskSource,
|
networking_task_source: NetworkingTaskSource,
|
||||||
performance_timeline_task_source: PerformanceTimelineTaskSource,
|
performance_timeline_task_source: PerformanceTimelineTaskSource,
|
||||||
|
port_message_queue: PortMessageQueue,
|
||||||
user_interaction_task_source: UserInteractionTaskSource,
|
user_interaction_task_source: UserInteractionTaskSource,
|
||||||
remote_event_task_source: RemoteEventTaskSource,
|
remote_event_task_source: RemoteEventTaskSource,
|
||||||
websocket_task_source: WebsocketTaskSource,
|
websocket_task_source: WebsocketTaskSource,
|
||||||
|
@ -73,6 +77,7 @@ impl TaskManager {
|
||||||
media_element_task_source,
|
media_element_task_source,
|
||||||
networking_task_source,
|
networking_task_source,
|
||||||
performance_timeline_task_source,
|
performance_timeline_task_source,
|
||||||
|
port_message_queue,
|
||||||
user_interaction_task_source,
|
user_interaction_task_source,
|
||||||
remote_event_task_source,
|
remote_event_task_source,
|
||||||
websocket_task_source,
|
websocket_task_source,
|
||||||
|
@ -136,6 +141,14 @@ impl TaskManager {
|
||||||
PerformanceTimeline
|
PerformanceTimeline
|
||||||
);
|
);
|
||||||
|
|
||||||
|
task_source_functions!(
|
||||||
|
self,
|
||||||
|
port_message_queue_with_canceller,
|
||||||
|
port_message_queue,
|
||||||
|
PortMessageQueue,
|
||||||
|
PortMessage
|
||||||
|
);
|
||||||
|
|
||||||
task_source_functions!(
|
task_source_functions!(
|
||||||
self,
|
self,
|
||||||
remote_event_task_source_with_canceller,
|
remote_event_task_source_with_canceller,
|
||||||
|
|
|
@ -8,6 +8,7 @@ pub mod history_traversal;
|
||||||
pub mod media_element;
|
pub mod media_element;
|
||||||
pub mod networking;
|
pub mod networking;
|
||||||
pub mod performance_timeline;
|
pub mod performance_timeline;
|
||||||
|
pub mod port_message;
|
||||||
pub mod remote_event;
|
pub mod remote_event;
|
||||||
pub mod user_interaction;
|
pub mod user_interaction;
|
||||||
pub mod websocket;
|
pub mod websocket;
|
||||||
|
@ -28,6 +29,7 @@ pub enum TaskSourceName {
|
||||||
HistoryTraversal,
|
HistoryTraversal,
|
||||||
Networking,
|
Networking,
|
||||||
PerformanceTimeline,
|
PerformanceTimeline,
|
||||||
|
PortMessage,
|
||||||
UserInteraction,
|
UserInteraction,
|
||||||
RemoteEvent,
|
RemoteEvent,
|
||||||
MediaElement,
|
MediaElement,
|
||||||
|
|
41
components/script/task_source/port_message.rs
Normal file
41
components/script/task_source/port_message.rs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/* 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 http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use crate::script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory};
|
||||||
|
use crate::task::{TaskCanceller, TaskOnce};
|
||||||
|
use crate::task_source::{TaskSource, TaskSourceName};
|
||||||
|
use msg::constellation_msg::PipelineId;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
#[derive(JSTraceable)]
|
||||||
|
pub struct PortMessageQueue(pub Box<dyn ScriptChan + Send + 'static>, pub PipelineId);
|
||||||
|
|
||||||
|
impl Clone for PortMessageQueue {
|
||||||
|
fn clone(&self) -> PortMessageQueue {
|
||||||
|
PortMessageQueue(self.0.clone(), self.1.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for PortMessageQueue {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "PortMessageQueue(...)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TaskSource for PortMessageQueue {
|
||||||
|
const NAME: TaskSourceName = TaskSourceName::PortMessage;
|
||||||
|
|
||||||
|
fn queue_with_canceller<T>(&self, task: T, canceller: &TaskCanceller) -> Result<(), ()>
|
||||||
|
where
|
||||||
|
T: TaskOnce + 'static,
|
||||||
|
{
|
||||||
|
let msg = CommonScriptMsg::Task(
|
||||||
|
ScriptThreadEventCategory::PortMessage,
|
||||||
|
Box::new(canceller.wrap_task(task)),
|
||||||
|
Some(self.1),
|
||||||
|
Self::NAME,
|
||||||
|
);
|
||||||
|
self.0.send(msg).map_err(|_| ())
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,8 +17,10 @@ extern crate malloc_size_of_derive;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
|
|
||||||
mod script_msg;
|
mod script_msg;
|
||||||
|
pub mod transferable;
|
||||||
pub mod webdriver_msg;
|
pub mod webdriver_msg;
|
||||||
|
|
||||||
|
use crate::transferable::MessagePortImpl;
|
||||||
use crate::webdriver_msg::{LoadStatus, WebDriverScriptCommand};
|
use crate::webdriver_msg::{LoadStatus, WebDriverScriptCommand};
|
||||||
use bluetooth_traits::BluetoothRequest;
|
use bluetooth_traits::BluetoothRequest;
|
||||||
use canvas_traits::webgl::WebGLPipeline;
|
use canvas_traits::webgl::WebGLPipeline;
|
||||||
|
@ -36,7 +38,7 @@ use keyboard_types::{CompositionEvent, KeyboardEvent};
|
||||||
use libc::c_void;
|
use libc::c_void;
|
||||||
use media::WindowGLContext;
|
use media::WindowGLContext;
|
||||||
use msg::constellation_msg::BackgroundHangMonitorRegister;
|
use msg::constellation_msg::BackgroundHangMonitorRegister;
|
||||||
use msg::constellation_msg::{BrowsingContextId, HistoryStateId, PipelineId};
|
use msg::constellation_msg::{BrowsingContextId, HistoryStateId, MessagePortId, PipelineId};
|
||||||
use msg::constellation_msg::{PipelineNamespaceId, TopLevelBrowsingContextId, TraversalDirection};
|
use msg::constellation_msg::{PipelineNamespaceId, TopLevelBrowsingContextId, TraversalDirection};
|
||||||
use net_traits::image::base::Image;
|
use net_traits::image::base::Image;
|
||||||
use net_traits::image_cache::ImageCache;
|
use net_traits::image_cache::ImageCache;
|
||||||
|
@ -51,7 +53,7 @@ use servo_atoms::Atom;
|
||||||
use servo_url::ImmutableOrigin;
|
use servo_url::ImmutableOrigin;
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::HashMap;
|
use std::collections::{HashMap, VecDeque};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -324,8 +326,11 @@ pub enum ConstellationControlMsg {
|
||||||
source_browsing_context: TopLevelBrowsingContextId,
|
source_browsing_context: TopLevelBrowsingContextId,
|
||||||
/// The expected origin of the target.
|
/// The expected origin of the target.
|
||||||
target_origin: Option<ImmutableOrigin>,
|
target_origin: Option<ImmutableOrigin>,
|
||||||
|
/// The source origin of the message.
|
||||||
|
/// https://html.spec.whatwg.org/multipage/#dom-messageevent-origin
|
||||||
|
source_origin: ImmutableOrigin,
|
||||||
/// The data to be posted.
|
/// The data to be posted.
|
||||||
data: Vec<u8>,
|
data: StructuredSerializedData,
|
||||||
},
|
},
|
||||||
/// Updates the current pipeline ID of a given iframe.
|
/// Updates the current pipeline ID of a given iframe.
|
||||||
/// First PipelineId is for the parent, second is the new PipelineId for the frame.
|
/// First PipelineId is for the parent, second is the new PipelineId for the frame.
|
||||||
|
@ -1013,3 +1018,33 @@ impl ScriptToConstellationChan {
|
||||||
self.sender.send((self.pipeline_id, msg))
|
self.sender.send((self.pipeline_id, msg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A data-holder for serialized data and transferred objects.
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#structuredserializewithtransfer>
|
||||||
|
#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
|
||||||
|
pub struct StructuredSerializedData {
|
||||||
|
/// Data serialized by SpiderMonkey.
|
||||||
|
pub serialized: Vec<u8>,
|
||||||
|
/// Transferred objects.
|
||||||
|
pub ports: Option<HashMap<MessagePortId, MessagePortImpl>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A task on the https://html.spec.whatwg.org/multipage/#port-message-queue
|
||||||
|
#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
|
||||||
|
pub struct PortMessageTask {
|
||||||
|
/// The origin of this task.
|
||||||
|
pub origin: ImmutableOrigin,
|
||||||
|
/// A data-holder for serialized data and transferred objects.
|
||||||
|
pub data: StructuredSerializedData,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Messages for communication between the constellation and a global managing ports.
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub enum MessagePortMsg {
|
||||||
|
/// Enables a port to catch-up on messages that were sent while the transfer was ongoing.
|
||||||
|
CompleteTransfer(MessagePortId, VecDeque<PortMessageTask>),
|
||||||
|
/// Remove a port, the entangled one doesn't exists anymore.
|
||||||
|
RemoveMessagePort(MessagePortId),
|
||||||
|
/// Handle a new port-message-task.
|
||||||
|
NewTask(MessagePortId, PortMessageTask),
|
||||||
|
}
|
||||||
|
|
|
@ -8,6 +8,9 @@ use crate::DocumentState;
|
||||||
use crate::IFrameLoadInfoWithData;
|
use crate::IFrameLoadInfoWithData;
|
||||||
use crate::LayoutControlMsg;
|
use crate::LayoutControlMsg;
|
||||||
use crate::LoadData;
|
use crate::LoadData;
|
||||||
|
use crate::MessagePortMsg;
|
||||||
|
use crate::PortMessageTask;
|
||||||
|
use crate::StructuredSerializedData;
|
||||||
use crate::WindowSizeType;
|
use crate::WindowSizeType;
|
||||||
use crate::WorkerGlobalScopeInit;
|
use crate::WorkerGlobalScopeInit;
|
||||||
use crate::WorkerScriptLoadOrigin;
|
use crate::WorkerScriptLoadOrigin;
|
||||||
|
@ -18,7 +21,9 @@ use euclid::default::Size2D as UntypedSize2D;
|
||||||
use euclid::Size2D;
|
use euclid::Size2D;
|
||||||
use gfx_traits::Epoch;
|
use gfx_traits::Epoch;
|
||||||
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
||||||
use msg::constellation_msg::{BrowsingContextId, PipelineId, TopLevelBrowsingContextId};
|
use msg::constellation_msg::{
|
||||||
|
BrowsingContextId, MessagePortId, MessagePortRouterId, PipelineId, TopLevelBrowsingContextId,
|
||||||
|
};
|
||||||
use msg::constellation_msg::{HistoryStateId, TraversalDirection};
|
use msg::constellation_msg::{HistoryStateId, TraversalDirection};
|
||||||
use net_traits::request::RequestBuilder;
|
use net_traits::request::RequestBuilder;
|
||||||
use net_traits::storage_thread::StorageType;
|
use net_traits::storage_thread::StorageType;
|
||||||
|
@ -109,6 +114,20 @@ pub enum HistoryEntryReplacement {
|
||||||
/// Messages from the script to the constellation.
|
/// Messages from the script to the constellation.
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub enum ScriptMsg {
|
pub enum ScriptMsg {
|
||||||
|
/// A new message-port was created or transferred, with corresponding control-sender.
|
||||||
|
NewMessagePort(MessagePortRouterId, MessagePortId),
|
||||||
|
/// A global has started managing message-ports
|
||||||
|
NewMessagePortRouter(MessagePortRouterId, IpcSender<MessagePortMsg>),
|
||||||
|
/// A global has stopped managing message-ports
|
||||||
|
RemoveMessagePortRouter(MessagePortRouterId),
|
||||||
|
/// A task requires re-routing to an already shipped message-port.
|
||||||
|
RerouteMessagePort(MessagePortId, PortMessageTask),
|
||||||
|
/// A message-port was shipped, let the entangled port know.
|
||||||
|
MessagePortShipped(MessagePortId),
|
||||||
|
/// A message-port has been discarded by script.
|
||||||
|
RemoveMessagePort(MessagePortId),
|
||||||
|
/// Entangle two message-ports.
|
||||||
|
EntanglePorts(MessagePortId, MessagePortId),
|
||||||
/// Forward a message to the embedder.
|
/// Forward a message to the embedder.
|
||||||
ForwardToEmbedder(EmbedderMsg),
|
ForwardToEmbedder(EmbedderMsg),
|
||||||
/// Requests are sent to constellation and fetches are checked manually
|
/// Requests are sent to constellation and fetches are checked manually
|
||||||
|
@ -166,8 +185,11 @@ pub enum ScriptMsg {
|
||||||
source: PipelineId,
|
source: PipelineId,
|
||||||
/// The expected origin of the target.
|
/// The expected origin of the target.
|
||||||
target_origin: Option<ImmutableOrigin>,
|
target_origin: Option<ImmutableOrigin>,
|
||||||
|
/// The source origin of the message.
|
||||||
|
/// https://html.spec.whatwg.org/multipage/#dom-messageevent-origin
|
||||||
|
source_origin: ImmutableOrigin,
|
||||||
/// The data to be posted.
|
/// The data to be posted.
|
||||||
data: Vec<u8>,
|
data: StructuredSerializedData,
|
||||||
},
|
},
|
||||||
/// Inform the constellation that a fragment was navigated to and whether or not it was a replacement navigation.
|
/// Inform the constellation that a fragment was navigated to and whether or not it was a replacement navigation.
|
||||||
NavigatedToFragment(ServoUrl, HistoryEntryReplacement),
|
NavigatedToFragment(ServoUrl, HistoryEntryReplacement),
|
||||||
|
@ -226,6 +248,13 @@ impl fmt::Debug for ScriptMsg {
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
use self::ScriptMsg::*;
|
use self::ScriptMsg::*;
|
||||||
let variant = match *self {
|
let variant = match *self {
|
||||||
|
NewMessagePortRouter(..) => "NewMessagePortRouter",
|
||||||
|
RemoveMessagePortRouter(..) => "RemoveMessagePortRouter",
|
||||||
|
NewMessagePort(..) => "NewMessagePort",
|
||||||
|
RerouteMessagePort(..) => "RerouteMessagePort",
|
||||||
|
RemoveMessagePort(..) => "RemoveMessagePort",
|
||||||
|
MessagePortShipped(..) => "MessagePortShipped",
|
||||||
|
EntanglePorts(..) => "EntanglePorts",
|
||||||
ForwardToEmbedder(..) => "ForwardToEmbedder",
|
ForwardToEmbedder(..) => "ForwardToEmbedder",
|
||||||
InitiateNavigateRequest(..) => "InitiateNavigateRequest",
|
InitiateNavigateRequest(..) => "InitiateNavigateRequest",
|
||||||
BroadcastStorageEvent(..) => "BroadcastStorageEvent",
|
BroadcastStorageEvent(..) => "BroadcastStorageEvent",
|
||||||
|
@ -283,8 +312,13 @@ pub struct ScopeThings {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Message that gets passed to service worker scope on postMessage
|
/// Message that gets passed to service worker scope on postMessage
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct DOMMessage(pub Vec<u8>);
|
pub struct DOMMessage {
|
||||||
|
/// The origin of the message
|
||||||
|
pub origin: ImmutableOrigin,
|
||||||
|
/// The payload of the message
|
||||||
|
pub data: StructuredSerializedData,
|
||||||
|
}
|
||||||
|
|
||||||
/// Channels to allow service worker manager to communicate with constellation and resource thread
|
/// Channels to allow service worker manager to communicate with constellation and resource thread
|
||||||
pub struct SWManagerSenders {
|
pub struct SWManagerSenders {
|
||||||
|
|
160
components/script_traits/transferable.rs
Normal file
160
components/script_traits/transferable.rs
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
//! This module contains implementations in script that are transferable.
|
||||||
|
//! The implementations are here instead of in script
|
||||||
|
//! so that the other modules involved in the transfer don't have
|
||||||
|
//! to depend on script.
|
||||||
|
|
||||||
|
use crate::PortMessageTask;
|
||||||
|
use msg::constellation_msg::MessagePortId;
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
|
||||||
|
enum MessagePortState {
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#detached>
|
||||||
|
Detached,
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#port-message-queue>
|
||||||
|
/// The message-queue of this port is enabled,
|
||||||
|
/// the boolean represents awaiting completion of a transfer.
|
||||||
|
Enabled(bool),
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#port-message-queue>
|
||||||
|
/// The message-queue of this port is disabled,
|
||||||
|
/// the boolean represents awaiting completion of a transfer.
|
||||||
|
Disabled(bool),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
|
||||||
|
/// The data and logic backing the DOM managed MessagePort.
|
||||||
|
pub struct MessagePortImpl {
|
||||||
|
/// The current state of the port.
|
||||||
|
state: MessagePortState,
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#entangle>
|
||||||
|
entangled_port: Option<MessagePortId>,
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#port-message-queue>
|
||||||
|
message_buffer: Option<VecDeque<PortMessageTask>>,
|
||||||
|
|
||||||
|
/// The UUID of this port.
|
||||||
|
message_port_id: MessagePortId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessagePortImpl {
|
||||||
|
/// Create a new messageport impl.
|
||||||
|
pub fn new(port_id: MessagePortId) -> MessagePortImpl {
|
||||||
|
MessagePortImpl {
|
||||||
|
state: MessagePortState::Disabled(false),
|
||||||
|
entangled_port: None,
|
||||||
|
message_buffer: None,
|
||||||
|
message_port_id: port_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the Id.
|
||||||
|
pub fn message_port_id(&self) -> &MessagePortId {
|
||||||
|
&self.message_port_id
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Maybe get the Id of the entangled port.
|
||||||
|
pub fn entangled_port_id(&self) -> Option<MessagePortId> {
|
||||||
|
self.entangled_port.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Entanged this port with another.
|
||||||
|
pub fn entangle(&mut self, other_id: MessagePortId) {
|
||||||
|
self.entangled_port = Some(other_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Is this port enabled?
|
||||||
|
pub fn enabled(&self) -> bool {
|
||||||
|
match self.state {
|
||||||
|
MessagePortState::Enabled(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mark this port as having been shipped.
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#has-been-shipped>
|
||||||
|
pub fn set_has_been_shipped(&mut self) {
|
||||||
|
match self.state {
|
||||||
|
MessagePortState::Detached => {
|
||||||
|
panic!("Messageport set_has_been_shipped called in detached state")
|
||||||
|
},
|
||||||
|
MessagePortState::Enabled(_) => self.state = MessagePortState::Enabled(true),
|
||||||
|
MessagePortState::Disabled(_) => self.state = MessagePortState::Disabled(true),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Handle the completion of the transfer,
|
||||||
|
/// this is data received from the constellation.
|
||||||
|
pub fn complete_transfer(&mut self, mut tasks: VecDeque<PortMessageTask>) {
|
||||||
|
match self.state {
|
||||||
|
MessagePortState::Detached => return,
|
||||||
|
MessagePortState::Enabled(_) => self.state = MessagePortState::Enabled(false),
|
||||||
|
MessagePortState::Disabled(_) => self.state = MessagePortState::Disabled(false),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: these are the tasks that were buffered while the transfer was ongoing,
|
||||||
|
// hence they need to execute first.
|
||||||
|
// The global will call `start` if we are enabled,
|
||||||
|
// which will add tasks on the event-loop to dispatch incoming messages.
|
||||||
|
match self.message_buffer {
|
||||||
|
Some(ref mut incoming_buffer) => {
|
||||||
|
while let Some(task) = tasks.pop_back() {
|
||||||
|
incoming_buffer.push_front(task);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => self.message_buffer = Some(tasks),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A message was received from our entangled port,
|
||||||
|
/// returns an optional task to be dispatched.
|
||||||
|
pub fn handle_incoming(&mut self, task: PortMessageTask) -> Option<PortMessageTask> {
|
||||||
|
let should_dispatch = match self.state {
|
||||||
|
MessagePortState::Detached => return None,
|
||||||
|
MessagePortState::Enabled(in_transfer) => !in_transfer,
|
||||||
|
MessagePortState::Disabled(_) => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if should_dispatch {
|
||||||
|
Some(task)
|
||||||
|
} else {
|
||||||
|
match self.message_buffer {
|
||||||
|
Some(ref mut buffer) => {
|
||||||
|
buffer.push_back(task);
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
let mut queue = VecDeque::new();
|
||||||
|
queue.push_back(task);
|
||||||
|
self.message_buffer = Some(queue);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#dom-messageport-start>
|
||||||
|
/// returns an optional queue of tasks that were buffered while the port was disabled.
|
||||||
|
pub fn start(&mut self) -> Option<VecDeque<PortMessageTask>> {
|
||||||
|
match self.state {
|
||||||
|
MessagePortState::Detached => return None,
|
||||||
|
MessagePortState::Enabled(_) => {},
|
||||||
|
MessagePortState::Disabled(in_transfer) => {
|
||||||
|
self.state = MessagePortState::Enabled(in_transfer);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if let MessagePortState::Enabled(true) = self.state {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
self.message_buffer.take()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#dom-messageport-close>
|
||||||
|
pub fn close(&mut self) {
|
||||||
|
// Step 1
|
||||||
|
self.state = MessagePortState::Detached;
|
||||||
|
}
|
||||||
|
}
|
|
@ -167,6 +167,8 @@ skip: true
|
||||||
skip: false
|
skip: false
|
||||||
[WebIDL]
|
[WebIDL]
|
||||||
skip: false
|
skip: false
|
||||||
|
[webmessaging]
|
||||||
|
skip: false
|
||||||
[websockets]
|
[websockets]
|
||||||
skip: false
|
skip: false
|
||||||
[webstorage]
|
[webstorage]
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
[Blob-constructor.html]
|
[Blob-constructor.html]
|
||||||
[Passing a FrozenArray as the blobParts array should work (FrozenArray<MessagePort>).]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[options properties should be accessed in lexicographic order.]
|
[options properties should be accessed in lexicographic order.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
[unicode-origin.sub.html]
|
|
||||||
[Verify serialization of non-ascii origin in Blob URLs]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -423442,6 +423442,49 @@
|
||||||
{}
|
{}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
"webmessaging/Channel_postMessage_transfer_xsite_incoming_messages.window.js": [
|
||||||
|
[
|
||||||
|
"webmessaging/Channel_postMessage_transfer_xsite_incoming_messages.window.html",
|
||||||
|
{
|
||||||
|
"script_metadata": [
|
||||||
|
[
|
||||||
|
"script",
|
||||||
|
"/common/get-host-info.sub.js"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"webmessaging/Channel_postMessage_with_transfer_entangled.any.js": [
|
||||||
|
[
|
||||||
|
"webmessaging/Channel_postMessage_with_transfer_entangled.any.html",
|
||||||
|
{}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"webmessaging/Channel_postMessage_with_transfer_entangled.any.worker.html",
|
||||||
|
{}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"webmessaging/Channel_postMessage_with_transfer_incoming_messages.any.js": [
|
||||||
|
[
|
||||||
|
"webmessaging/Channel_postMessage_with_transfer_incoming_messages.any.html",
|
||||||
|
{}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"webmessaging/Channel_postMessage_with_transfer_incoming_messages.any.worker.html",
|
||||||
|
{}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"webmessaging/Channel_postMessage_with_transfer_outgoing_messages.any.js": [
|
||||||
|
[
|
||||||
|
"webmessaging/Channel_postMessage_with_transfer_outgoing_messages.any.html",
|
||||||
|
{}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"webmessaging/Channel_postMessage_with_transfer_outgoing_messages.any.worker.html",
|
||||||
|
{}
|
||||||
|
]
|
||||||
|
],
|
||||||
"webmessaging/MessageEvent-trusted.html": [
|
"webmessaging/MessageEvent-trusted.html": [
|
||||||
[
|
[
|
||||||
"webmessaging/MessageEvent-trusted.html",
|
"webmessaging/MessageEvent-trusted.html",
|
||||||
|
@ -423646,6 +423689,19 @@
|
||||||
{}
|
{}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
"webmessaging/postMessage_MessagePorts_xsite.sub.window.js": [
|
||||||
|
[
|
||||||
|
"webmessaging/postMessage_MessagePorts_xsite.sub.window.html",
|
||||||
|
{
|
||||||
|
"script_metadata": [
|
||||||
|
[
|
||||||
|
"script",
|
||||||
|
"/common/get-host-info.sub.js"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
"webmessaging/postMessage_arrays.sub.htm": [
|
"webmessaging/postMessage_arrays.sub.htm": [
|
||||||
[
|
[
|
||||||
"webmessaging/postMessage_arrays.sub.htm",
|
"webmessaging/postMessage_arrays.sub.htm",
|
||||||
|
@ -714533,6 +714589,22 @@
|
||||||
"4b00e68d49ef9fc85e92a5526ff76bd92259d4d9",
|
"4b00e68d49ef9fc85e92a5526ff76bd92259d4d9",
|
||||||
"testharness"
|
"testharness"
|
||||||
],
|
],
|
||||||
|
"webmessaging/Channel_postMessage_transfer_xsite_incoming_messages.window.js": [
|
||||||
|
"23237ae1555e67dafcb170ce8fccab4c966f7a2e",
|
||||||
|
"testharness"
|
||||||
|
],
|
||||||
|
"webmessaging/Channel_postMessage_with_transfer_entangled.any.js": [
|
||||||
|
"2226b278440346290066e622fe6abbaab2b93bd2",
|
||||||
|
"testharness"
|
||||||
|
],
|
||||||
|
"webmessaging/Channel_postMessage_with_transfer_incoming_messages.any.js": [
|
||||||
|
"fe2e96220d34d88127dc596eee70d183f7debd18",
|
||||||
|
"testharness"
|
||||||
|
],
|
||||||
|
"webmessaging/Channel_postMessage_with_transfer_outgoing_messages.any.js": [
|
||||||
|
"aa80b7589cffa58da6f1d790e7cdbeb95642c6e3",
|
||||||
|
"testharness"
|
||||||
|
],
|
||||||
"webmessaging/META.yml": [
|
"webmessaging/META.yml": [
|
||||||
"95d5071171b5a20cc14a414c97c9eae2f525f43f",
|
"95d5071171b5a20cc14a414c97c9eae2f525f43f",
|
||||||
"support"
|
"support"
|
||||||
|
@ -714701,6 +714773,10 @@
|
||||||
"cf2b8eb4c11b0b824a47677079c2d1b8837b3802",
|
"cf2b8eb4c11b0b824a47677079c2d1b8837b3802",
|
||||||
"testharness"
|
"testharness"
|
||||||
],
|
],
|
||||||
|
"webmessaging/postMessage_MessagePorts_xsite.sub.window.js": [
|
||||||
|
"ca1e510edaa09f41350426e143923bb15e6df82b",
|
||||||
|
"testharness"
|
||||||
|
],
|
||||||
"webmessaging/postMessage_arrays.sub.htm": [
|
"webmessaging/postMessage_arrays.sub.htm": [
|
||||||
"41e4a75eda616196ab3546943a0913785cbe69be",
|
"41e4a75eda616196ab3546943a0913785cbe69be",
|
||||||
"testharness"
|
"testharness"
|
||||||
|
|
|
@ -5,8 +5,6 @@
|
||||||
[no-regexp-special-casing]
|
[no-regexp-special-casing]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Conversion to a sequence works]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[no-regexp-special-casing.any.html]
|
[no-regexp-special-casing.any.html]
|
||||||
[Untitled]
|
[Untitled]
|
||||||
|
@ -15,6 +13,3 @@
|
||||||
[no-regexp-special-casing]
|
[no-regexp-special-casing]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Conversion to a sequence works]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
|
|
|
@ -1,138 +1,17 @@
|
||||||
[remote-origin.htm]
|
[remote-origin.htm]
|
||||||
bug: https://github.com/servo/servo/issues/21563
|
bug: https://github.com/servo/servo/issues/21563
|
||||||
expected: TIMEOUT
|
|
||||||
[Allow origin: *]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Allow origin: _*__]
|
[Allow origin: _*__]
|
||||||
expected: TIMEOUT
|
expected: FAIL
|
||||||
|
|
||||||
[Allow origin: [tab\]*]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Allow origin: http://www1.web-platform.test:8000]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Allow origin: _http://www1.web-platform.test:8000]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Allow origin: _http://www1.web-platform.test:8000___[tab\]_]
|
[Allow origin: _http://www1.web-platform.test:8000___[tab\]_]
|
||||||
expected: TIMEOUT
|
expected: FAIL
|
||||||
|
|
||||||
[Allow origin: [tab\]http://www1.web-platform.test:8000]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: http://web-platform.test:8000]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: //www1.web-platform.test:8000]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: ://www1.web-platform.test:8000]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: ftp://www1.web-platform.test:8000]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: http:://www1.web-platform.test:8000]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: http:/www1.web-platform.test:8000]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: http:www1.web-platform.test:8000]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: www1.web-platform.test:8000]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: http://www1.web-platform.test:8000?]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: http://www1.web-platform.test:8000/]
|
[Disallow origin: http://www1.web-platform.test:8000/]
|
||||||
expected: TIMEOUT
|
expected: FAIL
|
||||||
|
|
||||||
[Disallow origin: http://www1.web-platform.test:8000_/]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: http://www1.web-platform.test:8000#]
|
[Disallow origin: http://www1.web-platform.test:8000#]
|
||||||
expected: TIMEOUT
|
expected: FAIL
|
||||||
|
|
||||||
[Disallow origin: http://www1.web-platform.test:8000%23]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: http://www1.web-platform.test:8000:80]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: http://www1.web-platform.test:8000,_*]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: http://www1.web-platform.test:8000\\0]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: HTTP://WWW1.WEB-PLATFORM.TEST:8000]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: HTTP://www1.web-platform.test:8000]
|
[Disallow origin: HTTP://www1.web-platform.test:8000]
|
||||||
expected: TIMEOUT
|
expected: FAIL
|
||||||
|
|
||||||
[Disallow origin: http://WWW1.WEB-PLATFORM.TEST:8000]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: -]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: **]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: \\0*]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: *\\0]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: '*']
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: "*"]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: *_*]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: *http://*]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: *http://www1.web-platform.test:8000]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: *_http://www1.web-platform.test:8000]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: *,_http://www1.web-platform.test:8000]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: \\0http://www1.web-platform.test:8000]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: null_http://www1.web-platform.test:8000]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: http://example.net]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: null]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: ]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: http://web-platform.test:8000/cors/remote-origin.htm]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: http://web-platform.test:8000/cors/]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Disallow origin: http://www1.web-platform.test:8000/cors/]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,3 @@
|
||||||
[DOMMatrix clone: non-initial values (3d)]
|
[DOMMatrix clone: non-initial values (3d)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[DOMRectList clone]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
[EventListener-incumbent-global-1.sub.html]
|
[EventListener-incumbent-global-1.sub.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
bug: https://github.com/servo/servo/issues/12715
|
bug: https://github.com/servo/servo/issues/12715
|
||||||
[Check the incumbent global EventListeners are called with]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
[EventListener-incumbent-global-2.sub.html]
|
|
||||||
type: testharness
|
|
||||||
bug: https://github.com/servo/servo/issues/12715
|
|
||||||
[Check the incumbent global EventListeners are called with]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
[embedded-credentials.tentative.sub.html]
|
[embedded-credentials.tentative.sub.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
|
expected: TIMEOUT
|
||||||
[Embedded credentials are treated as network errors.]
|
[Embedded credentials are treated as network errors.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -7,13 +8,13 @@
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Embedded credentials are treated as network errors in new windows.]
|
[Embedded credentials are treated as network errors in new windows.]
|
||||||
expected: FAIL
|
expected: TIMEOUT
|
||||||
|
|
||||||
[Embedded credentials matching the top-level are not treated as network errors for relative URLs.]
|
[Embedded credentials matching the top-level are not treated as network errors for relative URLs.]
|
||||||
expected: FAIL
|
expected: TIMEOUT
|
||||||
|
|
||||||
[Embedded credentials matching the top-level are not treated as network errors for same-origin URLs.]
|
[Embedded credentials matching the top-level are not treated as network errors for same-origin URLs.]
|
||||||
expected: FAIL
|
expected: TIMEOUT
|
||||||
|
|
||||||
[Embedded credentials matching the top-level are treated as network errors for cross-origin URLs.]
|
[Embedded credentials matching the top-level are treated as network errors for cross-origin URLs.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[origin-of-data-document.html]
|
|
||||||
type: testharness
|
|
||||||
[The origin of a 'data:' document in a frame is opaque.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,37 +1,38 @@
|
||||||
[document_domain_access_details.sub.html]
|
[document_domain_access_details.sub.html]
|
||||||
|
expected: TIMEOUT
|
||||||
[Access allowed if same-origin with no 'document.domain' modification. (Sanity check)]
|
[Access allowed if same-origin with no 'document.domain' modification. (Sanity check)]
|
||||||
expected: FAIL
|
expected: TIMEOUT
|
||||||
|
|
||||||
[Access is revoked to Window object when we stop being same effective script origin due to document.domain.]
|
[Access is revoked to Window object when we stop being same effective script origin due to document.domain.]
|
||||||
expected: FAIL
|
expected: NOTRUN
|
||||||
|
|
||||||
[Access allowed if different-origin but both set document.domain to parent domain.]
|
[Access allowed if different-origin but both set document.domain to parent domain.]
|
||||||
expected: FAIL
|
expected: NOTRUN
|
||||||
|
|
||||||
[Access is not revoked to random object when we stop being same effective script origin due to document.domain.]
|
[Access is not revoked to random object when we stop being same effective script origin due to document.domain.]
|
||||||
expected: FAIL
|
expected: NOTRUN
|
||||||
|
|
||||||
[Access not allowed if different-origin with no 'document.domain' modification. (Sanity check)]
|
[Access not allowed if different-origin with no 'document.domain' modification. (Sanity check)]
|
||||||
expected: FAIL
|
expected: NOTRUN
|
||||||
|
|
||||||
[Access disallowed again if same-origin, both set document-domain to existing value, then one sets to parent.]
|
[Access disallowed again if same-origin, both set document-domain to existing value, then one sets to parent.]
|
||||||
expected: FAIL
|
expected: NOTRUN
|
||||||
|
|
||||||
[Access is revoked to Location object when we stop being same effective script origin due to document.domain.]
|
[Access is revoked to Location object when we stop being same effective script origin due to document.domain.]
|
||||||
expected: FAIL
|
expected: NOTRUN
|
||||||
|
|
||||||
[Access allowed if same-origin and both set document.domain to existing value.]
|
[Access allowed if same-origin and both set document.domain to existing value.]
|
||||||
expected: FAIL
|
expected: NOTRUN
|
||||||
|
|
||||||
[Access is not revoked to Document object when we stop being same effective script origin due to document.domain.]
|
[Access is not revoked to Document object when we stop being same effective script origin due to document.domain.]
|
||||||
expected: FAIL
|
expected: NOTRUN
|
||||||
|
|
||||||
[Access disallowed if same-origin but only one sets document.domain.]
|
[Access disallowed if same-origin but only one sets document.domain.]
|
||||||
expected: FAIL
|
expected: NOTRUN
|
||||||
|
|
||||||
[Access evolves correctly for cross-origin objects when we join up via document.domain and then diverge again.]
|
[Access evolves correctly for cross-origin objects when we join up via document.domain and then diverge again.]
|
||||||
expected: FAIL
|
expected: NOTRUN
|
||||||
|
|
||||||
[Access evolves correctly for non-cross-origin objects when we join up via document.domain and then diverge again.]
|
[Access evolves correctly for non-cross-origin objects when we join up via document.domain and then diverge again.]
|
||||||
expected: FAIL
|
expected: NOTRUN
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,6 @@
|
||||||
[ElementInternals interface: operation setValidity(ValidityStateFlags, DOMString, HTMLElement)]
|
[ElementInternals interface: operation setValidity(ValidityStateFlags, DOMString, HTMLElement)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessageChannel interface: existence and properties of interface object]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[ValidityState interface: document.createElement("input").validity must inherit property "patternMismatch" with the proper type]
|
[ValidityState interface: document.createElement("input").validity must inherit property "patternMismatch" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -44,9 +41,6 @@
|
||||||
[ElementInternals interface: existence and properties of interface object]
|
[ElementInternals interface: existence and properties of interface object]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessagePort interface: attribute onmessage]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "imageSmoothingQuality" with the proper type]
|
[CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "imageSmoothingQuality" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -161,9 +155,6 @@
|
||||||
[SVGElement interface: attribute onmousemove]
|
[SVGElement interface: attribute onmousemove]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessagePort interface object length]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Navigator interface: window.navigator must inherit property "onLine" with the proper type]
|
[Navigator interface: window.navigator must inherit property "onLine" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -269,9 +260,6 @@
|
||||||
[SharedWorker interface object name]
|
[SharedWorker interface object name]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessageChannel interface: attribute port1]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[SVGSVGElement interface: attribute onbeforeprint]
|
[SVGSVGElement interface: attribute onbeforeprint]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -290,9 +278,6 @@
|
||||||
[SVGElement interface: attribute tabIndex]
|
[SVGElement interface: attribute tabIndex]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessageEvent interface: new MessageEvent("message", { data: 5 }) must inherit property "ports" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Location interface: window.location must have own property "ancestorOrigins"]
|
[Location interface: window.location must have own property "ancestorOrigins"]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -311,9 +296,6 @@
|
||||||
[ApplicationCache interface: constant UNCACHED on interface object]
|
[ApplicationCache interface: constant UNCACHED on interface object]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessageEvent interface: attribute ports]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[OffscreenCanvasRenderingContext2D interface: attribute filter]
|
[OffscreenCanvasRenderingContext2D interface: attribute filter]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -377,9 +359,6 @@
|
||||||
[SVGSVGElement interface: attribute onoffline]
|
[SVGSVGElement interface: attribute onoffline]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessagePort interface object name]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[OffscreenCanvasRenderingContext2D interface: existence and properties of interface prototype object's @@unscopables property]
|
[OffscreenCanvasRenderingContext2D interface: existence and properties of interface prototype object's @@unscopables property]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -410,9 +389,6 @@
|
||||||
[TextTrack interface: document.createElement("track").track must inherit property "inBandMetadataTrackDispatchType" with the proper type]
|
[TextTrack interface: document.createElement("track").track must inherit property "inBandMetadataTrackDispatchType" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessageChannel interface: existence and properties of interface prototype object's @@unscopables property]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[ValidityState interface: document.createElement("input").validity must inherit property "tooShort" with the proper type]
|
[ValidityState interface: document.createElement("input").validity must inherit property "tooShort" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -788,9 +764,6 @@
|
||||||
[ElementInternals interface: existence and properties of interface prototype object]
|
[ElementInternals interface: existence and properties of interface prototype object]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessageChannel interface object length]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[OffscreenCanvasRenderingContext2D interface: operation commit()]
|
[OffscreenCanvasRenderingContext2D interface: operation commit()]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -812,9 +785,6 @@
|
||||||
[Navigator interface: operation registerProtocolHandler(DOMString, USVString, DOMString)]
|
[Navigator interface: operation registerProtocolHandler(DOMString, USVString, DOMString)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessagePort interface: existence and properties of interface object]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[DataTransferItemList interface object name]
|
[DataTransferItemList interface object name]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -833,9 +803,6 @@
|
||||||
[SVGSVGElement interface: attribute onunhandledrejection]
|
[SVGSVGElement interface: attribute onunhandledrejection]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessageChannel interface: existence and properties of interface prototype object's "constructor" property]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[SVGElement interface: attribute onloadedmetadata]
|
[SVGElement interface: attribute onloadedmetadata]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -920,9 +887,6 @@
|
||||||
[CustomElementRegistry interface: operation whenDefined(DOMString)]
|
[CustomElementRegistry interface: operation whenDefined(DOMString)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessagePort interface: operation postMessage(any, PostMessageOptions)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[DragEvent interface: existence and properties of interface object]
|
[DragEvent interface: existence and properties of interface object]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -1010,9 +974,6 @@
|
||||||
[SVGElement interface: attribute ondragexit]
|
[SVGElement interface: attribute ondragexit]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessagePort interface: attribute onmessageerror]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Navigator interface: window.navigator must inherit property "oscpu" with the proper type]
|
[Navigator interface: window.navigator must inherit property "oscpu" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -1040,12 +1001,6 @@
|
||||||
[SharedWorker interface: existence and properties of interface prototype object]
|
[SharedWorker interface: existence and properties of interface prototype object]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessageChannel interface: existence and properties of interface prototype object]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[MessagePort interface: existence and properties of interface prototype object's "constructor" property]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[OffscreenCanvasRenderingContext2D interface: operation createPattern(CanvasImageSource, DOMString)]
|
[OffscreenCanvasRenderingContext2D interface: operation createPattern(CanvasImageSource, DOMString)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -1205,9 +1160,6 @@
|
||||||
[CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "drawFocusIfNeeded(Element)" with the proper type]
|
[CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "drawFocusIfNeeded(Element)" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessagePort interface: existence and properties of interface prototype object's @@unscopables property]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[OffscreenCanvasRenderingContext2D interface: operation closePath()]
|
[OffscreenCanvasRenderingContext2D interface: operation closePath()]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -1241,12 +1193,6 @@
|
||||||
[External interface object length]
|
[External interface object length]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessagePort interface: operation postMessage(any, [object Object\])]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[MessageChannel interface: attribute port2]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[CanvasRenderingContext2D interface: operation getTransform()]
|
[CanvasRenderingContext2D interface: operation getTransform()]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -1259,9 +1205,6 @@
|
||||||
[DataTransfer interface: attribute effectAllowed]
|
[DataTransfer interface: attribute effectAllowed]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessagePort interface: operation close()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[OffscreenCanvas interface: operation getContext(OffscreenRenderingContextId, any)]
|
[OffscreenCanvas interface: operation getContext(OffscreenRenderingContextId, any)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -1313,15 +1256,9 @@
|
||||||
[SVGAElement interface: attribute password]
|
[SVGAElement interface: attribute password]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessagePort interface: existence and properties of interface prototype object]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[SharedWorker interface: existence and properties of interface prototype object's "constructor" property]
|
[SharedWorker interface: existence and properties of interface prototype object's "constructor" property]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessageChannel interface object name]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[DataTransfer interface object name]
|
[DataTransfer interface object name]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -1355,9 +1292,6 @@
|
||||||
[ImageBitmapRenderingContext interface: existence and properties of interface prototype object's @@unscopables property]
|
[ImageBitmapRenderingContext interface: existence and properties of interface prototype object's @@unscopables property]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessagePort interface: operation start()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "isPointInStroke(unrestricted double, unrestricted double)" with the proper type]
|
[CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "isPointInStroke(unrestricted double, unrestricted double)" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -1552,9 +1486,6 @@
|
||||||
[Window interface: window must inherit property "queueMicrotask(VoidFunction)" with the proper type]
|
[Window interface: window must inherit property "queueMicrotask(VoidFunction)" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Window interface: operation postMessage(any, WindowPostMessageOptions)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Document interface: calling execCommand(DOMString, boolean, DOMString) on new Document() with too few arguments must throw TypeError]
|
[Document interface: calling execCommand(DOMString, boolean, DOMString) on new Document() with too few arguments must throw TypeError]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -1780,9 +1711,6 @@
|
||||||
[Document interface: iframe.contentDocument must inherit property "queryCommandState(DOMString)" with the proper type]
|
[Document interface: iframe.contentDocument must inherit property "queryCommandState(DOMString)" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Window interface: operation postMessage(any, USVString, [object Object\])]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Window interface: operation queueMicrotask(VoidFunction)]
|
[Window interface: operation queueMicrotask(VoidFunction)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -14,18 +14,12 @@
|
||||||
[DedicatedWorkerGlobalScope interface: self must inherit property "onmessageerror" with the proper type]
|
[DedicatedWorkerGlobalScope interface: self must inherit property "onmessageerror" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessagePort interface: existence and properties of interface prototype object's @@unscopables property]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[OffscreenCanvasRenderingContext2D interface: attribute filter]
|
[OffscreenCanvasRenderingContext2D interface: attribute filter]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[OffscreenCanvasRenderingContext2D interface: operation measureText(DOMString)]
|
[OffscreenCanvasRenderingContext2D interface: operation measureText(DOMString)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessagePort interface: attribute onmessage]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[ImageBitmapRenderingContext interface: existence and properties of interface object]
|
[ImageBitmapRenderingContext interface: existence and properties of interface object]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -65,15 +59,9 @@
|
||||||
[WorkerGlobalScope interface: self must inherit property "onlanguagechange" with the proper type]
|
[WorkerGlobalScope interface: self must inherit property "onlanguagechange" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessagePort interface: attribute onmessageerror]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WorkerNavigator interface: attribute languages]
|
[WorkerNavigator interface: attribute languages]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessagePort interface object length]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[OffscreenCanvasRenderingContext2D interface: operation strokeText(DOMString, unrestricted double, unrestricted double, unrestricted double)]
|
[OffscreenCanvasRenderingContext2D interface: operation strokeText(DOMString, unrestricted double, unrestricted double, unrestricted double)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -89,9 +77,6 @@
|
||||||
[ImageBitmapRenderingContext interface: existence and properties of interface prototype object]
|
[ImageBitmapRenderingContext interface: existence and properties of interface prototype object]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessagePort interface: existence and properties of interface prototype object]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Path2D interface: existence and properties of interface object]
|
[Path2D interface: existence and properties of interface object]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -104,9 +89,6 @@
|
||||||
[BroadcastChannel interface: operation close()]
|
[BroadcastChannel interface: operation close()]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessageChannel interface: existence and properties of interface object]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[DedicatedWorkerGlobalScope interface: calling requestAnimationFrame(FrameRequestCallback) on self with too few arguments must throw TypeError]
|
[DedicatedWorkerGlobalScope interface: calling requestAnimationFrame(FrameRequestCallback) on self with too few arguments must throw TypeError]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -116,12 +98,6 @@
|
||||||
[MessageEvent interface: calling initMessageEvent(DOMString, boolean, boolean, any, USVString, DOMString, MessageEventSource, [object Object\]) on new MessageEvent("message", { data: 5 }) with too few arguments must throw TypeError]
|
[MessageEvent interface: calling initMessageEvent(DOMString, boolean, boolean, any, USVString, DOMString, MessageEventSource, [object Object\]) on new MessageEvent("message", { data: 5 }) with too few arguments must throw TypeError]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessageChannel interface: attribute port1]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[MessageChannel interface: attribute port2]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[OffscreenCanvasRenderingContext2D interface: attribute lineWidth]
|
[OffscreenCanvasRenderingContext2D interface: attribute lineWidth]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -161,9 +137,6 @@
|
||||||
[Path2D interface: operation moveTo(unrestricted double, unrestricted double)]
|
[Path2D interface: operation moveTo(unrestricted double, unrestricted double)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessageChannel interface: existence and properties of interface prototype object's @@unscopables property]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[OffscreenCanvasRenderingContext2D interface: operation bezierCurveTo(unrestricted double, unrestricted double, unrestricted double, unrestricted double, unrestricted double, unrestricted double)]
|
[OffscreenCanvasRenderingContext2D interface: operation bezierCurveTo(unrestricted double, unrestricted double, unrestricted double, unrestricted double, unrestricted double, unrestricted double)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -179,9 +152,6 @@
|
||||||
[ImageBitmap interface: existence and properties of interface prototype object's @@unscopables property]
|
[ImageBitmap interface: existence and properties of interface prototype object's @@unscopables property]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessagePort interface: existence and properties of interface object]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Path2D interface object name]
|
[Path2D interface object name]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -329,18 +299,12 @@
|
||||||
[OffscreenCanvasRenderingContext2D interface: attribute miterLimit]
|
[OffscreenCanvasRenderingContext2D interface: attribute miterLimit]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessageChannel interface: existence and properties of interface prototype object's "constructor" property]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[OffscreenCanvasRenderingContext2D interface: operation strokeRect(unrestricted double, unrestricted double, unrestricted double, unrestricted double)]
|
[OffscreenCanvasRenderingContext2D interface: operation strokeRect(unrestricted double, unrestricted double, unrestricted double, unrestricted double)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[OffscreenCanvasRenderingContext2D interface: existence and properties of interface object]
|
[OffscreenCanvasRenderingContext2D interface: existence and properties of interface object]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessageChannel interface object length]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[OffscreenCanvasRenderingContext2D interface: operation commit()]
|
[OffscreenCanvasRenderingContext2D interface: operation commit()]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -350,9 +314,6 @@
|
||||||
[WorkerGlobalScope interface: self must inherit property "onoffline" with the proper type]
|
[WorkerGlobalScope interface: self must inherit property "onoffline" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessageEvent interface: attribute ports]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[OffscreenCanvasRenderingContext2D interface: attribute lineDashOffset]
|
[OffscreenCanvasRenderingContext2D interface: attribute lineDashOffset]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -425,12 +386,6 @@
|
||||||
[Path2D interface: existence and properties of interface prototype object's @@unscopables property]
|
[Path2D interface: existence and properties of interface prototype object's @@unscopables property]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessageChannel interface: existence and properties of interface prototype object]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[MessagePort interface: existence and properties of interface prototype object's "constructor" property]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[OffscreenCanvasRenderingContext2D interface: operation createPattern(CanvasImageSource, DOMString)]
|
[OffscreenCanvasRenderingContext2D interface: operation createPattern(CanvasImageSource, DOMString)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -479,9 +434,6 @@
|
||||||
[Path2D interface: operation ellipse(unrestricted double, unrestricted double, unrestricted double, unrestricted double, unrestricted double, unrestricted double, unrestricted double, boolean)]
|
[Path2D interface: operation ellipse(unrestricted double, unrestricted double, unrestricted double, unrestricted double, unrestricted double, unrestricted double, unrestricted double, boolean)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessageEvent interface: new MessageEvent("message", { data: 5 }) must inherit property "ports" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WorkerGlobalScope interface: attribute ononline]
|
[WorkerGlobalScope interface: attribute ononline]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -524,15 +476,9 @@
|
||||||
[BroadcastChannel interface: operation postMessage(any)]
|
[BroadcastChannel interface: operation postMessage(any)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessageChannel interface object name]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[SharedWorker interface: attribute port]
|
[SharedWorker interface: attribute port]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessagePort interface: operation postMessage(any, [object Object\])]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WorkerNavigator interface: self.navigator must not have property "taintEnabled"]
|
[WorkerNavigator interface: self.navigator must not have property "taintEnabled"]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -548,9 +494,6 @@
|
||||||
[SharedWorker interface object name]
|
[SharedWorker interface object name]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessagePort interface object name]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[OffscreenCanvas interface: operation getContext(OffscreenRenderingContextId, any)]
|
[OffscreenCanvas interface: operation getContext(OffscreenRenderingContextId, any)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -596,15 +539,6 @@
|
||||||
[OffscreenCanvasRenderingContext2D interface: operation clip(Path2D, CanvasFillRule)]
|
[OffscreenCanvasRenderingContext2D interface: operation clip(Path2D, CanvasFillRule)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessagePort interface: operation postMessage(any, PostMessageOptions)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[MessagePort interface: operation start()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[MessagePort interface: operation close()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WebSocket interface: new WebSocket("ws://foo") must inherit property "extensions" with the proper type]
|
[WebSocket interface: new WebSocket("ws://foo") must inherit property "extensions" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,9 @@
|
||||||
[no-coop-coep.https.any.worker.html]
|
[no-coop-coep.https.any.worker.html]
|
||||||
[SharedArrayBuffer over MessageChannel without COOP+COEP]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[SharedArrayBuffer over BroadcastChannel without COOP+COEP]
|
[SharedArrayBuffer over BroadcastChannel without COOP+COEP]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
||||||
[no-coop-coep.https.any.html]
|
[no-coop-coep.https.any.html]
|
||||||
[SharedArrayBuffer over MessageChannel without COOP+COEP]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[SharedArrayBuffer over postMessage() without COOP+COEP]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[SharedArrayBuffer over BroadcastChannel without COOP+COEP]
|
[SharedArrayBuffer over BroadcastChannel without COOP+COEP]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
[no-transferring.https.html]
|
|
||||||
[Trying to transfer a SharedArrayBuffer to a worker throws]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Trying to transfer a SharedArrayBuffer through a MessagePort throws]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Trying to transfer a SharedArrayBuffer to this window throws]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
[window-iframe-messagechannel-success.https.html]
|
[window-iframe-messagechannel-success.https.html]
|
||||||
expected: TIMEOUT
|
|
||||||
[postMessaging to a same-origin iframe via MessageChannel allows them to see each others' modifications]
|
[postMessaging to a same-origin iframe via MessageChannel allows them to see each others' modifications]
|
||||||
expected: TIMEOUT
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -5,27 +5,12 @@
|
||||||
[transfer-errors]
|
[transfer-errors]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Serialize should make the ArrayBuffer detached, so it cannot be transferred again]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Serialize should throw before a detached ArrayBuffer is found]
|
[Serialize should throw before a detached ArrayBuffer is found]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Cannot transfer ArrayBuffer detached while the message was serialized]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Cannot transfer the same MessagePort twice]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Serialize should make the MessagePort detached, so it cannot be transferred again]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Serialize should throw before a detached MessagePort is found]
|
[Serialize should throw before a detached MessagePort is found]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Cannot transfer MessagePort detached while the message was serialized]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Cannot transfer the same ImageBitmap twice]
|
[Cannot transfer the same ImageBitmap twice]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,5 @@
|
||||||
[tasks.window.html]
|
[tasks.window.html]
|
||||||
expected: TIMEOUT
|
expected: TIMEOUT
|
||||||
[document.open() and tasks (MessagePort)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[tasks without document.open() (MessagePort)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[document.open() and tasks (canvas.toBlob())]
|
[document.open() and tasks (canvas.toBlob())]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,6 @@
|
||||||
[Default event values]
|
[Default event values]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[MessageEventInit dictionary]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Passing null for ports member]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[ports attribute should be a FrozenArray]
|
[ports attribute should be a FrozenArray]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,11 @@
|
||||||
[promise-rejection-events.dedicatedworker.html]
|
[promise-rejection-events.dedicatedworker.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
[unhandledrejection: from a task-delayed rejection]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[no unhandledrejection/rejectionhandled: all inside a queued task, a rejection handler attached synchronously to a promise created from returning a Promise.reject-created promise in a fulfillment handler]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[microtask nesting: attaching a handler inside a combination of mutationObserverMicrotask + promise microtasks, all inside a postMessageTask]
|
[microtask nesting: attaching a handler inside a combination of mutationObserverMicrotask + promise microtasks, all inside a postMessageTask]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[microtask nesting: attaching a handler inside a combination of promise microtasks + mutationObserverMicrotask, all inside a postMessageTask]
|
[microtask nesting: attaching a handler inside a combination of promise microtasks + mutationObserverMicrotask, all inside a postMessageTask]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[delayed handling: a nested-task delay before attaching a handler causes unhandledrejection]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[delayed handling: a nested-postMessageTask after promise creation/rejection, plus promise microtasks, is too late to attach a rejection handler]
|
[delayed handling: a nested-postMessageTask after promise creation/rejection, plus promise microtasks, is too late to attach a rejection handler]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -33,18 +24,3 @@
|
||||||
[no unhandledrejection/rejectionhandled: rejection handler attached synchronously to a promise created from createImageBitmap]
|
[no unhandledrejection/rejectionhandled: rejection handler attached synchronously to a promise created from createImageBitmap]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[microtask nesting: attaching a handler inside a combination of mutationObserverMicrotask + promise microtasks, all inside a queueTask]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[microtask nesting: attaching a handler inside a combination of promise microtasks + mutationObserverMicrotask, all inside a queueTask]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[delayed handling: a nested-queueTask after promise creation/rejection, plus promise microtasks, is too late to attach a rejection handler]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[delayed handling: a nested-queueTask before promise creation/rejection, plus many promise microtasks, is too late to attach a rejection handler]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[delayed handling: a nested-queueTask after promise creation/rejection, plus many promise microtasks, is too late to attach a rejection handler]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[Promise-incumbent-global.sub.html]
|
|
||||||
type: testharness
|
|
||||||
[Check the incumbent global Promise callbacks are called with]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
[no-transferring.html]
|
|
||||||
[Trying to transfer a WebAssembly.Module to a worker throws]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Trying to transfer a WebAssembly.Module through a MessagePort throws]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Trying to transfer a WebAssembly.Module to this window throws]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[MessageEvent-trusted.html]
|
||||||
|
[With a BroadcastChannel]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
[basics.html]
|
||||||
|
[messages are delivered in port creation order]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[closing and creating channels during message delivery works correctly]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[messages aren't delivered to a closed port]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Closing a channel in onmessage doesn't cancel already queued events]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[postMessage results in correct event]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
[blobs.html]
|
||||||
|
[Blobs work with workers on BroadcastChannel]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Blobs work on BroadcastChannel]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
[interface.html]
|
||||||
|
[Null name should not throw]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[postMessage after close should throw]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Undefined name should not throw]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[postMessage should throw with uncloneable data]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[close should not throw when called multiple times]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[close should not throw]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Non-empty name should not throw]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[postMessage with null should not throw]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[postMessage should throw InvalidStateError after close, even with uncloneable data]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[BroadcastChannel should have an onmessage event]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Non-string name should not throw]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Should throw if no name is provided]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[postMessage without parameters should throw]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
[origin.window.html]
|
||||||
|
expected: TIMEOUT
|
||||||
|
[Serialization of BroadcastChannel origin]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[sandbox.html]
|
||||||
|
[Creating BroadcastChannel in an opaque origin]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
[workers.html]
|
||||||
|
expected: TIMEOUT
|
||||||
|
[BroadcastChannel used after a worker self.close()]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[BroadcastChannel works in shared workers]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[BroadcastChannel works in workers]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[BroadcastChannel created after a worker self.close()]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
[Closing and re-opening a channel works.]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[event.source.xorigin.sub.htm]
|
||||||
|
[Test Description: Cross-origin: event.source returns the WindowProxy of the source window.]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[user-activation.tentative.html]
|
||||||
|
[user activation messagechannel test]
|
||||||
|
expected: FAIL
|
||||||
|
|
7
tests/wpt/metadata/webmessaging/messageerror.html.ini
Normal file
7
tests/wpt/metadata/webmessaging/messageerror.html.ini
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
[messageerror.html]
|
||||||
|
[The onmessageerror content attribute must execute when an event is dispatched on the window]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[The onmessageerror content attribute must be compiled into the onmessageerror property]
|
||||||
|
expected: FAIL
|
||||||
|
|
4
tests/wpt/metadata/webmessaging/with-ports/011.html.ini
Normal file
4
tests/wpt/metadata/webmessaging/with-ports/011.html.ini
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
[011.html]
|
||||||
|
[posting an imagedata (from a cloned canvas) in an array]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[011.html]
|
||||||
|
[posting an imagedata (from a cloned canvas) in an array]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[026.html]
|
||||||
|
[Cloning objects with getter properties]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[028.html]
|
||||||
|
[Cloning objects, preserving sharing #2]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[worker_postMessage_user_activation.tentative.html]
|
||||||
|
[Post Message from a worker]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
[Worker-messageport.html]
|
|
||||||
[Test sending message to a worker on a port.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Test sending messages to workers with no port.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Test getting messages from a worker on a port.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Test sending many messages to workers using ports.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -5,18 +5,6 @@
|
||||||
[Test postMessage on channel with previous failed postMessage calls.]
|
[Test postMessage on channel with previous failed postMessage calls.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Test postMessage with no port.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Test postMessage with two ports.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Test postMessage with no ports and empty array.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Test postMessage with null ports throws exception.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Test postMessage with incorrect ports throws exception]
|
[Test postMessage with incorrect ports throws exception]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
[Worker-termination-with-port-messages.html]
|
|
||||||
[This test terminates a worker when there are many undelivered MessagePort messages still waiting to be dispatched into the Worker Context. This causes termination of JS execution and test should not try to dispatch the remaining messages. Test succeeds if it does not hang or crash (if worker thread is running in the separate process, that process could hang or crash).]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
[expected-self-properties.worker.html]
|
[expected-self-properties.worker.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
[existence of MessageChannel]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[existence of SharedWorker]
|
[existence of SharedWorker]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
[data-url-shared.html]
|
[data-url-shared.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
|
expected: TIMEOUT
|
||||||
[data URL shared worker]
|
[data URL shared worker]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -28,7 +29,7 @@
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[A data: URL shared worker should not be shared among origins.]
|
[A data: URL shared worker should not be shared among origins.]
|
||||||
expected: FAIL
|
expected: TIMEOUT
|
||||||
|
|
||||||
[indexedDB is present]
|
[indexedDB is present]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[event-ports-dedicated.html]
|
|
||||||
type: testharness
|
|
||||||
[e.ports in dedicated worker]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[second-argument-null-in-array.html]
|
|
||||||
type: testharness
|
|
||||||
[Using [null\] in postMessage's second argument]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -6,3 +6,9 @@
|
||||||
[opaque-origin]
|
[opaque-origin]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[Worker has an opaque origin.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Worker can access BroadcastChannel]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[postMessage_clone_port.htm]
|
|
||||||
type: testharness
|
|
||||||
[ postMessage(): clone a port ]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[postMessage_clone_port_error.htm]
|
|
||||||
type: testharness
|
|
||||||
[ postMessage(): cloning source port ]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue