diff options
author | Josh Matthews <josh@joshmatthews.net> | 2013-05-08 13:35:07 -0400 |
---|---|---|
committer | Josh Matthews <josh@joshmatthews.net> | 2013-05-08 14:17:50 -0400 |
commit | af2db0cf682e65abe5e6e6a380f9ea51a13cc16f (patch) | |
tree | 8a995a6555b975f0ae839d9e174978fb7a0dfbc4 /src/servo | |
parent | 597f7bdc6d547fbaf413e7352fe1b89ebe519b1c (diff) | |
download | servo-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.conf | 27 | ||||
-rw-r--r-- | src/servo/dom/bindings/codegen/CodegenRust.py | 389 | ||||
-rw-r--r-- | src/servo/dom/bindings/codegen/Configuration.py | 6 | ||||
-rw-r--r-- | src/servo/dom/bindings/codegen/Event.webidl | 80 | ||||
-rw-r--r-- | src/servo/dom/bindings/codegen/EventTarget.webidl | 14 | ||||
-rw-r--r-- | src/servo/dom/bindings/codegen/RegisterBindings.cpp | 4 | ||||
-rw-r--r-- | src/servo/dom/bindings/conversions.rs | 31 | ||||
-rw-r--r-- | src/servo/dom/bindings/event.rs | 55 | ||||
-rw-r--r-- | src/servo/dom/bindings/eventtarget.rs | 55 | ||||
-rw-r--r-- | src/servo/dom/bindings/utils.rs | 29 | ||||
-rw-r--r-- | src/servo/dom/event.rs | 89 | ||||
-rw-r--r-- | src/servo/dom/eventtarget.rs | 17 | ||||
-rw-r--r-- | src/servo/dom/node.rs | 6 | ||||
-rwxr-xr-x | src/servo/servo.rc | 5 |
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; |