aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
Diffstat (limited to 'components/script')
-rw-r--r--components/script/Cargo.toml2
-rw-r--r--components/script/dom/beforeunloadevent.rs10
-rw-r--r--components/script/dom/document.rs14
-rw-r--r--components/script/dom/event.rs407
-rw-r--r--components/script/dom/eventdispatcher.rs223
-rw-r--r--components/script/dom/eventtarget.rs7
-rw-r--r--components/script/dom/focusevent.rs7
-rw-r--r--components/script/dom/globalscope.rs3
-rw-r--r--components/script/dom/hashchangeevent.rs14
-rw-r--r--components/script/dom/htmlscriptelement.rs3
-rw-r--r--components/script/dom/mod.rs1
-rw-r--r--components/script/dom/pagetransitionevent.rs14
-rw-r--r--components/script/dom/popstateevent.rs14
-rw-r--r--components/script/dom/transitionevent.rs10
-rw-r--r--components/script/dom/webidls/BeforeUnloadEvent.webidl2
-rw-r--r--components/script/dom/webidls/FocusEvent.webidl3
-rw-r--r--components/script/dom/webidls/HashChangeEvent.webidl3
-rw-r--r--components/script/dom/webidls/Location.webidl2
-rw-r--r--components/script/dom/webidls/MouseEvent.webidl3
-rw-r--r--components/script/dom/webidls/PageTransitionEvent.webidl3
-rw-r--r--components/script/dom/webidls/PopStateEvent.webidl3
-rw-r--r--components/script/dom/worker.rs3
-rw-r--r--components/script/script_thread.rs2
-rw-r--r--components/script/test.rs1
24 files changed, 337 insertions, 417 deletions
diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml
index bcbfc949d7c..258ae0e1105 100644
--- a/components/script/Cargo.toml
+++ b/components/script/Cargo.toml
@@ -70,7 +70,7 @@ regex = "0.2"
rustc-serialize = "0.3"
script_layout_interface = {path = "../script_layout_interface"}
script_traits = {path = "../script_traits"}
-selectors = "0.15"
+selectors = "0.15.1"
serde = "0.8"
servo_atoms = {path = "../atoms"}
servo_config = {path = "../config", features = ["servo"] }
diff --git a/components/script/dom/beforeunloadevent.rs b/components/script/dom/beforeunloadevent.rs
index d9162002016..3787bb5b62d 100644
--- a/components/script/dom/beforeunloadevent.rs
+++ b/components/script/dom/beforeunloadevent.rs
@@ -13,7 +13,7 @@ use dom::bindings::js::Root;
use dom::bindings::reflector::reflect_dom_object;
use dom::bindings::str::DOMString;
use dom::event::{Event, EventBubbles, EventCancelable};
-use dom::globalscope::GlobalScope;
+use dom::window::Window;
use servo_atoms::Atom;
// https://html.spec.whatwg.org/multipage/#beforeunloadevent
@@ -31,17 +31,17 @@ impl BeforeUnloadEvent {
}
}
- pub fn new_uninitialized(global: &GlobalScope) -> Root<BeforeUnloadEvent> {
+ pub fn new_uninitialized(window: &Window) -> Root<BeforeUnloadEvent> {
reflect_dom_object(box BeforeUnloadEvent::new_inherited(),
- global,
+ window,
BeforeUnloadEventBinding::Wrap)
}
- pub fn new(global: &GlobalScope,
+ pub fn new(window: &Window,
type_: Atom,
bubbles: EventBubbles,
cancelable: EventCancelable) -> Root<BeforeUnloadEvent> {
- let ev = BeforeUnloadEvent::new_uninitialized(global);
+ let ev = BeforeUnloadEvent::new_uninitialized(window);
{
let event = ev.upcast::<Event>();
event.init_event(type_, bool::from(bubbles),
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 8702120c92e..6bf8c841d4d 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -7,6 +7,7 @@ use devtools_traits::ScriptToDevtoolsControlMsg;
use document_loader::{DocumentLoader, LoadType};
use dom::activation::{ActivationSource, synthetic_click_activation};
use dom::attr::Attr;
+use dom::beforeunloadevent::BeforeUnloadEvent;
use dom::bindings::callback::ExceptionHandling;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::DOMRectBinding::DOMRectMethods;
@@ -40,8 +41,7 @@ use dom::documenttype::DocumentType;
use dom::domimplementation::DOMImplementation;
use dom::element::{Element, ElementCreator, ElementPerformFullscreenEnter, ElementPerformFullscreenExit};
use dom::errorevent::ErrorEvent;
-use dom::event::{Event, EventBubbles, EventCancelable, EventDefault};
-use dom::eventdispatcher::EventStatus;
+use dom::event::{Event, EventBubbles, EventCancelable, EventDefault, EventStatus};
use dom::eventtarget::EventTarget;
use dom::focusevent::FocusEvent;
use dom::forcetouchevent::ForceTouchEvent;
@@ -2603,6 +2603,8 @@ impl DocumentMethods for Document {
fn CreateEvent(&self, mut interface: DOMString) -> Fallible<Root<Event>> {
interface.make_ascii_lowercase();
match &*interface {
+ "beforeunloadevent" =>
+ Ok(Root::upcast(BeforeUnloadEvent::new_uninitialized(&self.window))),
"closeevent" =>
Ok(Root::upcast(CloseEvent::new_uninitialized(self.window.upcast()))),
"customevent" =>
@@ -2612,9 +2614,9 @@ impl DocumentMethods for Document {
"events" | "event" | "htmlevents" | "svgevents" =>
Ok(Event::new_uninitialized(&self.window.upcast())),
"focusevent" =>
- Ok(Root::upcast(FocusEvent::new_uninitialized(self.window.upcast()))),
+ Ok(Root::upcast(FocusEvent::new_uninitialized(&self.window))),
"hashchangeevent" =>
- Ok(Root::upcast(HashChangeEvent::new_uninitialized(&self.window.upcast()))),
+ Ok(Root::upcast(HashChangeEvent::new_uninitialized(&self.window))),
"keyboardevent" =>
Ok(Root::upcast(KeyboardEvent::new_uninitialized(&self.window))),
"messageevent" =>
@@ -2622,9 +2624,9 @@ impl DocumentMethods for Document {
"mouseevent" | "mouseevents" =>
Ok(Root::upcast(MouseEvent::new_uninitialized(&self.window))),
"pagetransitionevent" =>
- Ok(Root::upcast(PageTransitionEvent::new_uninitialized(self.window.upcast()))),
+ Ok(Root::upcast(PageTransitionEvent::new_uninitialized(&self.window))),
"popstateevent" =>
- Ok(Root::upcast(PopStateEvent::new_uninitialized(self.window.upcast()))),
+ Ok(Root::upcast(PopStateEvent::new_uninitialized(&self.window))),
"progressevent" =>
Ok(Root::upcast(ProgressEvent::new_uninitialized(self.window.upcast()))),
"storageevent" => {
diff --git a/components/script/dom/event.rs b/components/script/dom/event.rs
index fa3b9bfae6b..2d3c2afe460 100644
--- a/components/script/dom/event.rs
+++ b/components/script/dom/event.rs
@@ -2,103 +2,29 @@
* 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 devtools_traits::{TimelineMarker, TimelineMarkerType};
+use dom::bindings::callback::ExceptionHandling;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::EventBinding;
use dom::bindings::codegen::Bindings::EventBinding::{EventConstants, EventMethods};
use dom::bindings::error::Fallible;
-use dom::bindings::js::{MutNullableJS, Root};
+use dom::bindings::inheritance::Castable;
+use dom::bindings::js::{JS, MutNullableJS, Root, RootedReference};
use dom::bindings::refcounted::Trusted;
-use dom::bindings::reflector::{Reflector, reflect_dom_object};
+use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
use dom::bindings::str::DOMString;
-use dom::eventdispatcher::EventStatus;
-use dom::eventtarget::EventTarget;
+use dom::document::Document;
+use dom::eventtarget::{CompiledEventListener, EventTarget, ListenerPhase};
use dom::globalscope::GlobalScope;
+use dom::node::Node;
+use dom::virtualmethods::vtable_for;
+use dom::window::Window;
use script_thread::Runnable;
use servo_atoms::Atom;
use std::cell::Cell;
use std::default::Default;
use time;
-#[derive(JSTraceable, Copy, Clone, Debug, PartialEq, Eq)]
-#[repr(u16)]
-#[derive(HeapSizeOf)]
-pub enum EventPhase {
- None = EventConstants::NONE,
- Capturing = EventConstants::CAPTURING_PHASE,
- AtTarget = EventConstants::AT_TARGET,
- Bubbling = EventConstants::BUBBLING_PHASE,
-}
-
-#[derive(PartialEq, HeapSizeOf, Copy, Clone)]
-pub enum EventBubbles {
- Bubbles,
- DoesNotBubble
-}
-
-impl From<EventBubbles> for bool {
- fn from(bubbles: EventBubbles) -> Self {
- match bubbles {
- EventBubbles::Bubbles => true,
- EventBubbles::DoesNotBubble => false
- }
- }
-}
-
-impl From<bool> for EventBubbles {
- fn from(boolean: bool) -> Self {
- match boolean {
- true => EventBubbles::Bubbles,
- false => EventBubbles::DoesNotBubble
- }
- }
-}
-
-#[derive(PartialEq, HeapSizeOf, Copy, Clone)]
-pub enum EventCancelable {
- Cancelable,
- NotCancelable
-}
-
-impl From<EventCancelable> for bool {
- fn from(bubbles: EventCancelable) -> Self {
- match bubbles {
- EventCancelable::Cancelable => true,
- EventCancelable::NotCancelable => false
- }
- }
-}
-
-impl From<bool> for EventCancelable {
- fn from(boolean: bool) -> Self {
- match boolean {
- true => EventCancelable::Cancelable,
- false => EventCancelable::NotCancelable
- }
- }
-}
-
-/// An enum to indicate whether the default action of an event is allowed.
-///
-/// This should've been a bool. Instead, it's an enum, because, aside from the allowed/canceled
-/// states, we also need something to stop the event from being handled again (without cancelling
-/// the event entirely). For example, an Up/Down `KeyEvent` inside a `textarea` element will
-/// trigger the cursor to go up/down if the text inside the element spans multiple lines. This enum
-/// helps us to prevent such events from being [sent to the constellation][msg] where it will be
-/// handled once again for page scrolling (which is definitely not what we'd want).
-///
-/// [msg]: https://doc.servo.org/script_traits/enum.ConstellationMsg.html#variant.KeyEvent
-///
-#[derive(JSTraceable, HeapSizeOf, Copy, Clone, PartialEq)]
-pub enum EventDefault {
- /// The default action of the event is allowed (constructor's default)
- Allowed,
- /// The default action has been prevented by calling `PreventDefault`
- Prevented,
- /// The event has been handled somewhere in the DOM, and it should be prevented from being
- /// re-handled elsewhere. This doesn't affect the judgement of `DefaultPrevented`
- Handled,
-}
-
#[dom_struct]
pub struct Event {
reflector_: Reflector,
@@ -176,46 +102,74 @@ impl Event {
self.cancelable.set(cancelable);
}
- pub fn status(&self) -> EventStatus {
- match self.DefaultPrevented() {
- true => EventStatus::Canceled,
- false => EventStatus::NotCanceled
- }
- }
+ // https://dom.spec.whatwg.org/#concept-event-dispatch
+ pub fn dispatch(&self,
+ target: &EventTarget,
+ target_override: Option<&EventTarget>)
+ -> EventStatus {
+ assert!(!self.dispatching());
+ assert!(self.initialized());
+ assert_eq!(self.phase.get(), EventPhase::None);
+ assert!(self.GetCurrentTarget().is_none());
- #[inline]
- pub fn set_current_target(&self, val: &EventTarget) {
- self.current_target.set(Some(val));
- }
+ // Step 1.
+ self.dispatching.set(true);
- #[inline]
- pub fn set_target(&self, val: &EventTarget) {
- self.target.set(Some(val));
- }
+ // Step 2.
+ self.target.set(Some(target_override.unwrap_or(target)));
- #[inline]
- pub fn phase(&self) -> EventPhase {
- self.phase.get()
- }
+ if self.stop_propagation.get() {
+ // If the event's stop propagation flag is set, we can skip everything because
+ // it prevents the calls of the invoke algorithm in the spec.
- #[inline]
- pub fn set_phase(&self, val: EventPhase) {
- self.phase.set(val)
- }
+ // Step 10-12.
+ self.clear_dispatching_flags();
- #[inline]
- pub fn stop_propagation(&self) -> bool {
- self.stop_propagation.get()
- }
+ // Step 14.
+ return self.status();
+ }
- #[inline]
- pub fn stop_immediate(&self) -> bool {
- self.stop_immediate.get()
+ // Step 3. The "invoke" algorithm is only used on `target` separately,
+ // so we don't put it in the path.
+ rooted_vec!(let mut event_path);
+
+ // Step 4.
+ if let Some(target_node) = target.downcast::<Node>() {
+ for ancestor in target_node.ancestors() {
+ event_path.push(JS::from_ref(ancestor.upcast::<EventTarget>()));
+ }
+ let top_most_ancestor_or_target =
+ Root::from_ref(event_path.r().last().cloned().unwrap_or(target));
+ if let Some(document) = Root::downcast::<Document>(top_most_ancestor_or_target) {
+ if self.type_() != atom!("load") && document.browsing_context().is_some() {
+ event_path.push(JS::from_ref(document.window().upcast()));
+ }
+ }
+ }
+
+ // Steps 5-9. In a separate function to short-circuit various things easily.
+ dispatch_to_listeners(self, target, event_path.r());
+
+ // Default action.
+ if let Some(target) = self.GetTarget() {
+ if let Some(node) = target.downcast::<Node>() {
+ let vtable = vtable_for(&node);
+ vtable.handle_event(self);
+ }
+ }
+
+ // Step 10-12.
+ self.clear_dispatching_flags();
+
+ // Step 14.
+ self.status()
}
- #[inline]
- pub fn bubbles(&self) -> bool {
- self.bubbles.get()
+ pub fn status(&self) -> EventStatus {
+ match self.DefaultPrevented() {
+ true => EventStatus::Canceled,
+ false => EventStatus::NotCanceled
+ }
}
#[inline]
@@ -224,21 +178,14 @@ impl Event {
}
#[inline]
- // https://dom.spec.whatwg.org/#concept-event-dispatch Step 1.
- pub fn mark_as_dispatching(&self) {
- assert!(!self.dispatching.get());
- self.dispatching.set(true);
- }
-
- #[inline]
// https://dom.spec.whatwg.org/#concept-event-dispatch Steps 10-12.
- pub fn clear_dispatching_flags(&self) {
+ fn clear_dispatching_flags(&self) {
assert!(self.dispatching.get());
self.dispatching.set(false);
self.stop_propagation.set(false);
self.stop_immediate.set(false);
- self.set_phase(EventPhase::None);
+ self.phase.set(EventPhase::None);
self.current_target.set(None);
}
@@ -261,6 +208,16 @@ impl Event {
pub fn get_cancel_state(&self) -> EventDefault {
self.canceled.get()
}
+
+ pub fn set_trusted(&self, trusted: bool) {
+ self.trusted.set(trusted);
+ }
+
+ // https://html.spec.whatwg.org/multipage/#fire-a-simple-event
+ pub fn fire(&self, target: &EventTarget) -> EventStatus {
+ self.set_trusted(true);
+ target.dispatch_event(self)
+ }
}
impl EventMethods for Event {
@@ -336,19 +293,92 @@ impl EventMethods for Event {
}
}
+#[derive(PartialEq, HeapSizeOf, Copy, Clone)]
+pub enum EventBubbles {
+ Bubbles,
+ DoesNotBubble
+}
-impl Event {
- pub fn set_trusted(&self, trusted: bool) {
- self.trusted.set(trusted);
+impl From<bool> for EventBubbles {
+ fn from(boolean: bool) -> Self {
+ match boolean {
+ true => EventBubbles::Bubbles,
+ false => EventBubbles::DoesNotBubble
+ }
}
+}
- // https://html.spec.whatwg.org/multipage/#fire-a-simple-event
- pub fn fire(&self, target: &EventTarget) -> EventStatus {
- self.set_trusted(true);
- target.dispatch_event(self)
+impl From<EventBubbles> for bool {
+ fn from(bubbles: EventBubbles) -> Self {
+ match bubbles {
+ EventBubbles::Bubbles => true,
+ EventBubbles::DoesNotBubble => false
+ }
}
}
+#[derive(PartialEq, HeapSizeOf, Copy, Clone)]
+pub enum EventCancelable {
+ Cancelable,
+ NotCancelable
+}
+
+impl From<bool> for EventCancelable {
+ fn from(boolean: bool) -> Self {
+ match boolean {
+ true => EventCancelable::Cancelable,
+ false => EventCancelable::NotCancelable
+ }
+ }
+}
+
+impl From<EventCancelable> for bool {
+ fn from(bubbles: EventCancelable) -> Self {
+ match bubbles {
+ EventCancelable::Cancelable => true,
+ EventCancelable::NotCancelable => false
+ }
+ }
+}
+
+#[derive(JSTraceable, Copy, Clone, Debug, PartialEq, Eq)]
+#[repr(u16)]
+#[derive(HeapSizeOf)]
+pub enum EventPhase {
+ None = EventConstants::NONE,
+ Capturing = EventConstants::CAPTURING_PHASE,
+ AtTarget = EventConstants::AT_TARGET,
+ Bubbling = EventConstants::BUBBLING_PHASE,
+}
+
+/// An enum to indicate whether the default action of an event is allowed.
+///
+/// This should've been a bool. Instead, it's an enum, because, aside from the allowed/canceled
+/// states, we also need something to stop the event from being handled again (without cancelling
+/// the event entirely). For example, an Up/Down `KeyEvent` inside a `textarea` element will
+/// trigger the cursor to go up/down if the text inside the element spans multiple lines. This enum
+/// helps us to prevent such events from being [sent to the constellation][msg] where it will be
+/// handled once again for page scrolling (which is definitely not what we'd want).
+///
+/// [msg]: https://doc.servo.org/script_traits/enum.ConstellationMsg.html#variant.KeyEvent
+///
+#[derive(JSTraceable, HeapSizeOf, Copy, Clone, PartialEq)]
+pub enum EventDefault {
+ /// The default action of the event is allowed (constructor's default)
+ Allowed,
+ /// The default action has been prevented by calling `PreventDefault`
+ Prevented,
+ /// The event has been handled somewhere in the DOM, and it should be prevented from being
+ /// re-handled elsewhere. This doesn't affect the judgement of `DefaultPrevented`
+ Handled,
+}
+
+#[derive(PartialEq)]
+pub enum EventStatus {
+ Canceled,
+ NotCanceled
+}
+
// https://dom.spec.whatwg.org/#concept-event-fire
pub struct EventRunnable {
pub target: Trusted<EventTarget>,
@@ -382,3 +412,116 @@ impl Runnable for SimpleEventRunnable {
target.fire_event(self.name);
}
}
+
+// See dispatch_event.
+// https://dom.spec.whatwg.org/#concept-event-dispatch
+fn dispatch_to_listeners(event: &Event, target: &EventTarget, event_path: &[&EventTarget]) {
+ assert!(!event.stop_propagation.get());
+ assert!(!event.stop_immediate.get());
+
+ let window = match Root::downcast::<Window>(target.global()) {
+ Some(window) => {
+ if window.need_emit_timeline_marker(TimelineMarkerType::DOMEvent) {
+ Some(window)
+ } else {
+ None
+ }
+ },
+ _ => None,
+ };
+
+ // Step 5.
+ event.phase.set(EventPhase::Capturing);
+
+ // Step 6.
+ for object in event_path.iter().rev() {
+ invoke(window.r(), object, event, Some(ListenerPhase::Capturing));
+ if event.stop_propagation.get() {
+ return;
+ }
+ }
+ assert!(!event.stop_propagation.get());
+ assert!(!event.stop_immediate.get());
+
+ // Step 7.
+ event.phase.set(EventPhase::AtTarget);
+
+ // Step 8.
+ invoke(window.r(), target, event, None);
+ if event.stop_propagation.get() {
+ return;
+ }
+ assert!(!event.stop_propagation.get());
+ assert!(!event.stop_immediate.get());
+
+ if !event.bubbles.get() {
+ return;
+ }
+
+ // Step 9.1.
+ event.phase.set(EventPhase::Bubbling);
+
+ // Step 9.2.
+ for object in event_path {
+ invoke(window.r(), object, event, Some(ListenerPhase::Bubbling));
+ if event.stop_propagation.get() {
+ return;
+ }
+ }
+}
+
+// https://dom.spec.whatwg.org/#concept-event-listener-invoke
+fn invoke(window: Option<&Window>,
+ object: &EventTarget,
+ event: &Event,
+ specific_listener_phase: Option<ListenerPhase>) {
+ // Step 1.
+ assert!(!event.stop_propagation.get());
+
+ // Steps 2-3.
+ let listeners = object.get_listeners_for(&event.type_(), specific_listener_phase);
+
+ // Step 4.
+ event.current_target.set(Some(object));
+
+ // Step 5.
+ inner_invoke(window, object, event, &listeners);
+
+ // TODO: step 6.
+}
+
+// https://dom.spec.whatwg.org/#concept-event-listener-inner-invoke
+fn inner_invoke(window: Option<&Window>,
+ object: &EventTarget,
+ event: &Event,
+ listeners: &[CompiledEventListener])
+ -> bool {
+ // Step 1.
+ let mut found = false;
+
+ // Step 2.
+ for listener in listeners {
+ // Steps 2.1 and 2.3-2.4 are not done because `listeners` contain only the
+ // relevant ones for this invoke call during the dispatch algorithm.
+
+ // Step 2.2.
+ found = true;
+
+ // TODO: step 2.5.
+
+ // Step 2.6.
+ let marker = TimelineMarker::start("DOMEvent".to_owned());
+ listener.call_or_handle_event(object, event, ExceptionHandling::Report);
+ if let Some(window) = window {
+ window.emit_timeline_marker(marker.end());
+ }
+ if event.stop_immediate.get() {
+ return found;
+ }
+
+ // TODO: step 2.7.
+ }
+
+ // Step 3.
+ found
+}
diff --git a/components/script/dom/eventdispatcher.rs b/components/script/dom/eventdispatcher.rs
deleted file mode 100644
index bdec56532dc..00000000000
--- a/components/script/dom/eventdispatcher.rs
+++ /dev/null
@@ -1,223 +0,0 @@
-/* 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 devtools_traits::{StartedTimelineMarker, TimelineMarker, TimelineMarkerType};
-use dom::bindings::callback::ExceptionHandling::Report;
-use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
-use dom::bindings::inheritance::Castable;
-use dom::bindings::js::{JS, Root, RootedReference};
-use dom::bindings::reflector::DomObject;
-use dom::document::Document;
-use dom::event::{Event, EventPhase};
-use dom::eventtarget::{CompiledEventListener, EventTarget, ListenerPhase};
-use dom::node::Node;
-use dom::virtualmethods::vtable_for;
-use dom::window::Window;
-
-struct AutoDOMEventMarker {
- window: Root<Window>,
- marker: Option<StartedTimelineMarker>,
-}
-
-impl AutoDOMEventMarker {
- fn new(window: &Window) -> AutoDOMEventMarker {
- AutoDOMEventMarker {
- window: Root::from_ref(window),
- marker: Some(TimelineMarker::start("DOMEvent".to_owned())),
- }
- }
-}
-
-impl Drop for AutoDOMEventMarker {
- fn drop(&mut self) {
- self.window.emit_timeline_marker(self.marker.take().unwrap().end());
- }
-}
-
-fn handle_event(window: Option<&Window>, listener: &CompiledEventListener,
- current_target: &EventTarget, event: &Event) {
- let _marker;
- if let Some(window) = window {
- _marker = AutoDOMEventMarker::new(window);
- }
-
- listener.call_or_handle_event(current_target, event, Report);
-}
-
-// See dispatch_event.
-// https://dom.spec.whatwg.org/#concept-event-dispatch
-fn dispatch_to_listeners(event: &Event, target: &EventTarget, event_path: &[&EventTarget]) {
- assert!(!event.stop_propagation());
- assert!(!event.stop_immediate());
-
- let window = match Root::downcast::<Window>(target.global()) {
- Some(window) => {
- if window.need_emit_timeline_marker(TimelineMarkerType::DOMEvent) {
- Some(window)
- } else {
- None
- }
- },
- _ => None,
- };
-
- // Step 5.
- event.set_phase(EventPhase::Capturing);
-
- // Step 6.
- for object in event_path.iter().rev() {
- invoke(window.r(), object, event, Some(ListenerPhase::Capturing));
- if event.stop_propagation() {
- return;
- }
- }
- assert!(!event.stop_propagation());
- assert!(!event.stop_immediate());
-
- // Step 7.
- event.set_phase(EventPhase::AtTarget);
-
- // Step 8.
- invoke(window.r(), target, event, None);
- if event.stop_propagation() {
- return;
- }
- assert!(!event.stop_propagation());
- assert!(!event.stop_immediate());
-
- if !event.bubbles() {
- return;
- }
-
- // Step 9.1.
- event.set_phase(EventPhase::Bubbling);
-
- // Step 9.2.
- for object in event_path {
- invoke(window.r(), object, event, Some(ListenerPhase::Bubbling));
- if event.stop_propagation() {
- return;
- }
- }
-}
-
-#[derive(PartialEq)]
-pub enum EventStatus {
- Canceled,
- NotCanceled
-}
-
-// https://dom.spec.whatwg.org/#concept-event-dispatch
-pub fn dispatch_event(target: &EventTarget,
- target_override: Option<&EventTarget>,
- event: &Event) -> EventStatus {
- assert!(!event.dispatching());
- assert!(event.initialized());
- assert_eq!(event.phase(), EventPhase::None);
- assert!(event.GetCurrentTarget().is_none());
-
- // Step 1.
- event.mark_as_dispatching();
-
- // Step 2.
- event.set_target(target_override.unwrap_or(target));
-
- if event.stop_propagation() {
- // If the event's stop propagation flag is set, we can skip everything because
- // it prevents the calls of the invoke algorithm in the spec.
-
- // Step 10-12.
- event.clear_dispatching_flags();
-
- // Step 14.
- return event.status();
- }
-
- // Step 3. The "invoke" algorithm is only used on `target` separately,
- // so we don't put it in the path.
- rooted_vec!(let mut event_path);
-
- // Step 4.
- if let Some(target_node) = target.downcast::<Node>() {
- for ancestor in target_node.ancestors() {
- event_path.push(JS::from_ref(ancestor.upcast::<EventTarget>()));
- }
- let top_most_ancestor_or_target =
- Root::from_ref(event_path.r().last().cloned().unwrap_or(target));
- if let Some(document) = Root::downcast::<Document>(top_most_ancestor_or_target) {
- if event.type_() != atom!("load") && document.browsing_context().is_some() {
- event_path.push(JS::from_ref(document.window().upcast()));
- }
- }
- }
-
- // Steps 5-9. In a separate function to short-circuit various things easily.
- dispatch_to_listeners(event, target, event_path.r());
-
- // Default action.
- if let Some(target) = event.GetTarget() {
- if let Some(node) = target.downcast::<Node>() {
- let vtable = vtable_for(&node);
- vtable.handle_event(event);
- }
- }
-
- // Step 10-12.
- event.clear_dispatching_flags();
-
- // Step 14.
- event.status()
-}
-
-// https://dom.spec.whatwg.org/#concept-event-listener-invoke
-fn invoke(window: Option<&Window>,
- object: &EventTarget,
- event: &Event,
- specific_listener_phase: Option<ListenerPhase>) {
- // Step 1.
- assert!(!event.stop_propagation());
-
- // Steps 2-3.
- let listeners = object.get_listeners_for(&event.type_(), specific_listener_phase);
-
- // Step 4.
- event.set_current_target(object);
-
- // Step 5.
- inner_invoke(window, object, event, &listeners);
-
- // TODO: step 6.
-}
-
-// https://dom.spec.whatwg.org/#concept-event-listener-inner-invoke
-fn inner_invoke(window: Option<&Window>,
- object: &EventTarget,
- event: &Event,
- listeners: &[CompiledEventListener])
- -> bool {
- // Step 1.
- let mut found = false;
-
- // Step 2.
- for listener in listeners {
- // Steps 2.1 and 2.3-2.4 are not done because `listeners` contain only the
- // relevant ones for this invoke call during the dispatch algorithm.
-
- // Step 2.2.
- found = true;
-
- // TODO: step 2.5.
-
- // Step 2.6.
- handle_event(window, listener, object, event);
- if event.stop_immediate() {
- return found;
- }
-
- // TODO: step 2.7.
- }
-
- // Step 3.
- found
-}
diff --git a/components/script/dom/eventtarget.rs b/components/script/dom/eventtarget.rs
index 1023b97600f..15790d7ce53 100644
--- a/components/script/dom/eventtarget.rs
+++ b/components/script/dom/eventtarget.rs
@@ -22,8 +22,7 @@ use dom::bindings::reflector::{DomObject, Reflector};
use dom::bindings::str::DOMString;
use dom::element::Element;
use dom::errorevent::ErrorEvent;
-use dom::event::{Event, EventBubbles, EventCancelable};
-use dom::eventdispatcher::{EventStatus, dispatch_event};
+use dom::event::{Event, EventBubbles, EventCancelable, EventStatus};
use dom::node::document_from_node;
use dom::virtualmethods::VirtualMethods;
use dom::window::Window;
@@ -300,11 +299,11 @@ impl EventTarget {
pub fn dispatch_event_with_target(&self,
target: &EventTarget,
event: &Event) -> EventStatus {
- dispatch_event(self, Some(target), event)
+ event.dispatch(self, Some(target))
}
pub fn dispatch_event(&self, event: &Event) -> EventStatus {
- dispatch_event(self, None, event)
+ event.dispatch(self, None)
}
/// https://html.spec.whatwg.org/multipage/#event-handler-attributes:event-handlers-11
diff --git a/components/script/dom/focusevent.rs b/components/script/dom/focusevent.rs
index c7e48531479..6ffed30e857 100644
--- a/components/script/dom/focusevent.rs
+++ b/components/script/dom/focusevent.rs
@@ -12,7 +12,6 @@ use dom::bindings::reflector::reflect_dom_object;
use dom::bindings::str::DOMString;
use dom::event::{EventBubbles, EventCancelable};
use dom::eventtarget::EventTarget;
-use dom::globalscope::GlobalScope;
use dom::uievent::UIEvent;
use dom::window::Window;
use std::default::Default;
@@ -31,9 +30,9 @@ impl FocusEvent {
}
}
- pub fn new_uninitialized(global: &GlobalScope) -> Root<FocusEvent> {
+ pub fn new_uninitialized(window: &Window) -> Root<FocusEvent> {
reflect_dom_object(box FocusEvent::new_inherited(),
- global,
+ window,
FocusEventBinding::Wrap)
}
@@ -44,7 +43,7 @@ impl FocusEvent {
view: Option<&Window>,
detail: i32,
related_target: Option<&EventTarget>) -> Root<FocusEvent> {
- let ev = FocusEvent::new_uninitialized(window.upcast());
+ let ev = FocusEvent::new_uninitialized(window);
ev.upcast::<UIEvent>().InitUIEvent(type_,
bool::from(can_bubble),
bool::from(cancelable),
diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs
index 7a9e5074266..f513d4285ad 100644
--- a/components/script/dom/globalscope.rs
+++ b/components/script/dom/globalscope.rs
@@ -15,8 +15,7 @@ use dom::bindings::str::DOMString;
use dom::crypto::Crypto;
use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope;
use dom::errorevent::ErrorEvent;
-use dom::event::{Event, EventBubbles, EventCancelable};
-use dom::eventdispatcher::EventStatus;
+use dom::event::{Event, EventBubbles, EventCancelable, EventStatus};
use dom::eventtarget::EventTarget;
use dom::window::Window;
use dom::workerglobalscope::WorkerGlobalScope;
diff --git a/components/script/dom/hashchangeevent.rs b/components/script/dom/hashchangeevent.rs
index b93b7a93631..cd4b2b0a71f 100644
--- a/components/script/dom/hashchangeevent.rs
+++ b/components/script/dom/hashchangeevent.rs
@@ -11,7 +11,7 @@ use dom::bindings::js::Root;
use dom::bindings::reflector::reflect_dom_object;
use dom::bindings::str::{DOMString, USVString};
use dom::event::Event;
-use dom::globalscope::GlobalScope;
+use dom::window::Window;
use servo_atoms::Atom;
// https://html.spec.whatwg.org/multipage/#hashchangeevent
@@ -31,13 +31,13 @@ impl HashChangeEvent {
}
}
- pub fn new_uninitialized(global: &GlobalScope) -> Root<HashChangeEvent> {
+ pub fn new_uninitialized(window: &Window) -> Root<HashChangeEvent> {
reflect_dom_object(box HashChangeEvent::new_inherited(String::new(), String::new()),
- global,
+ window,
HashChangeEventBinding::Wrap)
}
- pub fn new(global: &GlobalScope,
+ pub fn new(window: &Window,
type_: Atom,
bubbles: bool,
cancelable: bool,
@@ -45,7 +45,7 @@ impl HashChangeEvent {
new_url: String)
-> Root<HashChangeEvent> {
let ev = reflect_dom_object(box HashChangeEvent::new_inherited(old_url, new_url),
- global,
+ window,
HashChangeEventBinding::Wrap);
{
let event = ev.upcast::<Event>();
@@ -54,11 +54,11 @@ impl HashChangeEvent {
ev
}
- pub fn Constructor(global: &GlobalScope,
+ pub fn Constructor(window: &Window,
type_: DOMString,
init: &HashChangeEventBinding::HashChangeEventInit)
-> Fallible<Root<HashChangeEvent>> {
- Ok(HashChangeEvent::new(global,
+ Ok(HashChangeEvent::new(window,
Atom::from(type_),
init.parent.bubbles,
init.parent.cancelable,
diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs
index 42b4a4d149a..e1e8dabac7b 100644
--- a/components/script/dom/htmlscriptelement.rs
+++ b/components/script/dom/htmlscriptelement.rs
@@ -17,8 +17,7 @@ use dom::bindings::str::DOMString;
use dom::document::Document;
use dom::element::{AttributeMutation, Element, ElementCreator};
use dom::element::{cors_setting_for_element, reflect_cross_origin_attribute, set_cross_origin_attribute};
-use dom::event::{Event, EventBubbles, EventCancelable};
-use dom::eventdispatcher::EventStatus;
+use dom::event::{Event, EventBubbles, EventCancelable, EventStatus};
use dom::globalscope::GlobalScope;
use dom::htmlelement::HTMLElement;
use dom::node::{ChildrenMutation, CloneChildrenFlag, Node};
diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs
index 0fd610ed46b..5de594a5195 100644
--- a/components/script/dom/mod.rs
+++ b/components/script/dom/mod.rs
@@ -276,7 +276,6 @@ pub mod domtokenlist;
pub mod element;
pub mod errorevent;
pub mod event;
-pub mod eventdispatcher;
pub mod eventsource;
pub mod eventtarget;
pub mod extendableevent;
diff --git a/components/script/dom/pagetransitionevent.rs b/components/script/dom/pagetransitionevent.rs
index b40f6c1ab39..e76a6444d4c 100644
--- a/components/script/dom/pagetransitionevent.rs
+++ b/components/script/dom/pagetransitionevent.rs
@@ -11,7 +11,7 @@ use dom::bindings::js::Root;
use dom::bindings::reflector::reflect_dom_object;
use dom::bindings::str::DOMString;
use dom::event::Event;
-use dom::globalscope::GlobalScope;
+use dom::window::Window;
use servo_atoms::Atom;
use std::cell::Cell;
@@ -30,19 +30,19 @@ impl PageTransitionEvent {
}
}
- pub fn new_uninitialized(global: &GlobalScope) -> Root<PageTransitionEvent> {
+ pub fn new_uninitialized(window: &Window) -> Root<PageTransitionEvent> {
reflect_dom_object(box PageTransitionEvent::new_inherited(),
- global,
+ window,
PageTransitionEventBinding::Wrap)
}
- pub fn new(global: &GlobalScope,
+ pub fn new(window: &Window,
type_: Atom,
bubbles: bool,
cancelable: bool,
persisted: bool)
-> Root<PageTransitionEvent> {
- let ev = PageTransitionEvent::new_uninitialized(global);
+ let ev = PageTransitionEvent::new_uninitialized(window);
ev.persisted.set(persisted);
{
let event = ev.upcast::<Event>();
@@ -51,11 +51,11 @@ impl PageTransitionEvent {
ev
}
- pub fn Constructor(global: &GlobalScope,
+ pub fn Constructor(window: &Window,
type_: DOMString,
init: &PageTransitionEventBinding::PageTransitionEventInit)
-> Fallible<Root<PageTransitionEvent>> {
- Ok(PageTransitionEvent::new(global,
+ Ok(PageTransitionEvent::new(window,
Atom::from(type_),
init.parent.bubbles,
init.parent.cancelable,
diff --git a/components/script/dom/popstateevent.rs b/components/script/dom/popstateevent.rs
index 44183f7483f..fde05e30394 100644
--- a/components/script/dom/popstateevent.rs
+++ b/components/script/dom/popstateevent.rs
@@ -11,7 +11,7 @@ use dom::bindings::js::{MutHeapJSVal, Root};
use dom::bindings::reflector::reflect_dom_object;
use dom::bindings::str::DOMString;
use dom::event::Event;
-use dom::globalscope::GlobalScope;
+use dom::window::Window;
use js::jsapi::{HandleValue, JSContext};
use js::jsval::JSVal;
use servo_atoms::Atom;
@@ -32,19 +32,19 @@ impl PopStateEvent {
}
}
- pub fn new_uninitialized(global: &GlobalScope) -> Root<PopStateEvent> {
+ pub fn new_uninitialized(window: &Window) -> Root<PopStateEvent> {
reflect_dom_object(box PopStateEvent::new_inherited(),
- global,
+ window,
PopStateEventBinding::Wrap)
}
- pub fn new(global: &GlobalScope,
+ pub fn new(window: &Window,
type_: Atom,
bubbles: bool,
cancelable: bool,
state: HandleValue)
-> Root<PopStateEvent> {
- let ev = PopStateEvent::new_uninitialized(global);
+ let ev = PopStateEvent::new_uninitialized(window);
ev.state.set(state.get());
{
let event = ev.upcast::<Event>();
@@ -54,11 +54,11 @@ impl PopStateEvent {
}
#[allow(unsafe_code)]
- pub fn Constructor(global: &GlobalScope,
+ pub fn Constructor(window: &Window,
type_: DOMString,
init: &PopStateEventBinding::PopStateEventInit)
-> Fallible<Root<PopStateEvent>> {
- Ok(PopStateEvent::new(global,
+ Ok(PopStateEvent::new(window,
Atom::from(type_),
init.parent.bubbles,
init.parent.cancelable,
diff --git a/components/script/dom/transitionevent.rs b/components/script/dom/transitionevent.rs
index cc17e77eae1..4630ec70bc0 100644
--- a/components/script/dom/transitionevent.rs
+++ b/components/script/dom/transitionevent.rs
@@ -12,7 +12,6 @@ use dom::bindings::num::Finite;
use dom::bindings::reflector::reflect_dom_object;
use dom::bindings::str::DOMString;
use dom::event::Event;
-use dom::globalscope::GlobalScope;
use dom::window::Window;
use servo_atoms::Atom;
@@ -25,7 +24,7 @@ pub struct TransitionEvent {
}
impl TransitionEvent {
- pub fn new_inherited(init: &TransitionEventInit) -> TransitionEvent {
+ fn new_inherited(init: &TransitionEventInit) -> TransitionEvent {
TransitionEvent {
event: Event::new_inherited(),
property_name: Atom::from(init.propertyName.clone()),
@@ -34,11 +33,11 @@ impl TransitionEvent {
}
}
- pub fn new(global: &GlobalScope,
+ pub fn new(window: &Window,
type_: Atom,
init: &TransitionEventInit) -> Root<TransitionEvent> {
let ev = reflect_dom_object(box TransitionEvent::new_inherited(init),
- global,
+ window,
TransitionEventBinding::Wrap);
{
let event = ev.upcast::<Event>();
@@ -50,8 +49,7 @@ impl TransitionEvent {
pub fn Constructor(window: &Window,
type_: DOMString,
init: &TransitionEventInit) -> Fallible<Root<TransitionEvent>> {
- let global = window.upcast::<GlobalScope>();
- Ok(TransitionEvent::new(global, Atom::from(type_), init))
+ Ok(TransitionEvent::new(window, Atom::from(type_), init))
}
}
diff --git a/components/script/dom/webidls/BeforeUnloadEvent.webidl b/components/script/dom/webidls/BeforeUnloadEvent.webidl
index 74b0cd8e62c..71fe9396d48 100644
--- a/components/script/dom/webidls/BeforeUnloadEvent.webidl
+++ b/components/script/dom/webidls/BeforeUnloadEvent.webidl
@@ -6,7 +6,7 @@
* https://html.spec.whatwg.org/multipage/#beforeunloadevent
*/
-[Exposed=(Window,Worker)]
+[Exposed=Window]
interface BeforeUnloadEvent : Event {
attribute DOMString returnValue;
};
diff --git a/components/script/dom/webidls/FocusEvent.webidl b/components/script/dom/webidls/FocusEvent.webidl
index 42e560b72b4..14ec3ae67e9 100644
--- a/components/script/dom/webidls/FocusEvent.webidl
+++ b/components/script/dom/webidls/FocusEvent.webidl
@@ -3,7 +3,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://w3c.github.io/uievents/#interface-FocusEvent
-[Constructor(DOMString typeArg, optional FocusEventInit focusEventInitDict)]
+[Constructor(DOMString typeArg, optional FocusEventInit focusEventInitDict),
+ Exposed=Window]
interface FocusEvent : UIEvent {
readonly attribute EventTarget? relatedTarget;
};
diff --git a/components/script/dom/webidls/HashChangeEvent.webidl b/components/script/dom/webidls/HashChangeEvent.webidl
index d34400c7ccc..3d81e8ad383 100644
--- a/components/script/dom/webidls/HashChangeEvent.webidl
+++ b/components/script/dom/webidls/HashChangeEvent.webidl
@@ -3,7 +3,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#hashchangeevent
-[Constructor(DOMString type, optional HashChangeEventInit eventInitDict), Exposed=(Window,Worker)]
+[Constructor(DOMString type, optional HashChangeEventInit eventInitDict),
+ Exposed=Window]
interface HashChangeEvent : Event {
readonly attribute USVString oldURL;
readonly attribute USVString newURL;
diff --git a/components/script/dom/webidls/Location.webidl b/components/script/dom/webidls/Location.webidl
index 431ab87d5e5..d611a20b883 100644
--- a/components/script/dom/webidls/Location.webidl
+++ b/components/script/dom/webidls/Location.webidl
@@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#location
-[Exposed=(Window,Worker), Unforgeable] interface Location {
+[Exposed=Window, Unforgeable] interface Location {
/*stringifier*/ attribute USVString href;
readonly attribute USVString origin;
attribute USVString protocol;
diff --git a/components/script/dom/webidls/MouseEvent.webidl b/components/script/dom/webidls/MouseEvent.webidl
index c95739429a8..e9f7a31db48 100644
--- a/components/script/dom/webidls/MouseEvent.webidl
+++ b/components/script/dom/webidls/MouseEvent.webidl
@@ -3,7 +3,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://w3c.github.io/uievents/#interface-mouseevent
-[Constructor(DOMString typeArg, optional MouseEventInit mouseEventInitDict)]
+[Constructor(DOMString typeArg, optional MouseEventInit mouseEventInitDict),
+ Exposed=Window]
interface MouseEvent : UIEvent {
readonly attribute long screenX;
readonly attribute long screenY;
diff --git a/components/script/dom/webidls/PageTransitionEvent.webidl b/components/script/dom/webidls/PageTransitionEvent.webidl
index 3f3ed0b797a..a23f3099bad 100644
--- a/components/script/dom/webidls/PageTransitionEvent.webidl
+++ b/components/script/dom/webidls/PageTransitionEvent.webidl
@@ -3,7 +3,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#the-pagetransitionevent-interface
-[Constructor(DOMString type, optional PageTransitionEventInit eventInitDict), Exposed=(Window,Worker)]
+[Constructor(DOMString type, optional PageTransitionEventInit eventInitDict),
+ Exposed=Window]
interface PageTransitionEvent : Event {
readonly attribute boolean persisted;
};
diff --git a/components/script/dom/webidls/PopStateEvent.webidl b/components/script/dom/webidls/PopStateEvent.webidl
index f5052df597f..4508cac6288 100644
--- a/components/script/dom/webidls/PopStateEvent.webidl
+++ b/components/script/dom/webidls/PopStateEvent.webidl
@@ -3,7 +3,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#the-popstateevent-interface
-[Constructor(DOMString type, optional PopStateEventInit eventInitDict), Exposed=(Window,Worker)]
+[Constructor(DOMString type, optional PopStateEventInit eventInitDict),
+ Exposed=Window]
interface PopStateEvent : Event {
readonly attribute any state;
};
diff --git a/components/script/dom/worker.rs b/components/script/dom/worker.rs
index 2d6581b9e43..18b3a441d68 100644
--- a/components/script/dom/worker.rs
+++ b/components/script/dom/worker.rs
@@ -17,8 +17,7 @@ use dom::bindings::str::DOMString;
use dom::bindings::structuredclone::StructuredCloneData;
use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope;
use dom::errorevent::ErrorEvent;
-use dom::event::{Event, EventBubbles, EventCancelable};
-use dom::eventdispatcher::EventStatus;
+use dom::event::{Event, EventBubbles, EventCancelable, EventStatus};
use dom::eventtarget::EventTarget;
use dom::globalscope::GlobalScope;
use dom::messageevent::MessageEvent;
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index 8923ce7254d..db9a53816a2 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -1620,7 +1620,7 @@ impl ScriptThread {
// FIXME: Handle pseudo-elements properly
pseudoElement: DOMString::new()
};
- let transition_event = TransitionEvent::new(window.upcast(),
+ let transition_event = TransitionEvent::new(&window,
atom!("transitionend"),
&init);
transition_event.upcast::<Event>().fire(node.upcast());
diff --git a/components/script/test.rs b/components/script/test.rs
index 83523c47817..9aeff2a22a5 100644
--- a/components/script/test.rs
+++ b/components/script/test.rs
@@ -9,6 +9,7 @@ pub use dom::headers::normalize_value;
pub use dom::bindings::cell::DOMRefCell;
pub use dom::bindings::js::JS;
pub use dom::node::Node;
+pub use dom::bindings::refcounted::TrustedPromise;
pub mod area {
pub use dom::htmlareaelement::{Area, Shape};