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