mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
dom: Implement current window event.
This commit is contained in:
parent
19f4be38d2
commit
097a84671a
6 changed files with 63 additions and 24 deletions
|
@ -690,12 +690,15 @@ fn inner_invoke(
|
|||
object.remove_listener_if_once(&event.type_(), &event_listener);
|
||||
}
|
||||
|
||||
// Step 2.6-2.8
|
||||
// FIXME(#25478): we need to get the global that the event
|
||||
// listener is going to be called on, then if it's a Window
|
||||
// set its .event to the event, remembering the previous
|
||||
// value of its .event. This allows events to just use
|
||||
// the word "event" instead of taking the event as an argument.
|
||||
// Step 2.6
|
||||
let global = listener.associated_global();
|
||||
|
||||
// Step 2.7-2.8
|
||||
let current_event = if let Some(window) = global.downcast::<Window>() {
|
||||
window.set_current_event(Some(event))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Step 2.9 TODO: EventListener passive option not implemented
|
||||
|
||||
|
@ -712,8 +715,9 @@ fn inner_invoke(
|
|||
// Step 2.11 TODO: passive not implemented
|
||||
|
||||
// Step 2.12
|
||||
// TODO This is where we put back the .event we
|
||||
// had before step 2.6.
|
||||
if let Some(window) = global.downcast::<Window>() {
|
||||
window.set_current_event(current_event.as_ref().map(|e| &**e));
|
||||
}
|
||||
|
||||
// Step 2.13: short-circuit instead of going to next listener
|
||||
if event.stop_immediate.get() {
|
||||
|
|
|
@ -150,6 +150,23 @@ pub enum CompiledEventListener {
|
|||
}
|
||||
|
||||
impl CompiledEventListener {
|
||||
#[allow(unsafe_code)]
|
||||
pub fn associated_global(&self) -> DomRoot<GlobalScope> {
|
||||
let obj = match self {
|
||||
CompiledEventListener::Listener(listener) => listener.callback(),
|
||||
CompiledEventListener::Handler(CommonEventHandler::EventHandler(handler)) => {
|
||||
handler.callback()
|
||||
},
|
||||
CompiledEventListener::Handler(CommonEventHandler::ErrorEventHandler(handler)) => {
|
||||
handler.callback()
|
||||
},
|
||||
CompiledEventListener::Handler(CommonEventHandler::BeforeUnloadEventHandler(
|
||||
handler,
|
||||
)) => handler.callback(),
|
||||
};
|
||||
unsafe { GlobalScope::from_object(obj) }
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#the-event-handler-processing-algorithm
|
||||
pub fn call_or_handle_event(
|
||||
&self,
|
||||
|
|
|
@ -180,6 +180,10 @@ partial interface Window {
|
|||
Selection? getSelection();
|
||||
};
|
||||
|
||||
// https://dom.spec.whatwg.org/#interface-window-extensions
|
||||
partial interface Window {
|
||||
[Replaceable] readonly attribute any event; // historical
|
||||
};
|
||||
|
||||
dictionary WindowPostMessageOptions : PostMessageOptions {
|
||||
USVString targetOrigin = "/";
|
||||
|
|
|
@ -83,6 +83,7 @@ use euclid::default::{Point2D as UntypedPoint2D, Rect as UntypedRect};
|
|||
use euclid::{Point2D, Rect, Scale, Size2D, Vector2D};
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use ipc_channel::router::ROUTER;
|
||||
use js::conversions::ToJSValConvertible;
|
||||
use js::jsapi::Heap;
|
||||
use js::jsapi::JSAutoRealm;
|
||||
use js::jsapi::JSObject;
|
||||
|
@ -340,6 +341,9 @@ pub struct Window {
|
|||
/// those values will cause the marker to be set to false.
|
||||
#[ignore_malloc_size_of = "Rc is hard"]
|
||||
layout_marker: DomRefCell<Rc<Cell<bool>>>,
|
||||
|
||||
/// https://dom.spec.whatwg.org/#window-current-event
|
||||
current_event: DomRefCell<Option<Dom<Event>>>,
|
||||
}
|
||||
|
||||
impl Window {
|
||||
|
@ -1334,9 +1338,34 @@ impl WindowMethods for Window {
|
|||
fn GetSelection(&self) -> Option<DomRoot<Selection>> {
|
||||
self.document.get().and_then(|d| d.GetSelection())
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-window-event
|
||||
#[allow(unsafe_code)]
|
||||
fn Event(&self, cx: JSContext) -> JSVal {
|
||||
rooted!(in(*cx) let mut rval = UndefinedValue());
|
||||
if let Some(ref event) = *self.current_event.borrow() {
|
||||
unsafe {
|
||||
event
|
||||
.reflector()
|
||||
.get_jsobject()
|
||||
.to_jsval(*cx, rval.handle_mut());
|
||||
}
|
||||
}
|
||||
rval.get()
|
||||
}
|
||||
}
|
||||
|
||||
impl Window {
|
||||
pub(crate) fn set_current_event(&self, event: Option<&Event>) -> Option<DomRoot<Event>> {
|
||||
let current = self
|
||||
.current_event
|
||||
.borrow()
|
||||
.as_ref()
|
||||
.map(|e| DomRoot::from_ref(&**e));
|
||||
*self.current_event.borrow_mut() = event.map(|e| Dom::from_ref(e));
|
||||
current
|
||||
}
|
||||
|
||||
/// https://html.spec.whatwg.org/multipage/#window-post-message-steps
|
||||
fn post_message_impl(
|
||||
&self,
|
||||
|
@ -2375,6 +2404,7 @@ impl Window {
|
|||
event_loop_waker,
|
||||
visible: Cell::new(true),
|
||||
layout_marker: DomRefCell::new(Rc::new(Cell::new(true))),
|
||||
current_event: DomRefCell::new(None),
|
||||
});
|
||||
|
||||
unsafe { WindowBinding::Wrap(JSContext::from_ptr(runtime.cx()), win) }
|
||||
|
|
|
@ -1,19 +1,6 @@
|
|||
[event-global.html]
|
||||
[event exists on window, which is initially set to undefined]
|
||||
expected: FAIL
|
||||
|
||||
[window.event is only defined during dispatch]
|
||||
expected: FAIL
|
||||
|
||||
[window.event is undefined if the target is in a shadow tree (event dispatched outside shadow tree)]
|
||||
expected: FAIL
|
||||
|
||||
[window.event is undefined if the target is in a shadow tree (event dispatched inside shadow tree)]
|
||||
expected: FAIL
|
||||
|
||||
[window.event is set to the current event during dispatch]
|
||||
expected: FAIL
|
||||
|
||||
[window.event is set to the current event, which is the event passed to dispatch]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -152,9 +152,6 @@
|
|||
[AbortSignal interface object length]
|
||||
expected: FAIL
|
||||
|
||||
[Window interface: attribute event]
|
||||
expected: FAIL
|
||||
|
||||
[AbortController interface: new AbortController() must inherit property "abort()" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue