auto merge of #1171 : jdm/servo/events2, r=jdm,metajack

Now with a split between commits that just pull in unmodified Gecko code and those that modify it.
This commit is contained in:
bors-servo 2013-11-05 10:49:21 -08:00
commit c2a99933c9
27 changed files with 2593 additions and 171 deletions

View file

@ -0,0 +1,105 @@
/* 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 dom::bindings::utils::{WrapNativeParent, Reflectable};
use js::jsapi::{JSContext, JSObject, JS_WrapObject, JSVal, JS_ObjectIsCallable};
use js::jsapi::JS_GetProperty;
use js::{JSVAL_IS_OBJECT, JSVAL_TO_OBJECT};
use std::libc;
use std::ptr;
pub enum ExceptionHandling {
// Report any exception and don't throw it to the caller code.
eReportExceptions,
// Throw an exception to the caller code if the thrown exception is a
// binding object for a DOMError from the caller's scope, otherwise report
// it.
eRethrowContentExceptions,
// Throw any exception to the caller code.
eRethrowExceptions
}
#[deriving(Clone,Eq)]
pub struct CallbackInterface {
callback: *JSObject
}
pub trait CallbackContainer {
fn callback(&self) -> *JSObject;
}
impl CallbackContainer for CallbackInterface {
fn callback(&self) -> *JSObject {
self.callback
}
}
impl CallbackInterface {
pub fn new(callback: *JSObject) -> CallbackInterface {
CallbackInterface {
callback: callback
}
}
#[fixed_stack_segment]
pub fn GetCallableProperty(&self, cx: *JSContext, name: *libc::c_char, callable: &mut JSVal) -> bool {
unsafe {
if JS_GetProperty(cx, self.callback, name, &*callable) == 0 {
return false;
}
if !JSVAL_IS_OBJECT(*callable) ||
JS_ObjectIsCallable(cx, JSVAL_TO_OBJECT(*callable)) == 0 {
//ThrowErrorMessage(cx, MSG_NOT_CALLABLE, description.get());
return false;
}
return true;
}
}
}
pub fn GetJSObjectFromCallback<T: CallbackContainer>(callback: &T) -> *JSObject {
callback.callback()
}
#[fixed_stack_segment]
pub fn WrapCallThisObject<T: 'static + CallbackContainer + Reflectable>(cx: *JSContext,
scope: *JSObject,
p: @mut T) -> *JSObject {
let mut obj = GetJSObjectFromCallback(p);
if obj.is_null() {
obj = WrapNativeParent(cx, scope, Some(p as @mut Reflectable));
if obj.is_null() {
return ptr::null();
}
}
unsafe {
if JS_WrapObject(cx, &obj) == 0 {
return ptr::null();
}
}
return obj;
}
pub struct CallSetup {
cx: *JSContext,
handling: ExceptionHandling
}
impl CallSetup {
pub fn new(cx: *JSContext, handling: ExceptionHandling) -> CallSetup {
CallSetup {
cx: cx,
handling: handling
}
}
pub fn GetContext(&self) -> *JSContext {
self.cx
}
}

View file

@ -182,28 +182,21 @@ DOMInterfaces = {
},
'Event': {
'nativeType': 'AbstractEvent',
'concreteType': 'Event',
'pointerType': '',
},
'EventListener': [
{
'EventListener': {
'nativeType': 'EventListenerBinding::EventListener',
},
{
'workers': True,
}],
'EventTarget': [
{
# 'nativeType': 'nsDOMEventTargetHelper',
# 'hasInstanceInterface': 'nsIDOMEventTarget',
# 'concrete': False,
# 'prefable': True,
'EventTarget': {
'nativeType': 'AbstractEventTarget',
'concreteType': 'EventTarget',
'pointerType': '',
'needsAbstract': ['dispatchEvent']
},
#{
# 'workers': True,
# 'headerFile': 'mozilla/dom/workers/bindings/EventTarget.h',
# 'concrete': False
#}
],
'FileList': [
{
@ -291,6 +284,9 @@ DOMInterfaces = {
}],
'MouseEvent': {
'nativeType': 'AbstractEvent',
'concreteType': 'MouseEvent',
'pointerType': '',
},
'Navigator': {
@ -388,6 +384,9 @@ DOMInterfaces = {
}],
'UIEvent': {
'nativeType': 'AbstractEvent',
'concreteType': 'UIEvent',
'pointerType': '',
},
'ValidityState': {

File diff suppressed because it is too large Load diff

View file

@ -42,6 +42,8 @@ class Configuration:
self.enums = [e for e in parseData if e.isEnum()]
self.dictionaries = [d for d in parseData if d.isDictionary()]
self.callbacks = [c for c in parseData if
c.isCallback() and not c.isInterface()]
# Keep the descriptor list sorted for determinism.
self.descriptors.sort(lambda x,y: cmp(x.name, y.name))
@ -66,14 +68,34 @@ class Configuration:
getter = lambda x: x.interface.isCallback()
elif key == 'isExternal':
getter = lambda x: x.interface.isExternal()
elif key == 'isJSImplemented':
getter = lambda x: x.interface.isJSImplemented()
else:
getter = lambda x: getattr(x, key)
curr = filter(lambda x: getter(x) == val, curr)
return curr
def getEnums(self, webIDLFile):
return filter(lambda e: e.filename() == webIDLFile, self.enums)
def getDictionaries(self, webIDLFile):
return filter(lambda d: d.filename() == webIDLFile, self.dictionaries)
@staticmethod
def _filterForFileAndWorkers(items, filters):
"""Gets the items that match the given filters."""
for key, val in filters.iteritems():
if key == 'webIDLFile':
items = filter(lambda x: x.filename() == val, items)
elif key == 'workers':
if val:
items = filter(lambda x: x.getUserData("workers", False), items)
else:
items = filter(lambda x: x.getUserData("mainThread", False), items)
else:
assert(0) # Unknown key
return items
def getDictionaries(self, **filters):
return self._filterForFileAndWorkers(self.dictionaries, filters)
def getCallbacks(self, **filters):
return self._filterForFileAndWorkers(self.callbacks, filters)
def getDescriptor(self, interfaceName, workers):
"""
Gets the appropriate descriptor for the given interface name

View file

@ -58,8 +58,8 @@ interface Document : Node {
[Throws]
Node adoptNode(Node node);*/
// [Creator, Throws]
// Event createEvent(DOMString interface_);
[Creator, Throws]
Event createEvent(DOMString interface_);
/*[Creator, Throws]
Range createRange();*/

View file

