1 # Copyright (C) 2008 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
2 # Copyright (C) 2008 Martin Soto <soto@freedesktop.org>
3 # Copyright (C) 2008 Alp Toker <alp@atoker.com>
4 # Copyright (C) 2009 Adam Dingle <adam@yorba.org>
5 # Copyright (C) 2009 Jim Nelson <jim@yorba.org>
6 # Copyright (C) 2009, 2010 Igalia S.L.
8 # This library is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU Library General Public
10 # License as published by the Free Software Foundation; either
11 # version 2 of the License, or (at your option) any later version.
13 # This library is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 # Library General Public License for more details.
18 # You should have received a copy of the GNU Library General Public License
19 # along with this library; see the file COPYING.LIB. If not, write to
20 # the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 # Boston, MA 02111-1307, USA.
23 package CodeGeneratorGObject;
25 use constant FileNamePrefix => "WebKitDOM";
28 my %implIncludes = ();
31 my $defineTypeMacro = "G_DEFINE_TYPE";
32 my $defineTypeInterfaceImplementation = ")";
33 my @txtEventListeners = ();
34 my @txtInstallProps = ();
40 # FIXME: this should be replaced with a function that recurses up the tree
41 # to find the actual base type.
42 my %baseTypeHash = ("Object" => 1, "Node" => 1, "NodeList" => 1, "NamedNodeMap" => 1, "DOMImplementation" => 1,
43 "Event" => 1, "CSSRule" => 1, "CSSValue" => 1, "StyleSheet" => 1, "MediaList" => 1,
44 "Counter" => 1, "Rect" => 1, "RGBColor" => 1, "XPathExpression" => 1, "XPathResult" => 1,
45 "NodeIterator" => 1, "TreeWalker" => 1, "AbstractView" => 1, "Blob" => 1, "DOMTokenList" => 1,
46 "HTMLCollection" => 1);
48 # List of function parameters that are allowed to be NULL
49 my $canBeNullParams = {
50 'webkit_dom_document_evaluate' => ['inResult', 'resolver'],
51 'webkit_dom_node_insert_before' => ['refChild']
59 $codeGenerator = shift;
61 bless($reference, $object);
64 my $licenceTemplate = << "EOF";
66 This file is part of the WebKit open source project.
67 This file has been generated by generate-bindings.pl. DO NOT MODIFY!
69 This library is free software; you can redistribute it and/or
70 modify it under the terms of the GNU Library General Public
71 License as published by the Free Software Foundation; either
72 version 2 of the License, or (at your option) any later version.
74 This library is distributed in the hope that it will be useful,
75 but WITHOUT ANY WARRANTY; without even the implied warranty of
76 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
77 Library General Public License for more details.
79 You should have received a copy of the GNU Library General Public License
80 along with this library; see the file COPYING.LIB. If not, write to
81 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
82 Boston, MA 02110-1301, USA.
86 sub GetParentClassName {
87 my $interface = shift;
89 return "WebKitDOMObject" if @{$interface->parents} eq 0;
90 return "WebKitDOM" . $interface->parents(0);
93 sub GetParentImplClassName {
94 my $interface = shift;
96 return "Object" if @{$interface->parents} eq 0;
97 return $interface->parents(0);
104 return 1 if $baseTypeHash{$type};
112 return $parent if $parent eq "Object" or IsBaseType($parent);
113 return "Event" if $parent eq "UIEvent" or $parent eq "MouseEvent";
114 return "CSSValue" if $parent eq "SVGColor" or $parent eq "CSSValueList";
119 # From String::CamelCase 0.01
123 join('', map{ ucfirst $_ } split(/(?<=[A-Za-z])_(?=[A-Za-z])|\b/, $s));
129 $s =~ s{([^a-zA-Z]?)([A-Z]*)([A-Z])([a-z]?)}{
131 my ($p0,$p1,$p2,$p3) = ($1,lc$2,lc$3,$4);
132 my $t = $p0 || $fc ? $p0 : '_';
133 $t .= $p3 ? $p1 ? "${p1}_$p2$p3" : "$p2$p3" : "$p1$p2";
139 sub FixUpDecamelizedName {
140 my $classname = shift;
142 # FIXME: try to merge this somehow with the fixes in ClassNameToGobjectType
143 $classname =~ s/x_path/xpath/;
144 $classname =~ s/web_kit/webkit/;
145 $classname =~ s/htmli_frame/html_iframe/;
150 sub HumanReadableConditional {
151 my @conditional = split('_', shift);
152 my @upperCaseExceptions = ("SQL", "API");
155 for $part (@conditional) {
156 if (!grep {$_ eq $part} @upperCaseExceptions) {
157 $part = camelize(lc($part));
159 push(@humanReadable, $part);
162 return join(' ', @humanReadable);
165 sub ClassNameToGObjectType {
166 my $className = shift;
167 my $CLASS_NAME = uc(decamelize($className));
168 # Fixup: with our prefix being 'WebKitDOM' decamelize can't get
169 # WebKitDOMCSS and similar names right, so we have to fix it
171 $CLASS_NAME =~ s/DOMCSS/DOM_CSS/;
172 $CLASS_NAME =~ s/DOMHTML/DOM_HTML/;
173 $CLASS_NAME =~ s/DOMDOM/DOM_DOM/;
174 $CLASS_NAME =~ s/DOMCDATA/DOM_CDATA/;
175 $CLASS_NAME =~ s/DOMX_PATH/DOM_XPATH/;
176 $CLASS_NAME =~ s/DOM_WEB_KIT/DOM_WEBKIT/;
177 $CLASS_NAME =~ s/DOMUI/DOM_UI/;
178 $CLASS_NAME =~ s/HTMLI_FRAME/HTML_IFRAME/;
182 sub GetParentGObjType {
183 my $interface = shift;
185 return "WEBKIT_TYPE_DOM_OBJECT" if @{$interface->parents} eq 0;
186 return "WEBKIT_TYPE_DOM_" . ClassNameToGObjectType($interface->parents(0));
192 return "WebKitDOM$name";
196 my ($interfaceName, $name, $parameter) = @_;
198 return "WebCore::${interfaceName}* $name = WebKit::core($parameter);";
202 my $attribute = shift;
204 if ($attribute->signature->extendedAttributes->{"Custom"}
205 || $attribute->signature->extendedAttributes->{"CustomGetter"}
206 || $attribute->signature->extendedAttributes->{"CustomSetter"}) {
210 my $propType = $attribute->signature->type;
211 if ($propType =~ /Constructor$/) {
215 return 1 if $attribute->isStatic;
216 return 1 if $codeGenerator->IsTypedArrayType($propType);
218 $codeGenerator->AssertNotSequenceType($propType);
220 if ($codeGenerator->GetArrayType($propType)) {
224 if ($codeGenerator->IsEnumType($propType)) {
228 # This is for DOMWindow.idl location attribute
229 if ($attribute->signature->name eq "location") {
233 # This is for HTMLInput.idl valueAsDate
234 if ($attribute->signature->name eq "valueAsDate") {
238 # This is for DOMWindow.idl Crypto attribute
239 if ($attribute->signature->type eq "Crypto") {
243 # Skip indexed database attributes for now, they aren't yet supported for the GObject generator.
244 if ($attribute->signature->name =~ /^(?:webkit)?[Ii]ndexedDB/ or $attribute->signature->name =~ /^(?:webkit)?IDB/) {
252 my $function = shift;
253 my $decamelize = shift;
256 my $functionName = "webkit_dom_" . $decamelize . "_" . $prefix . decamelize($function->signature->name);
257 my $functionReturnType = $prefix eq "set_" ? "void" : $function->signature->type;
258 my $isCustomFunction = $function->signature->extendedAttributes->{"Custom"};
259 my $callWith = $function->signature->extendedAttributes->{"CallWith"};
260 my $isUnsupportedCallWith = $codeGenerator->ExtendedAttributeContains($callWith, "ScriptArguments") || $codeGenerator->ExtendedAttributeContains($callWith, "CallStack");
262 if (($isCustomFunction || $isUnsupportedCallWith) &&
263 $functionName ne "webkit_dom_node_replace_child" &&
264 $functionName ne "webkit_dom_node_insert_before" &&
265 $functionName ne "webkit_dom_node_remove_child" &&
266 $functionName ne "webkit_dom_node_append_child" &&
267 $functionName ne "webkit_dom_html_collection_item" &&
268 $functionName ne "webkit_dom_html_collection_named_item") {
272 if ($function->signature->name eq "getSVGDocument") {
276 if ($function->signature->name eq "getCSSCanvasContext") {
280 if ($function->signature->name eq "setRangeText" && @{$function->parameters} == 1) {
284 # This is for DataTransferItemList.idl add(File) method
285 if ($functionName eq "webkit_dom_data_transfer_item_list_add" &&
286 @{$function->parameters} == 1) {
290 if ($function->signature->name eq "timeEnd") {
294 if ($codeGenerator->GetSequenceType($functionReturnType)) {
298 if ($function->signature->name eq "supports" && @{$function->parameters} == 1) {
302 # Skip functions that have callback parameters, because this
303 # code generator doesn't know how to auto-generate callbacks.
304 # Skip functions that have "MediaQueryListListener" or sequence<T> parameters, because this
305 # code generator doesn't know how to auto-generate MediaQueryListListener or sequence<T>.
306 foreach my $param (@{$function->parameters}) {
307 if ($codeGenerator->IsCallbackInterface($param->type) ||
308 $param->extendedAttributes->{"Clamp"} ||
309 $param->type eq "MediaQueryListListener" ||
310 $codeGenerator->GetSequenceType($param->type)) {
318 # Name type used in the g_value_{set,get}_* functions
319 sub GetGValueTypeName {
322 my %types = ("DOMString", "string",
323 "DOMTimeStamp", "uint",
326 "boolean", "boolean",
329 "long long", "int64",
334 "unsigned int", "uint",
335 "unsigned long long", "uint64",
336 "unsigned long", "ulong",
337 "unsigned short", "uint");
339 return $types{$type} ? $types{$type} : "object";
342 # Name type used in C declarations
343 sub GetGlibTypeName {
345 my $name = GetClassName($type);
347 my %types = ("DOMString", "gchar*",
348 "DOMTimeStamp", "guint32",
349 "CompareHow", "gushort",
352 "boolean", "gboolean",
355 "long long", "gint64",
360 "unsigned int", "guint",
361 "unsigned long", "gulong",
362 "unsigned long long", "guint64",
363 "unsigned short", "gushort",
366 return $types{$type} ? $types{$type} : "$name*";
369 sub IsGDOMClassType {
372 return 0 if $codeGenerator->IsNonPointerType($type) || $codeGenerator->IsStringType($type);
376 sub GetReadableProperties {
377 my $properties = shift;
381 foreach my $property (@{$properties}) {
382 if (!SkipAttribute($property)) {
383 push(@result, $property);
390 sub GetWriteableProperties {
391 my $properties = shift;
394 foreach my $property (@{$properties}) {
395 my $gtype = GetGValueTypeName($property->signature->type);
396 my $hasGtypeSignature = ($gtype eq "boolean" || $gtype eq "float" || $gtype eq "double" ||
397 $gtype eq "uint64" || $gtype eq "ulong" || $gtype eq "long" ||
398 $gtype eq "uint" || $gtype eq "ushort" || $gtype eq "uchar" ||
399 $gtype eq "char" || $gtype eq "string");
400 # FIXME: We are not generating setters for 'Replaceable'
401 # attributes now, but we should somehow.
402 my $replaceable = $property->signature->extendedAttributes->{"Replaceable"};
403 if (!$property->isReadOnly && $hasGtypeSignature && !$replaceable) {
404 push(@result, $property);
411 sub GenerateConditionalWarning
414 my $indentSize = shift;
419 my $conditional = $node->extendedAttributes->{"Conditional"};
423 if ($conditional =~ /&/) {
424 my @splitConditionals = split(/&/, $conditional);
425 foreach $condition (@splitConditionals) {
426 push(@warn, "#if !ENABLE($condition)\n");
427 push(@warn, ' ' x $indentSize . "WEBKIT_WARN_FEATURE_NOT_PRESENT(\"" . HumanReadableConditional($condition) . "\")\n");
428 push(@warn, "#endif\n");
430 } elsif ($conditional =~ /\|/) {
431 foreach $condition (split(/\|/, $conditional)) {
432 push(@warn, ' ' x $indentSize . "WEBKIT_WARN_FEATURE_NOT_PRESENT(\"" . HumanReadableConditional($condition) . "\")\n");
435 push(@warn, ' ' x $indentSize . "WEBKIT_WARN_FEATURE_NOT_PRESENT(\"" . HumanReadableConditional($conditional) . "\")\n");
442 sub GenerateProperty {
443 my $attribute = shift;
444 my $interfaceName = shift;
445 my @writeableProperties = @{shift @_};
446 my $parentNode = shift;
448 my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
449 my @conditionalWarn = GenerateConditionalWarning($attribute->signature, 8);
450 my $parentConditionalString = $codeGenerator->GenerateConditionalString($parentNode);
451 my @parentConditionalWarn = GenerateConditionalWarning($parentNode, 8);
452 my $camelPropName = $attribute->signature->name;
453 my $setPropNameFunction = $codeGenerator->WK_ucfirst($camelPropName);
454 my $getPropNameFunction = $codeGenerator->WK_lcfirst($camelPropName);
455 my $hasGetterException = $attribute->signature->extendedAttributes->{"GetterRaisesException"};
456 my $hasSetterException = $attribute->signature->extendedAttributes->{"SetterRaisesException"};
458 my $propName = decamelize($camelPropName);
459 my $propNameCaps = uc($propName);
460 $propName =~ s/_/-/g;
461 my ${propEnum} = "PROP_${propNameCaps}";
462 push(@cBodyProperties, " ${propEnum},\n");
464 my $propType = $attribute->signature->type;
465 my ${propGType} = decamelize($propType);
466 my ${ucPropGType} = uc($propGType);
468 my $gtype = GetGValueTypeName($propType);
469 my $gparamflag = "WEBKIT_PARAM_READABLE";
470 my $writeable = !$attribute->isReadOnly;
471 my $const = "read-only ";
472 my $custom = $attribute->signature->extendedAttributes->{"Custom"};
473 if ($writeable && $custom) {
474 $const = "read-only (due to custom functions needed in webkitdom)";
477 if ($writeable && !$custom) {
478 $gparamflag = "WEBKIT_PARAM_READWRITE";
479 $const = "read-write ";
482 my $type = GetGlibTypeName($propType);
483 $nick = decamelize("${interfaceName}_${propName}");
484 $long = "${const} ${type} ${interfaceName}.${propName}";
486 my $convertFunction = "";
487 if ($gtype eq "string") {
488 $convertFunction = "WTF::String::fromUTF8";
491 my ($getterFunctionName, @getterArguments) = $codeGenerator->GetterExpression(\%implIncludes, $interfaceName, $attribute);
492 my ($setterFunctionName, @setterArguments) = $codeGenerator->SetterExpression(\%implIncludes, $interfaceName, $attribute);
494 if ($attribute->signature->extendedAttributes->{"ImplementedBy"}) {
495 my $implementedBy = $attribute->signature->extendedAttributes->{"ImplementedBy"};
496 $implIncludes{"${implementedBy}.h"} = 1;
497 push(@setterArguments, "${convertFunction}(g_value_get_$gtype(value))");
498 unshift(@getterArguments, "coreSelf");
499 unshift(@setterArguments, "coreSelf");
500 $getterFunctionName = "WebCore::${implementedBy}::$getterFunctionName";
501 $setterFunctionName = "WebCore::${implementedBy}::$setterFunctionName";
503 push(@setterArguments, "${convertFunction}(g_value_get_$gtype(value))");
504 $getterFunctionName = "coreSelf->$getterFunctionName";
505 $setterFunctionName = "coreSelf->$setterFunctionName";
507 push(@getterArguments, "isNull") if $attribute->signature->isNullable;
508 push(@getterArguments, "ec") if $hasGetterException;
509 push(@setterArguments, "ec") if $hasSetterException;
511 if (grep {$_ eq $attribute} @writeableProperties) {
512 push(@txtSetProps, " case ${propEnum}: {\n");
513 push(@txtSetProps, "#if ${parentConditionalString}\n") if $parentConditionalString;
514 push(@txtSetProps, "#if ${conditionalString}\n") if $conditionalString;
515 push(@txtSetProps, " WebCore::ExceptionCode ec = 0;\n") if $hasSetterException;
516 push(@txtSetProps, " ${setterFunctionName}(" . join(", ", @setterArguments) . ");\n");
517 push(@txtSetProps, "#else\n") if $conditionalString;
518 push(@txtSetProps, @conditionalWarn) if scalar(@conditionalWarn);
519 push(@txtSetProps, "#endif /* ${conditionalString} */\n") if $conditionalString;
520 push(@txtSetProps, "#else\n") if $parentConditionalString;
521 push(@txtSetProps, @parentConditionalWarn) if scalar(@parentConditionalWarn);
522 push(@txtSetProps, "#endif /* ${parentConditionalString} */\n") if $parentConditionalString;
523 push(@txtSetProps, " break;\n }\n");
526 push(@txtGetProps, " case ${propEnum}: {\n");
527 push(@txtGetProps, "#if ${parentConditionalString}\n") if $parentConditionalString;
528 push(@txtGetProps, "#if ${conditionalString}\n") if $conditionalString;
529 push(@txtGetProps, " bool isNull = false;\n") if $attribute->signature->isNullable;
530 push(@txtGetProps, " WebCore::ExceptionCode ec = 0;\n") if $hasGetterException;
532 # FIXME: Should we return a default value when isNull == true?
534 my $postConvertFunction = "";
536 if ($gtype eq "string") {
537 push(@txtGetProps, " g_value_take_string(value, convertToUTF8String(${getterFunctionName}(" . join(", ", @getterArguments) . ")));\n");
539 } elsif ($gtype eq "object") {
540 push(@txtGetProps, " RefPtr<WebCore::${propType}> ptr = ${getterFunctionName}(" . join(", ", @getterArguments) . ");\n");
541 push(@txtGetProps, " g_value_set_object(value, WebKit::kit(ptr.get()));\n");
545 # FIXME: get rid of this glitch?
547 if ($gtype eq "ushort") {
552 if ($attribute->signature->extendedAttributes->{"ImplementedBy"}) {
553 my $implementedBy = $attribute->signature->extendedAttributes->{"ImplementedBy"};
554 $implIncludes{"${implementedBy}.h"} = 1;
555 push(@txtGetProps, " g_value_set_$_gtype(value, ${convertFunction}${getterFunctionName}(" . join(", ", @getterArguments) . ")${postConvertFunction});\n");
557 push(@txtGetProps, " g_value_set_$_gtype(value, ${convertFunction}${getterFunctionName}(" . join(", ", @getterArguments) . ")${postConvertFunction});\n");
561 push(@txtGetProps, "#else\n") if $conditionalString;
562 push(@txtGetProps, @conditionalWarn) if scalar(@conditionalWarn);
563 push(@txtGetProps, "#endif /* ${conditionalString} */\n") if $conditionalString;
564 push(@txtGetProps, "#else\n") if $parentConditionalString;
565 push(@txtGetProps, @parentConditionalWarn) if scalar(@parentConditionalWarn);
566 push(@txtGetProps, "#endif /* ${parentConditionalString} */\n") if $parentConditionalString;
567 push(@txtGetProps, " break;\n }\n");
569 my %param_spec_options = ("int", "G_MININT, /* min */\nG_MAXINT, /* max */\n0, /* default */",
570 "boolean", "FALSE, /* default */",
571 "float", "-G_MAXFLOAT, /* min */\nG_MAXFLOAT, /* max */\n0.0, /* default */",
572 "double", "-G_MAXDOUBLE, /* min */\nG_MAXDOUBLE, /* max */\n0.0, /* default */",
573 "uint64", "0, /* min */\nG_MAXUINT64, /* min */\n0, /* default */",
574 "long", "G_MINLONG, /* min */\nG_MAXLONG, /* max */\n0, /* default */",
575 "int64", "G_MININT64, /* min */\nG_MAXINT64, /* max */\n0, /* default */",
576 "ulong", "0, /* min */\nG_MAXULONG, /* max */\n0, /* default */",
577 "uint", "0, /* min */\nG_MAXUINT, /* max */\n0, /* default */",
578 "ushort", "0, /* min */\nG_MAXUINT16, /* max */\n0, /* default */",
579 "uchar", "G_MININT8, /* min */\nG_MAXINT8, /* max */\n0, /* default */",
580 "char", "0, /* min */\nG_MAXUINT8, /* max */\n0, /* default */",
581 "string", "\"\", /* default */",
582 "object", "WEBKIT_TYPE_DOM_${ucPropGType}, /* gobject type */");
584 my $txtInstallProp = << "EOF";
585 g_object_class_install_property(gobjectClass,
587 g_param_spec_${_gtype}("${propName}", /* name */
588 "$nick", /* short description */
589 "$long", /* longer - could do with some extra doc stuff here */
590 $param_spec_options{$gtype}
593 push(@txtInstallProps, $txtInstallProp);
596 sub GenerateProperties {
597 my ($object, $interfaceName, $interface) = @_;
599 my $clsCaps = substr(ClassNameToGObjectType($className), 12);
600 my $lowerCaseIfaceName = "webkit_dom_" . (FixUpDecamelizedName(decamelize($interfaceName)));
601 my $parentImplClassName = GetParentImplClassName($interface);
603 my $conditionGuardStart = "";
604 my $conditionGuardEnd = "";
605 my $conditionalString = $codeGenerator->GenerateConditionalString($interface);
606 if ($conditionalString) {
607 $conditionGuardStart = "#if ${conditionalString}";
608 $conditionGuardEnd = "#endif // ${conditionalString}";
612 my $implContent = "";
613 my @readableProperties = GetReadableProperties($interface->attributes);
614 my @writeableProperties = GetWriteableProperties(\@readableProperties);
615 my $numProperties = scalar @readableProperties;
618 my $privFunction = GetCoreObject($interfaceName, "coreSelf", "self");
619 if ($numProperties > 0) {
620 $implContent = << "EOF";
624 push(@cBodyProperties, $implContent);
626 my $txtGetProp = << "EOF";
627 static void ${lowerCaseIfaceName}_get_property(GObject* object, guint propertyId, GValue* value, GParamSpec* pspec)
629 WebCore::JSMainThreadNullState state;
631 push(@txtGetProps, $txtGetProp);
632 $txtGetProp = << "EOF";
634 ${className}* self = WEBKIT_DOM_${clsCaps}(object);
638 push(@txtGetProps, $txtGetProp);
640 $txtGetProp = << "EOF";
641 switch (propertyId) {
643 push(@txtGetProps, $txtGetProp);
645 if (scalar @writeableProperties > 0) {
646 my $txtSetProps = << "EOF";
647 static void ${lowerCaseIfaceName}_set_property(GObject* object, guint propertyId, const GValue* value, GParamSpec* pspec)
649 WebCore::JSMainThreadNullState state;
651 push(@txtSetProps, $txtSetProps);
653 $txtSetProps = << "EOF";
655 ${className}* self = WEBKIT_DOM_${clsCaps}(object);
659 push(@txtSetProps, $txtSetProps);
661 $txtSetProps = << "EOF";
662 switch (propertyId) {
664 push(@txtSetProps, $txtSetProps);
667 foreach my $attribute (@readableProperties) {
668 if ($attribute->signature->type ne "EventListener" &&
669 $attribute->signature->type ne "MediaQueryListListener") {
670 GenerateProperty($attribute, $interfaceName, \@writeableProperties, $interface);
674 push(@cBodyProperties, "};\n\n");
676 $txtGetProp = << "EOF";
678 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyId, pspec);
683 push(@txtGetProps, $txtGetProp);
685 if (scalar @writeableProperties > 0) {
686 $txtSetProps = << "EOF";
688 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyId, pspec);
693 push(@txtSetProps, $txtSetProps);
697 # Do not insert extra spaces when interpolating array variables
700 if ($parentImplClassName eq "Object") {
701 $implContent = << "EOF";
702 static void ${lowerCaseIfaceName}_finalize(GObject* object)
704 ${className}Private* priv = WEBKIT_DOM_${clsCaps}_GET_PRIVATE(object);
706 WebKit::DOMObjectCache::forget(priv->coreObject.get());
708 priv->~${className}Private();
709 G_OBJECT_CLASS(${lowerCaseIfaceName}_parent_class)->finalize(object);
713 push(@cBodyProperties, $implContent);
716 if ($numProperties > 0) {
717 if (scalar @writeableProperties > 0) {
718 push(@cBodyProperties, @txtSetProps);
719 push(@cBodyProperties, "\n");
721 push(@cBodyProperties, @txtGetProps);
722 push(@cBodyProperties, "\n");
725 # Add a constructor implementation only for direct subclasses of Object to make sure
726 # that the WebCore wrapped object is added only once to the DOM cache. The DOM garbage
727 # collector works because Node is a direct subclass of Object and the version of
728 # DOMObjectCache::put() that receives a Node (which is the one setting the frame) is
729 # always called for DOM objects derived from Node.
730 if ($parentImplClassName eq "Object") {
731 $implContent = << "EOF";
732 static GObject* ${lowerCaseIfaceName}_constructor(GType type, guint constructPropertiesCount, GObjectConstructParam* constructProperties)
734 GObject* object = G_OBJECT_CLASS(${lowerCaseIfaceName}_parent_class)->constructor(type, constructPropertiesCount, constructProperties);
736 ${className}Private* priv = WEBKIT_DOM_${clsCaps}_GET_PRIVATE(object);
737 priv->coreObject = static_cast<WebCore::${interfaceName}*>(WEBKIT_DOM_OBJECT(object)->coreObject);
738 WebKit::DOMObjectCache::put(priv->coreObject.get(), object);
744 push(@cBodyProperties, $implContent);
747 $implContent = << "EOF";
748 static void ${lowerCaseIfaceName}_class_init(${className}Class* requestClass)
751 push(@cBodyProperties, $implContent);
753 if ($parentImplClassName eq "Object" || $numProperties > 0) {
754 push(@cBodyProperties, " GObjectClass* gobjectClass = G_OBJECT_CLASS(requestClass);\n");
756 if ($parentImplClassName eq "Object") {
757 push(@cBodyProperties, " g_type_class_add_private(gobjectClass, sizeof(${className}Private));\n");
758 push(@cBodyProperties, " gobjectClass->constructor = ${lowerCaseIfaceName}_constructor;\n");
759 push(@cBodyProperties, " gobjectClass->finalize = ${lowerCaseIfaceName}_finalize;\n");
762 if ($numProperties > 0) {
763 if (scalar @writeableProperties > 0) {
764 push(@cBodyProperties, " gobjectClass->set_property = ${lowerCaseIfaceName}_set_property;\n");
766 push(@cBodyProperties, " gobjectClass->get_property = ${lowerCaseIfaceName}_get_property;\n");
767 push(@cBodyProperties, "\n");
768 push(@cBodyProperties, @txtInstallProps);
771 $implContent = << "EOF";
774 static void ${lowerCaseIfaceName}_init(${className}* request)
777 push(@cBodyProperties, $implContent);
779 if ($parentImplClassName eq "Object") {
780 $implContent = << "EOF";
781 ${className}Private* priv = WEBKIT_DOM_${clsCaps}_GET_PRIVATE(request);
782 new (priv) ${className}Private();
784 push(@cBodyProperties, $implContent);
786 $implContent = << "EOF";
790 push(@cBodyProperties, $implContent);
794 my ($object, $interfaceName, $parentClassName) = @_;
796 my $implContent = "";
798 # Add the default header template
799 @hPrefix = split("\r", $licenceTemplate);
800 push(@hPrefix, "\n");
802 # Force single header include.
803 my $headerCheck = << "EOF";
804 #if !defined(__WEBKITDOM_H_INSIDE__) && !defined(BUILDING_WEBKIT)
805 #error "Only <webkitdom/webkitdom.h> can be included directly."
809 push(@hPrefix, $headerCheck);
812 my $guard = $className . "_h";
814 @hPrefixGuard = << "EOF";
820 $implContent = << "EOF";
825 push(@hBodyPre, $implContent);
827 my $decamelize = FixUpDecamelizedName(decamelize($interfaceName));
828 my $clsCaps = uc($decamelize);
829 my $lowerCaseIfaceName = "webkit_dom_" . ($decamelize);
831 $implContent = << "EOF";
832 #define WEBKIT_TYPE_DOM_${clsCaps} (${lowerCaseIfaceName}_get_type())
833 #define WEBKIT_DOM_${clsCaps}(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_DOM_${clsCaps}, ${className}))
834 #define WEBKIT_DOM_${clsCaps}_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_DOM_${clsCaps}, ${className}Class)
835 #define WEBKIT_DOM_IS_${clsCaps}(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_DOM_${clsCaps}))
836 #define WEBKIT_DOM_IS_${clsCaps}_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_DOM_${clsCaps}))
837 #define WEBKIT_DOM_${clsCaps}_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_DOM_${clsCaps}, ${className}Class))
839 struct _${className} {
840 ${parentClassName} parent_instance;
843 struct _${className}Class {
844 ${parentClassName}Class parent_class;
848 ${lowerCaseIfaceName}_get_type (void);
852 push(@hBody, $implContent);
855 sub GetGReturnMacro {
856 my ($paramName, $paramIDLType, $returnType, $functionName) = @_;
859 if ($paramIDLType eq "GError") {
860 $condition = "!$paramName || !*$paramName";
861 } elsif (IsGDOMClassType($paramIDLType)) {
862 my $paramTypeCaps = uc(FixUpDecamelizedName(decamelize($paramIDLType)));
863 $condition = "WEBKIT_DOM_IS_${paramTypeCaps}($paramName)";
864 if (ParamCanBeNull($functionName, $paramName)) {
865 $condition = "!$paramName || $condition";
868 $condition = "$paramName";
872 if ($returnType ne "void") {
873 $defaultReturn = $returnType eq "gboolean" ? "FALSE" : 0;
874 $macro = " g_return_val_if_fail($condition, $defaultReturn);\n";
876 $macro = " g_return_if_fail($condition);\n";
883 my($functionName, $paramName) = @_;
885 if (defined($functionName)) {
886 return scalar(grep(/$paramName/, @{$canBeNullParams->{$functionName}}));
891 sub GenerateFunction {
892 my ($object, $interfaceName, $function, $prefix, $parentNode) = @_;
894 my $decamelize = FixUpDecamelizedName(decamelize($interfaceName));
896 if ($object eq "MediaQueryListListener") {
900 if (SkipFunction($function, $decamelize, $prefix)) {
904 return if ($function->signature->name eq "set" and $parentNode->extendedAttributes->{"TypedArray"});
906 my $functionSigType = $prefix eq "set_" ? "void" : $function->signature->type;
907 my $functionName = "webkit_dom_" . $decamelize . "_" . $prefix . decamelize($function->signature->name);
908 my $returnType = GetGlibTypeName($functionSigType);
909 my $returnValueIsGDOMType = IsGDOMClassType($functionSigType);
911 my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
912 my $parentConditionalString = $codeGenerator->GenerateConditionalString($parentNode);
913 my @conditionalWarn = GenerateConditionalWarning($function->signature);
914 my @parentConditionalWarn = GenerateConditionalWarning($parentNode);
916 my $functionSig = "${className}* self";
920 foreach my $param (@{$function->parameters}) {
921 my $paramIDLType = $param->type;
922 if ($paramIDLType eq "EventListener" || $paramIDLType eq "MediaQueryListListener") {
923 # EventListeners are handled elsewhere.
927 my $paramType = GetGlibTypeName($paramIDLType);
928 my $const = $paramType eq "gchar*" ? "const " : "";
929 my $paramName = $param->name;
931 $functionSig .= ", ${const}$paramType $paramName";
933 my $paramIsGDOMType = IsGDOMClassType($paramIDLType);
934 if ($paramIsGDOMType) {
935 if ($paramIDLType ne "any") {
936 $implIncludes{"WebKitDOM${paramIDLType}Private.h"} = 1;
939 if ($paramIsGDOMType || ($paramIDLType eq "DOMString") || ($paramIDLType eq "CompareHow")) {
940 $paramName = "converted" . $codeGenerator->WK_ucfirst($paramName);
942 push(@callImplParams, $paramName);
945 if ($returnType ne "void" && $returnValueIsGDOMType && $functionSigType ne "any") {
946 $implIncludes{"WebKitDOM${functionSigType}Private.h"} = 1;
949 if (@{$function->raisesExceptions}) {
950 $functionSig .= ", GError** error";
953 # Insert introspection annotations
954 push(@hBody, "/**\n");
955 push(@hBody, " * ${functionName}:\n");
956 push(@hBody, " * \@self: A #${className}\n");
958 foreach my $param (@{$function->parameters}) {
959 my $paramType = GetGlibTypeName($param->type);
960 # $paramType can have a trailing * in some cases
961 $paramType =~ s/\*$//;
962 my $paramName = $param->name;
963 push(@hBody, " * \@${paramName}: A #${paramType}\n");
965 if(@{$function->raisesExceptions}) {
966 push(@hBody, " * \@error: #GError\n");
968 push(@hBody, " *\n");
969 if (IsGDOMClassType($function->signature->type)) {
970 push(@hBody, " * Returns: (transfer none):\n");
972 push(@hBody, " * Returns:\n");
974 push(@hBody, " *\n");
975 push(@hBody, "**/\n");
977 push(@hBody, "WEBKIT_API $returnType\n$functionName($functionSig);\n");
980 push(@cBody, "$returnType\n$functionName($functionSig)\n{\n");
981 push(@cBody, "#if ${parentConditionalString}\n") if $parentConditionalString;
982 push(@cBody, "#if ${conditionalString}\n") if $conditionalString;
984 push(@cBody, " WebCore::JSMainThreadNullState state;\n");
986 # g_return macros to check parameters of public methods.
987 $gReturnMacro = GetGReturnMacro("self", $interfaceName, $returnType);
988 push(@cBody, $gReturnMacro);
990 foreach my $param (@{$function->parameters}) {
991 my $paramName = $param->name;
992 my $paramIDLType = $param->type;
993 my $paramTypeIsPrimitive = $codeGenerator->IsPrimitiveType($paramIDLType);
994 my $paramIsGDOMType = IsGDOMClassType($paramIDLType);
995 if (!$paramTypeIsPrimitive) {
996 $gReturnMacro = GetGReturnMacro($paramName, $paramIDLType, $returnType, $functionName);
997 push(@cBody, $gReturnMacro);
1001 if (@{$function->raisesExceptions}) {
1002 $gReturnMacro = GetGReturnMacro("error", "GError", $returnType);
1003 push(@cBody, $gReturnMacro);
1006 # The WebKit::core implementations check for null already; no need to duplicate effort.
1007 push(@cBody, " WebCore::${interfaceName}* item = WebKit::core(self);\n");
1009 $returnParamName = "";
1010 foreach my $param (@{$function->parameters}) {
1011 my $paramIDLType = $param->type;
1012 my $paramName = $param->name;
1014 my $paramIsGDOMType = IsGDOMClassType($paramIDLType);
1015 $convertedParamName = "converted" . $codeGenerator->WK_ucfirst($paramName);
1016 if ($paramIDLType eq "DOMString") {
1017 push(@cBody, " WTF::String ${convertedParamName} = WTF::String::fromUTF8($paramName);\n");
1018 } elsif ($paramIDLType eq "CompareHow") {
1019 push(@cBody, " WebCore::Range::CompareHow ${convertedParamName} = static_cast<WebCore::Range::CompareHow>($paramName);\n");
1020 } elsif ($paramIsGDOMType) {
1021 push(@cBody, " WebCore::${paramIDLType}* ${convertedParamName} = WebKit::core($paramName);\n");
1023 $returnParamName = $convertedParamName if $param->extendedAttributes->{"CustomReturn"};
1028 my $assignPost = "";
1030 # We need to special-case these Node methods because their C++
1031 # signature is different from what we'd expect given their IDL
1032 # description; see Node.h.
1033 my $functionHasCustomReturn = $functionName eq "webkit_dom_node_append_child" ||
1034 $functionName eq "webkit_dom_node_insert_before" ||
1035 $functionName eq "webkit_dom_node_replace_child" ||
1036 $functionName eq "webkit_dom_node_remove_child";
1038 if ($returnType ne "void" && !$functionHasCustomReturn) {
1039 if ($returnValueIsGDOMType) {
1040 $assign = "RefPtr<WebCore::${functionSigType}> gobjectResult = ";
1041 $assignPre = "WTF::getPtr(";
1044 $assign = "${returnType} result = ";
1048 # FIXME: Should we return a default value when isNull == true?
1049 if ($function->signature->isNullable) {
1050 push(@cBody, " bool isNull = false;\n");
1051 push(@callImplParams, "isNull");
1054 if (@{$function->raisesExceptions}) {
1055 push(@cBody, " WebCore::ExceptionCode ec = 0;\n");
1056 push(@callImplParams, "ec");
1059 my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementedAs"} || $function->signature->name;
1061 if ($functionHasCustomReturn) {
1062 push(@cBody, " bool ok = item->${functionImplementationName}(" . join(", ", @callImplParams) . ");\n");
1063 my $customNodeAppendChild = << "EOF";
1065 return WebKit::kit($returnParamName);
1067 push(@cBody, $customNodeAppendChild);
1069 if(@{$function->raisesExceptions}) {
1070 my $exceptionHandling = << "EOF";
1072 WebCore::ExceptionCodeDescription ecdesc(ec);
1073 g_set_error_literal(error, g_quark_from_string("WEBKIT_DOM"), ecdesc.code, ecdesc.name);
1075 push(@cBody, $exceptionHandling);
1077 push(@cBody, " return 0;\n");
1078 push(@cBody, "}\n\n");
1080 } elsif ($functionSigType eq "DOMString") {
1081 my $getterContentHead;
1083 my ($functionName, @arguments) = $codeGenerator->GetterExpression(\%implIncludes, $interfaceName, $function);
1084 push(@arguments, @callImplParams);
1085 if ($function->signature->extendedAttributes->{"ImplementedBy"}) {
1086 my $implementedBy = $function->signature->extendedAttributes->{"ImplementedBy"};
1087 $implIncludes{"${implementedBy}.h"} = 1;
1088 unshift(@arguments, "item");
1089 $functionName = "WebCore::${implementedBy}::${functionName}";
1091 $functionName = "item->${functionName}";
1093 $getterContentHead = "${assign}convertToUTF8String(${functionName}(" . join(", ", @arguments) . "));\n";
1095 my @arguments = @callImplParams;
1096 if ($function->signature->extendedAttributes->{"ImplementedBy"}) {
1097 my $implementedBy = $function->signature->extendedAttributes->{"ImplementedBy"};
1098 $implIncludes{"${implementedBy}.h"} = 1;
1099 unshift(@arguments, "item");
1100 $getterContentHead = "${assign}convertToUTF8String(WebCore::${implementedBy}::${functionImplementationName}(" . join(", ", @arguments) . "));\n";
1102 $getterContentHead = "${assign}convertToUTF8String(item->${functionImplementationName}(" . join(", ", @arguments) . "));\n";
1105 push(@cBody, " ${getterContentHead}");
1108 if ($prefix eq "get_") {
1109 my ($functionName, @arguments) = $codeGenerator->GetterExpression(\%implIncludes, $interfaceName, $function);
1110 push(@arguments, @callImplParams);
1111 if ($function->signature->extendedAttributes->{"ImplementedBy"}) {
1112 my $implementedBy = $function->signature->extendedAttributes->{"ImplementedBy"};
1113 $implIncludes{"${implementedBy}.h"} = 1;
1114 unshift(@arguments, "item");
1115 $functionName = "WebCore::${implementedBy}::${functionName}";
1117 $functionName = "item->${functionName}";
1119 $contentHead = "${assign}${assignPre}${functionName}(" . join(", ", @arguments) . "${assignPost});\n";
1120 } elsif ($prefix eq "set_") {
1121 my ($functionName, @arguments) = $codeGenerator->SetterExpression(\%implIncludes, $interfaceName, $function);
1122 push(@arguments, @callImplParams);
1123 if ($function->signature->extendedAttributes->{"ImplementedBy"}) {
1124 my $implementedBy = $function->signature->extendedAttributes->{"ImplementedBy"};
1125 $implIncludes{"${implementedBy}.h"} = 1;
1126 unshift(@arguments, "item");
1127 $functionName = "WebCore::${implementedBy}::${functionName}";
1128 $contentHead = "${assign}${assignPre}${functionName}(" . join(", ", @arguments) . "${assignPost});\n";
1130 $functionName = "item->${functionName}";
1131 $contentHead = "${assign}${assignPre}${functionName}(" . join(", ", @arguments) . "${assignPost});\n";
1134 my @arguments = @callImplParams;
1135 if ($function->signature->extendedAttributes->{"ImplementedBy"}) {
1136 my $implementedBy = $function->signature->extendedAttributes->{"ImplementedBy"};
1137 $implIncludes{"${implementedBy}.h"} = 1;
1138 unshift(@arguments, "item");
1139 $contentHead = "${assign}${assignPre}WebCore::${implementedBy}::${functionImplementationName}(" . join(", ", @arguments) . "${assignPost});\n";
1141 $contentHead = "${assign}${assignPre}item->${functionImplementationName}(" . join(", ", @arguments) . "${assignPost});\n";
1144 push(@cBody, " ${contentHead}");
1146 if(@{$function->raisesExceptions}) {
1147 my $exceptionHandling = << "EOF";
1149 WebCore::ExceptionCodeDescription ecdesc(ec);
1150 g_set_error_literal(error, g_quark_from_string("WEBKIT_DOM"), ecdesc.code, ecdesc.name);
1153 push(@cBody, $exceptionHandling);
1157 if ($returnType ne "void" && !$functionHasCustomReturn) {
1158 if ($functionSigType ne "any") {
1159 if ($returnValueIsGDOMType) {
1160 push(@cBody, " return WebKit::kit(gobjectResult.get());\n");
1162 push(@cBody, " return result;\n");
1165 push(@cBody, " return 0; // TODO: return canvas object\n");
1169 if ($conditionalString) {
1170 push(@cBody, "#else\n");
1171 push(@cBody, @conditionalWarn) if scalar(@conditionalWarn);
1172 if ($returnType ne "void") {
1173 if ($codeGenerator->IsNonPointerType($functionSigType)) {
1174 push(@cBody, " return static_cast<${returnType}>(0);\n");
1176 push(@cBody, " return 0;\n");
1179 push(@cBody, "#endif /* ${conditionalString} */\n");
1182 if ($parentConditionalString) {
1183 push(@cBody, "#else\n");
1184 push(@cBody, @parentConditionalWarn) if scalar(@parentConditionalWarn);
1185 if ($returnType ne "void") {
1186 if ($codeGenerator->IsNonPointerType($functionSigType)) {
1187 push(@cBody, " return static_cast<${returnType}>(0);\n");
1189 push(@cBody, " return 0;\n");
1192 push(@cBody, "#endif /* ${parentConditionalString} */\n");
1195 push(@cBody, "}\n\n");
1198 sub ClassHasFunction {
1199 my ($class, $name) = @_;
1201 foreach my $function (@{$class->functions}) {
1202 if ($function->signature->name eq $name) {
1210 sub GenerateFunctions {
1211 my ($object, $interfaceName, $interface) = @_;
1213 foreach my $function (@{$interface->functions}) {
1214 $object->GenerateFunction($interfaceName, $function, "", $interface);
1218 foreach my $attribute (@{$interface->attributes}) {
1219 if (SkipAttribute($attribute) ||
1220 $attribute->signature->type eq "EventListener" ||
1221 $attribute->signature->type eq "MediaQueryListListener") {
1225 if ($attribute->signature->name eq "type"
1226 # This will conflict with the get_type() function we define to return a GType
1227 # according to GObject conventions. Skip this for now.
1228 || $attribute->signature->name eq "URL" # TODO: handle this
1233 my $attrNameUpper = $codeGenerator->WK_ucfirst($attribute->signature->name);
1234 my $getname = "get${attrNameUpper}";
1235 my $setname = "set${attrNameUpper}";
1236 if (ClassHasFunction($interface, $getname) || ClassHasFunction($interface, $setname)) {
1237 # Very occasionally an IDL file defines getter/setter functions for one of its
1238 # attributes; in this case we don't need to autogenerate the getter/setter.
1242 # Generate an attribute getter. For an attribute "foo", this is a function named
1243 # "get_foo" which calls a DOM class method named foo().
1244 my $function = new domFunction();
1245 $function->signature($attribute->signature);
1246 if ($attribute->signature->extendedAttributes->{"GetterRaisesException"}) {
1247 $function->raisesExceptions(["DOMException"]);
1249 $object->GenerateFunction($interfaceName, $function, "get_", $interface);
1251 # FIXME: We are not generating setters for 'Replaceable'
1252 # attributes now, but we should somehow.
1253 if ($attribute->isReadOnly || $attribute->signature->extendedAttributes->{"Replaceable"}) {
1257 # Generate an attribute setter. For an attribute, "foo", this is a function named
1258 # "set_foo" which calls a DOM class method named setFoo().
1259 $function = new domFunction();
1261 $function->signature(new domSignature());
1262 $function->signature->name($attribute->signature->name);
1263 $function->signature->type($attribute->signature->type);
1264 $function->signature->extendedAttributes($attribute->signature->extendedAttributes);
1266 my $param = new domSignature();
1267 $param->name("value");
1268 $param->type($attribute->signature->type);
1269 my %attributes = ();
1270 $param->extendedAttributes(\%attributes);
1271 my $arrayRef = $function->parameters;
1272 push(@$arrayRef, $param);
1274 if ($attribute->signature->extendedAttributes->{"SetterRaisesException"}) {
1275 $function->raisesExceptions(["DOMException"]);
1278 $object->GenerateFunction($interfaceName, $function, "set_", $interface);
1283 my ($object, $interfaceName, $parentClassName, $parentGObjType, $interface) = @_;
1285 if ($interface->extendedAttributes->{"EventTarget"}) {
1286 $object->GenerateEventTargetIface($interface);
1289 my $implContent = "";
1291 my $clsCaps = uc(FixUpDecamelizedName(decamelize($interfaceName)));
1292 my $lowerCaseIfaceName = "webkit_dom_" . FixUpDecamelizedName(decamelize($interfaceName));
1293 my $parentImplClassName = GetParentImplClassName($interface);
1294 my $baseClassName = GetBaseClass($parentImplClassName);
1296 # Add a private struct only for direct subclasses of Object so that we can use RefPtr
1297 # for the WebCore wrapped object and make sure we only increment the reference counter once.
1298 if ($parentImplClassName eq "Object") {
1299 my $conditionalString = $codeGenerator->GenerateConditionalString($interface);
1300 push(@cStructPriv, "#define WEBKIT_DOM_${clsCaps}_GET_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE(obj, WEBKIT_TYPE_DOM_${clsCaps}, ${className}Private)\n\n");
1301 push(@cStructPriv, "typedef struct _${className}Private {\n");
1302 push(@cStructPriv, "#if ${conditionalString}\n") if $conditionalString;
1303 push(@cStructPriv, " RefPtr<WebCore::${interfaceName}> coreObject;\n");
1304 push(@cStructPriv, "#endif // ${conditionalString}\n") if $conditionalString;
1305 push(@cStructPriv, "} ${className}Private;\n\n");
1308 $implContent = << "EOF";
1309 ${defineTypeMacro}(${className}, ${lowerCaseIfaceName}, ${parentGObjType}${defineTypeInterfaceImplementation}
1312 push(@cBodyProperties, $implContent);
1314 if ($parentImplClassName eq "Object") {
1315 push(@cBodyPriv, "${className}* kit(WebCore::$interfaceName* obj)\n");
1316 push(@cBodyPriv, "{\n");
1317 push(@cBodyPriv, " if (!obj)\n");
1318 push(@cBodyPriv, " return 0;\n\n");
1319 push(@cBodyPriv, " if (gpointer ret = DOMObjectCache::get(obj))\n");
1320 push(@cBodyPriv, " return WEBKIT_DOM_${clsCaps}(ret);\n\n");
1321 if (IsPolymorphic($interfaceName)) {
1322 push(@cBodyPriv, " return wrap(obj);\n");
1324 push(@cBodyPriv, " return wrap${interfaceName}(obj);\n");
1326 push(@cBodyPriv, "}\n\n");
1328 push(@cBodyPriv, "${className}* kit(WebCore::$interfaceName* obj)\n");
1329 push(@cBodyPriv, "{\n");
1330 if (!IsPolymorphic($baseClassName)) {
1331 push(@cBodyPriv, " if (!obj)\n");
1332 push(@cBodyPriv, " return 0;\n\n");
1333 push(@cBodyPriv, " if (gpointer ret = DOMObjectCache::get(obj))\n");
1334 push(@cBodyPriv, " return WEBKIT_DOM_${clsCaps}(ret);\n\n");
1335 push(@cBodyPriv, " return wrap${interfaceName}(obj);\n");
1337 push(@cBodyPriv, " return WEBKIT_DOM_${clsCaps}(kit(static_cast<WebCore::$baseClassName*>(obj)));\n");
1339 push(@cBodyPriv, "}\n\n");
1342 $implContent = << "EOF";
1343 WebCore::${interfaceName}* core(${className}* request)
1345 return request ? static_cast<WebCore::${interfaceName}*>(WEBKIT_DOM_OBJECT(request)->coreObject) : 0;
1348 ${className}* wrap${interfaceName}(WebCore::${interfaceName}* coreObject)
1351 return WEBKIT_DOM_${clsCaps}(g_object_new(WEBKIT_TYPE_DOM_${clsCaps}, "core-object", coreObject, NULL));
1355 push(@cBodyPriv, $implContent);
1357 $object->GenerateProperties($interfaceName, $interface);
1358 $object->GenerateFunctions($interfaceName, $interface);
1361 sub GenerateEndHeader {
1365 my $guard = $className . "_h";
1367 push(@hBody, "G_END_DECLS\n\n");
1368 push(@hPrefixGuardEnd, "#endif /* $guard */\n");
1374 # FIXME: should we use ObjCPolymorphic attribute? or is it specific to ObjC bindings?
1375 return 1 if $type eq "Node" or $type eq "Event" or $type eq "HTMLCollection" or $type eq "StyleSheet" or $type eq "Blob";
1379 sub GenerateEventTargetIface {
1381 my $interface = shift;
1383 my $interfaceName = $interface->name;
1384 my $decamelize = FixUpDecamelizedName(decamelize($interfaceName));
1385 my $conditionalString = $codeGenerator->GenerateConditionalString($interface);
1386 my @conditionalWarn = GenerateConditionalWarning($interface);
1388 $implIncludes{"GObjectEventListener.h"} = 1;
1389 $implIncludes{"WebKitDOMEventTarget.h"} = 1;
1390 $implIncludes{"WebKitDOMEventPrivate.h"} = 1;
1392 push(@cBodyProperties, "static void webkit_dom_${decamelize}_dispatch_event(WebKitDOMEventTarget* target, WebKitDOMEvent* event, GError** error)\n{\n");
1393 push(@cBodyProperties, "#if ${conditionalString}\n") if $conditionalString;
1394 push(@cBodyProperties, " WebCore::Event* coreEvent = WebKit::core(event);\n");
1395 push(@cBodyProperties, " WebCore::${interfaceName}* coreTarget = static_cast<WebCore::${interfaceName}*>(WEBKIT_DOM_OBJECT(target)->coreObject);\n\n");
1396 push(@cBodyProperties, " WebCore::ExceptionCode ec = 0;\n");
1397 push(@cBodyProperties, " coreTarget->dispatchEvent(coreEvent, ec);\n");
1398 push(@cBodyProperties, " if (ec) {\n WebCore::ExceptionCodeDescription description(ec);\n");
1399 push(@cBodyProperties, " g_set_error_literal(error, g_quark_from_string(\"WEBKIT_DOM\"), description.code, description.name);\n }\n");
1400 push(@cBodyProperties, "#else\n") if $conditionalString;
1401 push(@cBodyProperties, @conditionalWarn) if scalar(@conditionalWarn);
1402 push(@cBodyProperties, "#endif // ${conditionalString}\n") if $conditionalString;
1403 push(@cBodyProperties, "}\n\n");
1405 push(@cBodyProperties, "static gboolean webkit_dom_${decamelize}_add_event_listener(WebKitDOMEventTarget* target, const char* eventName, GCallback handler, gboolean bubble, gpointer userData)\n{\n");
1406 push(@cBodyProperties, "#if ${conditionalString}\n") if $conditionalString;
1407 push(@cBodyProperties, " WebCore::${interfaceName}* coreTarget = static_cast<WebCore::${interfaceName}*>(WEBKIT_DOM_OBJECT(target)->coreObject);\n");
1408 push(@cBodyProperties, " return WebCore::GObjectEventListener::addEventListener(G_OBJECT(target), coreTarget, eventName, handler, bubble, userData);\n");
1409 push(@cBodyProperties, "#else\n") if $conditionalString;
1410 push(@cBodyProperties, @conditionalWarn) if scalar(@conditionalWarn);
1411 push(@cBodyProperties, " return false;\n#endif // ${conditionalString}\n") if $conditionalString;
1412 push(@cBodyProperties, "}\n\n");
1414 push(@cBodyProperties, "static gboolean webkit_dom_${decamelize}_remove_event_listener(WebKitDOMEventTarget* target, const char* eventName, GCallback handler, gboolean bubble)\n{\n");
1415 push(@cBodyProperties, "#if ${conditionalString}\n") if $conditionalString;
1416 push(@cBodyProperties, " WebCore::${interfaceName}* coreTarget = static_cast<WebCore::${interfaceName}*>(WEBKIT_DOM_OBJECT(target)->coreObject);\n");
1417 push(@cBodyProperties, " return WebCore::GObjectEventListener::removeEventListener(G_OBJECT(target), coreTarget, eventName, handler, bubble);\n");
1418 push(@cBodyProperties, "#else\n") if $conditionalString;
1419 push(@cBodyProperties, @conditionalWarn) if scalar(@conditionalWarn);
1420 push(@cBodyProperties, " return false;\n#endif // ${conditionalString}\n") if $conditionalString;
1421 push(@cBodyProperties, "}\n\n");
1423 push(@cBodyProperties, "static void webkit_dom_event_target_init(WebKitDOMEventTargetIface* iface)\n{\n");
1424 push(@cBodyProperties, " iface->dispatch_event = webkit_dom_${decamelize}_dispatch_event;\n");
1425 push(@cBodyProperties, " iface->add_event_listener = webkit_dom_${decamelize}_add_event_listener;\n");
1426 push(@cBodyProperties, " iface->remove_event_listener = webkit_dom_${decamelize}_remove_event_listener;\n}\n\n");
1428 $defineTypeMacro = "G_DEFINE_TYPE_WITH_CODE";
1429 $defineTypeInterfaceImplementation = ", G_IMPLEMENT_INTERFACE(WEBKIT_TYPE_DOM_EVENT_TARGET, webkit_dom_event_target_init))";
1433 my ($object, $interface) = @_;
1435 my $parentClassName = GetParentClassName($interface);
1436 my $parentGObjType = GetParentGObjType($interface);
1437 my $interfaceName = $interface->name;
1438 my $parentImplClassName = GetParentImplClassName($interface);
1439 my $baseClassName = GetBaseClass($parentImplClassName);
1441 # Add the default impl header template
1442 @cPrefix = split("\r", $licenceTemplate);
1443 push(@cPrefix, "\n");
1445 $implIncludes{"DOMObjectCache.h"} = 1;
1446 $implIncludes{"WebKitDOMPrivate.h"} = 1;
1447 $implIncludes{"gobject/ConvertToUTF8String.h"} = 1;
1448 $implIncludes{"${className}Private.h"} = 1;
1449 $implIncludes{"JSMainThreadExecState.h"} = 1;
1450 $implIncludes{"ExceptionCode.h"} = 1;
1451 $implIncludes{"CSSImportRule.h"} = 1;
1452 if ($parentImplClassName ne "Object" and IsPolymorphic($baseClassName)) {
1453 $implIncludes{"WebKitDOM${baseClassName}Private.h"} = 1;
1456 $hdrIncludes{"webkitdom/${parentClassName}.h"} = 1;
1458 $object->GenerateHeader($interfaceName, $parentClassName);
1459 $object->GenerateCFile($interfaceName, $parentClassName, $parentGObjType, $interface);
1460 $object->GenerateEndHeader();
1465 my $interface = shift;
1466 my $outputDir = shift;
1469 # Write a private header.
1470 my $interfaceName = $interface->name;
1471 my $filename = "$outputDir/" . $className . "Private.h";
1472 my $guard = "${className}Private_h";
1474 # Add the guard if the 'Conditional' extended attribute exists
1475 my $conditionalString = $codeGenerator->GenerateConditionalString($interface);
1477 open(PRIVHEADER, ">$filename") or die "Couldn't open file $filename for writing";
1479 print PRIVHEADER split("\r", $licenceTemplate);
1480 print PRIVHEADER "\n";
1482 my $text = << "EOF";
1486 #include "${interfaceName}.h"
1487 #include <webkitdom/${className}.h>
1490 print PRIVHEADER $text;
1491 print PRIVHEADER "#if ${conditionalString}\n" if $conditionalString;
1492 print PRIVHEADER map { "#include \"$_\"\n" } sort keys(%hdrPropIncludes);
1493 print PRIVHEADER "\n";
1496 ${className}* wrap${interfaceName}(WebCore::${interfaceName}*);
1497 ${className}* kit(WebCore::${interfaceName}*);
1498 WebCore::${interfaceName}* core(${className}*);
1501 print PRIVHEADER $text;
1504 } // namespace WebKit
1508 print PRIVHEADER $text;
1509 print PRIVHEADER "#endif /* ${conditionalString} */\n\n" if $conditionalString;
1510 print PRIVHEADER "#endif /* ${guard} */\n";
1514 my $basename = FileNamePrefix . $interfaceName;
1515 $basename =~ s/_//g;
1517 # Write public header.
1518 my $fullHeaderFilename = "$outputDir/" . $basename . ".h";
1519 my $installedHeaderFilename = "${basename}.h";
1520 open(HEADER, ">$fullHeaderFilename") or die "Couldn't open file $fullHeaderFilename";
1522 print HEADER @hPrefix;
1523 print HEADER @hPrefixGuard;
1524 print HEADER "#include <glib-object.h>\n";
1525 print HEADER map { "#include <$_>\n" } sort keys(%hdrIncludes);
1526 print HEADER "#include <webkitdom/webkitdomdefines.h>\n\n";
1527 print HEADER @hBodyPre;
1528 print HEADER @hBody;
1529 print HEADER @hPrefixGuardEnd;
1533 # Write the implementation sources
1534 my $implFileName = "$outputDir/" . $basename . ".cpp";
1535 open(IMPL, ">$implFileName") or die "Couldn't open file $implFileName";
1537 print IMPL @cPrefix;
1538 print IMPL "#include \"config.h\"\n";
1539 print IMPL "#include \"$installedHeaderFilename\"\n\n";
1541 # Remove the implementation header from the list of included files.
1542 %includesCopy = %implIncludes;
1543 print IMPL map { "#include \"$_\"\n" } sort keys(%includesCopy);
1545 print IMPL "#include <wtf/GetPtr.h>\n";
1546 print IMPL "#include <wtf/RefPtr.h>\n\n";
1547 print IMPL @cStructPriv;
1548 print IMPL "#if ${conditionalString}\n\n" if $conditionalString;
1550 print IMPL "namespace WebKit {\n\n";
1551 print IMPL @cBodyPriv;
1552 print IMPL "} // namespace WebKit\n\n";
1553 print IMPL "#endif // ${conditionalString}\n\n" if $conditionalString;
1555 print IMPL @cBodyProperties;
1568 @cBodyProperties = ();
1572 sub GenerateInterface {
1573 my ($object, $interface, $defines) = @_;
1575 # Set up some global variables
1576 $className = GetClassName($interface->name);
1578 $object->Generate($interface);