1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/xpconnect/src/event_impl_gen.py Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,744 @@ 1.4 +#!/usr/bin/env python 1.5 +# header.py - Generate C++ header files from IDL. 1.6 +# 1.7 +# This Source Code Form is subject to the terms of the Mozilla Public 1.8 +# License, v. 2.0. If a copy of the MPL was not distributed with this 1.9 +# file, You can obtain one at http://mozilla.org/MPL/2.0/. 1.10 + 1.11 +import sys, os, xpidl, makeutils 1.12 + 1.13 +def strip_end(text, suffix): 1.14 + if not text.endswith(suffix): 1.15 + return text 1.16 + return text[:-len(suffix)] 1.17 + 1.18 +def findIDL(includePath, interfaceFileName): 1.19 + for d in includePath: 1.20 + # Not os.path.join: we need a forward slash even on Windows because 1.21 + # this filename ends up in makedepend output. 1.22 + path = d + '/' + interfaceFileName 1.23 + if os.path.exists(path): 1.24 + return path 1.25 + raise BaseException("No IDL file found for interface %s " 1.26 + "in include path %r" 1.27 + % (interfaceFileName, includePath)) 1.28 + 1.29 +eventFileNameToIdl = {}; 1.30 + 1.31 +def loadIDL(parser, includePath, filename): 1.32 + global eventFileNameToIdl 1.33 + if filename in eventFileNameToIdl: 1.34 + return eventFileNameToIdl[filename] 1.35 + 1.36 + idlFile = findIDL(includePath, filename) 1.37 + if not idlFile in makeutils.dependencies: 1.38 + makeutils.dependencies.append(idlFile) 1.39 + idl = p.parse(open(idlFile).read(), idlFile) 1.40 + idl.resolve(includePath, p) 1.41 + eventFileNameToIdl[filename] = idl 1.42 + return idl 1.43 + 1.44 +def loadEventIDL(parser, includePath, eventname): 1.45 + eventidl = ("nsIDOM%s.idl" % eventname) 1.46 + return loadIDL(parser, includePath, eventidl) 1.47 + 1.48 +class Configuration: 1.49 + def __init__(self, filename): 1.50 + config = {} 1.51 + execfile(filename, config) 1.52 + self.simple_events = config.get('simple_events', []) 1.53 + self.special_includes = config.get('special_includes', []) 1.54 + self.exclude_automatic_type_include = config.get('exclude_automatic_type_include', []) 1.55 + self.xpidl_to_native = config.get('xpidl_to_native', []) 1.56 + 1.57 +def readConfigFile(filename): 1.58 + return Configuration(filename) 1.59 + 1.60 +def firstCap(str): 1.61 + return str[0].upper() + str[1:] 1.62 + 1.63 +def getBaseName(iface): 1.64 + return ("%s" % iface.base[6:]) 1.65 + 1.66 +def print_header_file(fd, conf): 1.67 + fd.write("#ifndef _gen_mozilla_idl_generated_events_h_\n" 1.68 + "#define _gen_mozilla_idl_generated_events_h_\n\n") 1.69 + fd.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n") 1.70 + fd.write("#include \"nscore.h\"\n") 1.71 + fd.write("class nsIDOMEvent;\n") 1.72 + fd.write("class nsPresContext;\n") 1.73 + fd.write("namespace mozilla {\n"); 1.74 + fd.write("class WidgetEvent;\n") 1.75 + fd.write("namespace dom {\n"); 1.76 + fd.write("class EventTarget;\n") 1.77 + fd.write("}\n"); 1.78 + fd.write("}\n\n"); 1.79 + for e in conf.simple_events: 1.80 + fd.write("nsresult\n") 1.81 + fd.write("NS_NewDOM%s(nsIDOMEvent** aInstance, " % e) 1.82 + fd.write("mozilla::dom::EventTarget* aOwner, ") 1.83 + fd.write("nsPresContext* aPresContext, mozilla::WidgetEvent* aEvent);\n") 1.84 + 1.85 + fd.write("\n#endif\n") 1.86 + 1.87 +def print_classes_file(fd, conf): 1.88 + fd.write("#ifndef _gen_mozilla_idl_generated_event_declarations_h_\n") 1.89 + fd.write("#define _gen_mozilla_idl_generated_event_declarations_h_\n\n") 1.90 + 1.91 + fd.write("#include \"mozilla/dom/Event.h\"\n"); 1.92 + includes = [] 1.93 + for s in conf.special_includes: 1.94 + if not s in includes: 1.95 + includes.append(strip_end(s, ".h")) 1.96 + 1.97 + for e in conf.simple_events: 1.98 + if not e in includes: 1.99 + includes.append(("nsIDOM%s" % e)) 1.100 + 1.101 + attrnames = [] 1.102 + for e in conf.simple_events: 1.103 + idl = loadEventIDL(p, options.incdirs, e) 1.104 + collect_names_and_non_primitive_attribute_types(idl, attrnames, includes) 1.105 + 1.106 + for c in includes: 1.107 + if not c in conf.exclude_automatic_type_include: 1.108 + fd.write("#include \"%s.h\"\n" % c) 1.109 + 1.110 + for e in conf.simple_events: 1.111 + fd.write('#include "mozilla/dom/%sBinding.h"\n' % e); 1.112 + 1.113 + fd.write("namespace mozilla {\n") 1.114 + fd.write("namespace dom {\n") 1.115 + for e in conf.simple_events: 1.116 + idl = loadEventIDL(p, options.incdirs, e) 1.117 + for pr in idl.productions: 1.118 + if pr.kind == 'interface': 1.119 + print_class_declaration(e, pr, fd, conf) 1.120 + fd.write("} // namespace dom\n") 1.121 + fd.write("} // namespace mozilla\n\n") 1.122 + fd.write("#endif\n"); 1.123 + 1.124 +def print_class_declaration(eventname, iface, fd, conf): 1.125 + classname = ("%s" % eventname) 1.126 + basename = getBaseName(iface) 1.127 + attributes = [] 1.128 + ccattributes = [] 1.129 + for member in iface.members: 1.130 + if isinstance(member, xpidl.Attribute): 1.131 + attributes.append(member) 1.132 + if (member.realtype.nativeType('in').endswith('*')): 1.133 + ccattributes.append(member); 1.134 + 1.135 + baseinterfaces = [] 1.136 + baseiface = iface.idl.getName(iface.base, iface.location) 1.137 + while baseiface.name != "nsIDOMEvent": 1.138 + baseinterfaces.append(baseiface) 1.139 + baseiface = baseiface.idl.getName(baseiface.base, baseiface.location) 1.140 + baseinterfaces.reverse() 1.141 + 1.142 + allattributes = [] 1.143 + for baseiface in baseinterfaces: 1.144 + for member in baseiface.members: 1.145 + if isinstance(member, xpidl.Attribute): 1.146 + allattributes.append(member) 1.147 + allattributes.extend(attributes); 1.148 + 1.149 + fd.write("\nclass %s MOZ_FINAL : public %s, public %s\n" % (classname, basename, iface.name)) 1.150 + fd.write("{\n") 1.151 + fd.write("public:\n") 1.152 + fd.write(" %s(mozilla::dom::EventTarget* aOwner, " % classname) 1.153 + fd.write("nsPresContext* aPresContext = nullptr, mozilla::WidgetEvent* aEvent = nullptr);\n"); 1.154 + fd.write(" virtual ~%s();\n\n" % classname) 1.155 + fd.write(" NS_DECL_ISUPPORTS_INHERITED\n") 1.156 + fd.write(" NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(%s, %s)\n" % (classname, basename)) 1.157 + fd.write(" NS_FORWARD_TO_EVENT\n") 1.158 + 1.159 + for baseiface in baseinterfaces: 1.160 + baseimpl = ("%s" % baseiface.name[6:]) 1.161 + fd.write(" NS_FORWARD_%s(%s::)\n" % (baseiface.name.upper(), baseimpl)) 1.162 + 1.163 + fd.write(" NS_DECL_%s\n" % iface.name.upper()) 1.164 + 1.165 + hasVariant = False 1.166 + for a in allattributes: 1.167 + if a.type == "nsIVariant": 1.168 + hasVariant = True 1.169 + break; 1.170 + fd.write(" static already_AddRefed<%s> Constructor(const GlobalObject& aGlobal, " % eventname) 1.171 + if hasVariant: 1.172 + fd.write("JSContext* aCx, ") 1.173 + fd.write("const nsAString& aType, ") 1.174 + fd.write("const %sInit& aParam, " % eventname) 1.175 + fd.write("ErrorResult& aRv);\n\n") 1.176 + 1.177 + fd.write(" virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE\n") 1.178 + fd.write(" {\n") 1.179 + fd.write(" return mozilla::dom::%sBinding::Wrap(aCx, this);\n" % eventname) 1.180 + fd.write(" }\n\n") 1.181 + 1.182 + for a in attributes: 1.183 + """xpidl methods take care of string member variables!""" 1.184 + firstCapName = firstCap(a.name) 1.185 + cleanNativeType = a.realtype.nativeType('in').strip('* ') 1.186 + if a.realtype.nativeType('in').count("nsAString"): 1.187 + continue 1.188 + elif a.realtype.nativeType('in').count("nsIVariant"): 1.189 + fd.write(" void Get%s(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval, ErrorResult& aRv);\n\n" % firstCapName); 1.190 + elif a.realtype.nativeType('in').endswith('*'): 1.191 + fd.write(" already_AddRefed<%s> Get%s()\n" % (xpidl_to_native(cleanNativeType, conf), firstCapName)) 1.192 + fd.write(" {\n"); 1.193 + fd.write(" nsCOMPtr<%s> %s = do_QueryInterface(m%s);\n" % (xpidl_to_canonical(cleanNativeType, conf), a.name, firstCapName)) 1.194 + fd.write(" return %s.forget().downcast<%s>();\n" % (a.name, xpidl_to_native(cleanNativeType, conf))) 1.195 + fd.write(" }\n\n"); 1.196 + else: 1.197 + fd.write(" %s %s()\n" % (cleanNativeType, firstCapName)) 1.198 + fd.write(" {\n"); 1.199 + fd.write(" return m%s;\n" % firstCapName) 1.200 + fd.write(" }\n\n"); 1.201 + 1.202 + fd.write(" void ") 1.203 + fd.write("Init%s(" % eventname) 1.204 + if hasVariant: 1.205 + fd.write("JSContext* aCx, ") 1.206 + fd.write("const nsAString& aType, bool aCanBubble, bool aCancelable") 1.207 + for a in allattributes: 1.208 + writeNativeAttributeParams(fd, a, conf) 1.209 + fd.write(", ErrorResult& aRv);\n\n") 1.210 + 1.211 + fd.write("protected:\n") 1.212 + for a in attributes: 1.213 + fd.write(" %s\n" % attributeVariableTypeAndName(a)) 1.214 + fd.write("};\n") 1.215 + 1.216 +def collect_names_and_non_primitive_attribute_types(idl, attrnames, forwards): 1.217 + for p in idl.productions: 1.218 + if p.kind == 'interface' or p.kind == 'dictionary': 1.219 + interfaces = [] 1.220 + base = p.base 1.221 + baseiface = p 1.222 + while base is not None: 1.223 + baseiface = baseiface.idl.getName(baseiface.base, baseiface.location) 1.224 + interfaces.append(baseiface) 1.225 + base = baseiface.base 1.226 + 1.227 + interfaces.reverse() 1.228 + interfaces.append(p) 1.229 + 1.230 + for iface in interfaces: 1.231 + collect_names_and_non_primitive_attribute_types_from_interface(iface, attrnames, forwards) 1.232 + 1.233 +def collect_names_and_non_primitive_attribute_types_from_interface(iface, attrnames, forwards): 1.234 + for member in iface.members: 1.235 + if isinstance(member, xpidl.Attribute): 1.236 + if not member.name in attrnames: 1.237 + attrnames.append(member.name) 1.238 + if member.realtype.nativeType('in').endswith('*'): 1.239 + t = member.realtype.nativeType('in').strip('* ') 1.240 + if not t in forwards: 1.241 + forwards.append(t) 1.242 + 1.243 +def print_cpp(idl, fd, conf, eventname): 1.244 + for p in idl.productions: 1.245 + if p.kind == 'interface': 1.246 + write_cpp(eventname, p, fd, conf) 1.247 + 1.248 +def print_cpp_file(fd, conf): 1.249 + fd.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n") 1.250 + fd.write('#include "GeneratedEventClasses.h"\n') 1.251 + fd.write('#include "xpcprivate.h"\n'); 1.252 + fd.write('#include "mozilla/dom/Event.h"\n'); 1.253 + fd.write('#include "mozilla/dom/EventTarget.h"\n'); 1.254 + 1.255 + for e in conf.simple_events: 1.256 + idl = loadEventIDL(p, options.incdirs, e) 1.257 + print_cpp(idl, fd, conf, e) 1.258 + 1.259 +def init_value(attribute): 1.260 + realtype = attribute.realtype.nativeType('in') 1.261 + realtype = realtype.strip(' ') 1.262 + if realtype.endswith('*'): 1.263 + return "nullptr" 1.264 + if realtype == "bool": 1.265 + return "false" 1.266 + if realtype.count("nsAString"): 1.267 + return "" 1.268 + if realtype.count("nsACString"): 1.269 + return "" 1.270 + if realtype.count("JS::Value"): 1.271 + raise BaseException("JS::Value not supported in simple events!") 1.272 + return "0" 1.273 + 1.274 +def attributeVariableTypeAndName(a): 1.275 + if a.realtype.nativeType('in').endswith('*'): 1.276 + l = ["nsCOMPtr<%s> m%s;" % (a.realtype.nativeType('in').strip('* '), 1.277 + firstCap(a.name))] 1.278 + elif a.realtype.nativeType('in').count("nsAString"): 1.279 + l = ["nsString m%s;" % firstCap(a.name)] 1.280 + elif a.realtype.nativeType('in').count("nsACString"): 1.281 + l = ["nsCString m%s;" % firstCap(a.name)] 1.282 + else: 1.283 + l = ["%sm%s;" % (a.realtype.nativeType('in'), 1.284 + firstCap(a.name))] 1.285 + return ", ".join(l) 1.286 + 1.287 +def writeAttributeGetter(fd, classname, a): 1.288 + fd.write("NS_IMETHODIMP\n") 1.289 + fd.write("%s::Get%s(" % (classname, firstCap(a.name))) 1.290 + if a.realtype.nativeType('in').endswith('*'): 1.291 + fd.write("%s** a%s" % (a.realtype.nativeType('in').strip('* '), firstCap(a.name))) 1.292 + elif a.realtype.nativeType('in').count("nsAString"): 1.293 + fd.write("nsAString& a%s" % firstCap(a.name)) 1.294 + elif a.realtype.nativeType('in').count("nsACString"): 1.295 + fd.write("nsACString& a%s" % firstCap(a.name)) 1.296 + else: 1.297 + fd.write("%s*a%s" % (a.realtype.nativeType('in'), firstCap(a.name))) 1.298 + fd.write(")\n"); 1.299 + fd.write("{\n"); 1.300 + if a.realtype.nativeType('in').endswith('*'): 1.301 + fd.write(" NS_IF_ADDREF(*a%s = m%s);\n" % (firstCap(a.name), firstCap(a.name))) 1.302 + elif a.realtype.nativeType('in').count("nsAString"): 1.303 + fd.write(" a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name))) 1.304 + elif a.realtype.nativeType('in').count("nsACString"): 1.305 + fd.write(" a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name))) 1.306 + else: 1.307 + fd.write(" *a%s = %s();\n" % (firstCap(a.name), firstCap(a.name))) 1.308 + fd.write(" return NS_OK;\n"); 1.309 + fd.write("}\n\n"); 1.310 + if a.realtype.nativeType('in').count("nsIVariant"): 1.311 + fd.write("void\n") 1.312 + fd.write("%s::Get%s(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval, ErrorResult& aRv)\n" % (classname, firstCap(a.name))) 1.313 + fd.write("{\n") 1.314 + fd.write(" nsresult rv = NS_ERROR_UNEXPECTED;\n") 1.315 + fd.write(" if (!m%s) {\n" % firstCap(a.name)) 1.316 + fd.write(" aRetval.setNull();\n") 1.317 + fd.write(" } else if (!XPCVariant::VariantDataToJS(m%s, &rv, aRetval)) {\n" % (firstCap(a.name))) 1.318 + fd.write(" aRv.Throw(NS_ERROR_FAILURE);\n") 1.319 + fd.write(" }\n") 1.320 + fd.write("}\n\n") 1.321 + 1.322 +def writeAttributeParams(fd, a): 1.323 + if a.realtype.nativeType('in').endswith('*'): 1.324 + fd.write(", %s* a%s" % (a.realtype.nativeType('in').strip('* '), firstCap(a.name))) 1.325 + elif a.realtype.nativeType('in').count("nsAString"): 1.326 + fd.write(", const nsAString& a%s" % firstCap(a.name)) 1.327 + elif a.realtype.nativeType('in').count("nsACString"): 1.328 + fd.write(", const nsACString& a%s" % firstCap(a.name)) 1.329 + else: 1.330 + fd.write(", %s a%s" % (a.realtype.nativeType('in'), firstCap(a.name))) 1.331 + 1.332 +def writeNativeAttributeParams(fd, a, conf): 1.333 + if a.type == "nsIVariant": 1.334 + fd.write(", JS::Value a%s" % firstCap(a.name)); 1.335 + elif a.realtype.nativeType('in').endswith('*'): 1.336 + fd.write(", %s* a%s" % (xpidl_to_native(a.realtype.nativeType('in').strip('* '), conf), firstCap(a.name))) 1.337 + elif a.realtype.nativeType('in').count("nsAString"): 1.338 + fd.write(", const nsAString& a%s" % firstCap(a.name)) 1.339 + elif a.realtype.nativeType('in').count("nsACString"): 1.340 + fd.write(", const nsACString& a%s" % firstCap(a.name)) 1.341 + else: 1.342 + fd.write(", %s a%s" % (a.realtype.nativeType('in'), firstCap(a.name))) 1.343 + 1.344 +def write_cpp(eventname, iface, fd, conf): 1.345 + classname = ("%s" % eventname) 1.346 + basename = getBaseName(iface) 1.347 + attributes = [] 1.348 + ccattributes = [] 1.349 + for member in iface.members: 1.350 + if isinstance(member, xpidl.Attribute): 1.351 + attributes.append(member) 1.352 + if (member.realtype.nativeType('in').endswith('*')): 1.353 + ccattributes.append(member); 1.354 + 1.355 + baseinterfaces = [] 1.356 + baseiface = iface.idl.getName(iface.base, iface.location) 1.357 + while baseiface.name != "nsIDOMEvent": 1.358 + baseinterfaces.append(baseiface) 1.359 + baseiface = baseiface.idl.getName(baseiface.base, baseiface.location) 1.360 + baseinterfaces.reverse() 1.361 + 1.362 + baseattributes = [] 1.363 + for baseiface in baseinterfaces: 1.364 + for member in baseiface.members: 1.365 + if isinstance(member, xpidl.Attribute): 1.366 + baseattributes.append(member) 1.367 + 1.368 + allattributes = [] 1.369 + allattributes.extend(baseattributes); 1.370 + allattributes.extend(attributes); 1.371 + 1.372 + fd.write("namespace mozilla {\n") 1.373 + fd.write("namespace dom {\n\n") 1.374 + 1.375 + fd.write("%s::%s(mozilla::dom::EventTarget* aOwner, " % (classname, classname)) 1.376 + fd.write("nsPresContext* aPresContext, mozilla::WidgetEvent* aEvent)\n"); 1.377 + fd.write(": %s(aOwner, aPresContext, aEvent)" % basename) 1.378 + for a in attributes: 1.379 + fd.write(",\n m%s(%s)" % (firstCap(a.name), init_value(a))) 1.380 + fd.write("\n{\n") 1.381 + fd.write("}\n\n") 1.382 + 1.383 + fd.write("%s::~%s() {}\n\n" % (classname, classname)) 1.384 + 1.385 + fd.write("NS_IMPL_CYCLE_COLLECTION_CLASS(%s)\n" % (classname)) 1.386 + fd.write("NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(%s, %s)\n" % (classname, basename)) 1.387 + for c in ccattributes: 1.388 + fd.write(" NS_IMPL_CYCLE_COLLECTION_UNLINK(m%s)\n" % firstCap(c.name)) 1.389 + fd.write("NS_IMPL_CYCLE_COLLECTION_UNLINK_END\n\n"); 1.390 + fd.write("NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(%s, %s)\n" % (classname, basename)) 1.391 + for c in ccattributes: 1.392 + fd.write(" NS_IMPL_CYCLE_COLLECTION_TRAVERSE(m%s)\n" % firstCap(c.name)) 1.393 + fd.write("NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END\n\n"); 1.394 + 1.395 + fd.write("NS_IMPL_ADDREF_INHERITED(%s, %s)\n" % (classname, basename)) 1.396 + fd.write("NS_IMPL_RELEASE_INHERITED(%s, %s)\n\n" % (classname, basename)) 1.397 + 1.398 + fd.write("NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(%s)\n" % classname) 1.399 + fd.write(" NS_INTERFACE_MAP_ENTRY(nsIDOM%s)\n" % eventname) 1.400 + fd.write("NS_INTERFACE_MAP_END_INHERITING(%s)\n\n" % basename) 1.401 + 1.402 + hasVariant = False 1.403 + for a in allattributes: 1.404 + if a.type == "nsIVariant": 1.405 + hasVariant = True 1.406 + break; 1.407 + 1.408 + fd.write("already_AddRefed<%s>\n" % eventname) 1.409 + fd.write("%s::Constructor(const GlobalObject& aGlobal, " % eventname) 1.410 + if hasVariant: 1.411 + fd.write("JSContext* aCx, "); 1.412 + fd.write("const nsAString& aType, ") 1.413 + fd.write("const %sInit& aParam, " % eventname) 1.414 + fd.write("ErrorResult& aRv)\n") 1.415 + fd.write("{\n") 1.416 + fd.write(" nsCOMPtr<mozilla::dom::EventTarget> t = do_QueryInterface(aGlobal.GetAsSupports());\n") 1.417 + fd.write(" nsRefPtr<%s> e = new %s(t, nullptr, nullptr);\n" % (eventname, eventname)) 1.418 + fd.write(" bool trusted = e->Init(t);\n") 1.419 + fd.write(" e->Init%s(" % eventname) 1.420 + if hasVariant: 1.421 + fd.write("aCx, "); 1.422 + fd.write("aType, aParam.mBubbles, aParam.mCancelable") 1.423 + for a in allattributes: 1.424 + fd.write(", aParam.m%s" % firstCap(a.name)) 1.425 + fd.write(", aRv);\n") 1.426 + fd.write(" e->SetTrusted(trusted);\n") 1.427 + fd.write(" return e.forget();\n") 1.428 + fd.write("}\n\n") 1.429 + 1.430 + fd.write("NS_IMETHODIMP\n") 1.431 + fd.write("%s::Init%s(" % (classname, eventname)) 1.432 + fd.write("const nsAString& aType, bool aCanBubble, bool aCancelable") 1.433 + for a in allattributes: 1.434 + writeAttributeParams(fd, a) 1.435 + fd.write(")\n{\n") 1.436 + fd.write(" nsresult rv = %s::Init%s(aType, aCanBubble, aCancelable" % (basename, ("%s" % iface.base[6:]))) 1.437 + for a in baseattributes: 1.438 + fd.write(", a%s" % firstCap(a.name)) 1.439 + fd.write(");\n"); 1.440 + fd.write(" NS_ENSURE_SUCCESS(rv, rv);\n") 1.441 + for a in attributes: 1.442 + if a.realtype.nativeType("in").count("nsAString"): 1.443 + fd.write(" if (!m%s.Assign(a%s, fallible_t())) {\n" % (firstCap(a.name), firstCap(a.name))) 1.444 + fd.write(" return NS_ERROR_OUT_OF_MEMORY;\n") 1.445 + fd.write(" }\n") 1.446 + else: 1.447 + fd.write(" m%s = a%s;\n" % (firstCap(a.name), firstCap(a.name))) 1.448 + fd.write(" return NS_OK;\n") 1.449 + fd.write("}\n\n") 1.450 + 1.451 + fd.write("void\n") 1.452 + fd.write("%s::Init%s(" % (classname, eventname)) 1.453 + if hasVariant: 1.454 + fd.write("JSContext* aCx, ") 1.455 + fd.write("const nsAString& aType, bool aCanBubble, bool aCancelable") 1.456 + for a in allattributes: 1.457 + writeNativeAttributeParams(fd, a, conf) 1.458 + fd.write(", ErrorResult& aRv") 1.459 + fd.write(")\n") 1.460 + fd.write("{\n"); 1.461 + for a in allattributes: 1.462 + if a.type == "nsIVariant": 1.463 + fd.write(" nsCOMPtr<nsIVariant> %s = dont_AddRef(XPCVariant::newVariant(aCx, a%s));\n" % (a.name, firstCap(a.name))) 1.464 + fd.write(" if (!%s) {\n" % a.name) 1.465 + fd.write(" aRv.Throw(NS_ERROR_FAILURE);\n") 1.466 + fd.write(" return;\n") 1.467 + fd.write(" }\n") 1.468 + elif a.realtype.nativeType('in').endswith('*'): 1.469 + xpidl_t = a.realtype.nativeType('in').strip('* ') 1.470 + native_t = xpidl_to_native(xpidl_t, conf) 1.471 + if xpidl_t != native_t: 1.472 + fd.write(" nsCOMPtr<%s> %s = do_QueryInterface(static_cast<%s*>(a%s));\n" % (xpidl_t, a.name, xpidl_to_canonical(xpidl_t, conf), firstCap(a.name))) 1.473 + fd.write(" aRv = Init%s(" % classname); 1.474 + fd.write("aType, aCanBubble, aCancelable") 1.475 + for a in allattributes: 1.476 + if a.realtype.nativeType('in').endswith('*'): 1.477 + xpidl_t = a.realtype.nativeType('in').strip('* ') 1.478 + native_t = xpidl_to_native(xpidl_t, conf) 1.479 + if xpidl_t != native_t or a.type == "nsIVariant": 1.480 + fd.write(", %s" % a.name) 1.481 + continue 1.482 + fd.write(", a%s" % firstCap(a.name)) 1.483 + fd.write(");\n}\n\n"); 1.484 + 1.485 + for a in attributes: 1.486 + writeAttributeGetter(fd, classname, a) 1.487 + 1.488 + fd.write("} // namespace dom\n") 1.489 + fd.write("} // namespace mozilla\n\n") 1.490 + 1.491 + fd.write("nsresult\n") 1.492 + fd.write("NS_NewDOM%s(nsIDOMEvent** aInstance, " % eventname) 1.493 + fd.write("mozilla::dom::EventTarget* aOwner, nsPresContext* aPresContext = nullptr, mozilla::WidgetEvent* aEvent = nullptr)\n") 1.494 + fd.write("{\n") 1.495 + fd.write(" mozilla::dom::%s* it = new mozilla::dom::%s(aOwner, aPresContext, aEvent);\n" % (classname, classname)) 1.496 + fd.write(" NS_ADDREF(it);\n") 1.497 + fd.write(" *aInstance = static_cast<mozilla::dom::Event*>(it);\n") 1.498 + fd.write(" return NS_OK;\n"); 1.499 + fd.write("}\n\n") 1.500 + 1.501 +def toWebIDLType(attribute, inType=False, onlyInterface=False): 1.502 + if attribute.type == "nsIVariant": 1.503 + return "any"; 1.504 + if attribute.type == "nsISupports": 1.505 + return "%s%s" % (attribute.type, "" if onlyInterface else "?") 1.506 + if attribute.type.count("nsIDOM"): 1.507 + return "%s%s" % (attribute.type[6:], "" if onlyInterface else "?") 1.508 + if attribute.type.count("nsI"): 1.509 + return "%s%s" % (attribute.type[3:], "" if onlyInterface else "?") 1.510 + if attribute.realtype.nativeType('in').endswith('*') or attribute.realtype.nativeType('in').count("nsAString"): 1.511 + return "%s%s" % (attribute.type, "" if onlyInterface else "?") 1.512 + return attribute.type 1.513 + 1.514 +def write_webidl(eventname, iface, fd, conf, idl): 1.515 + basename = ("%s" % iface.base[6:]) 1.516 + attributes = [] 1.517 + ccattributes = [] 1.518 + consts = [] 1.519 + hasInit = False 1.520 + initMethod = "init%s" % eventname; 1.521 + for member in iface.members: 1.522 + if isinstance(member, xpidl.Attribute): 1.523 + attributes.append(member) 1.524 + if (member.realtype.nativeType('in').endswith('*')): 1.525 + ccattributes.append(member); 1.526 + elif isinstance(member, xpidl.Method) and member.name == initMethod: 1.527 + if not member.noscript and not member.notxpcom: 1.528 + hasInit = True 1.529 + elif isinstance(member, xpidl.ConstMember): 1.530 + consts.append(member); 1.531 + else: 1.532 + raise BaseException("Unsupported idl member %s::%s" % (eventname, member.name)) 1.533 + 1.534 + baseinterfaces = [] 1.535 + baseiface = iface.idl.getName(iface.base, iface.location) 1.536 + while baseiface.name != "nsIDOMEvent": 1.537 + baseinterfaces.append(baseiface) 1.538 + baseiface = baseiface.idl.getName(baseiface.base, baseiface.location) 1.539 + baseinterfaces.reverse() 1.540 + 1.541 + allattributes = [] 1.542 + for baseiface in baseinterfaces: 1.543 + for member in baseiface.members: 1.544 + if isinstance(member, xpidl.Attribute): 1.545 + allattributes.append(member) 1.546 + allattributes.extend(attributes) 1.547 + 1.548 + fd.write( 1.549 +"""/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.550 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.551 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.552 + * You can obtain one at http://mozilla.org/MPL/2.0/. 1.553 + */ 1.554 +""") 1.555 + 1.556 + neededInterfaces = [] 1.557 + for a in attributes: 1.558 + if a.realtype.nativeType('in').endswith('*'): 1.559 + nativeType = a.realtype.nativeType('in').strip('* ') 1.560 + mappingForWebIDL = False 1.561 + for xp in conf.xpidl_to_native: 1.562 + if xp[0] == nativeType: 1.563 + mappingForWebIDL = True 1.564 + break; 1.565 + if not mappingForWebIDL: 1.566 + webidlType = toWebIDLType(a, False, True) 1.567 + if (not webidlType in neededInterfaces and webidlType != "any"): 1.568 + neededInterfaces.append(webidlType); 1.569 + 1.570 + for i in neededInterfaces: 1.571 + fd.write("interface %s;\n" % i) 1.572 + 1.573 + fd.write("\n"); 1.574 + fd.write("[Constructor(DOMString type, optional %sInit eventInitDict), HeaderFile=\"GeneratedEventClasses.h\"]\n" % eventname); 1.575 + fd.write("interface %s : %s\n" % (eventname, basename)) 1.576 + fd.write("{\n") 1.577 + 1.578 + for c in consts: 1.579 + fd.write(" const %s %s = %s;\n" % (c.type, c.name, c.getValue())) 1.580 + if len(consts): 1.581 + fd.write("\n") 1.582 + 1.583 + for a in attributes: 1.584 + if a.realtype.nativeType('in').count("nsIVariant"): 1.585 + fd.write(" [Throws]\n") 1.586 + fd.write(" readonly attribute %s %s;\n" % (toWebIDLType(a), a.name)) 1.587 + elif a.realtype.nativeType('in').endswith('*') or a.realtype.nativeType('in').count("nsAString"): 1.588 + fd.write(" readonly attribute %s %s;\n" % (toWebIDLType(a), a.name)) 1.589 + else: 1.590 + fd.write(" readonly attribute %s %s;\n" % (a.type, a.name)) 1.591 + if hasInit: 1.592 + fd.write("\n [Throws]\n") 1.593 + m = " void %s(" % initMethod 1.594 + fd.write(m) 1.595 + indent = "".join(" " for i in range(len(m))) 1.596 + indent = ",\n%s" % indent 1.597 + fd.write("DOMString type") 1.598 + fd.write(indent); 1.599 + fd.write("boolean canBubble") 1.600 + fd.write(indent); 1.601 + fd.write("boolean cancelable") 1.602 + for a in baseattributes + attributes: 1.603 + fd.write(indent); 1.604 + fd.write("%s %s" % (toWebIDLType(a, True), a.name)) 1.605 + fd.write(");\n"); 1.606 + fd.write("};\n\n") 1.607 + 1.608 + dname = "%sInit" % eventname 1.609 + for p in idl.productions: 1.610 + if p.kind == "dictionary" and p.name == dname: 1.611 + fd.write("dictionary %s : %sInit\n" % (dname, basename)) 1.612 + fd.write("{\n") 1.613 + # We want to keep the same ordering what interface has. 1.614 + for ifaceattribute in attributes: 1.615 + for member in p.members: 1.616 + if member.name == ifaceattribute.name: 1.617 + a = member 1.618 + if a.realtype.nativeType('in').endswith('*'): 1.619 + fd.write(" %s %s = null;\n" % (toWebIDLType(a, True), a.name)) 1.620 + elif a.realtype.nativeType('in').count("nsAString"): 1.621 + if a.defvalue is None: 1.622 + if a.nullable: 1.623 + fd.write(" %s? %s = null;\n" % (a.type, a.name)) 1.624 + else: 1.625 + fd.write(" %s %s = \"\";\n" % (a.type, a.name)) 1.626 + else: 1.627 + if a.nullable: 1.628 + fd.write(" %s? %s = \"%s\";\n" % (a.type, a.name, a.defvalue)) 1.629 + else: 1.630 + fd.write(" %s %s = \"%s\";\n" % (a.type, a.name, a.defvalue)) 1.631 + else: 1.632 + if a.defvalue is None: 1.633 + if a.type == "boolean": 1.634 + fd.write(" %s %s = false;\n" % (a.type, a.name)) 1.635 + else: 1.636 + fd.write(" %s %s = 0;\n" % (a.type, a.name)) 1.637 + # Infinity is not supported by all the types, but 1.638 + # WebIDL parser will then complain about the wrong values. 1.639 + elif a.defvalue == "Infinity": 1.640 + fd.write(" unrestricted %s %s = Infinity;\n" % (a.type, a.name)) 1.641 + elif a.defvalue == "-Infinity": 1.642 + fd.write(" unrestricted %s %s = -Infinity;\n" % (a.type, a.name)) 1.643 + else: 1.644 + fd.write(" %s %s = %s;\n" % (a.type, a.name, a.defvalue)) 1.645 + continue 1.646 + fd.write("};\n") 1.647 + return 1.648 + 1.649 + # There is no dictionary defined in the .idl file. Generate one based on 1.650 + # the interface. 1.651 + fd.write("dictionary %s : %sInit\n" % (dname, basename)) 1.652 + fd.write("{\n") 1.653 + for a in attributes: 1.654 + if a.realtype.nativeType('in').endswith('*'): 1.655 + fd.write(" %s %s = null;\n" % (toWebIDLType(a, True), a.name)) 1.656 + elif a.realtype.nativeType('in').count("nsAString"): 1.657 + fd.write(" %s? %s = \"\";\n" % (a.type, a.name)) 1.658 + elif a.type == "boolean": 1.659 + fd.write(" %s %s = false;\n" % (a.type, a.name)) 1.660 + else: 1.661 + fd.write(" %s %s = 0;\n" % (a.type, a.name)) 1.662 + fd.write("};\n") 1.663 + 1.664 +def print_webidl_file(idl, fd, conf, eventname): 1.665 + for p in idl.productions: 1.666 + if p.kind == 'interface': 1.667 + write_webidl(eventname, p, fd, conf, idl) 1.668 + 1.669 +def xpidl_to_native(xpidl, conf): 1.670 + for x in conf.xpidl_to_native: 1.671 + if x[0] == xpidl: 1.672 + return x[1] 1.673 + return xpidl 1.674 + 1.675 +def xpidl_to_canonical(xpidl, conf): 1.676 + for x in conf.xpidl_to_native: 1.677 + if x[0] == xpidl: 1.678 + return x[2] 1.679 + return xpidl 1.680 + 1.681 +def native_to_xpidl(native, conf): 1.682 + for x in conf.xpidl_to_native: 1.683 + if x[1] == native: 1.684 + return x[0] 1.685 + return native 1.686 + 1.687 +def print_webidl_files(webidlDir, conf): 1.688 + for e in conf.simple_events: 1.689 + idl = loadEventIDL(p, options.incdirs, e) 1.690 + webidl = "%s/%s.webidl" % (webidlDir, e) 1.691 + if not os.path.exists(webidl): 1.692 + fd = open(webidl, 'w') 1.693 + print_webidl_file(idl, fd, conf, e) 1.694 + fd.close(); 1.695 + 1.696 +if __name__ == '__main__': 1.697 + from optparse import OptionParser 1.698 + o = OptionParser(usage="usage: %prog [options] configfile") 1.699 + o.add_option('-I', action='append', dest='incdirs', default=['.'], 1.700 + help="Directory to search for imported files") 1.701 + o.add_option('-o', "--stub-output", 1.702 + type='string', dest='stub_output', default=None, 1.703 + help="Quick stub C++ source output file", metavar="FILE") 1.704 + o.add_option('--header-output', type='string', default=None, 1.705 + help="Quick stub header output file", metavar="FILE") 1.706 + o.add_option('--makedepend-output', type='string', default=None, 1.707 + help="gnumake dependencies output file", metavar="FILE") 1.708 + o.add_option('--cachedir', dest='cachedir', default=None, 1.709 + help="Directory in which to cache lex/parse tables.") 1.710 + o.add_option('--class-declarations', type='string', default=None, 1.711 + help="Class declarations", metavar="FILE") 1.712 + o.add_option('--webidltarget', dest='webidltarget', default=None, 1.713 + help="Directory in which to store generated WebIDL files.") 1.714 + (options, filenames) = o.parse_args() 1.715 + if len(filenames) != 1: 1.716 + o.error("Exactly one config filename is needed.") 1.717 + filename = filenames[0] 1.718 + 1.719 + if options.cachedir is not None: 1.720 + if not os.path.isdir(options.cachedir): 1.721 + os.mkdir(options.cachedir) 1.722 + sys.path.append(options.cachedir) 1.723 + 1.724 + # Instantiate the parser. 1.725 + p = xpidl.IDLParser(outputdir=options.cachedir) 1.726 + 1.727 + conf = readConfigFile(filename) 1.728 + 1.729 + if options.header_output is not None: 1.730 + outfd = open(options.header_output, 'w') 1.731 + print_header_file(outfd, conf) 1.732 + outfd.close() 1.733 + if options.class_declarations is not None: 1.734 + outfd = open(options.class_declarations, 'w') 1.735 + print_classes_file(outfd, conf) 1.736 + outfd.close() 1.737 + if options.stub_output is not None: 1.738 + makeutils.targets.append(options.stub_output) 1.739 + outfd = open(options.stub_output, 'w') 1.740 + print_cpp_file(outfd, conf) 1.741 + outfd.close() 1.742 + if options.makedepend_output is not None: 1.743 + makeutils.writeMakeDependOutput(options.makedepend_output) 1.744 + 1.745 + if options.webidltarget is not None: 1.746 + print_webidl_files(options.webidltarget, conf) 1.747 +