@ -0,0 +1,16 @@
/* -*- 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.w3.org/TR/2012/WD-dom-20120105/
*
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/
callback interface EventListener {
void handleEvent(Event event);
};

View file

@ -11,4 +11,12 @@
*/
interface EventTarget {
void addEventListener(DOMString type,
EventListener? listener,
optional boolean capture = false);
void removeEventListener(DOMString type,
EventListener? listener,
optional boolean capture = false);
[Throws]
boolean dispatchEvent(Event event);
};

View file

@ -14,7 +14,7 @@
interface URI;
interface UserDataHandler;*/
interface Node /*: EventTarget*/ {
interface Node : EventTarget {
const unsigned short ELEMENT_NODE = 1;
const unsigned short ATTRIBUTE_NODE = 2; // historical
const unsigned short TEXT_NODE = 3;

View file

@ -8,7 +8,7 @@
*/
[NamedPropertiesObject]
/*sealed*/ interface Window /*: EventTarget*/ {
/*sealed*/ interface Window : EventTarget {
// the current browsing context
/*[Unforgeable] readonly attribute WindowProxy window;
[Replaceable] readonly attribute WindowProxy self;*/

View file

@ -146,6 +146,23 @@ class IDLObject(object):
def isCallback(self):
return False
def isSingleOperationInterface(self):
assert self.isCallback() or self.isJSImplemented()
return (
# JS-implemented things should never need the
# this-handling weirdness of single-operation interfaces.
not self.isJSImplemented() and
# Not inheriting from another interface
not self.parent and
# No consequential interfaces
len(self.getConsequentialInterfaces()) == 0 and
# No attributes of any kinds
not any(m.isAttr() for m in self.members) and
# There is at least one regular operation, and all regular
# operations have the same identifier
len(set(m.identifier.name for m in self.members if
m.isMethod() and not m.isStatic())) == 1)
def isType(self):
return False
@ -167,6 +184,38 @@ class IDLObject(object):
def handleExtendedAttribute(self, attr):
assert False # Override me!
def _getDependentObjects(self):
assert False # Override me!
def getDeps(self, visited=None):
""" Return a set of files that this object depends on. If any of
these files are changed the parser needs to be rerun to regenerate
a new IDLObject.
The visited argument is a set of all the objects already visited.
We must test to see if we are in it, and if so, do nothing. This
prevents infinite recursion."""
# NB: We can't use visited=set() above because the default value is
# evaluated when the def statement is evaluated, not when the function
# is executed, so there would be one set for all invocations.
if visited == None:
visited = set()
if self in visited:
return set()
visited.add(self)
deps = set()
if self.filename() != "<builtin>":
deps.add(self.filename())
for d in self._getDependentObjects():
deps = deps.union(d.getDeps(visited))
return deps
class IDLScope(IDLObject):
def __init__(self, location, parentScope, identifier):
IDLObject.__init__(self, location)
@ -428,6 +477,15 @@ class IDLExternalInterface(IDLObjectWithIdentifier):
def resolve(self, parentScope):
pass
def getJSImplementation(self):
return None
def isJSImplemented(self):
return False
def _getDependentObjects(self):
return set()
class IDLInterface(IDLObjectWithScope):
def __init__(self, location, parentScope, name, parent, members,
isPartial):
@ -777,6 +835,24 @@ class IDLInterface(IDLObjectWithScope):
# Put the new members at the beginning
self.members = members + self.members
def getJSImplementation(self):
classId = self.getExtendedAttribute("JSImplementation")
if not classId:
return classId
assert isinstance(classId, list)
assert len(classId) == 1
return classId[0]
def isJSImplemented(self):
return bool(self.getJSImplementation())
def _getDependentObjects(self):
deps = set(self.members)
deps.union(self.implementedInterfaces)
if self.parent:
deps.add(self.parent)
return deps
class IDLDictionary(IDLObjectWithScope):
def __init__(self, location, parentScope, name, parent, members):
assert isinstance(parentScope, IDLScope)
@ -847,6 +923,11 @@ class IDLDictionary(IDLObjectWithScope):
def addExtendedAttributes(self, attrs):
assert len(attrs) == 0
def _getDependentObjects(self):
deps = set(self.members)
if (self.parent):
deps.add(self.parent)
return deps
class IDLEnum(IDLObjectWithIdentifier):
def __init__(self, location, parentScope, name, values):
@ -875,6 +956,9 @@ class IDLEnum(IDLObjectWithIdentifier):
def addExtendedAttributes(self, attrs):
assert len(attrs) == 0
def _getDependentObjects(self):
return set()
class IDLType(IDLObject):
Tags = enum(
# The integer types
@ -893,6 +977,7 @@ class IDLType(IDLObject):
# Other types
'any',
'domstring',
'bytestring',
'object',
'date',
'void',
@ -930,6 +1015,12 @@ class IDLType(IDLObject):
def isString(self):
return False
def isByteString(self):
return False
def isDOMString(self):
return False
def isVoid(self):
return self.name == "Void"
@ -1075,6 +1166,12 @@ class IDLNullableType(IDLType):
def isString(self):
return self.inner.isString()
def isByteString(self):
return self.inner.isByteString()
def isDOMString(self):
return self.inner.isDOMString()
def isFloat(self):
return self.inner.isFloat()
@ -1163,6 +1260,9 @@ class IDLNullableType(IDLType):
return False
return self.inner.isDistinguishableFrom(other)
def _getDependentObjects(self):
return self.inner._getDependentObjects()
class IDLSequenceType(IDLType):
def __init__(self, location, parameterType):
assert not parameterType.isVoid()
@ -1231,6 +1331,9 @@ class IDLSequenceType(IDLType):
other.isDictionary() or other.isDate() or
other.isNonCallbackInterface())
def _getDependentObjects(self):
return self.inner._getDependentObjects()
class IDLUnionType(IDLType):
def __init__(self, location, memberTypes):
IDLType.__init__(self, location, "")
@ -1317,6 +1420,9 @@ class IDLUnionType(IDLType):
return False
return True
def _getDependentObjects(self):
return set(self.memberTypes)
class IDLArrayType(IDLType):
def __init__(self, location, parameterType):
assert not parameterType.isVoid()
@ -1393,6 +1499,9 @@ class IDLArrayType(IDLType):
other.isDictionary() or other.isDate() or
other.isNonCallbackInterface())
def _getDependentObjects(self):
return self.inner._getDependentObjects()
class IDLTypedefType(IDLType, IDLObjectWithIdentifier):
def __init__(self, location, innerType, name):
IDLType.__init__(self, location, innerType.name)
@ -1478,6 +1587,9 @@ class IDLTypedefType(IDLType, IDLObjectWithIdentifier):
def isDistinguishableFrom(self, other):
return self.inner.isDistinguishableFrom(other)
def _getDependentObjects(self):
return self.inner._getDependentObjects()
class IDLWrapperType(IDLType):
def __init__(self, location, inner):
IDLType.__init__(self, location, inner.identifier.name)
@ -1583,6 +1695,23 @@ class IDLWrapperType(IDLType):
assert other.isObject()
return False
def _getDependentObjects(self):
# NB: The codegen for an interface type depends on
# a) That the identifier is in fact an interface (as opposed to
# a dictionary or something else).
# b) The native type of the interface.
# If we depend on the interface object we will also depend on
# anything the interface depends on which is undesirable. We
# considered implementing a dependency just on the interface type
# file, but then every modification to an interface would cause this
# to be regenerated which is still undesirable. We decided not to
# depend on anything, reasoning that:
# 1) Changing the concrete type of the interface requires modifying
# Bindings.conf, which is still a global dependency.
# 2) Changing an interface to a dictionary (or vice versa) with the
# same identifier should be incredibly rare.
return set()
class IDLBuiltinType(IDLType):
Types = enum(
@ -1602,6 +1731,7 @@ class IDLBuiltinType(IDLType):
# Other types
'any',
'domstring',
'bytestring',
'object',
'date',
'void',
@ -1633,6 +1763,7 @@ class IDLBuiltinType(IDLType):
Types.double: IDLType.Tags.double,
Types.any: IDLType.Tags.any,
Types.domstring: IDLType.Tags.domstring,
Types.bytestring: IDLType.Tags.bytestring,
Types.object: IDLType.Tags.object,
Types.date: IDLType.Tags.date,
Types.void: IDLType.Tags.void,
@ -1658,6 +1789,13 @@ class IDLBuiltinType(IDLType):
return self._typeTag <= IDLBuiltinType.Types.double
def isString(self):
return self._typeTag == IDLBuiltinType.Types.domstring or \
self._typeTag == IDLBuiltinType.Types.bytestring
def isByteString(self):
return self._typeTag == IDLBuiltinType.Types.bytestring
def isDOMString(self):
return self._typeTag == IDLBuiltinType.Types.domstring
def isInteger(self):
@ -1733,6 +1871,9 @@ class IDLBuiltinType(IDLType):
(self.isTypedArray() and not other.isArrayBufferView() and not
(other.isTypedArray() and other.name == self.name)))))
def _getDependentObjects(self):
return set()
BuiltinTypes = {
IDLBuiltinType.Types.byte:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "Byte",
@ -1877,6 +2018,9 @@ class IDLValue(IDLObject):
raise WebIDLError("Cannot coerce type %s to type %s." %
(self.type, type), [location])
def _getDependentObjects(self):
return set()
class IDLNullValue(IDLObject):
def __init__(self, location):
IDLObject.__init__(self, location)
@ -1895,6 +2039,9 @@ class IDLNullValue(IDLObject):
nullValue.type = type
return nullValue
def _getDependentObjects(self):
return set()
class IDLInterfaceMember(IDLObjectWithIdentifier):
@ -1966,6 +2113,9 @@ class IDLConst(IDLInterfaceMember):
def validate(self):
pass
def _getDependentObjects(self):
return set([self.type, self.value])
class IDLAttribute(IDLInterfaceMember):
def __init__(self, location, identifier, type, readonly, inherit,
static=False):
@ -2052,6 +2202,9 @@ class IDLAttribute(IDLInterfaceMember):
def hasLenientThis(self):
return self.lenientThis
def _getDependentObjects(self):
return set([self.type])
class IDLArgument(IDLObjectWithIdentifier):
def __init__(self, location, identifier, type, optional=False, defaultValue=None, variadic=False, dictionaryMember=False):
IDLObjectWithIdentifier.__init__(self, location, None, identifier)
@ -2124,6 +2277,12 @@ class IDLArgument(IDLObjectWithIdentifier):
self.location)
assert self.defaultValue
def _getDependentObjects(self):
deps = set([self.type])
if self.defaultValue:
deps.add(self.defaultValue)
return deps
class IDLCallbackType(IDLType, IDLObjectWithScope):
def __init__(self, location, parentScope, identifier, returnType, arguments):
assert isinstance(returnType, IDLType)
@ -2179,6 +2338,9 @@ class IDLCallbackType(IDLType, IDLObjectWithScope):
return (other.isPrimitive() or other.isString() or other.isEnum() or
other.isNonCallbackInterface() or other.isDate())
def _getDependentObjects(self):
return set([self._returnType] + self._arguments)
class IDLMethodOverload:
"""
A class that represents a single overload of a WebIDL method. This is not
@ -2194,6 +2356,11 @@ class IDLMethodOverload:
self.arguments = list(arguments)
self.location = location
def _getDependentObjects(self):
deps = set(self.arguments)
deps.add(self.returnType)
return deps
class IDLMethod(IDLInterfaceMember, IDLScope):
Special = enum(
@ -2494,6 +2661,12 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
[attr.location, self.location])
IDLInterfaceMember.handleExtendedAttribute(self, attr)
def _getDependentObjects(self):
deps = set()
for overload in self._overloads:
deps.union(overload._getDependentObjects())
return deps
class IDLImplementsStatement(IDLObject):
def __init__(self, location, implementor, implementee):
IDLObject.__init__(self, location)

View file

@ -50,7 +50,7 @@ impl Traceable for Node<ScriptView> {
}
}
}
debug!("tracing {:p}?:", self.reflector_.get_jsobject());
debug!("tracing {:p}?:", self.reflector().get_jsobject());
trace_node(tracer, self.parent_node, "parent");
trace_node(tracer, self.first_child, "first child");
trace_node(tracer, self.last_child, "last child");

View file

@ -4,8 +4,8 @@
use dom::bindings::codegen::PrototypeList;
use dom::bindings::codegen::PrototypeList::MAX_PROTO_CHAIN_LENGTH;
use dom::window;
use dom::node::{AbstractNode, ScriptView};
use dom::window;
use std::libc::c_uint;
use std::cast;
@ -22,6 +22,7 @@ use js::glue::{js_IsObjectProxyClass, js_IsFunctionProxyClass, IsProxyHandlerFam
use js::jsapi::{JS_AlreadyHasOwnProperty, JS_NewObject, JS_NewFunction, JS_GetGlobalObject};
use js::jsapi::{JS_DefineProperties, JS_WrapValue, JS_ForwardGetPropertyTo};
use js::jsapi::{JS_GetClass, JS_LinkConstructorAndPrototype, JS_GetStringCharsAndLength};
use js::jsapi::{JS_ObjectIsRegExp, JS_ObjectIsDate};
use js::jsapi::{JS_GetFunctionPrototype, JS_InternString, JS_GetFunctionObject};
use js::jsapi::{JS_HasPropertyById, JS_GetPrototype, JS_GetGlobalForObject};
use js::jsapi::{JS_NewUCStringCopyN, JS_DefineFunctions, JS_DefineProperty};
@ -30,7 +31,7 @@ use js::jsapi::{JSContext, JSObject, JSBool, jsid, JSClass, JSNative, JSTracer};
use js::jsapi::{JSFunctionSpec, JSPropertySpec, JSVal, JSPropertyDescriptor};
use js::jsapi::{JSPropertyOp, JSStrictPropertyOp, JS_NewGlobalObject, JS_InitStandardClasses};
use js::jsfriendapi::bindgen::JS_NewObjectWithUniqueType;
use js::{JSPROP_ENUMERATE, JSVAL_NULL};
use js::{JSPROP_ENUMERATE, JSVAL_NULL, JSCLASS_IS_GLOBAL, JSCLASS_IS_DOMJSCLASS};
use js::{JSPROP_PERMANENT, JSID_VOID, JSPROP_NATIVE_ACCESSORS, JSPROP_GETTER};
use js::{JSPROP_SETTER, JSVAL_VOID, JSVAL_TRUE, JSVAL_FALSE};
use js::{JS_THIS_OBJECT, JSFUN_CONSTRUCTOR, JS_CALLEE, JSPROP_READONLY};
@ -767,6 +768,8 @@ pub enum Error {
NotFound,
HierarchyRequest,
InvalidCharacter,
NotSupported,
InvalidState
}
pub type Fallible<T> = Result<T, Error>;
@ -819,6 +822,13 @@ pub fn HasPropertyOnPrototype(cx: *JSContext, proxy: *JSObject, id: jsid) -> boo
return !GetPropertyOnPrototype(cx, proxy, id, &mut found, ptr::null()) || found;
}
#[fixed_stack_segment]
pub fn IsConvertibleToCallbackInterface(cx: *JSContext, obj: *JSObject) -> bool {
unsafe {
JS_ObjectIsDate(cx, obj) == 0 && JS_ObjectIsRegExp(cx, obj) == 0
}
}
#[fixed_stack_segment]
pub fn CreateDOMGlobal(cx: *JSContext, class: *JSClass) -> *JSObject {
unsafe {
@ -832,6 +842,30 @@ pub fn CreateDOMGlobal(cx: *JSContext, class: *JSClass) -> *JSObject {
}
}
#[fixed_stack_segment]
fn cx_for_dom_reflector(obj: *JSObject) -> *JSContext {
unsafe {
let global = GetGlobalForObjectCrossCompartment(obj);
let clasp = JS_GetClass(global);
assert!(((*clasp).flags & (JSCLASS_IS_DOMJSCLASS | JSCLASS_IS_GLOBAL)) != 0);
//XXXjdm either don't hardcode or sanity assert prototype stuff
let win = unwrap_object::<*Box<window::Window>>(global, PrototypeList::id::Window, 1);
match win {
Ok(win) => {
match (*win).data.page.js_info {
Some(ref info) => info.js_context.ptr,
None => fail!("no JS context for DOM global")
}
}
Err(_) => fail!("found DOM global that doesn't unwrap to Window")
}
}
}
pub fn cx_for_dom_object<T: Reflectable>(obj: &mut T) -> *JSContext {
cx_for_dom_reflector(obj.reflector().get_jsobject())
}
/// Check if an element name is valid. See http://www.w3.org/TR/xml/#NT-Name
/// for details.
pub fn is_valid_element_name(name: &str) -> bool {

View file

@ -5,15 +5,20 @@
use dom::comment::Comment;
use dom::bindings::codegen::DocumentBinding;
use dom::bindings::utils::{DOMString, ErrorResult, Fallible};
use dom::bindings::utils::{Reflectable, Reflector, DerivedWrapper};
use dom::bindings::utils::{is_valid_element_name, InvalidCharacter, Traceable, null_str_as_empty, null_str_as_word_null};
use dom::bindings::utils::{Reflectable, Reflector, DerivedWrapper, NotSupported};
use dom::bindings::utils::{is_valid_element_name, InvalidCharacter, Traceable};
use dom::bindings::utils::{null_str_as_empty_ref, null_str_as_empty, null_str_as_word_null};
use dom::documentfragment::DocumentFragment;
use dom::element::{Element};
use dom::element::{HTMLHeadElementTypeId, HTMLTitleElementTypeId};
use dom::event::{AbstractEvent, Event, HTMLEventTypeId, UIEventTypeId};
use dom::htmlcollection::HTMLCollection;
use dom::htmldocument::HTMLDocument;
use dom::htmlelement::HTMLElement;
use dom::mouseevent::MouseEvent;
use dom::node::{AbstractNode, ScriptView, Node, ElementNodeTypeId, DocumentNodeTypeId};
use dom::text::Text;
use dom::uievent::UIEvent;
use dom::window::Window;
use dom::htmltitleelement::HTMLTitleElement;
use html::hubbub_html_parser::build_element_from_tag;
@ -255,6 +260,15 @@ impl Document {
Comment::new(null_str_as_word_null(data), abstract_self)
}
pub fn CreateEvent(&self, interface: &DOMString) -> Fallible<AbstractEvent> {
match null_str_as_empty_ref(interface) {
"UIEvents" => Ok(UIEvent::new(self.window, UIEventTypeId)),
"MouseEvents" => Ok(MouseEvent::new(self.window)),
"HTMLEvents" => Ok(Event::new(self.window, HTMLEventTypeId)),
_ => Err(NotSupported)
}
}
pub fn Title(&self, _: AbstractDocument) -> DOMString {
let mut title = ~"";
match self.doctype {

View file

@ -2,17 +2,23 @@
* 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 dom::eventtarget::EventTarget;
use dom::eventtarget::AbstractEventTarget;
use dom::window::Window;
use dom::bindings::codegen::EventBinding;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::bindings::utils::{DOMString, ErrorResult, Fallible};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object, DerivedWrapper};
use dom::bindings::utils::{DOMString, ErrorResult, Fallible, null_str_as_word_null};
use dom::mouseevent::MouseEvent;
use dom::uievent::UIEvent;
use geom::point::Point2D;
use js::jsapi::{JSObject, JSContext};
use js::jsapi::{JSObject, JSContext, JSVal};
use js::glue::RUST_OBJECT_TO_JSVAL;
use script_task::page_from_context;
use std::cast;
use std::unstable::raw::Box;
pub enum Event_ {
ResizeEvent(uint, uint),
ReflowEvent,
@ -21,45 +27,194 @@ pub enum Event_ {
MouseUpEvent(uint, Point2D<f32>),
}
pub struct Event {
reflector_: Reflector,
type_: DOMString,
default_prevented: bool,
cancelable: bool,
bubbles: bool,
trusted: bool,
pub struct AbstractEvent {
event: *mut Box<Event>
}
impl Event {
pub fn new_inherited(type_: &DOMString) -> Event {
Event {
reflector_: Reflector::new(),
type_: (*type_).clone(),
default_prevented: false,
cancelable: true,
bubbles: true,
trusted: false
pub enum EventPhase {
Phase_None = 0,
Phase_Capturing,
Phase_At_Target,
Phase_Bubbling
}
impl AbstractEvent {
pub fn from_box(box: *mut Box<Event>) -> AbstractEvent {
AbstractEvent {
event: box
}
}
pub fn new(window: @mut Window, type_: &DOMString) -> @mut Event {
reflect_dom_object(@mut Event::new_inherited(type_), window, EventBinding::Wrap)
//
// Downcasting borrows
//
fn transmute<'a, T>(&'a self) -> &'a T {
unsafe {
let box: *Box<T> = self.event as *Box<T>;
&(*box).data
}
}
fn transmute_mut<'a, T>(&'a self) -> &'a mut T {
unsafe {
let box: *mut Box<T> = self.event as *mut Box<T>;
&mut (*box).data
}
}
pub fn type_id(&self) -> EventTypeId {
self.event().type_id
}
pub fn event<'a>(&'a self) -> &'a Event {
self.transmute()
}
pub fn mut_event<'a>(&'a self) -> &'a mut Event {
self.transmute_mut()
}
pub fn is_uievent(&self) -> bool {
self.type_id() == UIEventTypeId
}
pub fn uievent<'a>(&'a self) -> &'a UIEvent {
assert!(self.is_uievent());
self.transmute()
}
pub fn mut_uievent<'a>(&'a self) -> &'a mut UIEvent {
assert!(self.is_uievent());
self.transmute_mut()
}
pub fn is_mouseevent(&self) -> bool {
self.type_id() == MouseEventTypeId
}
pub fn mouseevent<'a>(&'a self) -> &'a MouseEvent {
assert!(self.is_mouseevent());
self.transmute()
}
pub fn mut_mouseevent<'a>(&'a self) -> &'a mut MouseEvent {
assert!(self.is_mouseevent());
self.transmute_mut()
}
pub fn propagation_stopped(&self) -> bool {
self.event().stop_propagation
}
pub fn bubbles(&self) -> bool {
self.event().bubbles
}
}
impl DerivedWrapper for AbstractEvent {
#[fixed_stack_segment]
fn wrap(&mut self, _cx: *JSContext, _scope: *JSObject, vp: *mut JSVal) -> i32 {
let wrapper = self.reflector().get_jsobject();
if wrapper.is_not_null() {
unsafe { *vp = RUST_OBJECT_TO_JSVAL(wrapper) };
return 1;
}
unreachable!()
}
}
impl Reflectable for AbstractEvent {
fn reflector<'a>(&'a self) -> &'a Reflector {
self.event().reflector()
}
fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
self.mut_event().mut_reflector()
}
fn wrap_object_shared(@mut self, _cx: *JSContext, _scope: *JSObject) -> *JSObject {
fail!(~"doesn't make any sense");
}
fn GetParentObject(&self, cx: *JSContext) -> Option<@mut Reflectable> {
self.event().GetParentObject(cx)
}
}
#[deriving(Eq)]
pub enum EventTypeId {
HTMLEventTypeId,
UIEventTypeId,
MouseEventTypeId,
KeyEventTypeId
}
pub struct Event {
type_id: EventTypeId,
reflector_: Reflector,
current_target: Option<AbstractEventTarget>,
target: Option<AbstractEventTarget>,
type_: ~str,
phase: EventPhase,
default_prevented: bool,
stop_propagation: bool,
stop_immediate: bool,
cancelable: bool,
bubbles: bool,
trusted: bool,
dispatching: bool,
initialized: bool
}
impl Event {
pub fn new_inherited(type_id: EventTypeId) -> Event {
Event {
type_id: type_id,
reflector_: Reflector::new(),
current_target: None,
target: None,
phase: Phase_None,
type_: ~"",
default_prevented: false,
cancelable: true,
bubbles: true,
trusted: false,
dispatching: false,
stop_propagation: false,
stop_immediate: false,
initialized: false,
}
}
//FIXME: E should be bounded by some trait that is only implemented for Event types
pub fn as_abstract<E>(event: @mut E) -> AbstractEvent {
// This surrenders memory management of the event!
AbstractEvent {
event: unsafe { cast::transmute(event) },
}
}
pub fn new(window: @mut Window, type_id: EventTypeId) -> AbstractEvent {
let ev = reflect_dom_object(@mut Event::new_inherited(type_id), window,
EventBinding::Wrap);
Event::as_abstract(ev)
}
pub fn EventPhase(&self) -> u16 {
0
self.phase as u16
}
pub fn Type(&self) -> DOMString {
self.type_.clone()
Some(self.type_.clone())
}
pub fn GetTarget(&self) -> Option<@mut EventTarget> {
None
pub fn GetTarget(&self) -> Option<AbstractEventTarget> {
self.target
}
pub fn GetCurrentTarget(&self) -> Option<@mut EventTarget> {
None
pub fn GetCurrentTarget(&self) -> Option<AbstractEventTarget> {
self.current_target
}
pub fn DefaultPrevented(&self) -> bool {
@ -67,13 +222,18 @@ impl Event {
}
pub fn PreventDefault(&mut self) {
self.default_prevented = true
if self.cancelable {
self.default_prevented = true
}
}
pub fn StopPropagation(&mut self) {
self.stop_propagation = true;
}
pub fn StopImmediatePropagation(&mut self) {
self.stop_immediate = true;
self.stop_propagation = true;
}
pub fn Bubbles(&self) -> bool {
@ -92,9 +252,10 @@ impl Event {
type_: &DOMString,
bubbles: bool,
cancelable: bool) -> ErrorResult {
self.type_ = (*type_).clone();
self.type_ = null_str_as_word_null(type_);
self.cancelable = cancelable;
self.bubbles = bubbles;
self.initialized = true;
Ok(())
}
@ -103,9 +264,11 @@ impl Event {
}
pub fn Constructor(global: @mut Window,
type_: &DOMString,
_init: &EventBinding::EventInit) -> Fallible<@mut Event> {
Ok(Event::new(global, type_))
type_: &DOMString,
init: &EventBinding::EventInit) -> Fallible<AbstractEvent> {
let ev = Event::new(global, HTMLEventTypeId);
ev.mut_event().InitEvent(type_, init.bubbles, init.cancelable);
Ok(ev)
}
}

View file

@ -0,0 +1,111 @@
/* 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 dom::bindings::callback::eReportExceptions;
use dom::eventtarget::{AbstractEventTarget, Capturing, Bubbling};
use dom::event::{AbstractEvent, Phase_At_Target, Phase_None, Phase_Bubbling, Phase_Capturing};
use dom::node::AbstractNode;
use servo_util::tree::{TreeNodeRef};
// See http://dom.spec.whatwg.org/#concept-event-dispatch for the full dispatch algorithm
pub fn dispatch_event(target: AbstractEventTarget, event: AbstractEvent) -> bool {
assert!(!event.event().dispatching);
{
let event = event.mut_event();
event.target = Some(target);
event.dispatching = true;
}
let type_ = event.event().type_.clone();
let mut chain = ~[];
//TODO: no chain if not participating in a tree
if target.is_node() {
for ancestor in AbstractNode::from_eventtarget(target).ancestors() {
chain.push(AbstractEventTarget::from_node(ancestor));
}
}
event.mut_event().phase = Phase_Capturing;
//FIXME: The "callback this value" should be currentTarget
/* capturing */
for &cur_target in chain.rev_iter() {
//XXX bad clone
let stopped = match cur_target.eventtarget().get_listeners_for(type_.clone(), Capturing) {
Some(listeners) => {
event.mut_event().current_target = Some(cur_target);
for listener in listeners.iter() {
listener.HandleEvent__(event, eReportExceptions);
if event.event().stop_immediate {
break;
}
}
event.propagation_stopped()
}
None => false
};
if stopped {
break;
}
}
/* at target */
if !event.propagation_stopped() {
{
let event = event.mut_event();
event.phase = Phase_At_Target;
event.current_target = Some(target);
}
let opt_listeners = target.eventtarget().get_listeners(type_.clone());
for listeners in opt_listeners.iter() {
for listener in listeners.iter() {
listener.HandleEvent__(event, eReportExceptions);
if event.event().stop_immediate {
break;
}
}
}
}
/* bubbling */
if event.bubbles() && !event.propagation_stopped() {
event.mut_event().phase = Phase_Bubbling;
for &cur_target in chain.iter() {
//XXX bad clone
let stopped = match cur_target.eventtarget().get_listeners_for(type_.clone(), Bubbling) {
Some(listeners) => {
event.mut_event().current_target = Some(cur_target);
for listener in listeners.iter() {
listener.HandleEvent__(event, eReportExceptions);
if event.event().stop_immediate {
break;
}
}
event.propagation_stopped()
}
None => false
};
if stopped {
break;
}
}
}
let event = event.mut_event();
event.dispatching = false;
event.phase = Phase_None;
event.current_target = None;
!event.DefaultPrevented()
}

View file

@ -3,24 +3,196 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::codegen::EventTargetBinding;
use dom::bindings::utils::{Reflectable, Reflector};
use dom::bindings::utils::{Reflectable, Reflector, DOMString, Fallible, DerivedWrapper};
use dom::bindings::utils::{null_str_as_word_null, InvalidState};
use dom::bindings::codegen::EventListenerBinding::EventListener;
use dom::event::AbstractEvent;
use dom::eventdispatcher::dispatch_event;
use dom::node::{AbstractNode, ScriptView};
use script_task::page_from_context;
use js::jsapi::{JSObject, JSContext};
use js::jsapi::{JSObject, JSContext, JSVal};
use js::glue::RUST_OBJECT_TO_JSVAL;
pub struct EventTarget {
reflector_: Reflector
use std::cast;
use std::hashmap::HashMap;
use std::unstable::raw::Box;
#[deriving(Eq)]
pub enum ListenerPhase {
Capturing,
Bubbling,
}
impl EventTarget {
pub fn new() -> ~EventTarget {
~EventTarget {
reflector_: Reflector::new()
#[deriving(Eq)]
pub enum EventTargetTypeId {
WindowTypeId,
NodeTypeId
}
#[deriving(Eq)]
struct EventListenerEntry {
phase: ListenerPhase,
listener: EventListener
}
pub struct EventTarget {
type_id: EventTargetTypeId,
reflector_: Reflector,
handlers: HashMap<~str, ~[EventListenerEntry]>,
}
pub struct AbstractEventTarget {
eventtarget: *mut Box<EventTarget>
}
impl AbstractEventTarget {
pub fn from_box<T>(box: *mut Box<T>) -> AbstractEventTarget {
AbstractEventTarget {
eventtarget: box as *mut Box<EventTarget>
}
}
pub fn init_wrapper(@mut self, cx: *JSContext, scope: *JSObject) {
self.wrap_object_shared(cx, scope);
pub fn from_node(node: AbstractNode<ScriptView>) -> AbstractEventTarget {
unsafe {
cast::transmute(node)
}
}
pub fn type_id(&self) -> EventTargetTypeId {
self.eventtarget().type_id
}
pub fn is_window(&self) -> bool {
self.type_id() == WindowTypeId
}
pub fn is_node(&self) -> bool {
self.type_id() == NodeTypeId
}
//
// Downcasting borrows
//
fn transmute<'a, T>(&'a self) -> &'a T {
unsafe {
let box: *Box<T> = self.eventtarget as *Box<T>;
&(*box).data
}
}
fn transmute_mut<'a, T>(&'a mut self) -> &'a mut T {
unsafe {
let box: *mut Box<T> = self.eventtarget as *mut Box<T>;
&mut (*box).data
}
}
pub fn eventtarget<'a>(&'a self) -> &'a EventTarget {
self.transmute()
}
pub fn mut_eventtarget<'a>(&'a mut self) -> &'a mut EventTarget {
self.transmute_mut()
}
}
impl DerivedWrapper for AbstractEventTarget {
#[fixed_stack_segment]
fn wrap(&mut self, _cx: *JSContext, _scope: *JSObject, vp: *mut JSVal) -> i32 {
let wrapper = self.reflector().get_jsobject();
if wrapper.is_not_null() {
unsafe { *vp = RUST_OBJECT_TO_JSVAL(wrapper) };
return 1;
}
unreachable!()
}
}
impl Reflectable for AbstractEventTarget {
fn reflector<'a>(&'a self) -> &'a Reflector {
self.eventtarget().reflector()
}
fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
self.mut_eventtarget().mut_reflector()
}
fn wrap_object_shared(@mut self, _cx: *JSContext, _scope: *JSObject) -> *JSObject {
unreachable!()
}
fn GetParentObject(&self, cx: *JSContext) -> Option<@mut Reflectable> {
self.eventtarget().GetParentObject(cx)
}
}
impl EventTarget {
pub fn new_inherited(type_id: EventTargetTypeId) -> EventTarget {
EventTarget {
type_id: type_id,
reflector_: Reflector::new(),
handlers: HashMap::new(),
}
}
pub fn get_listeners(&self, type_: ~str) -> Option<~[EventListener]> {
do self.handlers.find_equiv(&type_).map |listeners| {
listeners.iter().map(|entry| entry.listener).collect()
}
}
pub fn get_listeners_for(&self, type_: ~str, desired_phase: ListenerPhase)
-> Option<~[EventListener]> {
do self.handlers.find_equiv(&type_).map |listeners| {
let filtered = listeners.iter().filter(|entry| entry.phase == desired_phase);
filtered.map(|entry| entry.listener).collect()
}
}
pub fn AddEventListener(&mut self,
ty: &DOMString,
listener: Option<EventListener>,
capture: bool) {
for &listener in listener.iter() {
let entry = self.handlers.find_or_insert_with(null_str_as_word_null(ty), |_| ~[]);
let phase = if capture { Capturing } else { Bubbling };
let new_entry = EventListenerEntry {
phase: phase,
listener: listener
};
if entry.position_elem(&new_entry).is_none() {
entry.push(new_entry);
}
}
}
pub fn RemoveEventListener(&mut self,
ty: &DOMString,
listener: Option<EventListener>,
capture: bool) {
for &listener in listener.iter() {
let mut entry = self.handlers.find_mut(&null_str_as_word_null(ty));
for entry in entry.mut_iter() {
let phase = if capture { Capturing } else { Bubbling };
let old_entry = EventListenerEntry {
phase: phase,
listener: listener
};
let position = entry.position_elem(&old_entry);
for &position in position.iter() {
entry.remove(position);
}
}
}
}
pub fn DispatchEvent(&self, abstract_self: AbstractEventTarget, event: AbstractEvent) -> Fallible<bool> {
if event.event().dispatching || !event.event().initialized {
return Err(InvalidState);
}
Ok(dispatch_event(abstract_self, event))
}
}

View file

@ -5,7 +5,8 @@
use dom::bindings::codegen::MouseEventBinding;
use dom::bindings::utils::{ErrorResult, Fallible, DOMString};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::eventtarget::EventTarget;
use dom::event::{AbstractEvent, Event, MouseEventTypeId};
use dom::eventtarget::AbstractEventTarget;
use dom::uievent::UIEvent;
use dom::window::Window;
use dom::windowproxy::WindowProxy;
@ -23,38 +24,42 @@ pub struct MouseEvent {
alt_key: bool,
meta_key: bool,
button: u16,
related_target: Option<@mut EventTarget>
related_target: Option<AbstractEventTarget>
}
impl MouseEvent {
pub fn new(window: @mut Window, type_: &DOMString, can_bubble: bool, cancelable: bool,
view: Option<@mut WindowProxy>, detail: i32, screen_x: i32,
screen_y: i32, client_x: i32, client_y: i32, ctrl_key: bool,
shift_key: bool, alt_key: bool, meta_key: bool, button: u16,
_buttons: u16, related_target: Option<@mut EventTarget>) -> @mut MouseEvent {
let ev = @mut MouseEvent {
parent: UIEvent::new_inherited(type_, can_bubble, cancelable, view, detail),
screen_x: screen_x,
screen_y: screen_y,
client_x: client_x,
client_y: client_y,
ctrl_key: ctrl_key,
shift_key: shift_key,
alt_key: alt_key,
meta_key: meta_key,
button: button,
related_target: related_target
};
reflect_dom_object(ev, window, MouseEventBinding::Wrap)
pub fn new_inherited() -> MouseEvent {
MouseEvent {
parent: UIEvent::new_inherited(MouseEventTypeId),
screen_x: 0,
screen_y: 0,
client_x: 0,
client_y: 0,
ctrl_key: false,
shift_key: false,
alt_key: false,
meta_key: false,
button: 0,
related_target: None
}
}
pub fn new(window: @mut Window) -> AbstractEvent {
Event::as_abstract(reflect_dom_object(@mut MouseEvent::new_inherited(),
window,
MouseEventBinding::Wrap))
}
pub fn Constructor(owner: @mut Window,
type_: &DOMString,
init: &MouseEventBinding::MouseEventInit) -> Fallible<@mut MouseEvent> {
Ok(MouseEvent::new(owner, type_, init.bubbles, init.cancelable, init.view, init.detail,
init.screenX, init.screenY, init.clientX, init.clientY,
init.ctrlKey, init.shiftKey, init.altKey, init.metaKey,
init.button, init.buttons, init.relatedTarget))
init: &MouseEventBinding::MouseEventInit) -> Fallible<AbstractEvent> {
let ev = MouseEvent::new(owner);
ev.mut_mouseevent().InitMouseEvent(type_, init.bubbles, init.cancelable, init.view,
init.detail, init.screenX, init.screenY,
init.clientX, init.clientY, init.ctrlKey,
init.altKey, init.shiftKey, init.metaKey,
init.button, init.relatedTarget);
Ok(ev)
}
pub fn ScreenX(&self) -> i32 {
@ -98,7 +103,7 @@ impl MouseEvent {
0
}
pub fn GetRelatedTarget(&self) -> Option<@mut EventTarget> {
pub fn GetRelatedTarget(&self) -> Option<AbstractEventTarget> {
self.related_target
}
@ -122,7 +127,7 @@ impl MouseEvent {
shiftKeyArg: bool,
metaKeyArg: bool,
buttonArg: u16,
relatedTargetArg: Option<@mut EventTarget>) -> ErrorResult {
relatedTargetArg: Option<AbstractEventTarget>) -> ErrorResult {
self.parent.InitUIEvent(typeArg, canBubbleArg, cancelableArg, viewArg, detailArg);
self.screen_x = screenXArg;
self.screen_y = screenYArg;

View file

@ -12,6 +12,7 @@ use dom::document::{AbstractDocument, DocumentTypeId};
use dom::documenttype::DocumentType;
use dom::element::{Element, ElementTypeId, HTMLImageElementTypeId, HTMLIframeElementTypeId};
use dom::element::{HTMLStyleElementTypeId};
use dom::eventtarget::{AbstractEventTarget, EventTarget, NodeTypeId};
use dom::nodelist::{NodeList};
use dom::htmlimageelement::HTMLImageElement;
use dom::htmliframeelement::HTMLIFrameElement;
@ -63,7 +64,7 @@ pub struct AbstractNodeChildrenIterator<View> {
/// `LayoutData`.
pub struct Node<View> {
/// The JavaScript reflector for this node.
reflector_: Reflector,
eventtarget: EventTarget,
/// The type of node that this is.
type_id: NodeTypeId,
@ -210,6 +211,13 @@ impl<'self, View> AbstractNode<View> {
}
}
pub fn from_eventtarget(target: AbstractEventTarget) -> AbstractNode<View> {
assert!(target.is_node());
unsafe {
cast::transmute(target)
}
}
// Convenience accessors
/// Returns the type ID of this node. Fails if this node is borrowed mutably.
@ -521,7 +529,7 @@ impl Node<ScriptView> {
fn new_(type_id: NodeTypeId, doc: Option<AbstractDocument>) -> Node<ScriptView> {
Node {
reflector_: Reflector::new(),
eventtarget: EventTarget::new_inherited(NodeTypeId),
type_id: type_id,
abstract: None,
@ -1042,11 +1050,11 @@ impl Node<ScriptView> {
impl Reflectable for Node<ScriptView> {
fn reflector<'a>(&'a self) -> &'a Reflector {
&self.reflector_
self.eventtarget.reflector()
}
fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
&mut self.reflector_
self.eventtarget.mut_reflector()
}
fn wrap_object_shared(@mut self, _cx: *JSContext, _scope: *JSObject) -> *JSObject {

View file

@ -6,7 +6,7 @@ use dom::bindings::codegen::UIEventBinding;
use dom::bindings::utils::{DOMString, Fallible};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::node::{AbstractNode, ScriptView};
use dom::event::Event;
use dom::event::{AbstractEvent, Event, EventTypeId, UIEventTypeId};
use dom::window::Window;
use dom::windowproxy::WindowProxy;
@ -14,36 +14,33 @@ use js::jsapi::{JSObject, JSContext};
pub struct UIEvent {
parent: Event,
can_bubble: bool,
cancelable: bool,
view: Option<@mut WindowProxy>,
detail: i32
}
impl UIEvent {
pub fn new_inherited(type_: &DOMString, can_bubble: bool, cancelable: bool,
view: Option<@mut WindowProxy>, detail: i32) -> UIEvent {
pub fn new_inherited(type_id: EventTypeId) -> UIEvent {
UIEvent {
parent: Event::new_inherited(type_),
can_bubble: can_bubble,
cancelable: cancelable,
view: view,
detail: detail
parent: Event::new_inherited(type_id),
view: None,
detail: 0
}
}
pub fn new(window: @mut Window, type_: &DOMString, can_bubble: bool, cancelable: bool,
view: Option<@mut WindowProxy>, detail: i32) -> @mut UIEvent {
reflect_dom_object(@mut UIEvent::new_inherited(type_, can_bubble, cancelable, view, detail),
window,
UIEventBinding::Wrap)
pub fn new(window: @mut Window, type_id: EventTypeId) -> AbstractEvent {
let ev = reflect_dom_object(@mut UIEvent::new_inherited(type_id),
window,
UIEventBinding::Wrap);
Event::as_abstract(ev)
}
pub fn Constructor(owner: @mut Window,
type_: &DOMString,
init: &UIEventBinding::UIEventInit) -> Fallible<@mut UIEvent> {
Ok(UIEvent::new(owner, type_, init.parent.bubbles, init.parent.cancelable,
init.view, init.detail))
init: &UIEventBinding::UIEventInit) -> Fallible<AbstractEvent> {
let ev = UIEvent::new(owner, UIEventTypeId);
ev.mut_uievent().InitUIEvent(type_, init.parent.bubbles, init.parent.cancelable,
init.view, init.detail);
Ok(ev)
}
pub fn GetView(&self) -> Option<@mut WindowProxy> {
@ -61,8 +58,6 @@ impl UIEvent {
view: Option<@mut WindowProxy>,
detail: i32) {
self.parent.InitEvent(type_, can_bubble, cancelable);
self.can_bubble = can_bubble;
self.cancelable = cancelable;
self.view = view;
self.detail = detail;
}

View file

@ -6,6 +6,7 @@ use dom::bindings::codegen::WindowBinding;
use dom::bindings::utils::{Reflectable, Reflector};
use dom::bindings::utils::{DOMString, null_str_as_empty, Traceable};
use dom::document::AbstractDocument;
use dom::eventtarget::{EventTarget, WindowTypeId};
use dom::node::{AbstractNode, ScriptView};
use dom::navigator::Navigator;
@ -37,10 +38,10 @@ pub enum TimerControlMsg {
}
pub struct Window {
eventtarget: EventTarget,
page: @mut Page,
script_chan: ScriptChan,
compositor: @ScriptListener,
reflector_: Reflector,
timer_chan: SharedChan<TimerControlMsg>,
navigator: Option<@mut Navigator>,
image_cache_task: ImageCacheTask,
@ -140,11 +141,11 @@ impl Window {
impl Reflectable for Window {
fn reflector<'a>(&'a self) -> &'a Reflector {
&self.reflector_
self.eventtarget.reflector()
}
fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
&mut self.reflector_
self.eventtarget.mut_reflector()
}
fn wrap_object_shared(@mut self, cx: *JSContext, scope: *JSObject) -> *JSObject {
@ -204,10 +205,10 @@ impl Window {
image_cache_task: ImageCacheTask)
-> @mut Window {
let win = @mut Window {
eventtarget: EventTarget::new_inherited(WindowTypeId),
page: page,
script_chan: script_chan.clone(),
compositor: compositor,
reflector_: Reflector::new(),
timer_chan: {
let (timer_port, timer_chan) = comm::stream::<TimerControlMsg>();
let id = page.id.clone();