js/xpconnect/src/event_impl_gen.py

changeset 0
6474c204b198
     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 +

mercurial