Home | History | Annotate | Download | only in scripts
      1 
      2 # Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann (at] kde.org>
      3 # Copyright (C) 2006 Anders Carlsson <andersca (at] mac.com>
      4 # Copyright (C) 2006 Samuel Weinig <sam.weinig (at] gmail.com>
      5 # Copyright (C) 2006 Alexey Proskuryakov <ap (at] webkit.org>
      6 # Copyright (C) 2006 Apple Computer, Inc.
      7 # Copyright (C) 2007, 2008, 2009 Google Inc.
      8 # Copyright (C) 2009 Cameron McCormack <cam (at] mcc.id.au>
      9 #
     10 # This library is free software; you can redistribute it and/or
     11 # modify it under the terms of the GNU Library General Public
     12 # License as published by the Free Software Foundation; either
     13 # version 2 of the License, or (at your option) any later version.
     14 #
     15 # This library is distributed in the hope that it will be useful,
     16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
     17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     18 # Library General Public License for more details.
     19 #
     20 # You should have received a copy of the GNU Library General Public License
     21 # aint with this library; see the file COPYING.LIB.  If not, write to
     22 # the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
     23 # Boston, MA 02111-1307, USA.
     24 #
     25 
     26 package CodeGeneratorV8;
     27 
     28 use File::stat;
     29 use Digest::MD5;
     30 
     31 my $module = "";
     32 my $outputDir = "";
     33 
     34 my @headerContent = ();
     35 my @implContentHeader = ();
     36 my @implFixedHeader = ();
     37 my @implContent = ();
     38 my @implContentDecls = ();
     39 my %implIncludes = ();
     40 
     41 my @allParents = ();
     42 
     43 # Default .h template
     44 my $headerTemplate = << "EOF";
     45 /*
     46     This file is part of the WebKit open source project.
     47     This file has been generated by generate-bindings.pl. DO NOT MODIFY!
     48 
     49     This library is free software; you can redistribute it and/or
     50     modify it under the terms of the GNU Library General Public
     51     License as published by the Free Software Foundation; either
     52     version 2 of the License, or (at your option) any later version.
     53 
     54     This library is distributed in the hope that it will be useful,
     55     but WITHOUT ANY WARRANTY; without even the implied warranty of
     56     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     57     Library General Public License for more details.
     58 
     59     You should have received a copy of the GNU Library General Public License
     60     along with this library; see the file COPYING.LIB.  If not, write to
     61     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
     62     Boston, MA 02111-1307, USA.
     63 */
     64 EOF
     65 
     66 # Default constructor
     67 sub new
     68 {
     69     my $object = shift;
     70     my $reference = { };
     71 
     72     $codeGenerator = shift;
     73     $outputDir = shift;
     74 
     75     bless($reference, $object);
     76     return $reference;
     77 }
     78 
     79 sub finish
     80 {
     81     my $object = shift;
     82 
     83     # Commit changes!
     84     $object->WriteData();
     85 }
     86 
     87 sub leftShift($$) {
     88     my ($value, $distance) = @_;
     89     return (($value << $distance) & 0xFFFFFFFF);
     90 }
     91 
     92 # Workaround for V8 bindings difference where RGBColor is not a POD type.
     93 sub IsPodType
     94 {
     95     my $type = shift;
     96     return $codeGenerator->IsPodType($type);
     97 }
     98 
     99 # Params: 'domClass' struct
    100 sub GenerateInterface
    101 {
    102     my $object = shift;
    103     my $dataNode = shift;
    104     my $defines = shift;
    105 
    106     # Start actual generation
    107     $object->GenerateHeader($dataNode);
    108     $object->GenerateImplementation($dataNode);
    109 
    110     my $name = $dataNode->name;
    111 
    112     # Open files for writing
    113     my $headerFileName = "$outputDir/V8$name.h";
    114     my $implFileName = "$outputDir/V8$name.cpp";
    115 
    116     open($IMPL, ">$implFileName") || die "Couldn't open file $implFileName";
    117     open($HEADER, ">$headerFileName") || die "Couldn't open file $headerFileName";
    118 }
    119 
    120 # Params: 'idlDocument' struct
    121 sub GenerateModule
    122 {
    123     my $object = shift;
    124     my $dataNode = shift;
    125 
    126     $module = $dataNode->module;
    127 }
    128 
    129 sub GetLegacyHeaderIncludes
    130 {
    131     my $legacyParent = shift;
    132 
    133     die "Don't know what headers to include for module $module";
    134 }
    135 
    136 sub AvoidInclusionOfType
    137 {
    138     my $type = shift;
    139 
    140     # Special case: SVGRect.h / SVGPoint.h / SVGNumber.h / SVGMatrix.h do not exist.
    141     return 1 if $type eq "SVGRect" or $type eq "SVGPoint" or $type eq "SVGNumber" or $type eq "SVGMatrix";
    142     return 0;
    143 }
    144 
    145 sub UsesManualToJSImplementation
    146 {
    147     my $type = shift;
    148 
    149     return 1 if $type eq "SVGPathSeg";
    150     return 0;
    151 }
    152 
    153 sub AddIncludesForType
    154 {
    155     my $type = $codeGenerator->StripModule(shift);
    156 
    157     # When we're finished with the one-file-per-class
    158     # reorganization, we won't need these special cases.
    159     if (!$codeGenerator->IsPrimitiveType($type) and !AvoidInclusionOfType($type) and $type ne "Date") {
    160         # default, include the same named file
    161         $implIncludes{GetV8HeaderName(${type})} = 1;
    162 
    163         if ($type =~ /SVGPathSeg/) {
    164             $joinedName = $type;
    165             $joinedName =~ s/Abs|Rel//;
    166             $implIncludes{"${joinedName}.h"} = 1;
    167         }
    168     }
    169 
    170     # additional includes (things needed to compile the bindings but not the header)
    171 
    172     if ($type eq "CanvasRenderingContext2D") {
    173         $implIncludes{"CanvasGradient.h"} = 1;
    174         $implIncludes{"CanvasPattern.h"} = 1;
    175         $implIncludes{"CanvasStyle.h"} = 1;
    176     }
    177 
    178     if ($type eq "CanvasGradient" or $type eq "XPathNSResolver") {
    179         $implIncludes{"PlatformString.h"} = 1;
    180     }
    181 
    182     if ($type eq "CSSStyleDeclaration") {
    183         $implIncludes{"CSSMutableStyleDeclaration.h"} = 1;
    184     }
    185 
    186     if ($type eq "Plugin" or $type eq "PluginArray" or $type eq "MimeTypeArray") {
    187         # So we can get String -> AtomicString conversion for namedItem().
    188         $implIncludes{"AtomicString.h"} = 1;
    189     }
    190 }
    191 
    192 sub AddIncludesForSVGAnimatedType
    193 {
    194     my $type = shift;
    195     $type =~ s/SVGAnimated//;
    196 
    197     if ($type eq "Point" or $type eq "Rect") {
    198         $implIncludes{"Float$type.h"} = 1;
    199     } elsif ($type eq "String") {
    200         $implIncludes{"PlatformString.h"} = 1;
    201     }
    202 
    203     $implIncludes{"SVGAnimatedTemplate.h"} = 1;
    204 }
    205 
    206 sub AddClassForwardIfNeeded
    207 {
    208     my $implClassName = shift;
    209 
    210     # SVGAnimatedLength/Number/etc.. are typedefs to SVGAnimtatedTemplate, so don't use class forwards for them!
    211     push(@headerContent, "class $implClassName;\n\n") unless $codeGenerator->IsSVGAnimatedType($implClassName);
    212 }
    213 
    214 # If the node has a [Conditional=XXX] attribute, returns an "ENABLE(XXX)" string for use in an #if.
    215 sub GenerateConditionalString
    216 {
    217     my $node = shift;
    218     my $conditional = $node->extendedAttributes->{"Conditional"};
    219     if ($conditional) {
    220         return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
    221     } else {
    222         return "";
    223     }
    224 }
    225 
    226 sub GenerateHeader
    227 {
    228     my $object = shift;
    229     my $dataNode = shift;
    230 
    231     my $interfaceName = $dataNode->name;
    232     my $className = "V8$interfaceName";
    233     my $implClassName = $interfaceName;
    234 
    235     # Copy contents of parent classes except the first parent or if it is
    236     # EventTarget.
    237     $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@allParents, 1);
    238 
    239     my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
    240     my $conditionalString = GenerateConditionalString($dataNode);
    241 
    242     # - Add default header template
    243     @headerContent = split("\r", $headerTemplate);
    244 
    245     push(@headerContent, "\n#if ${conditionalString}\n\n") if $conditionalString;
    246     push(@headerContent, "\n#ifndef $className" . "_H");
    247     push(@headerContent, "\n#define $className" . "_H\n\n");
    248 
    249     # Get correct pass/store types respecting PODType flag
    250     my $podType = $dataNode->extendedAttributes->{"PODType"};
    251 
    252     push(@headerContent, "#include \"$podType.h\"\n") if $podType and ($podType ne "double" and $podType ne "float" and $podType ne "RGBA32");
    253 
    254     push(@headerContent, "#include <v8.h>\n");
    255     push(@headerContent, "#include <wtf/HashMap.h>\n");
    256     push(@headerContent, "#include \"StringHash.h\"\n");
    257     push(@headerContent, "#include \"V8Index.h\"\n");
    258     push(@headerContent, GetHeaderClassInclude($implClassName));
    259     push(@headerContent, "\nnamespace WebCore {\n");
    260     if ($podType) {
    261         push(@headerContent, "\ntemplate<typename PODType> class V8SVGPODTypeWrapper;\n");
    262     }
    263     push(@headerContent, "\nclass $className {\n");
    264 
    265     my $nativeType = GetNativeTypeForConversions($interfaceName);
    266     if ($podType) {
    267         $nativeType = "V8SVGPODTypeWrapper<${nativeType} >";
    268     }
    269     my $forceNewObjectParameter = IsDOMNodeType($interfaceName) ? ", bool forceNewObject = false" : "";
    270     push(@headerContent, <<END);
    271 
    272  public:
    273   static bool HasInstance(v8::Handle<v8::Value> value);
    274   static v8::Persistent<v8::FunctionTemplate> GetRawTemplate();
    275   static v8::Persistent<v8::FunctionTemplate> GetTemplate();
    276   static ${nativeType}* toNative(v8::Handle<v8::Object>);
    277   static v8::Handle<v8::Object> wrap(${nativeType}*${forceNewObjectParameter});
    278 END
    279 
    280     if ($implClassName eq "DOMWindow") {
    281       push(@headerContent, <<END);
    282   static v8::Persistent<v8::ObjectTemplate> GetShadowObjectTemplate();
    283 END
    284     }
    285 
    286     my @enabledAtRuntime;
    287     foreach my $function (@{$dataNode->functions}) {
    288         my $name = $function->signature->name;
    289         my $attrExt = $function->signature->extendedAttributes;
    290 
    291         # FIXME: We should only be generating callback declarations for functions labeled [Custom] or [V8Custom],
    292         # but we can't do that due to some mislabeled functions in the idl's (https://bugs.webkit.org/show_bug.cgi?id=33066).
    293         push(@headerContent, <<END);
    294   static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments&);
    295 END
    296         if ($attrExt->{"EnabledAtRuntime"}) {
    297             push(@enabledAtRuntime, $function);
    298         }
    299     }
    300 
    301     if ($dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"CanBeConstructed"}) {
    302         push(@headerContent, <<END);
    303   static v8::Handle<v8::Value> constructorCallback(const v8::Arguments& args);
    304 END
    305     }
    306 
    307     foreach my $attribute (@{$dataNode->attributes}) {
    308         my $name = $attribute->signature->name;
    309         my $attrExt = $attribute->signature->extendedAttributes;
    310         if ($attrExt->{"V8CustomGetter"} || $attrExt->{"CustomGetter"}
    311             || $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) {
    312             push(@headerContent, <<END);
    313   static v8::Handle<v8::Value> ${name}AccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);
    314 END
    315         }
    316         if ($attrExt->{"V8CustomSetter"} || $attrExt->{"CustomSetter"}
    317             || $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) {
    318             push(@headerContent, <<END);
    319   static void ${name}AccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info);
    320 END
    321         }
    322         if ($attrExt->{"EnabledAtRuntime"}) {
    323             push(@enabledAtRuntime, $attribute);
    324         }
    325     }
    326 
    327     GenerateHeaderNamedAndIndexedPropertyAccessors($dataNode);
    328     GenerateHeaderCustomCall($dataNode);
    329     GenerateHeaderCustomInternalFieldIndices($dataNode);
    330 
    331     if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) {
    332         push(@headerContent, <<END);
    333   static bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType, v8::Local<v8::Value> data);
    334   static bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType, v8::Local<v8::Value> data);
    335 END
    336     }
    337 
    338     push(@headerContent, <<END);
    339 };
    340 
    341   v8::Handle<v8::Value> toV8(${nativeType}*${forceNewObjectParameter});
    342 END
    343     if (IsRefPtrType($implClassName)) {
    344         push(@headerContent, <<END);
    345   v8::Handle<v8::Value> toV8(PassRefPtr<${nativeType} >${forceNewObjectParameter});
    346 END
    347     }
    348 
    349     push(@headerContent, "}\n\n");
    350     push(@headerContent, "#endif // $className" . "_H\n");
    351 
    352     push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;
    353 }
    354 
    355 sub GetInternalFields
    356 {
    357     my $dataNode = shift;
    358     my $name = $dataNode->name;
    359 
    360     # FIXME: I am hideous and hard-coded.  Make me beautiful.
    361     return ("cacheIndex", "implementationIndex") if ($name eq "Document") || ($name eq "SVGDocument");
    362     return ("cacheIndex", "implementationIndex", "markerIndex", "shadowIndex") if $name eq "HTMLDocument";
    363     return ("cacheIndex") if IsNodeSubType($dataNode);
    364     return ("cacheIndex") if $name eq "EventSource";
    365     return ("cacheIndex") if $name eq "XMLHttpRequest";
    366     return ("cacheIndex") if $name eq "XMLHttpRequestUpload";
    367     return ("cacheIndex") if $name eq "MessagePort";
    368     return ("port1Index", "port2Index") if ($name eq "MessageChannel");
    369     return ("cacheIndex") if $name eq "AbstractWorker";
    370     return ("abstractWorkerCacheIndex", "cacheIndex") if $name eq "Worker";
    371     return ("abstractWorkerCacheIndex", "cacheIndex") if $name eq "WorkerContext";
    372     return ("abstractWorkerCacheIndex", "workerContextCacheIndex", "cacheIndex") if $name eq "DedicatedWorkerContext";
    373     return ("abstractWorkerCacheIndex", "cacheIndex") if $name eq "SharedWorker";
    374     return ("abstractWorkerCacheIndex", "workerContextCacheIndex", "cacheIndex") if $name eq "SharedWorkerContext";
    375     return ("cacheIndex") if $name eq "Notification";
    376     return ("cacheIndex") if $name eq "IDBRequest";
    377     return ("cacheIndex") if $name eq "SVGElementInstance";
    378     return ("consoleIndex", "historyIndex", "locationbarIndex", "menubarIndex", "navigatorIndex", "personalbarIndex",
    379         "screenIndex", "scrollbarsIndex", "selectionIndex", "statusbarIndex", "toolbarIndex", "locationIndex",
    380         "domSelectionIndex", "cacheIndex", "enteredIsolatedWorldIndex") if $name eq "DOMWindow";
    381     return ("cacheIndex") if $name eq "DOMApplicationCache";
    382     return ("cacheIndex") if $name eq "WebSocket";
    383     return ("ownerNodeIndex") if ($name eq "StyleSheet") || ($name eq "CSSStyleSheet");
    384     return ("ownerNodeIndex") if ($name eq "NamedNodeMap");
    385     return ();
    386 }
    387 
    388 sub GetHeaderClassInclude
    389 {
    390     my $className = shift;
    391     if ($className =~ /SVGPathSeg/) {
    392         $className =~ s/Abs|Rel//;
    393     }
    394     return "" if (AvoidInclusionOfType($className));
    395     return "#include \"SVGAnimatedTemplate.h\"\n" if ($codeGenerator->IsSVGAnimatedType($className));
    396     return "#include \"${className}.h\"\n";
    397 }
    398 
    399 sub GenerateHeaderCustomInternalFieldIndices
    400 {
    401     my $dataNode = shift;
    402     my @customInternalFields = GetInternalFields($dataNode);
    403     my $customFieldCounter = 0;
    404     foreach my $customInternalField (@customInternalFields) {
    405         push(@headerContent, <<END);
    406   static const int ${customInternalField} = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
    407 END
    408         $customFieldCounter++;
    409     }
    410     push(@headerContent, <<END);
    411   static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
    412 END
    413 }
    414 
    415 my %indexerSpecialCases = (
    416     "Storage" => 1,
    417     "HTMLAppletElement" => 1,
    418     "HTMLDocument" => 1,
    419     "HTMLEmbedElement" => 1,
    420     "HTMLObjectElement" => 1
    421 );
    422 
    423 sub GenerateHeaderNamedAndIndexedPropertyAccessors
    424 {
    425     my $dataNode = shift;
    426     my $interfaceName = $dataNode->name;
    427     my $hasCustomIndexedGetter = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
    428     my $hasCustomIndexedSetter = $dataNode->extendedAttributes->{"HasCustomIndexSetter"} && !$dataNode->extendedAttributes->{"HasNumericIndexGetter"};
    429     my $hasCustomNamedGetter = $dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
    430     my $hasCustomNamedSetter = $dataNode->extendedAttributes->{"DelegatingPutFunction"};
    431     my $hasCustomDeleters = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
    432     my $hasCustomEnumerator = $dataNode->extendedAttributes->{"CustomGetPropertyNames"};
    433     if ($interfaceName eq "HTMLOptionsCollection") {
    434         $interfaceName = "HTMLCollection";
    435         $hasCustomIndexedGetter = 1;
    436         $hasCustomNamedGetter = 1;
    437     }
    438     if ($interfaceName eq "DOMWindow") {
    439         $hasCustomDeleterr = 0;
    440         $hasEnumerator = 0;
    441     }
    442     if ($interfaceName eq "HTMLSelectElement") {
    443         $hasCustomNamedGetter = 1;
    444     }
    445     my $isIndexerSpecialCase = exists $indexerSpecialCases{$interfaceName};
    446 
    447     if ($hasCustomIndexedGetter || $isIndexerSpecialCase) {
    448         push(@headerContent, <<END);
    449   static v8::Handle<v8::Value> indexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info);
    450 END
    451     }
    452 
    453     if ($isIndexerSpecialCase || $hasCustomIndexedSetter) {
    454         push(@headerContent, <<END);
    455   static v8::Handle<v8::Value> indexedPropertySetter(uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info);
    456 END
    457     }
    458     if ($hasCustomDeleters) {
    459         push(@headerContent, <<END);
    460   static v8::Handle<v8::Boolean> indexedPropertyDeleter(uint32_t index, const v8::AccessorInfo& info);
    461 END
    462     }
    463     if ($hasCustomNamedGetter) {
    464         push(@headerContent, <<END);
    465   static v8::Handle<v8::Value> namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);
    466 END
    467     }
    468     if ($hasCustomNamedSetter) {
    469         push(@headerContent, <<END);
    470   static v8::Handle<v8::Value> namedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info);
    471 END
    472     }
    473     if ($hasCustomDeleters || $interfaceName eq "HTMLDocument") {
    474         push(@headerContent, <<END);
    475   static v8::Handle<v8::Boolean> namedPropertyDeleter(v8::Local<v8::String> name, const v8::AccessorInfo& info);
    476 END
    477     }
    478     if ($hasCustomEnumerator) {
    479         push(@headerContent, <<END);
    480   static v8::Handle<v8::Array> namedPropertyEnumerator(const v8::AccessorInfo& info);
    481 END
    482     }
    483 }
    484 
    485 sub GenerateHeaderCustomCall
    486 {
    487     my $dataNode = shift;
    488 
    489     if ($dataNode->extendedAttributes->{"CustomCall"}) {
    490         push(@headerContent, "  static v8::Handle<v8::Value> callAsFunctionCallback(const v8::Arguments&);\n");
    491     }
    492     if ($dataNode->name eq "Event") {
    493         push(@headerContent, "  static v8::Handle<v8::Value> dataTransferAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
    494         push(@headerContent, "  static void valueAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info);\n");
    495     }
    496     if ($dataNode->name eq "Location") {
    497         push(@headerContent, "  static v8::Handle<v8::Value> assignAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
    498         push(@headerContent, "  static v8::Handle<v8::Value> reloadAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
    499         push(@headerContent, "  static v8::Handle<v8::Value> replaceAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
    500     }
    501 }
    502 
    503 sub GenerateSetDOMException
    504 {
    505     my $indent = shift;
    506     my $result = "";
    507 
    508     $result .= $indent . "if (UNLIKELY(ec)) {\n";
    509     $result .= $indent . "    V8Proxy::setDOMException(ec);\n";
    510     $result .= $indent . "    return v8::Handle<v8::Value>();\n";
    511     $result .= $indent . "}\n";
    512 
    513     return $result;
    514 }
    515 
    516 sub IsSubType
    517 {
    518     my $dataNode = shift;
    519     my $parentType = shift;
    520     return 1 if ($dataNode->name eq $parentType);
    521     foreach (@allParents) {
    522         my $parent = $codeGenerator->StripModule($_);
    523         return 1 if $parent eq $parentType;
    524     }
    525     return 0;
    526 }
    527 
    528 sub IsNodeSubType
    529 {
    530     my $dataNode = shift;
    531     return IsSubType($dataNode, "Node");
    532 }
    533 
    534 sub IsEventSubType
    535 {
    536     my $dataNode = shift;
    537     return IsSubType($dataNode, "Event");
    538 }
    539 
    540 sub GenerateDomainSafeFunctionGetter
    541 {
    542     my $function = shift;
    543     my $dataNode = shift;
    544     my $implClassName = shift;
    545 
    546     my $className = "V8" . $dataNode->name;
    547     my $funcName = $function->signature->name;
    548 
    549     my $signature = "v8::Signature::New(" . $className . "::GetRawTemplate())";
    550     if ($function->signature->extendedAttributes->{"V8DoNotCheckSignature"}) {
    551         $signature = "v8::Local<v8::Signature>()";
    552     }
    553 
    554     my $newTemplateString = GenerateNewFunctionTemplate($function, $dataNode, $signature);
    555 
    556     push(@implContentDecls, <<END);
    557   static v8::Handle<v8::Value> ${funcName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) {
    558     INC_STATS(\"DOM.$implClassName.$funcName._get\");
    559     static v8::Persistent<v8::FunctionTemplate> private_template =
    560         v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
    561     v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(${className}::GetTemplate(), info.This());
    562     if (holder.IsEmpty()) {
    563       // can only reach here by 'object.__proto__.func', and it should passed
    564       // domain security check already
    565       return private_template->GetFunction();
    566     }
    567     ${implClassName}* imp = ${className}::toNative(holder);
    568     if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false)) {
    569       static v8::Persistent<v8::FunctionTemplate> shared_template =
    570         v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
    571       return shared_template->GetFunction();
    572 
    573     } else {
    574       return private_template->GetFunction();
    575     }
    576   }
    577 
    578 END
    579 }
    580 
    581 sub GenerateConstructorGetter
    582 {
    583     my $implClassName = shift;
    584     my $classIndex = shift;
    585 
    586     push(@implContentDecls, <<END);
    587   static v8::Handle<v8::Value> ${implClassName}ConstructorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) {
    588     INC_STATS(\"DOM.$implClassName.constructors._get\");
    589     v8::Handle<v8::Value> data = info.Data();
    590     ASSERT(data->IsNumber());
    591     V8ClassIndex::V8WrapperType type = V8ClassIndex::FromInt(data->Int32Value());
    592 END
    593 
    594     if ($classIndex eq "DOMWINDOW") {
    595         push(@implContentDecls, <<END);
    596     // Get the proxy corresponding to the DOMWindow if possible to
    597     // make sure that the constructor function is constructed in the
    598     // context of the DOMWindow and not in the context of the caller.
    599     return V8DOMWrapper::getConstructor(type, V8DOMWindow::toNative(info.Holder()));
    600 END
    601     } elsif ($classIndex eq "DEDICATEDWORKERCONTEXT" or $classIndex eq "WORKERCONTEXT" or $classIndex eq "SHAREDWORKERCONTEXT") {
    602         push(@implContentDecls, <<END);
    603     return V8DOMWrapper::getConstructor(type, V8WorkerContext::toNative(info.Holder()));
    604 END
    605     } else {
    606         push(@implContentDecls, "    return v8::Handle<v8::Value>();");
    607     }
    608 
    609     push(@implContentDecls, <<END);
    610 
    611     }
    612 
    613 END
    614 }
    615 
    616 sub GenerateNormalAttrGetter
    617 {
    618     my $attribute = shift;
    619     my $dataNode = shift;
    620     my $implClassName = shift;
    621     my $interfaceName = shift;
    622 
    623     my $attrExt = $attribute->signature->extendedAttributes;
    624 
    625     my $attrName = $attribute->signature->name;
    626 
    627     my $attrType = GetTypeFromSignature($attribute->signature);
    628     my $attrIsPodType = IsPodType($attrType);
    629 
    630     my $nativeType = GetNativeTypeFromSignature($attribute->signature, -1);
    631     my $isPodType = IsPodType($implClassName);
    632     my $skipContext = 0;
    633 
    634 
    635     if ($isPodType) {
    636         $implClassName = GetNativeType($implClassName);
    637         $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
    638     }
    639 
    640     # Special case: SVGZoomEvent's attributes are all read-only
    641     if ($implClassName eq "SVGZoomEvent") {
    642         $attrIsPodType = 0;
    643         $skipContext = 1;
    644     }
    645 
    646     # Special case: SVGSVGEelement::viewport is read-only
    647     if (($implClassName eq "SVGSVGElement") and ($attrName eq "viewport")) {
    648         $attrIsPodType = 0;
    649         $skipContext = 1;
    650     }
    651 
    652     # Special case for SVGColor
    653     if (($implClassName eq "SVGColor") and ($attrName eq "rgbColor")) {
    654         $attrIsPodType = 0;
    655     }
    656 
    657     my $getterStringUsesImp = $implClassName ne "float";
    658 
    659   # Getter
    660     push(@implContentDecls, <<END);
    661   static v8::Handle<v8::Value> ${attrName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) {
    662     INC_STATS(\"DOM.$implClassName.$attrName._get\");
    663 END
    664 
    665     if ($isPodType) {
    666         push(@implContentDecls, <<END);
    667     V8SVGPODTypeWrapper<$implClassName>* imp_wrapper = V8SVGPODTypeWrapper<$implClassName>::toNative(info.Holder());
    668     $implClassName imp_instance = *imp_wrapper;
    669 END
    670         if ($getterStringUsesImp) {
    671             push(@implContentDecls, <<END);
    672     $implClassName* imp = &imp_instance;
    673 END
    674         }
    675 
    676     } elsif ($attrExt->{"v8OnProto"} || $attrExt->{"V8DisallowShadowing"}) {
    677       if ($interfaceName eq "DOMWindow") {
    678         push(@implContentDecls, <<END);
    679     v8::Handle<v8::Object> holder = info.Holder();
    680 END
    681       } else {
    682         # perform lookup first
    683         push(@implContentDecls, <<END);
    684     v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8${interfaceName}::GetTemplate(), info.This());
    685     if (holder.IsEmpty()) return v8::Handle<v8::Value>();
    686 END
    687       }
    688     push(@implContentDecls, <<END);
    689     ${implClassName}* imp = V8${implClassName}::toNative(holder);
    690 END
    691     } else {
    692         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
    693         if ($getterStringUsesImp && $reflect && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
    694             # Generate super-compact call for regular attribute getter:
    695             my $contentAttributeName = $reflect eq "1" ? $attrName : $reflect;
    696             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
    697             $implIncludes{"${namespace}.h"} = 1;
    698             push(@implContentDecls, "    return getElementStringAttr(info, ${namespace}::${contentAttributeName}Attr);\n");
    699             push(@implContentDecls, "  }\n\n");
    700             return;
    701             # Skip the rest of the function!
    702         }
    703         push(@implContentDecls, <<END);
    704     ${implClassName}* imp = V8${implClassName}::toNative(info.Holder());
    705 END
    706     }
    707 
    708     # Generate security checks if necessary
    709     if ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) {
    710         push(@implContentDecls, "    if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->$attrName())) return v8::Handle<v8::Value>();\n\n");
    711     } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) {
    712         push(@implContentDecls, "    if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->contentDocument())) return v8::Handle<v8::Value>();\n\n");
    713     }
    714 
    715     my $useExceptions = 1 if @{$attribute->getterExceptions} and !($isPodType);
    716     if ($useExceptions) {
    717         $implIncludes{"ExceptionCode.h"} = 1;
    718         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
    719     }
    720 
    721     if ($attribute->signature->extendedAttributes->{"v8referenceattr"}) {
    722         $attrName = $attribute->signature->extendedAttributes->{"v8referenceattr"};
    723     }
    724 
    725     my $getterFunc = $codeGenerator->WK_lcfirst($attrName);
    726 
    727     if ($codeGenerator->IsSVGAnimatedType($attribute->signature->type)) {
    728         # Some SVGFE*Element.idl use 'operator' as attribute name; rewrite as '_operator' to avoid clashes with C/C++
    729         $getterFunc = "_" . $getterFunc if ($attrName =~ /operator/);
    730         $getterFunc .= "Animated";
    731     }
    732 
    733     my $returnType = GetTypeFromSignature($attribute->signature);
    734 
    735     my $getterString;
    736     if ($getterStringUsesImp) {
    737         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
    738         my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
    739         if ($reflect || $reflectURL) {
    740             my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL);
    741             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
    742             $implIncludes{"${namespace}.h"} = 1;
    743             my $getAttributeFunctionName = $reflectURL ? "getURLAttribute" : "getAttribute";
    744             $getterString = "imp->$getAttributeFunctionName(${namespace}::${contentAttributeName}Attr";
    745         } else {
    746             $getterString = "imp->$getterFunc(";
    747         }
    748         $getterString .= "ec" if $useExceptions;
    749         $getterString .= ")";
    750         if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) {
    751             $getterString .= ".toInt()";
    752         }
    753     } else {
    754         $getterString = "imp_instance";
    755     }
    756 
    757     my $result;
    758     my $wrapper;
    759 
    760     if ($attrIsPodType) {
    761         $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
    762 
    763         my $getter = $getterString;
    764         $getter =~ s/imp->//;
    765         $getter =~ s/\(\)//;
    766         my $setter = "set" . $codeGenerator->WK_ucfirst($getter);
    767 
    768         my $implClassIsAnimatedType = $codeGenerator->IsSVGAnimatedType($implClassName);
    769         if (not $implClassIsAnimatedType and $codeGenerator->IsPodTypeWithWriteableProperties($attrType) and not defined $attribute->signature->extendedAttributes->{"Immutable"}) {
    770             if (IsPodType($implClassName)) {
    771                 my $wrapper = "V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($getterString, imp_wrapper)";
    772                 push(@implContentDecls, "    RefPtr<V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName> > wrapper = $wrapper;\n");
    773             } else {
    774                 my $wrapper = "V8SVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName>::create(imp, &${implClassName}::$getter, &${implClassName}::$setter)";
    775                 push(@implContentDecls, "    RefPtr<V8SVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName> > wrapper = $wrapper;\n");
    776             }
    777         } else {
    778             if ($implClassIsAnimatedType) {
    779                 # We can't hash member function pointers, so instead generate
    780                 # some hashing material based on the names of the methods.
    781                 my $hashhex = substr(Digest::MD5::md5_hex("${implClassName}::$getter ${implClassName}::$setter)"), 0, 8);
    782                 my $wrapper = "V8SVGDynamicPODTypeWrapperCache<$nativeType, $implClassName>::lookupOrCreateWrapper(imp, &${implClassName}::$getter, &${implClassName}::$setter, 0x$hashhex)";
    783                 push(@implContentDecls, "    RefPtr<V8SVGPODTypeWrapper<" . $nativeType . "> > wrapper = $wrapper;\n");
    784             } else {
    785                 my $wrapper = GenerateSVGStaticPodTypeWrapper($returnType, $getterString);
    786                 push(@implContentDecls, "    RefPtr<V8SVGStaticPODTypeWrapper<" . $nativeType . "> > wrapper = $wrapper;\n");
    787             }
    788         }
    789 
    790     } else {
    791         if ($attribute->signature->type eq "EventListener" && $dataNode->name eq "DOMWindow") {
    792             push(@implContentDecls, "    if (!imp->document())\n");
    793             push(@implContentDecls, "      return v8::Handle<v8::Value>();\n");
    794         }
    795 
    796         if ($useExceptions) {
    797             push(@implContentDecls, "    $nativeType v = ");
    798             push(@implContentDecls, "$getterString;\n");
    799             push(@implContentDecls, GenerateSetDOMException("    "));
    800             $result = "v";
    801             $result .= ".release()" if (IsRefPtrType($returnType));
    802         } else {
    803             # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
    804             $result = $getterString;
    805         }
    806     }
    807 
    808     if (IsSVGTypeNeedingContextParameter($attrType) && !$skipContext) {
    809         if ($attrIsPodType) {
    810             push(@implContentDecls, GenerateSVGContextAssignment($implClassName, "wrapper.get()", "    "));
    811         } else {
    812             push(@implContentDecls, GenerateSVGContextRetrieval($implClassName, "    "));
    813             # The templating associated with passing withSVGContext()'s return value directly into toV8 can get compilers confused,
    814             # so just manually set the return value to a PassRefPtr of the expected type.
    815             push(@implContentDecls, "    PassRefPtr<$attrType> resultAsPassRefPtr = V8Proxy::withSVGContext($result, context);\n");
    816             $result = "resultAsPassRefPtr";
    817         }
    818     }
    819 
    820     if ($attrIsPodType) {
    821         $implIncludes{"V8${attrType}.h"} = 1;
    822         push(@implContentDecls, "    return toV8(wrapper.release().get());\n");
    823     } else {
    824         push(@implContentDecls, "    " . ReturnNativeToJSValue($attribute->signature, $result, "    ").";\n");
    825     }
    826 
    827     push(@implContentDecls, "  }\n\n");  # end of getter
    828 }
    829 
    830 
    831 sub GenerateReplaceableAttrSetter
    832 {
    833     my $implClassName = shift;
    834 
    835     push(@implContentDecls,
    836        "  static void ${attrName}AttrSetter(v8::Local<v8::String> name," .
    837        " v8::Local<v8::Value> value, const v8::AccessorInfo& info) {\n");
    838 
    839     push(@implContentDecls, "    INC_STATS(\"DOM.$implClassName.$attrName._set\");\n");
    840 
    841     push(@implContentDecls, "    v8::Local<v8::String> ${attrName}_string = v8::String::New(\"${attrName}\");\n");
    842     push(@implContentDecls, "    info.Holder()->Delete(${attrName}_string);\n");
    843     push(@implContentDecls, "    info.This()->Set(${attrName}_string, value);\n");
    844     push(@implContentDecls, "  }\n\n");
    845 }
    846 
    847 
    848 sub GenerateNormalAttrSetter
    849 {
    850     my $attribute = shift;
    851     my $dataNode = shift;
    852     my $implClassName = shift;
    853     my $interfaceName = shift;
    854 
    855     my $attrExt = $attribute->signature->extendedAttributes;
    856 
    857     push(@implContentDecls,
    858        "  static void ${attrName}AttrSetter(v8::Local<v8::String> name," .
    859        " v8::Local<v8::Value> value, const v8::AccessorInfo& info) {\n");
    860 
    861     push(@implContentDecls, "    INC_STATS(\"DOM.$implClassName.$attrName._set\");\n");
    862 
    863     my $isPodType = IsPodType($implClassName);
    864 
    865     if ($isPodType) {
    866         $implClassName = GetNativeType($implClassName);
    867         $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
    868         push(@implContentDecls, "    V8SVGPODTypeWrapper<$implClassName>* wrapper = V8SVGPODTypeWrapper<$implClassName>::toNative(info.Holder());\n");
    869         push(@implContentDecls, "    $implClassName imp_instance = *wrapper;\n");
    870         push(@implContentDecls, "    $implClassName* imp = &imp_instance;\n");
    871 
    872     } elsif ($attrExt->{"v8OnProto"}) {
    873       if ($interfaceName eq "DOMWindow") {
    874         push(@implContentDecls, <<END);
    875     v8::Handle<v8::Object> holder = info.Holder();
    876 END
    877       } else {
    878         # perform lookup first
    879         push(@implContentDecls, <<END);
    880     v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8${interfaceName}::GetTemplate(), info.This());
    881     if (holder.IsEmpty()) return;
    882 END
    883       }
    884     push(@implContentDecls, <<END);
    885     ${implClassName}* imp = V8${implClassName}::toNative(holder);
    886 END
    887     } else {
    888         my $attrType = GetTypeFromSignature($attribute->signature);
    889         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
    890         my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
    891         if (($reflect || $reflectURL) && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
    892             # Generate super-compact call for regular attribute setter:
    893             my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL);
    894             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
    895             $implIncludes{"${namespace}.h"} = 1;
    896             push(@implContentDecls, "    setElementStringAttr(info, ${namespace}::${contentAttributeName}Attr, value);\n");
    897             push(@implContentDecls, "  }\n\n");
    898             return;
    899             # Skip the rest of the function!
    900         }
    901 
    902         push(@implContentDecls, <<END);
    903     ${implClassName}* imp = V8${implClassName}::toNative(info.Holder());
    904 END
    905     }
    906 
    907     my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0);
    908     if ($attribute->signature->type eq "EventListener") {
    909         if ($dataNode->name eq "DOMWindow") {
    910             push(@implContentDecls, "    if (!imp->document())\n");
    911             push(@implContentDecls, "      return;\n");
    912         }
    913     } else {
    914         push(@implContentDecls, "    $nativeType v = " . JSValueToNative($attribute->signature, "value") . ";\n");
    915     }
    916 
    917     my $result = "";
    918     if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) {
    919         $result .= "WebCore::String::number(";
    920     }
    921     $result .= "v";
    922     if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) {
    923         $result .= ")";
    924     }
    925     my $returnType = GetTypeFromSignature($attribute->signature);
    926     if (IsRefPtrType($returnType)) {
    927         $result = "WTF::getPtr(" . $result . ")";
    928     }
    929 
    930     my $useExceptions = 1 if @{$attribute->setterExceptions} and !($isPodType);
    931 
    932     if ($useExceptions) {
    933         $implIncludes{"ExceptionCode.h"} = 1;
    934         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
    935     }
    936 
    937     if ($implClassName eq "float") {
    938         push(@implContentDecls, "    *imp = $result;\n");
    939     } else {
    940         my $implSetterFunctionName = $codeGenerator->WK_ucfirst($attrName);
    941         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
    942         my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
    943         if ($reflect || $reflectURL) {
    944             my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL);
    945             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
    946             $implIncludes{"${namespace}.h"} = 1;
    947             push(@implContentDecls, "    imp->setAttribute(${namespace}::${contentAttributeName}Attr, $result");
    948         } elsif ($attribute->signature->type eq "EventListener") {
    949             $implIncludes{"V8AbstractEventListener.h"} = 1;
    950             push(@implContentDecls, "    transferHiddenDependency(info.Holder(), imp->$attrName(), value, V8${interfaceName}::cacheIndex);\n");
    951             push(@implContentDecls, "    imp->set$implSetterFunctionName(V8DOMWrapper::getEventListener(imp, value, true, ListenerFindOrCreate)");
    952         } else {
    953             push(@implContentDecls, "    imp->set$implSetterFunctionName($result");
    954         }
    955         push(@implContentDecls, ", ec") if $useExceptions;
    956         push(@implContentDecls, ");\n");
    957     }
    958 
    959     if ($useExceptions) {
    960         push(@implContentDecls, "    if (UNLIKELY(ec))\n");
    961         push(@implContentDecls, "        V8Proxy::setDOMException(ec);\n");
    962     }
    963 
    964     if ($isPodType) {
    965         push(@implContentDecls, "    wrapper->commitChange(*imp, V8Proxy::svgContext(wrapper));\n");
    966     } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
    967         $implIncludes{"SVGElement.h"} = 1;
    968 
    969         my $currentObject = "imp";
    970         if ($isPodType) {
    971             $currentObject = "wrapper";
    972         }
    973 
    974         push(@implContentDecls, "    if (SVGElement* context = V8Proxy::svgContext($currentObject)) {\n");
    975         push(@implContentDecls, "        context->svgAttributeChanged(imp->associatedAttributeName());\n");
    976         push(@implContentDecls, "    }\n");
    977     }
    978 
    979     push(@implContentDecls, "    return;\n");
    980     push(@implContentDecls, "  }\n\n");  # end of setter
    981 }
    982 
    983 sub GetFunctionTemplateCallbackName
    984 {
    985     $function = shift;
    986     $dataNode = shift;
    987 
    988     my $interfaceName = $dataNode->name;
    989     my $name = $function->signature->name;
    990 
    991     if ($function->signature->extendedAttributes->{"Custom"} ||
    992         $function->signature->extendedAttributes->{"V8Custom"}) {
    993         if ($function->signature->extendedAttributes->{"Custom"} &&
    994             $function->signature->extendedAttributes->{"V8Custom"}) {
    995             die "Custom and V8Custom should be mutually exclusive!"
    996         }
    997         return "V8${interfaceName}::${name}Callback";
    998     } else {
    999         return "${interfaceName}Internal::${name}Callback";
   1000     }
   1001 }
   1002 
   1003 sub GenerateNewFunctionTemplate
   1004 {
   1005     $function = shift;
   1006     $dataNode = shift;
   1007     $signature = shift;
   1008 
   1009     my $callback = GetFunctionTemplateCallbackName($function, $dataNode);
   1010     return "v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), $signature)";
   1011 }
   1012 
   1013 sub GenerateFunctionCallback
   1014 {
   1015     my $function = shift;
   1016     my $dataNode = shift;
   1017     my $classIndex = shift;
   1018     my $implClassName = shift;
   1019 
   1020     my $interfaceName = $dataNode->name;
   1021     my $name = $function->signature->name;
   1022 
   1023     push(@implContentDecls,
   1024 "  static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args) {\n" .
   1025 "    INC_STATS(\"DOM.$implClassName.$name\");\n");
   1026 
   1027     my $numParameters = @{$function->parameters};
   1028 
   1029     if ($function->signature->extendedAttributes->{"RequiresAllArguments"}) {
   1030         push(@implContentDecls,
   1031             "    if (args.Length() < $numParameters) return v8::Handle<v8::Value>();\n");
   1032     }
   1033 
   1034     if (IsPodType($implClassName)) {
   1035         my $nativeClassName = GetNativeType($implClassName);
   1036         push(@implContentDecls, "    V8SVGPODTypeWrapper<$nativeClassName>* imp_wrapper = V8SVGPODTypeWrapper<$nativeClassName>::toNative(args.Holder());\n");
   1037         push(@implContentDecls, "    $nativeClassName imp_instance = *imp_wrapper;\n");
   1038         push(@implContentDecls, "    $nativeClassName* imp = &imp_instance;\n");
   1039     } else {
   1040         push(@implContentDecls, <<END);
   1041     ${implClassName}* imp = V8${implClassName}::toNative(args.Holder());
   1042 END
   1043     }
   1044 
   1045   # Check domain security if needed
   1046     if (($dataNode->extendedAttributes->{"CheckDomainSecurity"}
   1047        || $interfaceName eq "DOMWindow")
   1048        && !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
   1049     # We have not find real use cases yet.
   1050     push(@implContentDecls,
   1051 "    if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) {\n".
   1052 "      return v8::Handle<v8::Value>();\n" .
   1053 "    }\n");
   1054     }
   1055 
   1056     my $raisesExceptions = @{$function->raisesExceptions};
   1057     if (!$raisesExceptions) {
   1058         foreach my $parameter (@{$function->parameters}) {
   1059             if (TypeCanFailConversion($parameter) or $parameter->extendedAttributes->{"IsIndex"}) {
   1060                 $raisesExceptions = 1;
   1061             }
   1062         }
   1063     }
   1064 
   1065     if ($raisesExceptions) {
   1066         $implIncludes{"ExceptionCode.h"} = 1;
   1067         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
   1068         push(@implContentDecls, "    {\n");
   1069         # The brace here is needed to prevent the ensuing 'goto fail's from jumping past constructors
   1070         # of objects (like Strings) declared later, causing compile errors. The block scope ends
   1071         # right before the label 'fail:'.
   1072     }
   1073 
   1074     if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
   1075         push(@implContentDecls,
   1076 "    OwnPtr<ScriptCallStack> callStack(ScriptCallStack::create(args, $numParameters));\n".
   1077 "    if (!callStack)\n".
   1078 "        return v8::Undefined();\n");
   1079         $implIncludes{"ScriptCallStack.h"} = 1;
   1080     }
   1081     if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) {
   1082         push(@implContentDecls,
   1083 "    if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->getSVGDocument(ec)))\n" .
   1084 "      return v8::Handle<v8::Value>();\n");
   1085     }
   1086 
   1087     my $paramIndex = 0;
   1088     foreach my $parameter (@{$function->parameters}) {
   1089         TranslateParameter($parameter);
   1090 
   1091         my $parameterName = $parameter->name;
   1092 
   1093         if ($parameter->extendedAttributes->{"Optional"}) {
   1094             # Generate early call if there are not enough parameters.
   1095             push(@implContentDecls, "    if (args.Length() <= $paramIndex) {\n");
   1096             my $functionCall = GenerateFunctionCallString($function, $paramIndex, "    " x 2, $implClassName);
   1097             push(@implContentDecls, $functionCall);
   1098             push(@implContentDecls, "    }\n");
   1099         }
   1100 
   1101         if (BasicTypeCanFailConversion($parameter)) {
   1102             push(@implContentDecls, "    bool ${parameterName}Ok;\n");
   1103         }
   1104 
   1105         push(@implContentDecls, "    " . GetNativeTypeFromSignature($parameter, $paramIndex) . " $parameterName = ");
   1106         push(@implContentDecls, JSValueToNative($parameter, "args[$paramIndex]",
   1107            BasicTypeCanFailConversion($parameter) ?  "${parameterName}Ok" : undef) . ";\n");
   1108 
   1109         if (TypeCanFailConversion($parameter)) {
   1110             $implIncludes{"ExceptionCode.h"} = 1;
   1111             push(@implContentDecls,
   1112 "    if (UNLIKELY(!$parameterName" . (BasicTypeCanFailConversion($parameter) ? "Ok" : "") . ")) {\n" .
   1113 "      ec = TYPE_MISMATCH_ERR;\n" .
   1114 "      goto fail;\n" .
   1115 "    }\n");
   1116         }
   1117 
   1118         if ($parameter->extendedAttributes->{"IsIndex"}) {
   1119             $implIncludes{"ExceptionCode.h"} = 1;
   1120             push(@implContentDecls,
   1121 "    if (UNLIKELY($parameterName < 0)) {\n" .
   1122 "      ec = INDEX_SIZE_ERR;\n" .
   1123 "      goto fail;\n" .
   1124 "    }\n");
   1125         }
   1126 
   1127         $paramIndex++;
   1128     }
   1129 
   1130     # Build the function call string.
   1131     my $callString = GenerateFunctionCallString($function, $paramIndex, "    ", $implClassName);
   1132     push(@implContentDecls, "$callString");
   1133 
   1134     if ($raisesExceptions) {
   1135         push(@implContentDecls, "    }\n");
   1136         push(@implContentDecls, "  fail:\n");
   1137         push(@implContentDecls, "    V8Proxy::setDOMException(ec);\n");
   1138         push(@implContentDecls, "    return v8::Handle<v8::Value>();\n");
   1139     }
   1140 
   1141     push(@implContentDecls, "  }\n\n");
   1142 }
   1143 
   1144 sub GenerateBatchedAttributeData
   1145 {
   1146     my $dataNode = shift;
   1147     my $interfaceName = $dataNode->name;
   1148     my $attributes = shift;
   1149 
   1150     foreach my $attribute (@$attributes) {
   1151         my $conditionalString = GenerateConditionalString($attribute->signature);
   1152         push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
   1153         GenerateSingleBatchedAttribute($interfaceName, $attribute, ",", "");
   1154         push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
   1155     }
   1156 }
   1157 
   1158 sub GenerateSingleBatchedAttribute
   1159 {
   1160     my $interfaceName = shift;
   1161     my $attribute = shift;
   1162     my $delimiter = shift;
   1163     my $indent = shift;
   1164     my $attrName = $attribute->signature->name;
   1165     my $attrExt = $attribute->signature->extendedAttributes;
   1166 
   1167     my $accessControl = "v8::DEFAULT";
   1168     if ($attrExt->{"DoNotCheckDomainSecurityOnGet"}) {
   1169         $accessControl = "v8::ALL_CAN_READ";
   1170     } elsif ($attrExt->{"DoNotCheckDomainSecurityOnSet"}) {
   1171         $accessControl = "v8::ALL_CAN_WRITE";
   1172     } elsif ($attrExt->{"DoNotCheckDomainSecurity"}) {
   1173         $accessControl = "v8::ALL_CAN_READ";
   1174         if (!($attribute->type =~ /^readonly/) && !($attrExt->{"V8ReadOnly"})) {
   1175             $accessControl .= "|v8::ALL_CAN_WRITE";
   1176         }
   1177     }
   1178     if ($attrExt->{"V8DisallowShadowing"}) {
   1179         $accessControl .= "|v8::PROHIBITS_OVERWRITING";
   1180     }
   1181     $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")";
   1182 
   1183     my $customAccessor =
   1184         $attrExt->{"Custom"} ||
   1185         $attrExt->{"CustomSetter"} ||
   1186         $attrExt->{"CustomGetter"} ||
   1187         $attrExt->{"V8Custom"} ||
   1188         $attrExt->{"V8CustomSetter"} ||
   1189         $attrExt->{"V8CustomGetter"} ||
   1190         "";
   1191     if ($customAccessor eq 1) {
   1192         # use the naming convension, interface + (capitalize) attr name
   1193         $customAccessor = $interfaceName . "::" . $attrName;
   1194     }
   1195 
   1196     my $getter;
   1197     my $setter;
   1198     my $propAttr = "v8::None";
   1199     my $hasCustomSetter = 0;
   1200 
   1201     # Check attributes.
   1202     if ($attrExt->{"DontEnum"}) {
   1203         $propAttr .= "|v8::DontEnum";
   1204     }
   1205     if ($attrExt->{"V8DisallowShadowing"}) {
   1206         $propAttr .= "|v8::DontDelete";
   1207     }
   1208 
   1209     my $on_proto = "0 /* on instance */";
   1210     my $data = "V8ClassIndex::INVALID_CLASS_INDEX /* no data */";
   1211 
   1212     # Constructor
   1213     if ($attribute->signature->type =~ /Constructor$/) {
   1214         my $constructorType = $codeGenerator->StripModule($attribute->signature->type);
   1215         $constructorType =~ s/Constructor$//;
   1216         my $constructorIndex = uc($constructorType);
   1217         if ($customAccessor) {
   1218             $getter = "V8${customAccessor}AccessorGetter";
   1219         } else {
   1220             $data = "V8ClassIndex::${constructorIndex}";
   1221             $getter = "${interfaceName}Internal::${interfaceName}ConstructorGetter";
   1222         }
   1223         $setter = "0";
   1224         $propAttr = "v8::ReadOnly";
   1225 
   1226     } else {
   1227         # Default Getter and Setter
   1228         $getter = "${interfaceName}Internal::${attrName}AttrGetter";
   1229         $setter = "${interfaceName}Internal::${attrName}AttrSetter";
   1230 
   1231         # Custom Setter
   1232         if ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
   1233             $hasCustomSetter = 1;
   1234             $setter = "V8${customAccessor}AccessorSetter";
   1235         }
   1236 
   1237         # Custom Getter
   1238         if ($attrExt->{"CustomGetter"} || $attrExt->{"V8CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
   1239             $getter = "V8${customAccessor}AccessorGetter";
   1240         }
   1241     }
   1242 
   1243     # Replaceable
   1244     if ($attrExt->{"Replaceable"} && !$hasCustomSetter) {
   1245         $setter = "0";
   1246         # Handle the special case of window.top being marked as Replaceable.
   1247         # FIXME: Investigate whether we could treat window.top as replaceable
   1248         # and allow shadowing without it being a security hole.
   1249         if (!($interfaceName eq "DOMWindow" and $attrName eq "top")) {
   1250             $propAttr .= "|v8::ReadOnly";
   1251         }
   1252     }
   1253 
   1254     # Read only attributes
   1255     if ($attribute->type =~ /^readonly/ || $attrExt->{"V8ReadOnly"}) {
   1256         $setter = "0";
   1257     }
   1258 
   1259     # An accessor can be installed on the proto
   1260     if ($attrExt->{"v8OnProto"}) {
   1261         $on_proto = "1 /* on proto */";
   1262     }
   1263 
   1264     my $commentInfo = "Attribute '$attrName' (Type: '" . $attribute->type .
   1265                       "' ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
   1266 
   1267     push(@implContent, $indent . "    {\n");
   1268     push(@implContent, $indent . "        \/\/ $commentInfo\n");
   1269     push(@implContent, $indent . "        \"$attrName\",\n");
   1270     push(@implContent, $indent . "        $getter,\n");
   1271     push(@implContent, $indent . "        $setter,\n");
   1272     push(@implContent, $indent . "        $data,\n");
   1273     push(@implContent, $indent . "        $accessControl,\n");
   1274     push(@implContent, $indent . "        static_cast<v8::PropertyAttribute>($propAttr),\n");
   1275     push(@implContent, $indent . "        $on_proto\n");
   1276     push(@implContent, $indent . "    }" . $delimiter . "\n");
   1277 END
   1278 }
   1279 
   1280 sub GenerateImplementationIndexer
   1281 {
   1282     my $dataNode = shift;
   1283     my $indexer = shift;
   1284     my $interfaceName = $dataNode->name;
   1285 
   1286     # FIXME: Figure out what HasNumericIndexGetter is really supposed to do. Right now, it's only set on WebGL-related files.
   1287     my $hasCustomSetter = $dataNode->extendedAttributes->{"HasCustomIndexSetter"} && !$dataNode->extendedAttributes->{"HasNumericIndexGetter"};
   1288     my $hasGetter = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
   1289 
   1290     # FIXME: Find a way to not have to special-case HTMLOptionsCollection.
   1291     if ($interfaceName eq "HTMLOptionsCollection") {
   1292         $hasGetter = 1;
   1293     }
   1294     # FIXME: If the parent interface of $dataNode already has
   1295     # HasIndexGetter, we don't need to handle the getter here.
   1296     if ($interfaceName eq "WebKitCSSTransformValue") {
   1297         $hasGetter = 0;
   1298     }
   1299 
   1300     # FIXME: Investigate and remove this nastinesss. In V8, named property handling and indexer handling are apparently decoupled,
   1301     # which means that object[X] where X is a number doesn't reach named property indexer. So we need to provide
   1302     # simplistic, mirrored indexer handling in addition to named property handling.
   1303     my $isSpecialCase = exists $indexerSpecialCases{$interfaceName};
   1304     if ($isSpecialCase) {
   1305         $hasGetter = 1;
   1306         if ($dataNode->extendedAttributes->{"DelegatingPutFunction"}) {
   1307             $hasCustomSetter = 1;
   1308         }
   1309     }
   1310 
   1311     if (!$hasGetter) {
   1312         return;
   1313     }
   1314 
   1315     $implIncludes{"V8Collection.h"} = 1;
   1316 
   1317     my $indexerType = $indexer ? $indexer->type : 0;
   1318 
   1319     # FIXME: Remove this once toV8 helper methods are implemented (see https://bugs.webkit.org/show_bug.cgi?id=32563).
   1320     if ($interfaceName eq "WebKitCSSKeyframesRule") {
   1321         $indexerType = "WebKitCSSKeyframeRule";
   1322     }
   1323 
   1324     if ($indexerType && !$hasCustomSetter) {
   1325         if ($indexerType eq "DOMString") {
   1326             my $conversion = $indexer->extendedAttributes->{"ConvertNullStringTo"};
   1327             if ($conversion && $conversion eq "Null") {
   1328                 push(@implContent, <<END);
   1329   setCollectionStringOrNullIndexedGetter<${interfaceName}>(desc);
   1330 END
   1331             } else {
   1332                 push(@implContent, <<END);
   1333   setCollectionStringIndexedGetter<${interfaceName}>(desc);
   1334 END
   1335             }
   1336         } else {
   1337             my $indexerClassIndex = uc($indexerType);
   1338             push(@implContent, <<END);
   1339   setCollectionIndexedGetter<${interfaceName}, ${indexerType}>(desc, V8ClassIndex::${indexerClassIndex});
   1340 END
   1341             # Include the header for this indexer type, because setCollectionIndexedGetter() requires toV8() for this type.
   1342             $implIncludes{"V8${indexerType}.h"} = 1;
   1343         }
   1344 
   1345         return;
   1346     }
   1347 
   1348     my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
   1349     my $hasEnumerator = !$isSpecialCase && IsNodeSubType($dataNode);
   1350     my $setOn = "Instance";
   1351 
   1352     # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
   1353     # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
   1354     # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
   1355     # on the object.
   1356     if ($interfaceName eq "DOMWindow") {
   1357         $setOn = "Prototype";
   1358         $hasDeleter = 0;
   1359     }
   1360 
   1361     push(@implContent, "  desc->${setOn}Template()->SetIndexedPropertyHandler(V8${interfaceName}::indexedPropertyGetter");
   1362     push(@implContent, $hasCustomSetter ? ", V8${interfaceName}::indexedPropertySetter" : ", 0");
   1363     push(@implContent, ", 0"); # IndexedPropertyQuery -- not being used at the moment.
   1364     push(@implContent, $hasDeleter ? ", V8${interfaceName}::indexedPropertyDeleter" : ", 0");
   1365     push(@implContent, ", nodeCollectionIndexedPropertyEnumerator<${interfaceName}>, v8::Integer::New(V8ClassIndex::NODE)") if $hasEnumerator;
   1366     push(@implContent, ");\n");
   1367 }
   1368 
   1369 sub GenerateImplementationNamedPropertyGetter
   1370 {
   1371     my $dataNode = shift;
   1372     my $namedPropertyGetter = shift;
   1373     my $interfaceName = $dataNode->name;
   1374     my $hasCustomGetter = $dataNode->extendedAttributes->{"HasOverridingNameGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
   1375 
   1376     # FIXME: Remove hard-coded HTMLOptionsCollection reference by changing HTMLOptionsCollection to not inherit
   1377     # from HTMLCollection per W3C spec (http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/html.html#HTMLOptionsCollection).
   1378     if ($interfaceName eq "HTMLOptionsCollection") {
   1379         $interfaceName = "HTMLCollection";
   1380         $hasCustomGetter = 1;
   1381     }
   1382 
   1383     my $hasGetter = $dataNode->extendedAttributes->{"HasNameGetter"} || $hasCustomGetter || $namedPropertyGetter;
   1384     if (!$hasGetter) {
   1385         return;
   1386     }
   1387 
   1388     if ($namedPropertyGetter && $namedPropertyGetter->type ne "Node" && !$namedPropertyGetter->extendedAttributes->{"Custom"} && !$hasCustomGetter) {
   1389         $implIncludes{"V8Collection.h"} = 1;
   1390         my $type = $namedPropertyGetter->type;
   1391         my $classIndex = uc($type);
   1392         push(@implContent, <<END);
   1393   setCollectionNamedGetter<${interfaceName}, ${type}>(desc, V8ClassIndex::${classIndex});
   1394 END
   1395         return;
   1396     }
   1397 
   1398     my $hasSetter = $dataNode->extendedAttributes->{"DelegatingPutFunction"};
   1399     # FIXME: Try to remove hard-coded HTMLDocument reference by aligning handling of document.all with JSC bindings.
   1400     my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"} || $interfaceName eq "HTMLDocument";
   1401     my $hasEnumerator = $dataNode->extendedAttributes->{"CustomGetPropertyNames"};
   1402     my $setOn = "Instance";
   1403 
   1404     # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
   1405     # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
   1406     # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
   1407     # on the object.
   1408     if ($interfaceName eq "DOMWindow") {
   1409         $setOn = "Prototype";
   1410         $hasDeleter = 0;
   1411         $hasEnumerator = 0;
   1412     }
   1413 
   1414     push(@implContent, "  desc->${setOn}Template()->SetNamedPropertyHandler(V8${interfaceName}::namedPropertyGetter, ");
   1415     push(@implContent, $hasSetter ? "V8${interfaceName}::namedPropertySetter, " : "0, ");
   1416     push(@implContent, "0, "); # NamedPropertyQuery -- not being used at the moment.
   1417     push(@implContent, $hasDeleter ? "V8${interfaceName}::namedPropertyDeleter, " : "0, ");
   1418     push(@implContent, $hasEnumerator ? "V8${interfaceName}::namedPropertyEnumerator" : "0");
   1419     push(@implContent, ");\n");
   1420 }
   1421 
   1422 sub GenerateImplementationCustomCall
   1423 {
   1424     my $dataNode = shift;
   1425     my $interfaceName = $dataNode->name;
   1426     my $hasCustomCall = $dataNode->extendedAttributes->{"CustomCall"};
   1427 
   1428     # FIXME: Remove hard-coded HTMLOptionsCollection reference.
   1429     if ($interfaceName eq "HTMLOptionsCollection") {
   1430         $interfaceName = "HTMLCollection";
   1431         $hasCustomCall = 1;
   1432     }
   1433 
   1434     if ($hasCustomCall) {
   1435         push(@implContent, "  desc->InstanceTemplate()->SetCallAsFunctionHandler(V8${interfaceName}::callAsFunctionCallback);\n");
   1436     }
   1437 }
   1438 
   1439 sub GenerateImplementationMasqueradesAsUndefined
   1440 {
   1441     my $dataNode = shift;
   1442     if ($dataNode->extendedAttributes->{"MasqueradesAsUndefined"})
   1443     {
   1444         push(@implContent, "  desc->InstanceTemplate()->MarkAsUndetectable();\n");
   1445     }
   1446 }
   1447 
   1448 sub GenerateImplementation
   1449 {
   1450     my $object = shift;
   1451     my $dataNode = shift;
   1452     my $interfaceName = $dataNode->name;
   1453     my $className = "V8$interfaceName";
   1454     my $implClassName = $interfaceName;
   1455     my $classIndex = uc($codeGenerator->StripModule($interfaceName));
   1456 
   1457     my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
   1458     my $conditionalString = GenerateConditionalString($dataNode);
   1459 
   1460     # - Add default header template
   1461     @implContentHeader = split("\r", $headerTemplate);
   1462 
   1463     push(@implFixedHeader,
   1464          "#include \"config.h\"\n" .
   1465          "#include \"RuntimeEnabledFeatures.h\"\n" .
   1466          "#include \"V8Proxy.h\"\n" .
   1467          "#include \"V8Binding.h\"\n" .
   1468          "#include \"V8BindingState.h\"\n" .
   1469          "#include \"V8DOMWrapper.h\"\n" .
   1470          "#include \"V8IsolatedContext.h\"\n\n" .
   1471          "#undef LOG\n\n");
   1472 
   1473     push(@implFixedHeader, "\n#if ${conditionalString}\n\n") if $conditionalString;
   1474 
   1475     if ($className =~ /^V8SVGAnimated/) {
   1476         AddIncludesForSVGAnimatedType($interfaceName);
   1477     }
   1478 
   1479     $implIncludes{"${className}.h"} = 1;
   1480 
   1481     AddIncludesForType($interfaceName);
   1482 
   1483     push(@implContentDecls, "namespace WebCore {\n");
   1484     push(@implContentDecls, "namespace ${interfaceName}Internal {\n\n");
   1485     push(@implContentDecls, "template <typename T> void V8_USE(T) { }\n\n");
   1486 
   1487     my $hasConstructors = 0;
   1488     # Generate property accessors for attributes.
   1489     for ($index = 0; $index < @{$dataNode->attributes}; $index++) {
   1490         $attribute = @{$dataNode->attributes}[$index];
   1491         $attrName = $attribute->signature->name;
   1492         $attrType = $attribute->signature->type;
   1493 
   1494         # Generate special code for the constructor attributes.
   1495         if ($attrType =~ /Constructor$/) {
   1496             if (!($attribute->signature->extendedAttributes->{"CustomGetter"} ||
   1497                 $attribute->signature->extendedAttributes->{"V8CustomGetter"})) {
   1498                 $hasConstructors = 1;
   1499             }
   1500             next;
   1501         }
   1502 
   1503         if ($attrType eq "EventListener" && $interfaceName eq "DOMWindow") {
   1504             $attribute->signature->extendedAttributes->{"v8OnProto"} = 1;
   1505         }
   1506 
   1507         # Do not generate accessor if this is a custom attribute.  The
   1508         # call will be forwarded to a hand-written accessor
   1509         # implementation.
   1510         if ($attribute->signature->extendedAttributes->{"Custom"} ||
   1511             $attribute->signature->extendedAttributes->{"V8Custom"}) {
   1512             next;
   1513         }
   1514 
   1515         # Generate the accessor.
   1516         if (!($attribute->signature->extendedAttributes->{"CustomGetter"} ||
   1517             $attribute->signature->extendedAttributes->{"V8CustomGetter"})) {
   1518             GenerateNormalAttrGetter($attribute, $dataNode, $implClassName, $interfaceName);
   1519         }
   1520         if (!($attribute->signature->extendedAttributes->{"CustomSetter"} ||
   1521             $attribute->signature->extendedAttributes->{"V8CustomSetter"})) {
   1522             if ($attribute->signature->extendedAttributes->{"Replaceable"}) {
   1523                 $dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"} || die "Replaceable attribute can only be used in interface that defines ExtendsDOMGlobalObject attribute!";
   1524                 # GenerateReplaceableAttrSetter($implClassName);
   1525             } elsif ($attribute->type !~ /^readonly/ && !$attribute->signature->extendedAttributes->{"V8ReadOnly"}) {
   1526                 GenerateNormalAttrSetter($attribute, $dataNode, $implClassName, $interfaceName);
   1527             }
   1528         }
   1529     }
   1530 
   1531     if ($hasConstructors) {
   1532         GenerateConstructorGetter($implClassName, $classIndex);
   1533     }
   1534 
   1535     my $indexer;
   1536     my $namedPropertyGetter;
   1537     # Generate methods for functions.
   1538     foreach my $function (@{$dataNode->functions}) {
   1539         # hack for addEventListener/RemoveEventListener
   1540         # FIXME: avoid naming conflict
   1541         if (!($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"V8Custom"})) {
   1542             GenerateFunctionCallback($function, $dataNode, $classIndex, $implClassName);
   1543         }
   1544 
   1545         if ($function->signature->name eq "item") {
   1546             $indexer = $function->signature;
   1547         }
   1548 
   1549         if ($function->signature->name eq "namedItem") {
   1550             $namedPropertyGetter = $function->signature;
   1551         }
   1552 
   1553         # If the function does not need domain security check, we need to
   1554         # generate an access getter that returns different function objects
   1555         # for different calling context.
   1556         if (($dataNode->extendedAttributes->{"CheckDomainSecurity"} || ($interfaceName eq "DOMWindow")) && $function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
   1557             GenerateDomainSafeFunctionGetter($function, $dataNode, $implClassName);
   1558         }
   1559     }
   1560 
   1561     # Attributes
   1562     my $attributes = $dataNode->attributes;
   1563 
   1564     # For the DOMWindow interface we partition the attributes into the
   1565     # ones that disallows shadowing and the rest.
   1566     my @disallowsShadowing;
   1567     # Also separate out attributes that are enabled at runtime so we can process them specially.
   1568     my @enabledAtRuntime;
   1569     my @normal;
   1570     foreach my $attribute (@$attributes) {
   1571 
   1572         if ($interfaceName eq "DOMWindow" && $attribute->signature->extendedAttributes->{"V8DisallowShadowing"}) {
   1573             push(@disallowsShadowing, $attribute);
   1574         } elsif ($attribute->signature->extendedAttributes->{"EnabledAtRuntime"}) {
   1575             push(@enabledAtRuntime, $attribute);
   1576         } else {
   1577             push(@normal, $attribute);
   1578         }
   1579     }
   1580     $attributes = \@normal;
   1581     # Put the attributes that disallow shadowing on the shadow object.
   1582     if (@disallowsShadowing) {
   1583         push(@implContent, "static const BatchedAttribute shadow_attrs[] = {\n");
   1584         GenerateBatchedAttributeData($dataNode, \@disallowsShadowing);
   1585         push(@implContent, "};\n");
   1586     }
   1587 
   1588     my $has_attributes = 0;
   1589     if (@$attributes) {
   1590         $has_attributes = 1;
   1591         push(@implContent, "static const BatchedAttribute ${interfaceName}_attrs[] = {\n");
   1592         GenerateBatchedAttributeData($dataNode, $attributes);
   1593         push(@implContent, "};\n");
   1594     }
   1595 
   1596     # Setup table of standard callback functions
   1597     $num_callbacks = 0;
   1598     $has_callbacks = 0;
   1599     foreach my $function (@{$dataNode->functions}) {
   1600         my $attrExt = $function->signature->extendedAttributes;
   1601         # Don't put any nonstandard functions into this table:
   1602         if ($attrExt->{"V8OnInstance"}) {
   1603             next;
   1604         }
   1605         if ($attrExt->{"EnabledAtRuntime"} || RequiresCustomSignature($function) || $attrExt->{"V8DoNotCheckSignature"}) {
   1606             next;
   1607         }
   1608         if ($attrExt->{"DoNotCheckDomainSecurity"} &&
   1609             ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) {
   1610             next;
   1611         }
   1612         if ($attrExt->{"DontEnum"} || $attrExt->{"V8ReadOnly"}) {
   1613             next;
   1614         }
   1615         if (!$has_callbacks) {
   1616             $has_callbacks = 1;
   1617             push(@implContent, "static const BatchedCallback ${interfaceName}_callbacks[] = {\n");
   1618         }
   1619         my $name = $function->signature->name;
   1620         my $callback = GetFunctionTemplateCallbackName($function, $dataNode);
   1621         push(@implContent, <<END);
   1622   {"$name", $callback},
   1623 END
   1624         $num_callbacks++;
   1625     }
   1626     push(@implContent, "};\n")  if $has_callbacks;
   1627 
   1628     # Setup constants
   1629     my $has_constants = 0;
   1630     if (@{$dataNode->constants}) {
   1631         $has_constants = 1;
   1632         push(@implContent, "static const BatchedConstant ${interfaceName}_consts[] = {\n");
   1633     }
   1634     foreach my $constant (@{$dataNode->constants}) {
   1635         my $name = $constant->name;
   1636         my $value = $constant->value;
   1637         # FIXME: we need the static_cast here only because of one constant, NodeFilter.idl
   1638         # defines "const unsigned long SHOW_ALL = 0xFFFFFFFF".  It would be better if we
   1639         # handled this here, and converted it to a -1 constant in the c++ output.
   1640         push(@implContent, <<END);
   1641   { "${name}", static_cast<signed int>($value) },
   1642 END
   1643     }
   1644     if ($has_constants) {
   1645         push(@implContent, "};\n");
   1646     }
   1647 
   1648     push(@implContentDecls, "} // namespace ${interfaceName}Internal\n\n");
   1649 
   1650     # In namespace WebCore, add generated implementation for 'CanBeConstructed'.
   1651     if ($dataNode->extendedAttributes->{"CanBeConstructed"} && !$dataNode->extendedAttributes->{"CustomConstructor"}) {
   1652         push(@implContent, <<END);
   1653  v8::Handle<v8::Value> ${className}::constructorCallback(const v8::Arguments& args)
   1654   {
   1655     INC_STATS("DOM.${interfaceName}.Contructor");
   1656     return V8Proxy::constructDOMObject<V8ClassIndex::${classIndex}, $interfaceName>(args);
   1657   }
   1658 END
   1659    }
   1660 
   1661     my $access_check = "";
   1662     if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !($interfaceName eq "DOMWindow")) {
   1663         $access_check = "instance->SetAccessCheckCallbacks(V8${interfaceName}::namedSecurityCheck, V8${interfaceName}::indexedSecurityCheck, v8::Integer::New(V8ClassIndex::ToInt(V8ClassIndex::${classIndex})));";
   1664     }
   1665 
   1666     # For the DOMWindow interface, generate the shadow object template
   1667     # configuration method.
   1668     if ($implClassName eq "DOMWindow") {
   1669         push(@implContent, <<END);
   1670 static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Persistent<v8::ObjectTemplate> templ) {
   1671   batchConfigureAttributes(templ,
   1672                            v8::Handle<v8::ObjectTemplate>(),
   1673                            shadow_attrs,
   1674                            sizeof(shadow_attrs)/sizeof(*shadow_attrs));
   1675 
   1676   // Install a security handler with V8.
   1677   templ->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::Integer::New(V8ClassIndex::DOMWINDOW));
   1678   templ->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
   1679   return templ;
   1680 }
   1681 END
   1682     }
   1683 
   1684     # find the super descriptor
   1685     my $parentClassTemplate = "";
   1686     foreach (@{$dataNode->parents}) {
   1687         my $parent = $codeGenerator->StripModule($_);
   1688         if ($parent eq "EventTarget") { next; }
   1689         $implIncludes{"V8${parent}.h"} = 1;
   1690         $parentClassTemplate = "V8" . $parent . "::GetTemplate()";
   1691         last;
   1692     }
   1693     if (!$parentClassTemplate) {
   1694         $parentClassTemplate = "v8::Persistent<v8::FunctionTemplate>()";
   1695     }
   1696 
   1697     # Generate the template configuration method
   1698     push(@implContent,  <<END);
   1699 static v8::Persistent<v8::FunctionTemplate> Configure${className}Template(v8::Persistent<v8::FunctionTemplate> desc) {
   1700   v8::Local<v8::Signature> default_signature = configureTemplate(desc, \"${interfaceName}\",
   1701       $parentClassTemplate, V8${interfaceName}::internalFieldCount,
   1702 END
   1703     # Set up our attributes if we have them
   1704     if ($has_attributes) {
   1705         push(@implContent, <<END);
   1706       ${interfaceName}_attrs, sizeof(${interfaceName}_attrs)/sizeof(*${interfaceName}_attrs),
   1707 END
   1708     } else {
   1709         push(@implContent, <<END);
   1710       NULL, 0,
   1711 END
   1712     }
   1713 
   1714     if ($has_callbacks) {
   1715         push(@implContent, <<END);
   1716       ${interfaceName}_callbacks, sizeof(${interfaceName}_callbacks)/sizeof(*${interfaceName}_callbacks));
   1717 END
   1718     } else {
   1719         push(@implContent, <<END);
   1720       NULL, 0);
   1721 END
   1722     }
   1723 
   1724     if ($dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"CanBeConstructed"}) {
   1725         push(@implContent, <<END);
   1726       desc->SetCallHandler(V8${interfaceName}::constructorCallback);
   1727 END
   1728     }
   1729 
   1730     if ($access_check or @enabledAtRuntime or @{$dataNode->functions} or $has_constants) {
   1731         push(@implContent,  <<END);
   1732   v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate();
   1733   v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate();
   1734 END
   1735     }
   1736 
   1737     push(@implContent,  "  $access_check\n");
   1738 
   1739     # Setup the enable-at-runtime attrs if we have them
   1740     foreach my $runtime_attr (@enabledAtRuntime) {
   1741         # A function named RuntimeEnabledFeatures::{methodName}Enabled() need to be written by hand.
   1742         $enable_function = "RuntimeEnabledFeatures::" . $codeGenerator->WK_lcfirst($runtime_attr->signature->name) . "Enabled";
   1743         my $conditionalString = GenerateConditionalString($runtime_attr->signature);
   1744         push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
   1745         push(@implContent, "    if (${enable_function}()) {\n");
   1746         push(@implContent, "        static const BatchedAttribute attrData =\\\n");
   1747         GenerateSingleBatchedAttribute($interfaceName, $runtime_attr, ";", "    ");
   1748         push(@implContent, <<END);
   1749         configureAttribute(instance, proto, attrData);
   1750     }
   1751 END
   1752         push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
   1753     }
   1754 
   1755     GenerateImplementationIndexer($dataNode, $indexer);
   1756     GenerateImplementationNamedPropertyGetter($dataNode, $namedPropertyGetter);
   1757     GenerateImplementationCustomCall($dataNode);
   1758     GenerateImplementationMasqueradesAsUndefined($dataNode);
   1759 
   1760     # Define our functions with Set() or SetAccessor()
   1761     $total_functions = 0;
   1762     foreach my $function (@{$dataNode->functions}) {
   1763         $total_functions++;
   1764         my $attrExt = $function->signature->extendedAttributes;
   1765         my $name = $function->signature->name;
   1766 
   1767         my $property_attributes = "v8::DontDelete";
   1768         if ($attrExt->{"DontEnum"}) {
   1769             $property_attributes .= "|v8::DontEnum";
   1770         }
   1771         if ($attrExt->{"V8ReadOnly"}) {
   1772             $property_attributes .= "|v8::ReadOnly";
   1773         }
   1774 
   1775         my $commentInfo = "Function '$name' (ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
   1776 
   1777         my $template = "proto";
   1778         if ($attrExt->{"V8OnInstance"}) {
   1779             $template = "instance";
   1780         }
   1781 
   1782         my $conditional = "";
   1783         if ($attrExt->{"EnabledAtRuntime"}) {
   1784             # Only call Set()/SetAccessor() if this method should be enabled
   1785             $enable_function = "RuntimeEnabledFeatures::" . $codeGenerator->WK_lcfirst($function->signature->name) . "Enabled";
   1786             $conditional = "if (${enable_function}())\n";
   1787         }
   1788 
   1789         if ($attrExt->{"DoNotCheckDomainSecurity"} &&
   1790             ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) {
   1791             # Mark the accessor as ReadOnly and set it on the proto object so
   1792             # it can be shadowed. This is really a hack to make it work.
   1793             # There are several sceneria to call into the accessor:
   1794             #   1) from the same domain: "window.open":
   1795             #      the accessor finds the DOM wrapper in the proto chain;
   1796             #   2) from the same domain: "window.__proto__.open":
   1797             #      the accessor will NOT find a DOM wrapper in the prototype chain
   1798             #   3) from another domain: "window.open":
   1799             #      the access find the DOM wrapper in the prototype chain
   1800             #   "window.__proto__.open" from another domain will fail when
   1801             #   accessing '__proto__'
   1802             #
   1803             # The solution is very hacky and fragile, it really needs to be replaced
   1804             # by a better solution.
   1805             $property_attributes .= "|v8::ReadOnly";
   1806             push(@implContent, <<END);
   1807 
   1808   // $commentInfo
   1809   $conditional $template->SetAccessor(
   1810       v8::String::New("$name"),
   1811       ${interfaceName}Internal::${name}AttrGetter,
   1812       0,
   1813       v8::Handle<v8::Value>(),
   1814       v8::ALL_CAN_READ,
   1815       static_cast<v8::PropertyAttribute>($property_attributes));
   1816 END
   1817           $num_callbacks++;
   1818           next;
   1819       }
   1820 
   1821       my $signature = "default_signature";
   1822       if ($attrExt->{"V8DoNotCheckSignature"}){
   1823           $signature = "v8::Local<v8::Signature>()";
   1824       }
   1825 
   1826       if (RequiresCustomSignature($function)) {
   1827           $signature = "${name}_signature";
   1828           push(@implContent, "\n  // Custom Signature '$name'\n", CreateCustomSignature($function));
   1829       }
   1830 
   1831       # Normal function call is a template
   1832       my $callback = GetFunctionTemplateCallbackName($function, $dataNode);
   1833 
   1834       if ($property_attributes eq "v8::DontDelete") {
   1835           $property_attributes = "";
   1836       } else {
   1837           $property_attributes = ", static_cast<v8::PropertyAttribute>($property_attributes)";
   1838       }
   1839 
   1840       if ($template eq "proto" && $conditional eq "" && $signature eq "default_signature" && $property_attributes eq "") {
   1841           # Standard type of callback, already created in the batch, so skip it here.
   1842           next;
   1843       }
   1844 
   1845       push(@implContent, <<END);
   1846   ${conditional}$template->Set(v8::String::New("$name"), v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), ${signature})$property_attributes);
   1847 END
   1848       $num_callbacks++;
   1849     }
   1850 
   1851     die "Wrong number of callbacks generated for $interfaceName ($num_callbacks, should be $total_functions)" if $num_callbacks != $total_functions;
   1852 
   1853     if ($has_constants) {
   1854         push(@implContent, <<END);
   1855   batchConfigureConstants(desc, proto, ${interfaceName}_consts, sizeof(${interfaceName}_consts)/sizeof(*${interfaceName}_consts));
   1856 END
   1857     }
   1858 
   1859     # Special cases
   1860     if ($interfaceName eq "DOMWindow") {
   1861         push(@implContent, <<END);
   1862 
   1863   proto->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
   1864   desc->SetHiddenPrototype(true);
   1865   instance->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
   1866   // Set access check callbacks, but turned off initially.
   1867   // When a context is detached from a frame, turn on the access check.
   1868   // Turning on checks also invalidates inline caches of the object.
   1869   instance->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::Integer::New(V8ClassIndex::DOMWINDOW), false);
   1870 END
   1871     }
   1872     if ($interfaceName eq "Location") {
   1873         push(@implContent, <<END);
   1874 
   1875   // For security reasons, these functions are on the instance instead
   1876   // of on the prototype object to insure that they cannot be overwritten.
   1877   instance->SetAccessor(v8::String::New("reload"), V8Location::reloadAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
   1878   instance->SetAccessor(v8::String::New("replace"), V8Location::replaceAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
   1879   instance->SetAccessor(v8::String::New("assign"), V8Location::assignAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
   1880 END
   1881     }
   1882 
   1883     my $nativeType = GetNativeTypeForConversions($interfaceName);
   1884     if ($dataNode->extendedAttributes->{"PODType"}) {
   1885         $nativeType = "V8SVGPODTypeWrapper<${nativeType}>";
   1886     }
   1887     push(@implContent, <<END);
   1888 
   1889   // Custom toString template
   1890   desc->Set(getToStringName(), getToStringTemplate());
   1891   return desc;
   1892 }
   1893 
   1894 v8::Persistent<v8::FunctionTemplate> ${className}::GetRawTemplate() {
   1895   static v8::Persistent<v8::FunctionTemplate> ${className}_raw_cache_ = createRawTemplate();
   1896   return ${className}_raw_cache_;
   1897 }
   1898 
   1899 v8::Persistent<v8::FunctionTemplate> ${className}::GetTemplate() {
   1900   static v8::Persistent<v8::FunctionTemplate> ${className}_cache_ = Configure${className}Template(GetRawTemplate());
   1901   return ${className}_cache_;
   1902 }
   1903 
   1904 ${nativeType}* ${className}::toNative(v8::Handle<v8::Object> object) {
   1905   return reinterpret_cast<${nativeType}*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex));
   1906 }
   1907 
   1908 bool ${className}::HasInstance(v8::Handle<v8::Value> value) {
   1909   return GetRawTemplate()->HasInstance(value);
   1910 }
   1911 
   1912 END
   1913 
   1914     if ($implClassName eq "DOMWindow") {
   1915         push(@implContent, <<END);
   1916 v8::Persistent<v8::ObjectTemplate> V8DOMWindow::GetShadowObjectTemplate() {
   1917   static v8::Persistent<v8::ObjectTemplate> V8DOMWindowShadowObject_cache_;
   1918   if (V8DOMWindowShadowObject_cache_.IsEmpty()) {
   1919     V8DOMWindowShadowObject_cache_ = v8::Persistent<v8::ObjectTemplate>::New(v8::ObjectTemplate::New());
   1920     ConfigureShadowObjectTemplate(V8DOMWindowShadowObject_cache_);
   1921   }
   1922   return V8DOMWindowShadowObject_cache_;
   1923 }
   1924 END
   1925     }
   1926 
   1927     GenerateToV8Converters($dataNode, $interfaceName, $className, $nativeType);
   1928 
   1929     push(@implContent, <<END);
   1930 } // namespace WebCore
   1931 END
   1932 
   1933     push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
   1934 }
   1935 
   1936 sub GenerateToV8Converters
   1937 {
   1938     my $dataNode = shift;
   1939     my $interfaceName = shift;
   1940     my $className = shift;
   1941     my $nativeType = shift;
   1942 
   1943     my $wrapperType = "V8ClassIndex::" . uc($interfaceName);
   1944     my $domMapFunction = GetDomMapFunction($dataNode, $interfaceName);
   1945     my $forceNewObjectInput = IsDOMNodeType($interfaceName) ? ", bool forceNewObject" : "";
   1946     my $forceNewObjectCall = IsDOMNodeType($interfaceName) ? ", forceNewObject" : "";
   1947 
   1948     push(@implContent, <<END);
   1949 
   1950 v8::Handle<v8::Object> ${className}::wrap(${nativeType}* impl${forceNewObjectInput}) {
   1951   v8::Handle<v8::Object> wrapper;
   1952   V8Proxy* proxy = 0;
   1953 END
   1954 
   1955     if (IsNodeSubType($dataNode)) {
   1956         push(@implContent, <<END);
   1957   if (impl->document()) {
   1958     proxy = V8Proxy::retrieve(impl->document()->frame());
   1959     if (proxy && static_cast<Node*>(impl->document()) == static_cast<Node*>(impl))
   1960       proxy->windowShell()->initContextIfNeeded();
   1961   }
   1962 
   1963 END
   1964     }
   1965 
   1966     if ($domMapFunction) {
   1967         push(@implContent, "  if (!forceNewObject) {\n") if IsDOMNodeType($interfaceName);
   1968         if (IsNodeSubType($dataNode)) {
   1969             push(@implContent, "  wrapper = V8DOMWrapper::getWrapper(impl);\n");
   1970         } else {
   1971             push(@implContent, "  wrapper = ${domMapFunction}.get(impl);\n");
   1972         }
   1973         push(@implContent, <<END);
   1974   if (!wrapper.IsEmpty())
   1975     return wrapper;
   1976 END
   1977         push(@implContent, "  }\n") if IsDOMNodeType($interfaceName);
   1978     }
   1979     if (IsNodeSubType($dataNode)) {
   1980         push(@implContent, <<END);
   1981 
   1982   v8::Handle<v8::Context> context;
   1983   if (proxy)
   1984     context = proxy->context();
   1985 
   1986   // Enter the node's context and create the wrapper in that context.
   1987   if (!context.IsEmpty())
   1988     context->Enter();
   1989 END
   1990     }
   1991 
   1992     push(@implContent, <<END);
   1993   wrapper = V8DOMWrapper::instantiateV8Object(proxy, ${wrapperType}, impl);
   1994 END
   1995 
   1996     if (IsNodeSubType($dataNode)) {
   1997         push(@implContent, <<END);
   1998   // Exit the node's context if it was entered.
   1999   if (!context.IsEmpty())
   2000     context->Exit();
   2001 END
   2002     }
   2003 
   2004     push(@implContent, <<END);
   2005   if (wrapper.IsEmpty())
   2006     return wrapper;
   2007 END
   2008     push(@implContent, "\n  impl->ref();\n") if IsRefPtrType($interfaceName);
   2009 
   2010     if ($domMapFunction) {
   2011         push(@implContent, <<END);
   2012   ${domMapFunction}.set(impl, v8::Persistent<v8::Object>::New(wrapper));
   2013 END
   2014     }
   2015 
   2016     push(@implContent, <<END);
   2017   return wrapper;
   2018 }
   2019 END
   2020 
   2021     if (IsRefPtrType($interfaceName)) {
   2022         push(@implContent, <<END);
   2023 
   2024 v8::Handle<v8::Value> toV8(PassRefPtr<${nativeType} > impl${forceNewObjectInput}) {
   2025   return toV8(impl.get()${forceNewObjectCall});
   2026 }
   2027 END
   2028     }
   2029 
   2030     if (!HasCustomToV8Implementation($dataNode, $interfaceName)) {
   2031         push(@implContent, <<END);
   2032 
   2033 v8::Handle<v8::Value> toV8(${nativeType}* impl${forceNewObjectInput}) {
   2034   if (!impl)
   2035     return v8::Null();
   2036   return ${className}::wrap(impl${forceNewObjectCall});
   2037 }
   2038 END
   2039     }
   2040 }
   2041 
   2042 sub HasCustomToV8Implementation {
   2043     # FIXME: This subroutine is lame. Probably should be an .idl attribute (CustomToV8)?
   2044     $dataNode = shift;
   2045     $interfaceName = shift;
   2046 
   2047     # We generate a custom converter (but JSC doesn't) for the following:
   2048     return 1 if $interfaceName eq "BarInfo";
   2049     return 1 if $interfaceName eq "CSSStyleSheet";
   2050     return 1 if $interfaceName eq "CanvasPixelArray";
   2051     return 1 if $interfaceName eq "DOMSelection";
   2052     return 1 if $interfaceName eq "DOMWindow";
   2053     return 1 if $interfaceName eq "Element";
   2054     return 1 if $interfaceName eq "Location";
   2055     return 1 if $interfaceName eq "HTMLDocument";
   2056     return 1 if $interfaceName eq "HTMLElement";
   2057     return 1 if $interfaceName eq "History";
   2058     return 1 if $interfaceName eq "NamedNodeMap";
   2059     return 1 if $interfaceName eq "Navigator";
   2060     return 1 if $interfaceName eq "SVGDocument";
   2061     return 1 if $interfaceName eq "SVGElement";
   2062     return 1 if $interfaceName eq "Screen";
   2063     return 1 if $interfaceName eq "WorkerContext";
   2064     # We don't generate a custom converter (but JSC does) for the following:
   2065     return 0 if $interfaceName eq "AbstractWorker";
   2066     return 0 if $interfaceName eq "CanvasRenderingContext";
   2067     return 0 if $interfaceName eq "ImageData";
   2068     return 0 if $interfaceName eq "SVGElementInstance";
   2069 
   2070     # For everything else, do what JSC does.
   2071     return $dataNode->extendedAttributes->{"CustomToJS"};
   2072 }
   2073 
   2074 sub GetDomMapFunction
   2075 {
   2076     my $dataNode = shift;
   2077     my $type = shift;
   2078     return "getDOMSVGElementInstanceMap()" if $type eq "SVGElementInstance";
   2079     return "getDOMNodeMap()" if IsNodeSubType($dataNode);
   2080     # Only use getDOMSVGObjectWithContextMap() for non-node svg objects
   2081     return "getDOMSVGObjectWithContextMap()" if $type =~ /SVG/;
   2082     return "" if $type eq "DOMImplementation";
   2083     return "getActiveDOMObjectMap()" if IsActiveDomType($type);
   2084     return "getDOMObjectMap()";
   2085 }
   2086 
   2087 sub IsActiveDomType
   2088 {
   2089     # FIXME: Consider making this an .idl attribute.
   2090     my $type = shift;
   2091     return 1 if $type eq "MessagePort";
   2092     return 1 if $type eq "XMLHttpRequest";
   2093     return 1 if $type eq "WebSocket";
   2094     return 1 if $type eq "Worker";
   2095     return 1 if $type eq "SharedWorker";
   2096     return 0;
   2097 }
   2098 
   2099 sub GetNativeTypeForConversions
   2100 {
   2101     my $type = shift;
   2102     return "FloatRect" if $type eq "SVGRect";
   2103     return "FloatPoint" if $type eq "SVGPoint";
   2104     return "AffineTransform" if $type eq "SVGMatrix";
   2105     return "float" if $type eq "SVGNumber";
   2106     return $type;
   2107 }
   2108 
   2109 sub GenerateFunctionCallString()
   2110 {
   2111     my $function = shift;
   2112     my $numberOfParameters = shift;
   2113     my $indent = shift;
   2114     my $implClassName = shift;
   2115 
   2116     my $name = $function->signature->name;
   2117     my $isPodType = IsPodType($implClassName);
   2118     my $returnType = GetTypeFromSignature($function->signature);
   2119     my $returnsPodType = IsPodType($returnType);
   2120     my $nativeReturnType = GetNativeType($returnType, 0);
   2121     my $result = "";
   2122 
   2123     # Special case: SVG matrix transform methods should not mutate
   2124     # the matrix but return a copy
   2125     my $copyFirst = 0;
   2126     if ($implClassName eq "SVGMatrix" && $function->signature->type eq "SVGMatrix") {
   2127         $copyFirst = 1;
   2128     }
   2129 
   2130     if ($function->signature->extendedAttributes->{"v8implname"}) {
   2131         $name = $function->signature->extendedAttributes->{"v8implname"};
   2132     }
   2133 
   2134     if ($function->signature->extendedAttributes->{"ImplementationFunction"}) {
   2135         $name = $function->signature->extendedAttributes->{"ImplementationFunction"};
   2136     }
   2137 
   2138     my $functionString = "imp->${name}(";
   2139 
   2140     if ($copyFirst) {
   2141         $functionString = "result.${name}(";
   2142     }
   2143 
   2144     my $returnsListItemPodType = 0;
   2145     # SVG lists functions that return POD types require special handling
   2146     if (IsSVGListTypeNeedingSpecialHandling($implClassName) && IsSVGListMethod($name) && $returnsPodType) {
   2147         $returnsListItemPodType = 1;
   2148         $result .= $indent . "SVGList<RefPtr<SVGPODListItem<$nativeReturnType> > >* listImp = imp;\n";
   2149         $functionString = "listImp->${name}(";
   2150     }
   2151 
   2152     my $first = 1;
   2153     my $index = 0;
   2154 
   2155     foreach my $parameter (@{$function->parameters}) {
   2156         if ($index eq $numberOfParameters) {
   2157             last;
   2158         }
   2159         if ($first) { $first = 0; }
   2160         else { $functionString .= ", "; }
   2161         my $paramName = $parameter->name;
   2162         my $paramType = $parameter->type;
   2163 
   2164         # This is a bit of a hack... we need to convert parameters to methods on SVG lists
   2165         # of POD types which are items in the list to appropriate SVGList<> instances
   2166         if ($returnsListItemPodType && $paramType . "List" eq $implClassName) {
   2167             $paramName = "SVGPODListItem<" . GetNativeType($paramType, 1) . ">::copy($paramName)";
   2168         }
   2169 
   2170         if ($parameter->type eq "NodeFilter" || $parameter->type eq "XPathNSResolver") {
   2171             $functionString .= "$paramName.get()";
   2172         } else {
   2173             $functionString .= $paramName;
   2174         }
   2175         $index++;
   2176     }
   2177 
   2178     if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
   2179         $functionString .= ", " if not $first;
   2180         $functionString .= "callStack.get()";
   2181         if ($first) { $first = 0; }
   2182     }
   2183 
   2184     if ($function->signature->extendedAttributes->{"NeedsUserGestureCheck"}) {
   2185         $functionString .= ", " if not $first;
   2186         # FIXME: We need to pass DOMWrapperWorld as a parameter.
   2187         # See http://trac.webkit.org/changeset/54182
   2188         $functionString .= "processingUserGesture()";
   2189         if ($first) { $first = 0; }
   2190     }
   2191 
   2192     if (@{$function->raisesExceptions}) {
   2193         $functionString .= ", " if not $first;
   2194         $functionString .= "ec";
   2195     }
   2196     $functionString .= ")";
   2197 
   2198     my $return = "result";
   2199     my $returnIsRef = IsRefPtrType($returnType);
   2200 
   2201     if ($returnType eq "void") {
   2202         $result .= $indent . "$functionString;\n";
   2203     } elsif ($copyFirst) {
   2204         $result .=
   2205             $indent . GetNativeType($returnType, 0) . " result = *imp;\n" .
   2206             $indent . "$functionString;\n";
   2207     } elsif ($returnsListItemPodType) {
   2208         $result .= $indent . "RefPtr<SVGPODListItem<$nativeReturnType> > result = $functionString;\n";
   2209     } elsif (@{$function->raisesExceptions} or $returnsPodType or $isPodType or IsSVGTypeNeedingContextParameter($returnType)) {
   2210         $result .= $indent . $nativeReturnType . " result = $functionString;\n";
   2211     } else {
   2212         # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
   2213         $return = $functionString;
   2214         $returnIsRef = 0;
   2215     }
   2216 
   2217     if (@{$function->raisesExceptions}) {
   2218         $result .= $indent . "if (UNLIKELY(ec)) goto fail;\n";
   2219     }
   2220 
   2221     # If the return type is a POD type, separate out the wrapper generation
   2222     if ($returnsListItemPodType) {
   2223         $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = ";
   2224         $result .= "V8SVGPODTypeWrapperCreatorForList<" . $nativeReturnType . ">::create($return, imp->associatedAttributeName());\n";
   2225         $return = "wrapper";
   2226     } elsif ($returnsPodType) {
   2227         $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = ";
   2228         $result .= GenerateSVGStaticPodTypeWrapper($returnType, $return) . ";\n";
   2229         $return = "wrapper";
   2230     }
   2231 
   2232     my $generatedSVGContextRetrieval = 0;
   2233     # If the return type needs an SVG context, output it
   2234     if (IsSVGTypeNeedingContextParameter($returnType)) {
   2235         $result .= GenerateSVGContextAssignment($implClassName, $return . ".get()", $indent);
   2236         $generatedSVGContextRetrieval = 1;
   2237     }
   2238 
   2239     if (IsSVGTypeNeedingContextParameter($implClassName) && $implClassName =~ /List$/ && IsSVGListMutator($name)) {
   2240         if (!$generatedSVGContextRetrieval) {
   2241             $result .= GenerateSVGContextRetrieval($implClassName, $indent);
   2242             $generatedSVGContextRetrieval = 1;
   2243         }
   2244 
   2245         $result .= $indent . "context->svgAttributeChanged(imp->associatedAttributeName());\n";
   2246         $implIncludes{"SVGElement.h"} = 1;
   2247     }
   2248 
   2249     # If the implementing class is a POD type, commit changes
   2250     if ($isPodType) {
   2251         if (!$generatedSVGContextRetrieval) {
   2252             $result .= GenerateSVGContextRetrieval($implClassName, $indent);
   2253             $generatedSVGContextRetrieval = 1;
   2254         }
   2255 
   2256         $result .= $indent . "imp_wrapper->commitChange(imp_instance, context);\n";
   2257     }
   2258 
   2259     if ($returnsPodType) {
   2260         $implIncludes{"V8${returnType}.h"} = 1;
   2261         $result .= $indent . "return toV8(wrapper.release());\n";
   2262     } else {
   2263         $return .= ".release()" if ($returnIsRef);
   2264         $result .= $indent . ReturnNativeToJSValue($function->signature, $return, $indent) . ";\n";
   2265     }
   2266 
   2267     return $result;
   2268 }
   2269 
   2270 
   2271 sub GetTypeFromSignature
   2272 {
   2273     my $signature = shift;
   2274 
   2275     return $codeGenerator->StripModule($signature->type);
   2276 }
   2277 
   2278 
   2279 sub GetNativeTypeFromSignature
   2280 {
   2281     my $signature = shift;
   2282     my $parameterIndex = shift;
   2283 
   2284     my $type = GetTypeFromSignature($signature);
   2285 
   2286     if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) {
   2287         # Special-case index arguments because we need to check that they aren't < 0.
   2288         return "int";
   2289     }
   2290 
   2291     $type = GetNativeType($type, $parameterIndex >= 0 ? 1 : 0);
   2292 
   2293     if ($parameterIndex >= 0 && $type eq "V8Parameter") {
   2294         my $mode = "";
   2295         if ($signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"}) {
   2296             $mode = "WithUndefinedOrNullCheck";
   2297         } elsif ($signature->extendedAttributes->{"ConvertNullToNullString"}) {
   2298             $mode = "WithNullCheck";
   2299         }
   2300         $type .= "<$mode>";
   2301     }
   2302 
   2303     return $type;
   2304 }
   2305 
   2306 sub IsRefPtrType
   2307 {
   2308     my $type = shift;
   2309 
   2310     return 0 if $type eq "boolean";
   2311     return 0 if $type eq "float";
   2312     return 0 if $type eq "int";
   2313     return 0 if $type eq "Date";
   2314     return 0 if $type eq "DOMString";
   2315     return 0 if $type eq "double";
   2316     return 0 if $type eq "short";
   2317     return 0 if $type eq "long";
   2318     return 0 if $type eq "unsigned";
   2319     return 0 if $type eq "unsigned long";
   2320     return 0 if $type eq "unsigned short";
   2321     return 0 if $type eq "SVGAnimatedPoints";
   2322 
   2323     return 1;
   2324 }
   2325 
   2326 sub GetNativeType
   2327 {
   2328     my $type = shift;
   2329     my $isParameter = shift;
   2330 
   2331     if ($type eq "float" or $type eq "double") {
   2332         return $type;
   2333     }
   2334 
   2335     return "V8Parameter" if ($type eq "DOMString" or $type eq "DOMUserData") and $isParameter;
   2336     return "int" if $type eq "int";
   2337     return "int" if $type eq "short" or $type eq "unsigned short";
   2338     return "unsigned" if $type eq "unsigned long";
   2339     return "int" if $type eq "long";
   2340     return "long long" if $type eq "long long";
   2341     return "unsigned long long" if $type eq "unsigned long long";
   2342     return "bool" if $type eq "boolean";
   2343     return "String" if $type eq "DOMString";
   2344     return "Range::CompareHow" if $type eq "CompareHow";
   2345     return "FloatRect" if $type eq "SVGRect";
   2346     return "FloatPoint" if $type eq "SVGPoint";
   2347     return "AffineTransform" if $type eq "SVGMatrix";
   2348     return "SVGTransform" if $type eq "SVGTransform";
   2349     return "SVGLength" if $type eq "SVGLength";
   2350     return "SVGAngle" if $type eq "SVGAngle";
   2351     return "float" if $type eq "SVGNumber";
   2352     return "SVGPreserveAspectRatio" if $type eq "SVGPreserveAspectRatio";
   2353     return "SVGPaint::SVGPaintType" if $type eq "SVGPaintType";
   2354     return "DOMTimeStamp" if $type eq "DOMTimeStamp";
   2355     return "unsigned" if $type eq "unsigned int";
   2356     return "Node*" if $type eq "EventTarget" and $isParameter;
   2357     return "double" if $type eq "Date";
   2358 
   2359     return "String" if $type eq "DOMUserData";  # FIXME: Temporary hack?
   2360 
   2361     # temporary hack
   2362     return "RefPtr<NodeFilter>" if $type eq "NodeFilter";
   2363 
   2364     # necessary as resolvers could be constructed on fly.
   2365     return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver";
   2366 
   2367     return "RefPtr<${type}>" if IsRefPtrType($type) and not $isParameter;
   2368 
   2369     # Default, assume native type is a pointer with same type name as idl type
   2370     return "${type}*";
   2371 }
   2372 
   2373 
   2374 my %typeCanFailConversion = (
   2375     "Attr" => 1,
   2376     "WebGLArray" => 0,
   2377     "WebGLBuffer" => 0,
   2378     "WebGLByteArray" => 0,
   2379     "WebGLUnsignedByteArray" => 0,
   2380     "WebGLContextAttributes" => 0,
   2381     "WebGLFloatArray" => 0,
   2382     "WebGLFramebuffer" => 0,
   2383     "CanvasGradient" => 0,
   2384     "WebGLIntArray" => 0,
   2385     "CanvasPixelArray" => 0,
   2386     "WebGLProgram" => 0,
   2387     "WebGLRenderbuffer" => 0,
   2388     "WebGLShader" => 0,
   2389     "WebGLShortArray" => 0,
   2390     "WebGLTexture" => 0,
   2391     "WebGLUniformLocation" => 0,
   2392     "CompareHow" => 0,
   2393     "DataGridColumn" => 0,
   2394     "DOMString" => 0,
   2395     "DOMWindow" => 0,
   2396     "DocumentType" => 0,
   2397     "Element" => 0,
   2398     "Event" => 0,
   2399     "EventListener" => 0,
   2400     "EventTarget" => 0,
   2401     "HTMLCanvasElement" => 0,
   2402     "HTMLElement" => 0,
   2403     "HTMLImageElement" => 0,
   2404     "HTMLOptionElement" => 0,
   2405     "HTMLVideoElement" => 0,
   2406     "Node" => 0,
   2407     "NodeFilter" => 0,
   2408     "MessagePort" => 0,
   2409     "NSResolver" => 0,
   2410     "Range" => 0,
   2411     "SQLResultSet" => 0,
   2412     "Storage" => 0,
   2413     "SVGAngle" => 1,
   2414     "SVGElement" => 0,
   2415     "SVGLength" => 1,
   2416     "SVGMatrix" => 1,
   2417     "SVGNumber" => 0,
   2418     "SVGPaintType" => 0,
   2419     "SVGPathSeg" => 0,
   2420     "SVGPoint" => 1,
   2421     "SVGPreserveAspectRatio" => 1,
   2422     "SVGRect" => 1,
   2423     "SVGTransform" => 1,
   2424     "TouchList" => 0,
   2425     "VoidCallback" => 1,
   2426     "WebKitCSSMatrix" => 0,
   2427     "WebKitPoint" => 0,
   2428     "XPathEvaluator" => 0,
   2429     "XPathNSResolver" => 0,
   2430     "XPathResult" => 0,
   2431     "boolean" => 0,
   2432     "double" => 0,
   2433     "float" => 0,
   2434     "long" => 0,
   2435     "unsigned long" => 0,
   2436     "unsigned short" => 0,
   2437     "long long" => 0,
   2438     "unsigned long long" => 0
   2439 );
   2440 
   2441 
   2442 sub TranslateParameter
   2443 {
   2444     my $signature = shift;
   2445 
   2446     # The IDL uses some pseudo-types which don't really exist.
   2447     if ($signature->type eq "TimeoutHandler") {
   2448       $signature->type("DOMString");
   2449     }
   2450 }
   2451 
   2452 sub BasicTypeCanFailConversion
   2453 {
   2454     my $signature = shift;
   2455     my $type = GetTypeFromSignature($signature);
   2456 
   2457     return 1 if $type eq "SVGAngle";
   2458     return 1 if $type eq "SVGLength";
   2459     return 1 if $type eq "SVGMatrix";
   2460     return 1 if $type eq "SVGPoint";
   2461     return 1 if $type eq "SVGPreserveAspectRatio";
   2462     return 1 if $type eq "SVGRect";
   2463     return 1 if $type eq "SVGTransform";
   2464     return 0;
   2465 }
   2466 
   2467 sub TypeCanFailConversion
   2468 {
   2469     my $signature = shift;
   2470 
   2471     my $type = GetTypeFromSignature($signature);
   2472 
   2473     $implIncludes{"ExceptionCode.h"} = 1 if $type eq "Attr";
   2474 
   2475     return $typeCanFailConversion{$type} if exists $typeCanFailConversion{$type};
   2476 
   2477     die "Don't know whether a JS value can fail conversion to type $type.";
   2478 }
   2479 
   2480 sub JSValueToNative
   2481 {
   2482     my $signature = shift;
   2483     my $value = shift;
   2484     my $okParam = shift;
   2485     my $maybeOkParam = $okParam ? ", ${okParam}" : "";
   2486 
   2487     my $type = GetTypeFromSignature($signature);
   2488 
   2489     return "$value" if $type eq "JSObject";
   2490     return "$value->BooleanValue()" if $type eq "boolean";
   2491     return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $type eq "double";
   2492     return "$value->NumberValue()" if $type eq "SVGNumber";
   2493 
   2494     return "toInt32($value${maybeOkParam})" if $type eq "unsigned long" or $type eq "unsigned short" or $type eq "long";
   2495     return "toInt64($value)" if $type eq "unsigned long long" or $type eq "long long";
   2496     return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "CompareHow";
   2497     return "static_cast<SVGPaint::SVGPaintType>($value->ToInt32()->Int32Value())" if $type eq "SVGPaintType";
   2498     return "toWebCoreDate($value)" if $type eq "Date";
   2499 
   2500     if ($type eq "DOMString" or $type eq "DOMUserData") {
   2501         return $value;
   2502     }
   2503 
   2504     if ($type eq "SerializedScriptValue") {
   2505         $implIncludes{"SerializedScriptValue.h"} = 1;
   2506         return "SerializedScriptValue::create($value)";
   2507     }
   2508 
   2509     if ($type eq "NodeFilter") {
   2510         return "V8DOMWrapper::wrapNativeNodeFilter($value)";
   2511     }
   2512 
   2513     if ($type eq "SVGRect") {
   2514         $implIncludes{"FloatRect.h"} = 1;
   2515     }
   2516 
   2517     if ($type eq "SVGPoint") {
   2518         $implIncludes{"FloatPoint.h"} = 1;
   2519     }
   2520 
   2521     # Default, assume autogenerated type conversion routines
   2522     if ($type eq "EventTarget") {
   2523         $implIncludes{"V8Node.h"} = 1;
   2524 
   2525         # EventTarget is not in DOM hierarchy, but all Nodes are EventTarget.
   2526         return "V8Node::HasInstance($value) ? V8Node::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
   2527     }
   2528 
   2529     if ($type eq "XPathNSResolver") {
   2530         return "V8DOMWrapper::getXPathNSResolver($value)";
   2531     }
   2532 
   2533     AddIncludesForType($type);
   2534 
   2535     if (IsDOMNodeType($type)) {
   2536         $implIncludes{"V8${type}.h"} = 1;
   2537 
   2538         # Perform type checks on the parameter, if it is expected Node type,
   2539         # return NULL.
   2540         return "V8${type}::HasInstance($value) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
   2541     } else {
   2542         # TODO: Temporary to avoid Window name conflict.
   2543         my $classIndex = uc($type);
   2544         my $implClassName = ${type};
   2545 
   2546         $implIncludes{"V8$type.h"} = 1;
   2547 
   2548         if (IsPodType($type)) {
   2549             my $nativeType = GetNativeType($type);
   2550             $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
   2551 
   2552             return "V8SVGPODTypeUtil::toSVGPODType<${nativeType}>(V8ClassIndex::${classIndex}, $value${maybeOkParam})"
   2553         }
   2554 
   2555         $implIncludes{"V8${type}.h"} = 1;
   2556 
   2557         # Perform type checks on the parameter, if it is expected Node type,
   2558         # return NULL.
   2559         return "V8${type}::HasInstance($value) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
   2560     }
   2561 }
   2562 
   2563 
   2564 sub GetV8HeaderName
   2565 {
   2566     my $type = shift;
   2567     return "V8Event.h" if $type eq "DOMTimeStamp";
   2568     return "EventListener.h" if $type eq "EventListener";
   2569     return "EventTarget.h" if $type eq "EventTarget";
   2570     return "SerializedScriptValue.h" if $type eq "SerializedScriptValue";
   2571     return "V8${type}.h";
   2572 }
   2573 
   2574 
   2575 sub CreateCustomSignature
   2576 {
   2577     my $function = shift;
   2578     my $count = @{$function->parameters};
   2579     my $name = $function->signature->name;
   2580     my $result = "  const int ${name}_argc = ${count};\n" .
   2581       "  v8::Handle<v8::FunctionTemplate> ${name}_argv[${name}_argc] = { ";
   2582     my $first = 1;
   2583     foreach my $parameter (@{$function->parameters}) {
   2584         if ($first) { $first = 0; }
   2585         else { $result .= ", "; }
   2586         if (IsWrapperType($parameter->type)) {
   2587             if ($parameter->type eq "XPathNSResolver") {
   2588                 # Special case for XPathNSResolver.  All other browsers accepts a callable,
   2589                 # so, even though it's against IDL, accept objects here.
   2590                 $result .= "v8::Handle<v8::FunctionTemplate>()";
   2591             } else {
   2592                 my $type = $parameter->type;
   2593                 my $header = GetV8HeaderName($type);
   2594                 $implIncludes{$header} = 1;
   2595                 $result .= "V8${type}::GetRawTemplate()";
   2596             }
   2597         } else {
   2598             $result .= "v8::Handle<v8::FunctionTemplate>()";
   2599         }
   2600     }
   2601     $result .= " };\n";
   2602     $result .= "  v8::Handle<v8::Signature> ${name}_signature = v8::Signature::New(desc, ${name}_argc, ${name}_argv);\n";
   2603     return $result;
   2604 }
   2605 
   2606 
   2607 sub RequiresCustomSignature
   2608 {
   2609     my $function = shift;
   2610     # No signature needed for Custom function
   2611     if ($function->signature->extendedAttributes->{"Custom"} ||
   2612         $function->signature->extendedAttributes->{"V8Custom"}) {
   2613         return 0;
   2614     }
   2615 
   2616     foreach my $parameter (@{$function->parameters}) {
   2617       if (IsWrapperType($parameter->type)) {
   2618           return 1;
   2619       }
   2620     }
   2621     return 0;
   2622 }
   2623 
   2624 
   2625 my %non_wrapper_types = (
   2626     'float' => 1,
   2627     'double' => 1,
   2628     'short' => 1,
   2629     'unsigned short' => 1,
   2630     'long' => 1,
   2631     'unsigned long' => 1,
   2632     'boolean' => 1,
   2633     'long long' => 1,
   2634     'unsigned long long' => 1,
   2635     'DOMString' => 1,
   2636     'CompareHow' => 1,
   2637     'SVGAngle' => 1,
   2638     'SVGRect' => 1,
   2639     'SVGPoint' => 1,
   2640     'SVGPreserveAspectRatio' => 1,
   2641     'SVGMatrix' => 1,
   2642     'SVGTransform' => 1,
   2643     'SVGLength' => 1,
   2644     'SVGNumber' => 1,
   2645     'SVGPaintType' => 1,
   2646     'DOMTimeStamp' => 1,
   2647     'JSObject' => 1,
   2648     'EventTarget' => 1,
   2649     'NodeFilter' => 1,
   2650     'EventListener' => 1
   2651 );
   2652 
   2653 
   2654 sub IsWrapperType
   2655 {
   2656     my $type = $codeGenerator->StripModule(shift);
   2657     return !($non_wrapper_types{$type});
   2658 }
   2659 
   2660 sub IsDOMNodeType
   2661 {
   2662     my $type = shift;
   2663 
   2664     return 1 if $type eq 'Attr';
   2665     return 1 if $type eq 'CDATASection';
   2666     return 1 if $type eq 'Comment';
   2667     return 1 if $type eq 'Document';
   2668     return 1 if $type eq 'DocumentFragment';
   2669     return 1 if $type eq 'DocumentType';
   2670     return 1 if $type eq 'Element';
   2671     return 1 if $type eq 'EntityReference';
   2672     return 1 if $type eq 'HTMLCanvasElement';
   2673     return 1 if $type eq 'HTMLDocument';
   2674     return 1 if $type eq 'HTMLElement';
   2675     return 1 if $type eq 'HTMLFormElement';
   2676     return 1 if $type eq 'HTMLTableCaptionElement';
   2677     return 1 if $type eq 'HTMLTableSectionElement';
   2678     return 1 if $type eq 'Node';
   2679     return 1 if $type eq 'ProcessingInstruction';
   2680     return 1 if $type eq 'SVGElement';
   2681     return 1 if $type eq 'SVGDocument';
   2682     return 1 if $type eq 'SVGSVGElement';
   2683     return 1 if $type eq 'SVGUseElement';
   2684     return 1 if $type eq 'Text';
   2685 
   2686     return 0;
   2687 }
   2688 
   2689 
   2690 sub ReturnNativeToJSValue
   2691 {
   2692     my $signature = shift;
   2693     my $value = shift;
   2694     my $indent = shift;
   2695     my $type = GetTypeFromSignature($signature);
   2696 
   2697     return "return v8::Date::New(static_cast<double>($value))" if $type eq "DOMTimeStamp";
   2698     return "return v8Boolean($value)" if $type eq "boolean";
   2699     return "return v8::Handle<v8::Value>()" if $type eq "void";     # equivalent to v8::Undefined()
   2700 
   2701     # For all the types where we use 'int' as the representation type,
   2702     # we use Integer::New which has a fast Smi conversion check.
   2703     my $nativeType = GetNativeType($type);
   2704     return "return v8::Integer::New($value)" if $nativeType eq "int";
   2705     return "return v8::Integer::NewFromUnsigned($value)" if $nativeType eq "unsigned";
   2706 
   2707     return "return v8DateOrNull($value);" if $type eq "Date";
   2708     return "return v8::Number::New($value)" if $codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType";
   2709 
   2710     if ($codeGenerator->IsStringType($type)) {
   2711         my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"};
   2712         if (defined $conv) {
   2713             return "return v8StringOrNull($value)" if $conv eq "Null";
   2714             return "return v8StringOrUndefined($value)" if $conv eq "Undefined";
   2715             return "return v8StringOrFalse($value)" if $conv eq "False";
   2716 
   2717             die "Unknown value for ConvertNullStringTo extended attribute";
   2718         }
   2719         return "return v8String($value)";
   2720     }
   2721 
   2722     AddIncludesForType($type);
   2723 
   2724     # special case for non-DOM node interfaces
   2725     if (IsDOMNodeType($type)) {
   2726         return "return toV8(${value}" . ($signature->extendedAttributes->{"ReturnsNew"} ? ", true)" : ")");
   2727     }
   2728 
   2729     if ($type eq "EventTarget") {
   2730         return "return V8DOMWrapper::convertEventTargetToV8Object($value)";
   2731     }
   2732 
   2733     if ($type eq "EventListener") {
   2734         $implIncludes{"V8AbstractEventListener.h"} = 1;
   2735         return "return ${value} ? v8::Handle<v8::Value>(static_cast<V8AbstractEventListener*>(${value})->getListenerObject(imp->scriptExecutionContext())) : v8::Handle<v8::Value>(v8::Null())";
   2736     }
   2737 
   2738     if ($type eq "SerializedScriptValue") {
   2739         $implIncludes{"$type.h"} = 1;
   2740         return "return $value->deserialize()";
   2741     }
   2742 
   2743     $implIncludes{"wtf/RefCounted.h"} = 1;
   2744     $implIncludes{"wtf/RefPtr.h"} = 1;
   2745     $implIncludes{"wtf/GetPtr.h"} = 1;
   2746 
   2747     if (IsPodType($type)) {
   2748         $value = GenerateSVGStaticPodTypeWrapper($type, $value) . ".get()";
   2749     }
   2750 
   2751     return "return toV8($value)";
   2752 }
   2753 
   2754 sub GenerateSVGStaticPodTypeWrapper {
   2755     my $type = shift;
   2756     my $value = shift;
   2757 
   2758     $implIncludes{"V8$type.h"}=1;
   2759     $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
   2760 
   2761     my $nativeType = GetNativeType($type);
   2762     return "V8SVGStaticPODTypeWrapper<$nativeType>::create($value)";
   2763 }
   2764 
   2765 # Internal helper
   2766 sub WriteData
   2767 {
   2768     if (defined($IMPL)) {
   2769         # Write content to file.
   2770         print $IMPL @implContentHeader;
   2771 
   2772         print $IMPL @implFixedHeader;
   2773 
   2774         foreach my $implInclude (sort keys(%implIncludes)) {
   2775             my $checkType = $implInclude;
   2776             $checkType =~ s/\.h//;
   2777 
   2778             print $IMPL "#include \"$implInclude\"\n" unless $codeGenerator->IsSVGAnimatedType($checkType);
   2779         }
   2780 
   2781         print $IMPL "\n";
   2782         print $IMPL @implContentDecls;
   2783         print $IMPL @implContent;
   2784         close($IMPL);
   2785         undef($IMPL);
   2786 
   2787         %implIncludes = ();
   2788         @implFixedHeader = ();
   2789         @implHeaderContent = ();
   2790         @implContentDecls = ();
   2791         @implContent = ();
   2792     }
   2793 
   2794     if (defined($HEADER)) {
   2795         # Write content to file.
   2796         print $HEADER @headerContent;
   2797         close($HEADER);
   2798         undef($HEADER);
   2799 
   2800         @headerContent = ();
   2801     }
   2802 }
   2803 
   2804 sub IsSVGTypeNeedingContextParameter
   2805 {
   2806     my $implClassName = shift;
   2807 
   2808     if ($implClassName =~ /SVG/ and not $implClassName =~ /Element/) {
   2809         return 1 unless $implClassName =~ /SVGPaint/ or $implClassName =~ /SVGColor/ or $implClassName =~ /SVGDocument/;
   2810     }
   2811 
   2812     return 0;
   2813 }
   2814 
   2815 sub GenerateSVGContextAssignment
   2816 {
   2817     my $srcType = shift;
   2818     my $value = shift;
   2819     my $indent = shift;
   2820 
   2821     $result = GenerateSVGContextRetrieval($srcType, $indent);
   2822     $result .= $indent . "V8Proxy::setSVGContext($value, context);\n";
   2823 
   2824     return $result;
   2825 }
   2826 
   2827 sub GenerateSVGContextRetrieval
   2828 {
   2829     my $srcType = shift;
   2830     my $indent = shift;
   2831 
   2832     my $srcIsPodType = IsPodType($srcType);
   2833 
   2834     my $srcObject = "imp";
   2835     if ($srcIsPodType) {
   2836         $srcObject = "imp_wrapper";
   2837     }
   2838 
   2839     my $contextDecl;
   2840 
   2841     if (IsSVGTypeNeedingContextParameter($srcType)) {
   2842         $contextDecl = "V8Proxy::svgContext($srcObject)";
   2843     } else {
   2844         $contextDecl = $srcObject;
   2845     }
   2846 
   2847     return $indent . "SVGElement* context = $contextDecl;\n";
   2848 }
   2849 
   2850 sub IsSVGListMutator
   2851 {
   2852     my $functionName = shift;
   2853 
   2854     return 1 if $functionName eq "clear";
   2855     return 1 if $functionName eq "initialize";
   2856     return 1 if $functionName eq "insertItemBefore";
   2857     return 1 if $functionName eq "replaceItem";
   2858     return 1 if $functionName eq "removeItem";
   2859     return 1 if $functionName eq "appendItem";
   2860 
   2861     return 0;
   2862 }
   2863 
   2864 sub IsSVGListMethod
   2865 {
   2866     my $functionName = shift;
   2867 
   2868     return 1 if $functionName eq "getFirst";
   2869     return 1 if $functionName eq "getLast";
   2870     return 1 if $functionName eq "getItem";
   2871 
   2872     return IsSVGListMutator($functionName);
   2873 }
   2874 
   2875 sub IsSVGListTypeNeedingSpecialHandling
   2876 {
   2877     my $className = shift;
   2878 
   2879     return 1 if $className eq "SVGPointList";
   2880     return 1 if $className eq "SVGTransformList";
   2881 
   2882     return 0;
   2883 }
   2884 
   2885 sub DebugPrint
   2886 {
   2887     my $output = shift;
   2888 
   2889     print $output;
   2890     print "\n";
   2891 }
   2892