Home | History | Annotate | Download | only in scripts
      1 # Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann (at] kde.org>
      2 # Copyright (C) 2006 Anders Carlsson <andersca (at] mac.com>
      3 # Copyright (C) 2006 Samuel Weinig <sam.weinig (at] gmail.com>
      4 # Copyright (C) 2006 Alexey Proskuryakov <ap (at] webkit.org>
      5 # Copyright (C) 2006 Apple Computer, Inc.
      6 # Copyright (C) 2007, 2008, 2009, 2012 Google Inc.
      7 # Copyright (C) 2009 Cameron McCormack <cam (at] mcc.id.au>
      8 # Copyright (C) Research In Motion Limited 2010. All rights reserved.
      9 # Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
     10 # Copyright (C) 2012 Ericsson AB. All rights reserved.
     11 # Copyright (C) 2013 Samsung Electronics. All rights reserved.
     12 #
     13 # This library is free software; you can redistribute it and/or
     14 # modify it under the terms of the GNU Library General Public
     15 # License as published by the Free Software Foundation; either
     16 # version 2 of the License, or (at your option) any later version.
     17 #
     18 # This library is distributed in the hope that it will be useful,
     19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
     20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     21 # Library General Public License for more details.
     22 #
     23 # You should have received a copy of the GNU Library General Public License
     24 # along with this library; see the file COPYING.LIB.  If not, write to
     25 # the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
     26 # Boston, MA 02111-1307, USA.
     27 #
     28 
     29 package Block;
     30 
     31 # Sample code:
     32 #   my $outer = new Block("Free Name 1", "namespace Foo {", "} // namespace Foo");
     33 #   $outer->add("    void foo() {}");
     34 #   my $inner = new Block("Free Name 2", "namespace Bar {", "} // namespace Bar");
     35 #   $inner->add("    void bar() {}");
     36 #   $outer->add($inner);
     37 #   print $outer->toString();
     38 #
     39 # Output code:
     40 #   namespace Foo {
     41 #       void foo() {}
     42 #   namespace Bar {
     43 #       void bar() {}
     44 #   } // namespace Bar
     45 #   } // namespace Foo
     46 
     47 sub new
     48 {
     49     my $package = shift;
     50     my $name = shift || "Anonymous block";
     51     my $header = shift || "";
     52     my $footer = shift || "";
     53 
     54     my $object = {
     55         "name" => $name,
     56         "header" => [$header],
     57         "footer" => [$footer],
     58         "contents" => [],
     59     };
     60     bless $object, $package;
     61     return $object;
     62 }
     63 
     64 sub addHeader
     65 {
     66     my $object = shift;
     67     my $header = shift || "";
     68 
     69     push(@{$object->{header}}, $header);
     70 }
     71 
     72 sub addFooter
     73 {
     74     my $object = shift;
     75     my $footer = shift || "";
     76 
     77     push(@{$object->{footer}}, $footer);
     78 }
     79 
     80 sub add
     81 {
     82     my $object = shift;
     83     my $content = shift || "";
     84 
     85     push(@{$object->{contents}}, $content);
     86 }
     87 
     88 sub toString
     89 {
     90     my $object = shift;
     91 
     92     my $header = join "", @{$object->{header}};
     93     my $footer = join "", @{$object->{footer}};
     94     my $code = "";
     95     $code .= "/* BEGIN " . $object->{name} . " */\n" if $verbose;
     96     $code .=  $header . "\n" if $header;
     97     for my $content (@{$object->{contents}}) {
     98         if (ref($content) eq "Block") {
     99             $code .= $content->toString();
    100         } else {
    101             $code .= $content;
    102         }
    103     }
    104     $code .=  $footer . "\n" if $footer;
    105     $code .= "/* END " . $object->{name} . " */\n" if $verbose;
    106     return $code;
    107 }
    108 
    109 
    110 package deprecated_code_generator_v8;
    111 
    112 use strict;
    113 use Cwd;
    114 use File::Basename;
    115 use File::Find;
    116 use File::Spec;
    117 
    118 my $idlDocument;
    119 my $idlDirectories;
    120 my $preprocessor;
    121 my $verbose;
    122 my $interfaceIdlFiles;
    123 my $writeFileOnlyIfChanged;
    124 my $sourceRoot;
    125 
    126 # Cache of IDL file pathnames.
    127 my $idlFiles;
    128 my $cachedInterfaces = {};
    129 
    130 my %implIncludes = ();
    131 my %headerIncludes = ();
    132 
    133 # Header code structure:
    134 # Root                    ... Copyright, include duplication check
    135 #   Conditional           ... #if FEATURE ... #endif  (to be removed soon)
    136 #     Includes
    137 #     NameSpaceWebCore
    138 #       Class
    139 #         ClassPublic
    140 #         ClassPrivate
    141 my %header;
    142 
    143 # Implementation code structure:
    144 # Root                    ... Copyright
    145 #   Conditional           ... #if FEATURE ... #endif  (to be removed soon)
    146 #     Includes
    147 #     NameSpaceWebCore
    148 #     NameSpaceInternal   ... namespace ${implClassName}V8Internal in case of non-callback
    149 my %implementation;
    150 
    151 my %primitiveTypeHash = ("boolean" => 1,
    152                          "void" => 1,
    153                          "Date" => 1,
    154                          "byte" => 1,
    155                          "octet" => 1,
    156                          "short" => 1,
    157                          "long" => 1,
    158                          "long long" => 1,
    159                          "unsigned short" => 1,
    160                          "unsigned long" => 1,
    161                          "unsigned long long" => 1,
    162                          "float" => 1,
    163                          "double" => 1,
    164                         );
    165 
    166 my %nonWrapperTypes = ("CompareHow" => 1,
    167                        "DOMTimeStamp" => 1,
    168                        "Dictionary" => 1,
    169                        "EventListener" => 1,
    170                        "EventHandler" => 1,
    171                        "MediaQueryListListener" => 1,
    172                        "NodeFilter" => 1,
    173                        "SerializedScriptValue" => 1,
    174                        "any" => 1,
    175                       );
    176 
    177 my %typedArrayHash = ("ArrayBuffer" => [],
    178                       "ArrayBufferView" => [],
    179                       "Uint8Array" => ["unsigned char", "v8::kExternalUnsignedByteArray"],
    180                       "Uint8ClampedArray" => ["unsigned char", "v8::kExternalPixelArray"],
    181                       "Uint16Array" => ["unsigned short", "v8::kExternalUnsignedShortArray"],
    182                       "Uint32Array" => ["unsigned int", "v8::kExternalUnsignedIntArray"],
    183                       "Int8Array" => ["signed char", "v8::kExternalByteArray"],
    184                       "Int16Array" => ["short", "v8::kExternalShortArray"],
    185                       "Int32Array" => ["int", "v8::kExternalIntArray"],
    186                       "Float32Array" => ["float", "v8::kExternalFloatArray"],
    187                       "Float64Array" => ["double", "v8::kExternalDoubleArray"],
    188                      );
    189 
    190 my %callbackFunctionTypeHash = ();
    191 
    192 my %enumTypeHash = ();
    193 
    194 my %svgAttributesInHTMLHash = ("class" => 1, "id" => 1, "onabort" => 1, "onclick" => 1,
    195                                "onerror" => 1, "onload" => 1, "onmousedown" => 1,
    196                                "onmouseenter" => 1, "onmouseleave" => 1,
    197                                "onmousemove" => 1, "onmouseout" => 1, "onmouseover" => 1,
    198                                "onmouseup" => 1, "onresize" => 1, "onscroll" => 1,
    199                                "onunload" => 1);
    200 
    201 my %svgTypeNeedingTearOff = (
    202     "SVGAngle" => "SVGPropertyTearOff<SVGAngle>",
    203     "SVGLength" => "SVGPropertyTearOff<SVGLength>",
    204     "SVGLengthList" => "SVGListPropertyTearOff<SVGLengthList>",
    205     "SVGMatrix" => "SVGPropertyTearOff<SVGMatrix>",
    206     "SVGNumber" => "SVGPropertyTearOff<SVGNumber>",
    207     "SVGNumberList" => "SVGListPropertyTearOff<SVGNumberList>",
    208     "SVGPathSegList" => "SVGPathSegListPropertyTearOff",
    209     "SVGPoint" => "SVGPropertyTearOff<SVGPoint>",
    210     "SVGPointList" => "SVGListPropertyTearOff<SVGPointList>",
    211     "SVGPreserveAspectRatio" => "SVGPropertyTearOff<SVGPreserveAspectRatio>",
    212     "SVGRect" => "SVGPropertyTearOff<SVGRect>",
    213     "SVGStringList" => "SVGStaticListPropertyTearOff<SVGStringList>",
    214     "SVGTransform" => "SVGPropertyTearOff<SVGTransform>",
    215     "SVGTransformList" => "SVGTransformListPropertyTearOff"
    216 );
    217 
    218 my %svgTypeWithWritablePropertiesNeedingTearOff = (
    219     "SVGPoint" => 1,
    220     "SVGMatrix" => 1
    221 );
    222 
    223 # Default .h template
    224 my $headerTemplate = <<EOF;
    225 /*
    226     This file is part of the Blink open source project.
    227     This file has been auto-generated by CodeGeneratorV8.pm. DO NOT MODIFY!
    228 
    229     This library is free software; you can redistribute it and/or
    230     modify it under the terms of the GNU Library General Public
    231     License as published by the Free Software Foundation; either
    232     version 2 of the License, or (at your option) any later version.
    233 
    234     This library is distributed in the hope that it will be useful,
    235     but WITHOUT ANY WARRANTY; without even the implied warranty of
    236     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    237     Library General Public License for more details.
    238 
    239     You should have received a copy of the GNU Library General Public License
    240     along with this library; see the file COPYING.LIB.  If not, write to
    241     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    242     Boston, MA 02111-1307, USA.
    243 */
    244 EOF
    245 
    246 sub new
    247 {
    248     my $object = shift;
    249     my $reference = { };
    250 
    251     $idlDocument = shift;
    252     $idlDirectories = shift;
    253     $preprocessor = shift;
    254     $verbose = shift;
    255     $interfaceIdlFiles = shift;
    256     $writeFileOnlyIfChanged = shift;
    257 
    258     $sourceRoot = getcwd();
    259 
    260     bless($reference, $object);
    261     return $reference;
    262 }
    263 
    264 
    265 sub IDLFileForInterface
    266 {
    267     my $interfaceName = shift;
    268 
    269     unless ($idlFiles) {
    270         my @directories = map { $_ = "$sourceRoot/$_" if -d "$sourceRoot/$_"; $_ } @$idlDirectories;
    271         push(@directories, ".");
    272 
    273         $idlFiles = { };
    274         foreach my $idlFile (@$interfaceIdlFiles) {
    275             $idlFiles->{fileparse(basename($idlFile), ".idl")} = $idlFile;
    276         }
    277 
    278         my $wanted = sub {
    279             $idlFiles->{$1} = $File::Find::name if /^([A-Z].*)\.idl$/;
    280             $File::Find::prune = 1 if /^\../;
    281         };
    282         find($wanted, @directories);
    283     }
    284 
    285     return $idlFiles->{$interfaceName};
    286 }
    287 
    288 sub ParseInterface
    289 {
    290     my $interfaceName = shift;
    291 
    292     if (exists $cachedInterfaces->{$interfaceName}) {
    293         return $cachedInterfaces->{$interfaceName};
    294     }
    295 
    296     # Step #1: Find the IDL file associated with 'interface'
    297     my $filename = IDLFileForInterface($interfaceName)
    298       or die("Could NOT find IDL file for interface \"$interfaceName\" $!\n");
    299 
    300     print "  |  |>  Parsing parent IDL \"$filename\" for interface \"$interfaceName\"\n" if $verbose;
    301 
    302     # Step #2: Parse the found IDL file (in quiet mode).
    303     my $parser = deprecated_idl_parser->new(1);
    304     my $document = $parser->Parse($filename, $preprocessor);
    305 
    306     foreach my $interface (@{$document->interfaces}) {
    307         if ($interface->name eq $interfaceName or $interface->isPartial) {
    308             $cachedInterfaces->{$interfaceName} = $interface;
    309             return $interface;
    310         }
    311     }
    312 
    313     die("Could NOT find interface definition for $interfaceName in $filename");
    314 }
    315 
    316 sub GenerateInterface
    317 {
    318     my $object = shift;
    319     my $interface = shift;
    320 
    321     %callbackFunctionTypeHash = map { $_->name => $_ } @{$idlDocument->callbackFunctions};
    322     %enumTypeHash = map { $_->name => $_->values } @{$idlDocument->enumerations};
    323     my $v8ClassName = GetV8ClassName($interface);
    324     my $defineName = $v8ClassName . "_h";
    325     my $internalNamespace = GetImplName($interface) . "V8Internal";
    326 
    327     my $conditionalString = GenerateConditionalString($interface);
    328     my $conditionalIf = "";
    329     my $conditionalEndif = "";
    330     if ($conditionalString) {
    331         $conditionalIf = "#if ${conditionalString}";
    332         $conditionalEndif = "#endif // ${conditionalString}";
    333     }
    334 
    335     $header{root} = new Block("ROOT", "", "");
    336     # FIXME: newlines should be generated by Block::toString().
    337     $header{conditional} = new Block("Conditional", "$conditionalIf", $conditionalEndif ? "$conditionalEndif\n" : "");
    338     $header{includes} = new Block("Includes", "", "");
    339     $header{nameSpaceWebCore} = new Block("Namespace WebCore", "\nnamespace WebCore {\n", "}\n");
    340     $header{class} = new Block("Class definition", "", "");
    341     $header{classPublic} = new Block("Class public:", "public:", "");
    342     $header{classPrivate} = new Block("Class private:", "private:", "");
    343 
    344     $header{root}->add($header{conditional});
    345     $header{conditional}->add($header{includes});
    346     $header{conditional}->add($header{nameSpaceWebCore});
    347     $header{nameSpaceWebCore}->add($header{class});
    348     $header{class}->add($header{classPublic});
    349     $header{class}->add($header{classPrivate});
    350 
    351     # - Add default header template
    352     $header{root}->addHeader($headerTemplate . "\n");
    353     $header{root}->addHeader("#ifndef $defineName\n#define $defineName\n");
    354     $header{root}->addFooter("#endif // $defineName");
    355 
    356     $implementation{root} = new Block("ROOT", "", "");
    357     $conditionalEndif = "\n$conditionalEndif" if !$interface->isCallback and $conditionalEndif;
    358     $implementation{conditional} = new Block("Conditional", $conditionalIf, $conditionalEndif);
    359     $implementation{includes} = new Block("Includes", "", "");
    360 
    361     # FIXME: newlines should be generated by Block::toString().
    362     my $nameSpaceWebCoreBegin = "namespace WebCore {\n";
    363     my $nameSpaceWebCoreEnd = "} // namespace WebCore";
    364     $nameSpaceWebCoreBegin = "$nameSpaceWebCoreBegin\n" if !$interface->isCallback;
    365     $nameSpaceWebCoreEnd = "\n$nameSpaceWebCoreEnd\n" if $interface->isCallback;
    366     $implementation{nameSpaceWebCore} = new Block("Namespace WebCore", $nameSpaceWebCoreBegin, $nameSpaceWebCoreEnd);
    367     $implementation{nameSpaceInternal} = new Block("Internal namespace", "namespace $internalNamespace {\n", "} // namespace $internalNamespace\n");
    368 
    369     $implementation{root}->add($implementation{conditional});
    370     $implementation{conditional}->add($implementation{includes});
    371     $implementation{conditional}->add($implementation{nameSpaceWebCore});
    372     if (!$interface->isCallback) {
    373         $implementation{nameSpaceWebCore}->add($implementation{nameSpaceInternal});
    374     }
    375 
    376     # - Add default header template
    377     $implementation{root}->addHeader($headerTemplate);
    378     $implementation{root}->addHeader("\n#include \"config.h\"");
    379     $implementation{includes}->add("#include \"${v8ClassName}.h\"\n\n");
    380 
    381     # Start actual generation
    382     if ($interface->isCallback) {
    383         $object->GenerateCallbackHeader($interface);
    384         $object->GenerateCallbackImplementation($interface);
    385     } else {
    386         $object->GenerateHeader($interface);
    387         $object->GenerateImplementation($interface);
    388     }
    389 }
    390 
    391 sub AddToImplIncludes
    392 {
    393     my $header = shift;
    394     $implIncludes{$header} = 1;
    395 }
    396 
    397 sub AddToHeaderIncludes
    398 {
    399     my @includes = @_;
    400 
    401     for my $include (@includes) {
    402         $headerIncludes{$include} = 1;
    403     }
    404 }
    405 
    406 sub SkipIncludeHeader
    407 {
    408     my $type = shift;
    409 
    410     return 1 if IsPrimitiveType($type);
    411     return 1 if IsEnumType($type);
    412     return 1 if IsCallbackFunctionType($type);
    413     return 1 if $type eq "DOMString";
    414     return 0;
    415 }
    416 
    417 sub AddIncludesForType
    418 {
    419     my $type = shift;
    420 
    421     return if SkipIncludeHeader($type);
    422 
    423     # Default includes
    424     if ($type eq "EventListener" or $type eq "EventHandler") {
    425         AddToImplIncludes("core/dom/EventListener.h");
    426     } elsif ($type eq "SerializedScriptValue") {
    427         AddToImplIncludes("bindings/v8/SerializedScriptValue.h");
    428     } elsif ($type eq "any" || IsCallbackFunctionType($type)) {
    429         AddToImplIncludes("bindings/v8/ScriptValue.h");
    430     } elsif (IsTypedArrayType($type)) {
    431         AddToImplIncludes("bindings/v8/custom/V8${type}Custom.h");
    432     } else {
    433         AddToImplIncludes("V8${type}.h");
    434     }
    435 }
    436 
    437 sub HeaderFilesForInterface
    438 {
    439     my $interfaceName = shift;
    440     my $implClassName = shift;
    441 
    442     my @includes = ();
    443     if (IsTypedArrayType($interfaceName)) {
    444         push(@includes, "wtf/${interfaceName}.h");
    445     } elsif (!SkipIncludeHeader($interfaceName)) {
    446         my $idlFilename = IDLFileForInterface($interfaceName) or die("Could NOT find IDL file for interface \"$interfaceName\" $!\n");
    447         my $idlRelPath= "bindings/" . File::Spec->abs2rel($idlFilename, $sourceRoot);
    448         push(@includes, dirname($idlRelPath) . "/" . $implClassName . ".h");
    449     }
    450     return @includes;
    451 }
    452 
    453 sub NeedsOpaqueRootForGC
    454 {
    455     my $interface = shift;
    456     return $interface->extendedAttributes->{"GenerateIsReachable"} || $interface->extendedAttributes->{"CustomIsReachable"};
    457 }
    458 
    459 sub GenerateOpaqueRootForGC
    460 {
    461     my $interface = shift;
    462     my $implClassName = GetImplName($interface);
    463     my $v8ClassName = GetV8ClassName($interface);
    464 
    465     if ($interface->extendedAttributes->{"CustomIsReachable"}) {
    466         return;
    467     }
    468 
    469     my $code = <<END;
    470 void* ${v8ClassName}::opaqueRootForGC(void* object, v8::Isolate* isolate)
    471 {
    472     ${implClassName}* impl = fromInternalPointer(object);
    473 END
    474     my $isReachableMethod = $interface->extendedAttributes->{"GenerateIsReachable"};
    475     if ($isReachableMethod) {
    476         AddToImplIncludes("bindings/v8/V8GCController.h");
    477         AddToImplIncludes("core/dom/Element.h");
    478         $code .= <<END;
    479     if (Node* owner = impl->${isReachableMethod}())
    480         return V8GCController::opaqueRootForGC(owner, isolate);
    481 END
    482     }
    483 
    484     $code .= <<END;
    485     return object;
    486 }
    487 
    488 END
    489     $implementation{nameSpaceWebCore}->add($code);
    490 }
    491 
    492 sub GetSVGPropertyTypes
    493 {
    494     my $implType = shift;
    495 
    496     my $svgPropertyType;
    497     my $svgListPropertyType;
    498     my $svgNativeType;
    499 
    500     return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $implType =~ /SVG/;
    501 
    502     $svgNativeType = GetSVGTypeNeedingTearOff($implType);
    503     return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $svgNativeType;
    504 
    505     # Append space to avoid compilation errors when using  PassRefPtr<$svgNativeType>
    506     $svgNativeType = "$svgNativeType ";
    507 
    508     my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($implType);
    509     if ($svgNativeType =~ /SVGPropertyTearOff/) {
    510         $svgPropertyType = $svgWrappedNativeType;
    511         AddToHeaderIncludes("core/svg/properties/SVGAnimatedPropertyTearOff.h");
    512     } elsif ($svgNativeType =~ /SVGListPropertyTearOff/ or $svgNativeType =~ /SVGStaticListPropertyTearOff/ or $svgNativeType =~ /SVGTransformListPropertyTearOff/) {
    513         $svgListPropertyType = $svgWrappedNativeType;
    514         AddToHeaderIncludes("core/svg/properties/SVGAnimatedListPropertyTearOff.h");
    515     } elsif ($svgNativeType =~ /SVGPathSegListPropertyTearOff/) {
    516         $svgListPropertyType = $svgWrappedNativeType;
    517         AddToHeaderIncludes("core/svg/properties/SVGPathSegListPropertyTearOff.h");
    518     }
    519 
    520     return ($svgPropertyType, $svgListPropertyType, $svgNativeType);
    521 }
    522 
    523 sub GetIndexedGetterFunction
    524 {
    525     my $interface = shift;
    526 
    527     # FIXME: Expose indexed getter of CSSMixFunctionValue by removing this special case
    528     # because CSSValueList(which is parent of CSSMixFunctionValue) has indexed property getter.
    529     if ($interface->name eq "CSSMixFunctionValue") {
    530         return 0;
    531     }
    532 
    533     return GetSpecialAccessorFunctionForType($interface, "getter", "unsigned long", 1);
    534 }
    535 
    536 sub GetIndexedSetterFunction
    537 {
    538     my $interface = shift;
    539 
    540     return GetSpecialAccessorFunctionForType($interface, "setter", "unsigned long", 2);
    541 }
    542 
    543 sub GetIndexedDeleterFunction
    544 {
    545     my $interface = shift;
    546 
    547     return GetSpecialAccessorFunctionForType($interface, "deleter", "unsigned long", 1);
    548 }
    549 
    550 sub GetNamedGetterFunction
    551 {
    552     my $interface = shift;
    553     return GetSpecialAccessorFunctionForType($interface, "getter", "DOMString", 1);
    554 }
    555 
    556 sub GetNamedSetterFunction
    557 {
    558     my $interface = shift;
    559     return GetSpecialAccessorFunctionForType($interface, "setter", "DOMString", 2);
    560 }
    561 
    562 sub GetNamedDeleterFunction
    563 {
    564     my $interface = shift;
    565     return GetSpecialAccessorFunctionForType($interface, "deleter", "DOMString", 1);
    566 }
    567 
    568 sub GetSpecialAccessorFunctionForType
    569 {
    570     my $interface = shift;
    571     my $special = shift;
    572     my $firstParameterType = shift;
    573     my $numberOfParameters = shift;
    574 
    575     foreach my $function (@{$interface->functions}) {
    576         my $specials = $function->specials;
    577         my $specialExists = grep { $_ eq $special } @$specials;
    578         my $parameters = $function->parameters;
    579         if ($specialExists and scalar(@$parameters) == $numberOfParameters and $parameters->[0]->type eq $firstParameterType) {
    580             return $function;
    581         }
    582     }
    583 
    584     return 0;
    585 }
    586 
    587 sub GenerateHeader
    588 {
    589     my $object = shift;
    590     my $interface = shift;
    591 
    592     my $interfaceName = $interface->name;
    593     my $implClassName = GetImplName($interface);
    594     my $v8ClassName = GetV8ClassName($interface);
    595 
    596     LinkOverloadedFunctions($interface);
    597 
    598     # Ensure the IsDOMNodeType function is in sync.
    599     die("IsDOMNodeType is out of date with respect to $interfaceName") if IsDOMNodeType($interfaceName) != InheritsInterface($interface, "Node");
    600 
    601     my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($interfaceName);
    602 
    603     my $parentInterface = $interface->parent;
    604     AddToHeaderIncludes("V8${parentInterface}.h") if $parentInterface;
    605     AddToHeaderIncludes("bindings/v8/WrapperTypeInfo.h");
    606     AddToHeaderIncludes("bindings/v8/V8Binding.h");
    607     AddToHeaderIncludes("bindings/v8/V8DOMWrapper.h");
    608     AddToHeaderIncludes(HeaderFilesForInterface($interfaceName, $implClassName));
    609     foreach my $headerInclude (sort keys(%headerIncludes)) {
    610         $header{includes}->add("#include \"${headerInclude}\"\n");
    611     }
    612 
    613     $header{nameSpaceWebCore}->addHeader("\ntemplate<typename PropertyType> class SVGPropertyTearOff;\n") if $svgPropertyType;
    614     if ($svgNativeType) {
    615         if ($svgNativeType =~ /SVGStaticListPropertyTearOff/) {
    616             $header{nameSpaceWebCore}->addHeader("\ntemplate<typename PropertyType> class SVGStaticListPropertyTearOff;\n");
    617         } else {
    618             $header{nameSpaceWebCore}->addHeader("\ntemplate<typename PropertyType> class SVGListPropertyTearOff;\n");
    619         }
    620     }
    621 
    622     $header{nameSpaceWebCore}->addHeader("\nclass Dictionary;") if IsConstructorTemplate($interface, "Event");
    623 
    624     my $nativeType = GetNativeTypeForConversions($interface);
    625     if ($interface->extendedAttributes->{"NamedConstructor"}) {
    626         $header{nameSpaceWebCore}->addHeader(<<END);
    627 
    628 class V8${nativeType}Constructor {
    629 public:
    630     static v8::Handle<v8::FunctionTemplate> GetTemplate(v8::Isolate*, WrapperWorldType);
    631     static WrapperTypeInfo info;
    632 };
    633 END
    634     }
    635 
    636     $header{class}->addHeader("class $v8ClassName {");
    637     $header{class}->addFooter("};");
    638 
    639     $header{classPublic}->add(<<END);
    640     static bool HasInstance(v8::Handle<v8::Value>, v8::Isolate*, WrapperWorldType);
    641     static bool HasInstanceInAnyWorld(v8::Handle<v8::Value>, v8::Isolate*);
    642     static v8::Handle<v8::FunctionTemplate> GetTemplate(v8::Isolate*, WrapperWorldType);
    643     static ${nativeType}* toNative(v8::Handle<v8::Object> object)
    644     {
    645         return fromInternalPointer(object->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex));
    646     }
    647     static void derefObject(void*);
    648     static WrapperTypeInfo info;
    649 END
    650 
    651     if (NeedsOpaqueRootForGC($interface)) {
    652         $header{classPublic}->add("    static void* opaqueRootForGC(void*, v8::Isolate*);\n");
    653     }
    654 
    655     if (InheritsExtendedAttribute($interface, "ActiveDOMObject")) {
    656         $header{classPublic}->add("    static ActiveDOMObject* toActiveDOMObject(v8::Handle<v8::Object>);\n");
    657     }
    658 
    659     if (InheritsInterface($interface, "EventTarget")) {
    660         $header{classPublic}->add("    static EventTarget* toEventTarget(v8::Handle<v8::Object>);\n");
    661     }
    662 
    663     if ($interfaceName eq "Window") {
    664         $header{classPublic}->add(<<END);
    665     static v8::Handle<v8::ObjectTemplate> GetShadowObjectTemplate(v8::Isolate*, WrapperWorldType);
    666 END
    667     }
    668 
    669     my @enabledPerContextFunctions;
    670     foreach my $function (@{$interface->functions}) {
    671         my $name = $function->name;
    672         next if $name eq "";
    673         my $attrExt = $function->extendedAttributes;
    674 
    675         if (HasCustomMethod($attrExt) && $function->{overloadIndex} == 1) {
    676             my $conditionalString = GenerateConditionalString($function);
    677             $header{classPublic}->add("#if ${conditionalString}\n") if $conditionalString;
    678             $header{classPublic}->add(<<END);
    679     static void ${name}MethodCustom(const v8::FunctionCallbackInfo<v8::Value>&);
    680 END
    681             $header{classPublic}->add("#endif // ${conditionalString}\n") if $conditionalString;
    682         }
    683         if ($attrExt->{"EnabledPerContext"}) {
    684             push(@enabledPerContextFunctions, $function);
    685         }
    686     }
    687 
    688     if (IsConstructable($interface)) {
    689         $header{classPublic}->add("    static void constructorCallback(const v8::FunctionCallbackInfo<v8::Value>&);\n");
    690 END
    691     }
    692     if (HasCustomConstructor($interface)) {
    693         $header{classPublic}->add("    static void constructorCustom(const v8::FunctionCallbackInfo<v8::Value>&);\n");
    694     }
    695 
    696     my @enabledPerContextAttributes;
    697     foreach my $attribute (@{$interface->attributes}) {
    698         my $name = $attribute->name;
    699         my $attrExt = $attribute->extendedAttributes;
    700         my $conditionalString = GenerateConditionalString($attribute);
    701         if (HasCustomGetter($attrExt) && !$attrExt->{"ImplementedBy"}) {
    702             $header{classPublic}->add("#if ${conditionalString}\n") if $conditionalString;
    703             $header{classPublic}->add(<<END);
    704     static void ${name}AttrGetterCustom(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>&);
    705 END
    706             $header{classPublic}->add("#endif // ${conditionalString}\n") if $conditionalString;
    707         }
    708         if (HasCustomSetter($attrExt) && !$attrExt->{"ImplementedBy"}) {
    709             $header{classPublic}->add("#if ${conditionalString}\n") if $conditionalString;
    710             $header{classPublic}->add(<<END);
    711     static void ${name}AttrSetterCustom(v8::Local<v8::String> name, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<void>&);
    712 END
    713             $header{classPublic}->add("#endif // ${conditionalString}\n") if $conditionalString;
    714         }
    715         if ($attrExt->{"EnabledPerContext"}) {
    716             push(@enabledPerContextAttributes, $attribute);
    717         }
    718     }
    719 
    720     GenerateHeaderNamedAndIndexedPropertyAccessors($interface);
    721     GenerateHeaderLegacyCall($interface);
    722     GenerateHeaderCustomInternalFieldIndices($interface);
    723 
    724     my $toWrappedType;
    725     my $fromWrappedType;
    726     if ($interface->parent) {
    727         my $v8ParentClassName = "V8" . $interface->parent;
    728         $toWrappedType = "${v8ParentClassName}::toInternalPointer(impl)";
    729         $fromWrappedType = "static_cast<${nativeType}*>(${v8ParentClassName}::fromInternalPointer(object))";
    730     } else {
    731         $toWrappedType = "impl";
    732         $fromWrappedType = "static_cast<${nativeType}*>(object)";
    733     }
    734 
    735     $header{classPublic}->add(<<END);
    736     static inline void* toInternalPointer(${nativeType}* impl)
    737     {
    738         return $toWrappedType;
    739     }
    740 
    741     static inline ${nativeType}* fromInternalPointer(void* object)
    742     {
    743         return $fromWrappedType;
    744     }
    745 END
    746 
    747     if ($interface->name eq "Window") {
    748         $header{classPublic}->add(<<END);
    749     static bool namedSecurityCheckCustom(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType, v8::Local<v8::Value> data);
    750     static bool indexedSecurityCheckCustom(v8::Local<v8::Object> host, uint32_t index, v8::AccessType, v8::Local<v8::Value> data);
    751 END
    752     }
    753 
    754     if (@enabledPerContextAttributes) {
    755         $header{classPublic}->add(<<END);
    756     static void installPerContextProperties(v8::Handle<v8::Object>, ${nativeType}*, v8::Isolate*);
    757 END
    758     } else {
    759         $header{classPublic}->add(<<END);
    760     static void installPerContextProperties(v8::Handle<v8::Object>, ${nativeType}*, v8::Isolate*) { }
    761 END
    762     }
    763 
    764     if (@enabledPerContextFunctions) {
    765         $header{classPublic}->add(<<END);
    766     static void installPerContextPrototypeProperties(v8::Handle<v8::Object>, v8::Isolate*);
    767 END
    768     } else {
    769         $header{classPublic}->add(<<END);
    770     static void installPerContextPrototypeProperties(v8::Handle<v8::Object>, v8::Isolate*) { }
    771 END
    772     }
    773 
    774     if ($interfaceName eq "HTMLElement") {
    775         $header{classPublic}->add(<<END);
    776     friend v8::Handle<v8::Object> createV8HTMLWrapper(HTMLElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
    777     friend v8::Handle<v8::Object> createV8HTMLDirectWrapper(HTMLElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
    778 END
    779     } elsif ($interfaceName eq "SVGElement") {
    780         $header{classPublic}->add(<<END);
    781     friend v8::Handle<v8::Object> createV8SVGWrapper(SVGElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
    782     friend v8::Handle<v8::Object> createV8SVGDirectWrapper(SVGElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
    783     friend v8::Handle<v8::Object> createV8SVGFallbackWrapper(SVGElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
    784 END
    785     } elsif ($interfaceName eq "HTMLUnknownElement") {
    786         $header{classPublic}->add(<<END);
    787     friend v8::Handle<v8::Object> createV8HTMLFallbackWrapper(HTMLUnknownElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
    788 END
    789     } elsif ($interfaceName eq "Element") {
    790         $header{classPublic}->add(<<END);
    791     // This is a performance optimization hack. See V8Element::wrap.
    792     friend v8::Handle<v8::Object> wrap(Node*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
    793 END
    794     }
    795 
    796     my $noToV8 = $interface->extendedAttributes->{"DoNotGenerateToV8"};
    797     my $noWrap = $interface->extendedAttributes->{"DoNotGenerateWrap"} || $noToV8;
    798     if (!$noWrap) {
    799         my $createWrapperArgumentType = GetPassRefPtrType($nativeType);
    800         $header{classPrivate}->add(<<END);
    801     friend v8::Handle<v8::Object> wrap(${nativeType}*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
    802     static v8::Handle<v8::Object> createWrapper(${createWrapperArgumentType}, v8::Handle<v8::Object> creationContext, v8::Isolate*);
    803 END
    804     }
    805 
    806     $header{nameSpaceWebCore}->add(<<END);
    807 
    808 template<>
    809 class WrapperTypeTraits<${nativeType} > {
    810 public:
    811     static WrapperTypeInfo* info() { return &${v8ClassName}::info; }
    812 };
    813 
    814 END
    815 
    816     my $customWrap = $interface->extendedAttributes->{"CustomToV8"};
    817     if ($noToV8) {
    818         die "Can't suppress toV8 for subclass\n" if $interface->parent;
    819     } elsif ($noWrap) {
    820         die "Must have custom toV8\n" if !$customWrap;
    821         $header{nameSpaceWebCore}->add(<<END);
    822 class ${nativeType};
    823 v8::Handle<v8::Value> toV8(${nativeType}*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
    824 v8::Handle<v8::Value> toV8ForMainWorld(${nativeType}*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
    825 
    826 template<class CallbackInfo, class Wrappable>
    827 inline v8::Handle<v8::Value> toV8Fast(${nativeType}* impl, const CallbackInfo& callbackInfo, Wrappable*)
    828 {
    829     return toV8(impl, callbackInfo.Holder(), callbackInfo.GetIsolate());
    830 }
    831 
    832 END
    833     } else {
    834 
    835         my $createWrapperCall = $customWrap ? "${v8ClassName}::wrap" : "${v8ClassName}::createWrapper";
    836 
    837         if ($customWrap) {
    838             $header{nameSpaceWebCore}->add(<<END);
    839 
    840 v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate*);
    841 END
    842         } else {
    843             $header{nameSpaceWebCore}->add(<<END);
    844 
    845 inline v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
    846 {
    847     ASSERT(impl);
    848     ASSERT(DOMDataStore::getWrapper<${v8ClassName}>(impl, isolate).IsEmpty());
    849     return $createWrapperCall(impl, creationContext, isolate);
    850 }
    851 END
    852         }
    853 
    854         $header{nameSpaceWebCore}->add(<<END);
    855 
    856 inline v8::Handle<v8::Value> toV8(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
    857 {
    858     if (UNLIKELY(!impl))
    859         return v8NullWithCheck(isolate);
    860     v8::Handle<v8::Value> wrapper = DOMDataStore::getWrapper<${v8ClassName}>(impl, isolate);
    861     if (!wrapper.IsEmpty())
    862         return wrapper;
    863     return wrap(impl, creationContext, isolate);
    864 }
    865 
    866 inline v8::Handle<v8::Value> toV8ForMainWorld(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
    867 {
    868     ASSERT(worldType(isolate) == MainWorld);
    869     if (UNLIKELY(!impl))
    870         return v8::Null(isolate);
    871     v8::Handle<v8::Value> wrapper = DOMDataStore::getWrapperForMainWorld<${v8ClassName}>(impl);
    872     if (!wrapper.IsEmpty())
    873         return wrapper;
    874     return wrap(impl, creationContext, isolate);
    875 }
    876 
    877 template<class CallbackInfo, class Wrappable>
    878 inline v8::Handle<v8::Value> toV8Fast(${nativeType}* impl, const CallbackInfo& callbackInfo, Wrappable* wrappable)
    879 {
    880     if (UNLIKELY(!impl))
    881         return v8::Null(callbackInfo.GetIsolate());
    882     v8::Handle<v8::Object> wrapper = DOMDataStore::getWrapperFast<${v8ClassName}>(impl, callbackInfo, wrappable);
    883     if (!wrapper.IsEmpty())
    884         return wrapper;
    885     return wrap(impl, callbackInfo.Holder(), callbackInfo.GetIsolate());
    886 }
    887 
    888 inline v8::Handle<v8::Value> toV8ForMainWorld(PassRefPtr< ${nativeType} > impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
    889 {
    890     return toV8ForMainWorld(impl.get(), creationContext, isolate);
    891 }
    892 
    893 END
    894     }
    895 
    896     $header{nameSpaceWebCore}->add(<<END);
    897 
    898 template<class CallbackInfo, class Wrappable>
    899 inline v8::Handle<v8::Value> toV8Fast(PassRefPtr< ${nativeType} > impl, const CallbackInfo& callbackInfo, Wrappable* wrappable)
    900 {
    901     return toV8Fast(impl.get(), callbackInfo, wrappable);
    902 }
    903 
    904 inline v8::Handle<v8::Value> toV8(PassRefPtr< ${nativeType} > impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
    905 {
    906     return toV8(impl.get(), creationContext, isolate);
    907 }
    908 
    909 END
    910 
    911     if (IsConstructorTemplate($interface, "Event")) {
    912         $header{nameSpaceWebCore}->add("bool fill${implClassName}Init(${implClassName}Init&, const Dictionary&);\n\n");
    913     }
    914 }
    915 
    916 sub GetInternalFields
    917 {
    918     my $interface = shift;
    919 
    920     my @customInternalFields = ();
    921     # Event listeners on DOM nodes are explicitly supported in the GC controller.
    922     if (!InheritsInterface($interface, "Node") &&
    923         InheritsInterface($interface, "EventTarget")) {
    924         push(@customInternalFields, "eventListenerCacheIndex");
    925     }
    926     return @customInternalFields;
    927 }
    928 
    929 sub GenerateHeaderCustomInternalFieldIndices
    930 {
    931     my $interface = shift;
    932     my @customInternalFields = GetInternalFields($interface);
    933     my $customFieldCounter = 0;
    934     foreach my $customInternalField (@customInternalFields) {
    935         $header{classPublic}->add(<<END);
    936     static const int ${customInternalField} = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
    937 END
    938         $customFieldCounter++;
    939     }
    940     $header{classPublic}->add(<<END);
    941     static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
    942 END
    943 }
    944 
    945 sub GenerateHeaderNamedAndIndexedPropertyAccessors
    946 {
    947     my $interface = shift;
    948 
    949     my $indexedGetterFunction = GetIndexedGetterFunction($interface);
    950     my $hasCustomIndexedGetter = $indexedGetterFunction && $indexedGetterFunction->extendedAttributes->{"Custom"};
    951 
    952     my $indexedSetterFunction = GetIndexedSetterFunction($interface);
    953     my $hasCustomIndexedSetter = $indexedSetterFunction && $indexedSetterFunction->extendedAttributes->{"Custom"};
    954 
    955     my $indexedDeleterFunction = GetIndexedDeleterFunction($interface);
    956     my $hasCustomIndexedDeleters = $indexedDeleterFunction && $indexedDeleterFunction->extendedAttributes->{"Custom"};
    957 
    958     my $namedGetterFunction = GetNamedGetterFunction($interface);
    959     my $hasCustomNamedGetter = $namedGetterFunction && $namedGetterFunction->extendedAttributes->{"Custom"};
    960 
    961     my $namedSetterFunction = GetNamedSetterFunction($interface);
    962     my $hasCustomNamedSetter = $namedSetterFunction && $namedSetterFunction->extendedAttributes->{"Custom"};
    963 
    964     my $namedDeleterFunction = GetNamedDeleterFunction($interface);
    965     my $hasCustomNamedDeleter = $namedDeleterFunction && $namedDeleterFunction->extendedAttributes->{"Custom"};
    966 
    967     my $namedEnumeratorFunction = $namedGetterFunction && !$namedGetterFunction->extendedAttributes->{"NotEnumerable"};
    968     my $hasCustomNamedEnumerator = $namedGetterFunction && $namedGetterFunction->extendedAttributes->{"CustomEnumerateProperty"};
    969 
    970     if ($hasCustomIndexedGetter) {
    971         $header{classPublic}->add("    static void indexedPropertyGetterCustom(uint32_t, const v8::PropertyCallbackInfo<v8::Value>&);\n");
    972     }
    973 
    974     if ($hasCustomIndexedSetter) {
    975         $header{classPublic}->add("    static void indexedPropertySetterCustom(uint32_t, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&);\n");
    976     }
    977 
    978     if ($hasCustomIndexedDeleters) {
    979         $header{classPublic}->add("    static void indexedPropertyDeleterCustom(uint32_t, const v8::PropertyCallbackInfo<v8::Boolean>&);\n");
    980     }
    981 
    982     if ($hasCustomNamedGetter) {
    983         $header{classPublic}->add("    static void namedPropertyGetterCustom(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>&);\n");
    984     }
    985 
    986     if ($hasCustomNamedSetter) {
    987         $header{classPublic}->add("    static void namedPropertySetterCustom(v8::Local<v8::String>, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&);\n");
    988     }
    989 
    990     if ($hasCustomNamedDeleter) {
    991         $header{classPublic}->add("    static void namedPropertyDeleterCustom(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Boolean>&);\n");
    992     }
    993 
    994     if ($hasCustomNamedEnumerator) {
    995         $header{classPublic}->add("    static void namedPropertyEnumeratorCustom(const v8::PropertyCallbackInfo<v8::Array>&);\n");
    996         $header{classPublic}->add("    static void namedPropertyQueryCustom(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Integer>&);\n");
    997     }
    998 }
    999 
   1000 sub GenerateHeaderLegacyCall
   1001 {
   1002     my $interface = shift;
   1003 
   1004     if ($interface->extendedAttributes->{"CustomLegacyCall"}) {
   1005         $header{classPublic}->add("    static void legacyCallCustom(const v8::FunctionCallbackInfo<v8::Value>&);\n");
   1006     }
   1007 }
   1008 
   1009 sub HasActivityLogging
   1010 {
   1011     my $forMainWorldSuffix = shift;
   1012     my $attrExt = shift;
   1013     my $access = shift;
   1014 
   1015     if (!$attrExt->{"ActivityLog"}) {
   1016         return 0;
   1017     }
   1018     my $logAllAccess = ($attrExt->{"ActivityLog"} =~ /^Access/);
   1019     my $logGetter = ($attrExt->{"ActivityLog"} =~ /^Getter/);
   1020     my $logSetter = ($attrExt->{"ActivityLog"} =~ /^Setter/);
   1021     my $logOnlyIsolatedWorlds = ($attrExt->{"ActivityLog"} =~ /ForIsolatedWorlds$/);
   1022 
   1023     if ($logOnlyIsolatedWorlds && $forMainWorldSuffix eq "ForMainWorld") {
   1024         return 0;
   1025     }
   1026     return $logAllAccess || ($logGetter && $access eq "Getter") || ($logSetter && $access eq "Setter");
   1027 }
   1028 
   1029 sub IsConstructable
   1030 {
   1031     my $interface = shift;
   1032 
   1033     return $interface->extendedAttributes->{"CustomConstructor"} || $interface->extendedAttributes->{"Constructor"} || $interface->extendedAttributes->{"ConstructorTemplate"};
   1034 }
   1035 
   1036 sub HasCustomConstructor
   1037 {
   1038     my $interface = shift;
   1039 
   1040     return $interface->extendedAttributes->{"CustomConstructor"};
   1041 }
   1042 
   1043 sub HasCustomGetter
   1044 {
   1045     my $attrExt = shift;
   1046     return $attrExt->{"Custom"} || $attrExt->{"CustomGetter"};
   1047 }
   1048 
   1049 sub HasCustomSetter
   1050 {
   1051     my $attrExt = shift;
   1052     return $attrExt->{"Custom"} || $attrExt->{"CustomSetter"};
   1053 }
   1054 
   1055 sub HasCustomMethod
   1056 {
   1057     my $attrExt = shift;
   1058     return $attrExt->{"Custom"};
   1059 }
   1060 
   1061 sub IsReadonly
   1062 {
   1063     my $attribute = shift;
   1064     my $attrExt = $attribute->extendedAttributes;
   1065     return $attribute->isReadOnly && !$attrExt->{"Replaceable"};
   1066 }
   1067 
   1068 sub GetV8ClassName
   1069 {
   1070     my $interface = shift;
   1071     return "V8" . $interface->name;
   1072 }
   1073 
   1074 sub GetImplName
   1075 {
   1076     my $interfaceOrAttributeOrFunction = shift;
   1077     return $interfaceOrAttributeOrFunction->extendedAttributes->{"ImplementedAs"} || $interfaceOrAttributeOrFunction->name;
   1078 }
   1079 
   1080 sub GetImplNameFromImplementedBy
   1081 {
   1082     my $implementedBy = shift;
   1083 
   1084     my $interface = ParseInterface($implementedBy);
   1085 
   1086     return $interface->extendedAttributes->{"ImplementedAs"} || $implementedBy;
   1087 }
   1088 
   1089 sub GenerateDomainSafeFunctionGetter
   1090 {
   1091     my $function = shift;
   1092     my $interface = shift;
   1093 
   1094     my $implClassName = GetImplName($interface);
   1095     my $v8ClassName = GetV8ClassName($interface);
   1096     my $funcName = $function->name;
   1097 
   1098     my $functionLength = GetFunctionLength($function);
   1099     my $signature = "v8::Signature::New(V8PerIsolateData::from(info.GetIsolate())->rawTemplate(&" . $v8ClassName . "::info, currentWorldType))";
   1100     if ($function->extendedAttributes->{"DoNotCheckSignature"}) {
   1101         $signature = "v8::Local<v8::Signature>()";
   1102     }
   1103 
   1104     my $newTemplateParams = "${implClassName}V8Internal::${funcName}MethodCallback, v8Undefined(), $signature";
   1105 
   1106     AddToImplIncludes("core/page/Frame.h");
   1107     AddToImplIncludes("bindings/v8/BindingSecurity.h");
   1108     $implementation{nameSpaceInternal}->add(<<END);
   1109 static void ${funcName}AttrGetter(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
   1110 {
   1111     // This is only for getting a unique pointer which we can pass to privateTemplate.
   1112     static const char* privateTemplateUniqueKey = "${funcName}PrivateTemplate";
   1113     WrapperWorldType currentWorldType = worldType(info.GetIsolate());
   1114     V8PerIsolateData* data = V8PerIsolateData::from(info.GetIsolate());
   1115     v8::Handle<v8::FunctionTemplate> privateTemplate = data->privateTemplate(currentWorldType, &privateTemplateUniqueKey, $newTemplateParams, $functionLength);
   1116 
   1117     v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(${v8ClassName}::GetTemplate(info.GetIsolate(), currentWorldType));
   1118     if (holder.IsEmpty()) {
   1119         // can only reach here by 'object.__proto__.func', and it should passed
   1120         // domain security check already
   1121         v8SetReturnValue(info, privateTemplate->GetFunction());
   1122         return;
   1123     }
   1124     ${implClassName}* imp = ${v8ClassName}::toNative(holder);
   1125     if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame(), DoNotReportSecurityError)) {
   1126         static const char* sharedTemplateUniqueKey = "${funcName}SharedTemplate";
   1127         v8::Handle<v8::FunctionTemplate> sharedTemplate = data->privateTemplate(currentWorldType, &sharedTemplateUniqueKey, $newTemplateParams, $functionLength);
   1128         v8SetReturnValue(info, sharedTemplate->GetFunction());
   1129         return;
   1130     }
   1131 
   1132     v8::Local<v8::Value> hiddenValue = info.This()->GetHiddenValue(name);
   1133     if (!hiddenValue.IsEmpty()) {
   1134         v8SetReturnValue(info, hiddenValue);
   1135         return;
   1136     }
   1137 
   1138     v8SetReturnValue(info, privateTemplate->GetFunction());
   1139 }
   1140 
   1141 END
   1142     $implementation{nameSpaceInternal}->add(<<END);
   1143 static void ${funcName}AttrGetterCallback(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
   1144 {
   1145     TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMGetter");
   1146     ${implClassName}V8Internal::${funcName}AttrGetter(name, info);
   1147     TRACE_EVENT_SET_SAMPLING_STATE("V8", "Execution");
   1148 }
   1149 
   1150 END
   1151 }
   1152 
   1153 sub GenerateDomainSafeFunctionSetter
   1154 {
   1155     my $interface = shift;
   1156 
   1157     my $implClassName = GetImplName($interface);
   1158     my $v8ClassName = GetV8ClassName($interface);
   1159 
   1160     AddToImplIncludes("bindings/v8/BindingSecurity.h");
   1161     $implementation{nameSpaceInternal}->add(<<END);
   1162 static void ${implClassName}DomainSafeFunctionSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)
   1163 {
   1164     v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(${v8ClassName}::GetTemplate(info.GetIsolate(), worldType(info.GetIsolate())));
   1165     if (holder.IsEmpty())
   1166         return;
   1167     ${implClassName}* imp = ${v8ClassName}::toNative(holder);
   1168     if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame()))
   1169         return;
   1170 
   1171     info.This()->SetHiddenValue(name, value);
   1172 }
   1173 
   1174 END
   1175 }
   1176 
   1177 sub GenerateConstructorGetter
   1178 {
   1179     my $interface = shift;
   1180     my $implClassName = GetImplName($interface);
   1181 
   1182     $implementation{nameSpaceInternal}->add(<<END);
   1183 static void ${implClassName}ConstructorGetter(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
   1184 {
   1185     v8::Handle<v8::Value> data = info.Data();
   1186     ASSERT(data->IsExternal());
   1187     V8PerContextData* perContextData = V8PerContextData::from(info.Holder()->CreationContext());
   1188     if (!perContextData)
   1189         return;
   1190     v8SetReturnValue(info, perContextData->constructorForType(WrapperTypeInfo::unwrap(data)));
   1191 }
   1192 END
   1193 }
   1194 
   1195 sub GenerateFeatureObservation
   1196 {
   1197     my $measureAs = shift;
   1198 
   1199     if ($measureAs) {
   1200         AddToImplIncludes("core/page/UseCounter.h");
   1201         return "    UseCounter::count(activeDOMWindow(), UseCounter::${measureAs});\n";
   1202     }
   1203 
   1204     return "";
   1205 }
   1206 
   1207 sub GenerateDeprecationNotification
   1208 {
   1209     my $deprecateAs = shift;
   1210     if ($deprecateAs) {
   1211         AddToImplIncludes("core/page/PageConsole.h");
   1212         AddToImplIncludes("core/page/UseCounter.h");
   1213         return "    UseCounter::countDeprecation(activeDOMWindow(), UseCounter::${deprecateAs});\n";
   1214     }
   1215     return "";
   1216 }
   1217 
   1218 sub GenerateActivityLogging
   1219 {
   1220     my $accessType = shift;
   1221     my $interface = shift;
   1222     my $propertyName = shift;
   1223 
   1224     my $interfaceName = $interface->name;
   1225 
   1226     AddToImplIncludes("bindings/v8/V8Binding.h");
   1227     AddToImplIncludes("bindings/v8/V8DOMActivityLogger.h");
   1228     AddToImplIncludes("wtf/Vector.h");
   1229 
   1230     my $code = "";
   1231     if ($accessType eq "Method") {
   1232         $code .= <<END;
   1233     V8PerContextData* contextData = V8PerContextData::from(args.GetIsolate()->GetCurrentContext());
   1234     if (contextData && contextData->activityLogger()) {
   1235         Vector<v8::Handle<v8::Value> > loggerArgs = toVectorOfArguments(args);
   1236         contextData->activityLogger()->log("${interfaceName}.${propertyName}", args.Length(), loggerArgs.data(), "${accessType}");
   1237     }
   1238 END
   1239     } elsif ($accessType eq "Setter") {
   1240         $code .= <<END;
   1241     V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->GetCurrentContext());
   1242     if (contextData && contextData->activityLogger()) {
   1243         v8::Handle<v8::Value> loggerArg[] = { value };
   1244         contextData->activityLogger()->log("${interfaceName}.${propertyName}", 1, &loggerArg[0], "${accessType}");
   1245     }
   1246 END
   1247     } elsif ($accessType eq "Getter") {
   1248         $code .= <<END;
   1249     V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->GetCurrentContext());
   1250     if (contextData && contextData->activityLogger())
   1251         contextData->activityLogger()->log("${interfaceName}.${propertyName}", 0, 0, "${accessType}");
   1252 END
   1253     } else {
   1254         die "Unrecognized activity logging access type";
   1255     }
   1256 
   1257     return $code;
   1258 }
   1259 
   1260 sub GenerateNormalAttrGetterCallback
   1261 {
   1262     my $attribute = shift;
   1263     my $interface = shift;
   1264     my $forMainWorldSuffix = shift;
   1265 
   1266     my $implClassName = GetImplName($interface);
   1267     my $v8ClassName = GetV8ClassName($interface);
   1268     my $attrExt = $attribute->extendedAttributes;
   1269     my $attrName = $attribute->name;
   1270 
   1271     my $conditionalString = GenerateConditionalString($attribute);
   1272     my $code = "";
   1273     $code .= "#if ${conditionalString}\n\n" if $conditionalString;
   1274 
   1275     $code .= "static void ${attrName}AttrGetterCallback${forMainWorldSuffix}(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
   1276     $code .= "{\n";
   1277     $code .= "    TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMGetter\");\n";
   1278     $code .= GenerateFeatureObservation($attrExt->{"MeasureAs"});
   1279     $code .= GenerateDeprecationNotification($attrExt->{"DeprecateAs"});
   1280     if (HasActivityLogging($forMainWorldSuffix, $attrExt, "Getter")) {
   1281         $code .= GenerateActivityLogging("Getter", $interface, "${attrName}");
   1282     }
   1283     if (HasCustomGetter($attrExt)) {
   1284         $code .= "    ${v8ClassName}::${attrName}AttrGetterCustom(name, info);\n";
   1285     } else {
   1286         $code .= "    ${implClassName}V8Internal::${attrName}AttrGetter${forMainWorldSuffix}(name, info);\n";
   1287     }
   1288     $code .= "    TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n";
   1289     $code .= "}\n\n";
   1290     $code .= "#endif // ${conditionalString}\n\n" if $conditionalString;
   1291 
   1292     $implementation{nameSpaceInternal}->add($code);
   1293 }
   1294 
   1295 sub GenerateNormalAttrGetter
   1296 {
   1297     my $attribute = shift;
   1298     my $interface = shift;
   1299     my $forMainWorldSuffix = shift;
   1300 
   1301     my $interfaceName = $interface->name;
   1302     my $implClassName = GetImplName($interface);
   1303     my $v8ClassName = GetV8ClassName($interface);
   1304     my $attrExt = $attribute->extendedAttributes;
   1305     my $attrName = $attribute->name;
   1306     my $attrType = $attribute->type;
   1307 
   1308     if (HasCustomGetter($attrExt)) {
   1309         return;
   1310     }
   1311 
   1312     AssertNotSequenceType($attrType);
   1313     my $nativeType = GetNativeType($attribute->type, $attribute->extendedAttributes, "");
   1314     my $svgNativeType = GetSVGTypeNeedingTearOff($interfaceName);
   1315 
   1316     my $conditionalString = GenerateConditionalString($attribute);
   1317     my $code = "";
   1318     $code .= "#if ${conditionalString}\n\n" if $conditionalString;
   1319     $code .= <<END;
   1320 static void ${attrName}AttrGetter${forMainWorldSuffix}(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
   1321 {
   1322 END
   1323     if ($svgNativeType) {
   1324         my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($interfaceName);
   1325         if ($svgWrappedNativeType =~ /List/) {
   1326             $code .= <<END;
   1327     $svgNativeType* imp = ${v8ClassName}::toNative(info.Holder());
   1328 END
   1329         } else {
   1330             $code .= <<END;
   1331     $svgNativeType* wrapper = ${v8ClassName}::toNative(info.Holder());
   1332     $svgWrappedNativeType& impInstance = wrapper->propertyReference();
   1333     $svgWrappedNativeType* imp = &impInstance;
   1334 END
   1335         }
   1336     } elsif ($attrExt->{"OnProto"} || $attrExt->{"Unforgeable"}) {
   1337         if ($interfaceName eq "Window") {
   1338             $code .= <<END;
   1339     v8::Handle<v8::Object> holder = info.Holder();
   1340 END
   1341         } else {
   1342             # perform lookup first
   1343             $code .= <<END;
   1344     v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(${v8ClassName}::GetTemplate(info.GetIsolate(), worldType(info.GetIsolate())));
   1345     if (holder.IsEmpty())
   1346         return;
   1347 END
   1348         }
   1349         $code .= <<END;
   1350     ${implClassName}* imp = ${v8ClassName}::toNative(holder);
   1351 END
   1352     } else {
   1353         my $reflect = $attribute->extendedAttributes->{"Reflect"};
   1354         my $url = $attribute->extendedAttributes->{"URL"};
   1355         if ($reflect && !$url && InheritsInterface($interface, "Node") && $attrType eq "DOMString") {
   1356             # Generate super-compact call for regular attribute getter:
   1357             my ($functionName, @arguments) = GetterExpression($interfaceName, $attribute);
   1358             $code .= "    Element* imp = V8Element::toNative(info.Holder());\n";
   1359             $code .= "    v8SetReturnValueString(info, imp->${functionName}(" . join(", ", @arguments) . "), info.GetIsolate());\n";
   1360             $code .= "    return;\n";
   1361             $code .= "}\n\n";
   1362             $code .= "#endif // ${conditionalString}\n\n" if $conditionalString;
   1363             $implementation{nameSpaceInternal}->add($code);
   1364             return;
   1365             # Skip the rest of the function!
   1366         }
   1367         if ($attribute->type eq "SerializedScriptValue" && $attrExt->{"CachedAttribute"}) {
   1368             $code .= <<END;
   1369     v8::Handle<v8::String> propertyName = v8::String::NewSymbol("${attrName}");
   1370     v8::Handle<v8::Value> value = info.Holder()->GetHiddenValue(propertyName);
   1371     if (!value.IsEmpty()) {
   1372         v8SetReturnValue(info, value);
   1373         return;
   1374     }
   1375 END
   1376         }
   1377         if (!$attribute->isStatic) {
   1378             $code .= <<END;
   1379     ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());
   1380 END
   1381         }
   1382     }
   1383 
   1384     # Generate security checks if necessary
   1385     if ($attribute->extendedAttributes->{"CheckSecurityForNode"}) {
   1386         AddToImplIncludes("bindings/v8/BindingSecurity.h");
   1387         $code .= "    if (!BindingSecurity::shouldAllowAccessToNode(imp->" . GetImplName($attribute) . "())) {\n";
   1388         $code .= "        v8SetReturnValueNull(info);\n";
   1389         $code .= "        return;\n";
   1390         $code .= "    }\n";
   1391     }
   1392 
   1393     my $useExceptions = 1 if $attribute->extendedAttributes->{"GetterRaisesException"} ||  $attribute->extendedAttributes->{"RaisesException"};
   1394     my $isNullable = $attribute->isNullable;
   1395     if ($useExceptions) {
   1396         AddToImplIncludes("bindings/v8/ExceptionState.h");
   1397         $code .= "    ExceptionState es(info.GetIsolate());\n";
   1398     }
   1399 
   1400     if ($isNullable) {
   1401         $code .= "    bool isNull = false;\n";
   1402     }
   1403 
   1404     my $returnType = $attribute->type;
   1405     my $getterString;
   1406 
   1407     my ($functionName, @arguments) = GetterExpression($interfaceName, $attribute);
   1408     push(@arguments, "isNull") if $isNullable;
   1409     push(@arguments, "es") if $useExceptions;
   1410     if ($attribute->extendedAttributes->{"ImplementedBy"}) {
   1411         my $implementedBy = $attribute->extendedAttributes->{"ImplementedBy"};
   1412         my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy);
   1413         AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implementedByImplName));
   1414         unshift(@arguments, "imp") if !$attribute->isStatic;
   1415         $functionName = "${implementedByImplName}::${functionName}";
   1416     } elsif ($attribute->isStatic) {
   1417         $functionName = "${implClassName}::${functionName}";
   1418     } else {
   1419         $functionName = "imp->${functionName}";
   1420     }
   1421     my ($arg, $subCode) = GenerateCallWith($attribute->extendedAttributes->{"CallWith"}, "    ", 0);
   1422     $code .= $subCode;
   1423     unshift(@arguments, @$arg);
   1424     $getterString = "${functionName}(" . join(", ", @arguments) . ")";
   1425 
   1426     my $expression;
   1427     if ($attribute->type eq "EventHandler" && $interface->name eq "Window") {
   1428         $code .= "    if (!imp->document())\n";
   1429         $code .= "        return;\n";
   1430     }
   1431 
   1432     if ($useExceptions || $isNullable) {
   1433         if ($nativeType =~ /^V8StringResource/) {
   1434             $code .= "    " . ConvertToV8StringResource($attribute, $nativeType, "v", $getterString) . ";\n";
   1435         } else {
   1436             $code .= "    $nativeType v = $getterString;\n";
   1437         }
   1438 
   1439         if ($isNullable) {
   1440             $code .= "    if (isNull) {\n";
   1441             $code .= "        v8SetReturnValueNull(info);\n";
   1442             $code .= "        return;\n";
   1443             $code .= "    }\n";
   1444         }
   1445 
   1446         if ($useExceptions) {
   1447             if ($useExceptions) {
   1448                 $code .= "    if (UNLIKELY(es.throwIfNeeded()))\n";
   1449                 $code .= "        return;\n";
   1450             }
   1451 
   1452             if (ExtendedAttributeContains($attribute->extendedAttributes->{"CallWith"}, "ScriptState")) {
   1453                 $code .= "    if (state.hadException()) {\n";
   1454                 $code .= "        throwError(state.exception());\n";
   1455                 $code .= "        return;\n";
   1456                 $code .= "    }\n";
   1457             }
   1458         }
   1459 
   1460         $expression = "v";
   1461         $expression .= ".release()" if (IsRefPtrType($returnType));
   1462     } else {
   1463         # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
   1464         $expression = $getterString;
   1465         # Fix amigious conversion problem, by casting to the base type first ($getterString returns a type that inherits from SVGAnimatedEnumeration, not the base class directly).
   1466         $expression = "static_pointer_cast<SVGAnimatedEnumeration>($expression)" if $returnType eq "SVGAnimatedEnumeration";
   1467     }
   1468 
   1469     if (ShouldKeepAttributeAlive($interface, $attribute, $returnType)) {
   1470         my $arrayType = GetArrayType($returnType);
   1471         if ($arrayType) {
   1472             AddIncludeForType("V8$arrayType.h");
   1473             $code .= "    v8SetReturnValue(info, v8Array(${getterString}, info.GetIsolate()));\n";
   1474             $code .= "    return;\n";
   1475             $code .= "}\n\n";
   1476             $implementation{nameSpaceInternal}->add($code);
   1477             return;
   1478         }
   1479 
   1480         AddIncludesForType($returnType);
   1481         AddToImplIncludes("bindings/v8/V8HiddenPropertyName.h");
   1482         # Check for a wrapper in the wrapper cache. If there is one, we know that a hidden reference has already
   1483         # been created. If we don't find a wrapper, we create both a wrapper and a hidden reference.
   1484         my $nativeReturnType = GetNativeType($returnType);
   1485         my $v8ReturnType = "V8" . $returnType;
   1486         $code .= "    $nativeReturnType result = ${getterString};\n";
   1487         if ($forMainWorldSuffix) {
   1488           $code .= "    v8::Handle<v8::Value> wrapper = result.get() ? v8::Handle<v8::Value>(DOMDataStore::getWrapper${forMainWorldSuffix}<${v8ReturnType}>(result.get())) : v8Undefined();\n";
   1489         } else {
   1490           $code .= "    v8::Handle<v8::Value> wrapper = result.get() ? v8::Handle<v8::Value>(DOMDataStore::getWrapper<${v8ReturnType}>(result.get(), info.GetIsolate())) : v8Undefined();\n";
   1491         }
   1492         $code .= "    if (wrapper.IsEmpty()) {\n";
   1493         $code .= "        wrapper = toV8(result.get(), info.Holder(), info.GetIsolate());\n"; # FIXME: Could use wrap here since the wrapper is empty.
   1494         $code .= "        if (!wrapper.IsEmpty())\n";
   1495         $code .= "            V8HiddenPropertyName::setNamedHiddenReference(info.Holder(), \"${attrName}\", wrapper);\n";
   1496         $code .= "    }\n";
   1497         $code .= "    v8SetReturnValue(info, wrapper);\n";
   1498         $code .= "    return;\n";
   1499         $code .= "}\n\n";
   1500         $code .= "#endif // ${conditionalString}\n\n" if $conditionalString;
   1501         $implementation{nameSpaceInternal}->add($code);
   1502         return;
   1503     }
   1504 
   1505     if ((IsSVGAnimatedType($interfaceName) or $interfaceName eq "SVGViewSpec") and IsSVGTypeNeedingTearOff($attrType)) {
   1506         AddToImplIncludes("V8$attrType.h");
   1507         my $svgNativeType = GetSVGTypeNeedingTearOff($attrType);
   1508         # Convert from abstract SVGProperty to real type, so the right toJS() method can be invoked.
   1509         if ($forMainWorldSuffix eq "ForMainWorld") {
   1510             $code .= "    v8SetReturnValue(info, toV8ForMainWorld(static_cast<$svgNativeType*>($expression), info.Holder(), info.GetIsolate()));\n";
   1511         } else {
   1512             $code .= "    v8SetReturnValue(info, toV8Fast(static_cast<$svgNativeType*>($expression), info, imp));\n";
   1513         }
   1514         $code .= "    return;\n";
   1515     } elsif (IsSVGTypeNeedingTearOff($attrType) and not $interfaceName =~ /List$/) {
   1516         AddToImplIncludes("V8$attrType.h");
   1517         AddToImplIncludes("core/svg/properties/SVGPropertyTearOff.h");
   1518         my $tearOffType = GetSVGTypeNeedingTearOff($attrType);
   1519         my $wrappedValue;
   1520         if (IsSVGTypeWithWritablePropertiesNeedingTearOff($attrType) and not defined $attribute->extendedAttributes->{"Immutable"}) {
   1521             my $getter = $expression;
   1522             $getter =~ s/imp->//;
   1523             $getter =~ s/\(\)//;
   1524 
   1525             my $updateMethod = "&${implClassName}::update" . FirstLetterToUpperCase($getter);
   1526 
   1527             my $selfIsTearOffType = IsSVGTypeNeedingTearOff($interfaceName);
   1528             if ($selfIsTearOffType) {
   1529                 AddToImplIncludes("core/svg/properties/SVGMatrixTearOff.h");
   1530                 # FIXME: Don't create a new one everytime we access the matrix property. This means, e.g, === won't work.
   1531                 $wrappedValue = "WTF::getPtr(SVGMatrixTearOff::create(wrapper, $expression))";
   1532             } else {
   1533                 AddToImplIncludes("core/svg/properties/SVGStaticPropertyTearOff.h");
   1534                 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyTearOff<$implClassName, /;
   1535 
   1536                 $wrappedValue = "WTF::getPtr(${tearOffType}::create(imp, $expression, $updateMethod))";
   1537             }
   1538         } elsif ($tearOffType =~ /SVGStaticListPropertyTearOff/) {
   1539                 $wrappedValue = "WTF::getPtr(${tearOffType}::create(imp, $expression))";
   1540         } elsif ($tearOffType =~ /SVG(Point|PathSeg)List/) {
   1541                 $wrappedValue = "WTF::getPtr($expression)";
   1542         } else {
   1543                 $wrappedValue = "WTF::getPtr(${tearOffType}::create($expression))";
   1544         }
   1545         if ($forMainWorldSuffix eq "ForMainWorld") {
   1546             $code .= "    v8SetReturnValue(info, toV8ForMainWorld($wrappedValue, info.Holder(), info.GetIsolate()));\n";
   1547         } else {
   1548             $code .= "    v8SetReturnValue(info, toV8Fast($wrappedValue, info, imp));\n";
   1549         }
   1550         $code .= "    return;\n";
   1551     } elsif ($attribute->type eq "SerializedScriptValue" && $attrExt->{"CachedAttribute"}) {
   1552         my $getterFunc = ToMethodName($attribute->name);
   1553         $code .= <<END;
   1554     RefPtr<SerializedScriptValue> serialized = imp->${getterFunc}();
   1555     value = serialized ? serialized->deserialize() : v8::Handle<v8::Value>(v8::Null(info.GetIsolate()));
   1556     info.Holder()->SetHiddenValue(propertyName, value);
   1557     v8SetReturnValue(info, value);
   1558     return;
   1559 END
   1560     } elsif ($attribute->type eq "EventHandler") {
   1561         AddToImplIncludes("bindings/v8/V8AbstractEventListener.h");
   1562         my $getterFunc = ToMethodName($attribute->name);
   1563         # FIXME: Pass the main world ID for main-world-only getters.
   1564         $code .= "    EventListener* listener = imp->${getterFunc}(isolatedWorldForIsolate(info.GetIsolate()));\n";
   1565         $code .= "    v8SetReturnValue(info, listener ? v8::Handle<v8::Value>(V8AbstractEventListener::cast(listener)->getListenerObject(imp->scriptExecutionContext())) : v8::Handle<v8::Value>(v8::Null(info.GetIsolate())));\n";
   1566         $code .= "    return;\n";
   1567     } else {
   1568         my $nativeValue = NativeToJSValue($attribute->type, $attribute->extendedAttributes, $expression, "    ", "", "info.Holder()", "info.GetIsolate()", "info", "imp", $forMainWorldSuffix, "return");
   1569         $code .= "${nativeValue}\n";
   1570         $code .= "    return;\n";
   1571     }
   1572 
   1573     $code .= "}\n\n";  # end of getter
   1574     $code .= "#endif // ${conditionalString}\n\n" if $conditionalString;
   1575     $implementation{nameSpaceInternal}->add($code);
   1576 }
   1577 
   1578 sub ShouldKeepAttributeAlive
   1579 {
   1580     my ($interface, $attribute, $returnType) = @_;
   1581     my $attrName = $attribute->name;
   1582 
   1583     return 1 if $attribute->extendedAttributes->{"KeepAttributeAliveForGC"};
   1584 
   1585     # Basically, for readonly or replaceable attributes, we have to guarantee
   1586     # that JS wrappers don't get garbage-collected prematually when their
   1587     # lifetime is strongly tied to their owner.
   1588     return 0 if !IsWrapperType($returnType);
   1589     return 0 if !IsReadonly($attribute) && !$attribute->extendedAttributes->{"Replaceable"};
   1590 
   1591     # However, there are a couple of exceptions.
   1592 
   1593     # Node lifetime is managed by object grouping.
   1594     return 0 if InheritsInterface($interface, "Node");
   1595     return 0 if IsDOMNodeType($returnType);
   1596 
   1597     # To avoid adding a reference to itself.
   1598     # FIXME: Introduce [DoNotKeepAttributeAliveForGC] and remove this hack
   1599     # depending on the attribute name.
   1600     return 0 if $attrName eq "self";
   1601 
   1602     # FIXME: Remove these hard-coded hacks.
   1603     return 0 if $returnType eq "EventTarget";
   1604     return 0 if $returnType eq "SerializedScriptValue";
   1605     return 0 if $returnType eq "Window";
   1606     return 0 if $returnType =~ /SVG/;
   1607     return 0 if $returnType =~ /HTML/;
   1608 
   1609     return 1;
   1610 }
   1611 
   1612 sub GenerateReplaceableAttrSetterCallback
   1613 {
   1614     my $interface = shift;
   1615     my $implClassName = GetImplName($interface);
   1616 
   1617     my $code = "";
   1618     $code .= "static void ${implClassName}ReplaceableAttrSetterCallback(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)\n";
   1619     $code .= "{\n";
   1620     $code .= GenerateFeatureObservation($interface->extendedAttributes->{"MeasureAs"});
   1621     $code .= GenerateDeprecationNotification($interface->extendedAttributes->{"DeprecateAs"});
   1622     $code .= GenerateCustomElementInvocationScopeIfNeeded($interface->extendedAttributes);
   1623     if (HasActivityLogging("", $interface->extendedAttributes, "Setter")) {
   1624          die "IDL error: ActivityLog attribute cannot exist on a ReplacableAttrSetterCallback";
   1625     }
   1626     $code .= "    ${implClassName}V8Internal::${implClassName}ReplaceableAttrSetter(name, value, info);\n";
   1627     $code .= "}\n\n";
   1628     $implementation{nameSpaceInternal}->add($code);
   1629 }
   1630 
   1631 sub GenerateReplaceableAttrSetter
   1632 {
   1633     my $interface = shift;
   1634 
   1635     my $implClassName = GetImplName($interface);
   1636     my $v8ClassName = GetV8ClassName($interface);
   1637 
   1638     my $code = "";
   1639     $code .= <<END;
   1640 static void ${implClassName}ReplaceableAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)
   1641 {
   1642 END
   1643     if ($interface->extendedAttributes->{"CheckSecurity"}) {
   1644         AddToImplIncludes("core/page/Frame.h");
   1645         AddToImplIncludes("bindings/v8/BindingSecurity.h");
   1646         $code .= <<END;
   1647     ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());
   1648     if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame()))
   1649         return;
   1650 END
   1651     }
   1652 
   1653     $code .= <<END;
   1654     info.This()->ForceSet(name, value);
   1655 }
   1656 
   1657 END
   1658     $implementation{nameSpaceInternal}->add($code);
   1659 }
   1660 
   1661 sub GenerateCustomElementInvocationScopeIfNeeded
   1662 {
   1663     my $code = "";
   1664     my $ext = shift;
   1665     my $annotation = $ext->{"CustomElementCallbacks"} || "";
   1666 
   1667     if ($annotation eq "None") {
   1668         # Explicit CustomElementCallbacks=None overrides any other
   1669         # heuristic.
   1670         return $code;
   1671     }
   1672 
   1673     if ($annotation eq "Enable" or $ext->{"Reflect"}) {
   1674         AddToImplIncludes("core/dom/CustomElementCallbackDispatcher.h");
   1675         $code .= <<END;
   1676     CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
   1677 END
   1678     }
   1679     return $code;
   1680 }
   1681 
   1682 sub GenerateNormalAttrSetterCallback
   1683 {
   1684     my $attribute = shift;
   1685     my $interface = shift;
   1686     my $forMainWorldSuffix = shift;
   1687 
   1688     my $implClassName = GetImplName($interface);
   1689     my $v8ClassName = GetV8ClassName($interface);
   1690     my $attrExt = $attribute->extendedAttributes;
   1691     my $attrName = $attribute->name;
   1692 
   1693     my $conditionalString = GenerateConditionalString($attribute);
   1694     my $code = "";
   1695     $code .= "#if ${conditionalString}\n\n" if $conditionalString;
   1696 
   1697     $code .= "static void ${attrName}AttrSetterCallback${forMainWorldSuffix}(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)\n";
   1698     $code .= "{\n";
   1699     $code .= "    TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMSetter\");\n";
   1700     $code .= GenerateFeatureObservation($attrExt->{"MeasureAs"});
   1701     $code .= GenerateDeprecationNotification($attrExt->{"DeprecateAs"});
   1702     if (HasActivityLogging($forMainWorldSuffix, $attrExt, "Setter")) {
   1703         $code .= GenerateActivityLogging("Setter", $interface, "${attrName}");
   1704     }
   1705     $code .= GenerateCustomElementInvocationScopeIfNeeded($attrExt);
   1706     if (HasCustomSetter($attrExt)) {
   1707         $code .= "    ${v8ClassName}::${attrName}AttrSetterCustom(name, value, info);\n";
   1708     } else {
   1709         $code .= "    ${implClassName}V8Internal::${attrName}AttrSetter${forMainWorldSuffix}(name, value, info);\n";
   1710     }
   1711     $code .= "    TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n";
   1712     $code .= "}\n\n";
   1713     $code .= "#endif // ${conditionalString}\n\n" if $conditionalString;
   1714     $implementation{nameSpaceInternal}->add($code);
   1715 }
   1716 
   1717 sub GenerateNormalAttrSetter
   1718 {
   1719     my $attribute = shift;
   1720     my $interface = shift;
   1721     my $forMainWorldSuffix = shift;
   1722 
   1723     my $interfaceName = $interface->name;
   1724     my $implClassName = GetImplName($interface);
   1725     my $v8ClassName = GetV8ClassName($interface);
   1726     my $attrName = $attribute->name;
   1727     my $attrExt = $attribute->extendedAttributes;
   1728     my $attrType = $attribute->type;
   1729 
   1730     if (HasCustomSetter($attrExt)) {
   1731         return;
   1732     }
   1733 
   1734     my $conditionalString = GenerateConditionalString($attribute);
   1735     my $code = "";
   1736     $code .= "#if ${conditionalString}\n\n" if $conditionalString;
   1737     $code .= "static void ${attrName}AttrSetter${forMainWorldSuffix}(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)\n";
   1738     $code .= "{\n";
   1739 
   1740     # If the "StrictTypeChecking" extended attribute is present, and the attribute's type is an
   1741     # interface type, then if the incoming value does not implement that interface, a TypeError is
   1742     # thrown rather than silently passing NULL to the C++ code.
   1743     # Per the Web IDL and ECMAScript specifications, incoming values can always be converted to both
   1744     # strings and numbers, so do not throw TypeError if the attribute is of these types.
   1745     if ($attribute->extendedAttributes->{"StrictTypeChecking"}) {
   1746         my $argType = $attribute->type;
   1747         if (IsWrapperType($argType)) {
   1748             $code .= "    if (!isUndefinedOrNull(value) && !V8${argType}::HasInstance(value, info.GetIsolate(), worldType(info.GetIsolate()))) {\n";
   1749             $code .= "        throwTypeError(info.GetIsolate());\n";
   1750             $code .= "        return;\n";
   1751             $code .= "    }\n";
   1752         }
   1753     }
   1754 
   1755     my $svgNativeType = GetSVGTypeNeedingTearOff($interfaceName);
   1756     if ($svgNativeType) {
   1757         my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($interfaceName);
   1758         if ($svgWrappedNativeType =~ /List$/) {
   1759             $code .= <<END;
   1760     $svgNativeType* imp = ${v8ClassName}::toNative(info.Holder());
   1761 END
   1762         } else {
   1763             AddToImplIncludes("bindings/v8/ExceptionState.h");
   1764             $code .= "    $svgNativeType* wrapper = ${v8ClassName}::toNative(info.Holder());\n";
   1765             $code .= "    if (wrapper->isReadOnly()) {\n";
   1766             $code .= "        setDOMException(NoModificationAllowedError, info.GetIsolate());\n";
   1767             $code .= "        return;\n";
   1768             $code .= "    }\n";
   1769             $code .= "    $svgWrappedNativeType& impInstance = wrapper->propertyReference();\n";
   1770             $code .= "    $svgWrappedNativeType* imp = &impInstance;\n";
   1771         }
   1772     } elsif ($attrExt->{"OnProto"}) {
   1773         $code .= <<END;
   1774     ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());
   1775 END
   1776     } else {
   1777         my $reflect = $attribute->extendedAttributes->{"Reflect"};
   1778         if ($reflect && InheritsInterface($interface, "Node") && $attrType eq "DOMString") {
   1779             # Generate super-compact call for regular attribute setter:
   1780             my $contentAttributeName = $reflect eq "VALUE_IS_MISSING" ? lc $attrName : $reflect;
   1781             my $namespace = NamespaceForAttributeName($interfaceName, $contentAttributeName);
   1782             AddToImplIncludes("${namespace}.h");
   1783             $code .= "    Element* imp = V8Element::toNative(info.Holder());\n";
   1784             $code .= "    V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, stringResource, value);\n";
   1785             $code .= "    imp->setAttribute(${namespace}::${contentAttributeName}Attr, stringResource);\n";
   1786             $code .= "}\n\n";
   1787             $code .= "#endif // ${conditionalString}\n\n" if $conditionalString;
   1788             $implementation{nameSpaceInternal}->add($code);
   1789             return;
   1790             # Skip the rest of the function!
   1791         }
   1792 
   1793         if (!$attribute->isStatic) {
   1794             $code .= <<END;
   1795     ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());
   1796 END
   1797         }
   1798     }
   1799 
   1800     my $nativeType = GetNativeType($attribute->type, $attribute->extendedAttributes, "parameter");
   1801     if ($attribute->type eq "EventHandler") {
   1802         if ($interface->name eq "Window") {
   1803             $code .= "    if (!imp->document())\n";
   1804             $code .= "        return;\n";
   1805         }
   1806     } else {
   1807         $code .= JSValueToNativeStatement($attribute->type, $attribute->extendedAttributes, "value", "v", "    ", "info.GetIsolate()");
   1808     }
   1809 
   1810     if (IsEnumType($attrType)) {
   1811         # setter ignores invalid enumeration values
   1812         my @enumValues = ValidEnumValues($attrType);
   1813         my @validEqualities = ();
   1814         foreach my $enumValue (@enumValues) {
   1815             push(@validEqualities, "string == \"$enumValue\"");
   1816         }
   1817         my $enumValidationExpression = join(" || ", @validEqualities);
   1818         $code .= <<END;
   1819     String string = v;
   1820     if (!($enumValidationExpression))
   1821         return;
   1822 END
   1823     }
   1824 
   1825     my $expression = "v";
   1826     my $returnType = $attribute->type;
   1827     if (IsRefPtrType($returnType) && !GetArrayType($returnType)) {
   1828         $expression = "WTF::getPtr(" . $expression . ")";
   1829     }
   1830 
   1831     $code .= GenerateCustomElementInvocationScopeIfNeeded($attribute->extendedAttributes);
   1832 
   1833     my $useExceptions = 1 if $attribute->extendedAttributes->{"SetterRaisesException"} ||  $attribute->extendedAttributes->{"RaisesException"};
   1834 
   1835     if ($useExceptions) {
   1836         AddToImplIncludes("bindings/v8/ExceptionState.h");
   1837         $code .= "    ExceptionState es(info.GetIsolate());\n";
   1838     }
   1839 
   1840     if ($attribute->type eq "EventHandler") {
   1841         my $implSetterFunctionName = FirstLetterToUpperCase($attrName);
   1842         AddToImplIncludes("bindings/v8/V8AbstractEventListener.h");
   1843         # Non callable input should be treated as null
   1844         $code .= "    if (!value->IsNull() && !value->IsFunction())\n";
   1845         $code .= "        value = v8::Null(info.GetIsolate());\n";
   1846         if (!InheritsInterface($interface, "Node")) {
   1847             my $attrImplName = GetImplName($attribute);
   1848             $code .= "    transferHiddenDependency(info.Holder(), imp->${attrImplName}(isolatedWorldForIsolate(info.GetIsolate())), value, ${v8ClassName}::eventListenerCacheIndex, info.GetIsolate());\n";
   1849         }
   1850         AddToImplIncludes("bindings/v8/V8EventListenerList.h");
   1851         if (($interfaceName eq "Window" or $interfaceName eq "WorkerGlobalScope") and $attribute->name eq "onerror") {
   1852             AddToImplIncludes("bindings/v8/V8ErrorHandler.h");
   1853             $code .= "    imp->set$implSetterFunctionName(V8EventListenerList::findOrCreateWrapper<V8ErrorHandler>(value, true), isolatedWorldForIsolate(info.GetIsolate()));\n";
   1854         } else {
   1855             $code .= "    imp->set$implSetterFunctionName(V8EventListenerList::getEventListener(value, true, ListenerFindOrCreate), isolatedWorldForIsolate(info.GetIsolate()));\n";
   1856         }
   1857     } else {
   1858         my ($functionName, @arguments) = SetterExpression($interfaceName, $attribute);
   1859         push(@arguments, $expression);
   1860         push(@arguments, "es") if $useExceptions;
   1861         if ($attribute->extendedAttributes->{"ImplementedBy"}) {
   1862             my $implementedBy = $attribute->extendedAttributes->{"ImplementedBy"};
   1863             my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy);
   1864             AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implementedByImplName));
   1865             unshift(@arguments, "imp") if !$attribute->isStatic;
   1866             $functionName = "${implementedByImplName}::${functionName}";
   1867         } elsif ($attribute->isStatic) {
   1868             $functionName = "${implClassName}::${functionName}";
   1869         } else {
   1870             $functionName = "imp->${functionName}";
   1871         }
   1872         my ($arg, $subCode) = GenerateCallWith($attribute->extendedAttributes->{"SetterCallWith"} || $attribute->extendedAttributes->{"CallWith"}, "    ", 1);
   1873         $code .= $subCode;
   1874         unshift(@arguments, @$arg);
   1875         $code .= "    ${functionName}(" . join(", ", @arguments) . ");\n";
   1876     }
   1877 
   1878     if ($useExceptions) {
   1879         $code .= "    es.throwIfNeeded();\n";
   1880     }
   1881 
   1882     if (ExtendedAttributeContains($attribute->extendedAttributes->{"CallWith"}, "ScriptState")) {
   1883         $code .= "    if (state.hadException())\n";
   1884         $code .= "        throwError(state.exception());\n";
   1885     }
   1886 
   1887     if ($svgNativeType) {
   1888         if ($useExceptions) {
   1889             $code .= "    if (!es.hadException())\n";
   1890             $code .= "        wrapper->commitChange();\n";
   1891         } else {
   1892             $code .= "    wrapper->commitChange();\n";
   1893         }
   1894     }
   1895 
   1896     if ($attribute->type eq "SerializedScriptValue" && $attribute->extendedAttributes->{"CachedAttribute"}) {
   1897         $code .= <<END;
   1898     info.Holder()->DeleteHiddenValue(v8::String::NewSymbol("${attrName}")); // Invalidate the cached value.
   1899 END
   1900     }
   1901 
   1902     $code .= "    return;\n";
   1903     $code .= "}\n\n";  # end of setter
   1904     $code .= "#endif // ${conditionalString}\n\n" if $conditionalString;
   1905     $implementation{nameSpaceInternal}->add($code);
   1906 }
   1907 
   1908 sub GenerateParametersCheckExpression
   1909 {
   1910     my $numParameters = shift;
   1911     my $function = shift;
   1912 
   1913     my @andExpression = ();
   1914     push(@andExpression, "args.Length() == $numParameters");
   1915     my $parameterIndex = 0;
   1916     foreach my $parameter (@{$function->parameters}) {
   1917         last if $parameterIndex >= $numParameters;
   1918         my $value = "args[$parameterIndex]";
   1919         my $type = $parameter->type;
   1920 
   1921         # Only DOMString or wrapper types are checked.
   1922         # For DOMString with StrictTypeChecking only Null, Undefined and Object
   1923         # are accepted for compatibility. Otherwise, no restrictions are made to
   1924         # match the non-overloaded behavior.
   1925         # FIXME: Implement WebIDL overload resolution algorithm.
   1926         if ($type eq "DOMString") {
   1927             if ($parameter->extendedAttributes->{"StrictTypeChecking"}) {
   1928                 push(@andExpression, "(${value}->IsNull() || ${value}->IsUndefined() || ${value}->IsString() || ${value}->IsObject())");
   1929             }
   1930         } elsif (IsCallbackInterface($parameter->type)) {
   1931             # For Callbacks only checks if the value is null or object.
   1932             push(@andExpression, "(${value}->IsNull() || ${value}->IsFunction())");
   1933         } elsif (GetArrayOrSequenceType($type)) {
   1934             if ($parameter->isNullable) {
   1935                 push(@andExpression, "(${value}->IsNull() || ${value}->IsArray())");
   1936             } else {
   1937                 push(@andExpression, "(${value}->IsArray())");
   1938             }
   1939         } elsif (IsWrapperType($type)) {
   1940             if ($parameter->isNullable) {
   1941                 push(@andExpression, "(${value}->IsNull() || V8${type}::HasInstance($value, args.GetIsolate(), worldType(args.GetIsolate())))");
   1942             } else {
   1943                 push(@andExpression, "(V8${type}::HasInstance($value, args.GetIsolate(), worldType(args.GetIsolate())))");
   1944             }
   1945         }
   1946 
   1947         $parameterIndex++;
   1948     }
   1949     my $res = join(" && ", @andExpression);
   1950     $res = "($res)" if @andExpression > 1;
   1951     return $res;
   1952 }
   1953 
   1954 # As per Web IDL specification, the length of a function Object is
   1955 # its number of mandatory parameters.
   1956 sub GetFunctionLength
   1957 {
   1958     my $function = shift;
   1959 
   1960     my $numMandatoryParams = 0;
   1961     foreach my $parameter (@{$function->parameters}) {
   1962         # Abort as soon as we find the first optional parameter as no mandatory
   1963         # parameter can follow an optional one.
   1964         last if $parameter->isOptional;
   1965         $numMandatoryParams++;
   1966     }
   1967     return $numMandatoryParams;
   1968 }
   1969 
   1970 sub GenerateFunctionParametersCheck
   1971 {
   1972     my $function = shift;
   1973 
   1974     my @orExpression = ();
   1975     my $numParameters = 0;
   1976     my $hasVariadic = 0;
   1977     my $numMandatoryParams = @{$function->parameters};
   1978     foreach my $parameter (@{$function->parameters}) {
   1979         if ($parameter->isOptional) {
   1980             push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
   1981             $numMandatoryParams--;
   1982         }
   1983         if ($parameter->isVariadic) {
   1984             $hasVariadic = 1;
   1985             last;
   1986         }
   1987         $numParameters++;
   1988     }
   1989     if (!$hasVariadic) {
   1990         push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
   1991     }
   1992     return ($numMandatoryParams, join(" || ", @orExpression));
   1993 }
   1994 
   1995 sub GenerateOverloadedFunction
   1996 {
   1997     my $function = shift;
   1998     my $interface = shift;
   1999     my $forMainWorldSuffix = shift;
   2000 
   2001     # Generate code for choosing the correct overload to call. Overloads are
   2002     # chosen based on the total number of arguments passed and the type of
   2003     # values passed in non-primitive argument slots. When more than a single
   2004     # overload is applicable, precedence is given according to the order of
   2005     # declaration in the IDL.
   2006 
   2007     my $name = $function->name;
   2008 
   2009     my $conditionalString = GenerateConditionalString($function);
   2010     my $leastNumMandatoryParams = 255;
   2011     my $code = "";
   2012     $code .= "#if ${conditionalString}\n\n" if $conditionalString;
   2013     $code .= <<END;
   2014 static void ${name}Method${forMainWorldSuffix}(const v8::FunctionCallbackInfo<v8::Value>& args)
   2015 {
   2016 END
   2017     $code .= GenerateFeatureObservation($function->extendedAttributes->{"MeasureAs"});
   2018     $code .= GenerateDeprecationNotification($function->extendedAttributes->{"DeprecateAs"});
   2019 
   2020     foreach my $overload (@{$function->{overloads}}) {
   2021         my ($numMandatoryParams, $parametersCheck) = GenerateFunctionParametersCheck($overload);
   2022         $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams < $leastNumMandatoryParams);
   2023         $code .= "    if ($parametersCheck) {\n";
   2024         my $overloadedIndexString = $overload->{overloadIndex};
   2025         $code .= "        ${name}${overloadedIndexString}Method${forMainWorldSuffix}(args);\n";
   2026         $code .= "        return;\n";
   2027         $code .= "    }\n";
   2028     }
   2029     if ($leastNumMandatoryParams >= 1) {
   2030         $code .= "    if (args.Length() < $leastNumMandatoryParams) {\n";
   2031         $code .= "        throwNotEnoughArgumentsError(args.GetIsolate());\n";
   2032         $code .= "        return;\n";
   2033         $code .= "    }\n";
   2034     }
   2035     $code .= <<END;
   2036     throwTypeError(args.GetIsolate());
   2037 END
   2038     $code .= "}\n\n";
   2039     $code .= "#endif // ${conditionalString}\n\n" if $conditionalString;
   2040     $implementation{nameSpaceInternal}->add($code);
   2041 }
   2042 
   2043 sub GenerateFunctionCallback
   2044 {
   2045     my $function = shift;
   2046     my $interface = shift;
   2047     my $forMainWorldSuffix = shift;
   2048 
   2049     my $implClassName = GetImplName($interface);
   2050     my $v8ClassName = GetV8ClassName($interface);
   2051     my $name = $function->name;
   2052 
   2053     if ($name eq "") {
   2054         return;
   2055     }
   2056 
   2057     my $conditionalString = GenerateConditionalString($function);
   2058     my $code = "";
   2059     $code .= "#if ${conditionalString}\n\n" if $conditionalString;
   2060     $code .= <<END;
   2061 static void ${name}MethodCallback${forMainWorldSuffix}(const v8::FunctionCallbackInfo<v8::Value>& args)
   2062 {
   2063 END
   2064     $code .= "    TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMMethod\");\n";
   2065     $code .= GenerateFeatureObservation($function->extendedAttributes->{"MeasureAs"});
   2066     $code .= GenerateDeprecationNotification($function->extendedAttributes->{"DeprecateAs"});
   2067     if (HasActivityLogging($forMainWorldSuffix, $function->extendedAttributes, "Access")) {
   2068         $code .= GenerateActivityLogging("Method", $interface, "${name}");
   2069     }
   2070     if (HasCustomMethod($function->extendedAttributes)) {
   2071         $code .= "    ${v8ClassName}::${name}MethodCustom(args);\n";
   2072     } else {
   2073         $code .= "    ${implClassName}V8Internal::${name}Method${forMainWorldSuffix}(args);\n";
   2074     }
   2075     $code .= "    TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n";
   2076     $code .= "}\n\n";
   2077     $code .= "#endif // ${conditionalString}\n\n" if $conditionalString;
   2078     $implementation{nameSpaceInternal}->add($code);
   2079 }
   2080 
   2081 sub GenerateFunction
   2082 {
   2083     my $function = shift;
   2084     my $interface = shift;
   2085     my $forMainWorldSuffix = shift;
   2086 
   2087     my $interfaceName = $interface->name;
   2088     my $implClassName = GetImplName($interface);
   2089     my $v8ClassName = GetV8ClassName($interface);
   2090     my $name = $function->name;
   2091     my $implName = GetImplName($function);
   2092     my $funcExt = $function->extendedAttributes;
   2093 
   2094     if (HasCustomMethod($funcExt) || $name eq "") {
   2095         return;
   2096     }
   2097 
   2098     if (@{$function->{overloads}} > 1) {
   2099         # Append a number to an overloaded method's name to make it unique:
   2100         $name = $name . $function->{overloadIndex};
   2101     }
   2102 
   2103     my $conditionalString = GenerateConditionalString($function);
   2104     my $code = "";
   2105     $code .= "#if ${conditionalString}\n\n" if $conditionalString;
   2106     $code .= "static void ${name}Method${forMainWorldSuffix}(const v8::FunctionCallbackInfo<v8::Value>& args)\n";
   2107     $code .= "{\n";
   2108 
   2109     if ($name eq "addEventListener" || $name eq "removeEventListener") {
   2110         my $lookupType = ($name eq "addEventListener") ? "OrCreate" : "Only";
   2111         my $passRefPtrHandling = ($name eq "addEventListener") ? "" : ".get()";
   2112         my $hiddenDependencyAction = ($name eq "addEventListener") ? "create" : "remove";
   2113 
   2114         AddToImplIncludes("bindings/v8/BindingSecurity.h");
   2115         AddToImplIncludes("bindings/v8/V8EventListenerList.h");
   2116         AddToImplIncludes("core/page/DOMWindow.h");
   2117         $code .= <<END;
   2118     EventTarget* impl = ${v8ClassName}::toNative(args.Holder());
   2119     if (DOMWindow* window = impl->toDOMWindow()) {
   2120         if (!BindingSecurity::shouldAllowAccessToFrame(window->frame()))
   2121             return;
   2122 
   2123         if (!window->document())
   2124             return;
   2125     }
   2126 
   2127     RefPtr<EventListener> listener = V8EventListenerList::getEventListener(args[1], false, ListenerFind${lookupType});
   2128     if (listener) {
   2129         V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, stringResource, args[0]);
   2130         impl->${implName}(stringResource, listener${passRefPtrHandling}, args[2]->BooleanValue());
   2131         if (!impl->toNode())
   2132             ${hiddenDependencyAction}HiddenDependency(args.Holder(), args[1], ${v8ClassName}::eventListenerCacheIndex, args.GetIsolate());
   2133     }
   2134 }
   2135 
   2136 END
   2137         $code .= "#endif // ${conditionalString}\n\n" if $conditionalString;
   2138         $implementation{nameSpaceInternal}->add($code);
   2139         return;
   2140     }
   2141 
   2142     $code .= GenerateArgumentsCountCheck($function, $interface);
   2143 
   2144     if ($name eq "set" and IsConstructorTemplate($interface, "TypedArray")) {
   2145         AddToImplIncludes("bindings/v8/custom/V8ArrayBufferViewCustom.h");
   2146         $code .= <<END;
   2147     setWebGLArrayHelper<$implClassName, ${v8ClassName}>(args);
   2148 }
   2149 
   2150 END
   2151         $implementation{nameSpaceInternal}->add($code);
   2152         return;
   2153     }
   2154 
   2155     my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($interfaceName);
   2156 
   2157     if ($svgNativeType) {
   2158         my $nativeClassName = GetNativeType($interfaceName);
   2159         if ($interfaceName =~ /List$/) {
   2160             $code .= "    $nativeClassName imp = ${v8ClassName}::toNative(args.Holder());\n";
   2161         } else {
   2162             AddToImplIncludes("bindings/v8/ExceptionState.h");
   2163             AddToImplIncludes("core/dom/ExceptionCode.h");
   2164             $code .= "    $nativeClassName wrapper = ${v8ClassName}::toNative(args.Holder());\n";
   2165             $code .= "    if (wrapper->isReadOnly()) {\n";
   2166             $code .= "        setDOMException(NoModificationAllowedError, args.GetIsolate());\n";
   2167             $code .= "        return;\n";
   2168             $code .= "    }\n";
   2169             my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($interfaceName);
   2170             $code .= "    $svgWrappedNativeType& impInstance = wrapper->propertyReference();\n";
   2171             $code .= "    $svgWrappedNativeType* imp = &impInstance;\n";
   2172         }
   2173     } elsif (!$function->isStatic) {
   2174         $code .= <<END;
   2175     ${implClassName}* imp = ${v8ClassName}::toNative(args.Holder());
   2176 END
   2177     }
   2178 
   2179     $code .= GenerateCustomElementInvocationScopeIfNeeded($funcExt);
   2180 
   2181     # Check domain security if needed
   2182     if ($interface->extendedAttributes->{"CheckSecurity"} && !$function->extendedAttributes->{"DoNotCheckSecurity"}) {
   2183         # We have not find real use cases yet.
   2184         AddToImplIncludes("core/page/Frame.h");
   2185         AddToImplIncludes("bindings/v8/BindingSecurity.h");
   2186         $code .= <<END;
   2187     if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame()))
   2188         return;
   2189 END
   2190     }
   2191 
   2192     my $raisesExceptions = $function->extendedAttributes->{"RaisesException"};
   2193     if (!$raisesExceptions) {
   2194         foreach my $parameter (@{$function->parameters}) {
   2195             if ($parameter->extendedAttributes->{"IsIndex"}) {
   2196                 $raisesExceptions = 1;
   2197             }
   2198         }
   2199     }
   2200 
   2201     if ($raisesExceptions) {
   2202         AddToImplIncludes("bindings/v8/ExceptionState.h");
   2203         $code .= "    ExceptionState es(args.GetIsolate());\n";
   2204     }
   2205 
   2206     if ($function->extendedAttributes->{"CheckSecurityForNode"}) {
   2207         AddToImplIncludes("bindings/v8/BindingSecurity.h");
   2208         $code .= "    if (!BindingSecurity::shouldAllowAccessToNode(imp->" . GetImplName($function) . "(es))) {\n";
   2209         $code .= "        v8SetReturnValueNull(args);\n";
   2210         $code .= "        return;\n";
   2211         $code .= "    }\n";
   2212 END
   2213     }
   2214 
   2215     my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersCheck($function, $interface, $forMainWorldSuffix);
   2216     $code .= $parameterCheckString;
   2217 
   2218     # Build the function call string.
   2219     $code .= GenerateFunctionCallString($function, $paramIndex, "    ", $interface, $forMainWorldSuffix, %replacements);
   2220     $code .= "}\n\n";
   2221     $code .= "#endif // ${conditionalString}\n\n" if $conditionalString;
   2222     $implementation{nameSpaceInternal}->add($code);
   2223 }
   2224 
   2225 sub GenerateCallWith
   2226 {
   2227     my $callWith = shift;
   2228     return ([], "") unless $callWith;
   2229     my $indent = shift;
   2230     my $returnVoid = shift;
   2231     my $function = shift;
   2232     my $code = "";
   2233 
   2234     my @callWithArgs;
   2235     if (ExtendedAttributeContains($callWith, "ScriptState")) {
   2236         $code .= $indent . "ScriptState* currentState = ScriptState::current();\n";
   2237         $code .= $indent . "if (!currentState)\n";
   2238         $code .= $indent . "    return" . ($returnVoid ? "" : " v8Undefined()") . ";\n";
   2239         $code .= $indent . "ScriptState& state = *currentState;\n";
   2240         push(@callWithArgs, "&state");
   2241     }
   2242     if (ExtendedAttributeContains($callWith, "ScriptExecutionContext")) {
   2243         $code .= $indent . "ScriptExecutionContext* scriptContext = getScriptExecutionContext();\n";
   2244         push(@callWithArgs, "scriptContext");
   2245     }
   2246     if ($function and ExtendedAttributeContains($callWith, "ScriptArguments")) {
   2247         $code .= $indent . "RefPtr<ScriptArguments> scriptArguments(createScriptArguments(args, " . @{$function->parameters} . "));\n";
   2248         push(@callWithArgs, "scriptArguments.release()");
   2249         AddToImplIncludes("bindings/v8/ScriptCallStackFactory.h");
   2250         AddToImplIncludes("core/inspector/ScriptArguments.h");
   2251     }
   2252     if (ExtendedAttributeContains($callWith, "ActiveWindow")) {
   2253         push(@callWithArgs, "activeDOMWindow()");
   2254     }
   2255     if (ExtendedAttributeContains($callWith, "FirstWindow")) {
   2256         push(@callWithArgs, "firstDOMWindow()");
   2257     }
   2258     return ([@callWithArgs], $code);
   2259 }
   2260 
   2261 sub GenerateArgumentsCountCheck
   2262 {
   2263     my $function = shift;
   2264     my $interface = shift;
   2265 
   2266     my $numMandatoryParams = 0;
   2267     my $allowNonOptional = 1;
   2268     foreach my $param (@{$function->parameters}) {
   2269         if ($param->isOptional or $param->isVariadic) {
   2270             $allowNonOptional = 0;
   2271         } else {
   2272             die "An argument must not be declared to be optional unless all subsequent arguments to the operation are also optional." if !$allowNonOptional;
   2273             $numMandatoryParams++;
   2274         }
   2275     }
   2276 
   2277     my $argumentsCountCheckString = "";
   2278     if ($numMandatoryParams >= 1) {
   2279         $argumentsCountCheckString .= "    if (args.Length() < $numMandatoryParams) {\n";
   2280         $argumentsCountCheckString .= "        throwNotEnoughArgumentsError(args.GetIsolate());\n";
   2281         $argumentsCountCheckString .= "        return;\n";
   2282         $argumentsCountCheckString .= "    }\n";
   2283     }
   2284     return $argumentsCountCheckString;
   2285 }
   2286 
   2287 sub GenerateParametersCheck
   2288 {
   2289     my $function = shift;
   2290     my $interface = shift;
   2291     my $forMainWorldSuffix = shift;
   2292     my $style = shift || "new";
   2293 
   2294     my $parameterCheckString = "";
   2295     my $paramIndex = 0;
   2296     my %replacements = ();
   2297 
   2298     foreach my $parameter (@{$function->parameters}) {
   2299         my $nativeType = GetNativeType($parameter->type, $parameter->extendedAttributes, "parameter");
   2300 
   2301         # Optional arguments without [Default=...] should generate an early call with fewer arguments.
   2302         # Optional arguments with [Optional=...] should not generate the early call.
   2303         # Optional Dictionary arguments always considered to have default of empty dictionary.
   2304         if ($parameter->isOptional && !$parameter->extendedAttributes->{"Default"} && $nativeType ne "Dictionary" && !IsCallbackInterface($parameter->type)) {
   2305             $parameterCheckString .= "    if (args.Length() <= $paramIndex)";
   2306             my $functionCall = GenerateFunctionCallString($function, $paramIndex, "    " x 2, $interface, $forMainWorldSuffix, %replacements);
   2307             my $multiLine = ($functionCall =~ tr/\n//) > 1;
   2308             $parameterCheckString .= $multiLine ? " {\n" : "\n";
   2309             $parameterCheckString .= $functionCall;
   2310             $parameterCheckString .= $multiLine ? "    }\n" : "\n";
   2311         }
   2312 
   2313         my $parameterName = $parameter->name;
   2314         AddToImplIncludes("bindings/v8/ExceptionState.h");
   2315         if (IsCallbackInterface($parameter->type)) {
   2316             my $v8ClassName = "V8" . $parameter->type;
   2317             AddToImplIncludes("$v8ClassName.h");
   2318             if ($parameter->isOptional) {
   2319                 $parameterCheckString .= "    RefPtr<" . $parameter->type . "> $parameterName;\n";
   2320                 $parameterCheckString .= "    if (args.Length() > $paramIndex && !args[$paramIndex]->IsNull() && !args[$paramIndex]->IsUndefined()) {\n";
   2321                 $parameterCheckString .= "        if (!args[$paramIndex]->IsFunction()) {\n";
   2322                 $parameterCheckString .= "            throwTypeError(args.GetIsolate());\n";
   2323                 $parameterCheckString .= "            return;\n";
   2324                 $parameterCheckString .= "        }\n";
   2325                 $parameterCheckString .= "        $parameterName = ${v8ClassName}::create(args[$paramIndex], getScriptExecutionContext());\n";
   2326                 $parameterCheckString .= "    }\n";
   2327             } else {
   2328                 $parameterCheckString .= "    if (args.Length() <= $paramIndex || ";
   2329                 if ($parameter->isNullable) {
   2330                     $parameterCheckString .= "!(args[$paramIndex]->IsFunction() || args[$paramIndex]->IsNull())";
   2331                 } else {
   2332                     $parameterCheckString .= "!args[$paramIndex]->IsFunction()";
   2333                 }
   2334                 $parameterCheckString .= ") {\n";
   2335                 $parameterCheckString .= "        throwTypeError(args.GetIsolate());\n";
   2336                 $parameterCheckString .= "        return;\n";
   2337                 $parameterCheckString .= "    }\n";
   2338                 $parameterCheckString .= "    RefPtr<" . $parameter->type . "> $parameterName = ";
   2339                 $parameterCheckString .= "args[$paramIndex]->IsNull() ? 0 : " if $parameter->isNullable;
   2340                 $parameterCheckString .= "${v8ClassName}::create(args[$paramIndex], getScriptExecutionContext());\n";
   2341             }
   2342         } elsif ($parameter->extendedAttributes->{"Clamp"}) {
   2343                 my $nativeValue = "${parameterName}NativeValue";
   2344                 my $paramType = $parameter->type;
   2345                 $parameterCheckString .= "    $paramType $parameterName = 0;\n";
   2346                 $parameterCheckString .= "    V8TRYCATCH_VOID(double, $nativeValue, args[$paramIndex]->NumberValue());\n";
   2347                 $parameterCheckString .= "    if (!std::isnan($nativeValue))\n";
   2348                 $parameterCheckString .= "        $parameterName = clampTo<$paramType>($nativeValue);\n";
   2349         } elsif ($parameter->type eq "SerializedScriptValue") {
   2350             AddToImplIncludes("bindings/v8/SerializedScriptValue.h");
   2351             $parameterCheckString .= "    bool ${parameterName}DidThrow = false;\n";
   2352             $parameterCheckString .= "    $nativeType $parameterName = SerializedScriptValue::create(args[$paramIndex], 0, 0, ${parameterName}DidThrow, args.GetIsolate());\n";
   2353             $parameterCheckString .= "    if (${parameterName}DidThrow)\n";
   2354             $parameterCheckString .= "        return;\n";
   2355         } elsif ($parameter->isVariadic) {
   2356             my $nativeElementType = GetNativeType($parameter->type);
   2357             if ($nativeElementType =~ />$/) {
   2358                 $nativeElementType .= " ";
   2359             }
   2360 
   2361             my $argType = $parameter->type;
   2362             if (IsWrapperType($argType)) {
   2363                 $parameterCheckString .= "    Vector<$nativeElementType> $parameterName;\n";
   2364                 $parameterCheckString .= "    for (int i = $paramIndex; i < args.Length(); ++i) {\n";
   2365                 $parameterCheckString .= "        if (!V8${argType}::HasInstance(args[i], args.GetIsolate(), worldType(args.GetIsolate()))) {\n";
   2366                 $parameterCheckString .= "            throwTypeError(args.GetIsolate());\n";
   2367                 $parameterCheckString .= "            return;\n";
   2368                 $parameterCheckString .= "        }\n";
   2369                 $parameterCheckString .= "        $parameterName.append(V8${argType}::toNative(v8::Handle<v8::Object>::Cast(args[i])));\n";
   2370                 $parameterCheckString .= "    }\n";
   2371             } else {
   2372                 $parameterCheckString .= "    V8TRYCATCH_VOID(Vector<$nativeElementType>, $parameterName, toNativeArguments<$nativeElementType>(args, $paramIndex));\n";
   2373             }
   2374         } elsif ($nativeType =~ /^V8StringResource/) {
   2375             my $default = defined $parameter->extendedAttributes->{"Default"} ? $parameter->extendedAttributes->{"Default"} : "";
   2376             my $jsValue = $parameter->isOptional && $default eq "NullString" ? "argumentOrNull(args, $paramIndex)" : "args[$paramIndex]";
   2377             $parameterCheckString .= JSValueToNativeStatement($parameter->type, $parameter->extendedAttributes, $jsValue, $parameterName, "    ", "args.GetIsolate()");
   2378             if (IsEnumType($parameter->type)) {
   2379                 my @enumValues = ValidEnumValues($parameter->type);
   2380                 my @validEqualities = ();
   2381                 foreach my $enumValue (@enumValues) {
   2382                     push(@validEqualities, "string == \"$enumValue\"");
   2383                 }
   2384                 my $enumValidationExpression = join(" || ", @validEqualities);
   2385                 $parameterCheckString .=  "    String string = $parameterName;\n";
   2386                 $parameterCheckString .= "    if (!($enumValidationExpression)) {\n";
   2387                 $parameterCheckString .= "        throwTypeError(args.GetIsolate());\n";
   2388                 $parameterCheckString .= "        return;\n";
   2389                 $parameterCheckString .= "    }\n";
   2390             }
   2391         } else {
   2392             # If the "StrictTypeChecking" extended attribute is present, and the argument's type is an
   2393             # interface type, then if the incoming value does not implement that interface, a TypeError
   2394             # is thrown rather than silently passing NULL to the C++ code.
   2395             # Per the Web IDL and ECMAScript specifications, incoming values can always be converted
   2396             # to both strings and numbers, so do not throw TypeError if the argument is of these
   2397             # types.
   2398             if ($function->extendedAttributes->{"StrictTypeChecking"}) {
   2399                 my $argValue = "args[$paramIndex]";
   2400                 my $argType = $parameter->type;
   2401                 if (IsWrapperType($argType)) {
   2402                     $parameterCheckString .= "    if (args.Length() > $paramIndex && !isUndefinedOrNull($argValue) && !V8${argType}::HasInstance($argValue, args.GetIsolate(), worldType(args.GetIsolate()))) {\n";
   2403                     $parameterCheckString .= "        throwTypeError(args.GetIsolate());\n";
   2404                     $parameterCheckString .= "        return;\n";
   2405                     $parameterCheckString .= "    }\n";
   2406                 }
   2407             }
   2408             my $default = defined $parameter->extendedAttributes->{"Default"} ? $parameter->extendedAttributes->{"Default"} : "";
   2409             my $jsValue = $parameter->isOptional && $default eq "NullString" ? "argumentOrNull(args, $paramIndex)" : "args[$paramIndex]";
   2410             $parameterCheckString .= JSValueToNativeStatement($parameter->type, $parameter->extendedAttributes, $jsValue, $parameterName, "    ", "args.GetIsolate()");
   2411             if ($nativeType eq 'Dictionary') {
   2412                 $parameterCheckString .= "    if (!$parameterName.isUndefinedOrNull() && !$parameterName.isObject()) {\n";
   2413                 $parameterCheckString .= "        throwTypeError(\"Not an object.\", args.GetIsolate());\n";
   2414                 $parameterCheckString .= "        return;\n";
   2415                 $parameterCheckString .= "    }\n";
   2416             }
   2417         }
   2418 
   2419         if ($parameter->extendedAttributes->{"IsIndex"}) {
   2420             AddToImplIncludes("core/dom/ExceptionCode.h");
   2421             $parameterCheckString .= "    if (UNLIKELY($parameterName < 0)) {\n";
   2422             $parameterCheckString .= "        setDOMException(IndexSizeError, args.GetIsolate());\n";
   2423             $parameterCheckString .= "        return;\n";
   2424             $parameterCheckString .= "    }\n";
   2425         }
   2426 
   2427         $paramIndex++;
   2428     }
   2429     return ($parameterCheckString, $paramIndex, %replacements);
   2430 }
   2431 
   2432 sub GenerateOverloadedConstructorCallback
   2433 {
   2434     my $interface = shift;
   2435     my $implClassName = GetImplName($interface);
   2436 
   2437     my $code = "";
   2438     $code .= <<END;
   2439 static void constructor(const v8::FunctionCallbackInfo<v8::Value>& args)
   2440 {
   2441 END
   2442     my $leastNumMandatoryParams = 255;
   2443     foreach my $constructor (@{$interface->constructors}) {
   2444         my $name = "constructor" . $constructor->overloadedIndex;
   2445         my ($numMandatoryParams, $parametersCheck) = GenerateFunctionParametersCheck($constructor);
   2446         $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams < $leastNumMandatoryParams);
   2447         $code .= "    if ($parametersCheck) {\n";
   2448         $code .= "        ${implClassName}V8Internal::${name}(args);\n";
   2449         $code .= "        return;\n";
   2450         $code .= "    }\n";
   2451     }
   2452     if ($leastNumMandatoryParams >= 1) {
   2453         $code .= "    if (args.Length() < $leastNumMandatoryParams) {\n";
   2454         $code .= "        throwNotEnoughArgumentsError(args.GetIsolate());\n";
   2455         $code .= "        return;\n";
   2456         $code .= "    }\n";
   2457     }
   2458     $code .= <<END;
   2459     throwTypeError(args.GetIsolate());
   2460     return;
   2461 END
   2462     $code .= "}\n\n";
   2463     $implementation{nameSpaceInternal}->add($code);
   2464 }
   2465 
   2466 sub GenerateSingleConstructorCallback
   2467 {
   2468     my $interface = shift;
   2469     my $function = shift;
   2470 
   2471     my $implClassName = GetImplName($interface);
   2472     my $v8ClassName = GetV8ClassName($interface);
   2473     my $overloadedIndexString = "";
   2474     if ($function->overloadedIndex > 0) {
   2475         $overloadedIndexString .= $function->overloadedIndex;
   2476     }
   2477 
   2478     my $raisesExceptions = $function->extendedAttributes->{"RaisesException"};
   2479     if ($interface->extendedAttributes->{"ConstructorRaisesException"}) {
   2480         $raisesExceptions = 1;
   2481     }
   2482     if (!$raisesExceptions) {
   2483         foreach my $parameter (@{$function->parameters}) {
   2484             if ($parameter->extendedAttributes->{"IsIndex"}) {
   2485                 $raisesExceptions = 1;
   2486             }
   2487         }
   2488     }
   2489 
   2490     my @beforeArgumentList;
   2491     my @afterArgumentList;
   2492     my $code = "";
   2493     $code .= <<END;
   2494 static void constructor${overloadedIndexString}(const v8::FunctionCallbackInfo<v8::Value>& args)
   2495 {
   2496 END
   2497 
   2498     if ($function->overloadedIndex == 0) {
   2499         $code .= GenerateArgumentsCountCheck($function, $interface);
   2500     }
   2501 
   2502     if ($raisesExceptions) {
   2503         AddToImplIncludes("bindings/v8/ExceptionState.h");
   2504         $code .= "    ExceptionState es(args.GetIsolate());\n";
   2505     }
   2506 
   2507     # FIXME: Currently [Constructor(...)] does not yet support optional arguments without [Default=...]
   2508     my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersCheck($function, $interface, "");
   2509     $code .= $parameterCheckString;
   2510 
   2511     if ($interface->extendedAttributes->{"ConstructorCallWith"}) {
   2512         if ($interface->extendedAttributes->{"ConstructorCallWith"} eq "ScriptExecutionContext") {
   2513             push(@beforeArgumentList, "context");
   2514             $code .= "\n";
   2515             $code .= "    ScriptExecutionContext* context = getScriptExecutionContext();";
   2516         } elsif ($interface->extendedAttributes->{"ConstructorCallWith"} eq "Document") {
   2517             push(@beforeArgumentList, "document");
   2518             $code .= "\n";
   2519             $code .= "    Document* document = toDocument(getScriptExecutionContext());";
   2520         }
   2521     }
   2522 
   2523     if ($interface->extendedAttributes->{"ConstructorRaisesException"}) {
   2524         push(@afterArgumentList, "es");
   2525     }
   2526 
   2527     my @argumentList;
   2528     my $index = 0;
   2529     foreach my $parameter (@{$function->parameters}) {
   2530         last if $index eq $paramIndex;
   2531         if ($replacements{$parameter->name}) {
   2532             push(@argumentList, $replacements{$parameter->name});
   2533         } else {
   2534             push(@argumentList, $parameter->name);
   2535         }
   2536         $index++;
   2537     }
   2538 
   2539     my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterArgumentList);
   2540     $code .= "\n";
   2541     $code .= "    RefPtr<${implClassName}> impl = ${implClassName}::create(${argumentString});\n";
   2542     $code .= "    v8::Handle<v8::Object> wrapper = args.Holder();\n";
   2543 
   2544     if ($interface->extendedAttributes->{"ConstructorRaisesException"}) {
   2545         $code .= "    if (es.throwIfNeeded())\n";
   2546         $code .= "        return;\n";
   2547     }
   2548 
   2549     $code .= <<END;
   2550 
   2551     V8DOMWrapper::associateObjectWithWrapper<${v8ClassName}>(impl.release(), &${v8ClassName}::info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
   2552     args.GetReturnValue().Set(wrapper);
   2553 }
   2554 
   2555 END
   2556     $implementation{nameSpaceInternal}->add($code);
   2557 }
   2558 
   2559 # The Web IDL specification states that Interface objects for interfaces MUST have a property named
   2560 # "length" that returns the length of the shortest argument list of the entries in the effective
   2561 # overload set for constructors. In other words, use the lowest number of mandatory arguments among
   2562 # all constructors.
   2563 sub GetInterfaceLength
   2564 {
   2565     my $interface = shift;
   2566 
   2567     my $leastConstructorLength = 0;
   2568     if (IsConstructorTemplate($interface, "Event") || IsConstructorTemplate($interface, "TypedArray")) {
   2569         $leastConstructorLength = 1;
   2570     } elsif ($interface->extendedAttributes->{"Constructor"} || $interface->extendedAttributes->{"CustomConstructor"}) {
   2571         my @constructors = @{$interface->constructors};
   2572         my @customConstructors = @{$interface->customConstructors};
   2573         $leastConstructorLength = 255;
   2574         foreach my $constructor (@constructors, @customConstructors) {
   2575             my $constructorLength = GetFunctionLength($constructor);
   2576             $leastConstructorLength = $constructorLength if ($constructorLength < $leastConstructorLength);
   2577         }
   2578     }
   2579 
   2580     return $leastConstructorLength;
   2581 }
   2582 
   2583 sub GenerateConstructorCallback
   2584 {
   2585     my $interface = shift;
   2586 
   2587     my $implClassName = GetImplName($interface);
   2588     my $v8ClassName = GetV8ClassName($interface);
   2589     my $code = "";
   2590     $code .= "void ${v8ClassName}::constructorCallback(const v8::FunctionCallbackInfo<v8::Value>& args)\n";
   2591     $code .= "{\n";
   2592     $code .= "    TRACE_EVENT_SCOPED_SAMPLING_STATE(\"Blink\", \"DOMConstructor\");\n";
   2593     $code .= GenerateFeatureObservation($interface->extendedAttributes->{"MeasureAs"});
   2594     $code .= GenerateDeprecationNotification($interface->extendedAttributes->{"DeprecateAs"});
   2595     $code .= GenerateConstructorHeader();
   2596     if (HasCustomConstructor($interface)) {
   2597         $code .= "    ${v8ClassName}::constructorCustom(args);\n";
   2598     } else {
   2599         $code .= "    ${implClassName}V8Internal::constructor(args);\n";
   2600     }
   2601     $code .= "}\n\n";
   2602     $implementation{nameSpaceWebCore}->add($code);
   2603 }
   2604 
   2605 sub GenerateConstructor
   2606 {
   2607     my $interface = shift;
   2608 
   2609     if (@{$interface->constructors} == 1) {
   2610         GenerateSingleConstructorCallback($interface, @{$interface->constructors}[0]);
   2611     } else {
   2612         foreach my $constructor (@{$interface->constructors}) {
   2613             GenerateSingleConstructorCallback($interface, $constructor);
   2614         }
   2615         GenerateOverloadedConstructorCallback($interface);
   2616     }
   2617 }
   2618 
   2619 sub GenerateEventConstructor
   2620 {
   2621     my $interface = shift;
   2622     my $implClassName = GetImplName($interface);
   2623     my $v8ClassName = GetV8ClassName($interface);
   2624 
   2625     my @anyAttributeNames;
   2626     my @serializableAnyAttributeNames;
   2627     foreach my $attribute (@{$interface->attributes}) {
   2628         if ($attribute->type eq "any") {
   2629             push(@anyAttributeNames, $attribute->name);
   2630             if (!$attribute->extendedAttributes->{"Unserializable"}) {
   2631                 push(@serializableAnyAttributeNames, $attribute->name);
   2632             }
   2633         }
   2634     }
   2635 
   2636     AddToImplIncludes("bindings/v8/Dictionary.h");
   2637     $implementation{nameSpaceInternal}->add(<<END);
   2638 static void constructor(const v8::FunctionCallbackInfo<v8::Value>& args)
   2639 {
   2640     if (args.Length() < 1) {
   2641         throwNotEnoughArgumentsError(args.GetIsolate());
   2642         return;
   2643     }
   2644 
   2645     V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, type, args[0]);
   2646 END
   2647 
   2648     foreach my $attrName (@anyAttributeNames) {
   2649         $implementation{nameSpaceInternal}->add("    v8::Local<v8::Value> ${attrName};\n");
   2650     }
   2651 
   2652     $implementation{nameSpaceInternal}->add(<<END);
   2653     ${implClassName}Init eventInit;
   2654     if (args.Length() >= 2) {
   2655         V8TRYCATCH_VOID(Dictionary, options, Dictionary(args[1], args.GetIsolate()));
   2656         if (!fill${implClassName}Init(eventInit, options))
   2657             return;
   2658 END
   2659 
   2660     # Store 'any'-typed properties on the wrapper to avoid leaking them between isolated worlds.
   2661     foreach my $attrName (@anyAttributeNames) {
   2662         $implementation{nameSpaceInternal}->add(<<END);
   2663         options.get("${attrName}", ${attrName});
   2664         if (!${attrName}.IsEmpty())
   2665             args.Holder()->SetHiddenValue(V8HiddenPropertyName::${attrName}(), ${attrName});
   2666 END
   2667     }
   2668 
   2669     $implementation{nameSpaceInternal}->add(<<END);
   2670     }
   2671 
   2672     RefPtr<${implClassName}> event = ${implClassName}::create(type, eventInit);
   2673 END
   2674 
   2675     if (@serializableAnyAttributeNames) {
   2676         # If we're in an isolated world, create a SerializedScriptValue and store it in the event for
   2677         # later cloning if the property is accessed from another world.
   2678         # The main world case is handled lazily (in Custom code).
   2679         $implementation{nameSpaceInternal}->add("    if (isolatedWorldForIsolate(args.GetIsolate())) {\n");
   2680         foreach my $attrName (@serializableAnyAttributeNames) {
   2681             my $setter = "setSerialized" . FirstLetterToUpperCase($attrName);
   2682             $implementation{nameSpaceInternal}->add(<<END);
   2683         if (!${attrName}.IsEmpty())
   2684             event->${setter}(SerializedScriptValue::createAndSwallowExceptions(${attrName}, args.GetIsolate()));
   2685 END
   2686         }
   2687         $implementation{nameSpaceInternal}->add("    }\n\n");
   2688     }
   2689 
   2690     $implementation{nameSpaceInternal}->add(<<END);
   2691     v8::Handle<v8::Object> wrapper = args.Holder();
   2692     V8DOMWrapper::associateObjectWithWrapper<${v8ClassName}>(event.release(), &${v8ClassName}::info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
   2693     v8SetReturnValue(args, wrapper);
   2694 }
   2695 END
   2696 
   2697     my $code = "";
   2698     $code .= <<END;
   2699 bool fill${implClassName}Init(${implClassName}Init& eventInit, const Dictionary& options)
   2700 {
   2701 END
   2702 
   2703     if ($interface->parent) {
   2704         my $interfaceBase = $interface->parent;
   2705         $code .= <<END;
   2706     if (!fill${interfaceBase}Init(eventInit, options))
   2707         return false;
   2708 
   2709 END
   2710     }
   2711 
   2712     foreach my $attribute (@{$interface->attributes}) {
   2713         if ($attribute->extendedAttributes->{"InitializedByEventConstructor"}) {
   2714             if ($attribute->type ne "any") {
   2715                 my $attributeName = $attribute->name;
   2716                 my $attributeImplName = GetImplName($attribute);
   2717                 my $deprecation = $attribute->extendedAttributes->{"DeprecateAs"};
   2718                 my $dictionaryGetter = "options.get(\"$attributeName\", eventInit.$attributeImplName)";
   2719                 if ($attribute->extendedAttributes->{"DeprecateAs"}) {
   2720                     $code .= "    if ($dictionaryGetter)\n";
   2721                     $code .= "    " . GenerateDeprecationNotification($attribute->extendedAttributes->{"DeprecateAs"});
   2722                 } else {
   2723                     $code .= "    $dictionaryGetter;\n";
   2724                 }
   2725             }
   2726         }
   2727     }
   2728 
   2729     $code .= <<END;
   2730     return true;
   2731 }
   2732 
   2733 END
   2734     $implementation{nameSpaceWebCore}->add($code);
   2735 }
   2736 
   2737 sub GenerateNamedConstructor
   2738 {
   2739     my $function = shift;
   2740     my $interface = shift;
   2741 
   2742     my $implClassName = GetImplName($interface);
   2743     my $v8ClassName = GetV8ClassName($interface);
   2744     my $raisesExceptions = $function->extendedAttributes->{"RaisesException"};
   2745     if ($interface->extendedAttributes->{"ConstructorRaisesException"}) {
   2746         $raisesExceptions = 1;
   2747     }
   2748     if (!$raisesExceptions) {
   2749         foreach my $parameter (@{$function->parameters}) {
   2750             if ($parameter->extendedAttributes->{"IsIndex"}) {
   2751                 $raisesExceptions = 1;
   2752             }
   2753         }
   2754     }
   2755 
   2756     my $maybeObserveFeature = GenerateFeatureObservation($function->extendedAttributes->{"MeasureAs"});
   2757     my $maybeDeprecateFeature = GenerateDeprecationNotification($function->extendedAttributes->{"DeprecateAs"});
   2758 
   2759     my @beforeArgumentList;
   2760     my @afterArgumentList;
   2761 
   2762     my $toActiveDOMObject = "0";
   2763     if (InheritsExtendedAttribute($interface, "ActiveDOMObject")) {
   2764         $toActiveDOMObject = "${v8ClassName}::toActiveDOMObject";
   2765     }
   2766 
   2767     my $toEventTarget = "0";
   2768     if (InheritsInterface($interface, "EventTarget")) {
   2769         $toEventTarget = "${v8ClassName}::toEventTarget";
   2770     }
   2771 
   2772     AddToImplIncludes("core/page/Frame.h");
   2773     $implementation{nameSpaceWebCore}->add(<<END);
   2774 WrapperTypeInfo ${v8ClassName}Constructor::info = { ${v8ClassName}Constructor::GetTemplate, ${v8ClassName}::derefObject, $toActiveDOMObject, $toEventTarget, 0, ${v8ClassName}::installPerContextPrototypeProperties, 0, WrapperTypeObjectPrototype };
   2775 
   2776 END
   2777 
   2778     my $code = "";
   2779     $code .= <<END;
   2780 static void ${v8ClassName}ConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& args)
   2781 {
   2782 END
   2783     $code .= $maybeObserveFeature if $maybeObserveFeature;
   2784     $code .= $maybeDeprecateFeature if $maybeDeprecateFeature;
   2785     $code .= GenerateConstructorHeader();
   2786     AddToImplIncludes("V8Document.h");
   2787     $code .= <<END;
   2788     Document* document = currentDocument();
   2789 
   2790     // Make sure the document is added to the DOM Node map. Otherwise, the ${implClassName} instance
   2791     // may end up being the only node in the map and get garbage-collected prematurely.
   2792     toV8(document, args.Holder(), args.GetIsolate());
   2793 
   2794 END
   2795 
   2796     $code .= GenerateArgumentsCountCheck($function, $interface);
   2797 
   2798     if ($raisesExceptions) {
   2799         AddToImplIncludes("bindings/v8/ExceptionState.h");
   2800         $code .= "    ExceptionState es(args.GetIsolate());\n";
   2801     }
   2802 
   2803     my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersCheck($function, $interface);
   2804     $code .= $parameterCheckString;
   2805 
   2806     push(@beforeArgumentList, "document");
   2807 
   2808     if ($interface->extendedAttributes->{"ConstructorRaisesException"}) {
   2809         push(@afterArgumentList, "es");
   2810     }
   2811 
   2812     my @argumentList;
   2813     my $index = 0;
   2814     foreach my $parameter (@{$function->parameters}) {
   2815         last if $index eq $paramIndex;
   2816         if ($replacements{$parameter->name}) {
   2817             push(@argumentList, $replacements{$parameter->name});
   2818         } else {
   2819             push(@argumentList, $parameter->name);
   2820         }
   2821         $index++;
   2822     }
   2823 
   2824     my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterArgumentList);
   2825     $code .= "\n";
   2826     $code .= "    RefPtr<${implClassName}> impl = ${implClassName}::createForJSConstructor(${argumentString});\n";
   2827     $code .= "    v8::Handle<v8::Object> wrapper = args.Holder();\n";
   2828 
   2829     if ($interface->extendedAttributes->{"ConstructorRaisesException"}) {
   2830         $code .= "    if (es.throwIfNeeded())\n";
   2831         $code .= "        return;\n";
   2832     }
   2833 
   2834     $code .= <<END;
   2835 
   2836     V8DOMWrapper::associateObjectWithWrapper<${v8ClassName}>(impl.release(), &${v8ClassName}Constructor::info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
   2837     args.GetReturnValue().Set(wrapper);
   2838 }
   2839 
   2840 END
   2841     $implementation{nameSpaceWebCore}->add($code);
   2842 
   2843     $code = <<END;
   2844 v8::Handle<v8::FunctionTemplate> ${v8ClassName}Constructor::GetTemplate(v8::Isolate* isolate, WrapperWorldType currentWorldType)
   2845 {
   2846     // This is only for getting a unique pointer which we can pass to privateTemplate.
   2847     static const char* privateTemplateUniqueKey = "${v8ClassName}Constructor::GetTemplatePrivateTemplate";
   2848     V8PerIsolateData* data = V8PerIsolateData::from(isolate);
   2849     v8::Handle<v8::FunctionTemplate> result = data->privateTemplateIfExists(currentWorldType, &privateTemplateUniqueKey);
   2850     if (!result.IsEmpty())
   2851         return result;
   2852 
   2853     TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink\", \"BuildDOMTemplate");
   2854     v8::HandleScope scope(isolate);
   2855     result = v8::FunctionTemplate::New(${v8ClassName}ConstructorCallback);
   2856 
   2857     v8::Local<v8::ObjectTemplate> instance = result->InstanceTemplate();
   2858     instance->SetInternalFieldCount(${v8ClassName}::internalFieldCount);
   2859     result->SetClassName(v8::String::NewSymbol("${implClassName}"));
   2860     result->Inherit(${v8ClassName}::GetTemplate(isolate, currentWorldType));
   2861     data->setPrivateTemplate(currentWorldType, &privateTemplateUniqueKey, result);
   2862 
   2863     return scope.Close(result);
   2864 }
   2865 
   2866 END
   2867     $implementation{nameSpaceWebCore}->add($code);
   2868 }
   2869 
   2870 sub GenerateConstructorHeader
   2871 {
   2872     AddToImplIncludes("bindings/v8/V8ObjectConstructor.h");
   2873     my $content = <<END;
   2874     if (!args.IsConstructCall()) {
   2875         throwTypeError("DOM object constructor cannot be called as a function.", args.GetIsolate());
   2876         return;
   2877     }
   2878 
   2879     if (ConstructorMode::current() == ConstructorMode::WrapExistingObject) {
   2880         args.GetReturnValue().Set(args.Holder());
   2881         return;
   2882     }
   2883 
   2884 END
   2885     return $content;
   2886 }
   2887 
   2888 sub GenerateBatchedAttributeData
   2889 {
   2890     my $interface = shift;
   2891     my $attributes = shift;
   2892     my $code = "";
   2893 
   2894     foreach my $attribute (@$attributes) {
   2895         my $conditionalString = GenerateConditionalString($attribute);
   2896         my $subCode = "";
   2897         $subCode .= "#if ${conditionalString}\n" if $conditionalString;
   2898         $subCode .= GenerateSingleBatchedAttribute($interface, $attribute, ",", "");
   2899         $subCode .= "#endif // ${conditionalString}\n" if $conditionalString;
   2900         $code .= $subCode;
   2901     }
   2902     return $code;
   2903 }
   2904 
   2905 sub GenerateSingleBatchedAttribute
   2906 {
   2907     my $interface = shift;
   2908     my $attribute = shift;
   2909     my $delimiter = shift;
   2910     my $indent = shift;
   2911     my $code = "";
   2912     my $attrName = $attribute->name;
   2913     my $attrExt = $attribute->extendedAttributes;
   2914     my $implClassName = GetImplName($interface);
   2915 
   2916     my $accessControl = "v8::DEFAULT";
   2917     if ($attrExt->{"DoNotCheckSecurityOnGetter"}) {
   2918         $accessControl = "v8::ALL_CAN_READ";
   2919     } elsif ($attrExt->{"DoNotCheckSecurityOnSetter"}) {
   2920         $accessControl = "v8::ALL_CAN_WRITE";
   2921     } elsif ($attrExt->{"DoNotCheckSecurity"}) {
   2922         $accessControl = "v8::ALL_CAN_READ";
   2923         if (!IsReadonly($attribute)) {
   2924             $accessControl .= " | v8::ALL_CAN_WRITE";
   2925         }
   2926     }
   2927     if ($attrExt->{"Unforgeable"}) {
   2928         $accessControl .= " | v8::PROHIBITS_OVERWRITING";
   2929     }
   2930     $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")";
   2931 
   2932     my $customAccessor = HasCustomGetter($attrExt) || HasCustomSetter($attrExt) || "";
   2933     if ($customAccessor eq "VALUE_IS_MISSING") {
   2934         # use the naming convension, interface + (capitalize) attr name
   2935         $customAccessor = $implClassName . "::" . $attrName;
   2936     }
   2937 
   2938     my $getter;
   2939     my $setter;
   2940     my $getterForMainWorld;
   2941     my $setterForMainWorld;
   2942     my $propAttr = "v8::None";
   2943 
   2944     my $isConstructor = ($attribute->type =~ /Constructor$/);
   2945 
   2946     # Check attributes.
   2947     # As per Web IDL specification, constructor properties on the ECMAScript global object should be
   2948     # configurable and should not be enumerable.
   2949     if ($attrExt->{"NotEnumerable"} || $isConstructor) {
   2950         $propAttr .= " | v8::DontEnum";
   2951     }
   2952     if ($attrExt->{"Unforgeable"} && !$isConstructor) {
   2953         $propAttr .= " | v8::DontDelete";
   2954     }
   2955 
   2956     my $on_proto = "0 /* on instance */";
   2957     my $data = "0 /* no data */";
   2958 
   2959     # Constructor
   2960     if ($isConstructor) {
   2961         my $constructorType = $attribute->type;
   2962         $constructorType =~ s/Constructor$//;
   2963         # $constructorType ~= /Constructor$/ indicates that it is NamedConstructor.
   2964         # We do not generate the header file for NamedConstructor of class XXXX,
   2965         # since we generate the NamedConstructor declaration into the header file of class XXXX.
   2966         if ($constructorType !~ /Constructor$/ || $attribute->extendedAttributes->{"CustomConstructor"}) {
   2967             AddToImplIncludes("V8${constructorType}.h");
   2968         }
   2969         $data = "&V8${constructorType}::info";
   2970         $getter = "${implClassName}V8Internal::${implClassName}ConstructorGetter";
   2971         $setter = "${implClassName}V8Internal::${implClassName}ReplaceableAttrSetterCallback";
   2972         $getterForMainWorld = "0";
   2973         $setterForMainWorld = "0";
   2974     } else {
   2975         # Default Getter and Setter
   2976         $getter = "${implClassName}V8Internal::${attrName}AttrGetterCallback";
   2977         $setter = "${implClassName}V8Internal::${attrName}AttrSetterCallback";
   2978         $getterForMainWorld = "${getter}ForMainWorld";
   2979         $setterForMainWorld = "${setter}ForMainWorld";
   2980 
   2981         if (!HasCustomSetter($attrExt) && $attrExt->{"Replaceable"}) {
   2982             $setter = "${implClassName}V8Internal::${implClassName}ReplaceableAttrSetterCallback";
   2983             $setterForMainWorld = "0";
   2984         }
   2985     }
   2986 
   2987     # Read only attributes
   2988     if (IsReadonly($attribute)) {
   2989         $setter = "0";
   2990         $setterForMainWorld = "0";
   2991     }
   2992 
   2993     # An accessor can be installed on the proto
   2994     if ($attrExt->{"OnProto"}) {
   2995         $on_proto = "1 /* on proto */";
   2996     }
   2997 
   2998     if (!$attrExt->{"PerWorldBindings"}) {
   2999       $getterForMainWorld = "0";
   3000       $setterForMainWorld = "0";
   3001     }
   3002 
   3003     my $commentInfo = "Attribute '$attrName'";
   3004 
   3005     $code .= $indent . "    \/\/ $commentInfo\n";
   3006     $code .= $indent . "    {\"$attrName\", $getter, $setter, $getterForMainWorld, $setterForMainWorld, $data, $accessControl, static_cast<v8::PropertyAttribute>($propAttr), $on_proto}" . $delimiter . "\n";
   3007     return $code;
   3008 }
   3009 
   3010 sub IsStandardFunction
   3011 {
   3012     my $interface = shift;
   3013     my $function = shift;
   3014 
   3015     my $interfaceName = $interface->name;
   3016     my $attrExt = $function->extendedAttributes;
   3017     return 0 if $attrExt->{"Unforgeable"};
   3018     return 0 if $function->isStatic;
   3019     return 0 if $attrExt->{"EnabledAtRuntime"};
   3020     return 0 if $attrExt->{"EnabledPerContext"};
   3021     return 0 if RequiresCustomSignature($function);
   3022     return 0 if $attrExt->{"DoNotCheckSignature"};
   3023     return 0 if ($attrExt->{"DoNotCheckSecurity"} && ($interface->extendedAttributes->{"CheckSecurity"} || $interfaceName eq "Window"));
   3024     return 0 if $attrExt->{"NotEnumerable"};
   3025     return 0 if $attrExt->{"ReadOnly"};
   3026     return 1;
   3027 }
   3028 
   3029 sub GenerateNonStandardFunction
   3030 {
   3031     my $interface = shift;
   3032     my $function = shift;
   3033     my $code = "";
   3034 
   3035     my $implClassName = GetImplName($interface);
   3036     my $attrExt = $function->extendedAttributes;
   3037     my $name = $function->name;
   3038 
   3039     my $property_attributes = "v8::DontDelete";
   3040     if ($attrExt->{"NotEnumerable"}) {
   3041         $property_attributes .= " | v8::DontEnum";
   3042     }
   3043     if ($attrExt->{"ReadOnly"}) {
   3044         $property_attributes .= " | v8::ReadOnly";
   3045     }
   3046 
   3047     my $commentInfo = "Function '$name' (ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
   3048 
   3049     my $template = "proto";
   3050     if ($attrExt->{"Unforgeable"}) {
   3051         $template = "instance";
   3052     }
   3053     if ($function->isStatic) {
   3054         $template = "desc";
   3055     }
   3056 
   3057     my $conditional = "";
   3058     if ($attrExt->{"EnabledAtRuntime"}) {
   3059         # Only call Set()/SetAccessor() if this method should be enabled
   3060         my $enable_function = GetRuntimeEnableFunctionName($function);
   3061         $conditional = "if (${enable_function}())\n        ";
   3062     }
   3063     if ($attrExt->{"EnabledPerContext"}) {
   3064         # Only call Set()/SetAccessor() if this method should be enabled
   3065         my $enable_function = GetContextEnableFunction($function);
   3066         $conditional = "if (${enable_function}(impl->document()))\n        ";
   3067     }
   3068 
   3069     if ($interface->extendedAttributes->{"CheckSecurity"} && $attrExt->{"DoNotCheckSecurity"}) {
   3070         my $setter = $attrExt->{"ReadOnly"} ? "0" : "${implClassName}V8Internal::${implClassName}DomainSafeFunctionSetter";
   3071         # Functions that are marked DoNotCheckSecurity are always readable but if they are changed
   3072         # and then accessed on a different domain we do not return the underlying value but instead
   3073         # return a new copy of the original function. This is achieved by storing the changed value
   3074         # as hidden property.
   3075         $code .= <<END;
   3076 
   3077     // $commentInfo
   3078     ${conditional}$template->SetAccessor(v8::String::NewSymbol("$name"), ${implClassName}V8Internal::${name}AttrGetterCallback, ${setter}, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>($property_attributes));
   3079 END
   3080         return $code;
   3081     }
   3082 
   3083     my $signature = "defaultSignature";
   3084     if ($attrExt->{"DoNotCheckSignature"} || $function->isStatic) {
   3085        $signature = "v8::Local<v8::Signature>()";
   3086     }
   3087 
   3088     my $conditionalString = GenerateConditionalString($function);
   3089     $code .= "#if ${conditionalString}\n" if $conditionalString;
   3090     if (RequiresCustomSignature($function)) {
   3091         $signature = "${name}Signature";
   3092         $code .= "\n    // Custom Signature '$name'\n" . CreateCustomSignature($function);
   3093     }
   3094 
   3095     if ($property_attributes eq "v8::DontDelete") {
   3096         $property_attributes = "";
   3097     } else {
   3098         $property_attributes = ", static_cast<v8::PropertyAttribute>($property_attributes)";
   3099     }
   3100 
   3101     if ($template eq "proto" && $conditional eq "" && $signature eq "defaultSignature" && $property_attributes eq "") {
   3102         die "This shouldn't happen: Class '$implClassName' $commentInfo\n";
   3103     }
   3104 
   3105     my $functionLength = GetFunctionLength($function);
   3106 
   3107     if ($function->extendedAttributes->{"PerWorldBindings"}) {
   3108         $code .= "    if (currentWorldType == MainWorld) {\n";
   3109         $code .= "        ${conditional}$template->Set(v8::String::NewSymbol(\"$name\"), v8::FunctionTemplate::New(${implClassName}V8Internal::${name}MethodCallbackForMainWorld, v8Undefined(), ${signature}, $functionLength)$property_attributes);\n";
   3110         $code .= "    } else {\n";
   3111         $code .= "        ${conditional}$template->Set(v8::String::NewSymbol(\"$name\"), v8::FunctionTemplate::New(${implClassName}V8Internal::${name}MethodCallback, v8Undefined(), ${signature}, $functionLength)$property_attributes);\n";
   3112         $code .= "    }\n";
   3113     } else {
   3114         $code .= "    ${conditional}$template->Set(v8::String::NewSymbol(\"$name\"), v8::FunctionTemplate::New(${implClassName}V8Internal::${name}MethodCallback, v8Undefined(), ${signature}, $functionLength)$property_attributes);\n";
   3115     }
   3116     $code .= "#endif // ${conditionalString}\n" if $conditionalString;
   3117     return $code;
   3118 }
   3119 
   3120 sub GenerateIsNullExpression
   3121 {
   3122     my $type = shift;
   3123     my $variableName = shift;
   3124     if (IsUnionType($type)) {
   3125         my $types = $type->unionMemberTypes;
   3126         my @expression = ();
   3127         for my $i (0 .. scalar(@$types)-1) {
   3128             my $unionMemberType = $types->[$i];
   3129             my $unionMemberVariable = $variableName . $i;
   3130             my $isNull = GenerateIsNullExpression($unionMemberType, $unionMemberVariable);
   3131             push @expression, $isNull;
   3132         }
   3133         return join " && ", @expression;
   3134     }
   3135     if (IsRefPtrType($type)) {
   3136         return "!${variableName}";
   3137     } elsif ($type eq "DOMString") {
   3138         return "${variableName}.isNull()";
   3139     } else {
   3140         return "";
   3141     }
   3142 }
   3143 
   3144 sub GenerateIfElseStatement
   3145 {
   3146     my $type = shift;
   3147     my $outputVariableName = shift;
   3148     my $conditions = shift;
   3149     my $statements = shift;
   3150 
   3151     my $code = "";
   3152     if (@$conditions == 1) {
   3153         $code .= "    ${type} ${outputVariableName} = " . $statements->[0] . "\n";
   3154     } else {
   3155         $code .= "    ${type} ${outputVariableName};\n";
   3156         for my $i (0 .. @$conditions - 1) {
   3157             my $token = "else if";
   3158             $token = "if" if $i == 0;
   3159             $token = "else" if $i == @$conditions - 1;
   3160             $code .= "    ${token}";
   3161             $code .= " (" . $conditions->[$i] . ")" if $conditions->[$i];
   3162             $code .= "\n";
   3163             $code .= "        ${outputVariableName} = " . $statements->[$i] . "\n";
   3164         }
   3165     }
   3166     return $code;
   3167 }
   3168 
   3169 sub GenerateImplementationIndexedPropertyAccessors
   3170 {
   3171     my $interface = shift;
   3172     my $interfaceName = $interface->name;
   3173     my $implClassName = GetImplName($interface);
   3174     my $v8ClassName = GetV8ClassName($interface);
   3175 
   3176     my $indexedGetterFunction = GetIndexedGetterFunction($interface);
   3177     if ($indexedGetterFunction) {
   3178         my $hasCustomIndexedGetter = $indexedGetterFunction->extendedAttributes->{"Custom"};
   3179         if (!$hasCustomIndexedGetter) {
   3180             GenerateImplementationIndexedPropertyGetter($interface, $indexedGetterFunction);
   3181         }
   3182         GenerateImplementationIndexedPropertyGetterCallback($interface, $hasCustomIndexedGetter);
   3183     }
   3184 
   3185     my $indexedSetterFunction = GetIndexedSetterFunction($interface);
   3186     if ($indexedSetterFunction) {
   3187         my $hasCustomIndexedSetter = $indexedSetterFunction->extendedAttributes->{"Custom"};
   3188         if (!$hasCustomIndexedSetter) {
   3189             GenerateImplementationIndexedPropertySetter($interface, $indexedSetterFunction);
   3190         }
   3191         GenerateImplementationIndexedPropertySetterCallback($interface, $hasCustomIndexedSetter);
   3192     }
   3193 
   3194     my $indexedDeleterFunction = GetIndexedDeleterFunction($interface);
   3195     if ($indexedDeleterFunction) {
   3196         my $hasCustomIndexedDeleter = $indexedDeleterFunction->extendedAttributes->{"Custom"};
   3197         if (!$hasCustomIndexedDeleter) {
   3198             GenerateImplementationIndexedPropertyDeleter($interface, $indexedDeleterFunction);
   3199         }
   3200         GenerateImplementationIndexedPropertyDeleterCallback($interface, $hasCustomIndexedDeleter);
   3201     }
   3202 
   3203     my $indexedEnumeratorFunction = $indexedGetterFunction;
   3204     $indexedEnumeratorFunction = 0 if $indexedGetterFunction && $indexedGetterFunction->extendedAttributes->{"NotEnumerable"};
   3205 
   3206     my $indexedQueryFunction = 0;
   3207     # If there is an enumerator, there MUST be a query method to properly communicate property attributes.
   3208     my $hasQuery = $indexedQueryFunction || $indexedEnumeratorFunction;
   3209 
   3210     my $setOn = "Instance";
   3211 
   3212     # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on Window
   3213     # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
   3214     # get implementation straight out of the Window prototype regardless of what prototype is actually set
   3215     # on the object.
   3216     if ($interfaceName eq "Window") {
   3217         $setOn = "Prototype";
   3218     }
   3219 
   3220     my $code = "";
   3221     if ($indexedGetterFunction || $indexedSetterFunction || $indexedDeleterFunction || $indexedEnumeratorFunction || $hasQuery) {
   3222         $code .= "    desc->${setOn}Template()->SetIndexedPropertyHandler(${implClassName}V8Internal::indexedPropertyGetterCallback";
   3223         $code .= $indexedSetterFunction ? ", ${implClassName}V8Internal::indexedPropertySetterCallback" : ", 0";
   3224         $code .= ", 0"; # IndexedPropertyQuery -- not being used at the moment.
   3225         $code .= $indexedDeleterFunction ? ", ${implClassName}V8Internal::indexedPropertyDeleterCallback" : ", 0";
   3226         $code .= $indexedEnumeratorFunction ? ", indexedPropertyEnumerator<${implClassName}>" : ", 0";
   3227         $code .= ");\n";
   3228     }
   3229 
   3230     return $code;
   3231 }
   3232 
   3233 sub GenerateImplementationIndexedPropertyGetter
   3234 {
   3235     my $interface = shift;
   3236     my $indexedGetterFunction = shift;
   3237     my $implClassName = GetImplName($interface);
   3238     my $v8ClassName = GetV8ClassName($interface);
   3239     my $methodName = GetImplName($indexedGetterFunction);
   3240 
   3241     my $returnType = $indexedGetterFunction->type;
   3242     my $nativeType = GetNativeType($returnType);
   3243     my $nativeValue = "element";
   3244     $nativeValue .= ".release()" if (IsRefPtrType($returnType));
   3245     my $isNull = GenerateIsNullExpression($returnType, "element");
   3246     my $returnJSValueCode = NativeToJSValue($indexedGetterFunction->type, $indexedGetterFunction->extendedAttributes, $nativeValue, "    ", "", "info.Holder()", "info.GetIsolate()", "info", "collection", "", "return");
   3247     my $raisesExceptions = $indexedGetterFunction->extendedAttributes->{"RaisesException"};
   3248     my $methodCallCode = GenerateMethodCall($returnType, "element", "collection->${methodName}", "index", $raisesExceptions);
   3249     my $getterCode = "static void indexedPropertyGetter(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
   3250     $getterCode .= "{\n";
   3251     $getterCode .= "    ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder()));\n";
   3252     $getterCode .= "    ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder());\n";
   3253     if ($raisesExceptions) {
   3254         $getterCode .= "    ExceptionState es(info.GetIsolate());\n";
   3255     }
   3256     $getterCode .= $methodCallCode . "\n";
   3257     if ($raisesExceptions) {
   3258         $getterCode .= "    if (es.throwIfNeeded())\n";
   3259         $getterCode .= "        return;\n";
   3260     }
   3261     if (IsUnionType($returnType)) {
   3262         $getterCode .= "${returnJSValueCode}\n";
   3263         $getterCode .= "    return;\n";
   3264     } else {
   3265         $getterCode .= "    if (${isNull})\n";
   3266         $getterCode .= "        return;\n";
   3267         $getterCode .= $returnJSValueCode . "\n";
   3268     }
   3269     $getterCode .= "}\n\n";
   3270     $implementation{nameSpaceInternal}->add($getterCode);
   3271 }
   3272 
   3273 sub GenerateImplementationIndexedPropertyGetterCallback
   3274 {
   3275     my $interface = shift;
   3276     my $hasCustom = shift;
   3277     my $implClassName = GetImplName($interface);
   3278     my $v8ClassName = GetV8ClassName($interface);
   3279 
   3280     my $code = "static void indexedPropertyGetterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
   3281     $code .= "{\n";
   3282     $code .= "    TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMIndexedProperty\");\n";
   3283     if ($hasCustom) {
   3284         $code .= "    ${v8ClassName}::indexedPropertyGetterCustom(index, info);\n";
   3285     } else {
   3286         $code .= "    ${implClassName}V8Internal::indexedPropertyGetter(index, info);\n";
   3287     }
   3288     $code .= "    TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n";
   3289     $code .= "}\n\n";
   3290     $implementation{nameSpaceInternal}->add($code);
   3291 }
   3292 
   3293 sub GenerateImplementationIndexedPropertySetterCallback
   3294 {
   3295     my $interface = shift;
   3296     my $hasCustom = shift;
   3297     my $implClassName = GetImplName($interface);
   3298     my $v8ClassName = GetV8ClassName($interface);
   3299 
   3300     my $code = "static void indexedPropertySetterCallback(uint32_t index, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
   3301     $code .= "{\n";
   3302     $code .= "    TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMIndexedProperty\");\n";
   3303     if ($hasCustom) {
   3304         $code .= "    ${v8ClassName}::indexedPropertySetterCustom(index, value, info);\n";
   3305     } else {
   3306         $code .= "    ${implClassName}V8Internal::indexedPropertySetter(index, value, info);\n";
   3307     }
   3308     $code .= "    TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n";
   3309     $code .= "}\n\n";
   3310     $implementation{nameSpaceInternal}->add($code);
   3311 }
   3312 
   3313 sub GenerateImplementationIndexedPropertyDeleterCallback
   3314 {
   3315     my $interface = shift;
   3316     my $hasCustom = shift;
   3317     my $implClassName = GetImplName($interface);
   3318     my $v8ClassName = GetV8ClassName($interface);
   3319 
   3320     my $code = "static void indexedPropertyDeleterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info)\n";
   3321     $code .= "{\n";
   3322     $code .= "    TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMIndexedProperty\");\n";
   3323     if ($hasCustom) {
   3324         $code .= "    ${v8ClassName}::indexedPropertyDeleterCustom(index, info);\n";
   3325     } else {
   3326         $code .= "    ${implClassName}V8Internal::indexedPropertyDeleter(index, info);\n";
   3327     }
   3328     $code .= "    TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n";
   3329     $code .= "}\n\n";
   3330     $implementation{nameSpaceInternal}->add($code);
   3331 }
   3332 
   3333 sub GenerateImplementationIndexedPropertySetter
   3334 {
   3335     my $interface = shift;
   3336     my $indexedSetterFunction = shift;
   3337     my $implClassName = GetImplName($interface);
   3338     my $v8ClassName = GetV8ClassName($interface);
   3339     my $methodName = GetImplName($indexedSetterFunction);
   3340 
   3341     my $type = $indexedSetterFunction->parameters->[1]->type;
   3342     my $raisesExceptions = $indexedSetterFunction->extendedAttributes->{"RaisesException"};
   3343     my $treatNullAs = $indexedSetterFunction->parameters->[1]->extendedAttributes->{"TreatNullAs"};
   3344     my $treatUndefinedAs = $indexedSetterFunction->parameters->[1]->extendedAttributes->{"TreatUndefinedAs"};
   3345     my $code = "static void indexedPropertySetter(uint32_t index, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
   3346     $code .= "{\n";
   3347     $code .= "    ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder());\n";
   3348     $code .= JSValueToNativeStatement($indexedSetterFunction->parameters->[1]->type, $indexedSetterFunction->extendedAttributes, "value", "propertyValue", "    ", "info.GetIsolate()");
   3349 
   3350     my $extraArguments = "";
   3351     if ($raisesExceptions) {
   3352         $code .= "    ExceptionState es(info.GetIsolate());\n";
   3353         $extraArguments = ", es";
   3354     }
   3355     my @conditions = ();
   3356     my @statements = ();
   3357     if ($treatNullAs && $treatNullAs ne "NullString") {
   3358         push @conditions, "value->IsNull()";
   3359         push @statements, "collection->${treatNullAs}(index$extraArguments);";
   3360     }
   3361     if ($treatUndefinedAs && $treatUndefinedAs ne "NullString") {
   3362         push @conditions, "value->IsUndefined()";
   3363         push @statements, "collection->${treatUndefinedAs}(index$extraArguments);";
   3364     }
   3365     push @conditions, "";
   3366     push @statements, "collection->${methodName}(index, propertyValue$extraArguments);";
   3367     $code .= GenerateIfElseStatement("bool", "result", \@conditions, \@statements);
   3368 
   3369     $code .= "    if (!result)\n";
   3370     $code .= "        return;\n";
   3371     if ($raisesExceptions) {
   3372         $code .= "    if (es.throwIfNeeded())\n";
   3373         $code .= "        return;\n";
   3374     }
   3375     $code .= "    v8SetReturnValue(info, value);\n";
   3376     $code .= "}\n\n";
   3377     $implementation{nameSpaceInternal}->add($code);
   3378 }
   3379 
   3380 sub GenerateImplementationNamedPropertyAccessors
   3381 {
   3382     my $interface = shift;
   3383 
   3384     my $interfaceName = $interface->name;
   3385     my $implClassName = GetImplName($interface);
   3386     my $v8ClassName = GetV8ClassName($interface);
   3387 
   3388     my $namedGetterFunction = GetNamedGetterFunction($interface);
   3389     if ($namedGetterFunction) {
   3390         my $hasCustomNamedGetter = $namedGetterFunction->extendedAttributes->{"Custom"};
   3391         if (!$hasCustomNamedGetter) {
   3392             GenerateImplementationNamedPropertyGetter($interface, $namedGetterFunction);
   3393         }
   3394         GenerateImplementationNamedPropertyGetterCallback($interface, $hasCustomNamedGetter);
   3395     }
   3396 
   3397     my $namedSetterFunction = GetNamedSetterFunction($interface);
   3398     if ($namedSetterFunction) {
   3399         my $hasCustomNamedSetter = $namedSetterFunction->extendedAttributes->{"Custom"};
   3400         if (!$hasCustomNamedSetter) {
   3401             GenerateImplementationNamedPropertySetter($interface, $namedSetterFunction);
   3402         }
   3403         GenerateImplementationNamedPropertySetterCallback($interface, $hasCustomNamedSetter);
   3404     }
   3405 
   3406     my $namedDeleterFunction = GetNamedDeleterFunction($interface);
   3407     if ($namedDeleterFunction) {
   3408         my $hasCustomNamedDeleter = $namedDeleterFunction->extendedAttributes->{"Custom"};
   3409         if (!$hasCustomNamedDeleter) {
   3410             GenerateImplementationNamedPropertyDeleter($interface, $namedDeleterFunction);
   3411         }
   3412         GenerateImplementationNamedPropertyDeleterCallback($interface, $hasCustomNamedDeleter);
   3413     }
   3414 
   3415     my $namedEnumeratorFunction = $namedGetterFunction && !$namedGetterFunction->extendedAttributes->{"NotEnumerable"};
   3416     if ($namedEnumeratorFunction) {
   3417         my $hasCustomNamedEnumerator = $namedGetterFunction->extendedAttributes->{"CustomEnumerateProperty"};
   3418         if (!$hasCustomNamedEnumerator) {
   3419             GenerateImplementationNamedPropertyEnumerator($interface);
   3420             GenerateImplementationNamedPropertyQuery($interface);
   3421         }
   3422         GenerateImplementationNamedPropertyEnumeratorCallback($interface, $hasCustomNamedEnumerator);
   3423         GenerateImplementationNamedPropertyQueryCallback($interface, $hasCustomNamedEnumerator);
   3424     }
   3425 
   3426     my $subCode = "";
   3427     if ($namedGetterFunction || $namedSetterFunction || $namedDeleterFunction || $namedEnumeratorFunction) {
   3428         my $setOn = "Instance";
   3429 
   3430         # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on Window
   3431         # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
   3432         # get implementation straight out of the Window prototype regardless of what prototype is actually set
   3433         # on the object.
   3434         if ($interfaceName eq "Window") {
   3435             $setOn = "Prototype";
   3436         }
   3437 
   3438         $subCode .= "    desc->${setOn}Template()->SetNamedPropertyHandler(";
   3439         $subCode .= $namedGetterFunction ? "${implClassName}V8Internal::namedPropertyGetterCallback, " : "0, ";
   3440         $subCode .= $namedSetterFunction ? "${implClassName}V8Internal::namedPropertySetterCallback, " : "0, ";
   3441         $subCode .= $namedEnumeratorFunction ? "${implClassName}V8Internal::namedPropertyQueryCallback, " : "0, ";
   3442         $subCode .= $namedDeleterFunction ? "${implClassName}V8Internal::namedPropertyDeleterCallback, " : "0, ";
   3443         $subCode .= $namedEnumeratorFunction ? "${implClassName}V8Internal::namedPropertyEnumeratorCallback" : "0";
   3444         $subCode .= ");\n";
   3445     }
   3446 
   3447     return $subCode;
   3448 }
   3449 
   3450 sub GenerateImplementationNamedPropertyGetterCallback
   3451 {
   3452     my $interface = shift;
   3453     my $hasCustom = shift;
   3454     my $implClassName = GetImplName($interface);
   3455     my $v8ClassName = GetV8ClassName($interface);
   3456 
   3457     my $code = "static void namedPropertyGetterCallback(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
   3458     $code .= "{\n";
   3459     $code .= "    TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\");\n";
   3460     if ($hasCustom) {
   3461         $code .= "    ${v8ClassName}::namedPropertyGetterCustom(name, info);\n";
   3462     } else {
   3463         $code .= "    ${implClassName}V8Internal::namedPropertyGetter(name, info);\n";
   3464     }
   3465     $code .= "    TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n";
   3466     $code .= "}\n\n";
   3467     $implementation{nameSpaceInternal}->add($code);
   3468 }
   3469 
   3470 sub GenerateImplementationNamedPropertySetterCallback
   3471 {
   3472     my $interface = shift;
   3473     my $hasCustom = shift;
   3474     my $implClassName = GetImplName($interface);
   3475     my $v8ClassName = GetV8ClassName($interface);
   3476 
   3477     my $code = "static void namedPropertySetterCallback(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
   3478     $code .= "{\n";
   3479     $code .= "    TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\");\n";
   3480     if ($hasCustom) {
   3481         $code .= "    ${v8ClassName}::namedPropertySetterCustom(name, value, info);\n";
   3482     } else {
   3483         $code .= "    ${implClassName}V8Internal::namedPropertySetter(name, value, info);\n";
   3484     }
   3485     $code .= "    TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n";
   3486     $code .= "}\n\n";
   3487     $implementation{nameSpaceInternal}->add($code);
   3488 }
   3489 
   3490 sub GenerateImplementationNamedPropertyDeleterCallback
   3491 {
   3492     my $interface = shift;
   3493     my $hasCustom = shift;
   3494     my $implClassName = GetImplName($interface);
   3495     my $v8ClassName = GetV8ClassName($interface);
   3496 
   3497     my $code = "static void namedPropertyDeleterCallback(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Boolean>& info)\n";
   3498     $code .= "{\n";
   3499     $code .= "    TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\");\n";
   3500     if ($hasCustom) {
   3501         $code .= "    ${v8ClassName}::namedPropertyDeleterCustom(name, info);\n";
   3502     } else {
   3503         $code .= "    ${implClassName}V8Internal::namedPropertyDeleter(name, info);\n";
   3504     }
   3505     $code .= "    TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n";
   3506     $code .= "}\n\n";
   3507     $implementation{nameSpaceInternal}->add($code);
   3508 }
   3509 
   3510 sub GenerateImplementationNamedPropertyEnumeratorCallback
   3511 {
   3512     my $interface = shift;
   3513     my $hasCustom = shift;
   3514     my $implClassName = GetImplName($interface);
   3515     my $v8ClassName = GetV8ClassName($interface);
   3516 
   3517     my $code = "static void namedPropertyEnumeratorCallback(const v8::PropertyCallbackInfo<v8::Array>& info)\n";
   3518     $code .= "{\n";
   3519     $code .= "    TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\");\n";
   3520     if ($hasCustom) {
   3521         $code .= "    ${v8ClassName}::namedPropertyEnumeratorCustom(info);\n";
   3522     } else {
   3523         $code .= "    ${implClassName}V8Internal::namedPropertyEnumerator(info);\n";
   3524     }
   3525     $code .= "    TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n";
   3526     $code .= "}\n\n";
   3527     $implementation{nameSpaceInternal}->add($code);
   3528 }
   3529 
   3530 sub GenerateImplementationNamedPropertyQueryCallback
   3531 {
   3532     my $interface = shift;
   3533     my $hasCustom = shift;
   3534     my $implClassName = GetImplName($interface);
   3535     my $v8ClassName = GetV8ClassName($interface);
   3536 
   3537     my $code = "static void namedPropertyQueryCallback(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Integer>& info)\n";
   3538     $code .= "{\n";
   3539     $code .= "    TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\");\n";
   3540     if ($hasCustom) {
   3541         $code .= "    ${v8ClassName}::namedPropertyQueryCustom(name, info);\n";
   3542     } else {
   3543         $code .= "    ${implClassName}V8Internal::namedPropertyQuery(name, info);\n";
   3544     }
   3545     $code .= "    TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n";
   3546     $code .= "}\n\n";
   3547     $implementation{nameSpaceInternal}->add($code);
   3548 }
   3549 
   3550 sub GenerateMethodCall
   3551 {
   3552     my $returnType = shift; # string or UnionType
   3553     my $returnName = shift;
   3554     my $functionExpression = shift;
   3555     my $firstArgument = shift;
   3556     my $raisesExceptions = shift;
   3557 
   3558     my @arguments = ();
   3559     push @arguments, $firstArgument;
   3560     if ($raisesExceptions) {
   3561         push @arguments, "es";
   3562     }
   3563 
   3564     if (IsUnionType($returnType)) {
   3565         my $code = "";
   3566         my @extraArguments = ();
   3567         for my $i (0..scalar(@{$returnType->unionMemberTypes})-1) {
   3568             my $unionMemberType = $returnType->unionMemberTypes->[$i];
   3569             my $nativeType = GetNativeType($unionMemberType);
   3570             my $unionMemberVariable = $returnName . $i;
   3571             my $unionMemberEnabledVariable = $returnName . $i . "Enabled";
   3572             $code .= "    bool ${unionMemberEnabledVariable} = false;\n";
   3573             $code .= "    ${nativeType} ${unionMemberVariable};\n";
   3574             push @extraArguments, $unionMemberEnabledVariable;
   3575             push @extraArguments, $unionMemberVariable;
   3576         }
   3577         push @arguments, @extraArguments;
   3578         $code .= "    ${functionExpression}(" . (join ", ", @arguments) . ");";
   3579         return $code;
   3580     } else {
   3581         my $nativeType = GetNativeType($returnType);
   3582         return "    ${nativeType} element = ${functionExpression}(" . (join ", ", @arguments) . ");"
   3583     }
   3584 }
   3585 
   3586 sub GenerateImplementationNamedPropertyGetter
   3587 {
   3588     my $interface = shift;
   3589     my $namedGetterFunction = shift;
   3590     my $implClassName = GetImplName($interface);
   3591     my $v8ClassName = GetV8ClassName($interface);
   3592     my $methodName = GetImplName($namedGetterFunction);
   3593 
   3594     my $returnType = $namedGetterFunction->type;
   3595     my $isNull = GenerateIsNullExpression($returnType, "element");
   3596     my $nativeValue = "element";
   3597     $nativeValue .= ".release()" if (IsRefPtrType($returnType));
   3598     my $returnJSValueCode = NativeToJSValue($namedGetterFunction->type, $namedGetterFunction->extendedAttributes, $nativeValue, "    ", "", "info.Holder()", "info.GetIsolate()", "info", "collection", "", "return");
   3599     my $raisesExceptions = $namedGetterFunction->extendedAttributes->{"RaisesException"};
   3600     my $methodCallCode = GenerateMethodCall($returnType, "element", "collection->${methodName}", "propertyName", $raisesExceptions);
   3601 
   3602     my $code = "static void namedPropertyGetter(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
   3603     $code .= "{\n";
   3604     if (!$namedGetterFunction->extendedAttributes->{"OverrideBuiltins"}) {
   3605         $code .= "    if (!info.Holder()->GetRealNamedPropertyInPrototypeChain(name).IsEmpty())\n";
   3606         $code .= "        return;\n";
   3607         $code .= "    if (info.Holder()->HasRealNamedCallbackProperty(name))\n";
   3608         $code .= "        return;\n";
   3609         $code .= "    if (info.Holder()->HasRealNamedProperty(name))\n";
   3610         $code .= "        return;\n";
   3611     }
   3612     $code .= "\n";
   3613     $code .= "    ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder()));\n";
   3614     $code .= "    ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder());\n";
   3615     $code .= "    AtomicString propertyName = toWebCoreAtomicString(name);\n";
   3616     if ($raisesExceptions) {
   3617         $code .= "    ExceptionState es(info.GetIsolate());\n";
   3618     }
   3619     $code .= $methodCallCode . "\n";
   3620     if ($raisesExceptions) {
   3621         $code .= "    if (es.throwIfNeeded())\n";
   3622         $code .= "        return;\n";
   3623     }
   3624     if (IsUnionType($returnType)) {
   3625         $code .= "${returnJSValueCode}\n";
   3626         $code .= "    return;\n";
   3627     } else {
   3628         $code .= "    if (${isNull})\n";
   3629         $code .= "        return;\n";
   3630         $code .= $returnJSValueCode . "\n";
   3631     }
   3632     $code .= "}\n\n";
   3633     $implementation{nameSpaceInternal}->add($code);
   3634 }
   3635 
   3636 sub GenerateImplementationNamedPropertySetter
   3637 {
   3638     my $interface = shift;
   3639     my $namedSetterFunction = shift;
   3640     my $implClassName = GetImplName($interface);
   3641     my $v8ClassName = GetV8ClassName($interface);
   3642     my $methodName = GetImplName($namedSetterFunction);
   3643 
   3644     my $raisesExceptions = $namedSetterFunction->extendedAttributes->{"RaisesException"};
   3645     my $treatNullAs = $namedSetterFunction->parameters->[1]->extendedAttributes->{"TreatNullAs"};
   3646     my $treatUndefinedAs = $namedSetterFunction->parameters->[1]->extendedAttributes->{"TreatUndefinedAs"};
   3647 
   3648     my $code = "static void namedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
   3649     $code .= "{\n";
   3650     if (!$namedSetterFunction->extendedAttributes->{"OverrideBuiltins"}) {
   3651         $code .= "    if (!info.Holder()->GetRealNamedPropertyInPrototypeChain(name).IsEmpty())\n";
   3652         $code .= "        return;\n";
   3653         $code .= "    if (info.Holder()->HasRealNamedCallbackProperty(name))\n";
   3654         $code .= "        return;\n";
   3655         $code .= "    if (info.Holder()->HasRealNamedProperty(name))\n";
   3656         $code .= "        return;\n";
   3657     }
   3658     $code .= "    ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder());\n";
   3659     $code .= JSValueToNativeStatement($namedSetterFunction->parameters->[0]->type, $namedSetterFunction->extendedAttributes, "name", "propertyName", "    ", "info.GetIsolate()");
   3660     $code .= JSValueToNativeStatement($namedSetterFunction->parameters->[1]->type, $namedSetterFunction->extendedAttributes, "value", "propertyValue", "    ", "info.GetIsolate()");
   3661     my $extraArguments = "";
   3662     if ($raisesExceptions) {
   3663         $code .= "    ExceptionState es(info.GetIsolate());\n";
   3664         $extraArguments = ", es";
   3665     }
   3666 
   3667     my @conditions = ();
   3668     my @statements = ();
   3669     if ($treatNullAs && $treatNullAs ne "NullString") {
   3670         push @conditions, "value->IsNull()";
   3671         push @statements, "collection->${treatNullAs}(propertyName$extraArguments);";
   3672     }
   3673     if ($treatUndefinedAs && $treatUndefinedAs ne "NullString") {
   3674         push @conditions, "value->IsUndefined()";
   3675         push @statements, "collection->${treatUndefinedAs}(propertyName$extraArguments);";
   3676     }
   3677     push @conditions, "";
   3678     push @statements, "collection->${methodName}(propertyName, propertyValue$extraArguments);";
   3679     $code .= GenerateIfElseStatement("bool", "result", \@conditions, \@statements);
   3680 
   3681     $code .= "    if (!result)\n";
   3682     $code .= "        return;\n";
   3683     if ($raisesExceptions) {
   3684         $code .= "    if (es.throwIfNeeded())\n";
   3685         $code .= "        return;\n";
   3686     }
   3687     $code .= "    v8SetReturnValue(info, value);\n";
   3688     $code .= "}\n\n";
   3689     $implementation{nameSpaceInternal}->add($code);
   3690 }
   3691 
   3692 sub GenerateImplementationIndexedPropertyDeleter
   3693 {
   3694     my $interface = shift;
   3695     my $indexedDeleterFunction = shift;
   3696     my $implClassName = GetImplName($interface);
   3697     my $v8ClassName = GetV8ClassName($interface);
   3698     my $methodName = GetImplName($indexedDeleterFunction);
   3699 
   3700     my $raisesExceptions = $indexedDeleterFunction->extendedAttributes->{"RaisesException"};
   3701 
   3702     my $code = "static void indexedPropertyDeleter(unsigned index, const v8::PropertyCallbackInfo<v8::Boolean>& info)\n";
   3703     $code .= "{\n";
   3704     $code .= "    ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder());\n";
   3705     my $extraArguments = "";
   3706     if ($raisesExceptions) {
   3707         $code .= "    ExceptionState es(info.GetIsolate());\n";
   3708         $extraArguments = ", es";
   3709     }
   3710     $code .= "    bool result = collection->${methodName}(index$extraArguments);\n";
   3711     if ($raisesExceptions) {
   3712         $code .= "    if (es.throwIfNeeded())\n";
   3713         $code .= "        return;\n";
   3714     }
   3715     $code .= "    return v8SetReturnValueBool(info, result);\n";
   3716     $code .= "}\n\n";
   3717     $implementation{nameSpaceInternal}->add($code);
   3718 }
   3719 
   3720 sub GenerateImplementationNamedPropertyDeleter
   3721 {
   3722     my $interface = shift;
   3723     my $namedDeleterFunction = shift;
   3724     my $implClassName = GetImplName($interface);
   3725     my $v8ClassName = GetV8ClassName($interface);
   3726     my $methodName = GetImplName($namedDeleterFunction);
   3727 
   3728     my $raisesExceptions = $namedDeleterFunction->extendedAttributes->{"RaisesException"};
   3729 
   3730     my $code = "static void namedPropertyDeleter(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Boolean>& info)\n";
   3731     $code .= "{\n";
   3732     $code .= "    ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder());\n";
   3733     $code .= "    AtomicString propertyName = toWebCoreAtomicString(name);\n";
   3734     my $extraArguments = "";
   3735     if ($raisesExceptions) {
   3736         $code .= "    ExceptionState es(info.GetIsolate());\n";
   3737         $extraArguments = ", es";
   3738     }
   3739     $code .= "    bool result = collection->${methodName}(propertyName$extraArguments);\n";
   3740     if ($raisesExceptions) {
   3741         $code .= "    if (es.throwIfNeeded())\n";
   3742         $code .= "        return;\n";
   3743     }
   3744     $code .= "    return v8SetReturnValueBool(info, result);\n";
   3745     $code .= "}\n\n";
   3746     $implementation{nameSpaceInternal}->add($code);
   3747 }
   3748 
   3749 sub GenerateImplementationNamedPropertyEnumerator
   3750 {
   3751     my $interface = shift;
   3752     my $implClassName = GetImplName($interface);
   3753     my $v8ClassName = GetV8ClassName($interface);
   3754 
   3755     $implementation{nameSpaceInternal}->add(<<END);
   3756 static void namedPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info)
   3757 {
   3758     ExceptionState es(info.GetIsolate());
   3759     ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder());
   3760     Vector<String> names;
   3761     collection->namedPropertyEnumerator(names, es);
   3762     if (es.throwIfNeeded())
   3763         return;
   3764     v8::Handle<v8::Array> v8names = v8::Array::New(names.size());
   3765     for (size_t i = 0; i < names.size(); ++i)
   3766         v8names->Set(v8::Integer::New(i, info.GetIsolate()), v8String(names[i], info.GetIsolate()));
   3767     v8SetReturnValue(info, v8names);
   3768 }
   3769 
   3770 END
   3771 }
   3772 
   3773 sub GenerateImplementationNamedPropertyQuery
   3774 {
   3775     my $interface = shift;
   3776     my $implClassName = GetImplName($interface);
   3777     my $v8ClassName = GetV8ClassName($interface);
   3778 
   3779     $implementation{nameSpaceInternal}->add(<<END);
   3780 static void namedPropertyQuery(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Integer>& info)
   3781 {
   3782     ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder());
   3783     AtomicString propertyName = toWebCoreAtomicString(name);
   3784     ExceptionState es(info.GetIsolate());
   3785     bool result = collection->namedPropertyQuery(propertyName, es);
   3786     if (es.throwIfNeeded())
   3787         return;
   3788     if (!result)
   3789         return;
   3790     v8SetReturnValueInt(info, v8::None);
   3791 }
   3792 
   3793 END
   3794 }
   3795 
   3796 sub GenerateImplementationLegacyCall
   3797 {
   3798     my $interface = shift;
   3799     my $code = "";
   3800 
   3801     my $v8ClassName = GetV8ClassName($interface);
   3802 
   3803     if ($interface->extendedAttributes->{"CustomLegacyCall"}) {
   3804         $code .= "    desc->InstanceTemplate()->SetCallAsFunctionHandler(${v8ClassName}::legacyCallCustom);\n";
   3805     }
   3806     return $code;
   3807 }
   3808 
   3809 sub GenerateImplementationMasqueradesAsUndefined
   3810 {
   3811     my $interface = shift;
   3812     my $code = "";
   3813 
   3814     if ($interface->extendedAttributes->{"MasqueradesAsUndefined"})
   3815     {
   3816         $code .= "    desc->InstanceTemplate()->MarkAsUndetectable();\n";
   3817     }
   3818     return $code;
   3819 }
   3820 
   3821 sub GenerateImplementation
   3822 {
   3823     my $object = shift;
   3824     my $interface = shift;
   3825     my $interfaceName = $interface->name;
   3826     my $implClassName = GetImplName($interface);
   3827     my $v8ClassName = GetV8ClassName($interface);
   3828     my $nativeType = GetNativeTypeForConversions($interface);
   3829 
   3830     AddToImplIncludes("bindings/v8/V8Binding.h");
   3831     AddToImplIncludes("bindings/v8/V8DOMWrapper.h");
   3832     AddToImplIncludes("core/dom/ContextFeatures.h");
   3833     AddToImplIncludes("core/dom/Document.h");
   3834     AddToImplIncludes("RuntimeEnabledFeatures.h");
   3835     AddToImplIncludes("core/platform/chromium/TraceEvent.h");
   3836 
   3837     AddIncludesForType($interfaceName);
   3838 
   3839     my $toActiveDOMObject = InheritsExtendedAttribute($interface, "ActiveDOMObject") ? "${v8ClassName}::toActiveDOMObject" : "0";
   3840     my $toEventTarget = InheritsInterface($interface, "EventTarget") ? "${v8ClassName}::toEventTarget" : "0";
   3841     my $rootForGC = NeedsOpaqueRootForGC($interface) ? "${v8ClassName}::opaqueRootForGC" : "0";
   3842 
   3843     # Find the super descriptor.
   3844     my $parentClass = "";
   3845     my $parentClassTemplate = "";
   3846     if ($interface->parent) {
   3847         my $parent = $interface->parent;
   3848         AddToImplIncludes("V8${parent}.h");
   3849         $parentClass = "V8" . $parent;
   3850         $parentClassTemplate = $parentClass . "::GetTemplate(isolate, currentWorldType)";
   3851     }
   3852 
   3853     my $parentClassInfo = $parentClass ? "&${parentClass}::info" : "0";
   3854     my $WrapperTypePrototype = $interface->isException ? "WrapperTypeErrorPrototype" : "WrapperTypeObjectPrototype";
   3855 
   3856     if (!IsSVGTypeNeedingTearOff($interfaceName)) {
   3857         my $code = <<END;
   3858 static void initializeScriptWrappableForInterface(${implClassName}* object)
   3859 {
   3860     if (ScriptWrappable::wrapperCanBeStoredInObject(object))
   3861         ScriptWrappable::setTypeInfoInObject(object, &${v8ClassName}::info);
   3862     else
   3863         ASSERT_NOT_REACHED();
   3864 }
   3865 
   3866 } // namespace WebCore
   3867 
   3868 // In ScriptWrappable::init, the use of a local function declaration has an issue on Windows:
   3869 // the local declaration does not pick up the surrounding namespace. Therefore, we provide this function
   3870 // in the global namespace.
   3871 // (More info on the MSVC bug here: http://connect.microsoft.com/VisualStudio/feedback/details/664619/the-namespace-of-local-function-declarations-in-c)
   3872 END
   3873 
   3874     if (GetNamespaceForInterface($interface) eq "WebCore") {
   3875         $code .= "void webCoreInitializeScriptWrappableForInterface(WebCore::${implClassName}* object)\n";
   3876     } else {
   3877         $code .= "void webCoreInitializeScriptWrappableForInterface(${implClassName}* object)\n";
   3878     }
   3879 
   3880     $code .= <<END;
   3881 {
   3882     WebCore::initializeScriptWrappableForInterface(object);
   3883 }
   3884 
   3885 namespace WebCore {
   3886 END
   3887         $implementation{nameSpaceWebCore}->addHeader($code);
   3888     }
   3889 
   3890     my $code = "WrapperTypeInfo ${v8ClassName}::info = { ${v8ClassName}::GetTemplate, ${v8ClassName}::derefObject, $toActiveDOMObject, $toEventTarget, ";
   3891     $code .= "$rootForGC, ${v8ClassName}::installPerContextPrototypeProperties, $parentClassInfo, $WrapperTypePrototype };\n";
   3892     $implementation{nameSpaceWebCore}->addHeader($code);
   3893 
   3894     $implementation{nameSpaceInternal}->add("template <typename T> void V8_USE(T) { }\n\n");
   3895 
   3896     my $hasConstructors = 0;
   3897     my $hasReplaceable = 0;
   3898 
   3899     # Generate property accessors for attributes.
   3900     for (my $index = 0; $index < @{$interface->attributes}; $index++) {
   3901         my $attribute = @{$interface->attributes}[$index];
   3902         my $attrType = $attribute->type;
   3903         my $attrExt = $attribute->extendedAttributes;
   3904 
   3905         # Generate special code for the constructor attributes.
   3906         if ($attrType =~ /Constructor$/) {
   3907             if (!HasCustomGetter($attrExt)) {
   3908                 $hasConstructors = 1;
   3909             }
   3910             next;
   3911         }
   3912 
   3913         if ($attrType eq "EventHandler" && $interfaceName eq "Window") {
   3914             $attrExt->{"OnProto"} = 1;
   3915         }
   3916 
   3917         if ($attrType eq "SerializedScriptValue") {
   3918             AddToImplIncludes("bindings/v8/SerializedScriptValue.h");
   3919         }
   3920 
   3921         GenerateNormalAttrGetter($attribute, $interface, "");
   3922         GenerateNormalAttrGetterCallback($attribute, $interface, "");
   3923         if ($attrExt->{"PerWorldBindings"}) {
   3924             GenerateNormalAttrGetter($attribute, $interface, "ForMainWorld");
   3925             GenerateNormalAttrGetterCallback($attribute, $interface, "ForMainWorld");
   3926         }
   3927         if (!HasCustomSetter($attrExt) && $attrExt->{"Replaceable"}) {
   3928             $hasReplaceable = 1;
   3929         } elsif (!IsReadonly($attribute)) {
   3930             GenerateNormalAttrSetter($attribute, $interface, "");
   3931             GenerateNormalAttrSetterCallback($attribute, $interface, "");
   3932             if ($attrExt->{"PerWorldBindings"}) {
   3933               GenerateNormalAttrSetter($attribute, $interface, "ForMainWorld");
   3934               GenerateNormalAttrSetterCallback($attribute, $interface, "ForMainWorld");
   3935             }
   3936         }
   3937     }
   3938 
   3939     if ($hasConstructors) {
   3940         GenerateConstructorGetter($interface);
   3941     }
   3942 
   3943     if ($hasConstructors || $hasReplaceable) {
   3944         GenerateReplaceableAttrSetter($interface);
   3945         GenerateReplaceableAttrSetterCallback($interface);
   3946     }
   3947 
   3948     if (NeedsOpaqueRootForGC($interface)) {
   3949         GenerateOpaqueRootForGC($interface);
   3950     }
   3951 
   3952     if ($interface->extendedAttributes->{"CheckSecurity"} && $interface->name ne "Window") {
   3953         GenerateSecurityCheckFunctions($interface);
   3954     }
   3955 
   3956     if (IsConstructorTemplate($interface, "TypedArray")) {
   3957         my ($nativeType, $arrayType) = GetNativeTypeOfTypedArray($interface);
   3958         $implementation{nameSpaceWebCore}->add(<<END);
   3959 v8::Handle<v8::Object> wrap($implClassName* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
   3960 {
   3961     ASSERT(impl);
   3962     v8::Handle<v8::Object> wrapper = ${v8ClassName}::createWrapper(impl, creationContext, isolate);
   3963     if (!wrapper.IsEmpty())
   3964         wrapper->SetIndexedPropertiesToExternalArrayData(impl->baseAddress(), $arrayType, impl->length());
   3965     return wrapper;
   3966 }
   3967 
   3968 END
   3969     }
   3970 
   3971     my @enabledPerContextFunctions;
   3972     my @normalFunctions;
   3973     my $needsDomainSafeFunctionSetter = 0;
   3974     # Generate methods for functions.
   3975     foreach my $function (@{$interface->functions}) {
   3976         next if $function->name eq "";
   3977         GenerateFunction($function, $interface, "");
   3978         if ($function->extendedAttributes->{"PerWorldBindings"}) {
   3979             GenerateFunction($function, $interface, "ForMainWorld");
   3980         }
   3981         if ($function->{overloadIndex} == @{$function->{overloads}}) {
   3982             if ($function->{overloadIndex} > 1) {
   3983                 GenerateOverloadedFunction($function, $interface, "");
   3984                 if ($function->extendedAttributes->{"PerWorldBindings"}) {
   3985                     GenerateOverloadedFunction($function, $interface, "ForMainWorld");
   3986                 }
   3987             }
   3988             GenerateFunctionCallback($function, $interface, "");
   3989             if ($function->extendedAttributes->{"PerWorldBindings"}) {
   3990                 GenerateFunctionCallback($function, $interface, "ForMainWorld");
   3991             }
   3992         }
   3993 
   3994         # If the function does not need domain security check, we need to
   3995         # generate an access getter that returns different function objects
   3996         # for different calling context.
   3997         if ($interface->extendedAttributes->{"CheckSecurity"} && $function->extendedAttributes->{"DoNotCheckSecurity"}) {
   3998             if (!HasCustomMethod($function->extendedAttributes) || $function->{overloadIndex} == 1) {
   3999                 GenerateDomainSafeFunctionGetter($function, $interface);
   4000                 if (!$function->extendedAttributes->{"ReadOnly"}) {
   4001                     $needsDomainSafeFunctionSetter = 1;
   4002                 }
   4003             }
   4004         }
   4005 
   4006         # Separate out functions that are enabled per context so we can process them specially.
   4007         if ($function->extendedAttributes->{"EnabledPerContext"}) {
   4008             push(@enabledPerContextFunctions, $function);
   4009         } else {
   4010             push(@normalFunctions, $function);
   4011         }
   4012     }
   4013 
   4014     if ($needsDomainSafeFunctionSetter) {
   4015         GenerateDomainSafeFunctionSetter($interface);
   4016     }
   4017 
   4018     # Attributes
   4019     my $attributes = $interface->attributes;
   4020 
   4021     # For the Window interface we partition the attributes into the
   4022     # ones that disallows shadowing and the rest.
   4023     my @disallowsShadowing;
   4024     # Also separate out attributes that are enabled at runtime so we can process them specially.
   4025     my @enabledAtRuntimeAttributes;
   4026     my @enabledPerContextAttributes;
   4027     my @normalAttributes;
   4028     foreach my $attribute (@$attributes) {
   4029 
   4030         if ($interfaceName eq "Window" && $attribute->extendedAttributes->{"Unforgeable"}) {
   4031             push(@disallowsShadowing, $attribute);
   4032         } elsif ($attribute->extendedAttributes->{"EnabledAtRuntime"} || $attribute->extendedAttributes->{"EnabledPerContext"}) {
   4033             if ($attribute->extendedAttributes->{"EnabledPerContext"}) {
   4034                 push(@enabledPerContextAttributes, $attribute);
   4035             }
   4036             if ($attribute->extendedAttributes->{"EnabledAtRuntime"}) {
   4037                 push(@enabledAtRuntimeAttributes, $attribute);
   4038             }
   4039         } else {
   4040             push(@normalAttributes, $attribute);
   4041         }
   4042     }
   4043     AddToImplIncludes("bindings/v8/V8DOMConfiguration.h");
   4044     $attributes = \@normalAttributes;
   4045     # Put the attributes that disallow shadowing on the shadow object.
   4046     if (@disallowsShadowing) {
   4047         my $code = "";
   4048         $code .= "static const V8DOMConfiguration::BatchedAttribute shadowAttrs[] = {\n";
   4049         $code .= GenerateBatchedAttributeData($interface, \@disallowsShadowing);
   4050         $code .= "};\n\n";
   4051         $implementation{nameSpaceWebCore}->add($code);
   4052     }
   4053 
   4054     my $has_attributes = 0;
   4055     if (@$attributes) {
   4056         $has_attributes = 1;
   4057         my $code = "";
   4058         $code .= "static const V8DOMConfiguration::BatchedAttribute ${v8ClassName}Attrs[] = {\n";
   4059         $code .= GenerateBatchedAttributeData($interface, $attributes);
   4060         $code .= "};\n\n";
   4061         $implementation{nameSpaceWebCore}->add($code);
   4062     }
   4063 
   4064     # Setup table of standard callback functions
   4065     my $num_callbacks = 0;
   4066     my $has_callbacks = 0;
   4067     $code = "";
   4068     foreach my $function (@normalFunctions) {
   4069         # Only one table entry is needed for overloaded methods:
   4070         next if $function->{overloadIndex} > 1;
   4071         # Don't put any nonstandard functions into this table:
   4072         next if !IsStandardFunction($interface, $function);
   4073         next if $function->name eq "";
   4074         if (!$has_callbacks) {
   4075             $has_callbacks = 1;
   4076             $code .= "static const V8DOMConfiguration::BatchedMethod ${v8ClassName}Methods[] = {\n";
   4077         }
   4078         my $name = $function->name;
   4079         my $methodForMainWorld = "0";
   4080         if ($function->extendedAttributes->{"PerWorldBindings"}) {
   4081             $methodForMainWorld = "${implClassName}V8Internal::${name}MethodCallbackForMainWorld";
   4082         }
   4083         my $functionLength = GetFunctionLength($function);
   4084         my $conditionalString = GenerateConditionalString($function);
   4085         $code .= "#if ${conditionalString}\n" if $conditionalString;
   4086         $code .= <<END;
   4087     {"$name", ${implClassName}V8Internal::${name}MethodCallback, ${methodForMainWorld}, ${functionLength}},
   4088 END
   4089         $code .= "#endif // ${conditionalString}\n" if $conditionalString;
   4090         $num_callbacks++;
   4091     }
   4092     $code .= "};\n\n"  if $has_callbacks;
   4093     $implementation{nameSpaceWebCore}->add($code);
   4094 
   4095     # Setup constants
   4096     my $has_constants = 0;
   4097     my @constantsEnabledAtRuntime;
   4098     $code = "";
   4099     if (@{$interface->constants}) {
   4100         $has_constants = 1;
   4101         $code .= "static const V8DOMConfiguration::BatchedConstant ${v8ClassName}Consts[] = {\n";
   4102     }
   4103     foreach my $constant (@{$interface->constants}) {
   4104         my $name = $constant->name;
   4105         my $value = $constant->value;
   4106         my $attrExt = $constant->extendedAttributes;
   4107         my $implementedBy = $attrExt->{"ImplementedBy"};
   4108         if ($implementedBy) {
   4109             my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy);
   4110             AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implementedByImplName));
   4111         }
   4112         if ($attrExt->{"EnabledAtRuntime"}) {
   4113             push(@constantsEnabledAtRuntime, $constant);
   4114         } else {
   4115             my $conditionalString = GenerateConditionalString($constant);
   4116             $code .= "#if ${conditionalString}\n" if $conditionalString;
   4117             # If the value we're dealing with is a hex number, preprocess it into a signed integer
   4118             # here, rather than running static_cast<signed int> in the generated code.
   4119             if (substr($value, 0, 2) eq "0x") {
   4120               $value = unpack('i', pack('I', hex($value)));
   4121             }
   4122             $code .= <<END;
   4123     {"${name}", $value},
   4124 END
   4125             $code .= "#endif\n" if $conditionalString;
   4126         }
   4127     }
   4128     if ($has_constants) {
   4129         $code .= "};\n\n";
   4130         $code .= join "", GenerateCompileTimeCheckForEnumsIfNeeded($interface);
   4131         $implementation{nameSpaceWebCore}->add($code);
   4132     }
   4133 
   4134     if (!HasCustomConstructor($interface)) {
   4135         if ($interface->extendedAttributes->{"NamedConstructor"}) {
   4136             GenerateNamedConstructor(@{$interface->constructors}[0], $interface);
   4137         } elsif ($interface->extendedAttributes->{"Constructor"}) {
   4138             GenerateConstructor($interface);
   4139         } elsif (IsConstructorTemplate($interface, "Event")) {
   4140             GenerateEventConstructor($interface);
   4141         }
   4142     }
   4143     if (IsConstructable($interface)) {
   4144         GenerateConstructorCallback($interface);
   4145     }
   4146 
   4147     my $access_check = "";
   4148     if ($interface->extendedAttributes->{"CheckSecurity"} && $interfaceName ne "Window") {
   4149         $access_check = "instance->SetAccessCheckCallbacks(${implClassName}V8Internal::namedSecurityCheck, ${implClassName}V8Internal::indexedSecurityCheck, v8::External::New(&${v8ClassName}::info));";
   4150     }
   4151 
   4152     # For the Window interface, generate the shadow object template
   4153     # configuration method.
   4154     if ($interfaceName eq "Window") {
   4155         $implementation{nameSpaceWebCore}->add(<<END);
   4156 static void ConfigureShadowObjectTemplate(v8::Handle<v8::ObjectTemplate> templ, v8::Isolate* isolate, WrapperWorldType currentWorldType)
   4157 {
   4158     V8DOMConfiguration::batchConfigureAttributes(templ, v8::Handle<v8::ObjectTemplate>(), shadowAttrs, WTF_ARRAY_LENGTH(shadowAttrs), isolate, currentWorldType);
   4159 
   4160     // Install a security handler with V8.
   4161     templ->SetAccessCheckCallbacks(V8Window::namedSecurityCheckCustom, V8Window::indexedSecurityCheckCustom, v8::External::New(&V8Window::info));
   4162     templ->SetInternalFieldCount(V8Window::internalFieldCount);
   4163 }
   4164 END
   4165     }
   4166 
   4167     if (!$parentClassTemplate) {
   4168         $parentClassTemplate = "v8::Local<v8::FunctionTemplate>()";
   4169     }
   4170 
   4171     # Generate the template configuration method
   4172     $code =  <<END;
   4173 static v8::Handle<v8::FunctionTemplate> Configure${v8ClassName}Template(v8::Handle<v8::FunctionTemplate> desc, v8::Isolate* isolate, WrapperWorldType currentWorldType)
   4174 {
   4175     desc->ReadOnlyPrototype();
   4176 
   4177     v8::Local<v8::Signature> defaultSignature;
   4178 END
   4179     if ($interface->extendedAttributes->{"EnabledAtRuntime"}) {
   4180         my $enable_function = GetRuntimeEnableFunctionName($interface);
   4181         $code .= <<END;
   4182     if (!${enable_function}())
   4183         defaultSignature = V8DOMConfiguration::configureTemplate(desc, \"\", $parentClassTemplate, ${v8ClassName}::internalFieldCount, 0, 0, 0, 0, isolate, currentWorldType);
   4184     else
   4185 END
   4186     }
   4187     $code .=  <<END;
   4188     defaultSignature = V8DOMConfiguration::configureTemplate(desc, \"${interfaceName}\", $parentClassTemplate, ${v8ClassName}::internalFieldCount,
   4189 END
   4190     # Set up our attributes if we have them
   4191     if ($has_attributes) {
   4192         $code .= <<END;
   4193         ${v8ClassName}Attrs, WTF_ARRAY_LENGTH(${v8ClassName}Attrs),
   4194 END
   4195     } else {
   4196         $code .= <<END;
   4197         0, 0,
   4198 END
   4199     }
   4200 
   4201     if ($has_callbacks) {
   4202         $code .= <<END;
   4203         ${v8ClassName}Methods, WTF_ARRAY_LENGTH(${v8ClassName}Methods), isolate, currentWorldType);
   4204 END
   4205     } else {
   4206         $code .= <<END;
   4207         0, 0, isolate, currentWorldType);
   4208 END
   4209     }
   4210 
   4211     AddToImplIncludes("wtf/UnusedParam.h");
   4212     $code .= <<END;
   4213     UNUSED_PARAM(defaultSignature); // In some cases, it will not be used.
   4214 END
   4215 
   4216     if (IsConstructable($interface)) {
   4217         $code .= "    desc->SetCallHandler(${v8ClassName}::constructorCallback);\n";
   4218         my $interfaceLength = GetInterfaceLength($interface);
   4219         $code .= "    desc->SetLength(${interfaceLength});\n";
   4220     }
   4221 
   4222     if ($access_check or @enabledAtRuntimeAttributes or @normalFunctions or $has_constants) {
   4223         $code .=  <<END;
   4224     v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate();
   4225     v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate();
   4226     UNUSED_PARAM(instance); // In some cases, it will not be used.
   4227     UNUSED_PARAM(proto); // In some cases, it will not be used.
   4228 END
   4229     }
   4230 
   4231     if ($access_check) {
   4232         $code .=  "    $access_check\n";
   4233     }
   4234 
   4235     # Setup the enable-at-runtime attrs if we have them
   4236     foreach my $runtime_attr (@enabledAtRuntimeAttributes) {
   4237         next if grep { $_ eq $runtime_attr } @enabledPerContextAttributes;
   4238         my $enable_function = GetRuntimeEnableFunctionName($runtime_attr);
   4239         my $conditionalString = GenerateConditionalString($runtime_attr);
   4240         $code .= "\n#if ${conditionalString}\n" if $conditionalString;
   4241         $code .= "    if (${enable_function}()) {\n";
   4242         $code .= "        static const V8DOMConfiguration::BatchedAttribute attrData =\\\n";
   4243         $code .= GenerateSingleBatchedAttribute($interface, $runtime_attr, ";", "    ");
   4244         $code .= <<END;
   4245         V8DOMConfiguration::configureAttribute(instance, proto, attrData, isolate, currentWorldType);
   4246     }
   4247 END
   4248         $code .= "\n#endif // ${conditionalString}\n" if $conditionalString;
   4249     }
   4250 
   4251     # Setup the enable-at-runtime constants if we have them
   4252     foreach my $runtime_const (@constantsEnabledAtRuntime) {
   4253         my $enable_function = GetRuntimeEnableFunctionName($runtime_const);
   4254         my $conditionalString = GenerateConditionalString($runtime_const);
   4255         my $name = $runtime_const->name;
   4256         my $value = $runtime_const->value;
   4257         $code .= "\n#if ${conditionalString}\n" if $conditionalString;
   4258         $code .= "    if (${enable_function}()) {\n";
   4259         $code .= <<END;
   4260         static const V8DOMConfiguration::BatchedConstant constData = {"${name}", static_cast<signed int>(${value})};
   4261         V8DOMConfiguration::batchConfigureConstants(desc, proto, &constData, 1, isolate);
   4262 END
   4263         $code .= "    }\n";
   4264         $code .= "\n#endif // ${conditionalString}\n" if $conditionalString;
   4265     }
   4266 
   4267     $code .= GenerateImplementationIndexedPropertyAccessors($interface);
   4268     $code .= GenerateImplementationNamedPropertyAccessors($interface);
   4269     $code .= GenerateImplementationLegacyCall($interface);
   4270     $code .= GenerateImplementationMasqueradesAsUndefined($interface);
   4271 
   4272     # Define our functions with Set() or SetAccessor()
   4273     my $total_functions = 0;
   4274     foreach my $function (@normalFunctions) {
   4275         # Only one accessor is needed for overloaded methods:
   4276         next if $function->{overloadIndex} > 1;
   4277         next if $function->name eq "";
   4278 
   4279         $total_functions++;
   4280         next if IsStandardFunction($interface, $function);
   4281         $code .= GenerateNonStandardFunction($interface, $function);
   4282         $num_callbacks++;
   4283     }
   4284 
   4285     die "Wrong number of callbacks generated for $interfaceName ($num_callbacks, should be $total_functions)" if $num_callbacks != $total_functions;
   4286 
   4287     if ($has_constants) {
   4288         $code .= <<END;
   4289     V8DOMConfiguration::batchConfigureConstants(desc, proto, ${v8ClassName}Consts, WTF_ARRAY_LENGTH(${v8ClassName}Consts), isolate);
   4290 END
   4291     }
   4292 
   4293     # Special cases
   4294     if ($interfaceName eq "Window") {
   4295         $code .= <<END;
   4296 
   4297     proto->SetInternalFieldCount(V8Window::internalFieldCount);
   4298     desc->SetHiddenPrototype(true);
   4299     instance->SetInternalFieldCount(V8Window::internalFieldCount);
   4300     // Set access check callbacks, but turned off initially.
   4301     // When a context is detached from a frame, turn on the access check.
   4302     // Turning on checks also invalidates inline caches of the object.
   4303     instance->SetAccessCheckCallbacks(V8Window::namedSecurityCheckCustom, V8Window::indexedSecurityCheckCustom, v8::External::New(&V8Window::info), false);
   4304 END
   4305     }
   4306     if ($interfaceName eq "HTMLDocument" or $interfaceName eq "DedicatedWorkerGlobalScope" or $interfaceName eq "SharedWorkerGlobalScope") {
   4307         $code .= <<END;
   4308     desc->SetHiddenPrototype(true);
   4309 END
   4310     }
   4311 
   4312     $code .= <<END;
   4313 
   4314     // Custom toString template
   4315     desc->Set(v8::String::NewSymbol("toString"), V8PerIsolateData::current()->toStringTemplate());
   4316     return desc;
   4317 }
   4318 
   4319 END
   4320     $implementation{nameSpaceWebCore}->add($code);
   4321 
   4322     $implementation{nameSpaceWebCore}->add(<<END);
   4323 v8::Handle<v8::FunctionTemplate> ${v8ClassName}::GetTemplate(v8::Isolate* isolate, WrapperWorldType currentWorldType)
   4324 {
   4325     V8PerIsolateData* data = V8PerIsolateData::from(isolate);
   4326     V8PerIsolateData::TemplateMap::iterator result = data->templateMap(currentWorldType).find(&info);
   4327     if (result != data->templateMap(currentWorldType).end())
   4328         return result->value.newLocal(isolate);
   4329 
   4330     TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate");
   4331     v8::HandleScope handleScope(isolate);
   4332     v8::Handle<v8::FunctionTemplate> templ =
   4333         Configure${v8ClassName}Template(data->rawTemplate(&info, currentWorldType), isolate, currentWorldType);
   4334     data->templateMap(currentWorldType).add(&info, UnsafePersistent<v8::FunctionTemplate>(isolate, templ));
   4335     return handleScope.Close(templ);
   4336 }
   4337 
   4338 END
   4339     $implementation{nameSpaceWebCore}->add(<<END);
   4340 bool ${v8ClassName}::HasInstance(v8::Handle<v8::Value> value, v8::Isolate* isolate, WrapperWorldType currentWorldType)
   4341 {
   4342     return V8PerIsolateData::from(isolate)->hasInstance(&info, value, currentWorldType);
   4343 }
   4344 
   4345 END
   4346     $implementation{nameSpaceWebCore}->add(<<END);
   4347 bool ${v8ClassName}::HasInstanceInAnyWorld(v8::Handle<v8::Value> value, v8::Isolate* isolate)
   4348 {
   4349     return V8PerIsolateData::from(isolate)->hasInstance(&info, value, MainWorld)
   4350         || V8PerIsolateData::from(isolate)->hasInstance(&info, value, IsolatedWorld)
   4351         || V8PerIsolateData::from(isolate)->hasInstance(&info, value, WorkerWorld);
   4352 }
   4353 
   4354 END
   4355 
   4356     if (@enabledPerContextAttributes) {
   4357         my $code = "";
   4358         $code .= <<END;
   4359 void ${v8ClassName}::installPerContextProperties(v8::Handle<v8::Object> instance, ${nativeType}* impl, v8::Isolate* isolate)
   4360 {
   4361     v8::Local<v8::Object> proto = v8::Local<v8::Object>::Cast(instance->GetPrototype());
   4362 END
   4363 
   4364         # Setup the enable-by-settings attrs if we have them
   4365         foreach my $runtimeAttr (@enabledPerContextAttributes) {
   4366             my $enableFunction = GetContextEnableFunction($runtimeAttr);
   4367             my $conditionalString = GenerateConditionalString($runtimeAttr);
   4368             $code .= "\n#if ${conditionalString}\n" if $conditionalString;
   4369             if (grep { $_ eq $runtimeAttr } @enabledAtRuntimeAttributes) {
   4370                 my $runtimeEnableFunction = GetRuntimeEnableFunctionName($runtimeAttr);
   4371                 $code .= "    if (${enableFunction}(impl->document()) && ${runtimeEnableFunction}()) {\n";
   4372             } else {
   4373                 $code .= "    if (${enableFunction}(impl->document())) {\n";
   4374             }
   4375 
   4376             $code .= "        static const V8DOMConfiguration::BatchedAttribute attrData =\\\n";
   4377             $code .= GenerateSingleBatchedAttribute($interface, $runtimeAttr, ";", "    ");
   4378             $code .= <<END;
   4379         V8DOMConfiguration::configureAttribute(instance, proto, attrData, isolate);
   4380 END
   4381             $code .= "    }\n";
   4382             $code .= "#endif // ${conditionalString}\n" if $conditionalString;
   4383         }
   4384         $code .= <<END;
   4385 }
   4386 
   4387 END
   4388         $implementation{nameSpaceWebCore}->add($code);
   4389     }
   4390 
   4391     if (@enabledPerContextFunctions) {
   4392         my $code = "";
   4393         $code .= <<END;
   4394 void ${v8ClassName}::installPerContextPrototypeProperties(v8::Handle<v8::Object> proto, v8::Isolate* isolate)
   4395 {
   4396     UNUSED_PARAM(proto);
   4397 END
   4398         # Setup the enable-by-settings functions if we have them
   4399         $code .=  <<END;
   4400     v8::Local<v8::Signature> defaultSignature = v8::Signature::New(GetTemplate(isolate, worldType(isolate)));
   4401     UNUSED_PARAM(defaultSignature); // In some cases, it will not be used.
   4402 
   4403     ScriptExecutionContext* context = toScriptExecutionContext(proto->CreationContext());
   4404 END
   4405 
   4406         foreach my $runtimeFunc (@enabledPerContextFunctions) {
   4407             my $enableFunction = GetContextEnableFunction($runtimeFunc);
   4408             my $functionLength = GetFunctionLength($runtimeFunc);
   4409             my $conditionalString = GenerateConditionalString($runtimeFunc);
   4410             $code .= "\n#if ${conditionalString}\n" if $conditionalString;
   4411             $code .= "    if (context && context->isDocument() && ${enableFunction}(toDocument(context)))\n";
   4412             my $name = $runtimeFunc->name;
   4413             $code .= <<END;
   4414         proto->Set(v8::String::NewSymbol("${name}"), v8::FunctionTemplate::New(${implClassName}V8Internal::${name}MethodCallback, v8Undefined(), defaultSignature, $functionLength)->GetFunction());
   4415 END
   4416             $code .= "#endif // ${conditionalString}\n" if $conditionalString;
   4417         }
   4418 
   4419         $code .= <<END;
   4420 }
   4421 
   4422 END
   4423         $implementation{nameSpaceWebCore}->add($code);
   4424     }
   4425 
   4426     if (InheritsExtendedAttribute($interface, "ActiveDOMObject")) {
   4427         # MessagePort is handled like an active dom object even though it doesn't inherit
   4428         # from ActiveDOMObject, so don't try to cast it to ActiveDOMObject.
   4429         my $returnValue = $interfaceName eq "MessagePort" ? "0" : "toNative(object)";
   4430         $implementation{nameSpaceWebCore}->add(<<END);
   4431 ActiveDOMObject* ${v8ClassName}::toActiveDOMObject(v8::Handle<v8::Object> object)
   4432 {
   4433     return $returnValue;
   4434 }
   4435 
   4436 END
   4437     }
   4438 
   4439     if (InheritsInterface($interface, "EventTarget")) {
   4440         $implementation{nameSpaceWebCore}->add(<<END);
   4441 EventTarget* ${v8ClassName}::toEventTarget(v8::Handle<v8::Object> object)
   4442 {
   4443     return toNative(object);
   4444 }
   4445 
   4446 END
   4447     }
   4448 
   4449     if ($interfaceName eq "Window") {
   4450         $implementation{nameSpaceWebCore}->add(<<END);
   4451 v8::Handle<v8::ObjectTemplate> V8Window::GetShadowObjectTemplate(v8::Isolate* isolate, WrapperWorldType currentWorldType)
   4452 {
   4453     if (currentWorldType == MainWorld) {
   4454         DEFINE_STATIC_LOCAL(v8::Persistent<v8::ObjectTemplate>, V8WindowShadowObjectCacheForMainWorld, ());
   4455         if (V8WindowShadowObjectCacheForMainWorld.IsEmpty()) {
   4456             TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate");
   4457             v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   4458             ConfigureShadowObjectTemplate(templ, isolate, currentWorldType);
   4459             V8WindowShadowObjectCacheForMainWorld.Reset(isolate, templ);
   4460             return templ;
   4461         }
   4462         return v8::Local<v8::ObjectTemplate>::New(isolate, V8WindowShadowObjectCacheForMainWorld);
   4463     } else {
   4464         DEFINE_STATIC_LOCAL(v8::Persistent<v8::ObjectTemplate>, V8WindowShadowObjectCacheForNonMainWorld, ());
   4465         if (V8WindowShadowObjectCacheForNonMainWorld.IsEmpty()) {
   4466             TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate");
   4467             v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
   4468             ConfigureShadowObjectTemplate(templ, isolate, currentWorldType);
   4469             V8WindowShadowObjectCacheForNonMainWorld.Reset(isolate, templ);
   4470             return templ;
   4471         }
   4472         return v8::Local<v8::ObjectTemplate>::New(isolate, V8WindowShadowObjectCacheForNonMainWorld);
   4473     }
   4474 }
   4475 
   4476 END
   4477     }
   4478 
   4479     GenerateToV8Converters($interface, $v8ClassName, $nativeType);
   4480 
   4481     $implementation{nameSpaceWebCore}->add(<<END);
   4482 void ${v8ClassName}::derefObject(void* object)
   4483 {
   4484     fromInternalPointer(object)->deref();
   4485 }
   4486 
   4487 END
   4488 }
   4489 
   4490 sub GenerateHeaderContentHeader
   4491 {
   4492     my $interface = shift;
   4493     my $v8ClassName = GetV8ClassName($interface);
   4494     my $conditionalString = GenerateConditionalString($interface);
   4495 
   4496     my @headerContentHeader = split("\r", $headerTemplate);
   4497 
   4498     push(@headerContentHeader, "\n#ifndef ${v8ClassName}" . "_h\n");
   4499     push(@headerContentHeader, "#define ${v8ClassName}" . "_h\n\n");
   4500     push(@headerContentHeader, "#if ${conditionalString}\n") if $conditionalString;
   4501     return join "", @headerContentHeader;
   4502 }
   4503 
   4504 sub GenerateCallbackHeader
   4505 {
   4506     my $object = shift;
   4507     my $interface = shift;
   4508 
   4509     my $interfaceName = $interface->name;
   4510     my $implClassName = GetImplName($interface);
   4511     my $v8ClassName = GetV8ClassName($interface);
   4512 
   4513     $header{root}->addFooter("\n");
   4514 
   4515     my @includes = ();
   4516     push(@includes, "bindings/v8/ActiveDOMCallback.h");
   4517     push(@includes, "bindings/v8/DOMWrapperWorld.h");
   4518     push(@includes, "bindings/v8/ScopedPersistent.h");
   4519     push(@includes, HeaderFilesForInterface($interfaceName, $implClassName));
   4520     for my $include (sort @includes) {
   4521         $header{includes}->add("#include \"$include\"\n");
   4522     }
   4523     $header{nameSpaceWebCore}->addHeader("\nclass ScriptExecutionContext;\n\n");
   4524     $header{class}->addHeader("class $v8ClassName : public $implClassName, public ActiveDOMCallback {");
   4525     $header{class}->addFooter("};\n");
   4526 
   4527     $header{classPublic}->add(<<END);
   4528     static PassRefPtr<${v8ClassName}> create(v8::Handle<v8::Value> value, ScriptExecutionContext* context)
   4529     {
   4530         ASSERT(value->IsObject());
   4531         ASSERT(context);
   4532         return adoptRef(new ${v8ClassName}(v8::Handle<v8::Object>::Cast(value), context));
   4533     }
   4534 
   4535     virtual ~${v8ClassName}();
   4536 
   4537 END
   4538 
   4539     # Functions
   4540     my $numFunctions = @{$interface->functions};
   4541     if ($numFunctions > 0) {
   4542         $header{classPublic}->add("    // Functions\n");
   4543         foreach my $function (@{$interface->functions}) {
   4544             my $code = "    virtual " . GetNativeTypeForCallbacks($function->type) . " " . $function->name . "(";
   4545 
   4546             my @args = ();
   4547             if (ExtendedAttributeContains($function->extendedAttributes->{"CallWith"}, "ThisValue")) {
   4548                 push(@args, GetNativeType("any") . " thisValue");
   4549             }
   4550             my @params = @{$function->parameters};
   4551             foreach my $param (@params) {
   4552                 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $param->name);
   4553             }
   4554             $code .= join(", ", @args);
   4555             $code .= ");\n";
   4556             $header{classPublic}->add($code);
   4557         }
   4558     }
   4559 
   4560     $header{classPublic}->add(<<END);
   4561 
   4562     virtual ScriptExecutionContext* scriptExecutionContext() const { return ContextLifecycleObserver::scriptExecutionContext(); }
   4563 
   4564 END
   4565     $header{classPrivate}->add(<<END);
   4566     ${v8ClassName}(v8::Handle<v8::Object>, ScriptExecutionContext*);
   4567 
   4568     ScopedPersistent<v8::Object> m_callback;
   4569     RefPtr<DOMWrapperWorld> m_world;
   4570 END
   4571 }
   4572 
   4573 sub GenerateCallbackImplementation
   4574 {
   4575     my $object = shift;
   4576     my $interface = shift;
   4577     my $v8ClassName = GetV8ClassName($interface);
   4578 
   4579     AddToImplIncludes("core/dom/ScriptExecutionContext.h");
   4580     AddToImplIncludes("bindings/v8/V8Binding.h");
   4581     AddToImplIncludes("bindings/v8/V8Callback.h");
   4582     AddToImplIncludes("wtf/Assertions.h");
   4583 
   4584     $implementation{nameSpaceWebCore}->add(<<END);
   4585 ${v8ClassName}::${v8ClassName}(v8::Handle<v8::Object> callback, ScriptExecutionContext* context)
   4586     : ActiveDOMCallback(context)
   4587     , m_callback(callback)
   4588     , m_world(DOMWrapperWorld::current())
   4589 {
   4590 }
   4591 
   4592 END
   4593 
   4594     $implementation{nameSpaceWebCore}->add(<<END);
   4595 ${v8ClassName}::~${v8ClassName}()
   4596 {
   4597 }
   4598 
   4599 END
   4600 
   4601     # Functions
   4602     my $numFunctions = @{$interface->functions};
   4603     if ($numFunctions > 0) {
   4604         $implementation{nameSpaceWebCore}->add("// Functions\n");
   4605         foreach my $function (@{$interface->functions}) {
   4606             my $code = "";
   4607             my @params = @{$function->parameters};
   4608             next if $function->extendedAttributes->{"Custom"};
   4609 
   4610             AddIncludesForType($function->type);
   4611             die "We don't yet support callbacks that return non-boolean values.\n" if $function->type ne "boolean";
   4612             $code .= "\n" . GetNativeTypeForCallbacks($function->type) . " ${v8ClassName}::" . $function->name . "(";
   4613             my $callWithThisValue = ExtendedAttributeContains($function->extendedAttributes->{"CallWith"}, "ThisValue");
   4614 
   4615             my @args = ();
   4616             if ($callWithThisValue) {
   4617                 push(@args, GetNativeTypeForCallbacks("any") . " thisValue");
   4618             }
   4619             foreach my $param (@params) {
   4620                 my $paramName = $param->name;
   4621                 my $type = $param->type;
   4622                 my $arrayOrSequenceType = GetArrayOrSequenceType($type);
   4623 
   4624                 if ($arrayOrSequenceType) {
   4625                     if (IsRefPtrType($arrayOrSequenceType)) {
   4626                         AddIncludesForType($arrayOrSequenceType);
   4627                      }
   4628                 } else {
   4629                     AddIncludesForType($type);
   4630                 }
   4631 
   4632                 push(@args, GetNativeTypeForCallbacks($type) . " " . $paramName);
   4633             }
   4634             $code .= join(", ", @args);
   4635 
   4636             $code .= ")\n";
   4637             $code .= "{\n";
   4638             $code .= "    if (!canInvokeCallback())\n";
   4639             $code .= "        return true;\n\n";
   4640             $code .= "    v8::Isolate* isolate = v8::Isolate::GetCurrent();\n";
   4641             $code .= "    v8::HandleScope handleScope(isolate);\n\n";
   4642             $code .= "    v8::Handle<v8::Context> v8Context = toV8Context(scriptExecutionContext(), m_world.get());\n";
   4643             $code .= "    if (v8Context.IsEmpty())\n";
   4644             $code .= "        return true;\n\n";
   4645             $code .= "    v8::Context::Scope scope(v8Context);\n\n";
   4646 
   4647             my $thisObjectHandle = "";
   4648             if ($callWithThisValue) {
   4649                 $code .= "    v8::Handle<v8::Value> thisHandle = thisValue.v8Value();\n";
   4650                 $code .= "    if (thisHandle.IsEmpty()) {\n";
   4651                 $code .= "        if (!isScriptControllerTerminating())\n";
   4652                 $code .= "            CRASH();\n";
   4653                 $code .= "        return true;\n";
   4654                 $code .= "    }\n";
   4655                 $code .= "    ASSERT(thisHandle->isObject());\n";
   4656                 $thisObjectHandle = "v8::Handle<v8::Object>::Cast(thisHandle), ";
   4657             }
   4658             @args = ();
   4659             foreach my $param (@params) {
   4660                 my $paramName = $param->name;
   4661                 $code .= NativeToJSValue($param->type, $param->extendedAttributes, $paramName, "    ", "v8::Handle<v8::Value> ${paramName}Handle =", "v8::Handle<v8::Object>()", "isolate", "") . "\n";
   4662                 $code .= "    if (${paramName}Handle.IsEmpty()) {\n";
   4663                 $code .= "        if (!isScriptControllerTerminating())\n";
   4664                 $code .= "            CRASH();\n";
   4665                 $code .= "        return true;\n";
   4666                 $code .= "    }\n";
   4667                 push(@args, "        ${paramName}Handle");
   4668             }
   4669 
   4670             if (scalar(@args) > 0) {
   4671                 $code .= "\n    v8::Handle<v8::Value> argv[] = {\n";
   4672                 $code .= join(",\n", @args);
   4673                 $code .= "\n    };\n\n";
   4674             } else {
   4675                 $code .= "\n    v8::Handle<v8::Value> *argv = 0;\n\n";
   4676             }
   4677             $code .= "    bool callbackReturnValue = false;\n";
   4678             $code .= "    return !invokeCallback(m_callback.newLocal(isolate), ${thisObjectHandle}" . scalar(@args) . ", argv, callbackReturnValue, scriptExecutionContext());\n";
   4679             $code .= "}\n";
   4680             $implementation{nameSpaceWebCore}->add($code);
   4681         }
   4682     }
   4683 }
   4684 
   4685 sub BaseInterfaceName
   4686 {
   4687     my $interface = shift;
   4688 
   4689     while ($interface->parent) {
   4690         $interface = ParseInterface($interface->parent);
   4691     }
   4692 
   4693     return $interface->name;
   4694 }
   4695 
   4696 sub GenerateToV8Converters
   4697 {
   4698     my $interface = shift;
   4699     my $v8ClassName = shift;
   4700     my $nativeType = shift;
   4701     my $interfaceName = $interface->name;
   4702 
   4703     if ($interface->extendedAttributes->{"DoNotGenerateWrap"} || $interface->extendedAttributes->{"DoNotGenerateToV8"}) {
   4704         return;
   4705     }
   4706 
   4707     AddToImplIncludes("bindings/v8/ScriptController.h");
   4708     AddToImplIncludes("core/page/Frame.h");
   4709 
   4710     my $createWrapperArgumentType = GetPassRefPtrType($nativeType);
   4711     my $baseType = BaseInterfaceName($interface);
   4712 
   4713     # FIXME: Do we really need to treat "GenerateIsReachable", "CustomIsReachable" and /SVG/
   4714     # as dependent DOM objects?
   4715     my $wrapperConfiguration = "WrapperConfiguration::Independent";
   4716     if (InheritsExtendedAttribute($interface, "ActiveDOMObject")
   4717         || InheritsExtendedAttribute($interface, "DependentLifetime")
   4718         || InheritsExtendedAttribute($interface, "GenerateIsReachable")
   4719         || InheritsExtendedAttribute($interface, "CustomIsReachable")
   4720         || $v8ClassName =~ /SVG/) {
   4721         $wrapperConfiguration = "WrapperConfiguration::Dependent";
   4722     }
   4723 
   4724     my $code = "";
   4725     $code .= <<END;
   4726 
   4727 v8::Handle<v8::Object> ${v8ClassName}::createWrapper(${createWrapperArgumentType} impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
   4728 {
   4729     ASSERT(impl.get());
   4730     ASSERT(DOMDataStore::getWrapper<${v8ClassName}>(impl.get(), isolate).IsEmpty());
   4731     if (ScriptWrappable::wrapperCanBeStoredInObject(impl.get())) {
   4732         const WrapperTypeInfo* actualInfo = ScriptWrappable::getTypeInfoFromObject(impl.get());
   4733         // Might be a XXXConstructor::info instead of an XXX::info. These will both have
   4734         // the same object de-ref functions, though, so use that as the basis of the check.
   4735         RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(actualInfo->derefObjectFunction == info.derefObjectFunction);
   4736     }
   4737 
   4738 END
   4739 
   4740     $code .= <<END if ($baseType ne $interfaceName);
   4741 END
   4742 
   4743     if (InheritsInterface($interface, "Document")) {
   4744         $code .= <<END;
   4745     if (Frame* frame = impl->frame()) {
   4746         if (frame->script()->initializeMainWorld()) {
   4747             // initializeMainWorld may have created a wrapper for the object, retry from the start.
   4748             v8::Handle<v8::Object> wrapper = DOMDataStore::getWrapper<${v8ClassName}>(impl.get(), isolate);
   4749             if (!wrapper.IsEmpty())
   4750                 return wrapper;
   4751         }
   4752     }
   4753 END
   4754     }
   4755 
   4756     $code .= <<END;
   4757 
   4758     v8::Handle<v8::Object> wrapper = V8DOMWrapper::createWrapper(creationContext, &info, toInternalPointer(impl.get()), isolate);
   4759     if (UNLIKELY(wrapper.IsEmpty()))
   4760         return wrapper;
   4761 END
   4762     if (IsTypedArrayType($interface->name)) {
   4763       AddToImplIncludes("bindings/v8/custom/V8ArrayBufferCustom.h");
   4764       $code .= <<END;
   4765     if (!impl->buffer()->hasDeallocationObserver()) {
   4766         v8::V8::AdjustAmountOfExternalAllocatedMemory(impl->buffer()->byteLength());
   4767         impl->buffer()->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instance());
   4768     }
   4769 END
   4770     }
   4771 
   4772     $code .= <<END;
   4773     installPerContextProperties(wrapper, impl.get(), isolate);
   4774     V8DOMWrapper::associateObjectWithWrapper<$v8ClassName>(impl, &info, wrapper, isolate, $wrapperConfiguration);
   4775     return wrapper;
   4776 }
   4777 END
   4778     $implementation{nameSpaceWebCore}->add($code);
   4779 }
   4780 
   4781 sub GenerateSecurityCheckFunctions
   4782 {
   4783     my $interface = shift;
   4784     my $implClassName = GetImplName($interface);
   4785     my $v8ClassName = GetV8ClassName($interface);
   4786 
   4787     AddToImplIncludes("bindings/v8/BindingSecurity.h");
   4788     $implementation{nameSpaceInternal}->add(<<END);
   4789 bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value>)
   4790 {
   4791     $implClassName* imp =  ${v8ClassName}::toNative(host);
   4792     return BindingSecurity::shouldAllowAccessToFrame(imp->frame(), DoNotReportSecurityError);
   4793 }
   4794 
   4795 END
   4796     $implementation{nameSpaceInternal}->add(<<END);
   4797 bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value>)
   4798 {
   4799     $implClassName* imp =  ${v8ClassName}::toNative(host);
   4800     return BindingSecurity::shouldAllowAccessToFrame(imp->frame(), DoNotReportSecurityError);
   4801 }
   4802 
   4803 END
   4804 }
   4805 
   4806 sub GetNativeTypeForConversions
   4807 {
   4808     my $interface = shift;
   4809     my $implClassName = GetImplName($interface);
   4810     $implClassName = GetSVGTypeNeedingTearOff($interface->name) if IsSVGTypeNeedingTearOff($interface->name);
   4811     return $implClassName;
   4812 }
   4813 
   4814 sub GetNamespaceForInterface
   4815 {
   4816     my $interface = shift;
   4817     return "WTF" if IsTypedArrayType($interface->name);
   4818     return "WebCore";
   4819 }
   4820 
   4821 sub GenerateFunctionCallString
   4822 {
   4823     my $function = shift;
   4824     my $numberOfParameters = shift;
   4825     my $indent = shift;
   4826     my $interface = shift;
   4827     my $forMainWorldSuffix = shift;
   4828     my %replacements = @_;
   4829 
   4830     my $interfaceName = $interface->name;
   4831     my $implClassName = GetImplName($interface);
   4832     my $name = GetImplName($function);
   4833     my $returnType = $function->type;
   4834     my $nativeReturnType = GetNativeType($returnType, {}, "");
   4835     my $code = "";
   4836 
   4837     my $isSVGTearOffType = (IsSVGTypeNeedingTearOff($returnType) and not $interfaceName =~ /List$/);
   4838     $nativeReturnType = GetSVGWrappedTypeNeedingTearOff($returnType) if $isSVGTearOffType;
   4839 
   4840     my $index = 0;
   4841 
   4842     my @arguments;
   4843     my $functionName;
   4844     my $implementedBy = $function->extendedAttributes->{"ImplementedBy"};
   4845     if ($implementedBy) {
   4846         my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy);
   4847         AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implementedByImplName));
   4848         unshift(@arguments, "imp") if !$function->isStatic;
   4849         $functionName = "${implementedByImplName}::${name}";
   4850     } elsif ($function->isStatic) {
   4851         $functionName = "${implClassName}::${name}";
   4852     } else {
   4853         $functionName = "imp->${name}";
   4854     }
   4855 
   4856     my $callWith = $function->extendedAttributes->{"CallWith"};
   4857     my ($callWithArgs, $subCode) = GenerateCallWith($callWith, $indent, 1, $function);
   4858     $code .= $subCode;
   4859     unshift(@arguments, @$callWithArgs);
   4860     $index += @$callWithArgs;
   4861     $numberOfParameters += @$callWithArgs;
   4862 
   4863     foreach my $parameter (@{$function->parameters}) {
   4864         if ($index eq $numberOfParameters) {
   4865             last;
   4866         }
   4867         my $paramName = $parameter->name;
   4868         my $paramType = $parameter->type;
   4869 
   4870         if ($replacements{$paramName}) {
   4871             push @arguments, $replacements{$paramName};
   4872         } elsif ($parameter->type eq "NodeFilter" || $parameter->type eq "XPathNSResolver") {
   4873             push @arguments, "$paramName.get()";
   4874         } elsif (IsSVGTypeNeedingTearOff($parameter->type) and not $interfaceName =~ /List$/) {
   4875             AddToImplIncludes("core/dom/ExceptionCode.h");
   4876             push @arguments, "$paramName->propertyReference()";
   4877             $code .= $indent . "if (!$paramName) {\n";
   4878             $code .= $indent . "    setDOMException(WebCore::TypeMismatchError, args.GetIsolate());\n";
   4879             $code .= $indent . "    return;\n";
   4880             $code .= $indent . "}\n";
   4881         } elsif ($parameter->type eq "SVGMatrix" and $interfaceName eq "SVGTransformList") {
   4882             push @arguments, "$paramName.get()";
   4883         } else {
   4884             push @arguments, $paramName;
   4885         }
   4886         $index++;
   4887     }
   4888 
   4889     if ($function->extendedAttributes->{"RaisesException"}) {
   4890         push @arguments, "es";
   4891     }
   4892 
   4893     my $functionString = "$functionName(" . join(", ", @arguments) . ")";
   4894 
   4895     my $return = "result";
   4896     my $returnIsRef = IsRefPtrType($returnType);
   4897 
   4898     if ($returnType eq "void") {
   4899         $code .= $indent . "$functionString;\n";
   4900     } elsif (ExtendedAttributeContains($callWith, "ScriptState") or $function->extendedAttributes->{"RaisesException"}) {
   4901         $code .= $indent . $nativeReturnType . " result = $functionString;\n";
   4902     } else {
   4903         # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
   4904         $return = $functionString;
   4905         $returnIsRef = 0;
   4906 
   4907         if ($interfaceName eq "SVGTransformList" and IsRefPtrType($returnType)) {
   4908             $return = "WTF::getPtr(" . $return . ")";
   4909         }
   4910     }
   4911 
   4912     if ($function->extendedAttributes->{"RaisesException"}) {
   4913         $code .= $indent . "if (es.throwIfNeeded())\n";
   4914         $code .= $indent . "    return;\n";
   4915     }
   4916 
   4917     if (ExtendedAttributeContains($callWith, "ScriptState")) {
   4918         $code .= $indent . "if (state.hadException()) {\n";
   4919         $code .= $indent . "    v8::Local<v8::Value> exception = state.exception();\n";
   4920         $code .= $indent . "    state.clearException();\n";
   4921         $code .= $indent . "    throwError(exception);\n";
   4922         $code .= $indent . "    return;\n";
   4923         $code .= $indent . "}\n";
   4924     }
   4925 
   4926     if ($isSVGTearOffType) {
   4927         AddToImplIncludes("V8$returnType.h");
   4928         AddToImplIncludes("core/svg/properties/SVGPropertyTearOff.h");
   4929         my $svgNativeType = GetSVGTypeNeedingTearOff($returnType);
   4930         # FIXME: Update for all ScriptWrappables.
   4931         if (IsDOMNodeType($interfaceName)) {
   4932             if ($forMainWorldSuffix eq "ForMainWorld") {
   4933                 $code .= $indent . "v8SetReturnValue(args, toV8ForMainWorld(WTF::getPtr(${svgNativeType}::create($return)), args.Holder(), args.GetIsolate()));\n";
   4934             } else {
   4935                 $code .= $indent . "v8SetReturnValue(args, toV8Fast(WTF::getPtr(${svgNativeType}::create($return)), args, imp));\n";
   4936             }
   4937         } else {
   4938             $code .= $indent . "v8SetReturnValue(args, toV8${forMainWorldSuffix}(WTF::getPtr(${svgNativeType}::create($return)), args.Holder(), args.GetIsolate()));\n";
   4939         }
   4940         $code .= $indent . "return;\n";
   4941         return $code;
   4942     }
   4943 
   4944     # If the implementing class is a POD type, commit changes
   4945     if (IsSVGTypeNeedingTearOff($interfaceName) and not $interfaceName =~ /List$/) {
   4946         $code .= $indent . "wrapper->commitChange();\n";
   4947     }
   4948 
   4949     $return .= ".release()" if ($returnIsRef);
   4950 
   4951     my $nativeValue;
   4952     # FIXME: Update for all ScriptWrappables.
   4953     if (IsDOMNodeType($interfaceName)) {
   4954         $nativeValue = NativeToJSValue($function->type, $function->extendedAttributes, $return, $indent, "", "args.Holder()", "args.GetIsolate()", "args", "imp", $forMainWorldSuffix, "return");
   4955     } else {
   4956         $nativeValue = NativeToJSValue($function->type, $function->extendedAttributes, $return, $indent, "", "args.Holder()", "args.GetIsolate()", "args", 0, $forMainWorldSuffix, "return");
   4957     }
   4958 
   4959     $code .= $nativeValue . "\n";
   4960     $code .= $indent . "return;\n";
   4961 
   4962     return $code;
   4963 }
   4964 
   4965 sub GetNativeType
   4966 {
   4967     my $type = shift;
   4968     my $extendedAttributes = shift;
   4969     my $isParameter = shift;
   4970 
   4971     my $svgNativeType = GetSVGTypeNeedingTearOff($type);
   4972     if ($svgNativeType) {
   4973         if ($svgNativeType =~ /List$/) {
   4974             return "${svgNativeType}*";
   4975         } else {
   4976             return "RefPtr<${svgNativeType} >";
   4977         }
   4978     }
   4979 
   4980     return "float" if $type eq "float";
   4981     return "double" if $type eq "double";
   4982     return "int" if $type eq "long" or $type eq "int" or $type eq "short" or $type eq "byte";
   4983     if ($type eq "unsigned long" or $type eq "unsigned int" or $type eq "unsigned short" or $type eq "octet") {
   4984         if ($extendedAttributes->{"IsIndex"}) {
   4985             # Special-case index arguments because we need to check that they aren't < 0.
   4986             return "int";
   4987         }
   4988         return "unsigned";
   4989     }
   4990     return "long long" if $type eq "long long";
   4991     return "unsigned long long" if $type eq "unsigned long long";
   4992     return "bool" if $type eq "boolean";
   4993 
   4994     if (($type eq "DOMString" || IsEnumType($type)) and $isParameter) {
   4995         # FIXME: This implements [TreatNullAs=NullString] and [TreatUndefinedAs=NullString],
   4996         # but the Web IDL spec requires [TreatNullAs=EmptyString] and [TreatUndefinedAs=EmptyString].
   4997         my $mode = "";
   4998         if (($extendedAttributes->{"TreatNullAs"} and $extendedAttributes->{"TreatNullAs"} eq "NullString") and ($extendedAttributes->{"TreatUndefinedAs"} and $extendedAttributes->{"TreatUndefinedAs"} eq "NullString")) {
   4999             $mode = "WithUndefinedOrNullCheck";
   5000         } elsif (($extendedAttributes->{"TreatNullAs"} and $extendedAttributes->{"TreatNullAs"} eq "NullString") or $extendedAttributes->{"Reflect"}) {
   5001             $mode = "WithNullCheck";
   5002         }
   5003         # FIXME: Add the case for 'elsif ($attributeOrParameter->extendedAttributes->{"TreatUndefinedAs"} and $attributeOrParameter->extendedAttributes->{"TreatUndefinedAs"} eq "NullString"))'.
   5004         return "V8StringResource<$mode>";
   5005     }
   5006 
   5007     return "String" if $type eq "DOMString" or IsEnumType($type);
   5008 
   5009     return "Range::CompareHow" if $type eq "CompareHow";
   5010     return "DOMTimeStamp" if $type eq "DOMTimeStamp";
   5011     return "double" if $type eq "Date";
   5012     return "ScriptValue" if $type eq "any" or IsCallbackFunctionType($type);
   5013     return "Dictionary" if $type eq "Dictionary";
   5014 
   5015     return "RefPtr<DOMStringList>" if $type eq "DOMStringList";
   5016     return "RefPtr<MediaQueryListListener>" if $type eq "MediaQueryListListener";
   5017     return "RefPtr<NodeFilter>" if $type eq "NodeFilter";
   5018     return "RefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValue";
   5019     return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver";
   5020 
   5021     die "UnionType is not supported" if IsUnionType($type);
   5022 
   5023     if (IsTypedArrayType($type)) {
   5024         return $isParameter ? "${type}*" : "RefPtr<${type}>";
   5025     }
   5026 
   5027     # We need to check [ImplementedAs] extended attribute for wrapper types.
   5028     if (IsWrapperType($type)) {
   5029         my $interface = ParseInterface($type);
   5030         my $implClassName = GetImplName($interface);
   5031         return $isParameter ? "${implClassName}*" : "RefPtr<${implClassName}>";
   5032     }
   5033     return "RefPtr<${type}>" if IsRefPtrType($type) and not $isParameter;
   5034 
   5035     my $arrayOrSequenceType = GetArrayOrSequenceType($type);
   5036 
   5037     if ($arrayOrSequenceType) {
   5038         my $nativeType = GetNativeType($arrayOrSequenceType);
   5039         $nativeType .= " " if ($nativeType =~ />$/);
   5040         return "Vector<${nativeType}>";
   5041     }
   5042 
   5043     # Default, assume native type is a pointer with same type name as idl type
   5044     return "${type}*";
   5045 }
   5046 
   5047 sub GetNativeTypeForCallbacks
   5048 {
   5049     my $type = shift;
   5050     return "const String&" if $type eq "DOMString";
   5051     return "PassRefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValue";
   5052 
   5053     # Callbacks use raw pointers, so pass isParameter = 1
   5054     return GetNativeType($type, {}, "parameter");
   5055 }
   5056 
   5057 sub JSValueToNativeStatement
   5058 {
   5059     my $type = shift;
   5060     my $extendedAttributes = shift;
   5061     my $jsValue = shift;
   5062     my $variableName = shift;
   5063     my $indent = shift;
   5064     my $getIsolate = shift;
   5065 
   5066     my $nativeType = GetNativeType($type, $extendedAttributes, "parameter");
   5067     if ($type eq "unsigned long" and $extendedAttributes->{"IsIndex"}) {
   5068         # Special-case index arguments because we need to check that they aren't < 0.
   5069         $nativeType = "int";
   5070     }
   5071     my $native_value = JSValueToNative($type, $extendedAttributes, $jsValue, $getIsolate);
   5072     my $code = "";
   5073     if ($type eq "DOMString" || IsEnumType($type)) {
   5074         die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8StringResource/;
   5075         if ($type eq "DOMString" or IsEnumType($type)) {
   5076             $code .= $indent . "V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID($nativeType, $variableName, $native_value);\n"
   5077         } else {
   5078             $code .= $indent . "$nativeType $variableName($native_value, true);\n";
   5079         }
   5080     } elsif ($extendedAttributes->{"EnforceRange"}) {
   5081         $code .= $indent . "V8TRYCATCH_WITH_TYPECHECK_VOID($nativeType, $variableName, $native_value, $getIsolate);\n";
   5082     } else {
   5083         $code .= $indent . "V8TRYCATCH_VOID($nativeType, $variableName, $native_value);\n";
   5084     }
   5085     return $code;
   5086 }
   5087 
   5088 
   5089 sub JSValueToNative
   5090 {
   5091     my $type = shift;
   5092     my $extendedAttributes = shift;
   5093     my $value = shift;
   5094     my $getIsolate = shift;
   5095 
   5096     my $intConversion = $extendedAttributes->{"EnforceRange"} ? "EnforceRange" : "NormalConversion";
   5097 
   5098     return "$value->BooleanValue()" if $type eq "boolean";
   5099     return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $type eq "double";
   5100 
   5101     if ($intConversion ne "NormalConversion") {
   5102         return "toInt8($value, $intConversion, ok)" if $type eq "byte";
   5103         return "toUInt8($value, $intConversion, ok)" if $type eq "octet";
   5104         return "toInt32($value, $intConversion, ok)" if $type eq "long" or $type eq "short";
   5105         return "toUInt32($value, $intConversion, ok)" if $type eq "unsigned long" or $type eq "unsigned short";
   5106         return "toInt64($value, $intConversion, ok)" if $type eq "long long";
   5107         return "toUInt64($value, $intConversion, ok)" if $type eq "unsigned long long";
   5108     } else {
   5109         return "toInt8($value)" if $type eq "byte";
   5110         return "toUInt8($value)" if $type eq "octet";
   5111         return "toInt32($value)" if $type eq "long" or $type eq "short";
   5112         return "toUInt32($value)" if $type eq "unsigned long" or $type eq "unsigned short";
   5113         return "toInt64($value)" if $type eq "long long";
   5114         return "toUInt64($value)" if $type eq "unsigned long long";
   5115     }
   5116     return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "CompareHow";
   5117     return "toWebCoreDate($value)" if $type eq "Date";
   5118     return "toDOMStringList($value, $getIsolate)" if $type eq "DOMStringList";
   5119 
   5120     if ($type eq "DOMString" or IsEnumType($type)) {
   5121         return $value;
   5122     }
   5123 
   5124     if ($type eq "SerializedScriptValue") {
   5125         AddToImplIncludes("bindings/v8/SerializedScriptValue.h");
   5126         return "SerializedScriptValue::create($value, $getIsolate)";
   5127     }
   5128 
   5129     if ($type eq "Dictionary") {
   5130         AddToImplIncludes("bindings/v8/Dictionary.h");
   5131         return "Dictionary($value, $getIsolate)";
   5132     }
   5133 
   5134     if ($type eq "any" || IsCallbackFunctionType($type)) {
   5135         AddToImplIncludes("bindings/v8/ScriptValue.h");
   5136         return "ScriptValue($value)";
   5137     }
   5138 
   5139     if ($type eq "NodeFilter") {
   5140         return "toNodeFilter($value, $getIsolate)";
   5141     }
   5142 
   5143     if ($type eq "MediaQueryListListener") {
   5144         AddToImplIncludes("core/css/MediaQueryListListener.h");
   5145         return "MediaQueryListListener::create(" . $value . ")";
   5146     }
   5147 
   5148     if ($type eq "EventTarget") {
   5149         return "V8DOMWrapper::isDOMWrapper($value) ? toWrapperTypeInfo(v8::Handle<v8::Object>::Cast($value))->toEventTarget(v8::Handle<v8::Object>::Cast($value)) : 0";
   5150     }
   5151 
   5152     if (IsTypedArrayType($type)) {
   5153         AddIncludesForType($type);
   5154         return "$value->Is${type}() ? V8${type}::toNative(v8::Handle<v8::${type}>::Cast($value)) : 0"
   5155     }
   5156 
   5157     if ($type eq "XPathNSResolver") {
   5158         return "toXPathNSResolver($value, $getIsolate)";
   5159     }
   5160 
   5161     my $arrayOrSequenceType = GetArrayOrSequenceType($type);
   5162 
   5163     if ($arrayOrSequenceType) {
   5164         if (IsRefPtrType($arrayOrSequenceType)) {
   5165             AddToImplIncludes("V8${arrayOrSequenceType}.h");
   5166             return "(toRefPtrNativeArray<${arrayOrSequenceType}, V8${arrayOrSequenceType}>($value, $getIsolate))";
   5167         }
   5168         return "toNativeArray<" . GetNativeType($arrayOrSequenceType) . ">($value, $getIsolate)";
   5169     }
   5170 
   5171     AddIncludesForType($type);
   5172 
   5173     AddToImplIncludes("V8${type}.h");
   5174     return "V8${type}::HasInstance($value, $getIsolate, worldType($getIsolate)) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
   5175 }
   5176 
   5177 sub CreateCustomSignature
   5178 {
   5179     my $function = shift;
   5180     my $count = @{$function->parameters};
   5181     my $name = $function->name;
   5182     my $code = "    const int ${name}Argc = ${count};\n" .
   5183       "    v8::Handle<v8::FunctionTemplate> ${name}Argv[${name}Argc] = { ";
   5184     my $first = 1;
   5185     foreach my $parameter (@{$function->parameters}) {
   5186         if ($first) { $first = 0; }
   5187         else { $code .= ", "; }
   5188         if (IsWrapperType($parameter->type) && not IsTypedArrayType($parameter->type)) {
   5189             if ($parameter->type eq "XPathNSResolver") {
   5190                 # Special case for XPathNSResolver.  All other browsers accepts a callable,
   5191                 # so, even though it's against IDL, accept objects here.
   5192                 $code .= "v8::Handle<v8::FunctionTemplate>()";
   5193             } else {
   5194                 my $type = $parameter->type;
   5195                 my $arrayOrSequenceType = GetArrayOrSequenceType($type);
   5196 
   5197                 if ($arrayOrSequenceType) {
   5198                     if (IsRefPtrType($arrayOrSequenceType)) {
   5199                         AddIncludesForType($arrayOrSequenceType);
   5200                     } else {
   5201                         $code .= "v8::Handle<v8::FunctionTemplate>()";
   5202                         next;
   5203                     }
   5204                 } else {
   5205                     AddIncludesForType($type);
   5206                 }
   5207                 $code .= "V8PerIsolateData::from(isolate)->rawTemplate(&V8${type}::info, currentWorldType)";
   5208             }
   5209         } else {
   5210             $code .= "v8::Handle<v8::FunctionTemplate>()";
   5211         }
   5212     }
   5213     $code .= " };\n";
   5214     $code .= "    v8::Handle<v8::Signature> ${name}Signature = v8::Signature::New(desc, ${name}Argc, ${name}Argv);\n";
   5215     return $code;
   5216 }
   5217 
   5218 
   5219 sub RequiresCustomSignature
   5220 {
   5221     my $function = shift;
   5222     # No signature needed for Custom function
   5223     if (HasCustomMethod($function->extendedAttributes)) {
   5224         return 0;
   5225     }
   5226     # No signature needed for overloaded function
   5227     if (@{$function->{overloads}} > 1) {
   5228         return 0;
   5229     }
   5230     if ($function->isStatic) {
   5231         return 0;
   5232     }
   5233     # Type checking is performed in the generated code
   5234     if ($function->extendedAttributes->{"StrictTypeChecking"}) {
   5235       return 0;
   5236     }
   5237     foreach my $parameter (@{$function->parameters}) {
   5238         if (($parameter->isOptional && !$parameter->extendedAttributes->{"Default"}) || IsCallbackInterface($parameter->type)) {
   5239             return 0;
   5240         }
   5241     }
   5242 
   5243     foreach my $parameter (@{$function->parameters}) {
   5244         if (IsWrapperType($parameter->type)) {
   5245             return 1;
   5246         }
   5247     }
   5248     return 0;
   5249 }
   5250 
   5251 sub IsUnionType
   5252 {
   5253     my $type = shift; # string or UnionType
   5254     if(ref($type) eq "UnionType") {
   5255         die "Currently only 2 values of non-union type is supported as union type.\n" unless @{$type->unionMemberTypes} == 2;
   5256         return 1;
   5257     }
   5258     return 0;
   5259 }
   5260 
   5261 sub IsWrapperType
   5262 {
   5263     my $type = shift;
   5264     return 0 if GetArrayType($type);
   5265     return 0 if GetSequenceType($type);
   5266     return 0 if IsCallbackFunctionType($type);
   5267     return 0 if IsEnumType($type);
   5268     return 0 if IsPrimitiveType($type);
   5269     return 0 if $type eq "DOMString";
   5270     return !$nonWrapperTypes{$type};
   5271 }
   5272 
   5273 sub IsCallbackInterface
   5274 {
   5275     my $type = shift;
   5276     return 0 unless IsWrapperType($type);
   5277     return 0 if IsTypedArrayType($type);
   5278 
   5279     my $idlFile = IDLFileForInterface($type)
   5280         or die("Could NOT find IDL file for interface \"$type\"!\n");
   5281 
   5282     open FILE, "<", $idlFile;
   5283     my @lines = <FILE>;
   5284     close FILE;
   5285 
   5286     my $fileContents = join('', @lines);
   5287     return ($fileContents =~ /callback\s+interface\s+(\w+)/gs);
   5288 }
   5289 
   5290 sub GetNativeTypeOfTypedArray
   5291 {
   5292     my $interface = shift;
   5293     my $interfaceName = $interface->name;
   5294     die "TypedArray of unknown type is found" unless $typedArrayHash{$interface->name};
   5295     return @{$typedArrayHash{$interface->name}};
   5296 }
   5297 
   5298 sub IsDOMNodeType
   5299 {
   5300     my $type = shift;
   5301 
   5302     return 1 if $type eq 'Attr';
   5303     return 1 if $type eq 'CDATASection';
   5304     return 1 if $type eq 'CharacterData';
   5305     return 1 if $type eq 'Comment';
   5306     return 1 if $type eq 'Document';
   5307     return 1 if $type eq 'DocumentFragment';
   5308     return 1 if $type eq 'DocumentType';
   5309     return 1 if $type eq 'Element';
   5310     return 1 if $type eq 'Entity';
   5311     return 1 if $type eq 'HTMLDocument';
   5312     return 1 if $type eq 'Node';
   5313     return 1 if $type eq 'Notation';
   5314     return 1 if $type eq 'ProcessingInstruction';
   5315     return 1 if $type eq 'ShadowRoot';
   5316     return 1 if $type eq 'SVGDocument';
   5317     return 1 if $type eq 'Text';
   5318 
   5319     return 1 if $type =~ /^HTML.*Element$/;
   5320     return 1 if $type =~ /^SVG.*Element$/;
   5321 
   5322     return 1 if $type eq 'TestNode';
   5323 
   5324     return 0;
   5325 }
   5326 
   5327 
   5328 sub NativeToJSValue
   5329 {
   5330     my $type = shift;
   5331     my $extendedAttributes = shift;
   5332     my $nativeValue = shift;
   5333     my $indent = shift;  # added before every line
   5334     my $receiver = shift;  # "return" or "<variableName> ="
   5335     my $getCreationContext = shift;
   5336     my $getIsolate = shift;
   5337     die "An Isolate is mandatory for native value => JS value conversion." unless $getIsolate;
   5338     my $getCallbackInfo = shift || "";
   5339     my $getCallbackInfoArg = $getCallbackInfo ? ", $getCallbackInfo" : "";
   5340     my $getScriptWrappable = shift || "";
   5341     my $getScriptWrappableArg = $getScriptWrappable ? ", $getScriptWrappable" : "";
   5342     my $forMainWorldSuffix = shift || "";
   5343     my $returnValueArg = shift || 0;
   5344     my $isReturnValue = $returnValueArg eq "return";
   5345 
   5346     if (IsUnionType($type)) {
   5347         my $types = $type->unionMemberTypes;
   5348         my @codes = ();
   5349         for my $i (0 .. scalar(@$types)-1) {
   5350             my $unionMemberType = $types->[$i];
   5351             my $unionMemberNumber = $i + 1;
   5352             my $unionMemberVariable = $nativeValue . $i;
   5353             my $unionMemberEnabledVariable = $nativeValue . $i . "Enabled";
   5354             my $unionMemberNativeValue = $unionMemberVariable;
   5355             $unionMemberNativeValue .= ".release()" if (IsRefPtrType($unionMemberType));
   5356             my $returnJSValueCode = NativeToJSValue($unionMemberType, $extendedAttributes, $unionMemberNativeValue, $indent . "    ", $receiver, $getCreationContext, $getIsolate, $getCallbackInfo, $getScriptWrappable, $forMainWorldSuffix, $returnValueArg);
   5357             my $code = "";
   5358             if ($isReturnValue) {
   5359               $code .= "${indent}if (${unionMemberEnabledVariable}) {\n";
   5360               $code .= "${returnJSValueCode}\n";
   5361               $code .= "${indent}    return;\n";
   5362               $code .= "${indent}}\n";
   5363             } else {
   5364               $code .= "${indent}if (${unionMemberEnabledVariable})\n";
   5365               $code .= "${returnJSValueCode}";
   5366             }
   5367             push @codes, $code;
   5368         }
   5369         return join "\n", @codes;
   5370     }
   5371 
   5372     if ($type eq "boolean") {
   5373         return "${indent}v8SetReturnValueBool(${getCallbackInfo}, ${nativeValue});" if $isReturnValue;
   5374         return "$indent$receiver v8Boolean($nativeValue, $getIsolate);";
   5375     }
   5376 
   5377     if ($type eq "void") { # equivalent to v8Undefined()
   5378         return "" if $isReturnValue;
   5379         return "$indent$receiver v8Undefined();"
   5380     }
   5381 
   5382     # HTML5 says that unsigned reflected attributes should be in the range
   5383     # [0, 2^31). When a value isn't in this range, a default value (or 0)
   5384     # should be returned instead.
   5385     if ($extendedAttributes->{"Reflect"} and ($type eq "unsigned long" or $type eq "unsigned short")) {
   5386         $nativeValue =~ s/getUnsignedIntegralAttribute/getIntegralAttribute/g;
   5387         return "${indent}v8SetReturnValueUnsigned(${getCallbackInfo}, std::max(0, ${nativeValue}));" if $isReturnValue;
   5388         return "$indent$receiver v8::Integer::NewFromUnsigned(std::max(0, " . $nativeValue . "), $getIsolate);";
   5389     }
   5390 
   5391     my $nativeType = GetNativeType($type);
   5392     if ($nativeType eq "int") {
   5393         return "${indent}v8SetReturnValueInt(${getCallbackInfo}, ${nativeValue});" if $isReturnValue;
   5394         return "$indent$receiver v8::Integer::New($nativeValue, $getIsolate);";
   5395     }
   5396 
   5397     if ($nativeType eq "unsigned") {
   5398         return "${indent}v8SetReturnValueUnsigned(${getCallbackInfo}, ${nativeValue});" if $isReturnValue;
   5399         return "$indent$receiver v8::Integer::NewFromUnsigned($nativeValue, $getIsolate);";
   5400     }
   5401 
   5402     if ($type eq "Date") {
   5403         return "${indent}v8SetReturnValue(${getCallbackInfo}, v8DateOrNull($nativeValue, $getIsolate));" if $isReturnValue;
   5404         return "$indent$receiver v8DateOrNull($nativeValue, $getIsolate);"
   5405     }
   5406 
   5407     # long long and unsigned long long are not representable in ECMAScript.
   5408     if ($type eq "long long" or $type eq "unsigned long long" or $type eq "DOMTimeStamp") {
   5409         return "${indent}v8SetReturnValue(${getCallbackInfo}, static_cast<double>($nativeValue));" if $isReturnValue;
   5410         return "$indent$receiver v8::Number::New(static_cast<double>($nativeValue));";
   5411     }
   5412 
   5413     if (IsPrimitiveType($type)) {
   5414         die "unexpected type $type" if not ($type eq "float" or $type eq "double");
   5415         return "${indent}v8SetReturnValue(${getCallbackInfo}, ${nativeValue});" if $isReturnValue;
   5416         return "$indent$receiver v8::Number::New($nativeValue);";
   5417     }
   5418 
   5419     if ($nativeType eq "ScriptValue") {
   5420         return "${indent}v8SetReturnValue(${getCallbackInfo}, ${nativeValue}.v8Value());" if $isReturnValue;
   5421         return "$indent$receiver $nativeValue.v8Value();";
   5422     }
   5423 
   5424     my $conv = $extendedAttributes->{"TreatReturnedNullStringAs"};
   5425     if (($type eq "DOMString" || IsEnumType($type)) && $isReturnValue) {
   5426         my $functionSuffix = "";
   5427         if (defined $conv) {
   5428             if ($conv eq "Null") {
   5429                 $functionSuffix = "OrNull";
   5430             } elsif ($conv eq "Undefined") {
   5431                 $functionSuffix = "OrUndefined";
   5432             } else {
   5433                 die "Unknown value for TreatReturnedNullStringAs extended attribute";
   5434             }
   5435         }
   5436         return "${indent}v8SetReturnValueString${functionSuffix}(${getCallbackInfo}, $nativeValue, $getIsolate);";
   5437     }
   5438 
   5439     if ($type eq "DOMString" or IsEnumType($type)) {
   5440         my $returnValue = "";
   5441         if (defined $conv) {
   5442             if ($conv eq "Null") {
   5443                 $returnValue = "v8StringOrNull($nativeValue, $getIsolate)";
   5444             } elsif ($conv eq "Undefined") {
   5445                 $returnValue = "v8StringOrUndefined($nativeValue, $getIsolate)";
   5446             } else {
   5447                 die "Unknown value for TreatReturnedNullStringAs extended attribute";
   5448             }
   5449         } else {
   5450             $returnValue = "v8String($nativeValue, $getIsolate)";
   5451         }
   5452         return "$indent$receiver $returnValue;";
   5453     }
   5454 
   5455     my $arrayOrSequenceType = GetArrayOrSequenceType($type);
   5456 
   5457     if ($arrayOrSequenceType) {
   5458         if (IsRefPtrType($arrayOrSequenceType)) {
   5459             AddIncludesForType($arrayOrSequenceType);
   5460         }
   5461         return "${indent}v8SetReturnValue(${getCallbackInfo}, v8Array($nativeValue, $getIsolate));" if $isReturnValue;
   5462         return "$indent$receiver v8Array($nativeValue, $getIsolate);";
   5463     }
   5464 
   5465     AddIncludesForType($type);
   5466 
   5467     if ($type eq "SerializedScriptValue") {
   5468         my $returnValue = "$nativeValue ? $nativeValue->deserialize() : v8::Handle<v8::Value>(v8::Null($getIsolate))";
   5469         return "${indent}v8SetReturnValue(${getCallbackInfo}, $returnValue);" if $isReturnValue;
   5470         return "$indent$receiver $returnValue;";
   5471     }
   5472 
   5473     AddToImplIncludes("wtf/RefPtr.h");
   5474     AddToImplIncludes("wtf/GetPtr.h");
   5475 
   5476     if ($getScriptWrappable) {
   5477         # FIXME: Use safe handles
   5478         if ($isReturnValue) {
   5479             if ($forMainWorldSuffix eq "ForMainWorld") {
   5480                 return "${indent}v8SetReturnValue(${getCallbackInfo}, toV8ForMainWorld($nativeValue, $getCallbackInfo.Holder(), $getCallbackInfo.GetIsolate()));";
   5481             }
   5482             return "${indent}v8SetReturnValue(${getCallbackInfo}, toV8Fast($nativeValue$getCallbackInfoArg$getScriptWrappableArg));";
   5483         }
   5484         if ($forMainWorldSuffix eq "ForMainWorld") {
   5485             return "$indent$receiver toV8ForMainWorld($nativeValue, $getCallbackInfo.Holder(), $getCallbackInfo.GetIsolate());";
   5486         }
   5487         return "$indent$receiver toV8Fast($nativeValue$getCallbackInfoArg$getScriptWrappableArg);";
   5488     }
   5489     # FIXME: Use safe handles
   5490     return "${indent}v8SetReturnValue(${getCallbackInfo}, toV8($nativeValue, $getCreationContext, $getIsolate));" if $isReturnValue;
   5491     return "$indent$receiver toV8($nativeValue, $getCreationContext, $getIsolate);";
   5492 }
   5493 
   5494 sub WriteData
   5495 {
   5496     my $object = shift;
   5497     my $interface = shift;
   5498     my $outputDirectory = shift;
   5499 
   5500     my $name = $interface->name;
   5501     my $headerFileName = "$outputDirectory/V8$name.h";
   5502     my $implFileName = "$outputDirectory/V8$name.cpp";
   5503 
   5504     my @includes = ();
   5505     foreach my $include (keys %implIncludes) {
   5506         push @includes, "\"$include\"";
   5507     }
   5508 
   5509     #FIXME: do not treat main header special
   5510     my $mainInclude = "\"V8$name.h\"";
   5511     foreach my $include (sort @includes) {
   5512         $implementation{includes}->add("#include $include\n") unless $include eq $mainInclude;
   5513     }
   5514     $implementation{includes}->add("\n") unless $interface->isCallback;
   5515     WriteFileIfChanged($implFileName, $implementation{root}->toString());
   5516 
   5517     %implIncludes = ();
   5518 
   5519     WriteFileIfChanged($headerFileName, $header{root}->toString());
   5520 }
   5521 
   5522 sub ConvertToV8StringResource
   5523 {
   5524     my $attributeOrParameter = shift;
   5525     my $nativeType = shift;
   5526     my $variableName = shift;
   5527     my $value = shift;
   5528 
   5529     die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8StringResource/;
   5530     if ($attributeOrParameter->type eq "DOMString" or IsEnumType($attributeOrParameter->type)) {
   5531         return "V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID($nativeType, $variableName, $value);"
   5532     } else {
   5533         return "$nativeType $variableName($value, true);";
   5534     }
   5535 }
   5536 
   5537 # Returns the RuntimeEnabledFeatures function name that is hooked up to check if a method/attribute is enabled.
   5538 sub GetRuntimeEnableFunctionName
   5539 {
   5540     my $signature = shift;
   5541 
   5542     # If a parameter is given (e.g. "EnabledAtRuntime=FeatureName") return the RuntimeEnabledFeatures::{FeatureName}Enabled() method.
   5543     return "RuntimeEnabledFeatures::" . ToMethodName($signature->extendedAttributes->{"EnabledAtRuntime"}) . "Enabled" if ($signature->extendedAttributes->{"EnabledAtRuntime"} && $signature->extendedAttributes->{"EnabledAtRuntime"} ne "VALUE_IS_MISSING");
   5544 
   5545     # Otherwise return a function named RuntimeEnabledFeatures::{methodName}Enabled().
   5546     return "RuntimeEnabledFeatures::" . ToMethodName($signature->name) . "Enabled";
   5547 }
   5548 
   5549 sub GetContextEnableFunction
   5550 {
   5551     my $signature = shift;
   5552 
   5553     # If a parameter is given (e.g. "EnabledPerContext=FeatureName") return the {FeatureName}Allowed() method.
   5554     if ($signature->extendedAttributes->{"EnabledPerContext"} && $signature->extendedAttributes->{"EnabledPerContext"} ne "VALUE_IS_MISSING") {
   5555         return "ContextFeatures::" . ToMethodName($signature->extendedAttributes->{"EnabledPerContext"}) . "Enabled";
   5556     }
   5557 
   5558     # Or it fallbacks to the attribute name if the parameter value is missing.
   5559     return "ContextFeatures::" . ToMethodName($signature->name) . "Enabled";
   5560 }
   5561 
   5562 sub GetPassRefPtrType
   5563 {
   5564     my $v8ClassName = shift;
   5565 
   5566     my $angleBracketSpace = $v8ClassName =~ />$/ ? " " : "";
   5567     return "PassRefPtr<${v8ClassName}${angleBracketSpace}>";
   5568 }
   5569 
   5570 sub WriteFileIfChanged
   5571 {
   5572     my $fileName = shift;
   5573     my $contents = shift;
   5574 
   5575     if (-f $fileName && $writeFileOnlyIfChanged) {
   5576         open FH, "<", $fileName or die "Couldn't open $fileName: $!\n";
   5577         my @lines = <FH>;
   5578         my $oldContents = join "", @lines;
   5579         close FH;
   5580         return if $contents eq $oldContents;
   5581     }
   5582     open FH, ">", $fileName or die "Couldn't open $fileName: $!\n";
   5583     print FH $contents;
   5584     close FH;
   5585 }
   5586 
   5587 sub ForAllParents
   5588 {
   5589     my $interface = shift;
   5590     my $beforeRecursion = shift;
   5591     my $afterRecursion = shift;
   5592 
   5593     my $recurse;
   5594     $recurse = sub {
   5595         my $currentInterface = shift;
   5596 
   5597         if ($currentInterface->parent) {
   5598             my $parentInterface = ParseInterface($currentInterface->parent);
   5599             if ($beforeRecursion) {
   5600                 &$beforeRecursion($parentInterface) eq 'prune' and return;
   5601             }
   5602             &$recurse($parentInterface);
   5603             &$afterRecursion($parentInterface) if $afterRecursion;
   5604         }
   5605     };
   5606 
   5607     &$recurse($interface);
   5608 }
   5609 
   5610 sub FindSuperMethod
   5611 {
   5612     my ($interface, $functionName) = @_;
   5613     my $indexer;
   5614     ForAllParents($interface, undef, sub {
   5615         my $currentInterface = shift;
   5616         foreach my $function (@{$currentInterface->functions}) {
   5617             if ($function->name eq $functionName) {
   5618                 $indexer = $function;
   5619                 return 'prune';
   5620             }
   5621         }
   5622     });
   5623     return $indexer;
   5624 }
   5625 
   5626 sub IsConstructorTemplate
   5627 {
   5628     my $interface = shift;
   5629     my $template = shift;
   5630 
   5631     return $interface->extendedAttributes->{"ConstructorTemplate"} && $interface->extendedAttributes->{"ConstructorTemplate"} eq $template;
   5632 }
   5633 
   5634 sub IsPrimitiveType
   5635 {
   5636     my $type = shift;
   5637 
   5638     return 1 if $primitiveTypeHash{$type};
   5639     return 0;
   5640 }
   5641 
   5642 sub IsCallbackFunctionType
   5643 {
   5644     my $type = shift;
   5645 
   5646     return 1 if $callbackFunctionTypeHash{$type};
   5647     return 0;
   5648 }
   5649 
   5650 sub IsEnumType
   5651 {
   5652     my $type = shift;
   5653 
   5654     return 1 if $enumTypeHash{$type};
   5655     return 0;
   5656 }
   5657 
   5658 sub ValidEnumValues
   5659 {
   5660     my $type = shift;
   5661 
   5662     return @{$enumTypeHash{$type}};
   5663 }
   5664 
   5665 sub IsSVGTypeNeedingTearOff
   5666 {
   5667     my $type = shift;
   5668 
   5669     return 1 if $svgTypeNeedingTearOff{$type};
   5670     return 0;
   5671 }
   5672 
   5673 sub IsSVGTypeWithWritablePropertiesNeedingTearOff
   5674 {
   5675     my $type = shift;
   5676 
   5677     return 1 if $svgTypeWithWritablePropertiesNeedingTearOff{$type};
   5678     return 0;
   5679 }
   5680 
   5681 sub IsTypedArrayType
   5682 {
   5683     my $type = shift;
   5684     return 1 if $typedArrayHash{$type};
   5685     return 0;
   5686 }
   5687 
   5688 sub IsRefPtrType
   5689 {
   5690     my $type = shift;
   5691 
   5692     return 0 if $type eq "any";
   5693     return 0 if IsPrimitiveType($type);
   5694     return 0 if GetArrayType($type);
   5695     return 0 if GetSequenceType($type);
   5696     return 0 if $type eq "DOMString";
   5697     return 0 if IsCallbackFunctionType($type);
   5698     return 0 if IsEnumType($type);
   5699     return 0 if IsUnionType($type);
   5700 
   5701     return 1;
   5702 }
   5703 
   5704 sub GetSVGTypeNeedingTearOff
   5705 {
   5706     my $type = shift;
   5707 
   5708     return $svgTypeNeedingTearOff{$type} if exists $svgTypeNeedingTearOff{$type};
   5709     return undef;
   5710 }
   5711 
   5712 sub GetSVGWrappedTypeNeedingTearOff
   5713 {
   5714     my $type = shift;
   5715 
   5716     my $svgTypeNeedingTearOff = GetSVGTypeNeedingTearOff($type);
   5717     return $svgTypeNeedingTearOff if not $svgTypeNeedingTearOff;
   5718 
   5719     if ($svgTypeNeedingTearOff =~ /SVGPropertyTearOff/) {
   5720         $svgTypeNeedingTearOff =~ s/SVGPropertyTearOff<//;
   5721     } elsif ($svgTypeNeedingTearOff =~ /SVGListPropertyTearOff/) {
   5722         $svgTypeNeedingTearOff =~ s/SVGListPropertyTearOff<//;
   5723     } elsif ($svgTypeNeedingTearOff =~ /SVGStaticListPropertyTearOff/) {
   5724         $svgTypeNeedingTearOff =~ s/SVGStaticListPropertyTearOff<//;
   5725     }  elsif ($svgTypeNeedingTearOff =~ /SVGTransformListPropertyTearOff/) {
   5726         $svgTypeNeedingTearOff =~ s/SVGTransformListPropertyTearOff<//;
   5727     }
   5728 
   5729     $svgTypeNeedingTearOff =~ s/>//;
   5730     return $svgTypeNeedingTearOff;
   5731 }
   5732 
   5733 sub IsSVGAnimatedType
   5734 {
   5735     my $type = shift;
   5736 
   5737     return $type =~ /^SVGAnimated/;
   5738 }
   5739 
   5740 sub GetSequenceType
   5741 {
   5742     my $type = shift;
   5743 
   5744     return $1 if $type =~ /^sequence<([\w\d_\s]+)>.*/;
   5745     return "";
   5746 }
   5747 
   5748 sub GetArrayType
   5749 {
   5750     my $type = shift;
   5751 
   5752     return $1 if $type =~ /^([\w\d_\s]+)\[\]/;
   5753     return "";
   5754 }
   5755 
   5756 sub GetArrayOrSequenceType
   5757 {
   5758     my $type = shift;
   5759 
   5760     return GetArrayType($type) || GetSequenceType($type);
   5761 }
   5762 
   5763 sub AssertNotSequenceType
   5764 {
   5765     my $type = shift;
   5766     die "Sequences must not be used as the type of an attribute, constant or exception field." if GetSequenceType($type);
   5767 }
   5768 
   5769 sub FirstLetterToUpperCase
   5770 {
   5771     my $param = shift;
   5772     my $ret = ucfirst($param);
   5773     # xmlEncoding becomes XMLEncoding, but xmlllang becomes Xmllang.
   5774     $ret =~ s/Xml/XML/ if $ret =~ /^Xml[^a-z]/;
   5775     $ret =~ s/Css/CSS/ if $ret =~ /^Css[^T]/;  # css -> setCSS, except setCssText.
   5776     $ret =~ s/Ime/IME/ if $ret =~ /^Ime/;  # ime -> setIME
   5777     $ret =~ s/Svg/SVG/ if $ret =~ /^Svg/;  # svg -> setSVG
   5778     return $ret;
   5779 }
   5780 
   5781 # URL becomes url, but SetURL becomes setURL.
   5782 sub ToMethodName
   5783 {
   5784     my $param = shift;
   5785     my $ret = lcfirst($param);
   5786     $ret =~ s/hTML/html/ if $ret =~ /^hTML/;
   5787     $ret =~ s/uRL/url/ if $ret =~ /^uRL/;
   5788     $ret =~ s/jS/js/ if $ret =~ /^jS/;
   5789     $ret =~ s/xML/xml/ if $ret =~ /^xML/;
   5790     $ret =~ s/xSLT/xslt/ if $ret =~ /^xSLT/;
   5791     $ret =~ s/cSS/css/ if $ret =~ /^cSS/;
   5792 
   5793     # For HTML5 FileSystem API Flags attributes.
   5794     # (create is widely used to instantiate an object and must be avoided.)
   5795     $ret =~ s/^create/isCreate/ if $ret =~ /^create$/;
   5796     $ret =~ s/^exclusive/isExclusive/ if $ret =~ /^exclusive$/;
   5797 
   5798     return $ret;
   5799 }
   5800 
   5801 sub NamespaceForAttributeName
   5802 {
   5803     my ($interfaceName, $attributeName) = @_;
   5804     return "SVGNames" if $interfaceName =~ /^SVG/ && !$svgAttributesInHTMLHash{$attributeName};
   5805     return "HTMLNames";
   5806 }
   5807 
   5808 # Identifies overloaded functions and for each function adds an array with
   5809 # links to its respective overloads (including itself).
   5810 sub LinkOverloadedFunctions
   5811 {
   5812     my $interface = shift;
   5813 
   5814     my %nameToFunctionsMap = ();
   5815     foreach my $function (@{$interface->functions}) {
   5816         my $name = $function->name;
   5817         $nameToFunctionsMap{$name} = [] if !exists $nameToFunctionsMap{$name} or !$name;  # Nameless functions cannot be overloaded
   5818         push(@{$nameToFunctionsMap{$name}}, $function);
   5819         $function->{overloads} = $nameToFunctionsMap{$name};
   5820         $function->{overloadIndex} = @{$nameToFunctionsMap{$name}};
   5821     }
   5822 }
   5823 
   5824 sub AttributeNameForGetterAndSetter
   5825 {
   5826     my $attribute = shift;
   5827 
   5828     my $attributeName = GetImplName($attribute);
   5829     if ($attribute->extendedAttributes->{"ImplementedAs"}) {
   5830         $attributeName = $attribute->extendedAttributes->{"ImplementedAs"};
   5831     }
   5832     my $attributeType = $attribute->type;
   5833 
   5834     return $attributeName;
   5835 }
   5836 
   5837 sub ContentAttributeName
   5838 {
   5839     my ($interfaceName, $attribute) = @_;
   5840 
   5841     my $contentAttributeName = $attribute->extendedAttributes->{"Reflect"};
   5842     return undef if !$contentAttributeName;
   5843 
   5844     $contentAttributeName = lc AttributeNameForGetterAndSetter($attribute) if $contentAttributeName eq "VALUE_IS_MISSING";
   5845 
   5846     my $namespace = NamespaceForAttributeName($interfaceName, $contentAttributeName);
   5847 
   5848     AddToImplIncludes("${namespace}.h");
   5849     return "WebCore::${namespace}::${contentAttributeName}Attr";
   5850 }
   5851 
   5852 sub GetterExpression
   5853 {
   5854     my ($interfaceName, $attribute) = @_;
   5855 
   5856     my $contentAttributeName = ContentAttributeName($interfaceName, $attribute);
   5857 
   5858     if (!$contentAttributeName) {
   5859         return (ToMethodName(AttributeNameForGetterAndSetter($attribute)));
   5860     }
   5861 
   5862     my $functionName;
   5863     if ($attribute->extendedAttributes->{"URL"}) {
   5864         $functionName = "getURLAttribute";
   5865     } elsif ($attribute->type eq "boolean") {
   5866         $functionName = "fastHasAttribute";
   5867     } elsif ($attribute->type eq "long") {
   5868         $functionName = "getIntegralAttribute";
   5869     } elsif ($attribute->type eq "unsigned long") {
   5870         $functionName = "getUnsignedIntegralAttribute";
   5871     } else {
   5872         if ($contentAttributeName eq "WebCore::HTMLNames::idAttr") {
   5873             $functionName = "getIdAttribute";
   5874             $contentAttributeName = "";
   5875         } elsif ($contentAttributeName eq "WebCore::HTMLNames::nameAttr") {
   5876             $functionName = "getNameAttribute";
   5877             $contentAttributeName = "";
   5878         } elsif ($contentAttributeName eq "WebCore::HTMLNames::classAttr") {
   5879             $functionName = "getClassAttribute";
   5880             $contentAttributeName = "";
   5881         } else {
   5882             # We cannot use fast attributes for animated SVG types.
   5883             $functionName = IsSVGAnimatedType($attribute->type) ? "getAttribute" : "fastGetAttribute";
   5884         }
   5885     }
   5886 
   5887     return ($functionName, $contentAttributeName);
   5888 }
   5889 
   5890 sub SetterExpression
   5891 {
   5892     my ($interfaceName, $attribute) = @_;
   5893 
   5894     my $contentAttributeName = ContentAttributeName($interfaceName, $attribute);
   5895 
   5896     if (!$contentAttributeName) {
   5897         return ("set" . FirstLetterToUpperCase(AttributeNameForGetterAndSetter($attribute)));
   5898     }
   5899 
   5900     my $functionName;
   5901     if ($attribute->type eq "boolean") {
   5902         $functionName = "setBooleanAttribute";
   5903     } elsif ($attribute->type eq "long") {
   5904         $functionName = "setIntegralAttribute";
   5905     } elsif ($attribute->type eq "unsigned long") {
   5906         $functionName = "setUnsignedIntegralAttribute";
   5907     } else {
   5908         $functionName = "setAttribute";
   5909     }
   5910 
   5911     return ($functionName, $contentAttributeName);
   5912 }
   5913 
   5914 sub GenerateConditionalString
   5915 {
   5916     my $node = shift;
   5917 
   5918     my $conditional = $node->extendedAttributes->{"Conditional"};
   5919     if ($conditional) {
   5920         return GenerateConditionalStringFromAttributeValue($conditional);
   5921     } else {
   5922         return "";
   5923     }
   5924 }
   5925 
   5926 sub GenerateConditionalStringFromAttributeValue
   5927 {
   5928     my $conditional = shift;
   5929 
   5930     my $operator = ($conditional =~ /&/ ? '&' : ($conditional =~ /\|/ ? '|' : ''));
   5931     if ($operator) {
   5932         # Avoid duplicated conditions.
   5933         my %conditions;
   5934         map { $conditions{$_} = 1 } split('\\' . $operator, $conditional);
   5935         return "ENABLE(" . join(") $operator$operator ENABLE(", sort keys %conditions) . ")";
   5936     } else {
   5937         return "ENABLE(" . $conditional . ")";
   5938     }
   5939 }
   5940 
   5941 sub GenerateCompileTimeCheckForEnumsIfNeeded
   5942 {
   5943     my $interface = shift;
   5944     my $implClassName = GetImplName($interface);
   5945     my @checks = ();
   5946     # If necessary, check that all constants are available as enums with the same value.
   5947     if (!$interface->extendedAttributes->{"DoNotCheckConstants"} && @{$interface->constants}) {
   5948         push(@checks, "\n");
   5949         foreach my $constant (@{$interface->constants}) {
   5950             my $reflect = $constant->extendedAttributes->{"Reflect"};
   5951             my $name = $reflect ? $reflect : $constant->name;
   5952             my $value = $constant->value;
   5953             my $conditionalString = GenerateConditionalString($constant);
   5954             push(@checks, "#if ${conditionalString}\n") if $conditionalString;
   5955 
   5956             if ($constant->extendedAttributes->{"ImplementedBy"}) {
   5957                 my $implementedByImplName = GetImplNameFromImplementedBy($constant->extendedAttributes->{"ImplementedBy"});
   5958                 push(@checks, "COMPILE_ASSERT($value == " . $implementedByImplName . "::$name, ${implClassName}Enum${name}IsWrongUseDoNotCheckConstants);\n");
   5959             } else {
   5960                 push(@checks, "COMPILE_ASSERT($value == ${implClassName}::$name, ${implClassName}Enum${name}IsWrongUseDoNotCheckConstants);\n");
   5961             }
   5962 
   5963             push(@checks, "#endif\n") if $conditionalString;
   5964         }
   5965         push(@checks, "\n");
   5966     }
   5967     return @checks;
   5968 }
   5969 
   5970 sub ExtendedAttributeContains
   5971 {
   5972     my $callWith = shift;
   5973     return 0 unless $callWith;
   5974     my $keyword = shift;
   5975 
   5976     my @callWithKeywords = split /\s*\&\s*/, $callWith;
   5977     return grep { $_ eq $keyword } @callWithKeywords;
   5978 }
   5979 
   5980 sub InheritsInterface
   5981 {
   5982     my $interface = shift;
   5983     my $interfaceName = shift;
   5984     my $found = 0;
   5985 
   5986     return 1 if $interfaceName eq $interface->name;
   5987     ForAllParents($interface, sub {
   5988         my $currentInterface = shift;
   5989         if ($currentInterface->name eq $interfaceName) {
   5990             $found = 1;
   5991         }
   5992         return 1 if $found;
   5993     }, 0);
   5994 
   5995     return $found;
   5996 }
   5997 
   5998 sub InheritsExtendedAttribute
   5999 {
   6000     my $interface = shift;
   6001     my $extendedAttribute = shift;
   6002     my $found = 0;
   6003 
   6004     return 1 if $interface->extendedAttributes->{$extendedAttribute};
   6005     ForAllParents($interface, sub {
   6006         my $currentInterface = shift;
   6007         if ($currentInterface->extendedAttributes->{$extendedAttribute}) {
   6008             $found = 1;
   6009         }
   6010         return 1 if $found;
   6011     }, 0);
   6012 
   6013     return $found;
   6014 }
   6015 
   6016 1;
   6017