js/xpconnect/src/event_impl_gen.py

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:24a903d52bb5
1 #!/usr/bin/env python
2 # header.py - Generate C++ header files from IDL.
3 #
4 # This Source Code Form is subject to the terms of the Mozilla Public
5 # License, v. 2.0. If a copy of the MPL was not distributed with this
6 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
8 import sys, os, xpidl, makeutils
9
10 def strip_end(text, suffix):
11 if not text.endswith(suffix):
12 return text
13 return text[:-len(suffix)]
14
15 def findIDL(includePath, interfaceFileName):
16 for d in includePath:
17 # Not os.path.join: we need a forward slash even on Windows because
18 # this filename ends up in makedepend output.
19 path = d + '/' + interfaceFileName
20 if os.path.exists(path):
21 return path
22 raise BaseException("No IDL file found for interface %s "
23 "in include path %r"
24 % (interfaceFileName, includePath))
25
26 eventFileNameToIdl = {};
27
28 def loadIDL(parser, includePath, filename):
29 global eventFileNameToIdl
30 if filename in eventFileNameToIdl:
31 return eventFileNameToIdl[filename]
32
33 idlFile = findIDL(includePath, filename)
34 if not idlFile in makeutils.dependencies:
35 makeutils.dependencies.append(idlFile)
36 idl = p.parse(open(idlFile).read(), idlFile)
37 idl.resolve(includePath, p)
38 eventFileNameToIdl[filename] = idl
39 return idl
40
41 def loadEventIDL(parser, includePath, eventname):
42 eventidl = ("nsIDOM%s.idl" % eventname)
43 return loadIDL(parser, includePath, eventidl)
44
45 class Configuration:
46 def __init__(self, filename):
47 config = {}
48 execfile(filename, config)
49 self.simple_events = config.get('simple_events', [])
50 self.special_includes = config.get('special_includes', [])
51 self.exclude_automatic_type_include = config.get('exclude_automatic_type_include', [])
52 self.xpidl_to_native = config.get('xpidl_to_native', [])
53
54 def readConfigFile(filename):
55 return Configuration(filename)
56
57 def firstCap(str):
58 return str[0].upper() + str[1:]
59
60 def getBaseName(iface):
61 return ("%s" % iface.base[6:])
62
63 def print_header_file(fd, conf):
64 fd.write("#ifndef _gen_mozilla_idl_generated_events_h_\n"
65 "#define _gen_mozilla_idl_generated_events_h_\n\n")
66 fd.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n")
67 fd.write("#include \"nscore.h\"\n")
68 fd.write("class nsIDOMEvent;\n")
69 fd.write("class nsPresContext;\n")
70 fd.write("namespace mozilla {\n");
71 fd.write("class WidgetEvent;\n")
72 fd.write("namespace dom {\n");
73 fd.write("class EventTarget;\n")
74 fd.write("}\n");
75 fd.write("}\n\n");
76 for e in conf.simple_events:
77 fd.write("nsresult\n")
78 fd.write("NS_NewDOM%s(nsIDOMEvent** aInstance, " % e)
79 fd.write("mozilla::dom::EventTarget* aOwner, ")
80 fd.write("nsPresContext* aPresContext, mozilla::WidgetEvent* aEvent);\n")
81
82 fd.write("\n#endif\n")
83
84 def print_classes_file(fd, conf):
85 fd.write("#ifndef _gen_mozilla_idl_generated_event_declarations_h_\n")
86 fd.write("#define _gen_mozilla_idl_generated_event_declarations_h_\n\n")
87
88 fd.write("#include \"mozilla/dom/Event.h\"\n");
89 includes = []
90 for s in conf.special_includes:
91 if not s in includes:
92 includes.append(strip_end(s, ".h"))
93
94 for e in conf.simple_events:
95 if not e in includes:
96 includes.append(("nsIDOM%s" % e))
97
98 attrnames = []
99 for e in conf.simple_events:
100 idl = loadEventIDL(p, options.incdirs, e)
101 collect_names_and_non_primitive_attribute_types(idl, attrnames, includes)
102
103 for c in includes:
104 if not c in conf.exclude_automatic_type_include:
105 fd.write("#include \"%s.h\"\n" % c)
106
107 for e in conf.simple_events:
108 fd.write('#include "mozilla/dom/%sBinding.h"\n' % e);
109
110 fd.write("namespace mozilla {\n")
111 fd.write("namespace dom {\n")
112 for e in conf.simple_events:
113 idl = loadEventIDL(p, options.incdirs, e)
114 for pr in idl.productions:
115 if pr.kind == 'interface':
116 print_class_declaration(e, pr, fd, conf)
117 fd.write("} // namespace dom\n")
118 fd.write("} // namespace mozilla\n\n")
119 fd.write("#endif\n");
120
121 def print_class_declaration(eventname, iface, fd, conf):
122 classname = ("%s" % eventname)
123 basename = getBaseName(iface)
124 attributes = []
125 ccattributes = []
126 for member in iface.members:
127 if isinstance(member, xpidl.Attribute):
128 attributes.append(member)
129 if (member.realtype.nativeType('in').endswith('*')):
130 ccattributes.append(member);
131
132 baseinterfaces = []
133 baseiface = iface.idl.getName(iface.base, iface.location)
134 while baseiface.name != "nsIDOMEvent":
135 baseinterfaces.append(baseiface)
136 baseiface = baseiface.idl.getName(baseiface.base, baseiface.location)
137 baseinterfaces.reverse()
138
139 allattributes = []
140 for baseiface in baseinterfaces:
141 for member in baseiface.members:
142 if isinstance(member, xpidl.Attribute):
143 allattributes.append(member)
144 allattributes.extend(attributes);
145
146 fd.write("\nclass %s MOZ_FINAL : public %s, public %s\n" % (classname, basename, iface.name))
147 fd.write("{\n")
148 fd.write("public:\n")
149 fd.write(" %s(mozilla::dom::EventTarget* aOwner, " % classname)
150 fd.write("nsPresContext* aPresContext = nullptr, mozilla::WidgetEvent* aEvent = nullptr);\n");
151 fd.write(" virtual ~%s();\n\n" % classname)
152 fd.write(" NS_DECL_ISUPPORTS_INHERITED\n")
153 fd.write(" NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(%s, %s)\n" % (classname, basename))
154 fd.write(" NS_FORWARD_TO_EVENT\n")
155
156 for baseiface in baseinterfaces:
157 baseimpl = ("%s" % baseiface.name[6:])
158 fd.write(" NS_FORWARD_%s(%s::)\n" % (baseiface.name.upper(), baseimpl))
159
160 fd.write(" NS_DECL_%s\n" % iface.name.upper())
161
162 hasVariant = False
163 for a in allattributes:
164 if a.type == "nsIVariant":
165 hasVariant = True
166 break;
167 fd.write(" static already_AddRefed<%s> Constructor(const GlobalObject& aGlobal, " % eventname)
168 if hasVariant:
169 fd.write("JSContext* aCx, ")
170 fd.write("const nsAString& aType, ")
171 fd.write("const %sInit& aParam, " % eventname)
172 fd.write("ErrorResult& aRv);\n\n")
173
174 fd.write(" virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE\n")
175 fd.write(" {\n")
176 fd.write(" return mozilla::dom::%sBinding::Wrap(aCx, this);\n" % eventname)
177 fd.write(" }\n\n")
178
179 for a in attributes:
180 """xpidl methods take care of string member variables!"""
181 firstCapName = firstCap(a.name)
182 cleanNativeType = a.realtype.nativeType('in').strip('* ')
183 if a.realtype.nativeType('in').count("nsAString"):
184 continue
185 elif a.realtype.nativeType('in').count("nsIVariant"):
186 fd.write(" void Get%s(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval, ErrorResult& aRv);\n\n" % firstCapName);
187 elif a.realtype.nativeType('in').endswith('*'):
188 fd.write(" already_AddRefed<%s> Get%s()\n" % (xpidl_to_native(cleanNativeType, conf), firstCapName))
189 fd.write(" {\n");
190 fd.write(" nsCOMPtr<%s> %s = do_QueryInterface(m%s);\n" % (xpidl_to_canonical(cleanNativeType, conf), a.name, firstCapName))
191 fd.write(" return %s.forget().downcast<%s>();\n" % (a.name, xpidl_to_native(cleanNativeType, conf)))
192 fd.write(" }\n\n");
193 else:
194 fd.write(" %s %s()\n" % (cleanNativeType, firstCapName))
195 fd.write(" {\n");
196 fd.write(" return m%s;\n" % firstCapName)
197 fd.write(" }\n\n");
198
199 fd.write(" void ")
200 fd.write("Init%s(" % eventname)
201 if hasVariant:
202 fd.write("JSContext* aCx, ")
203 fd.write("const nsAString& aType, bool aCanBubble, bool aCancelable")
204 for a in allattributes:
205 writeNativeAttributeParams(fd, a, conf)
206 fd.write(", ErrorResult& aRv);\n\n")
207
208 fd.write("protected:\n")
209 for a in attributes:
210 fd.write(" %s\n" % attributeVariableTypeAndName(a))
211 fd.write("};\n")
212
213 def collect_names_and_non_primitive_attribute_types(idl, attrnames, forwards):
214 for p in idl.productions:
215 if p.kind == 'interface' or p.kind == 'dictionary':
216 interfaces = []
217 base = p.base
218 baseiface = p
219 while base is not None:
220 baseiface = baseiface.idl.getName(baseiface.base, baseiface.location)
221 interfaces.append(baseiface)
222 base = baseiface.base
223
224 interfaces.reverse()
225 interfaces.append(p)
226
227 for iface in interfaces:
228 collect_names_and_non_primitive_attribute_types_from_interface(iface, attrnames, forwards)
229
230 def collect_names_and_non_primitive_attribute_types_from_interface(iface, attrnames, forwards):
231 for member in iface.members:
232 if isinstance(member, xpidl.Attribute):
233 if not member.name in attrnames:
234 attrnames.append(member.name)
235 if member.realtype.nativeType('in').endswith('*'):
236 t = member.realtype.nativeType('in').strip('* ')
237 if not t in forwards:
238 forwards.append(t)
239
240 def print_cpp(idl, fd, conf, eventname):
241 for p in idl.productions:
242 if p.kind == 'interface':
243 write_cpp(eventname, p, fd, conf)
244
245 def print_cpp_file(fd, conf):
246 fd.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n")
247 fd.write('#include "GeneratedEventClasses.h"\n')
248 fd.write('#include "xpcprivate.h"\n');
249 fd.write('#include "mozilla/dom/Event.h"\n');
250 fd.write('#include "mozilla/dom/EventTarget.h"\n');
251
252 for e in conf.simple_events:
253 idl = loadEventIDL(p, options.incdirs, e)
254 print_cpp(idl, fd, conf, e)
255
256 def init_value(attribute):
257 realtype = attribute.realtype.nativeType('in')
258 realtype = realtype.strip(' ')
259 if realtype.endswith('*'):
260 return "nullptr"
261 if realtype == "bool":
262 return "false"
263 if realtype.count("nsAString"):
264 return ""
265 if realtype.count("nsACString"):
266 return ""
267 if realtype.count("JS::Value"):
268 raise BaseException("JS::Value not supported in simple events!")
269 return "0"
270
271 def attributeVariableTypeAndName(a):
272 if a.realtype.nativeType('in').endswith('*'):
273 l = ["nsCOMPtr<%s> m%s;" % (a.realtype.nativeType('in').strip('* '),
274 firstCap(a.name))]
275 elif a.realtype.nativeType('in').count("nsAString"):
276 l = ["nsString m%s;" % firstCap(a.name)]
277 elif a.realtype.nativeType('in').count("nsACString"):
278 l = ["nsCString m%s;" % firstCap(a.name)]
279 else:
280 l = ["%sm%s;" % (a.realtype.nativeType('in'),
281 firstCap(a.name))]
282 return ", ".join(l)
283
284 def writeAttributeGetter(fd, classname, a):
285 fd.write("NS_IMETHODIMP\n")
286 fd.write("%s::Get%s(" % (classname, firstCap(a.name)))
287 if a.realtype.nativeType('in').endswith('*'):
288 fd.write("%s** a%s" % (a.realtype.nativeType('in').strip('* '), firstCap(a.name)))
289 elif a.realtype.nativeType('in').count("nsAString"):
290 fd.write("nsAString& a%s" % firstCap(a.name))
291 elif a.realtype.nativeType('in').count("nsACString"):
292 fd.write("nsACString& a%s" % firstCap(a.name))
293 else:
294 fd.write("%s*a%s" % (a.realtype.nativeType('in'), firstCap(a.name)))
295 fd.write(")\n");
296 fd.write("{\n");
297 if a.realtype.nativeType('in').endswith('*'):
298 fd.write(" NS_IF_ADDREF(*a%s = m%s);\n" % (firstCap(a.name), firstCap(a.name)))
299 elif a.realtype.nativeType('in').count("nsAString"):
300 fd.write(" a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name)))
301 elif a.realtype.nativeType('in').count("nsACString"):
302 fd.write(" a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name)))
303 else:
304 fd.write(" *a%s = %s();\n" % (firstCap(a.name), firstCap(a.name)))
305 fd.write(" return NS_OK;\n");
306 fd.write("}\n\n");
307 if a.realtype.nativeType('in').count("nsIVariant"):
308 fd.write("void\n")
309 fd.write("%s::Get%s(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval, ErrorResult& aRv)\n" % (classname, firstCap(a.name)))
310 fd.write("{\n")
311 fd.write(" nsresult rv = NS_ERROR_UNEXPECTED;\n")
312 fd.write(" if (!m%s) {\n" % firstCap(a.name))
313 fd.write(" aRetval.setNull();\n")
314 fd.write(" } else if (!XPCVariant::VariantDataToJS(m%s, &rv, aRetval)) {\n" % (firstCap(a.name)))
315 fd.write(" aRv.Throw(NS_ERROR_FAILURE);\n")
316 fd.write(" }\n")
317 fd.write("}\n\n")
318
319 def writeAttributeParams(fd, a):
320 if a.realtype.nativeType('in').endswith('*'):
321 fd.write(", %s* a%s" % (a.realtype.nativeType('in').strip('* '), firstCap(a.name)))
322 elif a.realtype.nativeType('in').count("nsAString"):
323 fd.write(", const nsAString& a%s" % firstCap(a.name))
324 elif a.realtype.nativeType('in').count("nsACString"):
325 fd.write(", const nsACString& a%s" % firstCap(a.name))
326 else:
327 fd.write(", %s a%s" % (a.realtype.nativeType('in'), firstCap(a.name)))
328
329 def writeNativeAttributeParams(fd, a, conf):
330 if a.type == "nsIVariant":
331 fd.write(", JS::Value a%s" % firstCap(a.name));
332 elif a.realtype.nativeType('in').endswith('*'):
333 fd.write(", %s* a%s" % (xpidl_to_native(a.realtype.nativeType('in').strip('* '), conf), firstCap(a.name)))
334 elif a.realtype.nativeType('in').count("nsAString"):
335 fd.write(", const nsAString& a%s" % firstCap(a.name))
336 elif a.realtype.nativeType('in').count("nsACString"):
337 fd.write(", const nsACString& a%s" % firstCap(a.name))
338 else:
339 fd.write(", %s a%s" % (a.realtype.nativeType('in'), firstCap(a.name)))
340
341 def write_cpp(eventname, iface, fd, conf):
342 classname = ("%s" % eventname)
343 basename = getBaseName(iface)
344 attributes = []
345 ccattributes = []
346 for member in iface.members:
347 if isinstance(member, xpidl.Attribute):
348 attributes.append(member)
349 if (member.realtype.nativeType('in').endswith('*')):
350 ccattributes.append(member);
351
352 baseinterfaces = []
353 baseiface = iface.idl.getName(iface.base, iface.location)
354 while baseiface.name != "nsIDOMEvent":
355 baseinterfaces.append(baseiface)
356 baseiface = baseiface.idl.getName(baseiface.base, baseiface.location)
357 baseinterfaces.reverse()
358
359 baseattributes = []
360 for baseiface in baseinterfaces:
361 for member in baseiface.members:
362 if isinstance(member, xpidl.Attribute):
363 baseattributes.append(member)
364
365 allattributes = []
366 allattributes.extend(baseattributes);
367 allattributes.extend(attributes);
368
369 fd.write("namespace mozilla {\n")
370 fd.write("namespace dom {\n\n")
371
372 fd.write("%s::%s(mozilla::dom::EventTarget* aOwner, " % (classname, classname))
373 fd.write("nsPresContext* aPresContext, mozilla::WidgetEvent* aEvent)\n");
374 fd.write(": %s(aOwner, aPresContext, aEvent)" % basename)
375 for a in attributes:
376 fd.write(",\n m%s(%s)" % (firstCap(a.name), init_value(a)))
377 fd.write("\n{\n")
378 fd.write("}\n\n")
379
380 fd.write("%s::~%s() {}\n\n" % (classname, classname))
381
382 fd.write("NS_IMPL_CYCLE_COLLECTION_CLASS(%s)\n" % (classname))
383 fd.write("NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(%s, %s)\n" % (classname, basename))
384 for c in ccattributes:
385 fd.write(" NS_IMPL_CYCLE_COLLECTION_UNLINK(m%s)\n" % firstCap(c.name))
386 fd.write("NS_IMPL_CYCLE_COLLECTION_UNLINK_END\n\n");
387 fd.write("NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(%s, %s)\n" % (classname, basename))
388 for c in ccattributes:
389 fd.write(" NS_IMPL_CYCLE_COLLECTION_TRAVERSE(m%s)\n" % firstCap(c.name))
390 fd.write("NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END\n\n");
391
392 fd.write("NS_IMPL_ADDREF_INHERITED(%s, %s)\n" % (classname, basename))
393 fd.write("NS_IMPL_RELEASE_INHERITED(%s, %s)\n\n" % (classname, basename))
394
395 fd.write("NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(%s)\n" % classname)
396 fd.write(" NS_INTERFACE_MAP_ENTRY(nsIDOM%s)\n" % eventname)
397 fd.write("NS_INTERFACE_MAP_END_INHERITING(%s)\n\n" % basename)
398
399 hasVariant = False
400 for a in allattributes:
401 if a.type == "nsIVariant":
402 hasVariant = True
403 break;
404
405 fd.write("already_AddRefed<%s>\n" % eventname)
406 fd.write("%s::Constructor(const GlobalObject& aGlobal, " % eventname)
407 if hasVariant:
408 fd.write("JSContext* aCx, ");
409 fd.write("const nsAString& aType, ")
410 fd.write("const %sInit& aParam, " % eventname)
411 fd.write("ErrorResult& aRv)\n")
412 fd.write("{\n")
413 fd.write(" nsCOMPtr<mozilla::dom::EventTarget> t = do_QueryInterface(aGlobal.GetAsSupports());\n")
414 fd.write(" nsRefPtr<%s> e = new %s(t, nullptr, nullptr);\n" % (eventname, eventname))
415 fd.write(" bool trusted = e->Init(t);\n")
416 fd.write(" e->Init%s(" % eventname)
417 if hasVariant:
418 fd.write("aCx, ");
419 fd.write("aType, aParam.mBubbles, aParam.mCancelable")
420 for a in allattributes:
421 fd.write(", aParam.m%s" % firstCap(a.name))
422 fd.write(", aRv);\n")
423 fd.write(" e->SetTrusted(trusted);\n")
424 fd.write(" return e.forget();\n")
425 fd.write("}\n\n")
426
427 fd.write("NS_IMETHODIMP\n")
428 fd.write("%s::Init%s(" % (classname, eventname))
429 fd.write("const nsAString& aType, bool aCanBubble, bool aCancelable")
430 for a in allattributes:
431 writeAttributeParams(fd, a)
432 fd.write(")\n{\n")
433 fd.write(" nsresult rv = %s::Init%s(aType, aCanBubble, aCancelable" % (basename, ("%s" % iface.base[6:])))
434 for a in baseattributes:
435 fd.write(", a%s" % firstCap(a.name))
436 fd.write(");\n");
437 fd.write(" NS_ENSURE_SUCCESS(rv, rv);\n")
438 for a in attributes:
439 if a.realtype.nativeType("in").count("nsAString"):
440 fd.write(" if (!m%s.Assign(a%s, fallible_t())) {\n" % (firstCap(a.name), firstCap(a.name)))
441 fd.write(" return NS_ERROR_OUT_OF_MEMORY;\n")
442 fd.write(" }\n")
443 else:
444 fd.write(" m%s = a%s;\n" % (firstCap(a.name), firstCap(a.name)))
445 fd.write(" return NS_OK;\n")
446 fd.write("}\n\n")
447
448 fd.write("void\n")
449 fd.write("%s::Init%s(" % (classname, eventname))
450 if hasVariant:
451 fd.write("JSContext* aCx, ")
452 fd.write("const nsAString& aType, bool aCanBubble, bool aCancelable")
453 for a in allattributes:
454 writeNativeAttributeParams(fd, a, conf)
455 fd.write(", ErrorResult& aRv")
456 fd.write(")\n")
457 fd.write("{\n");
458 for a in allattributes:
459 if a.type == "nsIVariant":
460 fd.write(" nsCOMPtr<nsIVariant> %s = dont_AddRef(XPCVariant::newVariant(aCx, a%s));\n" % (a.name, firstCap(a.name)))
461 fd.write(" if (!%s) {\n" % a.name)
462 fd.write(" aRv.Throw(NS_ERROR_FAILURE);\n")
463 fd.write(" return;\n")
464 fd.write(" }\n")
465 elif a.realtype.nativeType('in').endswith('*'):
466 xpidl_t = a.realtype.nativeType('in').strip('* ')
467 native_t = xpidl_to_native(xpidl_t, conf)
468 if xpidl_t != native_t:
469 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)))
470 fd.write(" aRv = Init%s(" % classname);
471 fd.write("aType, aCanBubble, aCancelable")
472 for a in allattributes:
473 if a.realtype.nativeType('in').endswith('*'):
474 xpidl_t = a.realtype.nativeType('in').strip('* ')
475 native_t = xpidl_to_native(xpidl_t, conf)
476 if xpidl_t != native_t or a.type == "nsIVariant":
477 fd.write(", %s" % a.name)
478 continue
479 fd.write(", a%s" % firstCap(a.name))
480 fd.write(");\n}\n\n");
481
482 for a in attributes:
483 writeAttributeGetter(fd, classname, a)
484
485 fd.write("} // namespace dom\n")
486 fd.write("} // namespace mozilla\n\n")
487
488 fd.write("nsresult\n")
489 fd.write("NS_NewDOM%s(nsIDOMEvent** aInstance, " % eventname)
490 fd.write("mozilla::dom::EventTarget* aOwner, nsPresContext* aPresContext = nullptr, mozilla::WidgetEvent* aEvent = nullptr)\n")
491 fd.write("{\n")
492 fd.write(" mozilla::dom::%s* it = new mozilla::dom::%s(aOwner, aPresContext, aEvent);\n" % (classname, classname))
493 fd.write(" NS_ADDREF(it);\n")
494 fd.write(" *aInstance = static_cast<mozilla::dom::Event*>(it);\n")
495 fd.write(" return NS_OK;\n");
496 fd.write("}\n\n")
497
498 def toWebIDLType(attribute, inType=False, onlyInterface=False):
499 if attribute.type == "nsIVariant":
500 return "any";
501 if attribute.type == "nsISupports":
502 return "%s%s" % (attribute.type, "" if onlyInterface else "?")
503 if attribute.type.count("nsIDOM"):
504 return "%s%s" % (attribute.type[6:], "" if onlyInterface else "?")
505 if attribute.type.count("nsI"):
506 return "%s%s" % (attribute.type[3:], "" if onlyInterface else "?")
507 if attribute.realtype.nativeType('in').endswith('*') or attribute.realtype.nativeType('in').count("nsAString"):
508 return "%s%s" % (attribute.type, "" if onlyInterface else "?")
509 return attribute.type
510
511 def write_webidl(eventname, iface, fd, conf, idl):
512 basename = ("%s" % iface.base[6:])
513 attributes = []
514 ccattributes = []
515 consts = []
516 hasInit = False
517 initMethod = "init%s" % eventname;
518 for member in iface.members:
519 if isinstance(member, xpidl.Attribute):
520 attributes.append(member)
521 if (member.realtype.nativeType('in').endswith('*')):
522 ccattributes.append(member);
523 elif isinstance(member, xpidl.Method) and member.name == initMethod:
524 if not member.noscript and not member.notxpcom:
525 hasInit = True
526 elif isinstance(member, xpidl.ConstMember):
527 consts.append(member);
528 else:
529 raise BaseException("Unsupported idl member %s::%s" % (eventname, member.name))
530
531 baseinterfaces = []
532 baseiface = iface.idl.getName(iface.base, iface.location)
533 while baseiface.name != "nsIDOMEvent":
534 baseinterfaces.append(baseiface)
535 baseiface = baseiface.idl.getName(baseiface.base, baseiface.location)
536 baseinterfaces.reverse()
537
538 allattributes = []
539 for baseiface in baseinterfaces:
540 for member in baseiface.members:
541 if isinstance(member, xpidl.Attribute):
542 allattributes.append(member)
543 allattributes.extend(attributes)
544
545 fd.write(
546 """/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
547 /* This Source Code Form is subject to the terms of the Mozilla Public
548 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
549 * You can obtain one at http://mozilla.org/MPL/2.0/.
550 */
551 """)
552
553 neededInterfaces = []
554 for a in attributes:
555 if a.realtype.nativeType('in').endswith('*'):
556 nativeType = a.realtype.nativeType('in').strip('* ')
557 mappingForWebIDL = False
558 for xp in conf.xpidl_to_native:
559 if xp[0] == nativeType:
560 mappingForWebIDL = True
561 break;
562 if not mappingForWebIDL:
563 webidlType = toWebIDLType(a, False, True)
564 if (not webidlType in neededInterfaces and webidlType != "any"):
565 neededInterfaces.append(webidlType);
566
567 for i in neededInterfaces:
568 fd.write("interface %s;\n" % i)
569
570 fd.write("\n");
571 fd.write("[Constructor(DOMString type, optional %sInit eventInitDict), HeaderFile=\"GeneratedEventClasses.h\"]\n" % eventname);
572 fd.write("interface %s : %s\n" % (eventname, basename))
573 fd.write("{\n")
574
575 for c in consts:
576 fd.write(" const %s %s = %s;\n" % (c.type, c.name, c.getValue()))
577 if len(consts):
578 fd.write("\n")
579
580 for a in attributes:
581 if a.realtype.nativeType('in').count("nsIVariant"):
582 fd.write(" [Throws]\n")
583 fd.write(" readonly attribute %s %s;\n" % (toWebIDLType(a), a.name))
584 elif a.realtype.nativeType('in').endswith('*') or a.realtype.nativeType('in').count("nsAString"):
585 fd.write(" readonly attribute %s %s;\n" % (toWebIDLType(a), a.name))
586 else:
587 fd.write(" readonly attribute %s %s;\n" % (a.type, a.name))
588 if hasInit:
589 fd.write("\n [Throws]\n")
590 m = " void %s(" % initMethod
591 fd.write(m)
592 indent = "".join(" " for i in range(len(m)))
593 indent = ",\n%s" % indent
594 fd.write("DOMString type")
595 fd.write(indent);
596 fd.write("boolean canBubble")
597 fd.write(indent);
598 fd.write("boolean cancelable")
599 for a in baseattributes + attributes:
600 fd.write(indent);
601 fd.write("%s %s" % (toWebIDLType(a, True), a.name))
602 fd.write(");\n");
603 fd.write("};\n\n")
604
605 dname = "%sInit" % eventname
606 for p in idl.productions:
607 if p.kind == "dictionary" and p.name == dname:
608 fd.write("dictionary %s : %sInit\n" % (dname, basename))
609 fd.write("{\n")
610 # We want to keep the same ordering what interface has.
611 for ifaceattribute in attributes:
612 for member in p.members:
613 if member.name == ifaceattribute.name:
614 a = member
615 if a.realtype.nativeType('in').endswith('*'):
616 fd.write(" %s %s = null;\n" % (toWebIDLType(a, True), a.name))
617 elif a.realtype.nativeType('in').count("nsAString"):
618 if a.defvalue is None:
619 if a.nullable:
620 fd.write(" %s? %s = null;\n" % (a.type, a.name))
621 else:
622 fd.write(" %s %s = \"\";\n" % (a.type, a.name))
623 else:
624 if a.nullable:
625 fd.write(" %s? %s = \"%s\";\n" % (a.type, a.name, a.defvalue))
626 else:
627 fd.write(" %s %s = \"%s\";\n" % (a.type, a.name, a.defvalue))
628 else:
629 if a.defvalue is None:
630 if a.type == "boolean":
631 fd.write(" %s %s = false;\n" % (a.type, a.name))
632 else:
633 fd.write(" %s %s = 0;\n" % (a.type, a.name))
634 # Infinity is not supported by all the types, but
635 # WebIDL parser will then complain about the wrong values.
636 elif a.defvalue == "Infinity":
637 fd.write(" unrestricted %s %s = Infinity;\n" % (a.type, a.name))
638 elif a.defvalue == "-Infinity":
639 fd.write(" unrestricted %s %s = -Infinity;\n" % (a.type, a.name))
640 else:
641 fd.write(" %s %s = %s;\n" % (a.type, a.name, a.defvalue))
642 continue
643 fd.write("};\n")
644 return
645
646 # There is no dictionary defined in the .idl file. Generate one based on
647 # the interface.
648 fd.write("dictionary %s : %sInit\n" % (dname, basename))
649 fd.write("{\n")
650 for a in attributes:
651 if a.realtype.nativeType('in').endswith('*'):
652 fd.write(" %s %s = null;\n" % (toWebIDLType(a, True), a.name))
653 elif a.realtype.nativeType('in').count("nsAString"):
654 fd.write(" %s? %s = \"\";\n" % (a.type, a.name))
655 elif a.type == "boolean":
656 fd.write(" %s %s = false;\n" % (a.type, a.name))
657 else:
658 fd.write(" %s %s = 0;\n" % (a.type, a.name))
659 fd.write("};\n")
660
661 def print_webidl_file(idl, fd, conf, eventname):
662 for p in idl.productions:
663 if p.kind == 'interface':
664 write_webidl(eventname, p, fd, conf, idl)
665
666 def xpidl_to_native(xpidl, conf):
667 for x in conf.xpidl_to_native:
668 if x[0] == xpidl:
669 return x[1]
670 return xpidl
671
672 def xpidl_to_canonical(xpidl, conf):
673 for x in conf.xpidl_to_native:
674 if x[0] == xpidl:
675 return x[2]
676 return xpidl
677
678 def native_to_xpidl(native, conf):
679 for x in conf.xpidl_to_native:
680 if x[1] == native:
681 return x[0]
682 return native
683
684 def print_webidl_files(webidlDir, conf):
685 for e in conf.simple_events:
686 idl = loadEventIDL(p, options.incdirs, e)
687 webidl = "%s/%s.webidl" % (webidlDir, e)
688 if not os.path.exists(webidl):
689 fd = open(webidl, 'w')
690 print_webidl_file(idl, fd, conf, e)
691 fd.close();
692
693 if __name__ == '__main__':
694 from optparse import OptionParser
695 o = OptionParser(usage="usage: %prog [options] configfile")
696 o.add_option('-I', action='append', dest='incdirs', default=['.'],
697 help="Directory to search for imported files")
698 o.add_option('-o', "--stub-output",
699 type='string', dest='stub_output', default=None,
700 help="Quick stub C++ source output file", metavar="FILE")
701 o.add_option('--header-output', type='string', default=None,
702 help="Quick stub header output file", metavar="FILE")
703 o.add_option('--makedepend-output', type='string', default=None,
704 help="gnumake dependencies output file", metavar="FILE")
705 o.add_option('--cachedir', dest='cachedir', default=None,
706 help="Directory in which to cache lex/parse tables.")
707 o.add_option('--class-declarations', type='string', default=None,
708 help="Class declarations", metavar="FILE")
709 o.add_option('--webidltarget', dest='webidltarget', default=None,
710 help="Directory in which to store generated WebIDL files.")
711 (options, filenames) = o.parse_args()
712 if len(filenames) != 1:
713 o.error("Exactly one config filename is needed.")
714 filename = filenames[0]
715
716 if options.cachedir is not None:
717 if not os.path.isdir(options.cachedir):
718 os.mkdir(options.cachedir)
719 sys.path.append(options.cachedir)
720
721 # Instantiate the parser.
722 p = xpidl.IDLParser(outputdir=options.cachedir)
723
724 conf = readConfigFile(filename)
725
726 if options.header_output is not None:
727 outfd = open(options.header_output, 'w')
728 print_header_file(outfd, conf)
729 outfd.close()
730 if options.class_declarations is not None:
731 outfd = open(options.class_declarations, 'w')
732 print_classes_file(outfd, conf)
733 outfd.close()
734 if options.stub_output is not None:
735 makeutils.targets.append(options.stub_output)
736 outfd = open(options.stub_output, 'w')
737 print_cpp_file(outfd, conf)
738 outfd.close()
739 if options.makedepend_output is not None:
740 makeutils.writeMakeDependOutput(options.makedepend_output)
741
742 if options.webidltarget is not None:
743 print_webidl_files(options.webidltarget, conf)
744

mercurial