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, 2010 Apple Inc. All rights reserved.
      7 # Copyright (C) 2009 Cameron McCormack <cam (at] mcc.id.au>
      8 # Copyright (C) Research In Motion Limited 2010. All rights reserved.
      9 # Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
     10 #
     11 # This library is free software; you can redistribute it and/or
     12 # modify it under the terms of the GNU Library General Public
     13 # License as published by the Free Software Foundation; either
     14 # version 2 of the License, or (at your option) any later version.
     15 #
     16 # This library is distributed in the hope that it will be useful,
     17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
     18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     19 # Library General Public License for more details.
     20 #
     21 # You should have received a copy of the GNU Library General Public License
     22 # along with this library; see the file COPYING.LIB.  If not, write to
     23 # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     24 # Boston, MA 02110-1301, USA.
     25 
     26 package CodeGeneratorJS;
     27 
     28 my $module = "";
     29 my $outputDir = "";
     30 my $writeDependencies = 0;
     31 
     32 my @headerContentHeader = ();
     33 my @headerContent = ();
     34 my %headerIncludes = ();
     35 my %headerTrailingIncludes = ();
     36 
     37 my @implContentHeader = ();
     38 my @implContent = ();
     39 my %implIncludes = ();
     40 my @depsContent = ();
     41 my $numCachedAttributes = 0;
     42 my $currentCachedAttribute = 0;
     43 
     44 # Default .h template
     45 my $headerTemplate = << "EOF";
     46 /*
     47     This file is part of the WebKit open source project.
     48     This file has been generated by generate-bindings.pl. DO NOT MODIFY!
     49 
     50     This library is free software; you can redistribute it and/or
     51     modify it under the terms of the GNU Library General Public
     52     License as published by the Free Software Foundation; either
     53     version 2 of the License, or (at your option) any later version.
     54 
     55     This library is distributed in the hope that it will be useful,
     56     but WITHOUT ANY WARRANTY; without even the implied warranty of
     57     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     58     Library General Public License for more details.
     59 
     60     You should have received a copy of the GNU Library General Public License
     61     along with this library; see the file COPYING.LIB.  If not, write to
     62     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     63     Boston, MA 02110-1301, USA.
     64 */
     65 EOF
     66 
     67 # Default constructor
     68 sub new
     69 {
     70     my $object = shift;
     71     my $reference = { };
     72 
     73     $codeGenerator = shift;
     74     $outputDir = shift;
     75     shift; # $outputHeadersDir
     76     shift; # $useLayerOnTop
     77     shift; # $preprocessor
     78     $writeDependencies = shift;
     79 
     80     bless($reference, $object);
     81     return $reference;
     82 }
     83 
     84 sub finish
     85 {
     86     my $object = shift;
     87 
     88     # Commit changes!
     89     $object->WriteData();
     90 }
     91 
     92 sub leftShift($$) {
     93     my ($value, $distance) = @_;
     94     return (($value << $distance) & 0xFFFFFFFF);
     95 }
     96 
     97 # Params: 'domClass' struct
     98 sub GenerateInterface
     99 {
    100     my $object = shift;
    101     my $dataNode = shift;
    102     my $defines = shift;
    103 
    104     $codeGenerator->LinkOverloadedFunctions($dataNode);
    105 
    106     # Start actual generation
    107     if ($dataNode->extendedAttributes->{"Callback"}) {
    108         $object->GenerateCallbackHeader($dataNode);
    109         $object->GenerateCallbackImplementation($dataNode);
    110     } else {
    111         $object->GenerateHeader($dataNode);
    112         $object->GenerateImplementation($dataNode);
    113     }
    114 
    115     my $name = $dataNode->name;
    116 
    117     # Open files for writing
    118     my $headerFileName = "$outputDir/JS$name.h";
    119     my $implFileName = "$outputDir/JS$name.cpp";
    120     my $depsFileName = "$outputDir/JS$name.dep";
    121 
    122     # Remove old dependency file.
    123     unlink($depsFileName);
    124 
    125     open($IMPL, ">$implFileName") || die "Couldn't open file $implFileName";
    126     open($HEADER, ">$headerFileName") || die "Couldn't open file $headerFileName";
    127     if (@depsContent) {
    128         open($DEPS, ">$depsFileName") || die "Couldn't open file $depsFileName";
    129     }
    130 }
    131 
    132 sub GenerateAttributeEventListenerCall
    133 {
    134     my $className = shift;
    135     my $implSetterFunctionName = shift;
    136     my $windowEventListener = shift;
    137 
    138     my $wrapperObject = $windowEventListener ? "globalObject" : "thisObject";
    139     my @GenerateEventListenerImpl = ();
    140 
    141     if ($className eq "JSSVGElementInstance") {
    142         # SVGElementInstances have to create JSEventListeners with the wrapper equal to the correspondingElement
    143         $wrapperObject = "asObject(correspondingElementWrapper)";
    144 
    145         push(@GenerateEventListenerImpl, <<END);
    146     JSValue correspondingElementWrapper = toJS(exec, imp->correspondingElement());
    147     if (correspondingElementWrapper.isObject())
    148 END
    149 
    150         # Add leading whitespace to format the imp->set... line correctly
    151         push(@GenerateEventListenerImpl, "    ");
    152     }
    153 
    154     push(@GenerateEventListenerImpl, "    imp->set$implSetterFunctionName(createJSAttributeEventListener(exec, value, $wrapperObject));\n");
    155     return @GenerateEventListenerImpl;
    156 }
    157 
    158 sub GenerateEventListenerCall
    159 {
    160     my $className = shift;
    161     my $functionName = shift;
    162     my $passRefPtrHandling = ($functionName eq "add") ? "" : ".get()";
    163 
    164     $implIncludes{"JSEventListener.h"} = 1;
    165 
    166     my @GenerateEventListenerImpl = ();
    167     my $wrapperObject = "castedThis";
    168     if ($className eq "JSSVGElementInstance") {
    169         # SVGElementInstances have to create JSEventListeners with the wrapper equal to the correspondingElement
    170         $wrapperObject = "asObject(correspondingElementWrapper)";
    171 
    172         push(@GenerateEventListenerImpl, <<END);
    173     JSValue correspondingElementWrapper = toJS(exec, imp->correspondingElement());
    174     if (!correspondingElementWrapper.isObject())
    175         return JSValue::encode(jsUndefined());
    176 END
    177     }
    178 
    179     push(@GenerateEventListenerImpl, <<END);
    180     JSValue listener = exec->argument(1);
    181     if (!listener.isObject())
    182         return JSValue::encode(jsUndefined());
    183     imp->${functionName}EventListener(ustringToAtomicString(exec->argument(0).toString(exec)), JSEventListener::create(asObject(listener), $wrapperObject, false, currentWorld(exec))$passRefPtrHandling, exec->argument(2).toBoolean(exec));
    184     return JSValue::encode(jsUndefined());
    185 END
    186     return @GenerateEventListenerImpl;
    187 }
    188 
    189 # Params: 'idlDocument' struct
    190 sub GenerateModule
    191 {
    192     my $object = shift;
    193     my $dataNode = shift;
    194 
    195     $module = $dataNode->module;
    196 }
    197 
    198 sub GetParentClassName
    199 {
    200     my $dataNode = shift;
    201 
    202     return $dataNode->extendedAttributes->{"LegacyParent"} if $dataNode->extendedAttributes->{"LegacyParent"};
    203     return "JSDOMWrapperWithGlobalPointer" if (@{$dataNode->parents} eq 0);
    204     return "JS" . $codeGenerator->StripModule($dataNode->parents(0));
    205 }
    206 
    207 sub GetVisibleClassName
    208 {
    209     my $className = shift;
    210 
    211     return "DOMException" if $className eq "DOMCoreException";
    212     return "FormData" if $className eq "DOMFormData";
    213     return "MimeType" if $className eq "DOMMimeType";
    214     return "MimeTypeArray" if $className eq "DOMMimeTypeArray";
    215     return "Plugin" if $className eq "DOMPlugin";
    216     return "PluginArray" if $className eq "DOMPluginArray";
    217     
    218     return $className;
    219 }
    220 
    221 sub GetCallbackClassName
    222 {
    223     my $className = shift;
    224 
    225     return "JSCustomVoidCallback" if $className eq "VoidCallback";
    226     return "JS$className";
    227 }
    228 
    229 sub IndexGetterReturnsStrings
    230 {
    231     my $type = shift;
    232 
    233     return 1 if $type eq "CSSStyleDeclaration" or $type eq "MediaList" or $type eq "DOMStringList" or $type eq "DOMTokenList" or $type eq "DOMSettableTokenList";
    234     return 0;
    235 }
    236 
    237 sub AddIncludesForType
    238 {
    239     my $type = $codeGenerator->StripModule(shift);
    240     my $isCallback = @_ ? shift : 0;
    241 
    242     # When we're finished with the one-file-per-class
    243     # reorganization, we won't need these special cases.
    244     if ($codeGenerator->IsPrimitiveType($type) or $codeGenerator->AvoidInclusionOfType($type)
    245         or $type eq "DOMString" or $type eq "DOMObject" or $type eq "Array") {
    246     } elsif ($type =~ /SVGPathSeg/) {
    247         $joinedName = $type;
    248         $joinedName =~ s/Abs|Rel//;
    249         $implIncludes{"${joinedName}.h"} = 1;
    250     } elsif ($type eq "XPathNSResolver") {
    251         $implIncludes{"JSXPathNSResolver.h"} = 1;
    252         $implIncludes{"JSCustomXPathNSResolver.h"} = 1;
    253     } elsif ($isCallback) {
    254         $implIncludes{"JS${type}.h"} = 1;
    255     } else {
    256         # default, include the same named file
    257         $implIncludes{"${type}.h"} = 1;
    258     }
    259 
    260     # additional includes (things needed to compile the bindings but not the header)
    261 
    262     if ($type eq "CanvasRenderingContext2D") {
    263         $implIncludes{"CanvasGradient.h"} = 1;
    264         $implIncludes{"CanvasPattern.h"} = 1;
    265         $implIncludes{"CanvasStyle.h"} = 1;
    266     }
    267 
    268     if ($type eq "CanvasGradient" or $type eq "XPathNSResolver" or $type eq "MessagePort") {
    269         $implIncludes{"PlatformString.h"} = 1;
    270     }
    271 
    272     if ($type eq "Document") {
    273         $implIncludes{"NodeFilter.h"} = 1;
    274     }
    275 
    276     if ($type eq "MediaQueryListListener") {
    277         $implIncludes{"MediaQueryListListener.h"} = 1;
    278     }
    279 }
    280 
    281 # FIXME: This method will go away once all SVG animated properties are converted to the new scheme.
    282 sub AddIncludesForSVGAnimatedType
    283 {
    284     my $type = shift;
    285     $type =~ s/SVGAnimated//;
    286 
    287     if ($type eq "Point" or $type eq "Rect") {
    288         $implIncludes{"Float$type.h"} = 1;
    289     } elsif ($type eq "String") {
    290         $implIncludes{"PlatformString.h"} = 1;
    291     }
    292 }
    293 
    294 sub IsScriptProfileType
    295 {
    296     my $type = shift;
    297     return 1 if ($type eq "ScriptProfileNode");
    298     return 0;
    299 }
    300 
    301 sub AddTypedefForScriptProfileType
    302 {
    303     my $type = shift;
    304     (my $jscType = $type) =~ s/Script//;
    305 
    306     push(@headerContent, "typedef JSC::$jscType $type;\n\n");
    307 }
    308 
    309 sub AddClassForwardIfNeeded
    310 {
    311     my $implClassName = shift;
    312 
    313     # SVGAnimatedLength/Number/etc. are typedefs to SVGAnimatedTemplate, so don't use class forwards for them!
    314     unless ($codeGenerator->IsSVGAnimatedType($implClassName) or IsScriptProfileType($implClassName)) {
    315         push(@headerContent, "class $implClassName;\n\n");
    316     # ScriptProfile and ScriptProfileNode are typedefs to JSC::Profile and JSC::ProfileNode.
    317     } elsif (IsScriptProfileType($implClassName)) {
    318         AddTypedefForScriptProfileType($implClassName);
    319     }
    320 }
    321 
    322 sub HashValueForClassAndName
    323 {
    324     my $class = shift;
    325     my $name = shift;
    326 
    327     # SVG Filter enums live in WebCore namespace (platform/graphics/)
    328     if ($class =~ /^SVGFE*/ or $class =~ /^SVGComponentTransferFunctionElement$/) {
    329         return "WebCore::$name";
    330     }
    331 
    332     return "${class}::$name";
    333 }
    334 
    335 sub hashTableAccessor
    336 {
    337     my $noStaticTables = shift;
    338     my $className = shift;
    339     if ($noStaticTables) {
    340         return "get${className}Table(exec)";
    341     } else {
    342         return "&${className}Table";
    343     }
    344 }
    345 
    346 sub prototypeHashTableAccessor
    347 {
    348     my $noStaticTables = shift;
    349     my $className = shift;
    350     if ($noStaticTables) {
    351         return "get${className}PrototypeTable(exec)";
    352     } else {
    353         return "&${className}PrototypeTable";
    354     }
    355 }
    356 
    357 sub GenerateConditionalStringFromAttributeValue
    358 {
    359     my $conditional = shift;
    360     if ($conditional =~ /&/) {
    361         return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
    362     } elsif ($conditional =~ /\|/) {
    363         return "ENABLE(" . join(") || ENABLE(", split(/\|/, $conditional)) . ")";
    364     } else {
    365         return "ENABLE(" . $conditional . ")";
    366     }
    367 }
    368 
    369 sub GenerateConditionalString
    370 {
    371     my $node = shift;
    372     my $conditional = $node->extendedAttributes->{"Conditional"};
    373     if ($conditional) {
    374         return GenerateConditionalStringFromAttributeValue($conditional);
    375     } else {
    376         return "";
    377     }
    378 }
    379 
    380 sub GenerateGetOwnPropertySlotBody
    381 {
    382     my ($dataNode, $interfaceName, $className, $implClassName, $hasAttributes, $inlined) = @_;
    383 
    384     my $namespaceMaybe = ($inlined ? "JSC::" : "");
    385 
    386     my @getOwnPropertySlotImpl = ();
    387 
    388     if ($interfaceName eq "NamedNodeMap" or $interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") {
    389         push(@getOwnPropertySlotImpl, "    ${namespaceMaybe}JSValue proto = prototype();\n");
    390         push(@getOwnPropertySlotImpl, "    if (proto.isObject() && static_cast<${namespaceMaybe}JSObject*>(asObject(proto))->hasProperty(exec, propertyName))\n");
    391         push(@getOwnPropertySlotImpl, "        return false;\n\n");
    392     }
    393 
    394     my $manualLookupGetterGeneration = sub {
    395         my $requiresManualLookup = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasNameGetter"};
    396         if ($requiresManualLookup) {
    397             push(@getOwnPropertySlotImpl, "    const ${namespaceMaybe}HashEntry* entry = ${className}Table.entry(exec, propertyName);\n");
    398             push(@getOwnPropertySlotImpl, "    if (entry) {\n");
    399             push(@getOwnPropertySlotImpl, "        slot.setCustom(this, entry->propertyGetter());\n");
    400             push(@getOwnPropertySlotImpl, "        return true;\n");
    401             push(@getOwnPropertySlotImpl, "    }\n");
    402         }
    403     };
    404 
    405     if (!$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
    406         &$manualLookupGetterGeneration();
    407     }
    408 
    409     if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
    410         push(@getOwnPropertySlotImpl, "    bool ok;\n");
    411         push(@getOwnPropertySlotImpl, "    unsigned index = propertyName.toUInt32(ok);\n");
    412 
    413         # If the item function returns a string then we let the ConvertNullStringTo handle the cases
    414         # where the index is out of range.
    415         if (IndexGetterReturnsStrings($implClassName)) {
    416             push(@getOwnPropertySlotImpl, "    if (ok) {\n");
    417         } else {
    418             push(@getOwnPropertySlotImpl, "    if (ok && index < static_cast<$implClassName*>(impl())->length()) {\n");
    419         }
    420         if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
    421             push(@getOwnPropertySlotImpl, "        slot.setValue(getByIndex(exec, index));\n");
    422         } else {
    423             push(@getOwnPropertySlotImpl, "        slot.setCustomIndex(this, index, indexGetter);\n");
    424         }
    425         push(@getOwnPropertySlotImpl, "        return true;\n");
    426         push(@getOwnPropertySlotImpl, "    }\n");
    427     }
    428 
    429     if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
    430         push(@getOwnPropertySlotImpl, "    if (canGetItemsForName(exec, static_cast<$implClassName*>(impl()), propertyName)) {\n");
    431         push(@getOwnPropertySlotImpl, "        slot.setCustom(this, nameGetter);\n");
    432         push(@getOwnPropertySlotImpl, "        return true;\n");
    433         push(@getOwnPropertySlotImpl, "    }\n");
    434         if ($inlined) {
    435             $headerIncludes{"wtf/text/AtomicString.h"} = 1;
    436         } else {
    437             $implIncludes{"wtf/text/AtomicString.h"} = 1;
    438         }
    439     }
    440 
    441     if ($dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
    442         &$manualLookupGetterGeneration();
    443     }
    444 
    445     if ($dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}) {
    446         push(@getOwnPropertySlotImpl, "    if (getOwnPropertySlotDelegate(exec, propertyName, slot))\n");
    447         push(@getOwnPropertySlotImpl, "        return true;\n");
    448     }
    449 
    450     if ($hasAttributes) {
    451         if ($inlined) {
    452             die "Cannot inline if NoStaticTables is set." if ($dataNode->extendedAttributes->{"NoStaticTables"});
    453             push(@getOwnPropertySlotImpl, "    return ${namespaceMaybe}getStaticValueSlot<$className, Base>(exec, s_info.staticPropHashTable, this, propertyName, slot);\n");
    454         } else {
    455             push(@getOwnPropertySlotImpl, "    return ${namespaceMaybe}getStaticValueSlot<$className, Base>(exec, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n");
    456         }
    457     } else {
    458         push(@getOwnPropertySlotImpl, "    return Base::getOwnPropertySlot(exec, propertyName, slot);\n");
    459     }
    460 
    461     return @getOwnPropertySlotImpl;
    462 }
    463 
    464 sub GenerateGetOwnPropertyDescriptorBody
    465 {
    466     my ($dataNode, $interfaceName, $className, $implClassName, $hasAttributes, $inlined) = @_;
    467     
    468     my $namespaceMaybe = ($inlined ? "JSC::" : "");
    469     
    470     my @getOwnPropertyDescriptorImpl = ();
    471     if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) {
    472         if ($interfaceName eq "DOMWindow") {
    473             push(@implContent, "    if (!static_cast<$className*>(thisObject)->allowsAccessFrom(exec))\n");
    474         } else {
    475             push(@implContent, "    if (!allowsAccessFromFrame(exec, static_cast<$className*>(thisObject)->impl()->frame()))\n");
    476         }
    477         push(@implContent, "        return false;\n");
    478     }
    479     
    480     if ($interfaceName eq "NamedNodeMap" or $interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") {
    481         push(@getOwnPropertyDescriptorImpl, "    ${namespaceMaybe}JSValue proto = prototype();\n");
    482         push(@getOwnPropertyDescriptorImpl, "    if (proto.isObject() && static_cast<${namespaceMaybe}JSObject*>(asObject(proto))->hasProperty(exec, propertyName))\n");
    483         push(@getOwnPropertyDescriptorImpl, "        return false;\n\n");
    484     }
    485     
    486     my $manualLookupGetterGeneration = sub {
    487         my $requiresManualLookup = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasNameGetter"};
    488         if ($requiresManualLookup) {
    489             push(@getOwnPropertyDescriptorImpl, "    const ${namespaceMaybe}HashEntry* entry = ${className}Table.entry(exec, propertyName);\n");
    490             push(@getOwnPropertyDescriptorImpl, "    if (entry) {\n");
    491             push(@getOwnPropertyDescriptorImpl, "        PropertySlot slot;\n");
    492             push(@getOwnPropertyDescriptorImpl, "        slot.setCustom(this, entry->propertyGetter());\n");
    493             push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());\n");
    494             push(@getOwnPropertyDescriptorImpl, "        return true;\n");
    495             push(@getOwnPropertyDescriptorImpl, "    }\n");
    496         }
    497     };
    498     
    499     if (!$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
    500         &$manualLookupGetterGeneration();
    501     }
    502     
    503     if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
    504         push(@getOwnPropertyDescriptorImpl, "    bool ok;\n");
    505         push(@getOwnPropertyDescriptorImpl, "    unsigned index = propertyName.toUInt32(ok);\n");
    506         push(@getOwnPropertyDescriptorImpl, "    if (ok && index < static_cast<$implClassName*>(impl())->length()) {\n");
    507         if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
    508             # Assume that if there's a setter, the index will be writable
    509             if ($dataNode->extendedAttributes->{"HasIndexSetter"} || $dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
    510                 push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(getByIndex(exec, index), ${namespaceMaybe}DontDelete);\n");
    511             } else {
    512                 push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(getByIndex(exec, index), ${namespaceMaybe}DontDelete | ${namespaceMaybe}ReadOnly);\n");
    513             }
    514         } else {
    515             push(@getOwnPropertyDescriptorImpl, "        ${namespaceMaybe}PropertySlot slot;\n");
    516             push(@getOwnPropertyDescriptorImpl, "        slot.setCustomIndex(this, index, indexGetter);\n");
    517             # Assume that if there's a setter, the index will be writable
    518             if ($dataNode->extendedAttributes->{"HasIndexSetter"} || $dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
    519                 push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(slot.getValue(exec, propertyName), ${namespaceMaybe}DontDelete);\n");
    520             } else {
    521                 push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(slot.getValue(exec, propertyName), ${namespaceMaybe}DontDelete | ${namespaceMaybe}ReadOnly);\n");
    522             }
    523         }
    524         push(@getOwnPropertyDescriptorImpl, "        return true;\n");
    525         push(@getOwnPropertyDescriptorImpl, "    }\n");
    526     }
    527     
    528     if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
    529         push(@getOwnPropertyDescriptorImpl, "    if (canGetItemsForName(exec, static_cast<$implClassName*>(impl()), propertyName)) {\n");
    530         push(@getOwnPropertyDescriptorImpl, "        ${namespaceMaybe}PropertySlot slot;\n");
    531         push(@getOwnPropertyDescriptorImpl, "        slot.setCustom(this, nameGetter);\n");
    532         push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);\n");
    533         push(@getOwnPropertyDescriptorImpl, "        return true;\n");
    534         push(@getOwnPropertyDescriptorImpl, "    }\n");
    535         if ($inlined) {
    536             $headerIncludes{"wtf/text/AtomicString.h"} = 1;
    537         } else {
    538             $implIncludes{"wtf/text/AtomicString.h"} = 1;
    539         }
    540     }
    541     
    542     if ($dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
    543         &$manualLookupGetterGeneration();
    544     }
    545     
    546     if ($dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}) {
    547         push(@getOwnPropertyDescriptorImpl, "    if (getOwnPropertyDescriptorDelegate(exec, propertyName, descriptor))\n");
    548         push(@getOwnPropertyDescriptorImpl, "        return true;\n");
    549     }
    550     
    551     if ($hasAttributes) {
    552         if ($inlined) {
    553             die "Cannot inline if NoStaticTables is set." if ($dataNode->extendedAttributes->{"NoStaticTables"});
    554             push(@getOwnPropertyDescriptorImpl, "    return ${namespaceMaybe}getStaticValueDescriptor<$className, Base>(exec, s_info.staticPropHashTable, this, propertyName, descriptor);\n");
    555         } else {
    556             push(@getOwnPropertyDescriptorImpl, "    return ${namespaceMaybe}getStaticValueDescriptor<$className, Base>(exec, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");
    557         }
    558     } else {
    559         push(@getOwnPropertyDescriptorImpl, "    return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);\n");
    560     }
    561     
    562     return @getOwnPropertyDescriptorImpl;
    563 }
    564 
    565 sub GenerateHeaderContentHeader
    566 {
    567     my $dataNode = shift;
    568     my $className = "JS" . $dataNode->name;
    569 
    570     my @headerContentHeader = split("\r", $headerTemplate);
    571 
    572     # - Add header protection
    573     push(@headerContentHeader, "\n#ifndef $className" . "_h");
    574     push(@headerContentHeader, "\n#define $className" . "_h\n\n");
    575 
    576     my $conditionalString = GenerateConditionalString($dataNode);
    577     push(@headerContentHeader, "#if ${conditionalString}\n\n") if $conditionalString;
    578     return @headerContentHeader;
    579 }
    580 
    581 sub GenerateImplementationContentHeader
    582 {
    583     my $dataNode = shift;
    584     my $className = "JS" . $dataNode->name;
    585 
    586     my @implContentHeader = split("\r", $headerTemplate);
    587 
    588     push(@implContentHeader, "\n#include \"config.h\"\n");
    589     my $conditionalString = GenerateConditionalString($dataNode);
    590     push(@implContentHeader, "\n#if ${conditionalString}\n\n") if $conditionalString;
    591     push(@implContentHeader, "#include \"$className.h\"\n\n");
    592     return @implContentHeader;
    593 }
    594 
    595 my %usesToJSNewlyCreated = (
    596     "CDATASection" => 1,
    597     "Element" => 1,
    598     "Node" => 1,
    599     "Text" => 1,
    600     "Touch" => 1,
    601     "TouchList" => 1
    602 );
    603 
    604 sub GenerateHeader
    605 {
    606     my $object = shift;
    607     my $dataNode = shift;
    608 
    609     my $interfaceName = $dataNode->name;
    610     my $className = "JS$interfaceName";
    611     my $implClassName = $interfaceName;
    612     my @ancestorInterfaceNames = ();
    613     my %structureFlags = ();
    614 
    615     # We only support multiple parents with SVG (for now).
    616     if (@{$dataNode->parents} > 1) {
    617         die "A class can't have more than one parent" unless $interfaceName =~ /SVG/;
    618         $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@ancestorInterfaceNames);
    619     }
    620 
    621     my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
    622     my $hasRealParent = @{$dataNode->parents} > 0;
    623     my $hasParent = $hasLegacyParent || $hasRealParent;
    624     my $parentClassName = GetParentClassName($dataNode);
    625     my $eventTarget = $dataNode->extendedAttributes->{"EventTarget"};
    626     my $needsMarkChildren = $dataNode->extendedAttributes->{"CustomMarkFunction"} || $dataNode->extendedAttributes->{"EventTarget"};
    627     
    628     # - Add default header template and header protection
    629     push(@headerContentHeader, GenerateHeaderContentHeader($dataNode));
    630 
    631     if ($hasParent) {
    632         $headerIncludes{"$parentClassName.h"} = 1;
    633     } else {
    634         $headerIncludes{"JSDOMBinding.h"} = 1;
    635         $headerIncludes{"<runtime/JSGlobalObject.h>"} = 1;
    636         $headerIncludes{"<runtime/ObjectPrototype.h>"} = 1;
    637     }
    638 
    639     if ($dataNode->extendedAttributes->{"CustomCall"}) {
    640         $headerIncludes{"<runtime/CallData.h>"} = 1;
    641     }
    642 
    643     if ($dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"}) {
    644         $headerIncludes{"<runtime/Lookup.h>"} = 1;
    645         $headerIncludes{"<wtf/AlwaysInline.h>"} = 1;
    646     }
    647 
    648     if ($hasParent && $dataNode->extendedAttributes->{"GenerateNativeConverter"}) {
    649         $headerIncludes{"$implClassName.h"} = 1;
    650     }
    651     
    652     $headerIncludes{"<runtime/JSObjectWithGlobalObject.h>"} = 1;
    653     $headerIncludes{"SVGElement.h"} = 1 if $className =~ /^JSSVG/;
    654 
    655     my $implType = $implClassName;
    656     my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implType);
    657     $implType = $svgNativeType if $svgNativeType;
    658 
    659     my $svgPropertyOrListPropertyType;
    660     $svgPropertyOrListPropertyType = $svgPropertyType if $svgPropertyType;
    661     $svgPropertyOrListPropertyType = $svgListPropertyType if $svgListPropertyType;
    662 
    663     my $numConstants = @{$dataNode->constants};
    664     my $numAttributes = @{$dataNode->attributes};
    665     my $numFunctions = @{$dataNode->functions};
    666 
    667     push(@headerContent, "\nnamespace WebCore {\n\n");
    668 
    669     if ($codeGenerator->IsSVGAnimatedType($implClassName)) {
    670         $headerIncludes{"$implClassName.h"} = 1;
    671     } else {
    672         # Implementation class forward declaration
    673         AddClassForwardIfNeeded($implClassName) unless $svgPropertyOrListPropertyType;
    674     }
    675 
    676     AddClassForwardIfNeeded("JSDOMWindowShell") if $interfaceName eq "DOMWindow";
    677 
    678     # Class declaration
    679     push(@headerContent, "class $className : public $parentClassName {\n");
    680     push(@headerContent, "    typedef $parentClassName Base;\n");
    681     push(@headerContent, "public:\n");
    682 
    683     # Constructor
    684     if ($interfaceName eq "DOMWindow") {
    685         push(@headerContent, "    $className(JSC::JSGlobalData&, JSC::Structure*, PassRefPtr<$implType>, JSDOMWindowShell*);\n");
    686     } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
    687         push(@headerContent, "    $className(JSC::JSGlobalData&, JSC::Structure*, PassRefPtr<$implType>);\n");
    688     } else {
    689         push(@headerContent, "    $className(JSC::Structure*, JSDOMGlobalObject*, PassRefPtr<$implType>);\n");
    690     }
    691 
    692     # Prototype
    693     push(@headerContent, "    static JSC::JSObject* createPrototype(JSC::ExecState*, JSC::JSGlobalObject*);\n") unless ($dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"});
    694 
    695     $headerTrailingIncludes{"${className}Custom.h"} = 1 if $dataNode->extendedAttributes->{"CustomHeader"};
    696 
    697     $implIncludes{"${className}Custom.h"} = 1 if !$dataNode->extendedAttributes->{"CustomHeader"} && ($dataNode->extendedAttributes->{"CustomPutFunction"} || $dataNode->extendedAttributes->{"DelegatingPutFunction"});
    698 
    699     my $hasGetter = $numAttributes > 0 
    700                  || !($dataNode->extendedAttributes->{"OmitConstructor"}
    701                  || $dataNode->extendedAttributes->{"CustomConstructor"})
    702                  || $dataNode->extendedAttributes->{"HasIndexGetter"}
    703                  || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}
    704                  || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}
    705                  || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}
    706                  || $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}
    707                  || $dataNode->extendedAttributes->{"HasNameGetter"}
    708                  || $dataNode->extendedAttributes->{"HasOverridingNameGetter"};
    709 
    710     # Getters
    711     if ($hasGetter) {
    712         push(@headerContent, "    virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);\n");
    713         push(@headerContent, "    virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&);\n");
    714         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"};
    715         push(@headerContent, "    bool getOwnPropertySlotDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"};
    716         push(@headerContent, "    bool getOwnPropertyDescriptorDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n") if $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"};
    717         $structureFlags{"JSC::OverridesGetOwnPropertySlot"} = 1;
    718     }
    719 
    720     # Check if we have any writable properties
    721     my $hasReadWriteProperties = 0;
    722     foreach (@{$dataNode->attributes}) {
    723         if ($_->type !~ /^readonly\ attribute$/) {
    724             $hasReadWriteProperties = 1;
    725         }
    726     }
    727 
    728     my $hasSetter = $hasReadWriteProperties
    729                  || $dataNode->extendedAttributes->{"CustomPutFunction"}
    730                  || $dataNode->extendedAttributes->{"DelegatingPutFunction"}
    731                  || $dataNode->extendedAttributes->{"HasCustomIndexSetter"};
    732 
    733     # Getters
    734     if ($hasSetter) {
    735         push(@headerContent, "    virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);\n");
    736         push(@headerContent, "    virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValue);\n") if $dataNode->extendedAttributes->{"HasCustomIndexSetter"};
    737         push(@headerContent, "    bool putDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, JSC::PutPropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingPutFunction"};
    738     }
    739 
    740     # Class info
    741     push(@headerContent, "    static const JSC::ClassInfo s_info;\n\n");
    742 
    743     # Structure ID
    744     if ($interfaceName eq "DOMWindow") {
    745         $structureFlags{"JSC::ImplementsHasInstance"} = 1;
    746         $structureFlags{"JSC::NeedsThisConversion"} = 1;
    747     }
    748     push(@headerContent,
    749         "    static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)\n" .
    750         "    {\n" .
    751         "        return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);\n" .
    752         "    }\n\n");
    753 
    754     # markChildren function
    755     if ($needsMarkChildren) {
    756         push(@headerContent, "    virtual void markChildren(JSC::MarkStack&);\n\n");
    757         $structureFlags{"JSC::OverridesMarkChildren"} = 1;
    758     }
    759 
    760     # Custom pushEventHandlerScope function
    761     push(@headerContent, "    virtual JSC::ScopeChainNode* pushEventHandlerScope(JSC::ExecState*, JSC::ScopeChainNode*) const;\n\n") if $dataNode->extendedAttributes->{"CustomPushEventHandlerScope"};
    762 
    763     # Custom call functions
    764     push(@headerContent, "    virtual JSC::CallType getCallData(JSC::CallData&);\n\n") if $dataNode->extendedAttributes->{"CustomCall"};
    765 
    766     # Custom deleteProperty function
    767     push(@headerContent, "    virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&);\n") if $dataNode->extendedAttributes->{"CustomDeleteProperty"};
    768 
    769     # Custom getPropertyNames function exists on DOMWindow
    770     if ($interfaceName eq "DOMWindow") {
    771         push(@headerContent, "    virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n");
    772         $structureFlags{"JSC::OverridesGetPropertyNames"} = 1;
    773     }
    774 
    775     # Custom defineProperty function exists on DOMWindow
    776     push(@headerContent, "    virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&, bool shouldThrow);\n") if $interfaceName eq "DOMWindow";
    777 
    778     # Custom getOwnPropertyNames function
    779     if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"} || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
    780         push(@headerContent, "    virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n");
    781         $structureFlags{"JSC::OverridesGetPropertyNames"} = 1;       
    782     }
    783 
    784     # Custom defineGetter function
    785     push(@headerContent, "    virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomDefineGetter"};
    786 
    787     # Custom defineSetter function
    788     push(@headerContent, "    virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomDefineSetter"};
    789 
    790     # Custom lookupGetter function
    791     push(@headerContent, "    virtual JSC::JSValue lookupGetter(JSC::ExecState*, const JSC::Identifier& propertyName);\n") if $dataNode->extendedAttributes->{"CustomLookupGetter"};
    792 
    793     # Custom lookupSetter function
    794     push(@headerContent, "    virtual JSC::JSValue lookupSetter(JSC::ExecState*, const JSC::Identifier& propertyName);\n") if $dataNode->extendedAttributes->{"CustomLookupSetter"};
    795 
    796     # Override toBoolean to return false for objects that want to 'MasqueradesAsUndefined'.
    797     if ($dataNode->extendedAttributes->{"MasqueradesAsUndefined"}) {
    798         push(@headerContent, "    virtual bool toBoolean(JSC::ExecState*) const { return false; };\n");
    799         $structureFlags{"JSC::MasqueradesAsUndefined"} = 1;
    800     }
    801 
    802     # Constructor object getter
    803     push(@headerContent, "    static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*);\n") if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"}));
    804 
    805     my $numCustomFunctions = 0;
    806     my $numCustomAttributes = 0;
    807 
    808     # Attribute and function enums
    809     if ($numAttributes > 0) {
    810         foreach (@{$dataNode->attributes}) {
    811             my $attribute = $_;
    812             $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"};
    813             $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"CustomGetter"} || $attribute->signature->extendedAttributes->{"JSCCustomGetter"};
    814             $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"CustomSetter"} || $attribute->signature->extendedAttributes->{"JSCCustomSetter"};
    815             if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) {
    816                 push(@headerContent, "    static const unsigned " . $attribute->signature->name . "Slot = $numCachedAttributes + Base::AnonymousSlotCount;\n");
    817                 $numCachedAttributes++;
    818             }
    819         }
    820     }
    821 
    822     if ($numCachedAttributes > 0) {
    823         push(@headerContent, "    using $parentClassName" . "::putAnonymousValue;\n");
    824         push(@headerContent, "    using $parentClassName" . "::getAnonymousValue;\n");
    825     }
    826     if ($numCustomAttributes > 0) {
    827         push(@headerContent, "\n    // Custom attributes\n");
    828 
    829         foreach my $attribute (@{$dataNode->attributes}) {
    830             if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"}) {
    831                 push(@headerContent, "    JSC::JSValue " . $codeGenerator->WK_lcfirst($attribute->signature->name) . "(JSC::ExecState*) const;\n");
    832                 if ($attribute->type !~ /^readonly/) {
    833                     push(@headerContent, "    void set" . $codeGenerator->WK_ucfirst($attribute->signature->name) . "(JSC::ExecState*, JSC::JSValue);\n");
    834                 }
    835             } elsif ($attribute->signature->extendedAttributes->{"CustomGetter"} || $attribute->signature->extendedAttributes->{"JSCCustomGetter"}) {
    836                 push(@headerContent, "    JSC::JSValue " . $codeGenerator->WK_lcfirst($attribute->signature->name) . "(JSC::ExecState*) const;\n");
    837             } elsif ($attribute->signature->extendedAttributes->{"CustomSetter"} || $attribute->signature->extendedAttributes->{"JSCCustomSetter"}) {
    838                 if ($attribute->type !~ /^readonly/) {
    839                     push(@headerContent, "    void set" . $codeGenerator->WK_ucfirst($attribute->signature->name) . "(JSC::ExecState*, JSC::JSValue);\n");
    840                 }
    841             }
    842         }
    843     }
    844 
    845     foreach my $function (@{$dataNode->functions}) {
    846         $numCustomFunctions++ if $function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"JSCCustom"};
    847     }
    848 
    849     if ($numCustomFunctions > 0) {
    850         push(@headerContent, "\n    // Custom functions\n");
    851         foreach my $function (@{$dataNode->functions}) {
    852             if ($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"JSCCustom"}) {
    853                 my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementationFunction"} || $codeGenerator->WK_lcfirst($function->signature->name);
    854                 push(@headerContent, "    JSC::JSValue " . $functionImplementationName . "(JSC::ExecState*);\n");
    855             }
    856         }
    857     }
    858 
    859     if (!$hasParent) {
    860         push(@headerContent, "    $implType* impl() const { return m_impl.get(); }\n\n");
    861         push(@headerContent, "private:\n");
    862         push(@headerContent, "    RefPtr<$implType> m_impl;\n");
    863     } elsif ($dataNode->extendedAttributes->{"GenerateNativeConverter"}) {
    864         push(@headerContent, "    $implClassName* impl() const\n");
    865         push(@headerContent, "    {\n");
    866         push(@headerContent, "        return static_cast<$implClassName*>(Base::impl());\n");
    867         push(@headerContent, "    }\n");
    868     }
    869     
    870     # anonymous slots
    871     if ($numCachedAttributes) {
    872         push(@headerContent, "public:\n");
    873         push(@headerContent, "    static const unsigned AnonymousSlotCount = $numCachedAttributes + Base::AnonymousSlotCount;\n");
    874     }
    875 
    876     # structure flags
    877     push(@headerContent, "protected:\n");
    878     push(@headerContent, "    static const unsigned StructureFlags = ");
    879     foreach my $structureFlag (keys %structureFlags) {
    880         push(@headerContent, $structureFlag . " | ");
    881     }
    882     push(@headerContent, "Base::StructureFlags;\n");
    883 
    884     # Index getter
    885     if ($dataNode->extendedAttributes->{"HasIndexGetter"}) {
    886         push(@headerContent, "    static JSC::JSValue indexGetter(JSC::ExecState*, JSC::JSValue, unsigned);\n");
    887     }
    888     if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
    889         push(@headerContent, "    JSC::JSValue getByIndex(JSC::ExecState*, unsigned index);\n");
    890         
    891     }
    892     
    893     # Index setter
    894     if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
    895         push(@headerContent, "    void indexSetter(JSC::ExecState*, unsigned index, JSC::JSValue);\n");
    896     }
    897     # Name getter
    898     if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
    899         push(@headerContent, "private:\n");
    900         push(@headerContent, "    static bool canGetItemsForName(JSC::ExecState*, $implClassName*, const JSC::Identifier&);\n");
    901         push(@headerContent, "    static JSC::JSValue nameGetter(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&);\n");
    902     }
    903 
    904     push(@headerContent, "};\n\n");
    905 
    906     if ($dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"} && !$dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}) {
    907         push(@headerContent, "ALWAYS_INLINE bool ${className}::getOwnPropertySlot(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertySlot& slot)\n");
    908         push(@headerContent, "{\n");
    909         push(@headerContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 1));
    910         push(@headerContent, "}\n\n");
    911         push(@headerContent, "ALWAYS_INLINE bool ${className}::getOwnPropertyDescriptor(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertyDescriptor& descriptor)\n");
    912         push(@headerContent, "{\n");
    913         push(@headerContent, GenerateGetOwnPropertyDescriptorBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 1));
    914         push(@headerContent, "}\n\n");
    915     }
    916 
    917     if (!$hasParent || $dataNode->extendedAttributes->{"GenerateToJS"} || $dataNode->extendedAttributes->{"CustomToJS"}) {
    918         if ($svgPropertyType) {
    919             push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType*);\n");
    920         } else {
    921             push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType*);\n");
    922         }
    923     }
    924     if (!$hasParent || $dataNode->extendedAttributes->{"GenerateNativeConverter"}) {
    925         if ($interfaceName eq "NodeFilter") {
    926             push(@headerContent, "PassRefPtr<NodeFilter> toNodeFilter(JSC::JSGlobalData&, JSC::JSValue);\n");
    927         } else {
    928             push(@headerContent, "$implType* to${interfaceName}(JSC::JSValue);\n");
    929         }
    930     }
    931     if ($usesToJSNewlyCreated{$interfaceName}) {
    932         push(@headerContent, "JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject*, $interfaceName*);\n");
    933     }
    934     
    935     push(@headerContent, "\n");
    936 
    937     # Add prototype declaration.
    938     %structureFlags = ();
    939     push(@headerContent, "class ${className}Prototype : public JSC::JSObjectWithGlobalObject {\n");
    940     push(@headerContent, "    typedef JSC::JSObjectWithGlobalObject Base;\n");
    941     push(@headerContent, "public:\n");
    942     if ($interfaceName eq "DOMWindow") {
    943         push(@headerContent, "    void* operator new(size_t);\n");
    944     } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
    945         push(@headerContent, "    void* operator new(size_t, JSC::JSGlobalData*);\n");
    946     } else {
    947         push(@headerContent, "    static JSC::JSObject* self(JSC::ExecState*, JSC::JSGlobalObject*);\n");
    948     }
    949     push(@headerContent, "    static const JSC::ClassInfo s_info;\n");
    950     if ($numFunctions > 0 || $numConstants > 0 || $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) {
    951         push(@headerContent, "    virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n");
    952         push(@headerContent, "    virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n");
    953         push(@headerContent, "    bool getOwnPropertySlotDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"};
    954         push(@headerContent, "    bool getOwnPropertyDescriptorDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n") if $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"};
    955         $structureFlags{"JSC::OverridesGetOwnPropertySlot"} = 1;
    956     }
    957     if ($dataNode->extendedAttributes->{"CustomMarkFunction"} or $needsMarkChildren) {
    958         $structureFlags{"JSC::OverridesMarkChildren"} = 1;
    959     }
    960     push(@headerContent,
    961         "    static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)\n" .
    962         "    {\n" .
    963         "        return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);\n" .
    964         "    }\n");
    965     if ($dataNode->extendedAttributes->{"DelegatingPrototypePutFunction"}) {
    966         push(@headerContent, "    virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);\n");
    967         push(@headerContent, "    bool putDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, JSC::PutPropertySlot&);\n");
    968     }
    969 
    970     # Custom defineGetter function
    971     push(@headerContent, "    virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomPrototypeDefineGetter"};
    972 
    973     push(@headerContent, "    ${className}Prototype(JSC::JSGlobalData& globalData, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) : JSC::JSObjectWithGlobalObject(globalData, globalObject, structure) { }\n");
    974 
    975     # structure flags
    976     push(@headerContent, "protected:\n");
    977     push(@headerContent, "    static const unsigned StructureFlags = ");
    978     foreach my $structureFlag (keys %structureFlags) {
    979         push(@headerContent, $structureFlag . " | ");
    980     }
    981     push(@headerContent, "Base::StructureFlags;\n");
    982 
    983     push(@headerContent, "};\n\n");
    984 
    985     # Conditionally emit the constructor object's declaration
    986     if ($dataNode->extendedAttributes->{"CustomConstructFunction"}) {
    987         GenerateConstructorDeclaration(\@headerContent, $className, $dataNode);
    988     }
    989 
    990 
    991     if ($numFunctions > 0) {
    992         push(@headerContent,"// Functions\n\n");
    993         foreach my $function (@{$dataNode->functions}) {
    994             next if $function->{overloadIndex} && $function->{overloadIndex} > 1;
    995             my $functionName = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($function->signature->name);
    996             push(@headerContent, "JSC::EncodedJSValue JSC_HOST_CALL ${functionName}(JSC::ExecState*);\n");
    997         }
    998     }
    999 
   1000     if ($numAttributes > 0 || !($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
   1001         push(@headerContent,"// Attributes\n\n");
   1002         foreach my $attribute (@{$dataNode->attributes}) {
   1003             my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
   1004             push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&);\n");
   1005             unless ($attribute->type =~ /readonly/) {
   1006                 my $setter = "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
   1007                 push(@headerContent, "void ${setter}(JSC::ExecState*, JSC::JSObject*, JSC::JSValue);\n");
   1008             }
   1009         }
   1010         
   1011         if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
   1012             my $getter = "js" . $interfaceName . "Constructor";
   1013             push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&);\n");
   1014         }
   1015 
   1016         if ($dataNode->extendedAttributes->{"ReplaceableConstructor"}) {
   1017             my $constructorFunctionName = "setJS" . $interfaceName . "Constructor";
   1018             push(@headerContent, "void ${constructorFunctionName}(JSC::ExecState*, JSC::JSObject*, JSC::JSValue);\n");
   1019         }
   1020     }
   1021 
   1022     if ($numConstants > 0) {
   1023         push(@headerContent,"// Constants\n\n");
   1024         foreach my $constant (@{$dataNode->constants}) {
   1025             my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);
   1026             push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&);\n");
   1027         }
   1028     }
   1029 
   1030     my $conditionalString = GenerateConditionalString($dataNode);
   1031     push(@headerContent, "\n} // namespace WebCore\n\n");
   1032     push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;
   1033     push(@headerContent, "#endif\n");
   1034 
   1035     # - Generate dependencies.
   1036     if ($writeDependencies && @ancestorInterfaceNames) {
   1037         push(@depsContent, "$className.h : ", join(" ", map { "$_.idl" } @ancestorInterfaceNames), "\n");
   1038         push(@depsContent, map { "$_.idl :\n" } @ancestorInterfaceNames); 
   1039     }
   1040 }
   1041 
   1042 sub GenerateAttributesHashTable($$)
   1043 {
   1044     my ($object, $dataNode) = @_;
   1045 
   1046     # FIXME: These should be functions on $dataNode.
   1047     my $interfaceName = $dataNode->name;
   1048     my $className = "JS$interfaceName";
   1049     
   1050     # - Add all attributes in a hashtable definition
   1051     my $numAttributes = @{$dataNode->attributes};
   1052     $numAttributes++ if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"}));
   1053 
   1054     return 0  if !$numAttributes;
   1055 
   1056     my $hashSize = $numAttributes;
   1057     my $hashName = $className . "Table";
   1058 
   1059     my @hashKeys = ();
   1060     my @hashSpecials = ();
   1061     my @hashValue1 = ();
   1062     my @hashValue2 = ();
   1063     my %conditionals = ();
   1064 
   1065     my @entries = ();
   1066 
   1067     foreach my $attribute (@{$dataNode->attributes}) {
   1068         my $name = $attribute->signature->name;
   1069         push(@hashKeys, $name);
   1070 
   1071         my @specials = ();
   1072         push(@specials, "DontDelete") unless $attribute->signature->extendedAttributes->{"Deletable"};
   1073         push(@specials, "DontEnum") if $attribute->signature->extendedAttributes->{"DontEnum"};
   1074         push(@specials, "ReadOnly") if $attribute->type =~ /readonly/;
   1075         my $special = (@specials > 0) ? join(" | ", @specials) : "0";
   1076         push(@hashSpecials, $special);
   1077 
   1078         my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
   1079         push(@hashValue1, $getter);
   1080 
   1081         if ($attribute->type =~ /readonly/) {
   1082             push(@hashValue2, "0");
   1083         } else {
   1084             my $setter = "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
   1085             push(@hashValue2, $setter);
   1086         }
   1087 
   1088         my $conditional = $attribute->signature->extendedAttributes->{"Conditional"};
   1089         if ($conditional) {
   1090             $conditionals{$name} = $conditional;
   1091         }
   1092     }
   1093 
   1094     if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
   1095         push(@hashKeys, "constructor");
   1096         my $getter = "js" . $interfaceName . "Constructor";
   1097         push(@hashValue1, $getter);
   1098         if ($dataNode->extendedAttributes->{"ReplaceableConstructor"}) {
   1099             my $setter = "setJS" . $interfaceName . "Constructor";
   1100             push(@hashValue2, $setter);
   1101             push(@hashSpecials, "DontEnum | DontDelete");
   1102         } else {            
   1103             push(@hashValue2, "0");
   1104             push(@hashSpecials, "DontEnum | ReadOnly");
   1105         }
   1106     }
   1107 
   1108     $object->GenerateHashTable($hashName, $hashSize,
   1109                                \@hashKeys, \@hashSpecials,
   1110                                \@hashValue1, \@hashValue2,
   1111                                \%conditionals);
   1112     return $numAttributes;
   1113 }
   1114 
   1115 sub GenerateParametersCheckExpression
   1116 {
   1117     my $numParameters = shift;
   1118     my $function = shift;
   1119 
   1120     my @andExpression = ();
   1121     push(@andExpression, "exec->argumentCount() == $numParameters");
   1122     my $parameterIndex = 0;
   1123     foreach $parameter (@{$function->parameters}) {
   1124         last if $parameterIndex >= $numParameters;
   1125         my $value = "exec->argument($parameterIndex)";
   1126         my $type = $codeGenerator->StripModule($parameter->type);
   1127 
   1128         # Only DOMString or wrapper types are checked.
   1129         # For DOMString, Null, Undefined and any Object are accepted too, as
   1130         # these are acceptable values for a DOMString argument (any Object can
   1131         # be converted to a string via .toString).
   1132         if ($codeGenerator->IsStringType($type)) {
   1133             push(@andExpression, "(${value}.isNull() || ${value}.isUndefined() || ${value}.isString() || ${value}.isObject())");
   1134         } elsif ($parameter->extendedAttributes->{"Callback"}) {
   1135             # For Callbacks only checks if the value is null or object.
   1136             push(@andExpression, "(${value}.isNull() || ${value}.isObject())");
   1137         } elsif (!IsNativeType($type)) {
   1138             push(@andExpression, "(${value}.isNull() || (${value}.isObject() && asObject(${value})->inherits(&JS${type}::s_info)))");
   1139         }
   1140         $parameterIndex++;
   1141     }
   1142     my $res = join(" && ", @andExpression);
   1143     $res = "($res)" if @andExpression > 1;
   1144     return $res;
   1145 }
   1146 
   1147 sub GenerateFunctionParametersCheck
   1148 {
   1149     my $function = shift;
   1150 
   1151     my @orExpression = ();
   1152     my $numParameters = 0;
   1153     foreach $parameter (@{$function->parameters}) {
   1154         if ($parameter->extendedAttributes->{"Optional"}) {
   1155             push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
   1156         }
   1157         $numParameters++;
   1158     }
   1159     push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
   1160     return join(" || ", @orExpression);
   1161 }
   1162 
   1163 sub GenerateOverloadedPrototypeFunction
   1164 {
   1165     my $function = shift;
   1166     my $dataNode = shift;
   1167     my $implClassName = shift;
   1168 
   1169     # Generate code for choosing the correct overload to call. Overloads are
   1170     # chosen based on the total number of arguments passed and the type of
   1171     # values passed in non-primitive argument slots. When more than a single
   1172     # overload is applicable, precedence is given according to the order of
   1173     # declaration in the IDL.
   1174 
   1175     my $functionName = "js${implClassName}PrototypeFunction" . $codeGenerator->WK_ucfirst($function->signature->name);
   1176 
   1177     push(@implContent, "EncodedJSValue JSC_HOST_CALL ${functionName}(ExecState* exec)\n");
   1178     push(@implContent, <<END);
   1179 {
   1180 END
   1181     foreach my $overload (@{$function->{overloads}}) {
   1182         my $parametersCheck = GenerateFunctionParametersCheck($overload);
   1183         push(@implContent, "    if ($parametersCheck)\n");
   1184         push(@implContent, "        return ${functionName}$overload->{overloadIndex}(exec);\n");
   1185     }
   1186     push(@implContent, <<END);
   1187     return throwVMTypeError(exec);
   1188 }
   1189 
   1190 END
   1191 }
   1192 
   1193 sub GenerateImplementation
   1194 {
   1195     my ($object, $dataNode) = @_;
   1196 
   1197     my $interfaceName = $dataNode->name;
   1198     my $className = "JS$interfaceName";
   1199     my $implClassName = $interfaceName;
   1200 
   1201     my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
   1202     my $hasRealParent = @{$dataNode->parents} > 0;
   1203     my $hasParent = $hasLegacyParent || $hasRealParent;
   1204     my $parentClassName = GetParentClassName($dataNode);
   1205     my $visibleClassName = GetVisibleClassName($interfaceName);
   1206     my $eventTarget = $dataNode->extendedAttributes->{"EventTarget"};
   1207     my $needsMarkChildren = $dataNode->extendedAttributes->{"CustomMarkFunction"} || $dataNode->extendedAttributes->{"EventTarget"};
   1208 
   1209     # - Add default header template
   1210     push(@implContentHeader, GenerateImplementationContentHeader($dataNode));
   1211 
   1212     AddIncludesForSVGAnimatedType($interfaceName) if $className =~ /^JSSVGAnimated/;
   1213 
   1214     $implIncludes{"<wtf/GetPtr.h>"} = 1;
   1215     $implIncludes{"<runtime/PropertyNameArray.h>"} = 1 if $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"};
   1216 
   1217     AddIncludesForType($interfaceName);
   1218 
   1219     @implContent = ();
   1220 
   1221     push(@implContent, "\nusing namespace JSC;\n\n");
   1222     push(@implContent, "namespace WebCore {\n\n");
   1223 
   1224     push(@implContent, "ASSERT_CLASS_FITS_IN_CELL($className);\n\n");
   1225 
   1226     my $numAttributes = GenerateAttributesHashTable($object, $dataNode);
   1227 
   1228     my $numConstants = @{$dataNode->constants};
   1229     my $numFunctions = @{$dataNode->functions};
   1230 
   1231     # - Add all constants
   1232     if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
   1233         $hashSize = $numConstants;
   1234         $hashName = $className . "ConstructorTable";
   1235 
   1236         @hashKeys = ();
   1237         @hashValue1 = ();
   1238         @hashValue2 = ();
   1239         @hashSpecials = ();
   1240 
   1241         # FIXME: we should not need a function for every constant.
   1242         foreach my $constant (@{$dataNode->constants}) {
   1243             push(@hashKeys, $constant->name);
   1244             my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);
   1245             push(@hashValue1, $getter);
   1246             push(@hashValue2, "0");
   1247             push(@hashSpecials, "DontDelete | ReadOnly");
   1248         }
   1249 
   1250         $object->GenerateHashTable($hashName, $hashSize,
   1251                                    \@hashKeys, \@hashSpecials,
   1252                                    \@hashValue1, \@hashValue2);
   1253 
   1254         push(@implContent, $codeGenerator->GenerateCompileTimeCheckForEnumsIfNeeded($dataNode));
   1255 
   1256         my $protoClassName = "${className}Prototype";
   1257 
   1258         GenerateConstructorDeclaration(\@implContent, $className, $dataNode) unless $dataNode->extendedAttributes->{"CustomConstructFunction"};
   1259         GenerateConstructorDefinition(\@implContent, $className, $protoClassName, $interfaceName, $visibleClassName, $dataNode);
   1260     }
   1261 
   1262     # - Add functions and constants to a hashtable definition
   1263     $hashSize = $numFunctions + $numConstants;
   1264     $hashName = $className . "PrototypeTable";
   1265 
   1266     @hashKeys = ();
   1267     @hashValue1 = ();
   1268     @hashValue2 = ();
   1269     @hashSpecials = ();
   1270 
   1271     # FIXME: we should not need a function for every constant.
   1272     foreach my $constant (@{$dataNode->constants}) {
   1273         push(@hashKeys, $constant->name);
   1274         my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);
   1275         push(@hashValue1, $getter);
   1276         push(@hashValue2, "0");
   1277         push(@hashSpecials, "DontDelete | ReadOnly");
   1278     }
   1279 
   1280     foreach my $function (@{$dataNode->functions}) {
   1281         next if $function->{overloadIndex} && $function->{overloadIndex} > 1;
   1282         my $name = $function->signature->name;
   1283         push(@hashKeys, $name);
   1284 
   1285         my $value = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($name);
   1286         push(@hashValue1, $value);
   1287 
   1288         my $numParameters = @{$function->parameters};
   1289         push(@hashValue2, $numParameters);
   1290 
   1291         my @specials = ();
   1292         push(@specials, "DontDelete") unless $function->signature->extendedAttributes->{"Deletable"};
   1293         push(@specials, "DontEnum") if $function->signature->extendedAttributes->{"DontEnum"};
   1294         push(@specials, "Function");
   1295         my $special = (@specials > 0) ? join(" | ", @specials) : "0";
   1296         push(@hashSpecials, $special);
   1297     }
   1298 
   1299     $object->GenerateHashTable($hashName, $hashSize,
   1300                                \@hashKeys, \@hashSpecials,
   1301                                \@hashValue1, \@hashValue2);
   1302 
   1303     if ($dataNode->extendedAttributes->{"NoStaticTables"}) {
   1304         push(@implContent, "static const HashTable* get${className}PrototypeTable(ExecState* exec)\n");
   1305         push(@implContent, "{\n");
   1306         push(@implContent, "    return getHashTableForGlobalData(exec->globalData(), &${className}PrototypeTable);\n");
   1307         push(@implContent, "}\n\n");
   1308         push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleClassName}Prototype\", &JSC::JSObjectWithGlobalObject::s_info, 0, get${className}PrototypeTable };\n\n");
   1309     } else {
   1310         push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleClassName}Prototype\", &JSC::JSObjectWithGlobalObject::s_info, &${className}PrototypeTable, 0 };\n\n");
   1311     }
   1312     if ($interfaceName eq "DOMWindow") {
   1313         push(@implContent, "void* ${className}Prototype::operator new(size_t size)\n");
   1314         push(@implContent, "{\n");
   1315         push(@implContent, "    return JSDOMWindow::commonJSGlobalData()->heap.allocate(size);\n");
   1316         push(@implContent, "}\n\n");
   1317     } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
   1318         push(@implContent, "void* ${className}Prototype::operator new(size_t size, JSGlobalData* globalData)\n");
   1319         push(@implContent, "{\n");
   1320         push(@implContent, "    return globalData->heap.allocate(size);\n");
   1321         push(@implContent, "}\n\n");
   1322     } else {
   1323         push(@implContent, "JSObject* ${className}Prototype::self(ExecState* exec, JSGlobalObject* globalObject)\n");
   1324         push(@implContent, "{\n");
   1325         push(@implContent, "    return getDOMPrototype<${className}>(exec, globalObject);\n");
   1326         push(@implContent, "}\n\n");
   1327     }
   1328     if ($numConstants > 0 || $numFunctions > 0 || $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) {
   1329         push(@implContent, "bool ${className}Prototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n");
   1330         push(@implContent, "{\n");
   1331 
   1332         if ($dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) {
   1333             push(@implContent, "    if (getOwnPropertySlotDelegate(exec, propertyName, slot))\n");
   1334             push(@implContent, "        return true;\n");
   1335         }
   1336 
   1337         if ($numConstants eq 0 && $numFunctions eq 0) {
   1338             push(@implContent, "    return Base::getOwnPropertySlot(exec, propertyName, slot);\n");        
   1339         } elsif ($numConstants eq 0) {
   1340             push(@implContent, "    return getStaticFunctionSlot<JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n");
   1341         } elsif ($numFunctions eq 0) {
   1342             push(@implContent, "    return getStaticValueSlot<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n");
   1343         } else {
   1344             push(@implContent, "    return getStaticPropertySlot<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n");
   1345         }
   1346         push(@implContent, "}\n\n");
   1347 
   1348         push(@implContent, "bool ${className}Prototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\n");
   1349         push(@implContent, "{\n");
   1350         
   1351         if ($dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) {
   1352             push(@implContent, "    if (getOwnPropertyDescriptorDelegate(exec, propertyName, descriptor))\n");
   1353             push(@implContent, "        return true;\n");
   1354         }
   1355         
   1356         if ($numConstants eq 0 && $numFunctions eq 0) {
   1357             push(@implContent, "    return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);\n");        
   1358         } elsif ($numConstants eq 0) {
   1359             push(@implContent, "    return getStaticFunctionDescriptor<JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");
   1360         } elsif ($numFunctions eq 0) {
   1361             push(@implContent, "    return getStaticValueDescriptor<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");
   1362         } else {
   1363             push(@implContent, "    return getStaticPropertyDescriptor<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");
   1364         }
   1365         push(@implContent, "}\n\n");
   1366     }
   1367 
   1368     if ($dataNode->extendedAttributes->{"DelegatingPrototypePutFunction"}) {
   1369         push(@implContent, "void ${className}Prototype::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)\n");
   1370         push(@implContent, "{\n");
   1371         push(@implContent, "    if (putDelegate(exec, propertyName, value, slot))\n");
   1372         push(@implContent, "        return;\n");
   1373         push(@implContent, "    Base::put(exec, propertyName, value, slot);\n");
   1374         push(@implContent, "}\n\n");
   1375     }
   1376 
   1377     # - Initialize static ClassInfo object
   1378     if ($numAttributes > 0 && $dataNode->extendedAttributes->{"NoStaticTables"}) {
   1379         push(@implContent, "static const HashTable* get${className}Table(ExecState* exec)\n");
   1380         push(@implContent, "{\n");
   1381         push(@implContent, "    return getHashTableForGlobalData(exec->globalData(), &${className}Table);\n");
   1382         push(@implContent, "}\n\n");
   1383     }
   1384 
   1385     push(@implContent, "const ClassInfo $className" . "::s_info = { \"${visibleClassName}\", &" . $parentClassName . "::s_info, ");
   1386 
   1387     if ($numAttributes > 0 && !$dataNode->extendedAttributes->{"NoStaticTables"}) {
   1388         push(@implContent, "&${className}Table");
   1389     } else {
   1390         push(@implContent, "0");
   1391     }
   1392     if ($numAttributes > 0 && $dataNode->extendedAttributes->{"NoStaticTables"}) {
   1393         push(@implContent, ", get${className}Table ");
   1394     } else {
   1395         push(@implContent, ", 0 ");
   1396     }
   1397     push(@implContent, "};\n\n");
   1398 
   1399     my $implType = $implClassName;
   1400     my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implType);
   1401     $implType = $svgNativeType if $svgNativeType;
   1402 
   1403     my $svgPropertyOrListPropertyType;
   1404     $svgPropertyOrListPropertyType = $svgPropertyType if $svgPropertyType;
   1405     $svgPropertyOrListPropertyType = $svgListPropertyType if $svgListPropertyType;
   1406 
   1407     # Constructor
   1408     if ($interfaceName eq "DOMWindow") {
   1409         AddIncludesForType("JSDOMWindowShell");
   1410         push(@implContent, "${className}::$className(JSGlobalData& globalData, Structure* structure, PassRefPtr<$implType> impl, JSDOMWindowShell* shell)\n");
   1411         push(@implContent, "    : $parentClassName(globalData, structure, impl, shell)\n");
   1412     } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
   1413         AddIncludesForType($interfaceName);
   1414         push(@implContent, "${className}::$className(JSGlobalData& globalData, Structure* structure, PassRefPtr<$implType> impl)\n");
   1415         push(@implContent, "    : $parentClassName(globalData, structure, impl)\n");
   1416     } else {
   1417         push(@implContent, "${className}::$className(Structure* structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl)\n");
   1418         if ($hasParent) {
   1419             push(@implContent, "    : $parentClassName(structure, globalObject, impl)\n");
   1420         } else {
   1421             push(@implContent, "    : $parentClassName(structure, globalObject)\n");
   1422             push(@implContent, "    , m_impl(impl)\n");
   1423         }
   1424     }
   1425     push(@implContent, "{\n");
   1426     push(@implContent, "    ASSERT(inherits(&s_info));\n");
   1427     if ($numCachedAttributes > 0) {
   1428         push(@implContent, "    for (unsigned i = Base::AnonymousSlotCount; i < AnonymousSlotCount; i++)\n");
   1429         push(@implContent, "        putAnonymousValue(globalObject->globalData(), i, JSValue());\n");
   1430     }
   1431     push(@implContent, "}\n\n");
   1432 
   1433     if ($needsMarkChildren && !$dataNode->extendedAttributes->{"CustomMarkFunction"}) {
   1434         push(@implContent, "void ${className}::markChildren(MarkStack& markStack)\n");
   1435         push(@implContent, "{\n");
   1436         push(@implContent, "    Base::markChildren(markStack);\n");
   1437         push(@implContent, "    impl()->markJSEventListeners(markStack);\n");
   1438         push(@implContent, "}\n\n");
   1439     }
   1440 
   1441     if (!$dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"}) {
   1442         push(@implContent, "JSObject* ${className}::createPrototype(ExecState* exec, JSGlobalObject* globalObject)\n");
   1443         push(@implContent, "{\n");
   1444         if ($hasParent && $parentClassName ne "JSC::DOMNodeFilter") {
   1445             push(@implContent, "    return new (exec) ${className}Prototype(exec->globalData(), globalObject, ${className}Prototype::createStructure(exec->globalData(), ${parentClassName}Prototype::self(exec, globalObject)));\n");
   1446         } else {
   1447             push(@implContent, "    return new (exec) ${className}Prototype(exec->globalData(), globalObject, ${className}Prototype::createStructure(globalObject->globalData(), globalObject->objectPrototype()));\n");
   1448         }
   1449         push(@implContent, "}\n\n");
   1450     }
   1451 
   1452     my $hasGetter = $numAttributes > 0 
   1453                  || !($dataNode->extendedAttributes->{"OmitConstructor"} 
   1454                  || $dataNode->extendedAttributes->{"CustomConstructor"})
   1455                  || $dataNode->extendedAttributes->{"HasIndexGetter"}
   1456                  || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}
   1457                  || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}
   1458                  || $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}
   1459                  || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}
   1460                  || $dataNode->extendedAttributes->{"HasNameGetter"}
   1461                  || $dataNode->extendedAttributes->{"HasOverridingNameGetter"};
   1462 
   1463     # Attributes
   1464     if ($hasGetter) {
   1465         if (!$dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"} && !$dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}) {
   1466             push(@implContent, "bool ${className}::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n");
   1467             push(@implContent, "{\n");
   1468             push(@implContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 0));
   1469             push(@implContent, "}\n\n");
   1470             push(@implContent, "bool ${className}::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\n");
   1471             push(@implContent, "{\n");
   1472             push(@implContent, GenerateGetOwnPropertyDescriptorBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 0));
   1473             push(@implContent, "}\n\n");
   1474         }
   1475 
   1476         if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) 
   1477                 && !$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
   1478             push(@implContent, "bool ${className}::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)\n");
   1479             push(@implContent, "{\n");
   1480             push(@implContent, "    if (propertyName < static_cast<$implClassName*>(impl())->length()) {\n");
   1481             if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
   1482                 push(@implContent, "        slot.setValue(getByIndex(exec, propertyName));\n");
   1483             } else {
   1484                 push(@implContent, "        slot.setCustomIndex(this, propertyName, indexGetter);\n");
   1485             }
   1486             push(@implContent, "        return true;\n");
   1487             push(@implContent, "    }\n");
   1488             push(@implContent, "    return getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);\n");
   1489             push(@implContent, "}\n\n");
   1490         }
   1491         
   1492         if ($numAttributes > 0) {
   1493             foreach my $attribute (@{$dataNode->attributes}) {
   1494                 my $name = $attribute->signature->name;
   1495                 my $type = $codeGenerator->StripModule($attribute->signature->type);
   1496                 my $getFunctionName = "js" . $interfaceName .  $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
   1497                 my $implGetterFunctionName = $codeGenerator->WK_lcfirst($name);
   1498 
   1499                 my $attributeConditionalString = GenerateConditionalString($attribute->signature);
   1500                 push(@implContent, "#if ${attributeConditionalString}\n") if $attributeConditionalString;
   1501 
   1502                 push(@implContent, "JSValue ${getFunctionName}(ExecState* exec, JSValue slotBase, const Identifier&)\n");
   1503                 push(@implContent, "{\n");
   1504                 push(@implContent, "    ${className}* castedThis = static_cast<$className*>(asObject(slotBase));\n");
   1505 
   1506                 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && 
   1507                         !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurity"} &&
   1508                         !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurityOnGet"}) {
   1509                     push(@implContent, "    if (!castedThis->allowsAccessFrom(exec))\n");
   1510                     push(@implContent, "        return jsUndefined();\n");
   1511                 }
   1512 
   1513                 if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"} || $attribute->signature->extendedAttributes->{"CustomGetter"} || $attribute->signature->extendedAttributes->{"JSCCustomGetter"}) {
   1514                     push(@implContent, "    return castedThis->$implGetterFunctionName(exec);\n");
   1515                 } elsif ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) {
   1516                     $implIncludes{"JSDOMBinding.h"} = 1;
   1517                     push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");
   1518                     push(@implContent, "    return checkNodeSecurity(exec, imp->$implGetterFunctionName()) ? " . NativeToJSValue($attribute->signature, 0, $implClassName, "imp->$implGetterFunctionName()", "castedThis") . " : jsUndefined();\n");
   1519                 } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) {
   1520                     $implIncludes{"Document.h"} = 1;
   1521                     $implIncludes{"JSDOMBinding.h"} = 1;
   1522                     push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");
   1523                     push(@implContent, "    return checkNodeSecurity(exec, imp->contentDocument()) ? " . NativeToJSValue($attribute->signature, 0, $implClassName, "imp->$implGetterFunctionName()", "castedThis") . " : jsUndefined();\n");
   1524                 } elsif ($type eq "EventListener") {
   1525                     $implIncludes{"EventListener.h"} = 1;
   1526                     push(@implContent, "    UNUSED_PARAM(exec);\n");
   1527                     push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");
   1528                     push(@implContent, "    if (EventListener* listener = imp->$implGetterFunctionName()) {\n");
   1529                     push(@implContent, "        if (const JSEventListener* jsListener = JSEventListener::cast(listener)) {\n");
   1530                     if ($implClassName eq "Document" || $implClassName eq "WorkerContext" || $implClassName eq "SharedWorkerContext" || $implClassName eq "DedicatedWorkerContext") {
   1531                         push(@implContent, "            if (JSObject* jsFunction = jsListener->jsFunction(imp))\n");
   1532                     } else {
   1533                         push(@implContent, "            if (JSObject* jsFunction = jsListener->jsFunction(imp->scriptExecutionContext()))\n");
   1534                     }
   1535                     push(@implContent, "                return jsFunction;\n");
   1536                     push(@implContent, "        }\n");
   1537                     push(@implContent, "    }\n");
   1538                     push(@implContent, "    return jsNull();\n");
   1539                 } elsif ($attribute->signature->type =~ /Constructor$/) {
   1540                     my $constructorType = $codeGenerator->StripModule($attribute->signature->type);
   1541                     $constructorType =~ s/Constructor$//;
   1542                     # Constructor attribute is only used by DOMWindow.idl, so it's correct to pass castedThis as the global object
   1543                     # Once JSDOMWrappers have a back-pointer to the globalObject we can pass castedThis->globalObject()
   1544                     push(@implContent, "    return JS" . $constructorType . "::getConstructor(exec, castedThis);\n");
   1545                 } elsif (!@{$attribute->getterExceptions}) {
   1546                     push(@implContent, "    UNUSED_PARAM(exec);\n");
   1547                     my $cacheIndex = 0;
   1548                     if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) {
   1549                         $cacheIndex = $currentCachedAttribute;
   1550                         $currentCachedAttribute++;
   1551                         push(@implContent, "    if (JSValue cachedValue = castedThis->getAnonymousValue(" . $className . "::" . $attribute->signature->name . "Slot))\n");
   1552                         push(@implContent, "        return cachedValue;\n");
   1553                     }
   1554 
   1555                     if ($svgListPropertyType) {
   1556                         push(@implContent, "    JSValue result =  " . NativeToJSValue($attribute->signature, 0, $implClassName, "castedThis->impl()->$implGetterFunctionName()", "castedThis") . ";\n");
   1557                     } elsif ($svgPropertyOrListPropertyType) {
   1558                         push(@implContent, "    $svgPropertyOrListPropertyType& imp = castedThis->impl()->propertyReference();\n");
   1559                         if ($svgPropertyOrListPropertyType eq "float") { # Special case for JSSVGNumber
   1560                             push(@implContent, "    JSValue result =  " . NativeToJSValue($attribute->signature, 0, $implClassName, "imp", "castedThis") . ";\n");
   1561                         } else {
   1562                             push(@implContent, "    JSValue result =  " . NativeToJSValue($attribute->signature, 0, $implClassName, "imp.$implGetterFunctionName()", "castedThis") . ";\n");
   1563                         }
   1564                     } else {
   1565                         my $getterExpression = "imp->" . $codeGenerator->GetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute) . ")";
   1566                         my $jsType = NativeToJSValue($attribute->signature, 0, $implClassName, $getterExpression, "castedThis");
   1567                         push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");
   1568                         if ($codeGenerator->IsSVGAnimatedType($type)) {
   1569                             push(@implContent, "    RefPtr<$type> obj = $jsType;\n");
   1570                             push(@implContent, "    JSValue result =  toJS(exec, castedThis->globalObject(), obj.get());\n");
   1571                         } else {
   1572                             push(@implContent, "    JSValue result = $jsType;\n");
   1573                         }
   1574                     }
   1575                     
   1576                     push(@implContent, "    castedThis->putAnonymousValue(exec->globalData(), " . $className . "::" . $attribute->signature->name . "Slot, result);\n") if ($attribute->signature->extendedAttributes->{"CachedAttribute"});
   1577                     push(@implContent, "    return result;\n");
   1578 
   1579                 } else {
   1580                     push(@implContent, "    ExceptionCode ec = 0;\n");                    
   1581                     if ($svgPropertyOrListPropertyType) {
   1582                         push(@implContent, "    $svgPropertyOrListPropertyType imp(*castedThis->impl());\n");
   1583                         push(@implContent, "    JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "imp.$implGetterFunctionName(ec)", "castedThis") . ";\n");
   1584                     } else {
   1585                         push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");
   1586                         push(@implContent, "    JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "imp->$implGetterFunctionName(ec)", "castedThis") . ";\n");
   1587                     }
   1588 
   1589                     push(@implContent, "    setDOMException(exec, ec);\n");
   1590                     push(@implContent, "    return result;\n");
   1591                 }
   1592 
   1593                 push(@implContent, "}\n\n");
   1594 
   1595                 push(@implContent, "#endif\n") if $attributeConditionalString;
   1596 
   1597                 push(@implContent, "\n");
   1598             }
   1599 
   1600             if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
   1601                 my $constructorFunctionName = "js" . $interfaceName . "Constructor";
   1602 
   1603                 push(@implContent, "JSValue ${constructorFunctionName}(ExecState* exec, JSValue slotBase, const Identifier&)\n");
   1604                 push(@implContent, "{\n");
   1605                 push(@implContent, "    ${className}* domObject = static_cast<$className*>(asObject(slotBase));\n");
   1606 
   1607                 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) {
   1608                     push(@implContent, "    if (!domObject->allowsAccessFrom(exec))\n");
   1609                     push(@implContent, "        return jsUndefined();\n");
   1610                 }
   1611 
   1612                 push(@implContent, "    return ${className}::getConstructor(exec, domObject->globalObject());\n");
   1613                 push(@implContent, "}\n\n");
   1614             }
   1615         }
   1616 
   1617         # Check if we have any writable attributes
   1618         my $hasReadWriteProperties = 0;
   1619         foreach my $attribute (@{$dataNode->attributes}) {
   1620             $hasReadWriteProperties = 1 if $attribute->type !~ /^readonly/;
   1621         }
   1622 
   1623         my $hasSetter = $hasReadWriteProperties
   1624                      || $dataNode->extendedAttributes->{"DelegatingPutFunction"}
   1625                      || $dataNode->extendedAttributes->{"HasCustomIndexSetter"};
   1626 
   1627         if ($hasSetter) {
   1628             if (!$dataNode->extendedAttributes->{"CustomPutFunction"}) {
   1629                 push(@implContent, "void ${className}::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)\n");
   1630                 push(@implContent, "{\n");
   1631                 if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
   1632                     push(@implContent, "    bool ok;\n");
   1633                     push(@implContent, "    unsigned index = propertyName.toUInt32(ok);\n");
   1634                     push(@implContent, "    if (ok) {\n");
   1635                     push(@implContent, "        indexSetter(exec, index, value);\n");
   1636                     push(@implContent, "        return;\n");
   1637                     push(@implContent, "    }\n");
   1638                 }
   1639                 if ($dataNode->extendedAttributes->{"DelegatingPutFunction"}) {
   1640                     push(@implContent, "    if (putDelegate(exec, propertyName, value, slot))\n");
   1641                     push(@implContent, "        return;\n");
   1642                 }
   1643 
   1644                 if ($hasReadWriteProperties) {
   1645                     push(@implContent, "    lookupPut<$className, Base>(exec, propertyName, value, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, slot);\n");
   1646                 } else {
   1647                     push(@implContent, "    Base::put(exec, propertyName, value, slot);\n");
   1648                 }
   1649                 push(@implContent, "}\n\n");
   1650             }
   1651 
   1652             if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
   1653                 push(@implContent, "void ${className}::put(ExecState* exec, unsigned propertyName, JSValue value)\n");
   1654                 push(@implContent, "{\n");
   1655                 push(@implContent, "    indexSetter(exec, propertyName, value);\n");
   1656                 push(@implContent, "    return;\n");
   1657                 push(@implContent, "}\n\n");
   1658             }
   1659 
   1660             if ($hasReadWriteProperties) {
   1661                 foreach my $attribute (@{$dataNode->attributes}) {
   1662                     if ($attribute->type !~ /^readonly/) {
   1663                         my $name = $attribute->signature->name;
   1664                         my $type = $codeGenerator->StripModule($attribute->signature->type);
   1665                         my $putFunctionName = "setJS" . $interfaceName .  $codeGenerator->WK_ucfirst($name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
   1666                         my $implSetterFunctionName = $codeGenerator->WK_ucfirst($name);
   1667 
   1668                         my $attributeConditionalString = GenerateConditionalString($attribute->signature);
   1669                         push(@implContent, "#if ${attributeConditionalString}\n") if $attributeConditionalString;
   1670 
   1671                         push(@implContent, "void ${putFunctionName}(ExecState* exec, JSObject* thisObject, JSValue value)\n");
   1672                         push(@implContent, "{\n");
   1673 
   1674                         if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
   1675                             if ($interfaceName eq "DOMWindow") {
   1676                                 push(@implContent, "    if (!static_cast<$className*>(thisObject)->allowsAccessFrom(exec))\n");
   1677                             } else {
   1678                                 push(@implContent, "    if (!allowsAccessFromFrame(exec, static_cast<$className*>(thisObject)->impl()->frame()))\n");
   1679                             }
   1680                             push(@implContent, "        return;\n");
   1681                         }
   1682 
   1683                         if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"} || $attribute->signature->extendedAttributes->{"CustomSetter"} || $attribute->signature->extendedAttributes->{"JSCCustomSetter"}) {
   1684                             push(@implContent, "    static_cast<$className*>(thisObject)->set$implSetterFunctionName(exec, value);\n");
   1685                         } elsif ($type eq "EventListener") {
   1686                             $implIncludes{"JSEventListener.h"} = 1;
   1687                             push(@implContent, "    UNUSED_PARAM(exec);\n");
   1688                             my $windowEventListener = $attribute->signature->extendedAttributes->{"WindowEventListener"};
   1689                             if ($windowEventListener) {
   1690                                 push(@implContent, "    ${className}* castedThis = static_cast<${className}*>(thisObject);\n");
   1691                                 push(@implContent, "    JSDOMGlobalObject* globalObject = castedThis->globalObject();\n");
   1692                             }
   1693                             push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(thisObject)->impl());\n");
   1694                             if ((($interfaceName eq "DOMWindow") or ($interfaceName eq "WorkerContext")) and $name eq "onerror") {
   1695                                 $implIncludes{"JSErrorHandler.h"} = 1;
   1696                                 push(@implContent, "    imp->set$implSetterFunctionName(createJSErrorHandler(exec, value, thisObject));\n");
   1697                             } else {
   1698                                 push(@implContent, GenerateAttributeEventListenerCall($className, $implSetterFunctionName, $windowEventListener));
   1699                             }
   1700                         } elsif ($attribute->signature->type =~ /Constructor$/) {
   1701                             my $constructorType = $attribute->signature->type;
   1702                             $constructorType =~ s/Constructor$//;
   1703                             if ($constructorType ne "DOMObject") {
   1704                                 $implIncludes{"JS" . $constructorType . ".h"} = 1;
   1705                             }
   1706                             push(@implContent, "    // Shadowing a built-in constructor\n");
   1707                             if ($interfaceName eq "DOMWindow" && $className eq "JSblah") {
   1708                                 push(@implContent, "    static_cast<$className*>(thisObject)->putDirect(exec->globalData(), exec->propertyNames().constructor, value);\n");
   1709                             } else {
   1710                                 push(@implContent, "    static_cast<$className*>(thisObject)->putDirect(exec->globalData(), Identifier(exec, \"$name\"), value);\n");
   1711                             }
   1712                         } elsif ($attribute->signature->extendedAttributes->{"Replaceable"}) {
   1713                             push(@implContent, "    // Shadowing a built-in object\n");
   1714                             push(@implContent, "    static_cast<$className*>(thisObject)->putDirect(exec->globalData(), Identifier(exec, \"$name\"), value);\n");
   1715                         } else {
   1716                             push(@implContent, "    $className* castedThis = static_cast<$className*>(thisObject);\n");
   1717                             push(@implContent, "    $implType* imp = static_cast<$implType*>(castedThis->impl());\n");
   1718                             push(@implContent, "    ExceptionCode ec = 0;\n") if @{$attribute->setterExceptions};
   1719 
   1720                             # If the "StrictTypeChecking" extended attribute is present, and the attribute's type is an
   1721                             # interface type, then if the incoming value does not implement that interface, a TypeError
   1722                             # is thrown rather than silently passing NULL to the C++ code.
   1723                             # Per the Web IDL and ECMAScript specifications, incoming values can always be converted to
   1724                             # both strings and numbers, so do not throw TypeError if the attribute is of these types.
   1725                             if ($attribute->signature->extendedAttributes->{"StrictTypeChecking"}) {
   1726                                 $implIncludes{"<runtime/Error.h>"} = 1;
   1727 
   1728                                 my $argType = $attribute->signature->type;
   1729                                 if (!IsNativeType($argType)) {
   1730                                     push(@implContent, "    if (!value.isUndefinedOrNull() && !value.inherits(&JS${argType}::s_info)) {\n");
   1731                                     push(@implContent, "        throwVMTypeError(exec);\n");
   1732                                     push(@implContent, "        return;\n");
   1733                                     push(@implContent, "    };\n");
   1734                                 }
   1735                             }
   1736 
   1737                             my $nativeValue = JSValueToNative($attribute->signature, "value");
   1738                             if ($svgPropertyOrListPropertyType) {
   1739                                 if ($svgPropertyType) {
   1740                                     push(@implContent, "    if (imp->role() == AnimValRole) {\n");
   1741                                     push(@implContent, "        setDOMException(exec, NO_MODIFICATION_ALLOWED_ERR);\n");
   1742                                     push(@implContent, "        return;\n");
   1743                                     push(@implContent, "    }\n");
   1744                                 }
   1745                                 push(@implContent, "    $svgPropertyOrListPropertyType& podImp = imp->propertyReference();\n");
   1746                                 if ($svgPropertyOrListPropertyType eq "float") { # Special case for JSSVGNumber
   1747                                     push(@implContent, "    podImp = $nativeValue;\n");
   1748                                 } else {
   1749                                     push(@implContent, "    podImp.set$implSetterFunctionName($nativeValue");
   1750                                     push(@implContent, ", ec") if @{$attribute->setterExceptions};
   1751                                     push(@implContent, ");\n");
   1752                                     push(@implContent, "    setDOMException(exec, ec);\n") if @{$attribute->setterExceptions};
   1753                                 }
   1754                                 if ($svgPropertyType) {
   1755                                     if (@{$attribute->setterExceptions}) {
   1756                                         push(@implContent, "    if (!ec)\n"); 
   1757                                         push(@implContent, "        imp->commitChange();\n");
   1758                                     } else {
   1759                                         push(@implContent, "    imp->commitChange();\n");
   1760                                     }
   1761                                 }
   1762                             } else {
   1763                                 my $setterExpressionPrefix = $codeGenerator->SetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute);
   1764                                 push(@implContent, "    imp->$setterExpressionPrefix$nativeValue");
   1765                                 push(@implContent, ", ec") if @{$attribute->setterExceptions};
   1766                                 push(@implContent, ");\n");
   1767                                 push(@implContent, "    setDOMException(exec, ec);\n") if @{$attribute->setterExceptions};
   1768                             }
   1769                         }
   1770                         
   1771                         push(@implContent, "}\n\n");
   1772 
   1773                         push(@implContent, "#endif\n") if $attributeConditionalString;
   1774 
   1775                         push(@implContent, "\n");
   1776                     }
   1777                 }
   1778             }
   1779             
   1780             if ($dataNode->extendedAttributes->{"ReplaceableConstructor"}) {
   1781                 my $constructorFunctionName = "setJS" . $interfaceName . "Constructor";
   1782                 
   1783                 push(@implContent, "void ${constructorFunctionName}(ExecState* exec, JSObject* thisObject, JSValue value)\n");
   1784                 push(@implContent, "{\n");
   1785                 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) {
   1786                     if ($interfaceName eq "DOMWindow") {
   1787                         push(@implContent, "    if (!static_cast<$className*>(thisObject)->allowsAccessFrom(exec))\n");
   1788                     } else {
   1789                         push(@implContent, "    if (!allowsAccessFromFrame(exec, static_cast<$className*>(thisObject)->impl()->frame()))\n");
   1790                     }
   1791                     push(@implContent, "        return;\n");
   1792                 }
   1793 
   1794                 push(@implContent, "    // Shadowing a built-in constructor\n");
   1795 
   1796                 if ($interfaceName eq "DOMWindow") {
   1797                     push(@implContent, "    static_cast<$className*>(thisObject)->putDirect(exec->globalData(), exec->propertyNames().constructor, value);\n");
   1798                 } else {
   1799                     push(@implContent, "    static_cast<$className*>(thisObject)->putDirect(exec->globalData(), Identifier(exec, \"$name\"), value);\n");
   1800                 }
   1801                 push(@implContent, "}\n\n");
   1802             }        
   1803         }
   1804     }
   1805 
   1806     if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) && !$dataNode->extendedAttributes->{"CustomGetPropertyNames"}) {
   1807         push(@implContent, "void ${className}::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)\n");
   1808         push(@implContent, "{\n");
   1809         if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
   1810             push(@implContent, "    for (unsigned i = 0; i < static_cast<${implClassName}*>(impl())->length(); ++i)\n");
   1811             push(@implContent, "        propertyNames.add(Identifier::from(exec, i));\n");
   1812         }
   1813         push(@implContent, "     Base::getOwnPropertyNames(exec, propertyNames, mode);\n");
   1814         push(@implContent, "}\n\n");
   1815     }
   1816 
   1817     if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
   1818         push(@implContent, "JSValue ${className}::getConstructor(ExecState* exec, JSGlobalObject* globalObject)\n{\n");
   1819         push(@implContent, "    return getDOMConstructor<${className}Constructor>(exec, static_cast<JSDOMGlobalObject*>(globalObject));\n");
   1820         push(@implContent, "}\n\n");
   1821     }
   1822 
   1823     # Functions
   1824     if ($numFunctions > 0) {
   1825         foreach my $function (@{$dataNode->functions}) {
   1826             AddIncludesForType($function->signature->type);
   1827 
   1828             my $functionName = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($function->signature->name);
   1829 
   1830             if ($function->{overloads} && @{$function->{overloads}} > 1) {
   1831                 # Append a number to an overloaded method's name to make it unique:
   1832                 $functionName = $functionName . $function->{overloadIndex};
   1833                 # Make this function static to avoid compiler warnings, since we
   1834                 # don't generate a prototype for it in the header.
   1835                 push(@implContent, "static ");
   1836             }
   1837             
   1838             my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementationFunction"} || $codeGenerator->WK_lcfirst($function->signature->name);
   1839 
   1840             push(@implContent, "EncodedJSValue JSC_HOST_CALL ${functionName}(ExecState* exec)\n");
   1841             push(@implContent, "{\n");
   1842 
   1843             $implIncludes{"<runtime/Error.h>"} = 1;
   1844 
   1845             if ($interfaceName eq "DOMWindow") {
   1846                 push(@implContent, "    $className* castedThis = toJSDOMWindow(exec->hostThisValue().toThisObject(exec));\n");
   1847                 push(@implContent, "    if (!castedThis)\n");
   1848                 push(@implContent, "        return throwVMTypeError(exec);\n");
   1849             } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
   1850                 push(@implContent, "    $className* castedThis = to${className}(exec->hostThisValue().toThisObject(exec));\n");
   1851                 push(@implContent, "    if (!castedThis)\n");
   1852                 push(@implContent, "        return throwVMTypeError(exec);\n");
   1853             } else {
   1854                 push(@implContent, "    JSValue thisValue = exec->hostThisValue();\n");
   1855                 push(@implContent, "    if (!thisValue.inherits(&${className}::s_info))\n");
   1856                 push(@implContent, "        return throwVMTypeError(exec);\n");
   1857                 push(@implContent, "    $className* castedThis = static_cast<$className*>(asObject(thisValue));\n");
   1858             }
   1859 
   1860             if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && 
   1861                 !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
   1862                 push(@implContent, "    if (!castedThis->allowsAccessFrom(exec))\n");
   1863                 push(@implContent, "        return JSValue::encode(jsUndefined());\n");
   1864             }
   1865 
   1866             if ($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"JSCCustom"}) {
   1867                 push(@implContent, "    return JSValue::encode(castedThis->" . $functionImplementationName . "(exec));\n");
   1868             } else {
   1869                 push(@implContent, "    $implType* imp = static_cast<$implType*>(castedThis->impl());\n");
   1870                 if ($svgPropertyType) {
   1871                     push(@implContent, "    if (imp->role() == AnimValRole) {\n");
   1872                     push(@implContent, "        setDOMException(exec, NO_MODIFICATION_ALLOWED_ERR);\n");
   1873                     push(@implContent, "        return JSValue::encode(jsUndefined());\n");
   1874                     push(@implContent, "    }\n");
   1875                     push(@implContent, "    $svgPropertyType& podImp = imp->propertyReference();\n");
   1876                 }
   1877 
   1878                 my $numParameters = @{$function->parameters};
   1879 
   1880                 my $requiresAllArguments = $function->signature->extendedAttributes->{"RequiresAllArguments"};
   1881                 if ($requiresAllArguments) {
   1882                     my $numMandatoryParams = @{$function->parameters};
   1883                     foreach my $param (reverse(@{$function->parameters})) {
   1884                         if ($param->extendedAttributes->{"Optional"}) {
   1885                             $numMandatoryParams--;
   1886                         } else {
   1887                             last;
   1888                         }
   1889                     }
   1890                     push(@implContent, "    if (exec->argumentCount() < $numMandatoryParams)\n");
   1891                     if ($requiresAllArguments eq "Raise") {
   1892                         push(@implContent, "        return throwVMError(exec, createSyntaxError(exec, \"Not enough arguments\"));\n");
   1893                     } else {
   1894                         push(@implContent, "        return JSValue::encode(jsUndefined());\n");
   1895                     }
   1896                 }
   1897 
   1898                 if (@{$function->raisesExceptions}) {
   1899                     push(@implContent, "    ExceptionCode ec = 0;\n");
   1900                 }
   1901 
   1902                 if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) {
   1903                     push(@implContent, "    if (!checkNodeSecurity(exec, imp->getSVGDocument(" . (@{$function->raisesExceptions} ? "ec" : "") .")))\n");
   1904                     push(@implContent, "        return JSValue::encode(jsUndefined());\n");
   1905                     $implIncludes{"JSDOMBinding.h"} = 1;
   1906                 }
   1907 
   1908                 if ($function->signature->name eq "addEventListener") {
   1909                     push(@implContent, GenerateEventListenerCall($className, "add"));
   1910                 } elsif ($function->signature->name eq "removeEventListener") {
   1911                     push(@implContent, GenerateEventListenerCall($className, "remove"));
   1912                 } else {
   1913                     my $argsIndex = 0;
   1914                     my $paramIndex = 0;
   1915                     my $functionString = (($svgPropertyOrListPropertyType and !$svgListPropertyType) ? "podImp." : "imp->") . $functionImplementationName . "(";
   1916                     my $hasOptionalArguments = 0;
   1917 
   1918                     if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
   1919                         push(@implContent, "    RefPtr<ScriptArguments> scriptArguments(createScriptArguments(exec, $numParameters));\n");
   1920                         push(@implContent, "    size_t maxStackSize = imp->shouldCaptureFullStackTrace() ? ScriptCallStack::maxCallStackSizeToCapture : 1;\n");
   1921                         push(@implContent, "    RefPtr<ScriptCallStack> callStack(createScriptCallStack(exec, maxStackSize));\n");
   1922                         $implIncludes{"ScriptArguments.h"} = 1;
   1923                         $implIncludes{"ScriptCallStack.h"} = 1;
   1924                         $implIncludes{"ScriptCallStackFactory.h"} = 1;
   1925                     }
   1926 
   1927                     my $callWith = $function->signature->extendedAttributes->{"CallWith"};
   1928                     if ($callWith) {
   1929                         my $callWithArg = "COMPILE_ASSERT(false)";
   1930                         if ($callWith eq "DynamicFrame") {
   1931                             push(@implContent, "    Frame* dynamicFrame = toDynamicFrame(exec);\n");
   1932                             push(@implContent, "    if (!dynamicFrame)\n");
   1933                             push(@implContent, "        return JSValue::encode(jsUndefined());\n");
   1934                             $callWithArg = "dynamicFrame";
   1935                         } elsif ($callWith eq "ScriptState") {
   1936                             $callWithArg = "exec";
   1937                         } elsif ($callWith eq "ScriptExecutionContext") {
   1938                             push(@implContent, "    ScriptExecutionContext* scriptContext = static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext();\n");
   1939                             push(@implContent, "    if (!scriptContext)\n");
   1940                             push(@implContent, "        return JSValue::encode(jsUndefined());\n");
   1941                             $callWithArg = "scriptContext"; 
   1942                         }
   1943                         $functionString .= ", " if $paramIndex;
   1944                         $functionString .= $callWithArg;
   1945                         $paramIndex++;
   1946                     }
   1947 
   1948                     $implIncludes{"ExceptionCode.h"} = 1;
   1949                     $implIncludes{"JSDOMBinding.h"} = 1;
   1950                     foreach my $parameter (@{$function->parameters}) {
   1951                         # Optional callbacks should be treated differently, because they always have a default value (0),
   1952                         # and we can reduce the number of overloaded functions that take a different number of parameters.
   1953                         if ($parameter->extendedAttributes->{"Optional"} && !$parameter->extendedAttributes->{"Callback"}) {
   1954                             # Generate early call if there are enough parameters.
   1955                             if (!$hasOptionalArguments) {
   1956                                 push(@implContent, "\n    int argsCount = exec->argumentCount();\n");
   1957                                 $hasOptionalArguments = 1;
   1958                             }
   1959                             push(@implContent, "    if (argsCount <= $argsIndex) {\n");
   1960                             GenerateImplementationFunctionCall($function, $functionString, $paramIndex, "    " x 2, $svgPropertyType, $implClassName);
   1961                             push(@implContent, "    }\n\n");
   1962                         }
   1963 
   1964                         my $name = $parameter->name;
   1965                         my $argType = $codeGenerator->StripModule($parameter->type);
   1966 
   1967                         if ($argType eq "XPathNSResolver") {
   1968                             push(@implContent, "    RefPtr<XPathNSResolver> customResolver;\n");
   1969                             push(@implContent, "    XPathNSResolver* resolver = toXPathNSResolver(exec->argument($argsIndex));\n");
   1970                             push(@implContent, "    if (!resolver) {\n");
   1971                             push(@implContent, "        customResolver = JSCustomXPathNSResolver::create(exec, exec->argument($argsIndex));\n");
   1972                             push(@implContent, "        if (exec->hadException())\n");
   1973                             push(@implContent, "            return JSValue::encode(jsUndefined());\n");
   1974                             push(@implContent, "        resolver = customResolver.get();\n");
   1975                             push(@implContent, "    }\n");
   1976                         } elsif ($parameter->extendedAttributes->{"Callback"}) {
   1977                             my $callbackClassName = GetCallbackClassName($argType);
   1978                             $implIncludes{"$callbackClassName.h"} = 1;
   1979                             if ($parameter->extendedAttributes->{"Optional"}) {
   1980                                 push(@implContent, "    RefPtr<$argType> $name;\n");
   1981                                 push(@implContent, "    if (exec->argumentCount() > $argsIndex && !exec->argument($argsIndex).isNull() && !exec->argument($argsIndex).isUndefined()) {\n");
   1982                                 push(@implContent, "        if (!exec->argument($argsIndex).isObject()) {\n");
   1983                                 push(@implContent, "            setDOMException(exec, TYPE_MISMATCH_ERR);\n");
   1984                                 push(@implContent, "            return JSValue::encode(jsUndefined());\n");
   1985                                 push(@implContent, "        }\n");
   1986                                 push(@implContent, "        $name = ${callbackClassName}::create(asObject(exec->argument($argsIndex)), castedThis->globalObject());\n");
   1987                                 push(@implContent, "    }\n");
   1988                             } else {
   1989                                 push(@implContent, "    if (exec->argumentCount() <= $argsIndex || !exec->argument($argsIndex).isObject()) {\n");
   1990                                 push(@implContent, "        setDOMException(exec, TYPE_MISMATCH_ERR);\n");
   1991                                 push(@implContent, "        return JSValue::encode(jsUndefined());\n");
   1992                                 push(@implContent, "    }\n");
   1993                                 push(@implContent, "    RefPtr<$argType> $name = ${callbackClassName}::create(asObject(exec->argument($argsIndex)), castedThis->globalObject());\n");
   1994                             }
   1995                         } else {
   1996                             # If the "StrictTypeChecking" extended attribute is present, and the argument's type is an
   1997                             # interface type, then if the incoming value does not implement that interface, a TypeError
   1998                             # is thrown rather than silently passing NULL to the C++ code.
   1999                             # Per the Web IDL and ECMAScript semantics, incoming values can always be converted to both
   2000                             # strings and numbers, so do not throw TypeError if the argument is of these types.
   2001                             if ($function->signature->extendedAttributes->{"StrictTypeChecking"}) {
   2002                                 $implIncludes{"<runtime/Error.h>"} = 1;
   2003 
   2004                                 my $argValue = "exec->argument($argsIndex)";
   2005                                 if (!IsNativeType($argType)) {
   2006                                     push(@implContent, "    if (exec->argumentCount() > $argsIndex && !${argValue}.isUndefinedOrNull() && !${argValue}.inherits(&JS${argType}::s_info))\n");
   2007                                     push(@implContent, "        return throwVMTypeError(exec);\n");
   2008                                 }
   2009                             }
   2010 
   2011                             push(@implContent, "    " . GetNativeTypeFromSignature($parameter) . " $name(" . JSValueToNative($parameter, "exec->argument($argsIndex)") . ");\n");
   2012 
   2013                             # If a parameter is "an index" and it's negative it should throw an INDEX_SIZE_ERR exception.
   2014                             # But this needs to be done in the bindings, because the type is unsigned and the fact that it
   2015                             # was negative will be lost by the time we're inside the DOM.
   2016                             if ($parameter->extendedAttributes->{"IsIndex"}) {
   2017                                 push(@implContent, "    if ($name < 0) {\n");
   2018                                 push(@implContent, "        setDOMException(exec, INDEX_SIZE_ERR);\n");
   2019                                 push(@implContent, "        return JSValue::encode(jsUndefined());\n");
   2020                                 push(@implContent, "    }\n");
   2021                             }
   2022 
   2023                             # Check if the type conversion succeeded.
   2024                             push(@implContent, "    if (exec->hadException())\n");
   2025                             push(@implContent, "        return JSValue::encode(jsUndefined());\n");
   2026 
   2027                             if ($codeGenerator->IsSVGTypeNeedingTearOff($argType) and not $implClassName =~ /List$/) {
   2028                                 push(@implContent, "    if (!$name) {\n");
   2029                                 push(@implContent, "        setDOMException(exec, TYPE_MISMATCH_ERR);\n");
   2030                                 push(@implContent, "        return JSValue::encode(jsUndefined());\n");
   2031                                 push(@implContent, "    }\n");
   2032                             }
   2033                         }
   2034 
   2035                         $functionString .= ", " if $paramIndex;
   2036 
   2037                         if ($argType eq "NodeFilter") {
   2038                             $functionString .= "$name.get()";
   2039                         } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($argType) and not $implClassName =~ /List$/) {
   2040                             $functionString .= "$name->propertyReference()";
   2041                         } else {
   2042                             $functionString .= $name;
   2043                         }
   2044                         $argsIndex++;
   2045                         $paramIndex++;
   2046                     }
   2047 
   2048                     if ($function->signature->extendedAttributes->{"NeedsUserGestureCheck"}) {
   2049                         $functionString .= ", " if $paramIndex;
   2050                         $functionString .= "processingUserGesture()";
   2051                         $paramIndex++;
   2052                     }
   2053 
   2054                     push(@implContent, "\n");
   2055                     GenerateImplementationFunctionCall($function, $functionString, $paramIndex, "    ", $svgPropertyType, $implClassName);
   2056                 }
   2057             }
   2058             push(@implContent, "}\n\n");
   2059 
   2060             if ($function->{overloads} && @{$function->{overloads}} > 1 && $function->{overloadIndex} == @{$function->{overloads}}) {
   2061                 # Generate a function dispatching call to the rest of the overloads.
   2062                 GenerateOverloadedPrototypeFunction($function, $dataNode, $implClassName);
   2063             }
   2064         }
   2065     }
   2066 
   2067     if ($numConstants > 0) {
   2068         push(@implContent, "// Constant getters\n\n");
   2069 
   2070         foreach my $constant (@{$dataNode->constants}) {
   2071             my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);
   2072 
   2073             # FIXME: this casts into int to match our previous behavior which turned 0xFFFFFFFF in -1 for NodeFilter.SHOW_ALL
   2074             push(@implContent, "JSValue ${getter}(ExecState* exec, JSValue, const Identifier&)\n");
   2075             push(@implContent, "{\n");
   2076             if ($constant->type eq "DOMString") {
   2077                 push(@implContent, "    return jsStringOrNull(exec, String(" . $constant->value . "));\n");
   2078             } else {
   2079                 push(@implContent, "    UNUSED_PARAM(exec);\n");
   2080                 push(@implContent, "    return jsNumber(static_cast<int>(" . $constant->value . "));\n");
   2081             }
   2082             push(@implContent, "}\n\n");
   2083         }
   2084     }
   2085 
   2086     if ($dataNode->extendedAttributes->{"HasIndexGetter"}) {
   2087         push(@implContent, "\nJSValue ${className}::indexGetter(ExecState* exec, JSValue slotBase, unsigned index)\n");
   2088         push(@implContent, "{\n");
   2089         push(@implContent, "    ${className}* thisObj = static_cast<$className*>(asObject(slotBase));\n");
   2090         if (IndexGetterReturnsStrings($implClassName)) {
   2091             $implIncludes{"KURL.h"} = 1;
   2092             push(@implContent, "    return jsStringOrNull(exec, thisObj->impl()->item(index));\n");
   2093         } else {
   2094             push(@implContent, "    return toJS(exec, thisObj->globalObject(), static_cast<$implClassName*>(thisObj->impl())->item(index));\n");
   2095         }
   2096         push(@implContent, "}\n\n");
   2097         if ($interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") {
   2098             $implIncludes{"JSNode.h"} = 1;
   2099             $implIncludes{"Node.h"} = 1;
   2100         }
   2101     }
   2102     
   2103     if ($dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
   2104         push(@implContent, "\nJSValue ${className}::getByIndex(ExecState*, unsigned index)\n");
   2105         push(@implContent, "{\n");
   2106         push(@implContent, "    return jsNumber(static_cast<$implClassName*>(impl())->item(index));\n");
   2107         push(@implContent, "}\n\n");
   2108         if ($interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") {
   2109             $implIncludes{"JSNode.h"} = 1;
   2110             $implIncludes{"Node.h"} = 1;
   2111         }
   2112     }
   2113 
   2114     if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateToJS"}) and !$dataNode->extendedAttributes->{"CustomToJS"}) {
   2115         if ($svgPropertyType) {
   2116             push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* impl)\n");
   2117         } else {
   2118             push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* impl)\n");
   2119         }
   2120         push(@implContent, "{\n");
   2121         if ($svgPropertyType) {
   2122             push(@implContent, "    return wrap<$className, $implType>(exec, globalObject, impl);\n");
   2123         } else {
   2124             push(@implContent, "    return wrap<$className>(exec, globalObject, impl);\n");
   2125         }
   2126         push(@implContent, "}\n\n");
   2127     }
   2128 
   2129     if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateNativeConverter"}) and !$dataNode->extendedAttributes->{"CustomNativeConverter"}) {
   2130         push(@implContent, "$implType* to${interfaceName}(JSC::JSValue value)\n");
   2131         push(@implContent, "{\n");
   2132         push(@implContent, "    return value.inherits(&${className}::s_info) ? static_cast<$className*>(asObject(value))->impl() : 0");
   2133         push(@implContent, ";\n}\n");
   2134     }
   2135 
   2136     push(@implContent, "\n}\n");
   2137 
   2138     my $conditionalString = GenerateConditionalString($dataNode);
   2139     push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
   2140 }
   2141 
   2142 sub GenerateCallbackHeader
   2143 {
   2144     my $object = shift;
   2145     my $dataNode = shift;
   2146 
   2147     my $interfaceName = $dataNode->name;
   2148     my $className = "JS$interfaceName";
   2149 
   2150     # - Add default header template and header protection
   2151     push(@headerContentHeader, GenerateHeaderContentHeader($dataNode));
   2152 
   2153     $headerIncludes{"ActiveDOMCallback.h"} = 1;
   2154     $headerIncludes{"$interfaceName.h"} = 1;
   2155     $headerIncludes{"JSCallbackData.h"} = 1;
   2156     $headerIncludes{"<wtf/Forward.h>"} = 1;
   2157 
   2158     push(@headerContent, "\nnamespace WebCore {\n\n");
   2159     push(@headerContent, "class $className : public $interfaceName, public ActiveDOMCallback {\n");
   2160     push(@headerContent, "public:\n");
   2161 
   2162     # The static create() method.
   2163     push(@headerContent, "    static PassRefPtr<$className> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject)\n");
   2164     push(@headerContent, "    {\n");
   2165     push(@headerContent, "        return adoptRef(new $className(callback, globalObject));\n");
   2166     push(@headerContent, "    }\n\n");
   2167 
   2168     # Destructor
   2169     push(@headerContent, "    virtual ~$className();\n");
   2170 
   2171     # Functions
   2172     my $numFunctions = @{$dataNode->functions};
   2173     if ($numFunctions > 0) {
   2174         push(@headerContent, "\n    // Functions\n");
   2175         foreach my $function (@{$dataNode->functions}) {
   2176             my @params = @{$function->parameters};
   2177             if (!$function->signature->extendedAttributes->{"Custom"} &&
   2178                 !(GetNativeType($function->signature->type) eq "bool")) {
   2179                 push(@headerContent, "    COMPILE_ASSERT(false)");
   2180             }
   2181 
   2182             push(@headerContent, "    virtual " . GetNativeType($function->signature->type) . " " . $function->signature->name . "(");
   2183 
   2184             my @args = ();
   2185             foreach my $param (@params) {
   2186                 push(@args, GetNativeType($param->type) . " " . $param->name);
   2187             }
   2188             push(@headerContent, join(", ", @args));
   2189 
   2190             push(@headerContent, ");\n");
   2191         }
   2192     }
   2193 
   2194     push(@headerContent, "\nprivate:\n");
   2195 
   2196     # Constructor
   2197     push(@headerContent, "    $className(JSC::JSObject* callback, JSDOMGlobalObject*);\n\n");
   2198 
   2199     # Private members
   2200     push(@headerContent, "    JSCallbackData* m_data;\n");
   2201     push(@headerContent, "};\n\n");
   2202 
   2203     push(@headerContent, "} // namespace WebCore\n\n");
   2204     my $conditionalString = GenerateConditionalString($dataNode);
   2205     push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;
   2206     push(@headerContent, "#endif\n");
   2207 }
   2208 
   2209 sub GenerateCallbackImplementation
   2210 {
   2211     my ($object, $dataNode) = @_;
   2212 
   2213     my $interfaceName = $dataNode->name;
   2214     my $className = "JS$interfaceName";
   2215 
   2216     # - Add default header template
   2217     push(@implContentHeader, GenerateImplementationContentHeader($dataNode));
   2218 
   2219     $implIncludes{"ScriptExecutionContext.h"} = 1;
   2220     $implIncludes{"<runtime/JSLock.h>"} = 1;
   2221     $implIncludes{"<wtf/MainThread.h>"} = 1;
   2222 
   2223     @implContent = ();
   2224 
   2225     push(@implContent, "\nusing namespace JSC;\n\n");
   2226     push(@implContent, "namespace WebCore {\n\n");
   2227 
   2228     # Constructor
   2229     push(@implContent, "${className}::${className}(JSObject* callback, JSDOMGlobalObject* globalObject)\n");
   2230     push(@implContent, "    : ActiveDOMCallback(globalObject->scriptExecutionContext())\n");
   2231     push(@implContent, "    , m_data(new JSCallbackData(callback, globalObject))\n");
   2232     push(@implContent, "{\n");
   2233     push(@implContent, "}\n\n");
   2234 
   2235     # Destructor
   2236     push(@implContent, "${className}::~${className}()\n");
   2237     push(@implContent, "{\n");
   2238     push(@implContent, "    ScriptExecutionContext* context = scriptExecutionContext();\n");
   2239     push(@implContent, "    // When the context is destroyed, all tasks with a reference to a callback\n");
   2240     push(@implContent, "    // should be deleted. So if the context is 0, we are on the context thread.\n");
   2241     push(@implContent, "    if (!context || context->isContextThread())\n");
   2242     push(@implContent, "        delete m_data;\n");
   2243     push(@implContent, "    else\n");
   2244     push(@implContent, "        context->postTask(DeleteCallbackDataTask::create(m_data));\n");
   2245     push(@implContent, "#ifndef NDEBUG\n");
   2246     push(@implContent, "    m_data = 0;\n");
   2247     push(@implContent, "#endif\n");
   2248     push(@implContent, "}\n");
   2249 
   2250     # Functions
   2251     my $numFunctions = @{$dataNode->functions};
   2252     if ($numFunctions > 0) {
   2253         push(@implContent, "\n// Functions\n");
   2254         foreach my $function (@{$dataNode->functions}) {
   2255             my @params = @{$function->parameters};
   2256             if ($function->signature->extendedAttributes->{"Custom"} ||
   2257                 !(GetNativeType($function->signature->type) eq "bool")) {
   2258                 next;
   2259             }
   2260 
   2261             AddIncludesForType($function->signature->type);
   2262             push(@implContent, "\n" . GetNativeType($function->signature->type) . " ${className}::" . $function->signature->name . "(");
   2263 
   2264             my @args = ();
   2265             foreach my $param (@params) {
   2266                 AddIncludesForType($param->type, 1);
   2267                 push(@args, GetNativeType($param->type) . " " . $param->name);
   2268             }
   2269             push(@implContent, join(", ", @args));
   2270             push(@implContent, ")\n");
   2271 
   2272             push(@implContent, "{\n");
   2273             push(@implContent, "    if (!canInvokeCallback())\n");
   2274             push(@implContent, "        return true;\n\n");
   2275             push(@implContent, "    RefPtr<$className> protect(this);\n\n");
   2276             push(@implContent, "    JSLock lock(SilenceAssertionsOnly);\n\n");
   2277             push(@implContent, "    ExecState* exec = m_data->globalObject()->globalExec();\n");
   2278             push(@implContent, "    MarkedArgumentBuffer args;\n");
   2279 
   2280             foreach my $param (@params) {
   2281                 my $paramName = $param->name;
   2282                 if ($param->type eq "DOMString") {
   2283                     push(@implContent, "    args.append(jsString(exec, ${paramName}));\n");
   2284                 } else {
   2285                     push(@implContent, "    args.append(toJS(exec, ${paramName}));\n");
   2286                 }
   2287             }
   2288 
   2289             push(@implContent, "\n    bool raisedException = false;\n");
   2290             push(@implContent, "    m_data->invokeCallback(args, &raisedException);\n");
   2291             push(@implContent, "    return !raisedException;\n");
   2292             push(@implContent, "}\n");
   2293         }
   2294     }
   2295 
   2296     push(@implContent, "\n}\n");
   2297     my $conditionalString = GenerateConditionalString($dataNode);
   2298     push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
   2299 }
   2300 
   2301 sub GenerateImplementationFunctionCall()
   2302 {
   2303     my $function = shift;
   2304     my $functionString = shift;
   2305     my $paramIndex = shift;
   2306     my $indent = shift;
   2307     my $svgPropertyType = shift;
   2308     my $implClassName = shift;
   2309 
   2310     if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
   2311         $functionString .= ", " if $paramIndex;
   2312         $paramIndex += 2;
   2313         $functionString .= "scriptArguments, callStack";
   2314     }
   2315 
   2316     if (@{$function->raisesExceptions}) {
   2317         $functionString .= ", " if $paramIndex;
   2318         $functionString .= "ec";
   2319     }
   2320     $functionString .= ")";
   2321 
   2322     if ($function->signature->type eq "void") {
   2323         push(@implContent, $indent . "$functionString;\n");
   2324         push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions};
   2325 
   2326         if ($svgPropertyType) {
   2327             if (@{$function->raisesExceptions}) {
   2328                 push(@implContent, $indent . "if (!ec)\n"); 
   2329                 push(@implContent, $indent . "    imp->commitChange();\n");
   2330             } else {
   2331                 push(@implContent, $indent . "imp->commitChange();\n");
   2332             }
   2333         }
   2334 
   2335         push(@implContent, $indent . "return JSValue::encode(jsUndefined());\n");
   2336     } else {
   2337         push(@implContent, "\n" . $indent . "JSC::JSValue result = " . NativeToJSValue($function->signature, 1, $implClassName, $functionString, "castedThis") . ";\n");
   2338         push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions};
   2339 
   2340         $callWith = $function->signature->extendedAttributes->{"CallWith"};
   2341         if ($callWith and $callWith eq "ScriptState") {
   2342             push(@implContent, $indent . "if (exec->hadException())\n");
   2343             push(@implContent, $indent . "    return JSValue::encode(jsUndefined());\n");
   2344         }
   2345 
   2346         push(@implContent, $indent . "return JSValue::encode(result);\n");
   2347     }
   2348 }
   2349 
   2350 sub GetNativeTypeFromSignature
   2351 {
   2352     my $signature = shift;
   2353     my $type = $codeGenerator->StripModule($signature->type);
   2354 
   2355     if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) {
   2356         # Special-case index arguments because we need to check that they aren't < 0.
   2357         return "int";
   2358     }
   2359 
   2360     return GetNativeType($type);
   2361 }
   2362 
   2363 my %nativeType = (
   2364     "CompareHow" => "Range::CompareHow",
   2365     "DOMString" => "const String&",
   2366     "DOMObject" => "ScriptValue",
   2367     "NodeFilter" => "RefPtr<NodeFilter>",
   2368     "SerializedScriptValue" => "RefPtr<SerializedScriptValue>",
   2369     "IDBKey" => "RefPtr<IDBKey>",
   2370     "boolean" => "bool",
   2371     "double" => "double",
   2372     "float" => "float",
   2373     "short" => "short",
   2374     "long" => "int",
   2375     "unsigned long" => "unsigned",
   2376     "unsigned short" => "unsigned short",
   2377     "long long" => "long long",
   2378     "unsigned long long" => "unsigned long long",
   2379     "MediaQueryListListener" => "RefPtr<MediaQueryListListener>"
   2380 );
   2381 
   2382 sub GetNativeType
   2383 {
   2384     my $type = shift;
   2385 
   2386     my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($type);
   2387     return "${svgNativeType}*" if $svgNativeType;
   2388     return $nativeType{$type} if exists $nativeType{$type};
   2389 
   2390     # For all other types, the native type is a pointer with same type name as the IDL type.
   2391     return "${type}*";
   2392 }
   2393 
   2394 sub GetSVGPropertyTypes
   2395 {
   2396     my $implType = shift;
   2397 
   2398     my $svgPropertyType;
   2399     my $svgListPropertyType;
   2400     my $svgNativeType;
   2401 
   2402     return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $implType =~ /SVG/;
   2403     
   2404     $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implType);
   2405     return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $svgNativeType;
   2406 
   2407     # Append space to avoid compilation errors when using  PassRefPtr<$svgNativeType>
   2408     $svgNativeType = "$svgNativeType ";
   2409 
   2410     my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implType);
   2411     if ($svgNativeType =~ /SVGPropertyTearOff/) {
   2412         $svgPropertyType = $svgWrappedNativeType;
   2413         $headerIncludes{"$svgWrappedNativeType.h"} = 1;
   2414         $headerIncludes{"SVGAnimatedPropertyTearOff.h"} = 1;
   2415     } elsif ($svgNativeType =~ /SVGListPropertyTearOff/ or $svgNativeType =~ /SVGStaticListPropertyTearOff/) {
   2416         $svgListPropertyType = $svgWrappedNativeType;
   2417         $headerIncludes{"$svgWrappedNativeType.h"} = 1;
   2418         $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;
   2419     } elsif ($svgNativeType =~ /SVGTransformListPropertyTearOff/) {
   2420         $svgListPropertyType = $svgWrappedNativeType;
   2421         $headerIncludes{"$svgWrappedNativeType.h"} = 1;
   2422         $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;
   2423         $headerIncludes{"SVGTransformListPropertyTearOff.h"} = 1;
   2424     } elsif ($svgNativeType =~ /SVGPathSegListPropertyTearOff/) {
   2425         $svgListPropertyType = $svgWrappedNativeType;
   2426         $headerIncludes{"$svgWrappedNativeType.h"} = 1;
   2427         $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;
   2428         $headerIncludes{"SVGPathSegListPropertyTearOff.h"} = 1;
   2429     }
   2430 
   2431     return ($svgPropertyType, $svgListPropertyType, $svgNativeType);
   2432 }
   2433 
   2434 sub IsNativeType
   2435 {
   2436     my $type = shift;
   2437     return exists $nativeType{$type};
   2438 }
   2439 
   2440 sub JSValueToNative
   2441 {
   2442     my $signature = shift;
   2443     my $value = shift;
   2444 
   2445     my $type = $codeGenerator->StripModule($signature->type);
   2446 
   2447     return "$value.toBoolean(exec)" if $type eq "boolean";
   2448     return "$value.toNumber(exec)" if $type eq "double";
   2449     return "$value.toFloat(exec)" if $type eq "float";
   2450     return "$value.toInt32(exec)" if $type eq "long" or $type eq "short";
   2451     return "$value.toUInt32(exec)" if $type eq "unsigned long" or $type eq "unsigned short";
   2452     return "static_cast<$type>($value.toInteger(exec))" if $type eq "long long" or $type eq "unsigned long long";
   2453 
   2454     return "valueToDate(exec, $value)" if $type eq "Date";
   2455     return "static_cast<Range::CompareHow>($value.toInt32(exec))" if $type eq "CompareHow";
   2456 
   2457     if ($type eq "DOMString") {
   2458         return "valueToStringWithNullCheck(exec, $value)" if $signature->extendedAttributes->{"ConvertNullToNullString"} || $signature->extendedAttributes->{"Reflect"};
   2459         return "valueToStringWithUndefinedOrNullCheck(exec, $value)" if $signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"};
   2460         return "ustringToString($value.toString(exec))";
   2461     }
   2462 
   2463     if ($type eq "DOMObject") {
   2464         return "exec->globalData(), $value";
   2465     }
   2466 
   2467     if ($type eq "NodeFilter") {
   2468         $implIncludes{"JS$type.h"} = 1;
   2469         return "to$type(exec->globalData(), $value)";
   2470     }
   2471 
   2472     if ($type eq "MediaQueryListListener") {
   2473         $implIncludes{"MediaQueryListListener.h"} = 1;
   2474         return "MediaQueryListListener::create(ScriptValue(exec->globalData(), " . $value ."))";
   2475     }
   2476 
   2477     if ($type eq "SerializedScriptValue" or $type eq "any") {
   2478         $implIncludes{"SerializedScriptValue.h"} = 1;
   2479         return "SerializedScriptValue::create(exec, $value)";
   2480     }
   2481 
   2482     if ($type eq "IDBKey") {
   2483         $implIncludes{"IDBBindingUtilities.h"} = 1;
   2484         $implIncludes{"IDBKey.h"} = 1;
   2485         return "createIDBKeyFromValue(exec, $value)";
   2486     }
   2487 
   2488     $implIncludes{"HTMLOptionElement.h"} = 1 if $type eq "HTMLOptionElement";
   2489     $implIncludes{"JSCustomVoidCallback.h"} = 1 if $type eq "VoidCallback";
   2490     $implIncludes{"Event.h"} = 1 if $type eq "Event";
   2491 
   2492     # Default, assume autogenerated type conversion routines
   2493     $implIncludes{"JS$type.h"} = 1;
   2494     return "to$type($value)";
   2495 }
   2496 
   2497 sub NativeToJSValue
   2498 {
   2499     my $signature = shift;
   2500     my $inFunctionCall = shift;
   2501     my $implClassName = shift;
   2502     my $value = shift;
   2503     my $thisValue = shift;
   2504 
   2505     my $type = $codeGenerator->StripModule($signature->type);
   2506 
   2507     return "jsBoolean($value)" if $type eq "boolean";
   2508 
   2509     # Need to check Date type before IsPrimitiveType().
   2510     if ($type eq "Date") {
   2511         return "jsDateOrNull(exec, $value)";
   2512     }
   2513 
   2514     if ($signature->extendedAttributes->{"Reflect"} and ($type eq "unsigned long" or $type eq "unsigned short")) {
   2515         $value =~ s/getUnsignedIntegralAttribute/getIntegralAttribute/g;
   2516         return "jsNumber(std::max(0, " . $value . "))";
   2517     }
   2518 
   2519     if ($codeGenerator->IsPrimitiveType($type) or $type eq "DOMTimeStamp") {
   2520         return "jsNumber($value)";
   2521     }
   2522 
   2523     if ($codeGenerator->IsStringType($type)) {
   2524         $implIncludes{"KURL.h"} = 1;
   2525         my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"};
   2526         if (defined $conv) {
   2527             return "jsStringOrNull(exec, $value)" if $conv eq "Null";
   2528             return "jsStringOrUndefined(exec, $value)" if $conv eq "Undefined";
   2529             return "jsStringOrFalse(exec, $value)" if $conv eq "False";
   2530 
   2531             die "Unknown value for ConvertNullStringTo extended attribute";
   2532         }
   2533         $conv = $signature->extendedAttributes->{"ConvertScriptString"};
   2534         return "jsOwnedStringOrNull(exec, $value)" if $conv;
   2535         $implIncludes{"<runtime/JSString.h>"} = 1;
   2536         return "jsString(exec, $value)";
   2537     }
   2538     
   2539     my $globalObject = "$thisValue->globalObject()";
   2540 
   2541     if ($type eq "CSSStyleDeclaration") {
   2542         $implIncludes{"CSSMutableStyleDeclaration.h"} = 1;
   2543     }
   2544 
   2545     if ($type eq "NodeList") {
   2546         $implIncludes{"NameNodeList.h"} = 1;
   2547     }
   2548 
   2549     if ($type eq "DOMObject") {
   2550         if ($implClassName eq "Document") {
   2551             $implIncludes{"JSCanvasRenderingContext2D.h"} = 1;
   2552         } else {
   2553             return "$value.jsValue();";
   2554         }
   2555     } elsif ($type =~ /SVGPathSeg/) {
   2556         $implIncludes{"JS$type.h"} = 1;
   2557         $joinedName = $type;
   2558         $joinedName =~ s/Abs|Rel//;
   2559         $implIncludes{"$joinedName.h"} = 1;
   2560     } elsif ($type eq "SerializedScriptValue" or $type eq "any") {
   2561         $implIncludes{"SerializedScriptValue.h"} = 1;
   2562         return "$value ? $value->deserialize(exec, castedThis->globalObject()) : jsNull()";
   2563     } else {
   2564         # Default, include header with same name.
   2565         $implIncludes{"JS$type.h"} = 1;
   2566         $implIncludes{"$type.h"} = 1 if not $codeGenerator->AvoidInclusionOfType($type);
   2567     }
   2568 
   2569     return $value if $codeGenerator->IsSVGAnimatedType($type);
   2570 
   2571     if ($signature->extendedAttributes->{"ReturnsNew"}) {        
   2572         return "toJSNewlyCreated(exec, $globalObject, WTF::getPtr($value))";
   2573     }
   2574 
   2575     if ($codeGenerator->IsSVGAnimatedType($implClassName)) {
   2576         # Convert from abstract SVGProperty to real type, so the right toJS() method can be invoked.
   2577         $value = "static_cast<" . GetNativeType($type) . ">($value)";
   2578     } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($type) and not $implClassName =~ /List$/) {
   2579         my $tearOffType = $codeGenerator->GetSVGTypeNeedingTearOff($type);
   2580         if ($codeGenerator->IsSVGTypeWithWritablePropertiesNeedingTearOff($type) and $inFunctionCall eq 0 and not defined $signature->extendedAttributes->{"Immutable"}) {
   2581             my $getter = $value;
   2582             $getter =~ s/imp\.//;
   2583             $getter =~ s/imp->//;
   2584             $getter =~ s/\(\)//;
   2585             my $updateMethod = "&${implClassName}::update" . $codeGenerator->WK_ucfirst($getter);
   2586 
   2587             my $selfIsTearOffType = $codeGenerator->IsSVGTypeNeedingTearOff($implClassName);
   2588             if ($selfIsTearOffType) {
   2589                 $implIncludes{"SVGStaticPropertyWithParentTearOff.h"} = 1;
   2590                 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyWithParentTearOff<$implClassName, /;
   2591 
   2592                 if ($value =~ /matrix/ and $implClassName eq "SVGTransform") {
   2593                     # SVGTransform offers a matrix() method for internal usage that returns an AffineTransform
   2594                     # and a svgMatrix() method returning a SVGMatrix, used for the bindings.
   2595                     $value =~ s/matrix/svgMatrix/;
   2596                 }
   2597 
   2598                 $value = "${tearOffType}::create(castedThis->impl(), $value, $updateMethod)";
   2599             } else {
   2600                 $implIncludes{"SVGStaticPropertyTearOff.h"} = 1;
   2601                 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyTearOff<$implClassName, /;
   2602                 $value = "${tearOffType}::create(imp, $value, $updateMethod)";
   2603             }
   2604         } elsif ($tearOffType =~ /SVGStaticListPropertyTearOff/) {
   2605             my $extraImp = "GetOwnerElementForType<$implClassName, IsDerivedFromSVGElement<$implClassName>::value>::ownerElement(imp), ";
   2606             $value = "${tearOffType}::create($extraImp$value)";
   2607         } elsif (not $tearOffType =~ /SVG(Point|PathSeg)List/) {
   2608             $value = "${tearOffType}::create($value)";
   2609         }
   2610     }
   2611 
   2612     return "toJS(exec, $globalObject, WTF::getPtr($value))";
   2613 }
   2614 
   2615 sub ceilingToPowerOf2
   2616 {
   2617     my ($size) = @_;
   2618 
   2619     my $powerOf2 = 1;
   2620     while ($size > $powerOf2) {
   2621         $powerOf2 <<= 1;
   2622     }
   2623 
   2624     return $powerOf2;
   2625 }
   2626 
   2627 # Internal Helper
   2628 sub GenerateHashTable
   2629 {
   2630     my $object = shift;
   2631 
   2632     my $name = shift;
   2633     my $size = shift;
   2634     my $keys = shift;
   2635     my $specials = shift;
   2636     my $value1 = shift;
   2637     my $value2 = shift;
   2638     my $conditionals = shift;
   2639 
   2640     # Generate size data for compact' size hash table
   2641 
   2642     my @table = ();
   2643     my @links = ();
   2644 
   2645     my $compactSize = ceilingToPowerOf2($size * 2);
   2646 
   2647     my $maxDepth = 0;
   2648     my $collisions = 0;
   2649     my $numEntries = $compactSize;
   2650 
   2651     my $i = 0;
   2652     foreach (@{$keys}) {
   2653         my $depth = 0;
   2654         my $h = $object->GenerateHashValue($_) % $numEntries;
   2655 
   2656         while (defined($table[$h])) {
   2657             if (defined($links[$h])) {
   2658                 $h = $links[$h];
   2659                 $depth++;
   2660             } else {
   2661                 $collisions++;
   2662                 $links[$h] = $compactSize;
   2663                 $h = $compactSize;
   2664                 $compactSize++;
   2665             }
   2666         }
   2667 
   2668         $table[$h] = $i;
   2669 
   2670         $i++;
   2671         $maxDepth = $depth if ($depth > $maxDepth);
   2672     }
   2673 
   2674     # Start outputing the hashtables
   2675     my $nameEntries = "${name}Values";
   2676     $nameEntries =~ s/:/_/g;
   2677 
   2678     if (($name =~ /Prototype/) or ($name =~ /Constructor/)) {
   2679         my $type = $name;
   2680         my $implClass;
   2681 
   2682         if ($name =~ /Prototype/) {
   2683             $type =~ s/Prototype.*//;
   2684             $implClass = $type; $implClass =~ s/Wrapper$//;
   2685             push(@implContent, "/* Hash table for prototype */\n");
   2686         } else {
   2687             $type =~ s/Constructor.*//;
   2688             $implClass = $type; $implClass =~ s/Constructor$//;
   2689             push(@implContent, "/* Hash table for constructor */\n");
   2690         }
   2691     } else {
   2692         push(@implContent, "/* Hash table */\n");
   2693     }
   2694 
   2695     # Dump the hash table
   2696     my $count = scalar @{$keys} + 1;
   2697     push(@implContent, "#if ENABLE(JIT)\n");
   2698     push(@implContent, "#define THUNK_GENERATOR(generator) , generator\n");
   2699     push(@implContent, "#else\n");
   2700     push(@implContent, "#define THUNK_GENERATOR(generator)\n");
   2701     push(@implContent, "#endif\n");
   2702     push(@implContent, "\nstatic const HashTableValue $nameEntries\[$count\] =\n\{\n");
   2703     $i = 0;
   2704     foreach my $key (@{$keys}) {
   2705         my $conditional;
   2706         my $targetType;
   2707 
   2708         if ($conditionals) {
   2709             $conditional = $conditionals->{$key};
   2710         }
   2711         if ($conditional) {
   2712             my $conditionalString = GenerateConditionalStringFromAttributeValue($conditional);
   2713             push(@implContent, "#if ${conditionalString}\n");
   2714         }
   2715         
   2716         if ("@$specials[$i]" =~ m/Function/) {
   2717             $targetType = "static_cast<NativeFunction>";
   2718         } else {
   2719             $targetType = "static_cast<PropertySlot::GetValueFunc>";
   2720         }
   2721         push(@implContent, "    { \"$key\", @$specials[$i], (intptr_t)" . $targetType . "(@$value1[$i]), (intptr_t)@$value2[$i] THUNK_GENERATOR(0) },\n");
   2722         if ($conditional) {
   2723             push(@implContent, "#endif\n");
   2724         }
   2725         ++$i;
   2726     }
   2727     push(@implContent, "    { 0, 0, 0, 0 THUNK_GENERATOR(0) }\n");
   2728     push(@implContent, "};\n\n");
   2729     push(@implContent, "#undef THUNK_GENERATOR\n");
   2730     my $compactSizeMask = $numEntries - 1;
   2731     push(@implContent, "static JSC_CONST_HASHTABLE HashTable $name = { $compactSize, $compactSizeMask, $nameEntries, 0 };\n");
   2732 }
   2733 
   2734 # Internal helper
   2735 sub GenerateHashValue
   2736 {
   2737     my $object = shift;
   2738 
   2739     @chars = split(/ */, $_[0]);
   2740 
   2741     # This hash is designed to work on 16-bit chunks at a time. But since the normal case
   2742     # (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they
   2743     # were 16-bit chunks, which should give matching results
   2744 
   2745     my $EXP2_32 = 4294967296;
   2746 
   2747     my $hash = 0x9e3779b9;
   2748     my $l    = scalar @chars; #I wish this was in Ruby --- Maks
   2749     my $rem  = $l & 1;
   2750     $l = $l >> 1;
   2751 
   2752     my $s = 0;
   2753 
   2754     # Main loop
   2755     for (; $l > 0; $l--) {
   2756         $hash   += ord($chars[$s]);
   2757         my $tmp = leftShift(ord($chars[$s+1]), 11) ^ $hash;
   2758         $hash   = (leftShift($hash, 16)% $EXP2_32) ^ $tmp;
   2759         $s += 2;
   2760         $hash += $hash >> 11;
   2761         $hash %= $EXP2_32;
   2762     }
   2763 
   2764     # Handle end case
   2765     if ($rem != 0) {
   2766         $hash += ord($chars[$s]);
   2767         $hash ^= (leftShift($hash, 11)% $EXP2_32);
   2768         $hash += $hash >> 17;
   2769     }
   2770 
   2771     # Force "avalanching" of final 127 bits
   2772     $hash ^= leftShift($hash, 3);
   2773     $hash += ($hash >> 5);
   2774     $hash = ($hash% $EXP2_32);
   2775     $hash ^= (leftShift($hash, 2)% $EXP2_32);
   2776     $hash += ($hash >> 15);
   2777     $hash = $hash% $EXP2_32;
   2778     $hash ^= (leftShift($hash, 10)% $EXP2_32);
   2779 
   2780     # this avoids ever returning a hash code of 0, since that is used to
   2781     # signal "hash not computed yet", using a value that is likely to be
   2782     # effectively the same as 0 when the low bits are masked
   2783     $hash = 0x80000000 if ($hash == 0);
   2784 
   2785     return $hash;
   2786 }
   2787 
   2788 # Internal helper
   2789 sub WriteData
   2790 {
   2791     if (defined($IMPL)) {
   2792         # Write content to file.
   2793         print $IMPL @implContentHeader;
   2794 
   2795         my @includes = ();
   2796         foreach my $include (keys %implIncludes) {
   2797             my $checkType = $include;
   2798             $checkType =~ s/\.h//;
   2799             next if $codeGenerator->IsSVGAnimatedType($checkType);
   2800 
   2801             $include = "\"$include\"" unless $include =~ /^["<]/; # "
   2802             push @includes, $include;
   2803         }
   2804         foreach my $include (sort @includes) {
   2805             print $IMPL "#include $include\n";
   2806         }
   2807 
   2808         print $IMPL @implContent;
   2809         close($IMPL);
   2810         undef($IMPL);
   2811 
   2812         @implContentHeader = ();
   2813         @implContent = ();
   2814         %implIncludes = ();
   2815     }
   2816 
   2817     if (defined($HEADER)) {
   2818         # Write content to file.
   2819         print $HEADER @headerContentHeader;
   2820 
   2821         my @includes = ();
   2822         foreach my $include (keys %headerIncludes) {
   2823             $include = "\"$include\"" unless $include =~ /^["<]/; # "
   2824             push @includes, $include;
   2825         }
   2826         foreach my $include (sort @includes) {
   2827             print $HEADER "#include $include\n";
   2828         }
   2829 
   2830         print $HEADER @headerContent;
   2831 
   2832         @includes = ();
   2833         foreach my $include (keys %headerTrailingIncludes) {
   2834             $include = "\"$include\"" unless $include =~ /^["<]/; # "
   2835             push @includes, $include;
   2836         }
   2837         foreach my $include (sort @includes) {
   2838             print $HEADER "#include $include\n";
   2839         }
   2840 
   2841         close($HEADER);
   2842         undef($HEADER);
   2843 
   2844         @headerContentHeader = ();
   2845         @headerContent = ();
   2846         %headerIncludes = ();
   2847         %headerTrailingIncludes = ();
   2848     }
   2849 
   2850     if (defined($DEPS)) {
   2851         # Write dependency file.
   2852         print $DEPS @depsContent;
   2853         close($DEPS);
   2854         undef($DEPS);
   2855 
   2856         @depsContent = ();
   2857     }
   2858 }
   2859 
   2860 sub GenerateConstructorDeclaration
   2861 {
   2862     my $outputArray = shift;
   2863     my $className = shift;
   2864     my $dataNode = shift;
   2865 
   2866     my $constructorClassName = "${className}Constructor";
   2867     my $canConstruct = $dataNode->extendedAttributes->{"CanBeConstructed"};
   2868     my $callWith = $dataNode->extendedAttributes->{"CallWith"};
   2869 
   2870     push(@$outputArray, "class ${constructorClassName} : public DOMConstructorObject {\n");
   2871     push(@$outputArray, "public:\n");
   2872     push(@$outputArray, "    ${constructorClassName}(JSC::ExecState*, JSDOMGlobalObject*);\n\n");
   2873 
   2874     push(@$outputArray, "    virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n");
   2875     push(@$outputArray, "    virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n");
   2876     push(@$outputArray, "    static const JSC::ClassInfo s_info;\n");
   2877 
   2878     push(@$outputArray, "    static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)\n");
   2879     push(@$outputArray, "    {\n");
   2880     push(@$outputArray, "        return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);\n");
   2881     push(@$outputArray, "    }\n");
   2882 
   2883     push(@$outputArray, "protected:\n");
   2884     push(@$outputArray, "    static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::ImplementsHasInstance | DOMConstructorObject::StructureFlags;\n");
   2885 
   2886     if ($canConstruct) {
   2887         push(@$outputArray, "    static JSC::EncodedJSValue JSC_HOST_CALL construct${className}(JSC::ExecState*);\n");
   2888         push(@$outputArray, "    virtual JSC::ConstructType getConstructData(JSC::ConstructData&);\n");
   2889     }
   2890     push(@$outputArray, "};\n\n");
   2891 }
   2892 
   2893 sub GenerateConstructorDefinition
   2894 {
   2895     my $outputArray = shift;
   2896 
   2897     my $className = shift;
   2898     my $protoClassName = shift;
   2899     my $interfaceName = shift;
   2900     my $visibleClassName = shift;
   2901     my $dataNode = shift;
   2902 
   2903     my $constructorClassName = "${className}Constructor";
   2904     my $canConstruct = $dataNode->extendedAttributes->{"CanBeConstructed"};
   2905     my $customConstructFunction = $dataNode->extendedAttributes->{"CustomConstructFunction"};
   2906     my $callWith = $dataNode->extendedAttributes->{"CallWith"};
   2907     my $numberOfconstructParameters = $dataNode->extendedAttributes->{"ConstructorParameters"};
   2908 
   2909     push(@$outputArray, "const ClassInfo ${constructorClassName}::s_info = { \"${visibleClassName}Constructor\", &DOMConstructorObject::s_info, &${constructorClassName}Table, 0 };\n\n");
   2910 
   2911     push(@$outputArray, "${constructorClassName}::${constructorClassName}(ExecState* exec, JSDOMGlobalObject* globalObject)\n");
   2912     push(@$outputArray, "    : DOMConstructorObject(${constructorClassName}::createStructure(globalObject->globalData(), globalObject->objectPrototype()), globalObject)\n");
   2913     push(@$outputArray, "{\n");
   2914     push(@$outputArray, "    ASSERT(inherits(&s_info));\n");
   2915     if ($interfaceName eq "DOMWindow") {
   2916         push(@$outputArray, "    putDirect(exec->globalData(), exec->propertyNames().prototype, globalObject->prototype(), DontDelete | ReadOnly);\n");
   2917     } else {
   2918         push(@$outputArray, "    putDirect(exec->globalData(), exec->propertyNames().prototype, ${protoClassName}::self(exec, globalObject), DontDelete | ReadOnly);\n");
   2919     }
   2920     push(@$outputArray, "    putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(${numberOfconstructParameters}), ReadOnly | DontDelete | DontEnum);\n") if $numberOfconstructParameters;
   2921     push(@$outputArray, "}\n\n");
   2922 
   2923     push(@$outputArray, "bool ${constructorClassName}::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n");
   2924     push(@$outputArray, "{\n");
   2925     push(@$outputArray, "    return getStaticValueSlot<${constructorClassName}, JSDOMWrapper>(exec, &${constructorClassName}Table, this, propertyName, slot);\n");
   2926     push(@$outputArray, "}\n\n");
   2927 
   2928     push(@$outputArray, "bool ${constructorClassName}::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\n");
   2929     push(@$outputArray, "{\n");
   2930     push(@$outputArray, "    return getStaticValueDescriptor<${constructorClassName}, JSDOMWrapper>(exec, &${constructorClassName}Table, this, propertyName, descriptor);\n");
   2931     push(@$outputArray, "}\n\n");
   2932 
   2933     if ($canConstruct) {
   2934         if (!$customConstructFunction) {
   2935             push(@$outputArray, "EncodedJSValue JSC_HOST_CALL ${constructorClassName}::construct${className}(ExecState* exec)\n");
   2936             push(@$outputArray, "{\n");
   2937             my $constructorArg = "";
   2938             if ($callWith and $callWith eq "ScriptExecutionContext") {
   2939                 $constructorArg = "context";
   2940                 push(@$outputArray, "    ScriptExecutionContext* context = static_cast<${constructorClassName}*>(exec->callee())->scriptExecutionContext();\n");
   2941                 push(@$outputArray, "    if (!context)\n");
   2942                 push(@$outputArray, "        return throwVMError(exec, createReferenceError(exec, \"Reference error\"));\n");
   2943             }
   2944             push(@$outputArray, "    return JSValue::encode(asObject(toJS(exec, static_cast<${constructorClassName}*>(exec->callee())->globalObject(), ${interfaceName}::create(${constructorArg}))));\n");
   2945             push(@$outputArray, "}\n\n");
   2946         }
   2947 
   2948         push(@$outputArray, "ConstructType ${constructorClassName}::getConstructData(ConstructData& constructData)\n");
   2949         push(@$outputArray, "{\n");
   2950         push(@$outputArray, "    constructData.native.function = construct${className};\n");
   2951         push(@$outputArray, "    return ConstructTypeHost;\n");
   2952         push(@$outputArray, "}\n\n");
   2953     }
   2954 }
   2955 
   2956 1;
   2957