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