1# Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
2# Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
3# Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
4# Copyright (C) 2006 Alexey Proskuryakov <ap@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@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
29package 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
47sub 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
64sub addHeader
65{
66    my $object = shift;
67    my $header = shift || "";
68
69    push(@{$object->{header}}, $header);
70}
71
72sub addFooter
73{
74    my $object = shift;
75    my $footer = shift || "";
76
77    push(@{$object->{footer}}, $footer);
78}
79
80sub add
81{
82    my $object = shift;
83    my $content = shift || "";
84
85    push(@{$object->{contents}}, $content);
86}
87
88sub 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
110package deprecated_code_generator_v8;
111
112use strict;
113use Cwd;
114use File::Basename;
115use File::Find;
116use File::Spec;
117
118my $idlDocument;
119my $idlDirectories;
120my $preprocessor;
121my $verbose;
122my $interfaceIdlFiles;
123my $writeFileOnlyIfChanged;
124my $sourceRoot;
125
126# Cache of IDL file pathnames.
127my $idlFiles;
128my $cachedInterfaces = {};
129
130my %implIncludes = ();
131my %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
141my %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
149my %implementation;
150
151my %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
166my %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
177my %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
190my %callbackFunctionTypeHash = ();
191
192my %enumTypeHash = ();
193
194my %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
201my %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
218my %svgTypeWithWritablePropertiesNeedingTearOff = (
219    "SVGPoint" => 1,
220    "SVGMatrix" => 1
221);
222
223# Default .h template
224my $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*/
244EOF
245
246sub 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
265sub 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
288sub 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
316sub 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
391sub AddToImplIncludes
392{
393    my $header = shift;
394    $implIncludes{$header} = 1;
395}
396
397sub AddToHeaderIncludes
398{
399    my @includes = @_;
400
401    for my $include (@includes) {
402        $headerIncludes{$include} = 1;
403    }
404}
405
406sub 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
417sub 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
437sub 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
453sub NeedsOpaqueRootForGC
454{
455    my $interface = shift;
456    return $interface->extendedAttributes->{"GenerateIsReachable"} || $interface->extendedAttributes->{"CustomIsReachable"};
457}
458
459sub 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;
470void* ${v8ClassName}::opaqueRootForGC(void* object, v8::Isolate* isolate)
471{
472    ${implClassName}* impl = fromInternalPointer(object);
473END
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);
481END
482    }
483
484    $code .= <<END;
485    return object;
486}
487
488END
489    $implementation{nameSpaceWebCore}->add($code);
490}
491
492sub 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
523sub 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
536sub GetIndexedSetterFunction
537{
538    my $interface = shift;
539
540    return GetSpecialAccessorFunctionForType($interface, "setter", "unsigned long", 2);
541}
542
543sub GetIndexedDeleterFunction
544{
545    my $interface = shift;
546
547    return GetSpecialAccessorFunctionForType($interface, "deleter", "unsigned long", 1);
548}
549
550sub GetNamedGetterFunction
551{
552    my $interface = shift;
553    return GetSpecialAccessorFunctionForType($interface, "getter", "DOMString", 1);
554}
555
556sub GetNamedSetterFunction
557{
558    my $interface = shift;
559    return GetSpecialAccessorFunctionForType($interface, "setter", "DOMString", 2);
560}
561
562sub GetNamedDeleterFunction
563{
564    my $interface = shift;
565    return GetSpecialAccessorFunctionForType($interface, "deleter", "DOMString", 1);
566}
567
568sub 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
587sub 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
628class V8${nativeType}Constructor {
629public:
630    static v8::Handle<v8::FunctionTemplate> GetTemplate(v8::Isolate*, WrapperWorldType);
631    static WrapperTypeInfo info;
632};
633END
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;
649END
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);
666END
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>&);
680END
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");
690END
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>&);
705END
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>&);
712END
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    }
745END
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);
751END
752    }
753
754    if (@enabledPerContextAttributes) {
755        $header{classPublic}->add(<<END);
756    static void installPerContextProperties(v8::Handle<v8::Object>, ${nativeType}*, v8::Isolate*);
757END
758    } else {
759        $header{classPublic}->add(<<END);
760    static void installPerContextProperties(v8::Handle<v8::Object>, ${nativeType}*, v8::Isolate*) { }
761END
762    }
763
764    if (@enabledPerContextFunctions) {
765        $header{classPublic}->add(<<END);
766    static void installPerContextPrototypeProperties(v8::Handle<v8::Object>, v8::Isolate*);
767END
768    } else {
769        $header{classPublic}->add(<<END);
770    static void installPerContextPrototypeProperties(v8::Handle<v8::Object>, v8::Isolate*) { }
771END
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*);
778END
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*);
784END
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*);
788END
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*);
793END
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*);
803END
804    }
805
806    $header{nameSpaceWebCore}->add(<<END);
807
808template<>
809class WrapperTypeTraits<${nativeType} > {
810public:
811    static WrapperTypeInfo* info() { return &${v8ClassName}::info; }
812};
813
814END
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);
822class ${nativeType};
823v8::Handle<v8::Value> toV8(${nativeType}*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
824v8::Handle<v8::Value> toV8ForMainWorld(${nativeType}*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
825
826template<class CallbackInfo, class Wrappable>
827inline v8::Handle<v8::Value> toV8Fast(${nativeType}* impl, const CallbackInfo& callbackInfo, Wrappable*)
828{
829    return toV8(impl, callbackInfo.Holder(), callbackInfo.GetIsolate());
830}
831
832END
833    } else {
834
835        my $createWrapperCall = $customWrap ? "${v8ClassName}::wrap" : "${v8ClassName}::createWrapper";
836
837        if ($customWrap) {
838            $header{nameSpaceWebCore}->add(<<END);
839
840v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate*);
841END
842        } else {
843            $header{nameSpaceWebCore}->add(<<END);
844
845inline 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}
851END
852        }
853
854        $header{nameSpaceWebCore}->add(<<END);
855
856inline 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
866inline 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
877template<class CallbackInfo, class Wrappable>
878inline 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
888inline 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
893END
894    }
895
896    $header{nameSpaceWebCore}->add(<<END);
897
898template<class CallbackInfo, class Wrappable>
899inline v8::Handle<v8::Value> toV8Fast(PassRefPtr< ${nativeType} > impl, const CallbackInfo& callbackInfo, Wrappable* wrappable)
900{
901    return toV8Fast(impl.get(), callbackInfo, wrappable);
902}
903
904inline 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
909END
910
911    if (IsConstructorTemplate($interface, "Event")) {
912        $header{nameSpaceWebCore}->add("bool fill${implClassName}Init(${implClassName}Init&, const Dictionary&);\n\n");
913    }
914}
915
916sub 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
929sub 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};
937END
938        $customFieldCounter++;
939    }
940    $header{classPublic}->add(<<END);
941    static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
942END
943}
944
945sub 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
1000sub 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
1009sub 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
1029sub IsConstructable
1030{
1031    my $interface = shift;
1032
1033    return $interface->extendedAttributes->{"CustomConstructor"} || $interface->extendedAttributes->{"Constructor"} || $interface->extendedAttributes->{"ConstructorTemplate"};
1034}
1035
1036sub HasCustomConstructor
1037{
1038    my $interface = shift;
1039
1040    return $interface->extendedAttributes->{"CustomConstructor"};
1041}
1042
1043sub HasCustomGetter
1044{
1045    my $attrExt = shift;
1046    return $attrExt->{"Custom"} || $attrExt->{"CustomGetter"};
1047}
1048
1049sub HasCustomSetter
1050{
1051    my $attrExt = shift;
1052    return $attrExt->{"Custom"} || $attrExt->{"CustomSetter"};
1053}
1054
1055sub HasCustomMethod
1056{
1057    my $attrExt = shift;
1058    return $attrExt->{"Custom"};
1059}
1060
1061sub IsReadonly
1062{
1063    my $attribute = shift;
1064    my $attrExt = $attribute->extendedAttributes;
1065    return $attribute->isReadOnly && !$attrExt->{"Replaceable"};
1066}
1067
1068sub GetV8ClassName
1069{
1070    my $interface = shift;
1071    return "V8" . $interface->name;
1072}
1073
1074sub GetImplName
1075{
1076    my $interfaceOrAttributeOrFunction = shift;
1077    return $interfaceOrAttributeOrFunction->extendedAttributes->{"ImplementedAs"} || $interfaceOrAttributeOrFunction->name;
1078}
1079
1080sub GetImplNameFromImplementedBy
1081{
1082    my $implementedBy = shift;
1083
1084    my $interface = ParseInterface($implementedBy);
1085
1086    return $interface->extendedAttributes->{"ImplementedAs"} || $implementedBy;
1087}
1088
1089sub 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);
1109static 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
1141END
1142    $implementation{nameSpaceInternal}->add(<<END);
1143static 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
1150END
1151}
1152
1153sub 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);
1162static 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
1174END
1175}
1176
1177sub GenerateConstructorGetter
1178{
1179    my $interface = shift;
1180    my $implClassName = GetImplName($interface);
1181
1182    $implementation{nameSpaceInternal}->add(<<END);
1183static 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}
1192END
1193}
1194
1195sub 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
1207sub 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
1218sub 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    }
1238END
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    }
1246END
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}");
1252END
1253    } else {
1254        die "Unrecognized activity logging access type";
1255    }
1256
1257    return $code;
1258}
1259
1260sub 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
1295sub 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;
1320static void ${attrName}AttrGetter${forMainWorldSuffix}(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
1321{
1322END
1323    if ($svgNativeType) {
1324        my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($interfaceName);
1325        if ($svgWrappedNativeType =~ /List/) {
1326            $code .= <<END;
1327    $svgNativeType* imp = ${v8ClassName}::toNative(info.Holder());
1328END
1329        } else {
1330            $code .= <<END;
1331    $svgNativeType* wrapper = ${v8ClassName}::toNative(info.Holder());
1332    $svgWrappedNativeType& impInstance = wrapper->propertyReference();
1333    $svgWrappedNativeType* imp = &impInstance;
1334END
1335        }
1336    } elsif ($attrExt->{"OnProto"} || $attrExt->{"Unforgeable"}) {
1337        if ($interfaceName eq "Window") {
1338            $code .= <<END;
1339    v8::Handle<v8::Object> holder = info.Holder();
1340END
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;
1347END
1348        }
1349        $code .= <<END;
1350    ${implClassName}* imp = ${v8ClassName}::toNative(holder);
1351END
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    }
1375END
1376        }
1377        if (!$attribute->isStatic) {
1378            $code .= <<END;
1379    ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());
1380END
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;
1559END
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
1578sub 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
1612sub 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
1631sub GenerateReplaceableAttrSetter
1632{
1633    my $interface = shift;
1634
1635    my $implClassName = GetImplName($interface);
1636    my $v8ClassName = GetV8ClassName($interface);
1637
1638    my $code = "";
1639    $code .= <<END;
1640static void ${implClassName}ReplaceableAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)
1641{
1642END
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;
1650END
1651    }
1652
1653    $code .= <<END;
1654    info.This()->ForceSet(name, value);
1655}
1656
1657END
1658    $implementation{nameSpaceInternal}->add($code);
1659}
1660
1661sub 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;
1677END
1678    }
1679    return $code;
1680}
1681
1682sub 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
1717sub 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());
1761END
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());
1775END
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());
1796END
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;
1822END
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.
1899END
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
1908sub 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.
1956sub 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
1970sub 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
1995sub 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;
2014static void ${name}Method${forMainWorldSuffix}(const v8::FunctionCallbackInfo<v8::Value>& args)
2015{
2016END
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());
2037END
2038    $code .= "}\n\n";
2039    $code .= "#endif // ${conditionalString}\n\n" if $conditionalString;
2040    $implementation{nameSpaceInternal}->add($code);
2041}
2042
2043sub 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;
2061static void ${name}MethodCallback${forMainWorldSuffix}(const v8::FunctionCallbackInfo<v8::Value>& args)
2062{
2063END
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
2081sub 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
2136END
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
2150END
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());
2176END
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;
2189END
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";
2212END
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
2225sub 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
2261sub 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
2287sub 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
2432sub GenerateOverloadedConstructorCallback
2433{
2434    my $interface = shift;
2435    my $implClassName = GetImplName($interface);
2436
2437    my $code = "";
2438    $code .= <<END;
2439static void constructor(const v8::FunctionCallbackInfo<v8::Value>& args)
2440{
2441END
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;
2461END
2462    $code .= "}\n\n";
2463    $implementation{nameSpaceInternal}->add($code);
2464}
2465
2466sub 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;
2494static void constructor${overloadedIndexString}(const v8::FunctionCallbackInfo<v8::Value>& args)
2495{
2496END
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
2555END
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.
2563sub 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
2583sub 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
2605sub 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
2619sub 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);
2638static 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]);
2646END
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;
2658END
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});
2666END
2667    }
2668
2669    $implementation{nameSpaceInternal}->add(<<END);
2670    }
2671
2672    RefPtr<${implClassName}> event = ${implClassName}::create(type, eventInit);
2673END
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()));
2685END
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}
2695END
2696
2697    my $code = "";
2698    $code .= <<END;
2699bool fill${implClassName}Init(${implClassName}Init& eventInit, const Dictionary& options)
2700{
2701END
2702
2703    if ($interface->parent) {
2704        my $interfaceBase = $interface->parent;
2705        $code .= <<END;
2706    if (!fill${interfaceBase}Init(eventInit, options))
2707        return false;
2708
2709END
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
2733END
2734    $implementation{nameSpaceWebCore}->add($code);
2735}
2736
2737sub 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);
2774WrapperTypeInfo ${v8ClassName}Constructor::info = { ${v8ClassName}Constructor::GetTemplate, ${v8ClassName}::derefObject, $toActiveDOMObject, $toEventTarget, 0, ${v8ClassName}::installPerContextPrototypeProperties, 0, WrapperTypeObjectPrototype };
2775
2776END
2777
2778    my $code = "";
2779    $code .= <<END;
2780static void ${v8ClassName}ConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& args)
2781{
2782END
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
2794END
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
2840END
2841    $implementation{nameSpaceWebCore}->add($code);
2842
2843    $code = <<END;
2844v8::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
2866END
2867    $implementation{nameSpaceWebCore}->add($code);
2868}
2869
2870sub 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
2884END
2885    return $content;
2886}
2887
2888sub 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
2905sub 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
3010sub 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
3029sub 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));
3079END
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
3120sub 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
3144sub 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
3169sub 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
3233sub 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
3273sub 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
3293sub 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
3313sub 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
3333sub 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
3380sub 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
3450sub 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
3470sub 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
3490sub 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
3510sub 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
3530sub 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
3550sub 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
3586sub 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
3636sub 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
3692sub 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
3720sub 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
3749sub GenerateImplementationNamedPropertyEnumerator
3750{
3751    my $interface = shift;
3752    my $implClassName = GetImplName($interface);
3753    my $v8ClassName = GetV8ClassName($interface);
3754
3755    $implementation{nameSpaceInternal}->add(<<END);
3756static 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
3770END
3771}
3772
3773sub GenerateImplementationNamedPropertyQuery
3774{
3775    my $interface = shift;
3776    my $implClassName = GetImplName($interface);
3777    my $v8ClassName = GetV8ClassName($interface);
3778
3779    $implementation{nameSpaceInternal}->add(<<END);
3780static 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
3793END
3794}
3795
3796sub 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
3809sub 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
3821sub 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;
3858static 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)
3872END
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
3885namespace WebCore {
3886END
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);
3959v8::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
3968END
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}},
4088END
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},
4124END
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);
4156static 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}
4164END
4165    }
4166
4167    if (!$parentClassTemplate) {
4168        $parentClassTemplate = "v8::Local<v8::FunctionTemplate>()";
4169    }
4170
4171    # Generate the template configuration method
4172    $code =  <<END;
4173static 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;
4178END
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
4185END
4186    }
4187    $code .=  <<END;
4188    defaultSignature = V8DOMConfiguration::configureTemplate(desc, \"${interfaceName}\", $parentClassTemplate, ${v8ClassName}::internalFieldCount,
4189END
4190    # Set up our attributes if we have them
4191    if ($has_attributes) {
4192        $code .= <<END;
4193        ${v8ClassName}Attrs, WTF_ARRAY_LENGTH(${v8ClassName}Attrs),
4194END
4195    } else {
4196        $code .= <<END;
4197        0, 0,
4198END
4199    }
4200
4201    if ($has_callbacks) {
4202        $code .= <<END;
4203        ${v8ClassName}Methods, WTF_ARRAY_LENGTH(${v8ClassName}Methods), isolate, currentWorldType);
4204END
4205    } else {
4206        $code .= <<END;
4207        0, 0, isolate, currentWorldType);
4208END
4209    }
4210
4211    AddToImplIncludes("wtf/UnusedParam.h");
4212    $code .= <<END;
4213    UNUSED_PARAM(defaultSignature); // In some cases, it will not be used.
4214END
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.
4228END
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    }
4247END
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);
4262END
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);
4290END
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);
4304END
4305    }
4306    if ($interfaceName eq "HTMLDocument" or $interfaceName eq "DedicatedWorkerGlobalScope" or $interfaceName eq "SharedWorkerGlobalScope") {
4307        $code .= <<END;
4308    desc->SetHiddenPrototype(true);
4309END
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
4319END
4320    $implementation{nameSpaceWebCore}->add($code);
4321
4322    $implementation{nameSpaceWebCore}->add(<<END);
4323v8::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
4338END
4339    $implementation{nameSpaceWebCore}->add(<<END);
4340bool ${v8ClassName}::HasInstance(v8::Handle<v8::Value> value, v8::Isolate* isolate, WrapperWorldType currentWorldType)
4341{
4342    return V8PerIsolateData::from(isolate)->hasInstance(&info, value, currentWorldType);
4343}
4344
4345END
4346    $implementation{nameSpaceWebCore}->add(<<END);
4347bool ${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
4354END
4355
4356    if (@enabledPerContextAttributes) {
4357        my $code = "";
4358        $code .= <<END;
4359void ${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());
4362END
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);
4380END
4381            $code .= "    }\n";
4382            $code .= "#endif // ${conditionalString}\n" if $conditionalString;
4383        }
4384        $code .= <<END;
4385}
4386
4387END
4388        $implementation{nameSpaceWebCore}->add($code);
4389    }
4390
4391    if (@enabledPerContextFunctions) {
4392        my $code = "";
4393        $code .= <<END;
4394void ${v8ClassName}::installPerContextPrototypeProperties(v8::Handle<v8::Object> proto, v8::Isolate* isolate)
4395{
4396    UNUSED_PARAM(proto);
4397END
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());
4404END
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());
4415END
4416            $code .= "#endif // ${conditionalString}\n" if $conditionalString;
4417        }
4418
4419        $code .= <<END;
4420}
4421
4422END
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);
4431ActiveDOMObject* ${v8ClassName}::toActiveDOMObject(v8::Handle<v8::Object> object)
4432{
4433    return $returnValue;
4434}
4435
4436END
4437    }
4438
4439    if (InheritsInterface($interface, "EventTarget")) {
4440        $implementation{nameSpaceWebCore}->add(<<END);
4441EventTarget* ${v8ClassName}::toEventTarget(v8::Handle<v8::Object> object)
4442{
4443    return toNative(object);
4444}
4445
4446END
4447    }
4448
4449    if ($interfaceName eq "Window") {
4450        $implementation{nameSpaceWebCore}->add(<<END);
4451v8::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
4476END
4477    }
4478
4479    GenerateToV8Converters($interface, $v8ClassName, $nativeType);
4480
4481    $implementation{nameSpaceWebCore}->add(<<END);
4482void ${v8ClassName}::derefObject(void* object)
4483{
4484    fromInternalPointer(object)->deref();
4485}
4486
4487END
4488}
4489
4490sub 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
4504sub 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
4537END
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
4564END
4565    $header{classPrivate}->add(<<END);
4566    ${v8ClassName}(v8::Handle<v8::Object>, ScriptExecutionContext*);
4567
4568    ScopedPersistent<v8::Object> m_callback;
4569    RefPtr<DOMWrapperWorld> m_world;
4570END
4571}
4572
4573sub 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
4592END
4593
4594    $implementation{nameSpaceWebCore}->add(<<END);
4595${v8ClassName}::~${v8ClassName}()
4596{
4597}
4598
4599END
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
4685sub BaseInterfaceName
4686{
4687    my $interface = shift;
4688
4689    while ($interface->parent) {
4690        $interface = ParseInterface($interface->parent);
4691    }
4692
4693    return $interface->name;
4694}
4695
4696sub 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
4727v8::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
4738END
4739
4740    $code .= <<END if ($baseType ne $interfaceName);
4741END
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    }
4753END
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;
4761END
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    }
4769END
4770    }
4771
4772    $code .= <<END;
4773    installPerContextProperties(wrapper, impl.get(), isolate);
4774    V8DOMWrapper::associateObjectWithWrapper<$v8ClassName>(impl, &info, wrapper, isolate, $wrapperConfiguration);
4775    return wrapper;
4776}
4777END
4778    $implementation{nameSpaceWebCore}->add($code);
4779}
4780
4781sub 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);
4789bool 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
4795END
4796    $implementation{nameSpaceInternal}->add(<<END);
4797bool 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
4803END
4804}
4805
4806sub 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
4814sub GetNamespaceForInterface
4815{
4816    my $interface = shift;
4817    return "WTF" if IsTypedArrayType($interface->name);
4818    return "WebCore";
4819}
4820
4821sub 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
4965sub 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
5047sub 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
5057sub 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
5089sub 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
5177sub 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
5219sub 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
5251sub 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
5261sub 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
5273sub 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
5290sub 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
5298sub 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
5328sub 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
5494sub 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
5522sub 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.
5538sub 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
5549sub 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
5562sub GetPassRefPtrType
5563{
5564    my $v8ClassName = shift;
5565
5566    my $angleBracketSpace = $v8ClassName =~ />$/ ? " " : "";
5567    return "PassRefPtr<${v8ClassName}${angleBracketSpace}>";
5568}
5569
5570sub 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
5587sub 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
5610sub 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
5626sub IsConstructorTemplate
5627{
5628    my $interface = shift;
5629    my $template = shift;
5630
5631    return $interface->extendedAttributes->{"ConstructorTemplate"} && $interface->extendedAttributes->{"ConstructorTemplate"} eq $template;
5632}
5633
5634sub IsPrimitiveType
5635{
5636    my $type = shift;
5637
5638    return 1 if $primitiveTypeHash{$type};
5639    return 0;
5640}
5641
5642sub IsCallbackFunctionType
5643{
5644    my $type = shift;
5645
5646    return 1 if $callbackFunctionTypeHash{$type};
5647    return 0;
5648}
5649
5650sub IsEnumType
5651{
5652    my $type = shift;
5653
5654    return 1 if $enumTypeHash{$type};
5655    return 0;
5656}
5657
5658sub ValidEnumValues
5659{
5660    my $type = shift;
5661
5662    return @{$enumTypeHash{$type}};
5663}
5664
5665sub IsSVGTypeNeedingTearOff
5666{
5667    my $type = shift;
5668
5669    return 1 if $svgTypeNeedingTearOff{$type};
5670    return 0;
5671}
5672
5673sub IsSVGTypeWithWritablePropertiesNeedingTearOff
5674{
5675    my $type = shift;
5676
5677    return 1 if $svgTypeWithWritablePropertiesNeedingTearOff{$type};
5678    return 0;
5679}
5680
5681sub IsTypedArrayType
5682{
5683    my $type = shift;
5684    return 1 if $typedArrayHash{$type};
5685    return 0;
5686}
5687
5688sub 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
5704sub GetSVGTypeNeedingTearOff
5705{
5706    my $type = shift;
5707
5708    return $svgTypeNeedingTearOff{$type} if exists $svgTypeNeedingTearOff{$type};
5709    return undef;
5710}
5711
5712sub 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
5733sub IsSVGAnimatedType
5734{
5735    my $type = shift;
5736
5737    return $type =~ /^SVGAnimated/;
5738}
5739
5740sub GetSequenceType
5741{
5742    my $type = shift;
5743
5744    return $1 if $type =~ /^sequence<([\w\d_\s]+)>.*/;
5745    return "";
5746}
5747
5748sub GetArrayType
5749{
5750    my $type = shift;
5751
5752    return $1 if $type =~ /^([\w\d_\s]+)\[\]/;
5753    return "";
5754}
5755
5756sub GetArrayOrSequenceType
5757{
5758    my $type = shift;
5759
5760    return GetArrayType($type) || GetSequenceType($type);
5761}
5762
5763sub 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
5769sub 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.
5782sub 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
5801sub 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).
5810sub 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
5824sub 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
5837sub 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
5852sub 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
5890sub 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
5914sub 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
5926sub 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
5941sub 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
5970sub 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
5980sub 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
5998sub 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
60161;
6017