Home | History | Annotate | Download | only in scripts
      1 #
      2 # Copyright (C) 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann (at] kde.org>
      3 # Copyright (C) 2006 Anders Carlsson <andersca (at] mac.com>
      4 # Copyright (C) 2006, 2007 Samuel Weinig <sam (at] webkit.org>
      5 # Copyright (C) 2006 Alexey Proskuryakov <ap (at] webkit.org>
      6 # Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
      7 # Copyright (C) 2009 Cameron McCormack <cam (at] mcc.id.au>
      8 # 
      9 # This library is free software; you can redistribute it and/or
     10 # modify it under the terms of the GNU Library General Public
     11 # License as published by the Free Software Foundation; either
     12 # version 2 of the License, or (at your option) any later version.
     13 #
     14 # This library is distributed in the hope that it will be useful,
     15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     17 # Library General Public License for more details.
     18 #
     19 # You should have received a copy of the GNU Library General Public License
     20 # aint with this library; see the file COPYING.LIB.  If not, write to
     21 # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     22 # Boston, MA 02110-1301, USA.
     23 
     24 package CodeGeneratorJS;
     25 
     26 use File::stat;
     27 
     28 my $module = "";
     29 my $outputDir = "";
     30 my $writeDependencies = 0;
     31 
     32 my @headerContentHeader = ();
     33 my @headerContent = ();
     34 my %headerIncludes = ();
     35 
     36 my @implContentHeader = ();
     37 my @implContent = ();
     38 my %implIncludes = ();
     39 my @depsContent = ();
     40 my $numCachedAttributes = 0;
     41 my $currentCachedAttribute = 0;
     42 
     43 # Default .h template
     44 my $headerTemplate = << "EOF";
     45 /*
     46     This file is part of the WebKit open source project.
     47     This file has been generated by generate-bindings.pl. DO NOT MODIFY!
     48 
     49     This library is free software; you can redistribute it and/or
     50     modify it under the terms of the GNU Library General Public
     51     License as published by the Free Software Foundation; either
     52     version 2 of the License, or (at your option) any later version.
     53 
     54     This library is distributed in the hope that it will be useful,
     55     but WITHOUT ANY WARRANTY; without even the implied warranty of
     56     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     57     Library General Public License for more details.
     58 
     59     You should have received a copy of the GNU Library General Public License
     60     along with this library; see the file COPYING.LIB.  If not, write to
     61     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     62     Boston, MA 02110-1301, USA.
     63 */
     64 EOF
     65 
     66 # Default constructor
     67 sub new
     68 {
     69     my $object = shift;
     70     my $reference = { };
     71 
     72     $codeGenerator = shift;
     73     $outputDir = shift;
     74     shift; # $useLayerOnTop
     75     shift; # $preprocessor
     76     $writeDependencies = shift;
     77 
     78     bless($reference, $object);
     79     return $reference;
     80 }
     81 
     82 sub finish
     83 {
     84     my $object = shift;
     85 
     86     # Commit changes!
     87     $object->WriteData();
     88 }
     89 
     90 sub leftShift($$) {
     91     my ($value, $distance) = @_;
     92     return (($value << $distance) & 0xFFFFFFFF);
     93 }
     94 
     95 # Params: 'domClass' struct
     96 sub GenerateInterface
     97 {
     98     my $object = shift;
     99     my $dataNode = shift;
    100     my $defines = shift;
    101 
    102     # Start actual generation
    103     $object->GenerateHeader($dataNode);
    104     $object->GenerateImplementation($dataNode);
    105 
    106     my $name = $dataNode->name;
    107 
    108     # Open files for writing
    109     my $headerFileName = "$outputDir/JS$name.h";
    110     my $implFileName = "$outputDir/JS$name.cpp";
    111     my $depsFileName = "$outputDir/JS$name.dep";
    112 
    113     # Remove old dependency file.
    114     unlink($depsFileName);
    115 
    116     open($IMPL, ">$implFileName") || die "Couldn't open file $implFileName";
    117     open($HEADER, ">$headerFileName") || die "Couldn't open file $headerFileName";
    118     if (@depsContent) {
    119         open($DEPS, ">$depsFileName") || die "Couldn't open file $depsFileName";
    120     }
    121 }
    122 
    123 # Params: 'idlDocument' struct
    124 sub GenerateModule
    125 {
    126     my $object = shift;
    127     my $dataNode = shift;
    128 
    129     $module = $dataNode->module;
    130 }
    131 
    132 sub GetParentClassName
    133 {
    134     my $dataNode = shift;
    135 
    136     return $dataNode->extendedAttributes->{"LegacyParent"} if $dataNode->extendedAttributes->{"LegacyParent"};
    137     return "DOMObjectWithGlobalPointer" if (@{$dataNode->parents} eq 0);
    138     return "JS" . $codeGenerator->StripModule($dataNode->parents(0));
    139 }
    140 
    141 sub GetVisibleClassName
    142 {
    143     my $className = shift;
    144 
    145     return "DOMException" if $className eq "DOMCoreException";
    146     return $className;
    147 }
    148 
    149 sub AvoidInclusionOfType
    150 {
    151     my $type = shift;
    152 
    153     # Special case: SVGRect.h / SVGPoint.h / SVGNumber.h / SVGMatrix.h do not exist.
    154     return 1 if $type eq "SVGRect" or $type eq "SVGPoint" or $type eq "SVGNumber" or $type eq "SVGMatrix";
    155     return 0;
    156 }
    157 
    158 sub IndexGetterReturnsStrings
    159 {
    160     my $type = shift;
    161 
    162     return 1 if $type eq "CSSStyleDeclaration" or $type eq "MediaList" or $type eq "CSSVariablesDeclaration";
    163     return 0;
    164 }
    165 
    166 sub AddIncludesForType
    167 {
    168     my $type = $codeGenerator->StripModule(shift);
    169 
    170     # When we're finished with the one-file-per-class
    171     # reorganization, we won't need these special cases.
    172     if ($codeGenerator->IsPrimitiveType($type) or AvoidInclusionOfType($type)
    173         or $type eq "DOMString" or $type eq "DOMObject" or $type eq "Array") {
    174     } elsif ($type =~ /SVGPathSeg/) {
    175         $joinedName = $type;
    176         $joinedName =~ s/Abs|Rel//;
    177         $implIncludes{"${joinedName}.h"} = 1;
    178     } elsif ($type eq "XPathNSResolver") {
    179         $implIncludes{"JSXPathNSResolver.h"} = 1;
    180         $implIncludes{"JSCustomXPathNSResolver.h"} = 1;
    181     } else {
    182         # default, include the same named file
    183         $implIncludes{"${type}.h"} = 1;
    184     }
    185 
    186     # additional includes (things needed to compile the bindings but not the header)
    187 
    188     if ($type eq "CanvasRenderingContext2D") {
    189         $implIncludes{"CanvasGradient.h"} = 1;
    190         $implIncludes{"CanvasPattern.h"} = 1;
    191         $implIncludes{"CanvasStyle.h"} = 1;
    192     }
    193 
    194     if ($type eq "CanvasGradient" or $type eq "XPathNSResolver" or $type eq "MessagePort") {
    195         $implIncludes{"PlatformString.h"} = 1;
    196     }
    197 
    198     if ($type eq "Document") {
    199         $implIncludes{"NodeFilter.h"} = 1;
    200     }
    201 }
    202 
    203 sub AddIncludesForSVGAnimatedType
    204 {
    205     my $type = shift;
    206     $type =~ s/SVGAnimated//;
    207 
    208     if ($type eq "Point" or $type eq "Rect") {
    209         $implIncludes{"Float$type.h"} = 1;
    210     } elsif ($type eq "String") {
    211         $implIncludes{"PlatformString.h"} = 1;
    212     }
    213 }
    214 
    215 sub AddClassForwardIfNeeded
    216 {
    217     my $implClassName = shift;
    218 
    219     # SVGAnimatedLength/Number/etc. are typedefs to SVGAnimatedTemplate, so don't use class forwards for them!
    220     push(@headerContent, "class $implClassName;\n\n") unless $codeGenerator->IsSVGAnimatedType($implClassName);
    221 }
    222 
    223 sub IsSVGTypeNeedingContextParameter
    224 {
    225     my $implClassName = shift;
    226 
    227     return 0 unless $implClassName =~ /SVG/;
    228     return 0 if $implClassName =~ /Element/;
    229     my @noContextNeeded = ("SVGPaint", "SVGColor", "SVGDocument", "SVGZoomEvent");
    230     foreach (@noContextNeeded) {
    231         return 0 if $implClassName eq $_;
    232     }
    233     return 1;
    234 }
    235 
    236 sub HashValueForClassAndName
    237 {
    238     my $class = shift;
    239     my $name = shift;
    240 
    241     # SVG Filter enums live in WebCore namespace (platform/graphics/)
    242     if ($class =~ /^SVGFE*/ or $class =~ /^SVGComponentTransferFunctionElement$/) {
    243         return "WebCore::$name";
    244     }
    245 
    246     return "${class}::$name";
    247 }
    248 
    249 sub hashTableAccessor
    250 {
    251     my $noStaticTables = shift;
    252     my $className = shift;
    253     if ($noStaticTables) {
    254         return "get${className}Table(exec)";
    255     } else {
    256         return "&${className}Table";
    257     }
    258 }
    259 
    260 sub prototypeHashTableAccessor
    261 {
    262     my $noStaticTables = shift;
    263     my $className = shift;
    264     if ($noStaticTables) {
    265         return "get${className}PrototypeTable(exec)";
    266     } else {
    267         return "&${className}PrototypeTable";
    268     }
    269 }
    270 
    271 sub GenerateGetOwnPropertySlotBody
    272 {
    273     my ($dataNode, $interfaceName, $className, $implClassName, $hasAttributes, $inlined) = @_;
    274 
    275     my $namespaceMaybe = ($inlined ? "JSC::" : "");
    276 
    277     my @getOwnPropertySlotImpl = ();
    278 
    279     if ($interfaceName eq "NamedNodeMap" or $interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") {
    280         push(@getOwnPropertySlotImpl, "    ${namespaceMaybe}JSValue proto = prototype();\n");
    281         push(@getOwnPropertySlotImpl, "    if (proto.isObject() && static_cast<${namespaceMaybe}JSObject*>(asObject(proto))->hasProperty(exec, propertyName))\n");
    282         push(@getOwnPropertySlotImpl, "        return false;\n\n");
    283     }
    284 
    285     my $manualLookupGetterGeneration = sub {
    286         my $requiresManualLookup = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasNameGetter"};
    287         if ($requiresManualLookup) {
    288             push(@getOwnPropertySlotImpl, "    const ${namespaceMaybe}HashEntry* entry = ${className}Table.entry(exec, propertyName);\n");
    289             push(@getOwnPropertySlotImpl, "    if (entry) {\n");
    290             push(@getOwnPropertySlotImpl, "        slot.setCustom(this, entry->propertyGetter());\n");
    291             push(@getOwnPropertySlotImpl, "        return true;\n");
    292             push(@getOwnPropertySlotImpl, "    }\n");
    293         }
    294     };
    295 
    296     if (!$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
    297         &$manualLookupGetterGeneration();
    298     }
    299 
    300     if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
    301         push(@getOwnPropertySlotImpl, "    bool ok;\n");
    302         push(@getOwnPropertySlotImpl, "    unsigned index = propertyName.toUInt32(&ok, false);\n");
    303 
    304         # If the item function returns a string then we let the ConvertNullStringTo handle the cases
    305         # where the index is out of range.
    306         if (IndexGetterReturnsStrings($implClassName)) {
    307             push(@getOwnPropertySlotImpl, "    if (ok) {\n");
    308         } else {
    309             push(@getOwnPropertySlotImpl, "    if (ok && index < static_cast<$implClassName*>(impl())->length()) {\n");
    310         }
    311         if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
    312             push(@getOwnPropertySlotImpl, "        slot.setValue(getByIndex(exec, index));\n");
    313         } else {
    314             push(@getOwnPropertySlotImpl, "        slot.setCustomIndex(this, index, indexGetter);\n");
    315         }
    316         push(@getOwnPropertySlotImpl, "        return true;\n");
    317         push(@getOwnPropertySlotImpl, "    }\n");
    318     }
    319 
    320     if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
    321         push(@getOwnPropertySlotImpl, "    if (canGetItemsForName(exec, static_cast<$implClassName*>(impl()), propertyName)) {\n");
    322         push(@getOwnPropertySlotImpl, "        slot.setCustom(this, nameGetter);\n");
    323         push(@getOwnPropertySlotImpl, "        return true;\n");
    324         push(@getOwnPropertySlotImpl, "    }\n");
    325         if ($inlined) {
    326             $headerIncludes{"AtomicString.h"} = 1;
    327         } else {
    328             $implIncludes{"AtomicString.h"} = 1;
    329         }
    330     }
    331 
    332     if ($dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
    333         &$manualLookupGetterGeneration();
    334     }
    335 
    336     if ($dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}) {
    337         push(@getOwnPropertySlotImpl, "    if (getOwnPropertySlotDelegate(exec, propertyName, slot))\n");
    338         push(@getOwnPropertySlotImpl, "        return true;\n");
    339     }
    340 
    341     if ($hasAttributes) {
    342         if ($inlined) {
    343             die "Cannot inline if NoStaticTables is set." if ($dataNode->extendedAttributes->{"NoStaticTables"});
    344             push(@getOwnPropertySlotImpl, "    return ${namespaceMaybe}getStaticValueSlot<$className, Base>(exec, s_info.staticPropHashTable, this, propertyName, slot);\n");
    345         } else {
    346             push(@getOwnPropertySlotImpl, "    return ${namespaceMaybe}getStaticValueSlot<$className, Base>(exec, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n");
    347         }
    348     } else {
    349         push(@getOwnPropertySlotImpl, "    return Base::getOwnPropertySlot(exec, propertyName, slot);\n");
    350     }
    351 
    352     return @getOwnPropertySlotImpl;
    353 }
    354 
    355 sub GenerateGetOwnPropertyDescriptorBody
    356 {
    357     my ($dataNode, $interfaceName, $className, $implClassName, $hasAttributes, $inlined) = @_;
    358     
    359     my $namespaceMaybe = ($inlined ? "JSC::" : "");
    360     
    361     my @getOwnPropertyDescriptorImpl = ();
    362     if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) {
    363         if ($interfaceName eq "DOMWindow") {
    364             push(@implContent, "    if (!static_cast<$className*>(thisObject)->allowsAccessFrom(exec))\n");
    365         } else {
    366             push(@implContent, "    if (!allowsAccessFromFrame(exec, static_cast<$className*>(thisObject)->impl()->frame()))\n");
    367         }
    368         push(@implContent, "        return false;\n");
    369     }
    370     
    371     if ($interfaceName eq "NamedNodeMap" or $interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") {
    372         push(@getOwnPropertyDescriptorImpl, "    ${namespaceMaybe}JSValue proto = prototype();\n");
    373         push(@getOwnPropertyDescriptorImpl, "    if (proto.isObject() && static_cast<${namespaceMaybe}JSObject*>(asObject(proto))->hasProperty(exec, propertyName))\n");
    374         push(@getOwnPropertyDescriptorImpl, "        return false;\n\n");
    375     }
    376     
    377     my $manualLookupGetterGeneration = sub {
    378         my $requiresManualLookup = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasNameGetter"};
    379         if ($requiresManualLookup) {
    380             push(@getOwnPropertyDescriptorImpl, "    const ${namespaceMaybe}HashEntry* entry = ${className}Table.entry(exec, propertyName);\n");
    381             push(@getOwnPropertyDescriptorImpl, "    if (entry) {\n");
    382             push(@getOwnPropertyDescriptorImpl, "        PropertySlot slot;\n");
    383             push(@getOwnPropertyDescriptorImpl, "        slot.setCustom(this, entry->propertyGetter());\n");
    384             push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());\n");
    385             push(@getOwnPropertyDescriptorImpl, "        return true;\n");
    386             push(@getOwnPropertyDescriptorImpl, "    }\n");
    387         }
    388     };
    389     
    390     if (!$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
    391         &$manualLookupGetterGeneration();
    392     }
    393     
    394     if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
    395         push(@getOwnPropertyDescriptorImpl, "    bool ok;\n");
    396         push(@getOwnPropertyDescriptorImpl, "    unsigned index = propertyName.toUInt32(&ok, false);\n");
    397         push(@getOwnPropertyDescriptorImpl, "    if (ok && index < static_cast<$implClassName*>(impl())->length()) {\n");
    398         if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
    399             # Assume that if there's a setter, the index will be writable
    400             if ($dataNode->extendedAttributes->{"HasIndexSetter"} || $dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
    401                 push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(getByIndex(exec, index), ${namespaceMaybe}DontDelete);\n");
    402             } else {
    403                 push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(getByIndex(exec, index), ${namespaceMaybe}DontDelete | ${namespaceMaybe}ReadOnly);\n");
    404             }
    405         } else {
    406             push(@getOwnPropertyDescriptorImpl, "        ${namespaceMaybe}PropertySlot slot;\n");
    407             push(@getOwnPropertyDescriptorImpl, "        slot.setCustomIndex(this, index, indexGetter);\n");
    408             # Assume that if there's a setter, the index will be writable
    409             if ($dataNode->extendedAttributes->{"HasIndexSetter"} || $dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
    410                 push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(slot.getValue(exec, propertyName), ${namespaceMaybe}DontDelete);\n");
    411             } else {
    412                 push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(slot.getValue(exec, propertyName), ${namespaceMaybe}DontDelete | ${namespaceMaybe}ReadOnly);\n");
    413             }
    414         }
    415         push(@getOwnPropertyDescriptorImpl, "        return true;\n");
    416         push(@getOwnPropertyDescriptorImpl, "    }\n");
    417     }
    418     
    419     if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
    420         push(@getOwnPropertyDescriptorImpl, "    if (canGetItemsForName(exec, static_cast<$implClassName*>(impl()), propertyName)) {\n");
    421         push(@getOwnPropertyDescriptorImpl, "        ${namespaceMaybe}PropertySlot slot;\n");
    422         push(@getOwnPropertyDescriptorImpl, "        slot.setCustom(this, nameGetter);\n");
    423         push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);\n");
    424         push(@getOwnPropertyDescriptorImpl, "        return true;\n");
    425         push(@getOwnPropertyDescriptorImpl, "    }\n");
    426         if ($inlined) {
    427             $headerIncludes{"AtomicString.h"} = 1;
    428         } else {
    429             $implIncludes{"AtomicString.h"} = 1;
    430         }
    431     }
    432     
    433     if ($dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
    434         &$manualLookupGetterGeneration();
    435     }
    436     
    437     if ($dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}) {
    438         push(@getOwnPropertyDescriptorImpl, "    if (getOwnPropertyDescriptorDelegate(exec, propertyName, descriptor))\n");
    439         push(@getOwnPropertyDescriptorImpl, "        return true;\n");
    440     }
    441     
    442     if ($hasAttributes) {
    443         if ($inlined) {
    444             die "Cannot inline if NoStaticTables is set." if ($dataNode->extendedAttributes->{"NoStaticTables"});
    445             push(@getOwnPropertyDescriptorImpl, "    return ${namespaceMaybe}getStaticValueDescriptor<$className, Base>(exec, s_info.staticPropHashTable, this, propertyName, descriptor);\n");
    446         } else {
    447             push(@getOwnPropertyDescriptorImpl, "    return ${namespaceMaybe}getStaticValueDescriptor<$className, Base>(exec, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");
    448         }
    449     } else {
    450         push(@getOwnPropertyDescriptorImpl, "    return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);\n");
    451     }
    452     
    453     return @getOwnPropertyDescriptorImpl;
    454 }
    455 
    456 sub GenerateHeader
    457 {
    458     my $object = shift;
    459     my $dataNode = shift;
    460 
    461     my $interfaceName = $dataNode->name;
    462     my $className = "JS$interfaceName";
    463     my $implClassName = $interfaceName;
    464     my @ancestorInterfaceNames = ();
    465     my %structureFlags = ();
    466 
    467     # We only support multiple parents with SVG (for now).
    468     if (@{$dataNode->parents} > 1) {
    469         die "A class can't have more than one parent" unless $interfaceName =~ /SVG/;
    470         $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@ancestorInterfaceNames);
    471     }
    472 
    473     my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
    474     my $hasRealParent = @{$dataNode->parents} > 0;
    475     my $hasParent = $hasLegacyParent || $hasRealParent;
    476     my $parentClassName = GetParentClassName($dataNode);
    477     my $conditional = $dataNode->extendedAttributes->{"Conditional"};
    478     my $eventTarget = $dataNode->extendedAttributes->{"EventTarget"};
    479     my $needsMarkChildren = $dataNode->extendedAttributes->{"CustomMarkFunction"} || $dataNode->extendedAttributes->{"EventTarget"};
    480     
    481     # - Add default header template
    482     @headerContentHeader = split("\r", $headerTemplate);
    483 
    484     # - Add header protection
    485     push(@headerContentHeader, "\n#ifndef $className" . "_h");
    486     push(@headerContentHeader, "\n#define $className" . "_h\n\n");
    487 
    488     my $conditionalString;
    489     if ($conditional) {
    490         $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
    491         push(@headerContentHeader, "#if ${conditionalString}\n\n");
    492     }
    493 
    494     if ($hasParent) {
    495         $headerIncludes{"$parentClassName.h"} = 1;
    496     } else {
    497         $headerIncludes{"JSDOMBinding.h"} = 1;
    498         $headerIncludes{"<runtime/JSGlobalObject.h>"} = 1;
    499         $headerIncludes{"<runtime/ObjectPrototype.h>"} = 1;
    500     }
    501 
    502     if ($dataNode->extendedAttributes->{"CustomCall"}) {
    503         $headerIncludes{"<runtime/CallData.h>"} = 1;
    504     }
    505 
    506     if ($dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"}) {
    507         $headerIncludes{"<runtime/Lookup.h>"} = 1;
    508         $headerIncludes{"<wtf/AlwaysInline.h>"} = 1;
    509     }
    510 
    511     if ($hasParent && $dataNode->extendedAttributes->{"GenerateNativeConverter"}) {
    512         $headerIncludes{"$implClassName.h"} = 1;
    513     }
    514 
    515     $headerIncludes{"SVGElement.h"} = 1 if $className =~ /^JSSVG/;
    516 
    517     # Get correct pass/store types respecting PODType flag
    518     my $podType = $dataNode->extendedAttributes->{"PODType"};
    519     my $implType = $podType ? "JSSVGPODTypeWrapper<$podType> " : $implClassName;
    520     $headerIncludes{"$podType.h"} = 1 if $podType and $podType ne "float";
    521 
    522     $headerIncludes{"JSSVGPODTypeWrapper.h"} = 1 if $podType;
    523 
    524     my $numConstants = @{$dataNode->constants};
    525     my $numAttributes = @{$dataNode->attributes};
    526     my $numFunctions = @{$dataNode->functions};
    527 
    528     push(@headerContent, "\nnamespace WebCore {\n\n");
    529 
    530     # Implementation class forward declaration
    531     AddClassForwardIfNeeded($implClassName) unless $podType;
    532     AddClassForwardIfNeeded("JSDOMWindowShell") if $interfaceName eq "DOMWindow";
    533 
    534     # Class declaration
    535     push(@headerContent, "class $className : public $parentClassName {\n");
    536     push(@headerContent, "    typedef $parentClassName Base;\n");
    537     push(@headerContent, "public:\n");
    538 
    539     # Constructor
    540     if ($interfaceName eq "DOMWindow") {
    541         push(@headerContent, "    $className(NonNullPassRefPtr<JSC::Structure>, PassRefPtr<$implType>, JSDOMWindowShell*);\n");
    542     } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
    543         push(@headerContent, "    $className(NonNullPassRefPtr<JSC::Structure>, PassRefPtr<$implType>);\n");
    544     } else {
    545         push(@headerContent, "    $className(NonNullPassRefPtr<JSC::Structure>, JSDOMGlobalObject*, PassRefPtr<$implType>);\n");
    546     }
    547 
    548     # Destructor
    549     push(@headerContent, "    virtual ~$className();\n") if (!$hasParent or $eventTarget or $interfaceName eq "DOMWindow");
    550 
    551     # Prototype
    552     push(@headerContent, "    static JSC::JSObject* createPrototype(JSC::ExecState*, JSC::JSGlobalObject*);\n") unless ($dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"});
    553 
    554     $implIncludes{"${className}Custom.h"} = 1 if $dataNode->extendedAttributes->{"CustomHeader"} || $dataNode->extendedAttributes->{"CustomPutFunction"} || $dataNode->extendedAttributes->{"DelegatingPutFunction"};
    555 
    556     my $hasGetter = $numAttributes > 0 
    557                  || !($dataNode->extendedAttributes->{"OmitConstructor"}
    558                  || $dataNode->extendedAttributes->{"CustomConstructor"})
    559                  || $dataNode->extendedAttributes->{"HasIndexGetter"}
    560                  || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}
    561                  || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}
    562                  || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}
    563                  || $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}
    564                  || $dataNode->extendedAttributes->{"HasNameGetter"}
    565                  || $dataNode->extendedAttributes->{"HasOverridingNameGetter"};
    566 
    567     # Getters
    568     if ($hasGetter) {
    569         push(@headerContent, "    virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);\n");
    570         push(@headerContent, "    virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&);\n");
    571         push(@headerContent, "    virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);\n") if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) && !$dataNode->extendedAttributes->{"HasOverridingNameGetter"};
    572         push(@headerContent, "    bool getOwnPropertySlotDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"};
    573         push(@headerContent, "    bool getOwnPropertyDescriptorDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n") if $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"};
    574         $structureFlags{"JSC::OverridesGetOwnPropertySlot"} = 1;
    575     }
    576 
    577     # Check if we have any writable properties
    578     my $hasReadWriteProperties = 0;
    579     foreach (@{$dataNode->attributes}) {
    580         if ($_->type !~ /^readonly\ attribute$/) {
    581             $hasReadWriteProperties = 1;
    582         }
    583     }
    584 
    585     my $hasSetter = $hasReadWriteProperties
    586                  || $dataNode->extendedAttributes->{"CustomPutFunction"}
    587                  || $dataNode->extendedAttributes->{"DelegatingPutFunction"}
    588                  || $dataNode->extendedAttributes->{"HasCustomIndexSetter"};
    589 
    590     # Getters
    591     if ($hasSetter) {
    592         push(@headerContent, "    virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);\n");
    593         push(@headerContent, "    virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValue);\n") if $dataNode->extendedAttributes->{"HasCustomIndexSetter"};
    594         push(@headerContent, "    bool putDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, JSC::PutPropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingPutFunction"};
    595     }
    596 
    597     # Class info
    598     push(@headerContent, "    virtual const JSC::ClassInfo* classInfo() const { return &s_info; }\n");
    599     push(@headerContent, "    static const JSC::ClassInfo s_info;\n\n");
    600 
    601     # Structure ID
    602     if ($interfaceName eq "DOMWindow") {
    603         $structureFlags{"JSC::ImplementsHasInstance"} = 1;
    604         $structureFlags{"JSC::NeedsThisConversion"} = 1;
    605     }
    606     push(@headerContent,
    607         "    static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype)\n" .
    608         "    {\n" .
    609         "        return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount);\n" .
    610         "    }\n\n");
    611 
    612     # markChildren function
    613     if ($needsMarkChildren) {
    614         push(@headerContent, "    virtual void markChildren(JSC::MarkStack&);\n\n");
    615         $structureFlags{"JSC::OverridesMarkChildren"} = 1;
    616     }
    617 
    618     # Custom pushEventHandlerScope function
    619     push(@headerContent, "    virtual void pushEventHandlerScope(JSC::ExecState*, JSC::ScopeChain&) const;\n\n") if $dataNode->extendedAttributes->{"CustomPushEventHandlerScope"};
    620 
    621     # Custom call functions
    622     push(@headerContent, "    virtual JSC::CallType getCallData(JSC::CallData&);\n\n") if $dataNode->extendedAttributes->{"CustomCall"};
    623 
    624     # Custom deleteProperty function
    625     push(@headerContent, "    virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&);\n") if $dataNode->extendedAttributes->{"CustomDeleteProperty"};
    626 
    627     # Custom getPropertyNames function exists on DOMWindow
    628     if ($interfaceName eq "DOMWindow") {
    629         push(@headerContent, "    virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n");
    630         $structureFlags{"JSC::OverridesGetPropertyNames"} = 1;
    631     }
    632 
    633     # Custom defineProperty function exists on DOMWindow
    634     push(@headerContent, "    virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&, bool shouldThrow);\n") if $interfaceName eq "DOMWindow";
    635 
    636     # Custom getOwnPropertyNames function
    637     if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"} || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
    638         push(@headerContent, "    virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n");
    639         $structureFlags{"JSC::OverridesGetPropertyNames"} = 1;       
    640     }
    641 
    642     # Custom defineGetter function
    643     push(@headerContent, "    virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomDefineGetter"};
    644 
    645     # Custom defineSetter function
    646     push(@headerContent, "    virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomDefineSetter"};
    647 
    648     # Custom lookupGetter function
    649     push(@headerContent, "    virtual JSC::JSValue lookupGetter(JSC::ExecState*, const JSC::Identifier& propertyName);\n") if $dataNode->extendedAttributes->{"CustomLookupGetter"};
    650 
    651     # Custom lookupSetter function
    652     push(@headerContent, "    virtual JSC::JSValue lookupSetter(JSC::ExecState*, const JSC::Identifier& propertyName);\n") if $dataNode->extendedAttributes->{"CustomLookupSetter"};
    653 
    654     # Override toBoolean to return false for objects that want to 'MasqueradesAsUndefined'.
    655     if ($dataNode->extendedAttributes->{"MasqueradesAsUndefined"}) {
    656         push(@headerContent, "    virtual bool toBoolean(JSC::ExecState*) const { return false; };\n");
    657         $structureFlags{"JSC::MasqueradesAsUndefined"} = 1;
    658     }
    659 
    660     # Constructor object getter
    661     push(@headerContent, "    static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*);\n") if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"}));
    662 
    663     my $numCustomFunctions = 0;
    664     my $numCustomAttributes = 0;
    665 
    666     # Attribute and function enums
    667     if ($numAttributes > 0) {
    668         foreach (@{$dataNode->attributes}) {
    669             my $attribute = $_;
    670             $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"};
    671             $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"CustomGetter"} || $attribute->signature->extendedAttributes->{"JSCCustomGetter"};
    672             $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"CustomSetter"} || $attribute->signature->extendedAttributes->{"JSCCustomSetter"};
    673             if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) {
    674                 push(@headerContent, "    static const unsigned " . $attribute->signature->name . "Slot = $numCachedAttributes + Base::AnonymousSlotCount;\n");
    675                 $numCachedAttributes++;
    676             }
    677         }
    678     }
    679 
    680     if ($numCachedAttributes > 0) {
    681         push(@headerContent, "    using $parentClassName" . "::putAnonymousValue;\n");
    682         push(@headerContent, "    using $parentClassName" . "::getAnonymousValue;\n");
    683     }
    684     if ($numCustomAttributes > 0) {
    685         push(@headerContent, "\n    // Custom attributes\n");
    686 
    687         foreach my $attribute (@{$dataNode->attributes}) {
    688             if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"}) {
    689                 push(@headerContent, "    JSC::JSValue " . $codeGenerator->WK_lcfirst($attribute->signature->name) . "(JSC::ExecState*) const;\n");
    690                 if ($attribute->type !~ /^readonly/) {
    691                     push(@headerContent, "    void set" . $codeGenerator->WK_ucfirst($attribute->signature->name) . "(JSC::ExecState*, JSC::JSValue);\n");
    692                 }
    693             } elsif ($attribute->signature->extendedAttributes->{"CustomGetter"} || $attribute->signature->extendedAttributes->{"JSCCustomGetter"}) {
    694                 push(@headerContent, "    JSC::JSValue " . $codeGenerator->WK_lcfirst($attribute->signature->name) . "(JSC::ExecState*) const;\n");
    695             } elsif ($attribute->signature->extendedAttributes->{"CustomSetter"} || $attribute->signature->extendedAttributes->{"JSCCustomSetter"}) {
    696                 if ($attribute->type !~ /^readonly/) {
    697                     push(@headerContent, "    void set" . $codeGenerator->WK_ucfirst($attribute->signature->name) . "(JSC::ExecState*, JSC::JSValue);\n");
    698                 }
    699             }
    700         }
    701     }
    702 
    703     foreach my $function (@{$dataNode->functions}) {
    704         $numCustomFunctions++ if $function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"JSCCustom"};
    705     }
    706 
    707     if ($numCustomFunctions > 0) {
    708         push(@headerContent, "\n    // Custom functions\n");
    709         foreach my $function (@{$dataNode->functions}) {
    710             if ($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"JSCCustom"}) {
    711                 my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementationFunction"} || $codeGenerator->WK_lcfirst($function->signature->name);
    712                 push(@headerContent, "    JSC::JSValue " . $functionImplementationName . "(JSC::ExecState*, const JSC::ArgList&);\n");
    713             }
    714         }
    715     }
    716 
    717     if (!$hasParent) {
    718         # Extra space after JSSVGPODTypeWrapper<> to make RefPtr<Wrapper<> > compile.
    719         my $implType = $podType ? "JSSVGPODTypeWrapper<$podType> " : $implClassName;
    720         push(@headerContent, "    $implType* impl() const { return m_impl.get(); }\n\n");
    721         push(@headerContent, "private:\n");
    722         push(@headerContent, "    RefPtr<$implType> m_impl;\n");
    723     } elsif ($dataNode->extendedAttributes->{"GenerateNativeConverter"}) {
    724         push(@headerContent, "    $implClassName* impl() const\n");
    725         push(@headerContent, "    {\n");
    726         push(@headerContent, "        return static_cast<$implClassName*>(Base::impl());\n");
    727         push(@headerContent, "    }\n");
    728     }
    729     
    730     # anonymous slots
    731     if ($numCachedAttributes) {
    732         push(@headerContent, "public:\n");
    733         push(@headerContent, "    static const unsigned AnonymousSlotCount = $numCachedAttributes + Base::AnonymousSlotCount;\n");
    734     }
    735 
    736     # structure flags
    737     push(@headerContent, "protected:\n");
    738     push(@headerContent, "    static const unsigned StructureFlags = ");
    739     foreach my $structureFlag (keys %structureFlags) {
    740         push(@headerContent, $structureFlag . " | ");
    741     }
    742     push(@headerContent, "Base::StructureFlags;\n");
    743 
    744     # Index getter
    745     if ($dataNode->extendedAttributes->{"HasIndexGetter"}) {
    746         push(@headerContent, "    static JSC::JSValue indexGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n");
    747     }
    748     if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
    749         push(@headerContent, "    JSC::JSValue getByIndex(JSC::ExecState*, unsigned index);\n");
    750         
    751     }
    752     
    753     # Index setter
    754     if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
    755         push(@headerContent, "    void indexSetter(JSC::ExecState*, unsigned index, JSC::JSValue);\n");
    756     }
    757     # Name getter
    758     if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
    759         push(@headerContent, "private:\n");
    760         push(@headerContent, "    static bool canGetItemsForName(JSC::ExecState*, $implClassName*, const JSC::Identifier&);\n");
    761         push(@headerContent, "    static JSC::JSValue nameGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n");
    762     }
    763 
    764     push(@headerContent, "};\n\n");
    765 
    766     if ($dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"} && !$dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}) {
    767         push(@headerContent, "ALWAYS_INLINE bool ${className}::getOwnPropertySlot(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertySlot& slot)\n");
    768         push(@headerContent, "{\n");
    769         push(@headerContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 1));
    770         push(@headerContent, "}\n\n");
    771         push(@headerContent, "ALWAYS_INLINE bool ${className}::getOwnPropertyDescriptor(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertyDescriptor& descriptor)\n");
    772         push(@headerContent, "{\n");
    773         push(@headerContent, GenerateGetOwnPropertyDescriptorBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 1));
    774         push(@headerContent, "}\n\n");
    775     }
    776 
    777     if (!$hasParent || $dataNode->extendedAttributes->{"GenerateToJS"} || $dataNode->extendedAttributes->{"CustomToJS"}) {
    778         if ($podType) {
    779             push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, JSSVGPODTypeWrapper<$podType>*, SVGElement*);\n");
    780         } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
    781             push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType*, SVGElement* context);\n");
    782         } else {
    783             push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType*);\n");
    784         }
    785     }
    786     if (!$hasParent || $dataNode->extendedAttributes->{"GenerateNativeConverter"}) {
    787         if ($podType) {
    788             push(@headerContent, "$podType to${interfaceName}(JSC::JSValue);\n");
    789         } elsif ($interfaceName eq "NodeFilter") {
    790             push(@headerContent, "PassRefPtr<NodeFilter> toNodeFilter(JSC::JSValue);\n");
    791         } else {
    792             push(@headerContent, "$implClassName* to${interfaceName}(JSC::JSValue);\n");
    793         }
    794     }
    795     if ($interfaceName eq "Node" or $interfaceName eq "Element" or $interfaceName eq "Text" or $interfaceName eq "CDATASection") {
    796         push(@headerContent, "JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject*, $interfaceName*);\n");
    797     }
    798     
    799     push(@headerContent, "\n");
    800 
    801     # Add prototype declaration.
    802     %structureFlags = ();
    803     push(@headerContent, "class ${className}Prototype : public JSC::JSObject {\n");
    804     push(@headerContent, "    typedef JSC::JSObject Base;\n");
    805     push(@headerContent, "public:\n");
    806     if ($interfaceName eq "DOMWindow") {
    807         push(@headerContent, "    void* operator new(size_t);\n");
    808     } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
    809         push(@headerContent, "    void* operator new(size_t, JSC::JSGlobalData*);\n");
    810     } else {
    811         push(@headerContent, "    static JSC::JSObject* self(JSC::ExecState*, JSC::JSGlobalObject*);\n");
    812     }
    813     push(@headerContent, "    virtual const JSC::ClassInfo* classInfo() const { return &s_info; }\n");
    814     push(@headerContent, "    static const JSC::ClassInfo s_info;\n");
    815     if ($numFunctions > 0 || $numConstants > 0 || $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) {
    816         push(@headerContent, "    virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n");
    817         push(@headerContent, "    virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n");
    818         push(@headerContent, "    bool getOwnPropertySlotDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"};
    819         push(@headerContent, "    bool getOwnPropertyDescriptorDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n") if $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"};
    820         $structureFlags{"JSC::OverridesGetOwnPropertySlot"} = 1;
    821     }
    822     if ($dataNode->extendedAttributes->{"CustomMarkFunction"} or $needsMarkChildren) {
    823         $structureFlags{"JSC::OverridesMarkChildren"} = 1;
    824     }
    825     push(@headerContent,
    826         "    static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype)\n" .
    827         "    {\n" .
    828         "        return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount);\n" .
    829         "    }\n");
    830     if ($dataNode->extendedAttributes->{"DelegatingPrototypePutFunction"}) {
    831         push(@headerContent, "    virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);\n");
    832         push(@headerContent, "    bool putDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, JSC::PutPropertySlot&);\n");
    833     }
    834 
    835     # Custom defineGetter function
    836     push(@headerContent, "    virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomPrototypeDefineGetter"};
    837 
    838     push(@headerContent, "    ${className}Prototype(NonNullPassRefPtr<JSC::Structure> structure) : JSC::JSObject(structure) { }\n");
    839 
    840     # structure flags
    841     push(@headerContent, "protected:\n");
    842     push(@headerContent, "    static const unsigned StructureFlags = ");
    843     foreach my $structureFlag (keys %structureFlags) {
    844         push(@headerContent, $structureFlag . " | ");
    845     }
    846     push(@headerContent, "Base::StructureFlags;\n");
    847 
    848     push(@headerContent, "};\n\n");
    849 
    850     if ($numFunctions > 0) {
    851         push(@headerContent,"// Functions\n\n");
    852         foreach my $function (@{$dataNode->functions}) {
    853             my $functionName = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($function->signature->name);
    854             push(@headerContent, "JSC::JSValue JSC_HOST_CALL ${functionName}(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);\n");
    855         }
    856     }
    857 
    858     if ($numAttributes > 0 || !($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
    859         push(@headerContent,"// Attributes\n\n");
    860         foreach my $attribute (@{$dataNode->attributes}) {
    861             my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
    862             push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n");
    863             unless ($attribute->type =~ /readonly/) {
    864                 my $setter = "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
    865                 push(@headerContent, "void ${setter}(JSC::ExecState*, JSC::JSObject*, JSC::JSValue);\n");
    866             }
    867         }
    868         
    869         if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
    870             my $getter = "js" . $interfaceName . "Constructor";
    871             push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n");
    872         }
    873     }
    874 
    875     if ($numConstants > 0) {
    876         push(@headerContent,"// Constants\n\n");
    877         foreach my $constant (@{$dataNode->constants}) {
    878             my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);
    879             push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n");
    880         }
    881     }
    882 
    883     push(@headerContent, "\n} // namespace WebCore\n\n");
    884     push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditional;
    885     push(@headerContent, "#endif\n");
    886 
    887     # - Generate dependencies.
    888     if ($writeDependencies && @ancestorInterfaceNames) {
    889         push(@depsContent, "$className.h : ", join(" ", map { "$_.idl" } @ancestorInterfaceNames), "\n");
    890         push(@depsContent, map { "$_.idl :\n" } @ancestorInterfaceNames); 
    891     }
    892 }
    893 
    894 sub GenerateImplementation
    895 {
    896     my ($object, $dataNode) = @_;
    897 
    898     my $interfaceName = $dataNode->name;
    899     my $className = "JS$interfaceName";
    900     my $implClassName = $interfaceName;
    901 
    902     my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
    903     my $hasRealParent = @{$dataNode->parents} > 0;
    904     my $hasParent = $hasLegacyParent || $hasRealParent;
    905     my $parentClassName = GetParentClassName($dataNode);
    906     my $conditional = $dataNode->extendedAttributes->{"Conditional"};
    907     my $visibleClassName = GetVisibleClassName($interfaceName);
    908     my $eventTarget = $dataNode->extendedAttributes->{"EventTarget"};
    909     my $needsMarkChildren = $dataNode->extendedAttributes->{"CustomMarkFunction"} || $dataNode->extendedAttributes->{"EventTarget"};
    910 
    911     # - Add default header template
    912     @implContentHeader = split("\r", $headerTemplate);
    913 
    914     push(@implContentHeader, "\n#include \"config.h\"\n");
    915     my $conditionalString;
    916     if ($conditional) {
    917         $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
    918         push(@implContentHeader, "\n#if ${conditionalString}\n\n");
    919     }
    920     push(@implContentHeader, "#include \"$className.h\"\n\n");
    921 
    922     AddIncludesForSVGAnimatedType($interfaceName) if $className =~ /^JSSVGAnimated/;
    923 
    924     $implIncludes{"<wtf/GetPtr.h>"} = 1;
    925     $implIncludes{"<runtime/PropertyNameArray.h>"} = 1 if $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"};
    926 
    927     AddIncludesForType($interfaceName);
    928 
    929     @implContent = ();
    930 
    931     push(@implContent, "\nusing namespace JSC;\n\n");
    932     push(@implContent, "namespace WebCore {\n\n");
    933 
    934     push(@implContent, "ASSERT_CLASS_FITS_IN_CELL($className);\n\n");
    935 
    936     # - Add all attributes in a hashtable definition
    937     my $numAttributes = @{$dataNode->attributes};
    938     $numAttributes++ if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"}));
    939 
    940     if ($numAttributes > 0) {
    941         my $hashSize = $numAttributes;
    942         my $hashName = $className . "Table";
    943 
    944         my @hashKeys = ();
    945         my @hashSpecials = ();
    946         my @hashValue1 = ();
    947         my @hashValue2 = ();
    948         my %conditionals = ();
    949 
    950         my @entries = ();
    951 
    952         foreach my $attribute (@{$dataNode->attributes}) {
    953             my $name = $attribute->signature->name;
    954             push(@hashKeys, $name);
    955 
    956             my @specials = ();
    957             push(@specials, "DontDelete") unless $attribute->signature->extendedAttributes->{"Deletable"};
    958             push(@specials, "DontEnum") if $attribute->signature->extendedAttributes->{"DontEnum"};
    959             push(@specials, "ReadOnly") if $attribute->type =~ /readonly/;
    960             my $special = (@specials > 0) ? join("|", @specials) : "0";
    961             push(@hashSpecials, $special);
    962 
    963             my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
    964             push(@hashValue1, $getter);
    965     
    966             if ($attribute->type =~ /readonly/) {
    967                 push(@hashValue2, "0");
    968             } else {
    969                 my $setter = "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
    970                 push(@hashValue2, $setter);
    971             }
    972 
    973             my $conditional = $attribute->signature->extendedAttributes->{"Conditional"};
    974             if ($conditional) {
    975                 $conditionals{$name} = $conditional;
    976             }
    977         }
    978 
    979         if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
    980             push(@hashKeys, "constructor");
    981             my $getter = "js" . $interfaceName . "Constructor";
    982             push(@hashValue1, $getter);
    983             push(@hashValue2, "0");
    984             push(@hashSpecials, "DontEnum|ReadOnly"); # FIXME: Setting the constructor should be possible.
    985         }
    986 
    987         $object->GenerateHashTable($hashName, $hashSize,
    988                                    \@hashKeys, \@hashSpecials,
    989                                    \@hashValue1, \@hashValue2,
    990                                    \%conditionals);
    991     }
    992 
    993     my $numConstants = @{$dataNode->constants};
    994     my $numFunctions = @{$dataNode->functions};
    995 
    996     # - Add all constants
    997     if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
    998         $hashSize = $numConstants;
    999         $hashName = $className . "ConstructorTable";
   1000 
   1001         @hashKeys = ();
   1002         @hashValue1 = ();
   1003         @hashValue2 = ();
   1004         @hashSpecials = ();
   1005 
   1006         # FIXME: we should not need a function for every constant.
   1007         foreach my $constant (@{$dataNode->constants}) {
   1008             push(@hashKeys, $constant->name);
   1009             my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);
   1010             push(@hashValue1, $getter);
   1011             push(@hashValue2, "0");
   1012             push(@hashSpecials, "DontDelete|ReadOnly");
   1013         }
   1014 
   1015         $object->GenerateHashTable($hashName, $hashSize,
   1016                                    \@hashKeys, \@hashSpecials,
   1017                                    \@hashValue1, \@hashValue2);
   1018 
   1019         my $protoClassName;
   1020         $protoClassName = "${className}Prototype";
   1021 
   1022         push(@implContent, constructorFor($className, $protoClassName, $interfaceName, $visibleClassName, $dataNode->extendedAttributes->{"CanBeConstructed"}));
   1023     }
   1024 
   1025     # - Add functions and constants to a hashtable definition
   1026     $hashSize = $numFunctions + $numConstants;
   1027     $hashName = $className . "PrototypeTable";
   1028 
   1029     @hashKeys = ();
   1030     @hashValue1 = ();
   1031     @hashValue2 = ();
   1032     @hashSpecials = ();
   1033 
   1034     # FIXME: we should not need a function for every constant.
   1035     foreach my $constant (@{$dataNode->constants}) {
   1036         push(@hashKeys, $constant->name);
   1037         my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);
   1038         push(@hashValue1, $getter);
   1039         push(@hashValue2, "0");
   1040         push(@hashSpecials, "DontDelete|ReadOnly");
   1041     }
   1042 
   1043     foreach my $function (@{$dataNode->functions}) {
   1044         my $name = $function->signature->name;
   1045         push(@hashKeys, $name);
   1046 
   1047         my $value = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($name);
   1048         push(@hashValue1, $value);
   1049 
   1050         my $numParameters = @{$function->parameters};
   1051         push(@hashValue2, $numParameters);
   1052 
   1053         my @specials = ();
   1054         push(@specials, "DontDelete") unless $function->signature->extendedAttributes->{"Deletable"};
   1055         push(@specials, "DontEnum") if $function->signature->extendedAttributes->{"DontEnum"};
   1056         push(@specials, "Function");
   1057         my $special = (@specials > 0) ? join("|", @specials) : "0";
   1058         push(@hashSpecials, $special);
   1059     }
   1060 
   1061     $object->GenerateHashTable($hashName, $hashSize,
   1062                                \@hashKeys, \@hashSpecials,
   1063                                \@hashValue1, \@hashValue2);
   1064 
   1065     if ($dataNode->extendedAttributes->{"NoStaticTables"}) {
   1066         push(@implContent, "static const HashTable* get${className}PrototypeTable(ExecState* exec)\n");
   1067         push(@implContent, "{\n");
   1068         push(@implContent, "    return getHashTableForGlobalData(exec->globalData(), &${className}PrototypeTable);\n");
   1069         push(@implContent, "}\n");
   1070         push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleClassName}Prototype\", 0, 0, get${className}PrototypeTable };\n\n");
   1071     } else {
   1072         push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleClassName}Prototype\", 0, &${className}PrototypeTable, 0 };\n\n");
   1073     }
   1074     if ($interfaceName eq "DOMWindow") {
   1075         push(@implContent, "void* ${className}Prototype::operator new(size_t size)\n");
   1076         push(@implContent, "{\n");
   1077         push(@implContent, "    return JSDOMWindow::commonJSGlobalData()->heap.allocate(size);\n");
   1078         push(@implContent, "}\n\n");
   1079     } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
   1080         push(@implContent, "void* ${className}Prototype::operator new(size_t size, JSGlobalData* globalData)\n");
   1081         push(@implContent, "{\n");
   1082         push(@implContent, "    return globalData->heap.allocate(size);\n");
   1083         push(@implContent, "}\n\n");
   1084     } else {
   1085         push(@implContent, "JSObject* ${className}Prototype::self(ExecState* exec, JSGlobalObject* globalObject)\n");
   1086         push(@implContent, "{\n");
   1087         push(@implContent, "    return getDOMPrototype<${className}>(exec, globalObject);\n");
   1088         push(@implContent, "}\n\n");
   1089     }
   1090     if ($numConstants > 0 || $numFunctions > 0 || $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) {
   1091         push(@implContent, "bool ${className}Prototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n");
   1092         push(@implContent, "{\n");
   1093 
   1094         if ($dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) {
   1095             push(@implContent, "    if (getOwnPropertySlotDelegate(exec, propertyName, slot))\n");
   1096             push(@implContent, "        return true;\n");
   1097         }
   1098 
   1099         if ($numConstants eq 0 && $numFunctions eq 0) {
   1100             push(@implContent, "    return Base::getOwnPropertySlot(exec, propertyName, slot);\n");        
   1101         } elsif ($numConstants eq 0) {
   1102             push(@implContent, "    return getStaticFunctionSlot<JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n");
   1103         } elsif ($numFunctions eq 0) {
   1104             push(@implContent, "    return getStaticValueSlot<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n");
   1105         } else {
   1106             push(@implContent, "    return getStaticPropertySlot<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n");
   1107         }
   1108         push(@implContent, "}\n\n");
   1109 
   1110         push(@implContent, "bool ${className}Prototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\n");
   1111         push(@implContent, "{\n");
   1112         
   1113         if ($dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) {
   1114             push(@implContent, "    if (getOwnPropertyDescriptorDelegate(exec, propertyName, descriptor))\n");
   1115             push(@implContent, "        return true;\n");
   1116         }
   1117         
   1118         if ($numConstants eq 0 && $numFunctions eq 0) {
   1119             push(@implContent, "    return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);\n");        
   1120         } elsif ($numConstants eq 0) {
   1121             push(@implContent, "    return getStaticFunctionDescriptor<JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");
   1122         } elsif ($numFunctions eq 0) {
   1123             push(@implContent, "    return getStaticValueDescriptor<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");
   1124         } else {
   1125             push(@implContent, "    return getStaticPropertyDescriptor<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");
   1126         }
   1127         push(@implContent, "}\n\n");
   1128     }
   1129 
   1130     if ($dataNode->extendedAttributes->{"DelegatingPrototypePutFunction"}) {
   1131         push(@implContent, "void ${className}Prototype::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)\n");
   1132         push(@implContent, "{\n");
   1133         push(@implContent, "    if (putDelegate(exec, propertyName, value, slot))\n");
   1134         push(@implContent, "        return;\n");
   1135         push(@implContent, "    Base::put(exec, propertyName, value, slot);\n");
   1136         push(@implContent, "}\n\n");
   1137     }
   1138 
   1139     # - Initialize static ClassInfo object
   1140     if ($numAttributes > 0 && $dataNode->extendedAttributes->{"NoStaticTables"}) {
   1141         push(@implContent, "static const HashTable* get${className}Table(ExecState* exec)\n");
   1142         push(@implContent, "{\n");
   1143         push(@implContent, "    return getHashTableForGlobalData(exec->globalData(), &${className}Table);\n");
   1144         push(@implContent, "}\n");
   1145     }
   1146     push(@implContent, "const ClassInfo $className" . "::s_info = { \"${visibleClassName}\", ");
   1147     if ($hasParent) {
   1148         push(@implContent, "&" . $parentClassName . "::s_info, ");
   1149     } else {
   1150         push(@implContent, "0, ");
   1151     }
   1152 
   1153     if ($numAttributes > 0 && !$dataNode->extendedAttributes->{"NoStaticTables"}) {
   1154         push(@implContent, "&${className}Table");
   1155     } else {
   1156         push(@implContent, "0");
   1157     }
   1158     if ($numAttributes > 0 && $dataNode->extendedAttributes->{"NoStaticTables"}) {
   1159         push(@implContent, ", get${className}Table ");
   1160     } else {
   1161         push(@implContent, ", 0 ");
   1162     }
   1163     push(@implContent, "};\n\n");
   1164 
   1165     # Get correct pass/store types respecting PODType flag
   1166     my $podType = $dataNode->extendedAttributes->{"PODType"};
   1167     my $implType = $podType ? "JSSVGPODTypeWrapper<$podType> " : $implClassName;
   1168 
   1169     # Constructor
   1170     if ($interfaceName eq "DOMWindow") {
   1171         AddIncludesForType("JSDOMWindowShell");
   1172         push(@implContent, "${className}::$className(NonNullPassRefPtr<Structure> structure, PassRefPtr<$implType> impl, JSDOMWindowShell* shell)\n");
   1173         push(@implContent, "    : $parentClassName(structure, impl, shell)\n");
   1174     } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
   1175         AddIncludesForType($interfaceName);
   1176         push(@implContent, "${className}::$className(NonNullPassRefPtr<Structure> structure, PassRefPtr<$implType> impl)\n");
   1177         push(@implContent, "    : $parentClassName(structure, impl)\n");
   1178     } else {
   1179         push(@implContent, "${className}::$className(NonNullPassRefPtr<Structure> structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl)\n");
   1180         if ($hasParent) {
   1181             push(@implContent, "    : $parentClassName(structure, globalObject, impl)\n");
   1182         } else {
   1183             push(@implContent, "    : $parentClassName(structure, globalObject)\n");
   1184             push(@implContent, "    , m_impl(impl)\n");
   1185         }
   1186     }
   1187     push(@implContent, "{\n");
   1188     if ($numCachedAttributes > 0) {
   1189         push(@implContent, "    for (unsigned i = Base::AnonymousSlotCount; i < AnonymousSlotCount; i++)\n");
   1190         push(@implContent, "        putAnonymousValue(i, JSValue());\n");
   1191     }
   1192     push(@implContent, "}\n\n");
   1193 
   1194     # Destructor
   1195     if (!$hasParent || $eventTarget) {
   1196         push(@implContent, "${className}::~$className()\n");
   1197         push(@implContent, "{\n");
   1198 
   1199         if ($eventTarget) {
   1200             $implIncludes{"RegisteredEventListener.h"} = 1;
   1201             push(@implContent, "    impl()->invalidateJSEventListeners(this);\n");
   1202         }
   1203 
   1204         if (!$dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"}) {
   1205             if ($interfaceName eq "Node") {
   1206                  push(@implContent, "    forgetDOMNode(this, impl(), impl()->document());\n");
   1207             } else {
   1208                 push(@implContent, "    forgetDOMObject(this, impl());\n");
   1209             }
   1210 
   1211             push(@implContent, "    JSSVGContextCache::forgetWrapper(this);\n") if IsSVGTypeNeedingContextParameter($implClassName);
   1212         }
   1213 
   1214         push(@implContent, "}\n\n");
   1215     }
   1216 
   1217     if ($needsMarkChildren && !$dataNode->extendedAttributes->{"CustomMarkFunction"}) {
   1218         push(@implContent, "void ${className}::markChildren(MarkStack& markStack)\n");
   1219         push(@implContent, "{\n");
   1220         push(@implContent, "    Base::markChildren(markStack);\n");
   1221         push(@implContent, "    impl()->markJSEventListeners(markStack);\n");
   1222         push(@implContent, "}\n\n");
   1223     }
   1224 
   1225     if (!$dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"}) {
   1226         push(@implContent, "JSObject* ${className}::createPrototype(ExecState* exec, JSGlobalObject* globalObject)\n");
   1227         push(@implContent, "{\n");
   1228         if ($hasParent && $parentClassName ne "JSC::DOMNodeFilter") {
   1229             push(@implContent, "    return new (exec) ${className}Prototype(${className}Prototype::createStructure(${parentClassName}Prototype::self(exec, globalObject)));\n");
   1230         } else {
   1231             push(@implContent, "    return new (exec) ${className}Prototype(${className}Prototype::createStructure(globalObject->objectPrototype()));\n");
   1232         }
   1233         push(@implContent, "}\n\n");
   1234     }
   1235 
   1236     my $hasGetter = $numAttributes > 0 
   1237                  || !($dataNode->extendedAttributes->{"OmitConstructor"} 
   1238                  || $dataNode->extendedAttributes->{"CustomConstructor"})
   1239                  || $dataNode->extendedAttributes->{"HasIndexGetter"}
   1240                  || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}
   1241                  || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}
   1242                  || $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}
   1243                  || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}
   1244                  || $dataNode->extendedAttributes->{"HasNameGetter"}
   1245                  || $dataNode->extendedAttributes->{"HasOverridingNameGetter"};
   1246 
   1247     # Attributes
   1248     if ($hasGetter) {
   1249         if (!$dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"} && !$dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}) {
   1250             push(@implContent, "bool ${className}::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n");
   1251             push(@implContent, "{\n");
   1252             push(@implContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 0));
   1253             push(@implContent, "}\n\n");
   1254             push(@implContent, "bool ${className}::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\n");
   1255             push(@implContent, "{\n");
   1256             push(@implContent, GenerateGetOwnPropertyDescriptorBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 0));
   1257             push(@implContent, "}\n\n");
   1258         }
   1259 
   1260         if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) 
   1261                 && !$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
   1262             push(@implContent, "bool ${className}::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)\n");
   1263             push(@implContent, "{\n");
   1264             push(@implContent, "    if (propertyName < static_cast<$implClassName*>(impl())->length()) {\n");
   1265             if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
   1266                 push(@implContent, "        slot.setValue(getByIndex(exec, propertyName));\n");
   1267             } else {
   1268                 push(@implContent, "        slot.setCustomIndex(this, propertyName, indexGetter);\n");
   1269             }
   1270             push(@implContent, "        return true;\n");
   1271             push(@implContent, "    }\n");
   1272             push(@implContent, "    return getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);\n");
   1273             push(@implContent, "}\n\n");
   1274         }
   1275         
   1276         if ($numAttributes > 0) {
   1277             foreach my $attribute (@{$dataNode->attributes}) {
   1278                 my $name = $attribute->signature->name;
   1279                 my $type = $codeGenerator->StripModule($attribute->signature->type);
   1280                 my $getFunctionName = "js" . $interfaceName .  $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
   1281                 my $implGetterFunctionName = $codeGenerator->WK_lcfirst($name);
   1282 
   1283                 my $conditional = $attribute->signature->extendedAttributes->{"Conditional"};
   1284                 if ($conditional) {
   1285                     $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
   1286                     push(@implContent, "#if ${conditionalString}\n");
   1287                 }
   1288 
   1289                 push(@implContent, "JSValue ${getFunctionName}(ExecState* exec, const Identifier&, const PropertySlot& slot)\n");
   1290                 push(@implContent, "{\n");
   1291                 push(@implContent, "    ${className}* castedThis = static_cast<$className*>(asObject(slot.slotBase()));\n");
   1292 
   1293                 my $implClassNameForValueConversion = "";
   1294                 if (!$podType and ($codeGenerator->IsSVGAnimatedType($implClassName) or $attribute->type !~ /^readonly/)) {
   1295                     $implClassNameForValueConversion = $implClassName;
   1296                 }
   1297 
   1298                 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && 
   1299                         !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurity"} &&
   1300                         !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurityOnGet"}) {
   1301                     push(@implContent, "    if (!castedThis->allowsAccessFrom(exec))\n");
   1302                     push(@implContent, "        return jsUndefined();\n");
   1303                 }
   1304 
   1305                 if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"} || $attribute->signature->extendedAttributes->{"CustomGetter"} || $attribute->signature->extendedAttributes->{"JSCCustomGetter"}) {
   1306                     push(@implContent, "    return castedThis->$implGetterFunctionName(exec);\n");
   1307                 } elsif ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) {
   1308                     $implIncludes{"JSDOMBinding.h"} = 1;
   1309                     push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");
   1310                     push(@implContent, "    return checkNodeSecurity(exec, imp->$implGetterFunctionName()) ? " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$implGetterFunctionName()", "castedThis") . " : jsUndefined();\n");
   1311                 } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) {
   1312                     $implIncludes{"Document.h"} = 1;
   1313                     $implIncludes{"JSDOMBinding.h"} = 1;
   1314                     push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");
   1315                     push(@implContent, "    return checkNodeSecurity(exec, imp->contentDocument()) ? " . NativeToJSValue($attribute->signature,  0, $implClassName, $implClassNameForValueConversion, "imp->$implGetterFunctionName()", "castedThis") . " : jsUndefined();\n");
   1316                 } elsif ($type eq "EventListener") {
   1317                     $implIncludes{"EventListener.h"} = 1;
   1318                     push(@implContent, "    UNUSED_PARAM(exec);\n");
   1319                     push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");
   1320                     push(@implContent, "    if (EventListener* listener = imp->$implGetterFunctionName()) {\n");
   1321                     push(@implContent, "        if (const JSEventListener* jsListener = JSEventListener::cast(listener)) {\n");
   1322                     if ($implClassName eq "Document" || $implClassName eq "WorkerContext" || $implClassName eq "SharedWorkerContext" || $implClassName eq "DedicatedWorkerContext") {
   1323                         push(@implContent, "            if (JSObject* jsFunction = jsListener->jsFunction(imp))\n");
   1324                     } else {
   1325                         push(@implContent, "            if (JSObject* jsFunction = jsListener->jsFunction(imp->scriptExecutionContext()))\n");
   1326                     }
   1327                     push(@implContent, "                return jsFunction;\n");
   1328                     push(@implContent, "        }\n");
   1329                     push(@implContent, "    }\n");
   1330                     push(@implContent, "    return jsNull();\n");
   1331                 } elsif ($attribute->signature->type =~ /Constructor$/) {
   1332                     my $constructorType = $codeGenerator->StripModule($attribute->signature->type);
   1333                     $constructorType =~ s/Constructor$//;
   1334                     # Constructor attribute is only used by DOMWindow.idl, so it's correct to pass castedThis as the global object
   1335                     # Once DOMObjects have a back-pointer to the globalObject we can pass castedThis->globalObject()
   1336                     push(@implContent, "    return JS" . $constructorType . "::getConstructor(exec, castedThis);\n");
   1337                 } elsif (!@{$attribute->getterExceptions}) {
   1338                     push(@implContent, "    UNUSED_PARAM(exec);\n");
   1339                     my $cacheIndex = 0;
   1340                     if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) {
   1341                         $cacheIndex = $currentCachedAttribute;
   1342                         $currentCachedAttribute++;
   1343                         push(@implContent, "    if (JSValue cachedValue = castedThis->getAnonymousValue(" . $className . "::" . $attribute->signature->name . "Slot))\n");
   1344                         push(@implContent, "        return cachedValue;\n");
   1345                     }
   1346                     if ($podType) {
   1347                         push(@implContent, "    $podType imp(*castedThis->impl());\n");
   1348                         if ($podType eq "float") { # Special case for JSSVGNumber
   1349                             push(@implContent, "    JSValue result =  " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp", "castedThis") . ";\n");
   1350                         } else {
   1351                             push(@implContent, "    JSValue result =  " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$implGetterFunctionName()", "castedThis") . ";\n");
   1352                         }
   1353                     } else {
   1354                         push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");
   1355                         my $value;
   1356                         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
   1357                         my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
   1358                         if ($reflect || $reflectURL) {
   1359                             my $contentAttributeName = (($reflect || $reflectURL) eq "1") ? $name : ($reflect || $reflectURL);
   1360                             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
   1361                             $implIncludes{"${namespace}.h"} = 1;
   1362                             my $getAttributeFunctionName = $reflectURL ? "getURLAttribute" : "getAttribute";
   1363                             $value = "imp->$getAttributeFunctionName(${namespace}::${contentAttributeName}Attr)"
   1364                         } else {
   1365                             $value = "imp->$implGetterFunctionName()";
   1366                         }
   1367                         my $jsType = NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, $value, "castedThis");
   1368                         if ($codeGenerator->IsSVGAnimatedType($type)) {
   1369                             push(@implContent, "    RefPtr<$type> obj = $jsType;\n");
   1370                             push(@implContent, "    JSValue result =  toJS(exec, castedThis->globalObject(), obj.get(), imp);\n");
   1371                         } else {
   1372                             push(@implContent, "    JSValue result = $jsType;\n");
   1373                         }
   1374                     }
   1375                     
   1376                     push(@implContent, "    castedThis->putAnonymousValue(" . $className . "::" . $attribute->signature->name . "Slot, result);\n") if ($attribute->signature->extendedAttributes->{"CachedAttribute"});
   1377                     push(@implContent, "    return result;\n");
   1378 
   1379                 } else {
   1380                     push(@implContent, "    ExceptionCode ec = 0;\n");                    
   1381                     if ($podType) {
   1382                         push(@implContent, "    $podType imp(*castedThis->impl());\n");
   1383                         push(@implContent, "    JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$implGetterFunctionName(ec)", "castedThis") . ";\n");
   1384                     } else {
   1385                         push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");
   1386                         push(@implContent, "    JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$implGetterFunctionName(ec)", "castedThis") . ";\n");
   1387                     }
   1388 
   1389                     push(@implContent, "    setDOMException(exec, ec);\n");
   1390                     push(@implContent, "    return result;\n");
   1391                 }
   1392 
   1393                 push(@implContent, "}\n");
   1394 
   1395                 if ($conditional) {
   1396                     push(@implContent, "#endif\n");
   1397                 }
   1398 
   1399                 push(@implContent, "\n");
   1400             }
   1401 
   1402             if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
   1403                 my $constructorFunctionName = "js" . $interfaceName . "Constructor";
   1404 
   1405                 push(@implContent, "JSValue ${constructorFunctionName}(ExecState* exec, const Identifier&, const PropertySlot& slot)\n");
   1406                 push(@implContent, "{\n");
   1407                 push(@implContent, "    ${className}* domObject = static_cast<$className*>(asObject(slot.slotBase()));\n");
   1408                 push(@implContent, "    return ${className}::getConstructor(exec, domObject->globalObject());\n");
   1409                 push(@implContent, "}\n");
   1410             }
   1411         }
   1412 
   1413         # Check if we have any writable attributes
   1414         my $hasReadWriteProperties = 0;
   1415         foreach my $attribute (@{$dataNode->attributes}) {
   1416             $hasReadWriteProperties = 1 if $attribute->type !~ /^readonly/;
   1417         }
   1418 
   1419         my $hasSetter = $hasReadWriteProperties
   1420                      || $dataNode->extendedAttributes->{"DelegatingPutFunction"}
   1421                      || $dataNode->extendedAttributes->{"HasCustomIndexSetter"};
   1422 
   1423         if ($hasSetter) {
   1424             if (!$dataNode->extendedAttributes->{"CustomPutFunction"}) {
   1425                 push(@implContent, "void ${className}::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)\n");
   1426                 push(@implContent, "{\n");
   1427                 if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
   1428                     push(@implContent, "    bool ok;\n");
   1429                     push(@implContent, "    unsigned index = propertyName.toUInt32(&ok, false);\n");
   1430                     push(@implContent, "    if (ok) {\n");
   1431                     push(@implContent, "        indexSetter(exec, index, value);\n");
   1432                     push(@implContent, "        return;\n");
   1433                     push(@implContent, "    }\n");
   1434                 }
   1435                 if ($dataNode->extendedAttributes->{"DelegatingPutFunction"}) {
   1436                     push(@implContent, "    if (putDelegate(exec, propertyName, value, slot))\n");
   1437                     push(@implContent, "        return;\n");
   1438                 }
   1439 
   1440                 if ($hasReadWriteProperties) {
   1441                     push(@implContent, "    lookupPut<$className, Base>(exec, propertyName, value, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, slot);\n");
   1442                 } else {
   1443                     push(@implContent, "    Base::put(exec, propertyName, value, slot);\n");
   1444                 }
   1445                 push(@implContent, "}\n\n");
   1446             }
   1447 
   1448             if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
   1449                 push(@implContent, "void ${className}::put(ExecState* exec, unsigned propertyName, JSValue value)\n");
   1450                 push(@implContent, "{\n");
   1451                 push(@implContent, "    indexSetter(exec, propertyName, value);\n");
   1452                 push(@implContent, "    return;\n");
   1453                 push(@implContent, "}\n\n");
   1454             }
   1455 
   1456             if ($hasReadWriteProperties) {
   1457                 foreach my $attribute (@{$dataNode->attributes}) {
   1458                     if ($attribute->type !~ /^readonly/) {
   1459                         my $name = $attribute->signature->name;
   1460                         my $type = $codeGenerator->StripModule($attribute->signature->type);
   1461                         my $putFunctionName = "setJS" . $interfaceName .  $codeGenerator->WK_ucfirst($name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
   1462                         my $implSetterFunctionName = $codeGenerator->WK_ucfirst($name);
   1463 
   1464                         push(@implContent, "void ${putFunctionName}(ExecState* exec, JSObject* thisObject, JSValue value)\n");
   1465                         push(@implContent, "{\n");
   1466 
   1467                         if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
   1468                             if ($interfaceName eq "DOMWindow") {
   1469                                 push(@implContent, "    if (!static_cast<$className*>(thisObject)->allowsAccessFrom(exec))\n");
   1470                             } else {
   1471                                 push(@implContent, "    if (!allowsAccessFromFrame(exec, static_cast<$className*>(thisObject)->impl()->frame()))\n");
   1472                             }
   1473                             push(@implContent, "        return;\n");
   1474                         }
   1475 
   1476                         if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"} || $attribute->signature->extendedAttributes->{"CustomSetter"} || $attribute->signature->extendedAttributes->{"JSCCustomSetter"}) {
   1477                             push(@implContent, "    static_cast<$className*>(thisObject)->set$implSetterFunctionName(exec, value);\n");
   1478                         } elsif ($type eq "EventListener") {
   1479                             $implIncludes{"JSEventListener.h"} = 1;
   1480                             push(@implContent, "    UNUSED_PARAM(exec);\n");
   1481                             push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(thisObject)->impl());\n");
   1482                             push(@implContent, "    imp->set$implSetterFunctionName(createJSAttributeEventListener(exec, value, thisObject));\n");
   1483                         } elsif ($attribute->signature->type =~ /Constructor$/) {
   1484                             my $constructorType = $attribute->signature->type;
   1485                             $constructorType =~ s/Constructor$//;
   1486                             $implIncludes{"JS" . $constructorType . ".h"} = 1;
   1487                             push(@implContent, "    // Shadowing a built-in constructor\n");
   1488                             push(@implContent, "    static_cast<$className*>(thisObject)->putDirect(Identifier(exec, \"$name\"), value);\n");
   1489                         } elsif ($attribute->signature->extendedAttributes->{"Replaceable"}) {
   1490                             push(@implContent, "    // Shadowing a built-in object\n");
   1491                             push(@implContent, "    static_cast<$className*>(thisObject)->putDirect(Identifier(exec, \"$name\"), value);\n");
   1492                         } else {
   1493                             push(@implContent, "    $className* castedThisObj = static_cast<$className*>(thisObject);\n");
   1494                             push(@implContent, "    $implType* imp = static_cast<$implType*>(castedThisObj->impl());\n");
   1495                             if ($podType) {
   1496                                 push(@implContent, "    $podType podImp(*imp);\n");
   1497                                 if ($podType eq "float") { # Special case for JSSVGNumber
   1498                                     push(@implContent, "    podImp = " . JSValueToNative($attribute->signature, "value") . ";\n");
   1499                                 } else {
   1500                                     push(@implContent, "    podImp.set$implSetterFunctionName(" . JSValueToNative($attribute->signature, "value") . ");\n");
   1501                                 }
   1502                                 push(@implContent, "    imp->commitChange(podImp, castedThisObj);\n");
   1503                             } else {
   1504                                 my $nativeValue = JSValueToNative($attribute->signature, "value");
   1505                                 push(@implContent, "    ExceptionCode ec = 0;\n") if @{$attribute->setterExceptions};
   1506                                 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
   1507                                 my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
   1508                                 if ($reflect || $reflectURL) {
   1509                                     my $contentAttributeName = (($reflect || $reflectURL) eq "1") ? $name : ($reflect || $reflectURL);
   1510                                     my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
   1511                                     $implIncludes{"${namespace}.h"} = 1;
   1512                                     push(@implContent, "    imp->setAttribute(${namespace}::${contentAttributeName}Attr, $nativeValue");
   1513                                 } else {
   1514                                     push(@implContent, "    imp->set$implSetterFunctionName($nativeValue");
   1515                                 }
   1516                                 push(@implContent, ", ec") if @{$attribute->setterExceptions};
   1517                                 push(@implContent, ");\n");
   1518                                 push(@implContent, "    setDOMException(exec, ec);\n") if @{$attribute->setterExceptions};
   1519                                 if (IsSVGTypeNeedingContextParameter($implClassName)) {
   1520                                     push(@implContent, "    JSSVGContextCache::propagateSVGDOMChange(castedThisObj, imp->associatedAttributeName());\n");
   1521                                 }
   1522                             }
   1523                         }
   1524                         
   1525                         push(@implContent, "}\n\n");
   1526                     }
   1527                 }
   1528             }
   1529         }
   1530     }
   1531 
   1532     if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) && !$dataNode->extendedAttributes->{"CustomGetPropertyNames"}) {
   1533         push(@implContent, "void ${className}::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)\n");
   1534         push(@implContent, "{\n");
   1535         if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
   1536             push(@implContent, "    for (unsigned i = 0; i < static_cast<${implClassName}*>(impl())->length(); ++i)\n");
   1537             push(@implContent, "        propertyNames.add(Identifier::from(exec, i));\n");
   1538         }
   1539         push(@implContent, "     Base::getOwnPropertyNames(exec, propertyNames, mode);\n");
   1540         push(@implContent, "}\n\n");
   1541     }
   1542 
   1543     if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
   1544         push(@implContent, "JSValue ${className}::getConstructor(ExecState* exec, JSGlobalObject* globalObject)\n{\n");
   1545         push(@implContent, "    return getDOMConstructor<${className}Constructor>(exec, static_cast<JSDOMGlobalObject*>(globalObject));\n");
   1546         push(@implContent, "}\n\n");
   1547     }
   1548 
   1549     # Functions
   1550     if ($numFunctions > 0) {
   1551         foreach my $function (@{$dataNode->functions}) {
   1552             AddIncludesForType($function->signature->type);
   1553 
   1554             my $functionName = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($function->signature->name);
   1555             my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementationFunction"} || $codeGenerator->WK_lcfirst($function->signature->name);
   1556 
   1557             push(@implContent, "JSValue JSC_HOST_CALL ${functionName}(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)\n");
   1558             push(@implContent, "{\n");
   1559             push(@implContent, "    UNUSED_PARAM(args);\n");
   1560 
   1561             $implIncludes{"<runtime/Error.h>"} = 1;
   1562 
   1563             if ($interfaceName eq "DOMWindow") {
   1564                 push(@implContent, "    $className* castedThisObj = toJSDOMWindow(thisValue.toThisObject(exec));\n");
   1565                 push(@implContent, "    if (!castedThisObj)\n");
   1566                 push(@implContent, "        return throwError(exec, TypeError);\n");
   1567             } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
   1568                 push(@implContent, "    $className* castedThisObj = to${className}(thisValue.toThisObject(exec));\n");
   1569                 push(@implContent, "    if (!castedThisObj)\n");
   1570                 push(@implContent, "        return throwError(exec, TypeError);\n");
   1571             } else {
   1572                 push(@implContent, "    if (!thisValue.inherits(&${className}::s_info))\n");
   1573                 push(@implContent, "        return throwError(exec, TypeError);\n");
   1574                 push(@implContent, "    $className* castedThisObj = static_cast<$className*>(asObject(thisValue));\n");
   1575             }
   1576 
   1577             if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && 
   1578                 !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
   1579                 push(@implContent, "    if (!castedThisObj->allowsAccessFrom(exec))\n");
   1580                 push(@implContent, "        return jsUndefined();\n");
   1581             }
   1582 
   1583             # Special case for JSSVGLengthList / JSSVGTransformList / JSSVGPointList / JSSVGNumberList
   1584             # Instead of having JSSVG*Custom.cpp implementations for the SVGList interface for all of these
   1585             # classes, we directly forward the calls to JSSVGPODListCustom, which centralizes the otherwise
   1586             # duplicated code for the JSSVG*List classes mentioned above.
   1587             my $svgPODListType;
   1588             if ($implClassName =~ /SVG.*List/) {
   1589                 $svgPODListType = $implClassName;
   1590                 $svgPODListType =~ s/List$//;
   1591                 $svgPODListType = "" unless $codeGenerator->IsPodType($svgPODListType);
   1592                 
   1593                 # Ignore additional (non-SVGList) SVGTransformList methods, that are not handled through JSSVGPODListCustom
   1594                 $svgPODListType = "" if $functionImplementationName =~ /createSVGTransformFromMatrix/;
   1595                 $svgPODListType = "" if $functionImplementationName =~ /consolidate/;
   1596             }
   1597 
   1598             if ($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"JSCCustom"}) {
   1599                 push(@implContent, "    return castedThisObj->" . $functionImplementationName . "(exec, args);\n");
   1600             } elsif ($svgPODListType) {
   1601                 $implIncludes{"JS${svgPODListType}.h"} = 1;
   1602                 $implIncludes{"JSSVGPODListCustom.h"} = 1;
   1603                 push(@implContent, "    return JSSVGPODListCustom::$functionImplementationName<$className, " . GetNativeType($svgPODListType)
   1604                                  . ">(castedThisObj, exec, args, to" . $svgPODListType . ");\n");
   1605             } else {
   1606                 push(@implContent, "    $implType* imp = static_cast<$implType*>(castedThisObj->impl());\n");
   1607                 push(@implContent, "    $podType podImp(*imp);\n") if $podType;
   1608 
   1609                 my $numParameters = @{$function->parameters};
   1610 
   1611                 if ($function->signature->extendedAttributes->{"RequiresAllArguments"}) {
   1612                         push(@implContent, "    if (args.size() < $numParameters)\n");
   1613                         push(@implContent, "        return jsUndefined();\n");
   1614                 }
   1615 
   1616                 if (@{$function->raisesExceptions}) {
   1617                     push(@implContent, "    ExceptionCode ec = 0;\n");
   1618                 }
   1619 
   1620                 if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) {
   1621                     push(@implContent, "    if (!checkNodeSecurity(exec, imp->getSVGDocument(" . (@{$function->raisesExceptions} ? "ec" : "") .")))\n");
   1622                     push(@implContent, "        return jsUndefined();\n");
   1623                     $implIncludes{"JSDOMBinding.h"} = 1;
   1624                 }
   1625 
   1626                 my $paramIndex = 0;
   1627                 my $functionString = ($podType ? "podImp." : "imp->") . $functionImplementationName . "(";
   1628 
   1629                 my $hasOptionalArguments = 0;
   1630 
   1631                 if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
   1632                     push(@implContent, "    ScriptCallStack callStack(exec, args, $numParameters);\n");
   1633                     $implIncludes{"ScriptCallStack.h"} = 1;
   1634                 }
   1635 
   1636                 foreach my $parameter (@{$function->parameters}) {
   1637                     if (!$hasOptionalArguments && $parameter->extendedAttributes->{"Optional"}) {
   1638                         push(@implContent, "\n    int argsCount = args.size();\n");
   1639                         $hasOptionalArguments = 1;
   1640                     }
   1641 
   1642                     if ($hasOptionalArguments) {
   1643                         push(@implContent, "    if (argsCount < " . ($paramIndex + 1) . ") {\n");
   1644                         GenerateImplementationFunctionCall($function, $functionString, $paramIndex, "    " x 2, $podType, $implClassName);
   1645                         push(@implContent, "    }\n\n");
   1646                     }
   1647 
   1648                     my $name = $parameter->name;
   1649                     
   1650                     if ($parameter->type eq "XPathNSResolver") {
   1651                         push(@implContent, "    RefPtr<XPathNSResolver> customResolver;\n");
   1652                         push(@implContent, "    XPathNSResolver* resolver = toXPathNSResolver(args.at($paramIndex));\n");
   1653                         push(@implContent, "    if (!resolver) {\n");
   1654                         push(@implContent, "        customResolver = JSCustomXPathNSResolver::create(exec, args.at($paramIndex));\n");
   1655                         push(@implContent, "        if (exec->hadException())\n");
   1656                         push(@implContent, "            return jsUndefined();\n");
   1657                         push(@implContent, "        resolver = customResolver.get();\n");
   1658                         push(@implContent, "    }\n");
   1659                     } else {
   1660                         push(@implContent, "    " . GetNativeTypeFromSignature($parameter) . " $name = " . JSValueToNative($parameter, "args.at($paramIndex)") . ";\n");
   1661 
   1662                         # If a parameter is "an index" and it's negative it should throw an INDEX_SIZE_ERR exception.
   1663                         # But this needs to be done in the bindings, because the type is unsigned and the fact that it
   1664                         # was negative will be lost by the time we're inside the DOM.
   1665                         if ($parameter->extendedAttributes->{"IsIndex"}) {
   1666                             $implIncludes{"ExceptionCode.h"} = 1;
   1667                             push(@implContent, "    if ($name < 0) {\n");
   1668                             push(@implContent, "        setDOMException(exec, INDEX_SIZE_ERR);\n");
   1669                             push(@implContent, "        return jsUndefined();\n");
   1670                             push(@implContent, "    }\n");
   1671                         }
   1672                     }
   1673 
   1674                     $functionString .= ", " if $paramIndex;
   1675 
   1676                     if ($parameter->type eq "NodeFilter") {
   1677                         $functionString .= "$name.get()";
   1678                     } else {
   1679                         $functionString .= $name;
   1680                     }
   1681                     $paramIndex++;
   1682                 }
   1683 
   1684                 if ($function->signature->extendedAttributes->{"NeedsUserGestureCheck"}) {
   1685                     $functionString .= ", " if $paramIndex;
   1686                     $functionString .= "processingUserGesture(exec)";
   1687                     $paramIndex++;
   1688                 }
   1689 
   1690                 push(@implContent, "\n");
   1691                 GenerateImplementationFunctionCall($function, $functionString, $paramIndex, "    ", $podType, $implClassName);
   1692             }
   1693             push(@implContent, "}\n\n");
   1694         }
   1695     }
   1696 
   1697     if ($numConstants > 0) {
   1698         push(@implContent, "// Constant getters\n\n");
   1699 
   1700         foreach my $constant (@{$dataNode->constants}) {
   1701             my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);
   1702 
   1703             # FIXME: this casts into int to match our previous behavior which turned 0xFFFFFFFF in -1 for NodeFilter.SHOW_ALL
   1704             push(@implContent, "JSValue ${getter}(ExecState* exec, const Identifier&, const PropertySlot&)\n");
   1705             push(@implContent, "{\n");
   1706             push(@implContent, "    return jsNumber(exec, static_cast<int>(" . $constant->value . "));\n");
   1707             push(@implContent, "}\n\n");
   1708         }
   1709     }
   1710 
   1711     if ($dataNode->extendedAttributes->{"HasIndexGetter"}) {
   1712         push(@implContent, "\nJSValue ${className}::indexGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)\n");
   1713         push(@implContent, "{\n");
   1714         push(@implContent, "    ${className}* thisObj = static_cast<$className*>(asObject(slot.slotBase()));\n");
   1715         if (IndexGetterReturnsStrings($implClassName)) {
   1716             $implIncludes{"KURL.h"} = 1;
   1717             push(@implContent, "    return jsStringOrNull(exec, thisObj->impl()->item(slot.index()));\n");
   1718         } else {
   1719             push(@implContent, "    return toJS(exec, thisObj->globalObject(), static_cast<$implClassName*>(thisObj->impl())->item(slot.index()));\n");
   1720         }
   1721         push(@implContent, "}\n");
   1722         if ($interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") {
   1723             $implIncludes{"JSNode.h"} = 1;
   1724             $implIncludes{"Node.h"} = 1;
   1725         }
   1726     }
   1727     
   1728     if ($dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
   1729         push(@implContent, "\nJSValue ${className}::getByIndex(ExecState* exec, unsigned index)\n");
   1730         push(@implContent, "{\n");
   1731         push(@implContent, "    return jsNumber(exec, static_cast<$implClassName*>(impl())->item(index));\n");
   1732         push(@implContent, "}\n");
   1733         if ($interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") {
   1734             $implIncludes{"JSNode.h"} = 1;
   1735             $implIncludes{"Node.h"} = 1;
   1736         }
   1737     }
   1738 
   1739     if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateToJS"}) and !$dataNode->extendedAttributes->{"CustomToJS"}) {
   1740         if ($podType) {
   1741             push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, JSSVGPODTypeWrapper<$podType>* object, SVGElement* context)\n");
   1742         } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
   1743             push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* object, SVGElement* context)\n");
   1744         } else {
   1745             push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* object)\n");
   1746         }
   1747         push(@implContent, "{\n");
   1748         if ($podType) {
   1749             push(@implContent, "    return getDOMObjectWrapper<$className, JSSVGPODTypeWrapper<$podType> >(exec, globalObject, object, context);\n");
   1750         } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
   1751             push(@implContent, "    return getDOMObjectWrapper<$className>(exec, globalObject, object, context);\n");
   1752         } else {
   1753             push(@implContent, "    return getDOMObjectWrapper<$className>(exec, globalObject, object);\n");
   1754         }
   1755         push(@implContent, "}\n");
   1756     }
   1757 
   1758     if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateNativeConverter"}) and !$dataNode->extendedAttributes->{"CustomNativeConverter"}) {
   1759         if ($podType) {
   1760             push(@implContent, "$podType to${interfaceName}(JSC::JSValue value)\n");
   1761         } else {
   1762             push(@implContent, "$implClassName* to${interfaceName}(JSC::JSValue value)\n");
   1763         }
   1764 
   1765         push(@implContent, "{\n");
   1766 
   1767         push(@implContent, "    return value.inherits(&${className}::s_info) ? " . ($podType ? "($podType) *" : "") . "static_cast<$className*>(asObject(value))->impl() : ");
   1768         if ($podType and $podType ne "float") {
   1769             push(@implContent, "$podType();\n}\n");
   1770         } else {
   1771             push(@implContent, "0;\n}\n");
   1772         }
   1773     }
   1774 
   1775     push(@implContent, "\n}\n");
   1776 
   1777     push(@implContent, "\n#endif // ${conditionalString}\n") if $conditional;
   1778 }
   1779 
   1780 sub GenerateImplementationFunctionCall()
   1781 {
   1782     my $function = shift;
   1783     my $functionString = shift;
   1784     my $paramIndex = shift;
   1785     my $indent = shift;
   1786     my $podType = shift;
   1787     my $implClassName = shift;
   1788 
   1789     if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
   1790         $functionString .= ", " if $paramIndex;
   1791         ++$paramIndex;
   1792         $functionString .= "&callStack";
   1793     }
   1794 
   1795     if (@{$function->raisesExceptions}) {
   1796         $functionString .= ", " if $paramIndex;
   1797         $functionString .= "ec";
   1798     }
   1799     $functionString .= ")";
   1800 
   1801     if ($function->signature->type eq "void") {
   1802         push(@implContent, $indent . "$functionString;\n");
   1803         push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions};
   1804         push(@implContent, $indent . "imp->commitChange(podImp, castedThisObj);\n") if $podType;
   1805         push(@implContent, $indent . "return jsUndefined();\n");
   1806     } else {
   1807         push(@implContent, "\n" . $indent . "JSC::JSValue result = " . NativeToJSValue($function->signature, 1, $implClassName, "", $functionString, "castedThisObj") . ";\n");
   1808         push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions};
   1809 
   1810         if ($podType and not $function->signature->extendedAttributes->{"Immutable"}) {
   1811             # Immutable methods do not commit changes back to the instance, thus producing
   1812             # a new instance rather than mutating existing one.
   1813             push(@implContent, $indent . "imp->commitChange(podImp, castedThisObj);\n");
   1814         }
   1815 
   1816         push(@implContent, $indent . "return result;\n");
   1817     }
   1818 }
   1819 
   1820 sub GetNativeTypeFromSignature
   1821 {
   1822     my $signature = shift;
   1823     my $type = $codeGenerator->StripModule($signature->type);
   1824 
   1825     if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) {
   1826         # Special-case index arguments because we need to check that they aren't < 0.
   1827         return "int";
   1828     }
   1829 
   1830     return GetNativeType($type);
   1831 }
   1832 
   1833 my %nativeType = (
   1834     "CompareHow" => "Range::CompareHow",
   1835     "DOMString" => "const UString&",
   1836     "NodeFilter" => "RefPtr<NodeFilter>",
   1837     "SVGAngle" => "SVGAngle",
   1838     "SVGLength" => "SVGLength",
   1839     "SVGMatrix" => "AffineTransform",
   1840     "SVGNumber" => "float",
   1841     "SVGPaintType" => "SVGPaint::SVGPaintType",
   1842     "SVGPreserveAspectRatio" => "SVGPreserveAspectRatio",
   1843     "SVGPoint" => "FloatPoint",
   1844     "SVGRect" => "FloatRect",
   1845     "SVGTransform" => "SVGTransform",
   1846     "boolean" => "bool",
   1847     "double" => "double",
   1848     "float" => "float",
   1849     "long" => "int",
   1850     "unsigned long" => "unsigned",
   1851     "unsigned short" => "unsigned short",
   1852     "long long" => "long long",
   1853     "unsigned long long" => "unsigned long long",
   1854 );
   1855 
   1856 sub GetNativeType
   1857 {
   1858     my $type = shift;
   1859 
   1860     return $nativeType{$type} if exists $nativeType{$type};
   1861 
   1862     # For all other types, the native type is a pointer with same type name as the IDL type.
   1863     return "${type}*";
   1864 }
   1865 
   1866 sub JSValueToNative
   1867 {
   1868     my $signature = shift;
   1869     my $value = shift;
   1870 
   1871     my $type = $codeGenerator->StripModule($signature->type);
   1872 
   1873     return "$value.toBoolean(exec)" if $type eq "boolean";
   1874     return "$value.toNumber(exec)" if $type eq "double";
   1875     return "$value.toFloat(exec)" if $type eq "float" or $type eq "SVGNumber";
   1876     return "$value.toInt32(exec)" if $type eq "unsigned long" or $type eq "long" or $type eq "unsigned short";
   1877     return "static_cast<$type>($value.toInteger(exec))" if $type eq "long long" or $type eq "unsigned long long";
   1878 
   1879     return "valueToDate(exec, $value)" if $type eq "Date";
   1880     return "static_cast<Range::CompareHow>($value.toInt32(exec))" if $type eq "CompareHow";
   1881     return "static_cast<SVGPaint::SVGPaintType>($value.toInt32(exec))" if $type eq "SVGPaintType";
   1882 
   1883     if ($type eq "DOMString") {
   1884         return "valueToStringWithNullCheck(exec, $value)" if $signature->extendedAttributes->{"ConvertNullToNullString"};
   1885         return "valueToStringWithUndefinedOrNullCheck(exec, $value)" if $signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"};
   1886         return "$value.toString(exec)";
   1887     }
   1888 
   1889     if ($type eq "SerializedScriptValue" or $type eq "any") {
   1890         $implIncludes{"SerializedScriptValue.h"} = 1;
   1891         return "SerializedScriptValue::create(exec, $value)";
   1892     }
   1893 
   1894     $implIncludes{"FloatPoint.h"} = 1 if $type eq "SVGPoint";
   1895     $implIncludes{"FloatRect.h"} = 1 if $type eq "SVGRect";
   1896     $implIncludes{"HTMLOptionElement.h"} = 1 if $type eq "HTMLOptionElement";
   1897     $implIncludes{"JSCustomVoidCallback.h"} = 1 if $type eq "VoidCallback";
   1898     $implIncludes{"Event.h"} = 1 if $type eq "Event";
   1899 
   1900     # Default, assume autogenerated type conversion routines
   1901     $implIncludes{"JS$type.h"} = 1;
   1902     return "to$type($value)";
   1903 }
   1904 
   1905 sub NativeToJSValue
   1906 {
   1907     my $signature = shift;
   1908     my $inFunctionCall = shift;
   1909     my $implClassName = shift;
   1910     my $implClassNameForValueConversion = shift;
   1911     my $value = shift;
   1912     my $thisValue = shift;
   1913 
   1914     my $type = $codeGenerator->StripModule($signature->type);
   1915 
   1916     return "jsBoolean($value)" if $type eq "boolean";
   1917 
   1918     # Need to check Date type before IsPrimitiveType().
   1919     if ($type eq "Date") {
   1920         return "jsDateOrNull(exec, $value)";
   1921     }
   1922     if ($codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType" or $type eq "DOMTimeStamp") {
   1923         $implIncludes{"<runtime/JSNumberCell.h>"} = 1;
   1924         return "jsNumber(exec, $value)";
   1925     }
   1926 
   1927     if ($codeGenerator->IsStringType($type)) {
   1928         $implIncludes{"KURL.h"} = 1;
   1929         my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"};
   1930         if (defined $conv) {
   1931             return "jsStringOrNull(exec, $value)" if $conv eq "Null";
   1932             return "jsStringOrUndefined(exec, $value)" if $conv eq "Undefined";
   1933             return "jsStringOrFalse(exec, $value)" if $conv eq "False";
   1934 
   1935             die "Unknown value for ConvertNullStringTo extended attribute";
   1936         }
   1937         $implIncludes{"<runtime/JSString.h>"} = 1;
   1938         return "jsString(exec, $value)";
   1939     }
   1940     
   1941     my $globalObject = "$thisValue->globalObject()";
   1942     if ($codeGenerator->IsPodType($type)) {
   1943         $implIncludes{"JS$type.h"} = 1;
   1944 
   1945         my $nativeType = GetNativeType($type);
   1946 
   1947         my $getter = $value;
   1948         $getter =~ s/imp->//;
   1949         $getter =~ s/\(\)//;
   1950 
   1951         my $setter = "set" . $codeGenerator->WK_ucfirst($getter);
   1952 
   1953         # Function calls will never return 'modifyable' POD types (ie. SVGRect getBBox()) - no need to keep track changes to the returned SVGRect
   1954         if ($inFunctionCall eq 0
   1955             and not $codeGenerator->IsSVGAnimatedType($implClassName)
   1956             and $codeGenerator->IsPodTypeWithWriteableProperties($type)
   1957             and not defined $signature->extendedAttributes->{"Immutable"}) {
   1958             if ($codeGenerator->IsPodType($implClassName)) {
   1959                 return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($value, $thisValue->impl()).get(), JSSVGContextCache::svgContextForDOMObject(castedThis))";
   1960             } else {
   1961                 return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName>::create(imp, &${implClassName}::$getter, &${implClassName}::$setter).get(), imp)";
   1962             }
   1963         }
   1964 
   1965         if ($implClassNameForValueConversion eq "") {
   1966             return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), 0 /* no context on purpose */)";
   1967         } else {
   1968             return "toJS(exec, $globalObject, JSSVGDynamicPODTypeWrapperCache<$nativeType, $implClassNameForValueConversion>::lookupOrCreateWrapper(imp, &${implClassNameForValueConversion}::$getter, &${implClassNameForValueConversion}::$setter).get(), JSSVGContextCache::svgContextForDOMObject(castedThis));"
   1969         }
   1970     }
   1971 
   1972     if ($codeGenerator->IsSVGAnimatedType($type)) {
   1973         # Some SVGFE*Element.idl use 'operator' as attribute name, rewrite as '_operator' to avoid clashes with C/C++
   1974         $value =~ s/operator\(\)/_operator\(\)/ if ($value =~ /operator/);
   1975         $value =~ s/\(\)//;
   1976         $value .= "Animated()";
   1977     }
   1978 
   1979     if ($type eq "CSSStyleDeclaration") {
   1980         $implIncludes{"CSSMutableStyleDeclaration.h"} = 1;
   1981     }
   1982 
   1983     if ($type eq "NodeList") {
   1984         $implIncludes{"NameNodeList.h"} = 1;
   1985     }
   1986 
   1987     if ($type eq "DOMObject") {
   1988         $implIncludes{"JSCanvasRenderingContext2D.h"} = 1;
   1989     } elsif ($type =~ /SVGPathSeg/) {
   1990         $implIncludes{"JS$type.h"} = 1;
   1991         $joinedName = $type;
   1992         $joinedName =~ s/Abs|Rel//;
   1993         $implIncludes{"$joinedName.h"} = 1;
   1994     } elsif ($type eq "SerializedScriptValue" or $type eq "any") {
   1995         $implIncludes{"SerializedScriptValue.h"} = 1;
   1996         return "$value ? $value->deserialize(exec, castedThis->globalObject()) : jsNull()";
   1997     } else {
   1998         # Default, include header with same name.
   1999         $implIncludes{"JS$type.h"} = 1;
   2000         $implIncludes{"$type.h"} = 1;
   2001     }
   2002 
   2003     return $value if $codeGenerator->IsSVGAnimatedType($type);
   2004 
   2005     if (IsSVGTypeNeedingContextParameter($type)) {
   2006         my $contextPtr = IsSVGTypeNeedingContextParameter($implClassName) ? "JSSVGContextCache::svgContextForDOMObject(castedThis)" : "imp";
   2007         return "toJS(exec, $globalObject, WTF::getPtr($value), $contextPtr)";
   2008     }
   2009 
   2010     if ($signature->extendedAttributes->{"ReturnsNew"}) {        
   2011         return "toJSNewlyCreated(exec, $globalObject, WTF::getPtr($value))";
   2012     }
   2013 
   2014     return "toJS(exec, $globalObject, WTF::getPtr($value))";
   2015 }
   2016 
   2017 sub ceilingToPowerOf2
   2018 {
   2019     my ($size) = @_;
   2020 
   2021     my $powerOf2 = 1;
   2022     while ($size > $powerOf2) {
   2023         $powerOf2 <<= 1;
   2024     }
   2025 
   2026     return $powerOf2;
   2027 }
   2028 
   2029 # Internal Helper
   2030 sub GenerateHashTable
   2031 {
   2032     my $object = shift;
   2033 
   2034     my $name = shift;
   2035     my $size = shift;
   2036     my $keys = shift;
   2037     my $specials = shift;
   2038     my $value1 = shift;
   2039     my $value2 = shift;
   2040     my $conditionals = shift;
   2041 
   2042     # Generate size data for two hash tables
   2043     # - The 'perfect' size makes a table large enough for perfect hashing
   2044     # - The 'compact' size uses the legacy table format for smaller table sizes
   2045 
   2046     # Perfect size
   2047     my @hashes = ();
   2048     foreach my $key (@{$keys}) {
   2049         push @hashes, $object->GenerateHashValue($key);
   2050     }
   2051 
   2052     # Compact size
   2053     my @table = ();
   2054     my @links = ();
   2055 
   2056     my $compactSize = ceilingToPowerOf2($size * 2);
   2057 
   2058     my $maxDepth = 0;
   2059     my $collisions = 0;
   2060     my $numEntries = $compactSize;
   2061 
   2062     my $i = 0;
   2063     foreach (@{$keys}) {
   2064         my $depth = 0;
   2065         my $h = $object->GenerateHashValue($_) % $numEntries;
   2066 
   2067         while (defined($table[$h])) {
   2068             if (defined($links[$h])) {
   2069                 $h = $links[$h];
   2070                 $depth++;
   2071             } else {
   2072                 $collisions++;
   2073                 $links[$h] = $compactSize;
   2074                 $h = $compactSize;
   2075                 $compactSize++;
   2076             }
   2077         }
   2078 
   2079         $table[$h] = $i;
   2080 
   2081         $i++;
   2082         $maxDepth = $depth if ($depth > $maxDepth);
   2083     }
   2084 
   2085     # Collect hashtable information
   2086     my $perfectSize;
   2087 tableSizeLoop:
   2088     for ($perfectSize = ceilingToPowerOf2(scalar @{$keys}); ; $perfectSize += $perfectSize) {
   2089         my @table = ();
   2090         my $i = 0;
   2091         foreach my $hash (@hashes) {
   2092             my $h = $hash % $perfectSize;
   2093             next tableSizeLoop if defined $table[$h];
   2094             $table[$h] = $i++;
   2095         }
   2096         last;
   2097     }
   2098 
   2099     # Start outputing the hashtables
   2100     my $nameEntries = "${name}Values";
   2101     $nameEntries =~ s/:/_/g;
   2102 
   2103     if (($name =~ /Prototype/) or ($name =~ /Constructor/)) {
   2104         my $type = $name;
   2105         my $implClass;
   2106 
   2107         if ($name =~ /Prototype/) {
   2108             $type =~ s/Prototype.*//;
   2109             $implClass = $type; $implClass =~ s/Wrapper$//;
   2110             push(@implContent, "/* Hash table for prototype */\n");
   2111         } else {
   2112             $type =~ s/Constructor.*//;
   2113             $implClass = $type; $implClass =~ s/Constructor$//;
   2114             push(@implContent, "/* Hash table for constructor */\n");
   2115         }
   2116     } else {
   2117         push(@implContent, "/* Hash table */\n");
   2118     }
   2119 
   2120     # Dump the hash table
   2121     my $count = scalar @{$keys} + 1;
   2122     push(@implContent, "\nstatic const HashTableValue $nameEntries\[$count\] =\n\{\n");
   2123     $i = 0;
   2124     foreach my $key (@{$keys}) {
   2125         my $conditional;
   2126 
   2127         if ($conditionals) {
   2128             $conditional = $conditionals->{$key};
   2129         }
   2130         if ($conditional) {
   2131             my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
   2132             push(@implContent, "#if ${conditionalString}\n");
   2133         }
   2134         push(@implContent, "    { \"$key\", @$specials[$i], (intptr_t)@$value1[$i], (intptr_t)@$value2[$i] },\n");
   2135         if ($conditional) {
   2136             push(@implContent, "#endif\n");
   2137         }
   2138         ++$i;
   2139     }
   2140     push(@implContent, "    { 0, 0, 0, 0 }\n");
   2141     push(@implContent, "};\n\n");
   2142     my $perfectSizeMask = $perfectSize - 1;
   2143     my $compactSizeMask = $numEntries - 1;
   2144     push(@implContent, "static JSC_CONST_HASHTABLE HashTable $name =\n");
   2145     push(@implContent, "#if ENABLE(PERFECT_HASH_SIZE)\n");
   2146     push(@implContent, "    { $perfectSizeMask, $nameEntries, 0 };\n");
   2147     push(@implContent, "#else\n");
   2148     push(@implContent, "    { $compactSize, $compactSizeMask, $nameEntries, 0 };\n");
   2149     push(@implContent, "#endif\n\n");
   2150 }
   2151 
   2152 # Internal helper
   2153 sub GenerateHashValue
   2154 {
   2155     my $object = shift;
   2156 
   2157     @chars = split(/ */, $_[0]);
   2158 
   2159     # This hash is designed to work on 16-bit chunks at a time. But since the normal case
   2160     # (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they
   2161     # were 16-bit chunks, which should give matching results
   2162 
   2163     my $EXP2_32 = 4294967296;
   2164 
   2165     my $hash = 0x9e3779b9;
   2166     my $l    = scalar @chars; #I wish this was in Ruby --- Maks
   2167     my $rem  = $l & 1;
   2168     $l = $l >> 1;
   2169 
   2170     my $s = 0;
   2171 
   2172     # Main loop
   2173     for (; $l > 0; $l--) {
   2174         $hash   += ord($chars[$s]);
   2175         my $tmp = leftShift(ord($chars[$s+1]), 11) ^ $hash;
   2176         $hash   = (leftShift($hash, 16)% $EXP2_32) ^ $tmp;
   2177         $s += 2;
   2178         $hash += $hash >> 11;
   2179         $hash %= $EXP2_32;
   2180     }
   2181 
   2182     # Handle end case
   2183     if ($rem != 0) {
   2184         $hash += ord($chars[$s]);
   2185         $hash ^= (leftShift($hash, 11)% $EXP2_32);
   2186         $hash += $hash >> 17;
   2187     }
   2188 
   2189     # Force "avalanching" of final 127 bits
   2190     $hash ^= leftShift($hash, 3);
   2191     $hash += ($hash >> 5);
   2192     $hash = ($hash% $EXP2_32);
   2193     $hash ^= (leftShift($hash, 2)% $EXP2_32);
   2194     $hash += ($hash >> 15);
   2195     $hash = $hash% $EXP2_32;
   2196     $hash ^= (leftShift($hash, 10)% $EXP2_32);
   2197 
   2198     # this avoids ever returning a hash code of 0, since that is used to
   2199     # signal "hash not computed yet", using a value that is likely to be
   2200     # effectively the same as 0 when the low bits are masked
   2201     $hash = 0x80000000 if ($hash == 0);
   2202 
   2203     return $hash;
   2204 }
   2205 
   2206 # Internal helper
   2207 sub WriteData
   2208 {
   2209     if (defined($IMPL)) {
   2210         # Write content to file.
   2211         print $IMPL @implContentHeader;
   2212 
   2213         my @includes = ();
   2214         foreach my $include (keys %implIncludes) {
   2215             my $checkType = $include;
   2216             $checkType =~ s/\.h//;
   2217             next if $codeGenerator->IsSVGAnimatedType($checkType);
   2218 
   2219             $include = "\"$include\"" unless $include =~ /^["<]/; # "
   2220             push @includes, $include;
   2221         }
   2222         foreach my $include (sort @includes) {
   2223             print $IMPL "#include $include\n";
   2224         }
   2225 
   2226         print $IMPL @implContent;
   2227         close($IMPL);
   2228         undef($IMPL);
   2229 
   2230         @implContentHeader = ();
   2231         @implContent = ();
   2232         %implIncludes = ();
   2233     }
   2234 
   2235     if (defined($HEADER)) {
   2236         # Write content to file.
   2237         print $HEADER @headerContentHeader;
   2238 
   2239         my @includes = ();
   2240         foreach my $include (keys %headerIncludes) {
   2241             $include = "\"$include\"" unless $include =~ /^["<]/; # "
   2242             push @includes, $include;
   2243         }
   2244         foreach my $include (sort @includes) {
   2245             print $HEADER "#include $include\n";
   2246         }
   2247 
   2248         print $HEADER @headerContent;
   2249         close($HEADER);
   2250         undef($HEADER);
   2251 
   2252         @headerContentHeader = ();
   2253         @headerContent = ();
   2254         %headerIncludes = ();
   2255     }
   2256 
   2257     if (defined($DEPS)) {
   2258         # Write dependency file.
   2259         print $DEPS @depsContent;
   2260         close($DEPS);
   2261         undef($DEPS);
   2262 
   2263         @depsContent = ();
   2264     }
   2265 }
   2266 
   2267 sub constructorFor
   2268 {
   2269     my $className = shift;
   2270     my $protoClassName = shift;
   2271     my $interfaceName = shift;
   2272     my $visibleClassName = shift;
   2273     my $canConstruct = shift;
   2274     my $constructorClassName = "${className}Constructor";
   2275 
   2276 my $implContent = << "EOF";
   2277 class ${constructorClassName} : public DOMConstructorObject {
   2278 public:
   2279     ${constructorClassName}(ExecState* exec, JSDOMGlobalObject* globalObject)
   2280         : DOMConstructorObject(${constructorClassName}::createStructure(globalObject->objectPrototype()), globalObject)
   2281     {
   2282         putDirect(exec->propertyNames().prototype, ${protoClassName}::self(exec, globalObject), None);
   2283     }
   2284     virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
   2285     virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
   2286     virtual const ClassInfo* classInfo() const { return &s_info; }
   2287     static const ClassInfo s_info;
   2288 
   2289     static PassRefPtr<Structure> createStructure(JSValue proto) 
   2290     { 
   2291         return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); 
   2292     }
   2293     
   2294 protected:
   2295     static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | DOMConstructorObject::StructureFlags;
   2296 EOF
   2297 
   2298     if ($canConstruct) {
   2299 $implContent .= << "EOF";
   2300     static JSObject* construct${interfaceName}(ExecState* exec, JSObject* constructor, const ArgList&)
   2301     {
   2302         return asObject(toJS(exec, static_cast<${constructorClassName}*>(constructor)->globalObject(), ${interfaceName}::create()));
   2303     }
   2304     virtual ConstructType getConstructData(ConstructData& constructData)
   2305     {
   2306         constructData.native.function = construct${interfaceName};
   2307         return ConstructTypeHost;
   2308     }
   2309 EOF
   2310     }
   2311 
   2312 $implContent .= << "EOF";
   2313 };
   2314 
   2315 const ClassInfo ${constructorClassName}::s_info = { "${visibleClassName}Constructor", 0, &${constructorClassName}Table, 0 };
   2316 
   2317 bool ${constructorClassName}::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
   2318 {
   2319     return getStaticValueSlot<${constructorClassName}, DOMObject>(exec, &${constructorClassName}Table, this, propertyName, slot);
   2320 }
   2321 
   2322 bool ${constructorClassName}::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
   2323 {
   2324     return getStaticValueDescriptor<${constructorClassName}, DOMObject>(exec, &${constructorClassName}Table, this, propertyName, descriptor);
   2325 }
   2326 
   2327 EOF
   2328 
   2329     $implJSCInclude{"JSNumberCell.h"} = 1; # FIXME: What is this for?
   2330 
   2331     return $implContent;
   2332 }
   2333 
   2334 1;
   2335