mirror of
https://github.com/servo/servo.git
synced 2025-06-24 09:04:33 +01:00
Add stubs for inline event handler manipulation.
This commit is contained in:
parent
2717ab65ec
commit
2d6153772c
10 changed files with 223 additions and 23 deletions
|
@ -34,6 +34,7 @@ DOMInterfaces = {
|
||||||
'DOMParser': {},
|
'DOMParser': {},
|
||||||
'Element': {},
|
'Element': {},
|
||||||
'Event': {},
|
'Event': {},
|
||||||
|
'EventHandler': {},
|
||||||
'EventListener': {
|
'EventListener': {
|
||||||
'nativeType': 'EventListenerBinding::EventListener',
|
'nativeType': 'EventListenerBinding::EventListener',
|
||||||
},
|
},
|
||||||
|
|
|
@ -705,17 +705,17 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
|
||||||
"rooting issues")
|
"rooting issues")
|
||||||
# XXXbz we're going to assume that callback types are always
|
# XXXbz we're going to assume that callback types are always
|
||||||
# nullable and always have [TreatNonCallableAsNull] for now.
|
# nullable and always have [TreatNonCallableAsNull] for now.
|
||||||
haveCallable = "${val}.isObject() && JS_ObjectIsCallable(cx, &${val}.toObject())"
|
haveCallable = "${val}.is_object() && JS_ObjectIsCallable(cx, ${val}.to_object()) != 0"
|
||||||
if defaultValue is not None:
|
if defaultValue is not None:
|
||||||
assert(isinstance(defaultValue, IDLNullValue))
|
assert(isinstance(defaultValue, IDLNullValue))
|
||||||
haveCallable = "${haveValue} && " + haveCallable
|
haveCallable = "${haveValue} && " + haveCallable
|
||||||
return (
|
return (
|
||||||
"if (%s) {\n"
|
"if (%s) {\n"
|
||||||
" ${declName} = &${val}.toObject();\n"
|
" ${val}.to_object()\n"
|
||||||
"} else {\n"
|
"} else {\n"
|
||||||
" ${declName} = NULL;\n"
|
" ptr::mut_null()\n"
|
||||||
"}" % haveCallable,
|
"}" % haveCallable,
|
||||||
CGGeneric("JSObject*"), None, needsRooting)
|
CGGeneric("*mut JSObject"), needsRooting)
|
||||||
|
|
||||||
if type.isAny():
|
if type.isAny():
|
||||||
assert not isEnforceRange and not isClamp
|
assert not isEnforceRange and not isClamp
|
||||||
|
@ -1346,6 +1346,14 @@ class CGIfWrapper(CGWrapper):
|
||||||
CGWrapper.__init__(self, CGIndenter(child), pre=pre.define(),
|
CGWrapper.__init__(self, CGIndenter(child), pre=pre.define(),
|
||||||
post="\n}")
|
post="\n}")
|
||||||
|
|
||||||
|
class CGTemplatedType(CGWrapper):
|
||||||
|
def __init__(self, templateName, child, isConst=False, isReference=False):
|
||||||
|
const = "const " if isConst else ""
|
||||||
|
pre = "%s%s<" % (const, templateName)
|
||||||
|
ref = "&" if isReference else ""
|
||||||
|
post = ">%s" % ref
|
||||||
|
CGWrapper.__init__(self, child, pre=pre, post=post)
|
||||||
|
|
||||||
class CGNamespace(CGWrapper):
|
class CGNamespace(CGWrapper):
|
||||||
def __init__(self, namespace, child, public=False):
|
def __init__(self, namespace, child, public=False):
|
||||||
pre = "%smod %s {\n" % ("pub " if public else "", namespace)
|
pre = "%smod %s {\n" % ("pub " if public else "", namespace)
|
||||||
|
@ -3128,7 +3136,7 @@ class ClassMember(ClassItem):
|
||||||
ClassItem.__init__(self, name, visibility)
|
ClassItem.__init__(self, name, visibility)
|
||||||
|
|
||||||
def declare(self, cgClass):
|
def declare(self, cgClass):
|
||||||
return '%s: %s,\n' % (self.name, self.type)
|
return '%s %s: %s,\n' % (self.visibility, self.name, self.type)
|
||||||
|
|
||||||
def define(self, cgClass):
|
def define(self, cgClass):
|
||||||
if not self.static:
|
if not self.static:
|
||||||
|
@ -4357,7 +4365,7 @@ class CGNativeMember(ClassMethod):
|
||||||
elif type.isAny():
|
elif type.isAny():
|
||||||
typeDecl, template = "JS::Value", "return ${declName};"
|
typeDecl, template = "JS::Value", "return ${declName};"
|
||||||
elif type.isObject():
|
elif type.isObject():
|
||||||
typeDecl, template = "JSObject*", "return ${declName};"
|
typeDecl, template = "*JSObject", "return ${declName};"
|
||||||
elif type.isSpiderMonkeyInterface():
|
elif type.isSpiderMonkeyInterface():
|
||||||
if type.nullable():
|
if type.nullable():
|
||||||
returnCode = "return ${declName}.IsNull() ? nullptr : ${declName}.Value().Obj();"
|
returnCode = "return ${declName}.IsNull() ? nullptr : ${declName}.Value().Obj();"
|
||||||
|
@ -4561,7 +4569,7 @@ class CGNativeMember(ClassMethod):
|
||||||
elif optional:
|
elif optional:
|
||||||
# Note: All variadic args claim to be optional, but we can just use
|
# Note: All variadic args claim to be optional, but we can just use
|
||||||
# empty arrays to represent them not being present.
|
# empty arrays to represent them not being present.
|
||||||
decl = CGTemplatedType("Optional", decl)
|
decl = CGTemplatedType("Option", decl)
|
||||||
ref = True
|
ref = True
|
||||||
return (decl, ref)
|
return (decl, ref)
|
||||||
|
|
||||||
|
@ -4816,6 +4824,7 @@ class CallbackMember(CGNativeMember):
|
||||||
def getResultConversion(self):
|
def getResultConversion(self):
|
||||||
replacements = {
|
replacements = {
|
||||||
"val": "rval",
|
"val": "rval",
|
||||||
|
"declName": "rvalDecl",
|
||||||
}
|
}
|
||||||
|
|
||||||
if isJSImplementedDescriptor(self.descriptorProvider):
|
if isJSImplementedDescriptor(self.descriptorProvider):
|
||||||
|
|
|
@ -9,7 +9,7 @@ use dom::bindings::utils::jsstring_to_str;
|
||||||
use dom::bindings::utils::unwrap_jsmanaged;
|
use dom::bindings::utils::unwrap_jsmanaged;
|
||||||
use servo_util::str::DOMString;
|
use servo_util::str::DOMString;
|
||||||
|
|
||||||
use js::jsapi::{JSBool, JSContext};
|
use js::jsapi::{JSBool, JSContext, JSObject};
|
||||||
use js::jsapi::{JS_ValueToUint64, JS_ValueToInt64};
|
use js::jsapi::{JS_ValueToUint64, JS_ValueToInt64};
|
||||||
use js::jsapi::{JS_ValueToECMAUint32, JS_ValueToECMAInt32};
|
use js::jsapi::{JS_ValueToECMAUint32, JS_ValueToECMAInt32};
|
||||||
use js::jsapi::{JS_ValueToUint16, JS_ValueToNumber, JS_ValueToBoolean};
|
use js::jsapi::{JS_ValueToUint16, JS_ValueToNumber, JS_ValueToBoolean};
|
||||||
|
@ -18,7 +18,7 @@ use js::jsapi::{JS_NewUCStringCopyN, JS_NewStringCopyN};
|
||||||
use js::jsapi::{JS_WrapValue};
|
use js::jsapi::{JS_WrapValue};
|
||||||
use js::jsval::JSVal;
|
use js::jsval::JSVal;
|
||||||
use js::jsval::{UndefinedValue, NullValue, BooleanValue, Int32Value, UInt32Value};
|
use js::jsval::{UndefinedValue, NullValue, BooleanValue, Int32Value, UInt32Value};
|
||||||
use js::jsval::{StringValue, ObjectValue};
|
use js::jsval::{StringValue, ObjectValue, ObjectOrNullValue};
|
||||||
use js::glue::RUST_JS_NumberValue;
|
use js::glue::RUST_JS_NumberValue;
|
||||||
use libc;
|
use libc;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
|
@ -348,3 +348,9 @@ impl<X: Default, T: FromJSValConvertible<X>> FromJSValConvertible<()> for Option
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToJSValConvertible for *mut JSObject {
|
||||||
|
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal {
|
||||||
|
ObjectOrNullValue(*self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
use dom::bindings::codegen::InheritTypes::{DocumentDerived, EventCast, HTMLElementCast};
|
use dom::bindings::codegen::InheritTypes::{DocumentDerived, EventCast, HTMLElementCast};
|
||||||
use dom::bindings::codegen::InheritTypes::{HTMLHeadElementCast, TextCast, ElementCast};
|
use dom::bindings::codegen::InheritTypes::{HTMLHeadElementCast, TextCast, ElementCast};
|
||||||
use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, HTMLHtmlElementCast, NodeCast};
|
use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, HTMLHtmlElementCast, NodeCast};
|
||||||
|
use dom::bindings::codegen::InheritTypes::EventTargetCast;
|
||||||
use dom::bindings::codegen::BindingDeclarations::DocumentBinding;
|
use dom::bindings::codegen::BindingDeclarations::DocumentBinding;
|
||||||
use dom::bindings::js::{JS, JSRef, Temporary, OptionalSettable, TemporaryPushable};
|
use dom::bindings::js::{JS, JSRef, Temporary, OptionalSettable, TemporaryPushable};
|
||||||
use dom::bindings::js::OptionalRootable;
|
use dom::bindings::js::OptionalRootable;
|
||||||
|
@ -21,7 +22,7 @@ use dom::element::{Element, AttributeHandlers, get_attribute_parts};
|
||||||
use dom::element::{HTMLHtmlElementTypeId, HTMLHeadElementTypeId, HTMLTitleElementTypeId};
|
use dom::element::{HTMLHtmlElementTypeId, HTMLHeadElementTypeId, HTMLTitleElementTypeId};
|
||||||
use dom::element::{HTMLBodyElementTypeId, HTMLFrameSetElementTypeId};
|
use dom::element::{HTMLBodyElementTypeId, HTMLFrameSetElementTypeId};
|
||||||
use dom::event::Event;
|
use dom::event::Event;
|
||||||
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
use dom::eventtarget::{EventTarget, NodeTargetTypeId, EventTargetHelpers};
|
||||||
use dom::htmlcollection::{HTMLCollection, CollectionFilter};
|
use dom::htmlcollection::{HTMLCollection, CollectionFilter};
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::htmlheadelement::HTMLHeadElement;
|
use dom::htmlheadelement::HTMLHeadElement;
|
||||||
|
@ -44,7 +45,7 @@ use servo_util::namespace::{Namespace, Null};
|
||||||
use servo_util::str::{DOMString, null_str_as_empty_ref};
|
use servo_util::str::{DOMString, null_str_as_empty_ref};
|
||||||
|
|
||||||
use collections::hashmap::HashMap;
|
use collections::hashmap::HashMap;
|
||||||
use js::jsapi::JSContext;
|
use js::jsapi::{JSObject, JSContext};
|
||||||
use std::ascii::StrAsciiExt;
|
use std::ascii::StrAsciiExt;
|
||||||
use url::{Url, from_str};
|
use url::{Url, from_str};
|
||||||
|
|
||||||
|
@ -325,6 +326,8 @@ pub trait DocumentMethods {
|
||||||
fn Applets(&self) -> Temporary<HTMLCollection>;
|
fn Applets(&self) -> Temporary<HTMLCollection>;
|
||||||
fn Location(&mut self) -> Temporary<Location>;
|
fn Location(&mut self) -> Temporary<Location>;
|
||||||
fn Children(&self) -> Temporary<HTMLCollection>;
|
fn Children(&self) -> Temporary<HTMLCollection>;
|
||||||
|
fn GetOnload(&self, _cx: *mut JSContext) -> *mut JSObject;
|
||||||
|
fn SetOnload(&mut self, _cx: *mut JSContext, listener: *mut JSObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DocumentMethods for JSRef<'a, Document> {
|
impl<'a> DocumentMethods for JSRef<'a, Document> {
|
||||||
|
@ -804,4 +807,14 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
|
||||||
let window = self.window.root();
|
let window = self.window.root();
|
||||||
HTMLCollection::children(&*window, NodeCast::from_ref(self))
|
HTMLCollection::children(&*window, NodeCast::from_ref(self))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn GetOnload(&self, _cx: *mut JSContext) -> *mut JSObject {
|
||||||
|
let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(self);
|
||||||
|
eventtarget.get_event_handler_common("load")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn SetOnload(&mut self, _cx: *mut JSContext, listener: *mut JSObject) {
|
||||||
|
let eventtarget: &mut JSRef<EventTarget> = EventTargetCast::from_mut_ref(self);
|
||||||
|
eventtarget.set_event_handler_common("load", listener)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,16 +2,19 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use dom::bindings::callback::CallbackContainer;
|
||||||
|
use dom::bindings::codegen::BindingDeclarations::EventListenerBinding::EventListener;
|
||||||
|
use dom::bindings::error::{Fallible, InvalidState};
|
||||||
use dom::bindings::js::JSRef;
|
use dom::bindings::js::JSRef;
|
||||||
use dom::bindings::utils::{Reflectable, Reflector};
|
use dom::bindings::utils::{Reflectable, Reflector};
|
||||||
use dom::bindings::error::{Fallible, InvalidState};
|
|
||||||
use dom::bindings::codegen::BindingDeclarations::EventListenerBinding::EventListener;
|
|
||||||
use dom::event::Event;
|
use dom::event::Event;
|
||||||
use dom::eventdispatcher::dispatch_event;
|
use dom::eventdispatcher::dispatch_event;
|
||||||
use dom::node::NodeTypeId;
|
use dom::node::NodeTypeId;
|
||||||
use dom::xmlhttprequest::XMLHttpRequestId;
|
use dom::xmlhttprequest::XMLHttpRequestId;
|
||||||
use dom::virtualmethods::VirtualMethods;
|
use dom::virtualmethods::VirtualMethods;
|
||||||
|
use js::jsapi::JSObject;
|
||||||
use servo_util::str::DOMString;
|
use servo_util::str::DOMString;
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
use collections::hashmap::HashMap;
|
use collections::hashmap::HashMap;
|
||||||
|
|
||||||
|
@ -28,10 +31,24 @@ pub enum EventTargetTypeId {
|
||||||
XMLHttpRequestTargetTypeId(XMLHttpRequestId)
|
XMLHttpRequestTargetTypeId(XMLHttpRequestId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deriving(Eq, Encodable)]
|
||||||
|
pub enum EventListenerType {
|
||||||
|
Additive(EventListener),
|
||||||
|
Inline(EventListener),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventListenerType {
|
||||||
|
fn get_listener(&self) -> EventListener {
|
||||||
|
match *self {
|
||||||
|
Additive(listener) | Inline(listener) => listener
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[deriving(Eq,Encodable)]
|
#[deriving(Eq,Encodable)]
|
||||||
pub struct EventListenerEntry {
|
pub struct EventListenerEntry {
|
||||||
pub phase: ListenerPhase,
|
pub phase: ListenerPhase,
|
||||||
pub listener: EventListener
|
pub listener: EventListenerType
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deriving(Encodable)]
|
#[deriving(Encodable)]
|
||||||
|
@ -52,7 +69,7 @@ impl EventTarget {
|
||||||
|
|
||||||
pub fn get_listeners(&self, type_: &str) -> Option<Vec<EventListener>> {
|
pub fn get_listeners(&self, type_: &str) -> Option<Vec<EventListener>> {
|
||||||
self.handlers.find_equiv(&type_).map(|listeners| {
|
self.handlers.find_equiv(&type_).map(|listeners| {
|
||||||
listeners.iter().map(|entry| entry.listener).collect()
|
listeners.iter().map(|entry| entry.listener.get_listener()).collect()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +77,7 @@ impl EventTarget {
|
||||||
-> Option<Vec<EventListener>> {
|
-> Option<Vec<EventListener>> {
|
||||||
self.handlers.find_equiv(&type_).map(|listeners| {
|
self.handlers.find_equiv(&type_).map(|listeners| {
|
||||||
let filtered = listeners.iter().filter(|entry| entry.phase == desired_phase);
|
let filtered = listeners.iter().filter(|entry| entry.phase == desired_phase);
|
||||||
filtered.map(|entry| entry.listener).collect()
|
filtered.map(|entry| entry.listener.get_listener()).collect()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,6 +86,12 @@ pub trait EventTargetHelpers {
|
||||||
fn dispatch_event_with_target<'a>(&self,
|
fn dispatch_event_with_target<'a>(&self,
|
||||||
target: Option<JSRef<'a, EventTarget>>,
|
target: Option<JSRef<'a, EventTarget>>,
|
||||||
event: &mut JSRef<Event>) -> Fallible<bool>;
|
event: &mut JSRef<Event>) -> Fallible<bool>;
|
||||||
|
fn set_inline_event_listener(&mut self,
|
||||||
|
ty: DOMString,
|
||||||
|
listener: Option<EventListener>);
|
||||||
|
fn get_inline_event_listener(&self, ty: DOMString) -> Option<EventListener>;
|
||||||
|
fn set_event_handler_common(&mut self, ty: &str, listener: *mut JSObject);
|
||||||
|
fn get_event_handler_common(&self, ty: &str) -> *mut JSObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> {
|
impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> {
|
||||||
|
@ -80,6 +103,57 @@ impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> {
|
||||||
}
|
}
|
||||||
Ok(dispatch_event(self, target, event))
|
Ok(dispatch_event(self, target, event))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_inline_event_listener(&mut self,
|
||||||
|
ty: DOMString,
|
||||||
|
listener: Option<EventListener>) {
|
||||||
|
let entries = self.handlers.find_or_insert_with(ty, |_| vec!());
|
||||||
|
let idx = entries.iter().position(|&entry| {
|
||||||
|
match entry.listener {
|
||||||
|
Inline(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
match idx {
|
||||||
|
Some(idx) => {
|
||||||
|
match listener {
|
||||||
|
Some(listener) => entries.get_mut(idx).listener = Inline(listener),
|
||||||
|
None => {
|
||||||
|
entries.remove(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
if listener.is_some() {
|
||||||
|
entries.push(EventListenerEntry {
|
||||||
|
phase: Capturing, //XXXjdm no idea when inline handlers should run
|
||||||
|
listener: Inline(listener.unwrap()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_inline_event_listener(&self, ty: DOMString) -> Option<EventListener> {
|
||||||
|
let entries = self.handlers.find(&ty);
|
||||||
|
entries.and_then(|entries| entries.iter().find(|entry| {
|
||||||
|
match entry.listener {
|
||||||
|
Inline(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}).map(|entry| entry.listener.get_listener()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_event_handler_common(&mut self, ty: &str, listener: *mut JSObject) {
|
||||||
|
let listener = EventListener::new(listener);
|
||||||
|
self.set_inline_event_listener(ty.to_owned(), Some(listener));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_event_handler_common(&self, ty: &str) -> *mut JSObject {
|
||||||
|
let listener = self.get_inline_event_listener(ty.to_owned());
|
||||||
|
listener.map(|listener| listener.parent.callback()).unwrap_or(ptr::mut_null())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait EventTargetMethods {
|
pub trait EventTargetMethods {
|
||||||
|
@ -104,7 +178,7 @@ impl<'a> EventTargetMethods for JSRef<'a, EventTarget> {
|
||||||
let phase = if capture { Capturing } else { Bubbling };
|
let phase = if capture { Capturing } else { Bubbling };
|
||||||
let new_entry = EventListenerEntry {
|
let new_entry = EventListenerEntry {
|
||||||
phase: phase,
|
phase: phase,
|
||||||
listener: listener
|
listener: Additive(listener)
|
||||||
};
|
};
|
||||||
if entry.as_slice().position_elem(&new_entry).is_none() {
|
if entry.as_slice().position_elem(&new_entry).is_none() {
|
||||||
entry.push(new_entry);
|
entry.push(new_entry);
|
||||||
|
@ -122,7 +196,7 @@ impl<'a> EventTargetMethods for JSRef<'a, EventTarget> {
|
||||||
let phase = if capture { Capturing } else { Bubbling };
|
let phase = if capture { Capturing } else { Bubbling };
|
||||||
let old_entry = EventListenerEntry {
|
let old_entry = EventListenerEntry {
|
||||||
phase: phase,
|
phase: phase,
|
||||||
listener: listener
|
listener: Additive(listener)
|
||||||
};
|
};
|
||||||
let position = entry.as_slice().position_elem(&old_entry);
|
let position = entry.as_slice().position_elem(&old_entry);
|
||||||
for &position in position.iter() {
|
for &position in position.iter() {
|
||||||
|
|
|
@ -68,3 +68,4 @@ partial interface Document {
|
||||||
};
|
};
|
||||||
|
|
||||||
Document implements ParentNode;
|
Document implements ParentNode;
|
||||||
|
Document implements GlobalEventHandlers;
|
||||||
|
|
45
src/components/script/dom/webidls/EventHandler.webidl
Normal file
45
src/components/script/dom/webidls/EventHandler.webidl
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* 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
|
||||||
|
* http://www.whatwg.org/specs/web-apps/current-work/#eventhandler
|
||||||
|
*
|
||||||
|
* © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
|
||||||
|
* Opera Software ASA. You are granted a license to use, reproduce
|
||||||
|
* and create derivative works of this document.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//[TreatNonObjectAsNull] //XXXjdm webidl.py assertion
|
||||||
|
callback EventHandlerNonNull = any (Event event);
|
||||||
|
typedef EventHandlerNonNull? EventHandler;
|
||||||
|
|
||||||
|
//[TreatNonObjectAsNull] //XXXjdm webidl.py assertion
|
||||||
|
callback OnErrorEventHandlerNonNull = boolean ((Event or DOMString) event, optional DOMString source, optional unsigned long lineno, optional unsigned long column, optional any error);
|
||||||
|
typedef OnErrorEventHandlerNonNull? OnErrorEventHandler;
|
||||||
|
|
||||||
|
[NoInterfaceObject]
|
||||||
|
interface GlobalEventHandlers {
|
||||||
|
attribute EventHandler onload;
|
||||||
|
};
|
||||||
|
|
||||||
|
[NoInterfaceObject]
|
||||||
|
interface WindowEventHandlers {
|
||||||
|
attribute EventHandler onunload;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The spec has |attribute OnErrorEventHandler onerror;| on
|
||||||
|
// GlobalEventHandlers, and calls the handler differently depending on
|
||||||
|
// whether an ErrorEvent was fired. We don't do that, and until we do we'll
|
||||||
|
// need to distinguish between onerror on Window or on nodes.
|
||||||
|
|
||||||
|
[NoInterfaceObject]
|
||||||
|
interface OnErrorEventHandlerForNodes {
|
||||||
|
attribute EventHandler onerror;
|
||||||
|
};
|
||||||
|
|
||||||
|
[NoInterfaceObject]
|
||||||
|
interface OnErrorEventHandlerForWindow {
|
||||||
|
attribute OnErrorEventHandler onerror;
|
||||||
|
};
|
|
@ -84,6 +84,9 @@ interface WindowTimers {
|
||||||
void clearInterval(optional long handle = 0);*/
|
void clearInterval(optional long handle = 0);*/
|
||||||
};
|
};
|
||||||
Window implements WindowTimers;
|
Window implements WindowTimers;
|
||||||
|
Window implements GlobalEventHandlers;
|
||||||
|
Window implements WindowEventHandlers;
|
||||||
|
Window implements OnErrorEventHandlerForWindow;
|
||||||
|
|
||||||
// Proprietary extensions.
|
// Proprietary extensions.
|
||||||
partial interface Window {
|
partial interface Window {
|
||||||
|
|
|
@ -3,13 +3,14 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use dom::bindings::codegen::BindingDeclarations::WindowBinding;
|
use dom::bindings::codegen::BindingDeclarations::WindowBinding;
|
||||||
|
use dom::bindings::codegen::InheritTypes::EventTargetCast;
|
||||||
use dom::bindings::js::{JS, JSRef, Temporary, OptionalSettable};
|
use dom::bindings::js::{JS, JSRef, Temporary, OptionalSettable};
|
||||||
use dom::bindings::trace::{Traceable, Untraceable};
|
use dom::bindings::trace::{Traceable, Untraceable};
|
||||||
use dom::bindings::utils::{Reflectable, Reflector};
|
use dom::bindings::utils::{Reflectable, Reflector};
|
||||||
use dom::browsercontext::BrowserContext;
|
use dom::browsercontext::BrowserContext;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::element::Element;
|
use dom::element::Element;
|
||||||
use dom::eventtarget::{EventTarget, WindowTypeId};
|
use dom::eventtarget::{EventTarget, WindowTypeId, EventTargetHelpers};
|
||||||
use dom::console::Console;
|
use dom::console::Console;
|
||||||
use dom::location::Location;
|
use dom::location::Location;
|
||||||
use dom::navigator::Navigator;
|
use dom::navigator::Navigator;
|
||||||
|
@ -23,7 +24,7 @@ use servo_util::str::DOMString;
|
||||||
use servo_util::task::{spawn_named};
|
use servo_util::task::{spawn_named};
|
||||||
use servo_util::url::parse_url;
|
use servo_util::url::parse_url;
|
||||||
|
|
||||||
use js::jsapi::JSContext;
|
use js::jsapi::{JSContext, JSObject};
|
||||||
use js::jsapi::{JS_GC, JS_GetRuntime};
|
use js::jsapi::{JS_GC, JS_GetRuntime};
|
||||||
use js::jsval::{NullValue, JSVal};
|
use js::jsval::{NullValue, JSVal};
|
||||||
|
|
||||||
|
@ -140,6 +141,12 @@ pub trait WindowMethods {
|
||||||
fn Window(&self) -> Temporary<Window>;
|
fn Window(&self) -> Temporary<Window>;
|
||||||
fn Self(&self) -> Temporary<Window>;
|
fn Self(&self) -> Temporary<Window>;
|
||||||
fn Performance(&mut self) -> Temporary<Performance>;
|
fn Performance(&mut self) -> Temporary<Performance>;
|
||||||
|
fn GetOnload(&self, _cx: *mut JSContext) -> *mut JSObject;
|
||||||
|
fn SetOnload(&mut self, _cx: *mut JSContext, listener: *mut JSObject);
|
||||||
|
fn GetOnunload(&self, _cx: *mut JSContext) -> *mut JSObject;
|
||||||
|
fn SetOnunload(&mut self, _cx: *mut JSContext, listener: *mut JSObject);
|
||||||
|
fn GetOnerror(&self, _cx: *mut JSContext) -> *mut JSObject;
|
||||||
|
fn SetOnerror(&mut self, _cx: *mut JSContext, listener: *mut JSObject);
|
||||||
fn Debug(&self, message: DOMString);
|
fn Debug(&self, message: DOMString);
|
||||||
fn Gc(&self);
|
fn Gc(&self);
|
||||||
}
|
}
|
||||||
|
@ -268,6 +275,36 @@ impl<'a> WindowMethods for JSRef<'a, Window> {
|
||||||
Temporary::new(self.performance.get_ref().clone())
|
Temporary::new(self.performance.get_ref().clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn GetOnload(&self, _cx: *mut JSContext) -> *mut JSObject {
|
||||||
|
let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(self);
|
||||||
|
eventtarget.get_event_handler_common("load")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn SetOnload(&mut self, _cx: *mut JSContext, listener: *mut JSObject) {
|
||||||
|
let eventtarget: &mut JSRef<EventTarget> = EventTargetCast::from_mut_ref(self);
|
||||||
|
eventtarget.set_event_handler_common("load", listener)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn GetOnunload(&self, _cx: *mut JSContext) -> *mut JSObject {
|
||||||
|
let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(self);
|
||||||
|
eventtarget.get_event_handler_common("unload")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn SetOnunload(&mut self, _cx: *mut JSContext, listener: *mut JSObject) {
|
||||||
|
let eventtarget: &mut JSRef<EventTarget> = EventTargetCast::from_mut_ref(self);
|
||||||
|
eventtarget.set_event_handler_common("unload", listener)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn GetOnerror(&self, _cx: *mut JSContext) -> *mut JSObject {
|
||||||
|
let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(self);
|
||||||
|
eventtarget.get_event_handler_common("error")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn SetOnerror(&mut self, _cx: *mut JSContext, listener: *mut JSObject) {
|
||||||
|
let eventtarget: &mut JSRef<EventTarget> = EventTargetCast::from_mut_ref(self);
|
||||||
|
eventtarget.set_event_handler_common("error", listener)
|
||||||
|
}
|
||||||
|
|
||||||
fn Debug(&self, message: DOMString) {
|
fn Debug(&self, message: DOMString) {
|
||||||
debug!("{:s}", message);
|
debug!("{:s}", message);
|
||||||
}
|
}
|
||||||
|
@ -392,7 +429,6 @@ impl<'a> PrivateWindowHelpers for JSRef<'a, Window> {
|
||||||
handle
|
handle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
pub fn new(cx: *mut JSContext,
|
pub fn new(cx: *mut JSContext,
|
||||||
page: Rc<Page>,
|
page: Rc<Page>,
|
||||||
|
|
|
@ -4,13 +4,25 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script>
|
<script>
|
||||||
addEventListener("load", function(ev) {
|
var onloads = 0;
|
||||||
|
function check(ev) {
|
||||||
is_a(ev, Event);
|
is_a(ev, Event);
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
is(ev.defaultPrevented, false);
|
is(ev.defaultPrevented, false);
|
||||||
is(ev.target, document);
|
is(ev.target, document);
|
||||||
is(ev.currentTarget, window);
|
is(ev.currentTarget, window);
|
||||||
finish();
|
if (onloads == 2) {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onload = function(ev) {
|
||||||
|
onloads++;
|
||||||
|
check(ev);
|
||||||
|
}
|
||||||
|
addEventListener("load", function(ev) {
|
||||||
|
onloads++;
|
||||||
|
check(ev);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue