aboutsummaryrefslogtreecommitdiffstats
path: root/src/servo
diff options
context:
space:
mode:
authorJosh Matthews <josh@joshmatthews.net>2013-05-08 13:35:07 -0400
committerJosh Matthews <josh@joshmatthews.net>2013-05-08 14:17:50 -0400
commitaf2db0cf682e65abe5e6e6a380f9ea51a13cc16f (patch)
tree8a995a6555b975f0ae839d9e174978fb7a0dfbc4 /src/servo
parent597f7bdc6d547fbaf413e7352fe1b89ebe519b1c (diff)
downloadservo-af2db0cf682e65abe5e6e6a380f9ea51a13cc16f.tar.gz
servo-af2db0cf682e65abe5e6e6a380f9ea51a13cc16f.zip
Add codegen support for dictionaries, and implement Event bindings as a side-effect. Add a stub EventTarget to allow the build to complete.
Diffstat (limited to 'src/servo')
-rw-r--r--src/servo/dom/bindings/codegen/Bindings.conf27
-rw-r--r--src/servo/dom/bindings/codegen/CodegenRust.py389
-rw-r--r--src/servo/dom/bindings/codegen/Configuration.py6
-rw-r--r--src/servo/dom/bindings/codegen/Event.webidl80
-rw-r--r--src/servo/dom/bindings/codegen/EventTarget.webidl14
-rw-r--r--src/servo/dom/bindings/codegen/RegisterBindings.cpp4
-rw-r--r--src/servo/dom/bindings/conversions.rs31
-rw-r--r--src/servo/dom/bindings/event.rs55
-rw-r--r--src/servo/dom/bindings/eventtarget.rs55
-rw-r--r--src/servo/dom/bindings/utils.rs29
-rw-r--r--src/servo/dom/event.rs89
-rw-r--r--src/servo/dom/eventtarget.rs17
-rw-r--r--src/servo/dom/node.rs6
-rwxr-xr-xsrc/servo/servo.rc5
14 files changed, 704 insertions, 103 deletions
diff --git a/src/servo/dom/bindings/codegen/Bindings.conf b/src/servo/dom/bindings/codegen/Bindings.conf
index 8c2b3cb29a5..442bd0b432c 100644
--- a/src/servo/dom/bindings/codegen/Bindings.conf
+++ b/src/servo/dom/bindings/codegen/Bindings.conf
@@ -116,13 +116,11 @@ DOMInterfaces = {
'ClientRect': [
{
'nativeType': 'ClientRect',
- 'pointerType': '@mut '
}],
'ClientRectList': [
{
'nativeType': 'ClientRectList',
- 'pointerType': '@mut '
}],
'CSS2Properties': {
@@ -137,7 +135,6 @@ DOMInterfaces = {
'DOMParser': {
'nativeType': 'DOMParser',
- 'pointerType': '@mut '
},
'DOMSettableTokenList': [
@@ -160,10 +157,9 @@ DOMInterfaces = {
'Event': [
{
+ 'nativeType': 'Event_'
},
-{
- 'workers': True,
-}],
+],
'EventListener': [
{
@@ -174,16 +170,17 @@ DOMInterfaces = {
'EventTarget': [
{
- 'nativeType': 'nsDOMEventTargetHelper',
- 'hasInstanceInterface': 'nsIDOMEventTarget',
- 'concrete': False,
- 'prefable': True,
+# 'nativeType': 'nsDOMEventTargetHelper',
+# 'hasInstanceInterface': 'nsIDOMEventTarget',
+# 'concrete': False,
+# 'prefable': True,
},
-{
- 'workers': True,
- 'headerFile': 'mozilla/dom/workers/bindings/EventTarget.h',
- 'concrete': False
-}],
+#{
+# 'workers': True,
+# 'headerFile': 'mozilla/dom/workers/bindings/EventTarget.h',
+# 'concrete': False
+#}
+],
'FileList': [
{
diff --git a/src/servo/dom/bindings/codegen/CodegenRust.py b/src/servo/dom/bindings/codegen/CodegenRust.py
index ee57ef3e325..675557ba556 100644
--- a/src/servo/dom/bindings/codegen/CodegenRust.py
+++ b/src/servo/dom/bindings/codegen/CodegenRust.py
@@ -506,7 +506,7 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
return template
return CGWrapper(
CGIndenter(CGGeneric(template)),
- pre="if (${haveValue}) {\n",
+ pre="if ${haveValue} != 0 {\n",
post=("\n"
"} else {\n"
"%s;\n"
@@ -1181,9 +1181,8 @@ for (uint32_t i = 0; i < length; ++i) {
# should be able to assume not isOptional here.
assert not isOptional
- typeName = "" #XXXjdm unfinished
- #typeName = CGDictionary.makeDictionaryName(type.inner,
- # descriptorProvider.workers)
+ typeName = CGDictionary.makeDictionaryName(type.inner,
+ descriptorProvider.workers)
actualTypeName = typeName
selfRef = "${declName}"
@@ -1192,20 +1191,20 @@ for (uint32_t i = 0; i < length; ++i) {
# If we're a member of something else, the const
# will come from the Optional or our container.
if not isMember:
- declType = CGWrapper(declType, pre="const ")
- selfRef = "const_cast<%s&>(%s)" % (typeName, selfRef)
+ selfRef = "%s" % selfRef
# We do manual default value handling here, because we
# actually do want a jsval, and we only handle null anyway
if defaultValue is not None:
assert(isinstance(defaultValue, IDLNullValue))
- val = "(${haveValue}) ? ${val} : JSVAL_NULL"
+ val = "if ${haveValue} { ${val} } else { JSVAL_NULL }"
else:
val = "${val}"
- template = ("if (!%s.Init(cx, %s)) {\n"
- " return false;\n"
- "}" % (selfRef, val))
+ template = ("%s = %s::new();\n"
+ "if %s.Init(cx, %s) == 0 {\n"
+ " return 0;\n"
+ "}" % (selfRef, actualTypeName, selfRef, val))
return (template, declType, None, False)
@@ -1238,10 +1237,10 @@ for (uint32_t i = 0; i < length; ++i) {
dataLoc = "${declName}"
#XXXjdm conversionBehavior should be used
template = (
- "match JSValConvertible::from_jsval::<%s, %s>(${val}) {\n"
+ "match JSValConvertible::from_jsval::<%s>(${val}) {\n"
" None => return 0,\n"
" Some(v) => %s = v\n"
- "}" % (typeName, typeName, dataLoc))
+ "}" % (typeName, dataLoc))
declType = CGGeneric(typeName)
if (defaultValue is not None and
# We already handled IDLNullValue, so just deal with the other ones
@@ -1253,7 +1252,7 @@ for (uint32_t i = 0; i < length; ++i) {
assert(tag == IDLType.Tags.bool)
defaultStr = toStringBool(defaultValue.value)
template = CGWrapper(CGIndenter(CGGeneric(template)),
- pre="if (${haveValue}) {\n",
+ pre="if ${haveValue} != 0 {\n",
post=("\n"
"} else {\n"
" %s = %s;\n"
@@ -1305,7 +1304,7 @@ def instantiateJSToNativeConversionTemplate(templateTuple, replacements,
mutableDeclType = CGWrapper(declType, pre="Optional< ", post=" >")
declType = CGWrapper(mutableDeclType, pre="const ")
result.append(
- CGList([CGGeneric("let "),
+ CGList([CGGeneric("let mut "),
CGGeneric(originalDeclName),
CGGeneric(": "),
declType,
@@ -1349,19 +1348,19 @@ def instantiateJSToNativeConversionTemplate(templateTuple, replacements,
def convertConstIDLValueToJSVal(value):
if isinstance(value, IDLNullValue):
- return "JSVAL_NULL"
+ return "NullVal"
tag = value.type.tag()
if tag in [IDLType.Tags.int8, IDLType.Tags.uint8, IDLType.Tags.int16,
IDLType.Tags.uint16, IDLType.Tags.int32]:
- return "INT_TO_JSVAL(%s)" % (value.value)
+ return "IntVal(%s)" % (value.value)
if tag == IDLType.Tags.uint32:
- return "UINT_TO_JSVAL(%s)" % (value.value)
+ return "UintVal(%s)" % (value.value)
if tag in [IDLType.Tags.int64, IDLType.Tags.uint64]:
- return "DOUBLE_TO_JSVAL(%s)" % (value.value)
+ return "DoubleVal(%s)" % (value.value)
if tag == IDLType.Tags.bool:
- return "JSVAL_TRUE" if value.value else "JSVAL_FALSE"
+ return "BoolVal(true)" if value.value else "BoolVal(false)"
if tag in [IDLType.Tags.float, IDLType.Tags.double]:
- return "DOUBLE_TO_JSVAL(%s)" % (value.value)
+ return "DoubleVal(%s)" % (value.value)
raise TypeError("Const value of unhandled type: " + value.type)
class CGArgumentConverter(CGThing):
@@ -1455,7 +1454,7 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
"""
if failureCode is None:
if not haveSuccessCode:
- return "return " + wrapCall + ";"
+ return wrapCall + ";\n" + "return if *vp != 0 { 1 } else { 0 };"
failureCode = "return 0;"
str = ("if !%s {\n" +
CGIndenter(CGGeneric(failureCode)).define() + "\n" +
@@ -1554,9 +1553,10 @@ for (uint32_t i = 0; i < length; ++i) {
if type.isString():
if type.nullable():
- return (wrapAndSetPtr("xpc::StringToJsval(cx, %s, ${jsvalPtr})" % result), False)
+ return (wrapAndSetPtr("*${jsvalPtr} = domstring_to_jsval(cx, &%s)" % result), False)
else:
- return (wrapAndSetPtr("xpc::NonVoidStringToJsval(cx, %s, ${jsvalPtr})" % result), False)
+ #XXXjdm Can we be smarter when we know it's not nullable?
+ return (wrapAndSetPtr("*${jsvalPtr} = domstring_to_jsval(cx, &%s)" % result), False)
if type.isEnum():
if type.nullable():
@@ -1624,7 +1624,7 @@ if (!%(resultStr)s) {
return (setValue("RUST_UINT_TO_JSVAL(%s)" % result), True)
elif tag == IDLType.Tags.bool:
- return (setValue("RUST_BOOLEAN_TO_JSVAL(%s)" % result), True)
+ return (setValue("RUST_BOOLEAN_TO_JSVAL(%s as JSBool)" % result), True)
else:
raise TypeError("Need to learn to wrap primitive: %s" % type)
@@ -1688,7 +1688,7 @@ def getRetvalDeclarationForType(returnType, descriptorProvider,
result = CGWrapper(result, pre="Nullable<", post=">")
return result, False
if returnType.isString():
- return CGGeneric("nsString"), True
+ return CGGeneric("DOMString"), False
if returnType.isEnum():
if returnType.nullable():
raise TypeError("We don't support nullable enum return values")
@@ -2027,8 +2027,8 @@ class ConstDefiner(PropertyDefiner):
return decls + self.generatePrefableArray(
array, name,
- ' { &%s_name as *u8 as *libc::c_char, %s }',
- ' { 0, JSVAL_VOID }',
+ ' ConstantSpec { name: &%s_name as *u8 as *libc::c_char, value: %s }',
+ ' ConstantSpec { name: 0 as *libc::c_char, value: VoidVal }',
'ConstantSpec',
PropertyDefiner.getControllingPref, specData, doIdArrays)
@@ -2302,7 +2302,7 @@ static InterfaceObjectClass: JSClass = {
0 as *u8, /* trace */
JSCLASS_NO_INTERNAL_MEMBERS
};
-""" % (str_to_const_array("Function", ctorname, hasinstance, ctorname))
+""" % (str_to_const_array("Function"), ctorname, hasinstance, ctorname)
class CGList(CGThing):
"""
@@ -2480,21 +2480,19 @@ class CGWrapWithCacheMethod(CGAbstractMethod):
//JSAutoCompartment ac(aCx, parent);
let global = JS_GetGlobalForObject(aCx, parent);
-%s
let proto = GetProtoObject(aCx, global, global);
if proto.is_null() {
return ptr::null();
}
let cache = ptr::to_mut_unsafe_ptr(aObject.get_wrappercache());
-
%s
+
//NS_ADDREF(aObject);
(*cache).set_wrapper(obj);
- return obj;""" % (CheckPref(self.descriptor, "global", "*aTriedToWrap", "NULL", "aCache"),
- CreateBindingJSObject(self.descriptor, "parent"))
+ return obj;""" % (CreateBindingJSObject(self.descriptor, "parent"))
class CGWrapMethod(CGAbstractMethod):
def __init__(self, descriptor):
@@ -2768,35 +2766,6 @@ class CGGetConstructorObjectMethod(CGGetPerInterfaceObject):
/* Get the interface object for this class. This will create the object as
needed. */""" + CGGetPerInterfaceObject.definition_body(self)
-def CheckPref(descriptor, globalName, varName, retval, wrapperCache = None):
- """
- Check whether bindings should be enabled for this descriptor. If not, set
- varName to false and return retval.
- """
- if not descriptor.prefable:
- return ""
-
- if wrapperCache:
- wrapperCache = " %s->ClearIsDOMBinding();\n" % (wrapperCache)
- else:
- wrapperCache = ""
-
- failureCode = (" %s = false;\n" +
- " return %s;") % (varName, retval)
- return """
- {
- XPCWrappedNativeScope* scope =
- XPCWrappedNativeScope::FindInJSObjectScope(aCx, %s);
- if (!scope) {
-%s
- }
-
- if (!scope->ExperimentalBindingsEnabled()) {
-%s%s
- }
- }
-""" % (globalName, failureCode, wrapperCache, failureCode)
-
class CGDefineDOMInterfaceMethod(CGAbstractMethod):
"""
A method for resolve hooks to try to lazily define the interface object for
@@ -2827,7 +2796,8 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
getter = "GetConstructorObject"
body = " let content = task_from_context(aCx);\n"
- if self.descriptor.proxy:
+ #XXXjdm This self.descriptor.concrete check shouldn't be necessary
+ if not self.descriptor.concrete or self.descriptor.proxy:
body += """ let traps = ProxyTraps {
getPropertyDescriptor: getPropertyDescriptor,
getOwnPropertyDescriptor: getOwnPropertyDescriptor,
@@ -2869,7 +2839,6 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
body = "" #XXXjdm xray stuff isn't necessary yet
return (body + " let global: *JSObject = JS_GetGlobalForObject(aCx, aReceiver);\n" +
- CheckPref(self.descriptor, "global", "*aEnabled", "false") +
"""
*aEnabled = true;
return %s(aCx, global, aReceiver).is_not_null();""" % (getter))
@@ -2903,6 +2872,9 @@ class CGCallGenerator(CGThing):
# This is a workaround for a bug in Apple's clang.
if a.type.isObject() and not a.type.nullable() and not a.optional:
name = "(JSObject&)" + name
+ #XXXjdm Perhaps we should pass all nontrivial types by borrowed pointer
+ if a.type.isDictionary():
+ name = "&" + name
args.append(CGGeneric(name))
# Return values that go in outparams go here
@@ -3149,7 +3121,7 @@ class CGSpecializedMethod(CGAbstractExternMethod):
self.method = method
name = method.identifier.name
args = [Argument('*JSContext', 'cx'), Argument('JSHandleObject', 'obj'),
- Argument('*%s' % descriptor.nativeType, 'self'),
+ Argument('*mut %s' % descriptor.nativeType, 'self'),
Argument('libc::c_uint', 'argc'), Argument('*mut JSVal', 'vp')]
CGAbstractExternMethod.__init__(self, descriptor, name, 'JSBool', args)
@@ -3165,7 +3137,7 @@ class CGGenericGetter(CGAbstractBindingMethod):
A class for generating the C++ code for an IDL attribute getter.
"""
def __init__(self, descriptor, lenientThis=False):
- args = [Argument('*JSContext', 'cx'), Argument('uint', '_argc'),
+ args = [Argument('*JSContext', 'cx'), Argument('uint', 'argc'),
Argument('*JSVal', 'vp')]
if lenientThis:
name = "genericLenientGetter"
@@ -3192,8 +3164,8 @@ class CGSpecializedGetter(CGAbstractExternMethod):
def __init__(self, descriptor, attr):
self.attr = attr
name = 'get_' + attr.identifier.name
- args = [ Argument('*JSContext', '_cx'),
- Argument('JSHandleObject', '_obj'),
+ args = [ Argument('*JSContext', 'cx'),
+ Argument('JSHandleObject', 'obj'),
Argument('*%s' % descriptor.nativeType, 'self'),
Argument('*mut JSVal', 'vp') ]
CGAbstractExternMethod.__init__(self, descriptor, name, "JSBool", args)
@@ -3210,8 +3182,9 @@ class CGSpecializedGetter(CGAbstractExternMethod):
getter=True))
if resultOutParam or self.attr.type.nullable() or not infallible:
nativeName = "Get" + nativeName
- return CGIndenter(CGGetterCall(self.attr.type, nativeName,
- self.descriptor, self.attr)).define()
+ return CGWrapper(CGIndenter(CGGetterCall(self.attr.type, nativeName,
+ self.descriptor, self.attr)),
+ pre=" let obj = (*obj.unnamed);\n").define()
def infallibleForMember(member, type, descriptorProvider):
"""
@@ -3356,7 +3329,7 @@ class CGXrayHelper(CGAbstractExternMethod):
consts = self.properties.consts
if consts.hasNonChromeOnly() or consts.hasChromeOnly():
constArgs = "Some(vec::zip_slice(%(consts)s, *const_ids))" % varNames
- setup += "let const_ids = (*content).dom_static.const_ids.get(&(prototypes::id::ClientRect as uint));\n"
+ setup += "let const_ids = (*content).dom_static.constant_ids.get(&(prototypes::id::ClientRect as uint));\n"
else:
constArgs = "None"
constArgs = CGGeneric(constArgs)
@@ -3372,7 +3345,7 @@ class CGXrayHelper(CGAbstractExternMethod):
class CGResolveProperty(CGXrayHelper):
def __init__(self, descriptor, properties):
args = [Argument('*JSContext', 'cx'), Argument('*JSObject', 'wrapper'),
- Argument('jsid', 'id'), Argument('bool', '_set'),
+ Argument('jsid', 'id'), Argument('bool', 'set'),
Argument('*mut JSPropertyDescriptor', 'desc')]
CGXrayHelper.__init__(self, descriptor, "ResolveProperty", args,
properties)
@@ -3469,7 +3442,7 @@ class CGProxyUnwrap(CGAbstractMethod):
class CGDOMJSProxyHandler_get(CGAbstractExternMethod):
def __init__(self, descriptor):
args = [Argument('*JSContext', 'cx'), Argument('*JSObject', 'proxy'),
- Argument('*JSObject', '_receiver'), Argument('jsid', 'id'),
+ Argument('*JSObject', 'receiver'), Argument('jsid', 'id'),
Argument('*mut JSVal', 'vp')]
CGAbstractExternMethod.__init__(self, descriptor, "get", "JSBool", args)
self.descriptor = descriptor
@@ -3530,7 +3503,7 @@ if !GetPropertyOnPrototype(cx, proxy, id, &mut found, cast::transmute(vp)) {
return 0;
}
-if (found) {
+if found {
return 1;
}
%s
@@ -3542,7 +3515,7 @@ return 1;""" % (getIndexedOrExpando, getNamed)
class CGDOMJSProxyHandler_obj_toString(CGAbstractExternMethod):
def __init__(self, descriptor):
- args = [Argument('*JSContext', 'cx'), Argument('*JSObject', '_proxy')]
+ args = [Argument('*JSContext', 'cx'), Argument('*JSObject', 'proxy')]
CGAbstractExternMethod.__init__(self, descriptor, "obj_toString", "*JSString", args)
self.descriptor = descriptor
def getBody(self):
@@ -3617,7 +3590,7 @@ class CGClassConstructHook(CGAbstractExternMethod):
JS-visible constructor for our objects
"""
def __init__(self, descriptor):
- args = [Argument('*JSContext', 'cx'), Argument('u32', '_argc'), Argument('*mut JSVal', 'vp')]
+ args = [Argument('*JSContext', 'cx'), Argument('u32', 'argc'), Argument('*mut JSVal', 'vp')]
CGAbstractExternMethod.__init__(self, descriptor, CONSTRUCT_HOOK_NAME,
'JSBool', args)
self._ctor = self.descriptor.interface.ctor()
@@ -3709,7 +3682,7 @@ class CGClassFinalizeHook(CGAbstractClassHook):
A hook for finalize, used to release our native object.
"""
def __init__(self, descriptor):
- args = [Argument('*JSFreeOp', '_fop'), Argument('*JSObject', 'obj')]
+ args = [Argument('*JSFreeOp', 'fop'), Argument('*JSObject', 'obj')]
CGAbstractClassHook.__init__(self, descriptor, FINALIZE_HOOK_NAME,
'void', args)
@@ -3857,6 +3830,239 @@ class CGDescriptor(CGThing):
def define(self):
return self.cgRoot.define()
+class CGDictionary(CGThing):
+ def __init__(self, dictionary, descriptorProvider):
+ self.dictionary = dictionary;
+ self.workers = descriptorProvider.workers
+ if all(CGDictionary(d, descriptorProvider).generatable for
+ d in CGDictionary.getDictionaryDependencies(dictionary)):
+ self.generatable = True
+ else:
+ self.generatable = False
+ # Nothing else to do here
+ return
+ # Getting a conversion template for interface types can fail
+ # if we don't have a relevant descriptor when self.workers is True.
+ # If that happens, just mark ourselves as not being
+ # generatable and move on.
+ try:
+ self.memberInfo = [
+ (member,
+ getJSToNativeConversionTemplate(member.type,
+ descriptorProvider,
+ isMember=True,
+ isOptional=(not member.defaultValue),
+ defaultValue=member.defaultValue))
+ for member in dictionary.members ]
+ except NoSuchDescriptorError, err:
+ if not self.workers:
+ raise err
+ self.generatable = False
+
+ def declare(self):
+ if not self.generatable:
+ return ""
+ d = self.dictionary
+ if d.parent:
+ inheritance = ": public %s " % self.makeClassName(d.parent) #XXXjdm
+ else:
+ inheritance = ""
+ memberDecls = [" %s: %s," %
+ (m[0].identifier.name, self.getMemberType(m))
+ for m in self.memberInfo]
+
+ return (string.Template(
+ "pub struct ${selfName} {\n" + #XXXjdm deal with inheritance
+ "\n".join(memberDecls) + "\n" +
+ # NOTE: jsids are per-runtime, so don't use them in workers
+ "\n".join(" //static jsid " +
+ self.makeIdName(m.identifier.name) + ";" for
+ m in d.members) + "\n"
+ "}").substitute( { "selfName": self.makeClassName(d),
+ "inheritance": inheritance }))
+
+ def define(self):
+ if not self.generatable:
+ return ""
+ d = self.dictionary
+ if d.parent:
+ initParent = ("// Per spec, we init the parent's members first\n"
+ "if (!%s::Init(cx, val)) {\n"
+ " return false;\n"
+ "}\n" % self.makeClassName(d.parent))
+ else:
+ initParent = ""
+
+ memberInits = [CGIndenter(self.getMemberConversion(m)).define()
+ for m in self.memberInfo]
+ idinit = [CGGeneric('!InternJSString(cx, %s, "%s")' %
+ (m.identifier.name + "_id", m.identifier.name))
+ for m in d.members]
+ idinit = CGList(idinit, " ||\n")
+ idinit = CGWrapper(idinit, pre="if (",
+ post=(") {\n"
+ " return false;\n"
+ "}"),
+ reindent=True)
+
+ def defaultValue(ty):
+ if ty is "bool":
+ return "false"
+ elif ty in ["i32", "u32"]:
+ return "0"
+ elif ty is "nsString":
+ return "\"\""
+ elif ty.startswith("Optional"):
+ return "None"
+ else:
+ return "/* uh oh: %s */" % ty
+
+ return string.Template(
+ # NOTE: jsids are per-runtime, so don't use them in workers
+ ("static initedIds: bool = false;\n" +
+ "\n".join("static %s: jsid = JSID_VOID;" %
+ self.makeIdName(m.identifier.name)
+ for m in d.members) + "\n"
+ "\n"
+ "impl ${selfName} {\n"
+ "fn new() -> ${selfName} {\n"
+ " ${selfName} {\n" +
+ "\n".join(" %s: %s," % (m[0].identifier.name, defaultValue(self.getMemberType(m))) for m in self.memberInfo) + "\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "fn InitIds(cx: *JSContext) -> bool {\n"
+ " //MOZ_ASSERT(!initedIds);\n"
+ "/*${idInit}\n"
+ " initedIds = true;*/ //XXXjdm\n"
+ " return true;\n"
+ "}\n"
+ "\n" if not self.workers else "") +
+ "fn Init(&mut self, cx: *JSContext, val: JSVal) -> JSBool\n"
+ "{\n"
+ " unsafe {\n" +
+ # NOTE: jsids are per-runtime, so don't use them in workers
+ (" if (!initedIds && !${selfName}::InitIds(cx)) {\n"
+ " return 0;\n"
+ " }\n" if not self.workers else "") +
+ "${initParent}"
+ " let mut found: JSBool = 0;\n"
+ " let temp: JSVal = JSVAL_NULL;\n"
+ " let isNull = RUST_JSVAL_IS_NULL(val) != 0 || RUST_JSVAL_IS_VOID(val) != 0;\n"
+ " if !isNull && RUST_JSVAL_IS_PRIMITIVE(val) != 0 {\n"
+ " return 0; //XXXjdm throw properly here\n"
+ " //return Throw<${isMainThread}>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);\n"
+ " }\n"
+ "\n"
+ "${initMembers}\n"
+ " return 1;\n"
+ " }\n"
+ "}\n"
+ "}").substitute({
+ "selfName": self.makeClassName(d),
+ "initParent": CGIndenter(CGGeneric(initParent)).define(),
+ "initMembers": "\n\n".join(memberInits),
+ "idInit": CGIndenter(idinit).define(),
+ "isMainThread": toStringBool(not self.workers)
+ })
+
+ @staticmethod
+ def makeDictionaryName(dictionary, workers):
+ suffix = "Workers" if workers else ""
+ return dictionary.identifier.name + suffix
+
+ def makeClassName(self, dictionary):
+ return self.makeDictionaryName(dictionary, self.workers)
+
+ def getMemberType(self, memberInfo):
+ (member, (templateBody, declType,
+ holderType, dealWithOptional)) = memberInfo
+ # We can't handle having a holderType here
+ assert holderType is None
+ if dealWithOptional:
+ declType = CGWrapper(declType, pre="Optional< ", post=" >")
+ return declType.define()
+
+ def getMemberConversion(self, memberInfo):
+ (member, (templateBody, declType,
+ holderType, dealWithOptional)) = memberInfo
+ replacements = { "val": "temp",
+ "valPtr": "&temp",
+ "declName": ("self.%s" % member.identifier.name),
+ # We need a holder name for external interfaces, but
+ # it's scoped down to the conversion so we can just use
+ # anything we want.
+ "holderName": "holder"}
+ # We can't handle having a holderType here
+ assert holderType is None
+ if dealWithOptional:
+ replacements["declName"] = "(" + replacements["declName"] + ".Value())"
+ if member.defaultValue:
+ replacements["haveValue"] = "found"
+
+ # NOTE: jsids are per-runtime, so don't use them in workers
+ if True or self.workers: #XXXjdm hack until 'static mut' exists for global jsids
+ propName = member.identifier.name
+ propCheck = ('str::as_c_str("%s", |s| { JS_HasProperty(cx, RUST_JSVAL_TO_OBJECT(val), s, ptr::to_unsafe_ptr(&found)) })' %
+ propName)
+ propGet = ('str::as_c_str("%s", |s| { JS_GetProperty(cx, RUST_JSVAL_TO_OBJECT(val), s, ptr::to_unsafe_ptr(&temp)) })' %
+ propName)
+ else:
+ propId = self.makeIdName(member.identifier.name);
+ propCheck = ("JS_HasPropertyById(cx, RUST_JSVAL_TO_OBJECT(val), %s, ptr::to_unsafe_ptr(&found))" %
+ propId)
+ propGet = ("JS_GetPropertyById(cx, RUST_JSVAL_TO_OBJECT(val), %s, ptr::to_unsafe_ptr(&temp))" %
+ propId)
+
+ conversionReplacements = {
+ "prop": "(this->%s)" % member.identifier.name,
+ "convert": string.Template(templateBody).substitute(replacements),
+ "propCheck": propCheck,
+ "propGet": propGet
+ }
+ conversion = ("if isNull {\n"
+ " found = 0;\n"
+ "} else if ${propCheck} == 0 {\n"
+ " return 0;\n"
+ "}\n")
+ if member.defaultValue:
+ conversion += (
+ "if found != 0 {\n"
+ " if ${propGet} == 0 {\n"
+ " return 0;\n"
+ " }\n"
+ "}\n"
+ "${convert}")
+ else:
+ conversion += (
+ "if found != 0 {\n"
+ " ${prop}.Construct();\n"
+ " if ${propGet} == 0 {\n"
+ " return 0;\n"
+ " }\n"
+ "${convert}\n"
+ "}")
+ conversionReplacements["convert"] = CGIndenter(
+ CGGeneric(conversionReplacements["convert"])).define()
+
+ return CGGeneric(
+ string.Template(conversion).substitute(conversionReplacements)
+ )
+
+ @staticmethod
+ def makeIdName(name):
+ return name + "_id"
+
+ @staticmethod
+ def getDictionaryDependencies(dictionary):
+ deps = set();
+ if dictionary.parent:
+ deps.add(dictionary.parent)
+ for member in dictionary.members:
+ if member.type.isDictionary():
+ deps.add(member.type.unroll().inner)
+ return deps
+
class CGBindingRoot(CGThing):
"""
Root codegen class for binding generation. Instantiate the class, and call
@@ -3880,6 +4086,35 @@ class CGBindingRoot(CGThing):
cgthings = [ fun(e) for e in config.getEnums(webIDLFile)
for fun in [makeEnum, makeEnumTypedef] ]
+ # Do codegen for all the dictionaries. We have to be a bit careful
+ # here, because we have to generate these in order from least derived
+ # to most derived so that class inheritance works out. We also have to
+ # generate members before the dictionary that contains them.
+ #
+ # XXXbz this will fail if we have two webidl files A and B such that A
+ # declares a dictionary which inherits from a dictionary in B and B
+ # declares a dictionary (possibly a different one!) that inherits from a
+ # dictionary in A. The good news is that I expect this to never happen.
+ reSortedDictionaries = []
+ dictionaries = set(dictionaries)
+ while len(dictionaries) != 0:
+ # Find the dictionaries that don't depend on anything else anymore
+ # and move them over.
+ toMove = [d for d in dictionaries if
+ len(CGDictionary.getDictionaryDependencies(d) &
+ dictionaries) == 0]
+ if len(toMove) == 0:
+ raise TypeError("Loop in dictionary dependency graph")
+ dictionaries = dictionaries - set(toMove)
+ reSortedDictionaries.extend(toMove)
+
+ dictionaries = reSortedDictionaries
+ #XXXjdm No codegen for workers right now.
+ #cgthings.extend([CGDictionary(d, config.getDescriptorProvider(True))
+ # for d in dictionaries])
+ cgthings.extend([CGDictionary(d, config.getDescriptorProvider(False))
+ for d in dictionaries])
+
# Do codegen for all the descriptors
cgthings.extend([CGDescriptor(x) for x in descriptors])
@@ -3910,6 +4145,8 @@ class CGBindingRoot(CGThing):
'dom::htmlcollection::*', #XXXjdm
'dom::bindings::proxyhandler::*',
'dom::domparser::*', #XXXjdm
+ 'dom::event::*', #XXXjdm
+ 'dom::eventtarget::*', #XXXjdm
'content::content_task::task_from_context',
'dom::bindings::utils::EnumEntry',
],
diff --git a/src/servo/dom/bindings/codegen/Configuration.py b/src/servo/dom/bindings/codegen/Configuration.py
index d1ca528a3a3..46e16fdc37c 100644
--- a/src/servo/dom/bindings/codegen/Configuration.py
+++ b/src/servo/dom/bindings/codegen/Configuration.py
@@ -134,12 +134,12 @@ class Descriptor(DescriptorProvider):
nativeTypeDefault = "nsIDOM" + ifaceName
else:
if self.workers:
- nativeTypeDefault = "mozilla::dom::workers::" + ifaceName
+ nativeTypeDefault = "workers::" + ifaceName
else:
- nativeTypeDefault = "mozilla::dom::" + ifaceName
+ nativeTypeDefault = ifaceName
self.nativeType = desc.get('nativeType', nativeTypeDefault)
- self.pointerType = desc.get('pointerType', '~')
+ self.pointerType = desc.get('pointerType', '@mut ')
self.hasInstanceInterface = desc.get('hasInstanceInterface', None)
# Do something sane for JSObject
diff --git a/src/servo/dom/bindings/codegen/Event.webidl b/src/servo/dom/bindings/codegen/Event.webidl
new file mode 100644
index 00000000000..48af319ada0
--- /dev/null
+++ b/src/servo/dom/bindings/codegen/Event.webidl
@@ -0,0 +1,80 @@
+[Constructor(DOMString type, optional EventInit eventInitDict)]
+interface Event {
+ readonly attribute DOMString type;
+ readonly attribute EventTarget? target;
+ readonly attribute EventTarget? currentTarget;
+
+ const unsigned short NONE = 0;
+ const unsigned short CAPTURING_PHASE = 1;
+ const unsigned short AT_TARGET = 2;
+ const unsigned short BUBBLING_PHASE = 3;
+ readonly attribute unsigned short eventPhase;
+
+ void stopPropagation();
+ void stopImmediatePropagation();
+
+ readonly attribute boolean bubbles;
+ readonly attribute boolean cancelable;
+ void preventDefault();
+ readonly attribute boolean defaultPrevented;
+
+ readonly attribute boolean isTrusted;
+ readonly attribute DOMTimeStamp timeStamp;
+
+ [Throws]
+ void initEvent(DOMString type, boolean bubbles, boolean cancelable);
+};
+
+/*// Mozilla specific legacy stuff.
+partial interface Event {
+ const long MOUSEDOWN = 0x00000001;
+ const long MOUSEUP = 0x00000002;
+ const long MOUSEOVER = 0x00000004;
+ const long MOUSEOUT = 0x00000008;
+ const long MOUSEMOVE = 0x00000010;
+ const long MOUSEDRAG = 0x00000020;
+ const long CLICK = 0x00000040;
+ const long DBLCLICK = 0x00000080;
+ const long KEYDOWN = 0x00000100;
+ const long KEYUP = 0x00000200;
+ const long KEYPRESS = 0x00000400;
+ const long DRAGDROP = 0x00000800;
+ const long FOCUS = 0x00001000;
+ const long BLUR = 0x00002000;
+ const long SELECT = 0x00004000;
+ const long CHANGE = 0x00008000;
+ const long RESET = 0x00010000;
+ const long SUBMIT = 0x00020000;
+ const long SCROLL = 0x00040000;
+ const long LOAD = 0x00080000;
+ const long UNLOAD = 0x00100000;
+ const long XFER_DONE = 0x00200000;
+ const long ABORT = 0x00400000;
+ const long ERROR = 0x00800000;
+ const long LOCATE = 0x01000000;
+ const long MOVE = 0x02000000;
+ const long RESIZE = 0x04000000;
+ const long FORWARD = 0x08000000;
+ const long HELP = 0x10000000;
+ const long BACK = 0x20000000;
+ const long TEXT = 0x40000000;
+
+ const long ALT_MASK = 0x00000001;
+ const long CONTROL_MASK = 0x00000002;
+ const long SHIFT_MASK = 0x00000004;
+ const long META_MASK = 0x00000008;
+
+ readonly attribute EventTarget? originalTarget;
+ readonly attribute EventTarget? explicitOriginalTarget;
+ [ChromeOnly] readonly attribute boolean multipleActionsPrevented;
+
+ void preventBubble();
+ void preventCapture();
+ boolean getPreventDefault();
+ };*/
+
+dictionary EventInit {
+ boolean bubbles = false;
+ boolean cancelable = false;
+};
+
diff --git a/src/servo/dom/bindings/codegen/EventTarget.webidl b/src/servo/dom/bindings/codegen/EventTarget.webidl
new file mode 100644
index 00000000000..f4e1ba00f70
--- /dev/null
+++ b/src/servo/dom/bindings/codegen/EventTarget.webidl
@@ -0,0 +1,14 @@
+/* -*- 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.
+ */
+
+interface EventTarget {
+};
diff --git a/src/servo/dom/bindings/codegen/RegisterBindings.cpp b/src/servo/dom/bindings/codegen/RegisterBindings.cpp
index c1fb6c3350b..74244842a21 100644
--- a/src/servo/dom/bindings/codegen/RegisterBindings.cpp
+++ b/src/servo/dom/bindings/codegen/RegisterBindings.cpp
@@ -1,6 +1,8 @@
#include "ClientRectBinding.h"
#include "ClientRectListBinding.h"
#include "DOMParserBinding.h"
+#include "EventBinding.h"
+#include "EventTargetBinding.h"
#include "HTMLCollectionBinding.h"
#include "nsScriptNameSpaceManager.h"
@@ -16,6 +18,8 @@ Register(nsScriptNameSpaceManager* aNameSpaceManager)
REGISTER_PROTO(ClientRect, nullptr);
REGISTER_PROTO(ClientRectList, nullptr);
REGISTER_PROTO(DOMParser, nullptr);
+REGISTER_PROTO(Event, nullptr);
+REGISTER_PROTO(EventTarget, nullptr);
REGISTER_PROTO(HTMLCollection, nullptr);
#undef REGISTER_PROTO
diff --git a/src/servo/dom/bindings/conversions.rs b/src/servo/dom/bindings/conversions.rs
index 0a2715e2af9..7350427a95e 100644
--- a/src/servo/dom/bindings/conversions.rs
+++ b/src/servo/dom/bindings/conversions.rs
@@ -3,19 +3,40 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use js::jsapi::JSVal;
-use js::glue::bindgen::{RUST_INT_TO_JSVAL, RUST_JSVAL_TO_INT};
+use js::{JSVAL_FALSE, JSVAL_TRUE};
+use js::glue::bindgen::{RUST_UINT_TO_JSVAL, RUST_JSVAL_TO_INT};
-pub trait JSValConvertible<T> {
+pub trait JSValConvertible {
fn to_jsval(&self) -> JSVal;
- fn from_jsval(val: JSVal) -> Option<T>;
+ fn from_jsval(val: JSVal) -> Option<Self>;
}
-impl JSValConvertible<u32> for u32 {
+impl JSValConvertible for u32 {
fn to_jsval(&self) -> JSVal {
- RUST_INT_TO_JSVAL(*self as i32)
+ RUST_UINT_TO_JSVAL(*self)
}
fn from_jsval(val: JSVal) -> Option<u32> {
Some(RUST_JSVAL_TO_INT(val) as u32)
}
}
+
+impl JSValConvertible for bool {
+ fn to_jsval(&self) -> JSVal {
+ if *self {
+ JSVAL_TRUE
+ } else {
+ JSVAL_FALSE
+ }
+ }
+
+ fn from_jsval(val: JSVal) -> Option<bool> {
+ if val == JSVAL_TRUE {
+ Some(true)
+ } else if val == JSVAL_FALSE {
+ Some(false)
+ } else {
+ None
+ }
+ }
+} \ No newline at end of file
diff --git a/src/servo/dom/bindings/event.rs b/src/servo/dom/bindings/event.rs
new file mode 100644
index 00000000000..b2af9b35e69
--- /dev/null
+++ b/src/servo/dom/bindings/event.rs
@@ -0,0 +1,55 @@
+/* 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 content::content_task::{task_from_context, global_content};
+use dom::bindings::utils::{CacheableWrapper, WrapperCache, BindingObject, DerivedWrapper};
+use dom::bindings::codegen::EventBinding;
+use dom::event::Event_;
+use js::jsapi::{JSObject, JSContext, JSVal};
+use js::glue::bindgen::RUST_OBJECT_TO_JSVAL;
+
+pub impl Event_ {
+ pub fn init_wrapper(@mut self) {
+ let content = global_content();
+ let cx = content.compartment.get().cx.ptr;
+ let owner = content.window.get();
+ let cache = owner.get_wrappercache();
+ let scope = cache.get_wrapper();
+ self.wrap_object_shared(cx, scope);
+ }
+}
+
+impl CacheableWrapper for Event_ {
+ fn get_wrappercache(&mut self) -> &mut WrapperCache {
+ unsafe { cast::transmute(&self.wrapper) }
+ }
+
+ fn wrap_object_shared(@mut self, cx: *JSContext, scope: *JSObject) -> *JSObject {
+ let mut unused = false;
+ EventBinding::Wrap(cx, scope, self, &mut unused)
+ }
+}
+
+impl BindingObject for Event_ {
+ fn GetParentObject(&self, cx: *JSContext) -> @mut CacheableWrapper {
+ let content = task_from_context(cx);
+ unsafe { (*content).window.get() as @mut CacheableWrapper }
+ }
+}
+
+impl DerivedWrapper for Event_ {
+ fn wrap(&mut self, _cx: *JSContext, _scope: *JSObject, _vp: *mut JSVal) -> i32 {
+ fail!(~"nyi")
+ }
+
+ fn wrap_shared(@mut self, cx: *JSContext, scope: *JSObject, vp: *mut JSVal) -> i32 {
+ let obj = self.wrap_object_shared(cx, scope);
+ if obj.is_null() {
+ return 0;
+ } else {
+ unsafe { *vp = RUST_OBJECT_TO_JSVAL(obj) };
+ return 1;
+ }
+ }
+}
diff --git a/src/servo/dom/bindings/eventtarget.rs b/src/servo/dom/bindings/eventtarget.rs
new file mode 100644
index 00000000000..24242e7f9f4
--- /dev/null
+++ b/src/servo/dom/bindings/eventtarget.rs
@@ -0,0 +1,55 @@
+/* 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 content::content_task::{task_from_context, global_content};
+use dom::bindings::utils::{CacheableWrapper, WrapperCache, BindingObject, DerivedWrapper};
+use dom::bindings::codegen::EventTargetBinding;
+use dom::eventtarget::EventTarget;
+use js::jsapi::{JSObject, JSContext, JSVal};
+use js::glue::bindgen::RUST_OBJECT_TO_JSVAL;
+
+pub impl EventTarget {
+ pub fn init_wrapper(@mut self) {
+ let content = global_content();
+ let cx = content.compartment.get().cx.ptr;
+ let owner = content.window.get();
+ let cache = owner.get_wrappercache();
+ let scope = cache.get_wrapper();
+ self.wrap_object_shared(cx, scope);
+ }
+}
+
+impl CacheableWrapper for EventTarget {
+ fn get_wrappercache(&mut self) -> &mut WrapperCache {
+ unsafe { cast::transmute(&self.wrapper) }
+ }
+
+ fn wrap_object_shared(@mut self, cx: *JSContext, scope: *JSObject) -> *JSObject {
+ let mut unused = false;
+ EventTargetBinding::Wrap(cx, scope, self, &mut unused)
+ }
+}
+
+impl BindingObject for EventTarget {
+ fn GetParentObject(&self, cx: *JSContext) -> @mut CacheableWrapper {
+ let content = task_from_context(cx);
+ unsafe { (*content).window.get() as @mut CacheableWrapper }
+ }
+}
+
+impl DerivedWrapper for EventTarget {
+ fn wrap(&mut self, _cx: *JSContext, _scope: *JSObject, _vp: *mut JSVal) -> i32 {
+ fail!(~"nyi")
+ }
+
+ fn wrap_shared(@mut self, cx: *JSContext, scope: *JSObject, vp: *mut JSVal) -> i32 {
+ let obj = self.wrap_object_shared(cx, scope);
+ if obj.is_null() {
+ return 0;
+ } else {
+ unsafe { *vp = RUST_OBJECT_TO_JSVAL(obj) };
+ return 1;
+ }
+ }
+}
diff --git a/src/servo/dom/bindings/utils.rs b/src/servo/dom/bindings/utils.rs
index dd925ee3df8..0fe45f79e04 100644
--- a/src/servo/dom/bindings/utils.rs
+++ b/src/servo/dom/bindings/utils.rs
@@ -6,7 +6,8 @@ use js;
use js::rust::Compartment;
use js::{JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSVAL_NULL,
JS_THIS_OBJECT, JSFUN_CONSTRUCTOR, JS_CALLEE, JSPROP_READONLY,
- JSPROP_PERMANENT, JSID_VOID, JSPROP_NATIVE_ACCESSORS, JSPROP_GETTER, JSPROP_SETTER};
+ JSPROP_PERMANENT, JSID_VOID, JSPROP_NATIVE_ACCESSORS, JSPROP_GETTER,
+ JSPROP_SETTER, JSVAL_VOID, JSVAL_TRUE, JSVAL_FALSE};
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSNative,
JSFunctionSpec, JSPropertySpec, JSVal, JSPropertyDescriptor};
use js::jsapi::bindgen::{JS_ValueToString,
@@ -327,9 +328,18 @@ pub struct JSNativeHolder {
propertyHooks: *NativePropertyHooks
}
+pub enum ConstantVal {
+ IntVal(i32),
+ UintVal(u32),
+ DoubleVal(f64),
+ BoolVal(bool),
+ NullVal,
+ VoidVal
+}
+
pub struct ConstantSpec {
name: *libc::c_char,
- value: JSVal
+ value: ConstantVal
}
pub struct DOMClass {
@@ -360,6 +370,8 @@ pub mod prototypes {
ClientRectList,
DOMParser,
HTMLCollection,
+ Event,
+ EventTarget,
_ID_Count
}
}
@@ -492,8 +504,17 @@ fn DefineConstants(cx: *JSContext, obj: *JSObject, constants: *ConstantSpec) ->
if spec.name.is_null() {
return true;
}
+ let jsval = match spec.value {
+ NullVal => JSVAL_NULL,
+ IntVal(i) => RUST_INT_TO_JSVAL(i),
+ UintVal(u) => RUST_UINT_TO_JSVAL(u),
+ DoubleVal(d) => RUST_DOUBLE_TO_JSVAL(d),
+ BoolVal(b) if b => JSVAL_TRUE,
+ BoolVal(_) => JSVAL_FALSE,
+ VoidVal => JSVAL_VOID
+ };
if JS_DefineProperty(cx, obj, spec.name,
- spec.value, ptr::null(),
+ jsval, ptr::null(),
ptr::null(),
JSPROP_ENUMERATE | JSPROP_READONLY |
JSPROP_PERMANENT) == 0 {
@@ -543,7 +564,7 @@ pub extern fn ThrowingConstructor(_cx: *JSContext, _argc: uint, _vp: *JSVal) ->
}
pub fn initialize_global(global: *JSObject) {
- let protoArray = @mut ([0 as *JSObject, ..4]); //XXXjdm prototypes::_ID_COUNT
+ let protoArray = @mut ([0 as *JSObject, ..6]); //XXXjdm prototypes::_ID_COUNT
unsafe {
//XXXjdm we should be storing the box pointer instead of the inner
let box = squirrel_away(protoArray);
diff --git a/src/servo/dom/event.rs b/src/servo/dom/event.rs
index 83b1a115f80..7b1fba2ac37 100644
--- a/src/servo/dom/event.rs
+++ b/src/servo/dom/event.rs
@@ -2,8 +2,97 @@
* 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::window::Window;
+use dom::bindings::codegen::EventBinding;
+use dom::bindings::utils::{DOMString, ErrorResult, WrapperCache};
+
pub enum Event {
ResizeEvent(uint, uint, comm::Chan<()>),
ReflowEvent
}
+pub struct Event_ {
+ wrapper: WrapperCache,
+ type_: DOMString,
+ default_prevented: bool,
+ cancelable: bool,
+ bubbles: bool,
+ trusted: bool,
+}
+
+impl Event_ {
+ pub fn new(type_: DOMString) -> Event_ {
+ Event_ {
+ wrapper: WrapperCache::new(),
+ type_: type_,
+ default_prevented: false,
+ cancelable: true,
+ bubbles: true,
+ trusted: false
+ }
+ }
+
+ pub fn EventPhase(&self) -> u16 {
+ 0
+ }
+
+ pub fn Type(&self) -> DOMString {
+ copy self.type_
+ }
+
+ pub fn GetTarget(&self) -> Option<@mut EventTarget> {
+ None
+ }
+
+ pub fn GetCurrentTarget(&self) -> Option<@mut EventTarget> {
+ None
+ }
+
+ pub fn DefaultPrevented(&self) -> bool {
+ self.default_prevented
+ }
+
+ pub fn PreventDefault(&mut self) {
+ self.default_prevented = true
+ }
+
+ pub fn StopPropagation(&mut self) {
+ }
+
+ pub fn StopImmediatePropagation(&mut self) {
+ }
+
+ pub fn Bubbles(&self) -> bool {
+ self.bubbles
+ }
+
+ pub fn Cancelable(&self) -> bool {
+ self.cancelable
+ }
+
+ pub fn TimeStamp(&self) -> u64 {
+ 0
+ }
+
+ pub fn InitEvent(&mut self,
+ type_: DOMString,
+ bubbles: bool,
+ cancelable: bool,
+ _rv: &mut ErrorResult) {
+ self.type_ = type_;
+ self.cancelable = cancelable;
+ self.bubbles = bubbles;
+ }
+
+ pub fn IsTrusted(&self) -> bool {
+ self.trusted
+ }
+
+ pub fn Constructor(_global: @mut Window,
+ type_: DOMString,
+ _init: &EventBinding::EventInit,
+ _rv: &mut ErrorResult) -> @mut Event_ {
+ @mut Event_::new(type_)
+ }
+}
diff --git a/src/servo/dom/eventtarget.rs b/src/servo/dom/eventtarget.rs
new file mode 100644
index 00000000000..b216b7d0cca
--- /dev/null
+++ b/src/servo/dom/eventtarget.rs
@@ -0,0 +1,17 @@
+/* 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::WrapperCache;
+
+pub struct EventTarget {
+ wrapper: WrapperCache
+}
+
+pub impl EventTarget {
+ fn new() -> ~EventTarget {
+ ~EventTarget {
+ wrapper: WrapperCache::new()
+ }
+ }
+} \ No newline at end of file
diff --git a/src/servo/dom/node.rs b/src/servo/dom/node.rs
index b24e50d6a3e..541d268dbc6 100644
--- a/src/servo/dom/node.rs
+++ b/src/servo/dom/node.rs
@@ -449,4 +449,10 @@ pub fn define_bindings(compartment: @mut Compartment) {
assert!(codegen::DOMParserBinding::DefineDOMInterface(compartment.cx.ptr,
compartment.global_obj.ptr,
&mut unused));
+ assert!(codegen::EventBinding::DefineDOMInterface(compartment.cx.ptr,
+ compartment.global_obj.ptr,
+ &mut unused));
+ assert!(codegen::EventTargetBinding::DefineDOMInterface(compartment.cx.ptr,
+ compartment.global_obj.ptr,
+ &mut unused));
}
diff --git a/src/servo/servo.rc b/src/servo/servo.rc
index d2d749d8c70..2d5355690ab 100755
--- a/src/servo/servo.rc
+++ b/src/servo/servo.rc
@@ -61,6 +61,8 @@ pub mod dom {
pub mod bindings {
pub mod document;
pub mod element;
+ pub mod event;
+ pub mod eventtarget;
pub mod node;
pub mod text;
pub mod utils;
@@ -75,6 +77,8 @@ pub mod dom {
pub mod ClientRectBinding;
pub mod ClientRectListBinding;
pub mod DOMParserBinding;
+ pub mod EventBinding;
+ pub mod EventTargetBinding;
pub mod HTMLCollectionBinding;
}
}
@@ -85,6 +89,7 @@ pub mod dom {
pub mod domparser;
pub mod element;
pub mod event;
+ pub mod eventtarget;
pub mod htmlcollection;
pub mod node;
pub mod window;