f2f4dad0772a58a37c76b6bd0c3896f1fc2e26a0
[WebKit-https.git] / Source / WebCore / bindings / scripts / CodeGeneratorV8.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 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 #
11 # This library is free software; you can redistribute it and/or
12 # modify it under the terms of the GNU Library General Public
13 # License as published by the Free Software Foundation; either
14 # version 2 of the License, or (at your option) any later version.
15 #
16 # This library is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 # Library General Public License for more details.
20 #
21 # You should have received a copy of the GNU Library General Public License
22 # along with this library; see the file COPYING.LIB.  If not, write to
23 # the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 # Boston, MA 02111-1307, USA.
25 #
26
27 package CodeGeneratorV8;
28
29 use strict;
30
31 use Digest::MD5;
32
33 my ($codeGenerator, $IMPL, $HEADER);
34
35 my $module = "";
36 my $outputDir = "";
37 my $outputHeadersDir = "";
38
39 my @headerContent = ();
40 my @implContentHeader = ();
41 my @implFixedHeader = ();
42 my @implHeaderContent = ();
43 my @implContent = ();
44 my @implContentDecls = ();
45 my %implIncludes = ();
46 my %headerIncludes = ();
47
48 my @allParents = ();
49
50 # Default .h template
51 my $headerTemplate = << "EOF";
52 /*
53     This file is part of the WebKit open source project.
54     This file has been generated by generate-bindings.pl. DO NOT MODIFY!
55
56     This library is free software; you can redistribute it and/or
57     modify it under the terms of the GNU Library General Public
58     License as published by the Free Software Foundation; either
59     version 2 of the License, or (at your option) any later version.
60
61     This library is distributed in the hope that it will be useful,
62     but WITHOUT ANY WARRANTY; without even the implied warranty of
63     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
64     Library General Public License for more details.
65
66     You should have received a copy of the GNU Library General Public License
67     along with this library; see the file COPYING.LIB.  If not, write to
68     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
69     Boston, MA 02111-1307, USA.
70 */
71 EOF
72
73 # Default constructor
74 sub new
75 {
76     my $object = shift;
77     my $reference = { };
78
79     $codeGenerator = shift;
80     $outputDir = shift;
81     $outputHeadersDir = shift;
82
83     bless($reference, $object);
84     return $reference;
85 }
86
87 sub finish
88 {
89     my $object = shift;
90
91     # Commit changes!
92     $object->WriteData();
93 }
94
95 # Params: 'domClass' struct
96 sub GenerateInterface
97 {
98     my $object = shift;
99     my $dataNode = shift;
100     my $defines = shift;
101
102     # Start actual generation
103     if ($dataNode->extendedAttributes->{"Callback"}) {
104         $object->GenerateCallbackHeader($dataNode);
105         $object->GenerateCallbackImplementation($dataNode);
106     } else {
107         $object->GenerateHeader($dataNode);
108         $object->GenerateImplementation($dataNode);
109     }
110
111     my $name = $dataNode->name;
112
113     # Open files for writing
114     my $headerFileName = "$outputHeadersDir/V8$name.h";
115     my $implFileName = "$outputDir/V8$name.cpp";
116
117     open($IMPL, ">$implFileName") || die "Couldn't open file $implFileName";
118     open($HEADER, ">$headerFileName") || die "Couldn't open file $headerFileName";
119 }
120
121 # Params: 'idlDocument' struct
122 sub GenerateModule
123 {
124     my $object = shift;
125     my $dataNode = shift;
126
127     $module = $dataNode->module;
128 }
129
130 sub AddToImplIncludes
131 {
132     my $header = shift;
133     my $conditional = shift;
134
135     if (not $conditional) {
136         $implIncludes{$header} = 1;
137     } elsif (not exists($implIncludes{$header})) {
138         $implIncludes{$header} = $conditional;
139     } else {
140         my $oldValue = $implIncludes{$header};
141         if ($oldValue ne 1) {
142             my %newValue = ();
143             $newValue{$conditional} = 1;
144             foreach my $condition (split(/\|/, $oldValue)) {
145                 $newValue{$condition} = 1;
146             }
147             $implIncludes{$header} = join("|", sort keys %newValue);
148         }
149     }
150 }
151
152 sub AddIncludesForType
153 {
154     my $type = $codeGenerator->StripModule(shift);
155
156     # When we're finished with the one-file-per-class
157     # reorganization, we won't need these special cases.
158     if (!$codeGenerator->IsPrimitiveType($type) and !$codeGenerator->IsStringType($type) and !$codeGenerator->AvoidInclusionOfType($type) and $type ne "Date") {
159         # default, include the same named file
160         AddToImplIncludes(GetV8HeaderName(${type}));
161
162         if ($type =~ /SVGPathSeg/) {
163             my $joinedName = $type;
164             $joinedName =~ s/Abs|Rel//;
165             AddToImplIncludes("${joinedName}.h");
166         }
167     }
168
169     # additional includes (things needed to compile the bindings but not the header)
170
171     if ($type eq "CanvasRenderingContext2D") {
172         AddToImplIncludes("CanvasGradient.h");
173         AddToImplIncludes("CanvasPattern.h");
174         AddToImplIncludes("CanvasStyle.h");
175     }
176
177     if ($type eq "CanvasGradient" or $type eq "XPathNSResolver") {
178         AddToImplIncludes("PlatformString.h");
179     }
180
181     if ($type eq "CSSStyleDeclaration") {
182         AddToImplIncludes("CSSMutableStyleDeclaration.h");
183     }
184
185     if ($type eq "Plugin" or $type eq "PluginArray" or $type eq "MimeTypeArray") {
186         # So we can get String -> AtomicString conversion for namedItem().
187         AddToImplIncludes("wtf/text/AtomicString.h");
188     }
189 }
190
191 # If the node has a [Conditional=XXX] attribute, returns an "ENABLE(XXX)" string for use in an #if.
192 sub GenerateConditionalStringFromAttributeValue
193 {
194     my $conditional = shift;
195     if ($conditional =~ /&/) {
196         return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
197     } elsif ($conditional =~ /\|/) {
198         return "ENABLE(" . join(") || ENABLE(", split(/\|/, $conditional)) . ")";
199     } else {
200         return "ENABLE(" . $conditional . ")";
201     }
202 }
203
204 sub GenerateConditionalString
205 {
206     my $node = shift;
207     my $conditional = $node->extendedAttributes->{"Conditional"};
208     if ($conditional) {
209         return GenerateConditionalStringFromAttributeValue($conditional);
210     } else {
211         return "";
212     }
213 }
214
215 sub GetSVGPropertyTypes
216 {
217     my $implType = shift;
218
219     my $svgPropertyType;
220     my $svgListPropertyType;
221     my $svgNativeType;
222
223     return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $implType =~ /SVG/;
224
225     $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implType);
226     return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $svgNativeType;
227
228     # Append space to avoid compilation errors when using  PassRefPtr<$svgNativeType>
229     $svgNativeType = "$svgNativeType ";
230
231     my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implType);
232     if ($svgNativeType =~ /SVGPropertyTearOff/) {
233         $svgPropertyType = $svgWrappedNativeType;
234         AddToImplIncludes("SVGAnimatedPropertyTearOff.h");
235     } elsif ($svgNativeType =~ /SVGListPropertyTearOff/ or $svgNativeType =~ /SVGStaticListPropertyTearOff/) {
236         $svgListPropertyType = $svgWrappedNativeType;
237         $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;
238         $headerIncludes{"SVGStaticListPropertyTearOff.h"} = 1;
239     } elsif ($svgNativeType =~ /SVGTransformListPropertyTearOff/) {
240         $svgListPropertyType = $svgWrappedNativeType;
241         $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;
242         $headerIncludes{"SVGTransformListPropertyTearOff.h"} = 1;
243     } elsif ($svgNativeType =~ /SVGPathSegListPropertyTearOff/) {
244         $svgListPropertyType = $svgWrappedNativeType;
245         $headerIncludes{"SVGPathSegListPropertyTearOff.h"} = 1;
246     }
247
248     if ($svgPropertyType) {
249         $svgPropertyType = "SVGPoint" if $svgPropertyType eq "FloatPoint";
250     }
251
252     return ($svgPropertyType, $svgListPropertyType, $svgNativeType);
253 }
254
255 sub GenerateHeader
256 {
257     my $object = shift;
258     my $dataNode = shift;
259
260     my $interfaceName = $dataNode->name;
261     my $className = "V8$interfaceName";
262     my $implClassName = $interfaceName;
263
264     # Copy contents of parent classes except the first parent or if it is
265     # EventTarget.
266     $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@allParents, 1);
267
268     my $hasDependentLifetime = $dataNode->extendedAttributes->{"V8DependentLifetime"} || $dataNode->extendedAttributes->{"ActiveDOMObject"} || $className =~ /SVG/;
269     if (!$hasDependentLifetime) {
270         foreach (@{$dataNode->parents}) {
271             my $parent = $codeGenerator->StripModule($_);
272             next if $parent eq "EventTarget";
273             $headerIncludes{"V8${parent}.h"} = 1;
274         }
275     }
276
277     my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
278
279     # - Add default header template
280     push(@headerContent, GenerateHeaderContentHeader($dataNode));
281
282     $headerIncludes{"wtf/text/StringHash.h"} = 1;
283     $headerIncludes{"WrapperTypeInfo.h"} = 1;
284     $headerIncludes{"V8DOMWrapper.h"} = 1;
285
286     my $headerClassInclude = GetHeaderClassInclude($implClassName);
287     $headerIncludes{$headerClassInclude} = 1 if $headerClassInclude ne "";
288
289     my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implClassName);
290
291     foreach my $headerInclude (sort keys(%headerIncludes)) {
292         if ($headerInclude =~ /wtf/) {
293             push(@headerContent, "#include \<${headerInclude}\>\n");
294         } else {
295             push(@headerContent, "#include \"${headerInclude}\"\n");
296         }
297     }
298
299     push(@headerContent, "#include <v8.h>\n");
300     push(@headerContent, "#include <wtf/HashMap.h>\n");
301
302     push(@headerContent, "\nnamespace WebCore {\n");
303     push(@headerContent, "\ntemplate<typename PropertyType> class SVGPropertyTearOff;\n") if $svgPropertyType;
304     if ($svgNativeType) {
305         if ($svgNativeType =~ /SVGStaticListPropertyTearOff/) {
306             push(@headerContent, "\ntemplate<typename PropertyType> class SVGStaticListPropertyTearOff;\n");
307         } else {
308             push(@headerContent, "\ntemplate<typename PropertyType> class SVGListPropertyTearOff;\n");
309         }
310     }
311     push(@headerContent, "\nclass FloatRect;\n") if $svgPropertyType && $svgPropertyType eq "FloatRect";
312     push(@headerContent, "\nclass $className {\n");
313     push(@headerContent, "public:\n");
314
315     push(@headerContent, "    static const bool hasDependentLifetime = ");
316     if ($hasDependentLifetime) {
317         push(@headerContent, "true;\n");
318     } elsif (@{$dataNode->parents}) {
319         # Even if this type doesn't have the V8DependentLifetime attribute its parents may.
320         # Let the compiler statically determine this for us.
321         my $separator = "";
322         foreach (@{$dataNode->parents}) {
323             my $parent = $codeGenerator->StripModule($_);
324             next if $parent eq "EventTarget";
325             $headerIncludes{"V8${parent}.h"} = 1;
326             push(@headerContent, "${separator}V8${parent}::hasDependentLifetime");
327             $separator = " || ";
328         }
329         push(@headerContent, ";\n");
330     } else {
331         push(@headerContent, "false;\n");
332     }
333
334     my $nativeType = GetNativeTypeForConversions($dataNode, $interfaceName);
335     my $domMapFunction = GetDomMapFunction($dataNode, $interfaceName);
336     my $forceNewObjectParameter = IsDOMNodeType($interfaceName) ? ", bool forceNewObject = false" : "";
337     my $forceNewObjectInput = IsDOMNodeType($interfaceName) ? ", bool forceNewObject" : "";
338     my $forceNewObjectCall = IsDOMNodeType($interfaceName) ? ", forceNewObject" : "";
339
340     push(@headerContent, <<END);
341     static bool HasInstance(v8::Handle<v8::Value> value);
342     static v8::Persistent<v8::FunctionTemplate> GetRawTemplate();
343     static v8::Persistent<v8::FunctionTemplate> GetTemplate();
344     static ${nativeType}* toNative(v8::Handle<v8::Object> object)
345     {
346         return reinterpret_cast<${nativeType}*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex));
347     }
348     inline static v8::Handle<v8::Object> wrap(${nativeType}*${forceNewObjectParameter});
349     static void derefObject(void*);
350     static WrapperTypeInfo info;
351 END
352     if ($dataNode->extendedAttributes->{"ActiveDOMObject"}) {
353         push(@headerContent, "    static ActiveDOMObject* toActiveDOMObject(v8::Handle<v8::Object>);\n");
354     }
355
356     if ($implClassName eq "DOMWindow") {
357         push(@headerContent, <<END);
358     static v8::Persistent<v8::ObjectTemplate> GetShadowObjectTemplate();
359 END
360     }
361
362     if ($implClassName eq "HTMLDocument") {
363       push(@headerContent, <<END);
364   static v8::Local<v8::Object> WrapInShadowObject(v8::Local<v8::Object> wrapper, Node* impl);
365   static v8::Handle<v8::Value> GetNamedProperty(HTMLDocument* htmlDocument, const AtomicString& key);
366 END
367     }
368
369     my @enabledAtRuntime;
370     foreach my $function (@{$dataNode->functions}) {
371         my $name = $function->signature->name;
372         my $attrExt = $function->signature->extendedAttributes;
373
374         if ($attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
375             push(@headerContent, <<END);
376     static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments&);
377 END
378         }
379
380         if ($attrExt->{"EnabledAtRuntime"}) {
381             push(@enabledAtRuntime, $function);
382         }
383     }
384
385     if ($dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"V8CustomConstructor"} || $dataNode->extendedAttributes->{"CanBeConstructed"} || $dataNode->extendedAttributes->{"Constructor"}) {
386         push(@headerContent, <<END);
387     static v8::Handle<v8::Value> constructorCallback(const v8::Arguments& args);
388 END
389     }
390
391     foreach my $attribute (@{$dataNode->attributes}) {
392         my $name = $attribute->signature->name;
393         my $attrExt = $attribute->signature->extendedAttributes;
394         if ($attrExt->{"V8CustomGetter"} || $attrExt->{"CustomGetter"}
395             || $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) {
396             push(@headerContent, <<END);
397     static v8::Handle<v8::Value> ${name}AccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);
398 END
399         }
400         if ($attrExt->{"V8CustomSetter"} || $attrExt->{"CustomSetter"}
401             || $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) {
402             push(@headerContent, <<END);
403     static void ${name}AccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info);
404 END
405         }
406         if ($attrExt->{"EnabledAtRuntime"}) {
407             push(@enabledAtRuntime, $attribute);
408         }
409     }
410
411     GenerateHeaderNamedAndIndexedPropertyAccessors($dataNode);
412     GenerateHeaderCustomCall($dataNode);
413     GenerateHeaderCustomInternalFieldIndices($dataNode);
414
415     if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) {
416         push(@headerContent, <<END);
417     static bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType, v8::Local<v8::Value> data);
418     static bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType, v8::Local<v8::Value> data);
419 END
420     }
421
422     push(@headerContent, <<END);
423     static v8::Handle<v8::Object> existingWrapper(${nativeType}*);
424
425 private:
426     static v8::Handle<v8::Object> wrapSlow(${nativeType}*);
427 };
428
429 END
430
431     push(@headerContent, <<END);
432 ALWAYS_INLINE v8::Handle<v8::Object> ${className}::existingWrapper(${nativeType}* impl)
433 {
434 END
435     my $getWrapper = IsNodeSubType($dataNode) ? "V8DOMWrapper::getWrapper(impl)" : "${domMapFunction}.get(impl)";
436     push(@headerContent, <<END);
437     return ${getWrapper};
438 }
439
440 v8::Handle<v8::Object> ${className}::wrap(${nativeType}* impl${forceNewObjectInput})
441 {
442 END
443     push(@headerContent, "    if (!forceNewObject) {\n") if IsDOMNodeType($interfaceName);
444     push(@headerContent, <<END);
445         v8::Handle<v8::Object> wrapper = existingWrapper(impl);
446         if (!wrapper.IsEmpty())
447             return wrapper;
448 END
449     push(@headerContent, "    }\n") if IsDOMNodeType($interfaceName);
450     push(@headerContent, <<END);
451     return ${className}::wrapSlow(impl);
452 }
453 END
454
455     if (!HasCustomToV8Implementation($dataNode, $interfaceName)) {
456         push(@headerContent, <<END);
457
458 inline v8::Handle<v8::Value> toV8(${nativeType}* impl${forceNewObjectParameter})
459 {
460     if (!impl)
461         return v8::Null();
462     return ${className}::wrap(impl${forceNewObjectCall});
463 }
464 END
465     } elsif ($interfaceName ne 'Node') {
466         push(@headerContent, <<END);
467
468 v8::Handle<v8::Value> toV8(${nativeType}*${forceNewObjectParameter});
469 END
470     } else {
471         push(@headerContent, <<END);
472
473 v8::Handle<v8::Value> toV8Slow(Node*, bool);
474
475 inline v8::Handle<v8::Value> toV8(Node* impl, bool forceNewObject = false)
476 {
477     if (!impl)
478         return v8::Null();
479     if (!forceNewObject) {
480         v8::Handle<v8::Value> wrapper = V8DOMWrapper::getWrapper(impl);
481         if (!wrapper.IsEmpty())
482             return wrapper;
483     }
484     return toV8Slow(impl, forceNewObject);
485 }
486 END
487     }
488
489     if (IsRefPtrType($implClassName)) {
490         push(@headerContent, <<END);
491 inline v8::Handle<v8::Value> toV8(PassRefPtr< ${nativeType} > impl${forceNewObjectParameter})
492 {
493     return toV8(impl.get()${forceNewObjectCall});
494 }
495 END
496     }
497
498     push(@headerContent, "}\n\n");
499     push(@headerContent, "#endif // $className" . "_h\n");
500
501     my $conditionalString = GenerateConditionalString($dataNode);
502     push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;
503 }
504
505 sub GetInternalFields
506 {
507     my $dataNode = shift;
508     my $name = $dataNode->name;
509     
510     my @customInternalFields = ();
511  
512     # We can't ask whether a parent type has a given extendedAttribute, so special-case AbstractWorker and WorkerContext to include all sub-types.
513     # Event listeners on DOM nodes are explicitly supported in the GC controller.
514     # FIXME: SVGElementInstance should probably have the EventTarget extended attribute, but doesn't.
515     if (!IsNodeSubType($dataNode) &&
516         ($dataNode->extendedAttributes->{"EventTarget"} ||
517          IsSubType($dataNode, "AbstractWorker") ||
518          IsSubType($dataNode, "WorkerContext") ||
519          $name eq "SVGElementInstance")) {
520         push(@customInternalFields, "eventListenerCacheIndex");
521     }
522
523     if ($name eq "DOMWindow") {
524         push(@customInternalFields, "enteredIsolatedWorldIndex");
525     }
526     return @customInternalFields;
527 }
528
529 sub GetHeaderClassInclude
530 {
531     my $className = shift;
532     if ($className =~ /SVGPathSeg/) {
533         $className =~ s/Abs|Rel//;
534     }
535     return "" if ($codeGenerator->AvoidInclusionOfType($className));
536     return "${className}.h";
537 }
538
539 sub GenerateHeaderCustomInternalFieldIndices
540 {
541     my $dataNode = shift;
542     my @customInternalFields = GetInternalFields($dataNode);
543     my $customFieldCounter = 0;
544     foreach my $customInternalField (@customInternalFields) {
545         push(@headerContent, <<END);
546     static const int ${customInternalField} = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
547 END
548         $customFieldCounter++;
549     }
550     push(@headerContent, <<END);
551     static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
552 END
553 }
554
555 my %indexerSpecialCases = (
556     "Storage" => 1,
557     "HTMLAppletElement" => 1,
558     "HTMLEmbedElement" => 1,
559     "HTMLObjectElement" => 1
560 );
561
562 sub GenerateHeaderNamedAndIndexedPropertyAccessors
563 {
564     my $dataNode = shift;
565     my $interfaceName = $dataNode->name;
566     my $hasCustomIndexedGetter = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
567     my $hasCustomIndexedSetter = $dataNode->extendedAttributes->{"HasCustomIndexSetter"} && !$dataNode->extendedAttributes->{"HasNumericIndexGetter"};
568     my $hasCustomNamedGetter = $dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
569     my $hasCustomNamedSetter = $dataNode->extendedAttributes->{"DelegatingPutFunction"};
570     my $hasCustomDeleters = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
571     my $hasCustomEnumerator = $dataNode->extendedAttributes->{"CustomGetPropertyNames"};
572     if ($interfaceName eq "HTMLOptionsCollection") {
573         $interfaceName = "HTMLCollection";
574         $hasCustomIndexedGetter = 1;
575         $hasCustomNamedGetter = 1;
576     }
577     if ($interfaceName eq "DOMWindow") {
578         $hasCustomDeleters = 0;
579         $hasCustomEnumerator = 0;
580     }
581     if ($interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") {
582         $hasCustomNamedGetter = 1;
583     }
584     if ($interfaceName eq "HTMLDocument") {
585         $hasCustomNamedGetter = 0;
586         $hasCustomIndexedGetter = 0;
587     }
588     my $isIndexerSpecialCase = exists $indexerSpecialCases{$interfaceName};
589
590     if ($hasCustomIndexedGetter || $isIndexerSpecialCase) {
591         push(@headerContent, <<END);
592     static v8::Handle<v8::Value> indexedPropertyGetter(uint32_t, const v8::AccessorInfo&);
593 END
594     }
595
596     if ($isIndexerSpecialCase || $hasCustomIndexedSetter) {
597         push(@headerContent, <<END);
598     static v8::Handle<v8::Value> indexedPropertySetter(uint32_t, v8::Local<v8::Value>, const v8::AccessorInfo&);
599 END
600     }
601     if ($hasCustomDeleters) {
602         push(@headerContent, <<END);
603     static v8::Handle<v8::Boolean> indexedPropertyDeleter(uint32_t, const v8::AccessorInfo&);
604 END
605     }
606     if ($hasCustomNamedGetter) {
607         push(@headerContent, <<END);
608     static v8::Handle<v8::Value> namedPropertyGetter(v8::Local<v8::String>, const v8::AccessorInfo&);
609 END
610     }
611     if ($hasCustomNamedSetter) {
612         push(@headerContent, <<END);
613     static v8::Handle<v8::Value> namedPropertySetter(v8::Local<v8::String>, v8::Local<v8::Value>, const v8::AccessorInfo&);
614 END
615     }
616     if ($hasCustomDeleters) {
617         push(@headerContent, <<END);
618     static v8::Handle<v8::Boolean> namedPropertyDeleter(v8::Local<v8::String>, const v8::AccessorInfo&);
619 END
620     }
621     if ($hasCustomEnumerator) {
622         push(@headerContent, <<END);
623     static v8::Handle<v8::Array> namedPropertyEnumerator(const v8::AccessorInfo&);
624     static v8::Handle<v8::Integer> namedPropertyQuery(v8::Local<v8::String>, const v8::AccessorInfo&);
625 END
626     }
627 }
628
629 sub GenerateHeaderCustomCall
630 {
631     my $dataNode = shift;
632
633     if ($dataNode->extendedAttributes->{"CustomCall"} || $dataNode->extendedAttributes->{"V8CustomCall"}) {
634         push(@headerContent, "    static v8::Handle<v8::Value> callAsFunctionCallback(const v8::Arguments&);\n");
635     }
636     if ($dataNode->name eq "Event") {
637         push(@headerContent, "    static v8::Handle<v8::Value> dataTransferAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
638         push(@headerContent, "    static void valueAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info);\n");
639     }
640     if ($dataNode->name eq "Location") {
641         push(@headerContent, "    static v8::Handle<v8::Value> assignAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
642         push(@headerContent, "    static v8::Handle<v8::Value> reloadAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
643         push(@headerContent, "    static v8::Handle<v8::Value> replaceAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
644     }
645 }
646
647 sub GenerateSetDOMException
648 {
649     my $indent = shift;
650     my $result = "";
651
652     $result .= $indent . "if (UNLIKELY(ec)) {\n";
653     $result .= $indent . "    V8Proxy::setDOMException(ec);\n";
654     $result .= $indent . "    return v8::Handle<v8::Value>();\n";
655     $result .= $indent . "}\n";
656
657     return $result;
658 }
659
660 sub IsSubType
661 {
662     my $dataNode = shift;
663     my $parentType = shift;
664     return 1 if ($dataNode->name eq $parentType);
665     foreach (@allParents) {
666         my $parent = $codeGenerator->StripModule($_);
667         return 1 if $parent eq $parentType;
668     }
669     return 0;
670 }
671
672 sub IsNodeSubType
673 {
674     my $dataNode = shift;
675     return IsSubType($dataNode, "Node");
676 }
677
678 sub IsVisibleAcrossOrigins
679 {
680     my $dataNode = shift;
681     return $dataNode->extendedAttributes->{"CheckDomainSecurity"} && !($dataNode->name eq "DOMWindow");
682 }
683
684 sub GenerateDomainSafeFunctionGetter
685 {
686     my $function = shift;
687     my $implClassName = shift;
688
689     my $className = "V8" . $implClassName;
690     my $funcName = $function->signature->name;
691
692     my $signature = "v8::Signature::New(" . $className . "::GetRawTemplate())";
693     if ($function->signature->extendedAttributes->{"V8DoNotCheckSignature"}) {
694         $signature = "v8::Local<v8::Signature>()";
695     }
696
697     my $newTemplateString = GenerateNewFunctionTemplate($function, $implClassName, $signature);
698
699     push(@implContentDecls, <<END);
700 static v8::Handle<v8::Value> ${funcName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
701 {
702     INC_STATS(\"DOM.$implClassName.$funcName._get\");
703     static v8::Persistent<v8::FunctionTemplate> privateTemplate = v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
704     v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(${className}::GetTemplate(), info.This());
705     if (holder.IsEmpty()) {
706         // can only reach here by 'object.__proto__.func', and it should passed
707         // domain security check already
708         return privateTemplate->GetFunction();
709     }
710     ${implClassName}* imp = ${className}::toNative(holder);
711     if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false)) {
712         static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
713         return sharedTemplate->GetFunction();
714     }
715     return privateTemplate->GetFunction();
716 }
717
718 END
719 }
720
721 sub GenerateConstructorGetter
722 {
723     my $implClassName = shift;
724
725     push(@implContentDecls, <<END);
726 static v8::Handle<v8::Value> ${implClassName}ConstructorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
727 {
728     INC_STATS(\"DOM.$implClassName.constructors._get\");
729     v8::Handle<v8::Value> data = info.Data();
730     ASSERT(data->IsExternal() || data->IsNumber());
731     WrapperTypeInfo* type = WrapperTypeInfo::unwrap(data);
732 END
733
734     if ($implClassName eq "DOMWindow") {
735         push(@implContentDecls, <<END);
736     // Get the proxy corresponding to the DOMWindow if possible to
737     // make sure that the constructor function is constructed in the
738     // context of the DOMWindow and not in the context of the caller.
739     return V8DOMWrapper::getConstructor(type, V8DOMWindow::toNative(info.Holder()));
740 END
741     } elsif ($implClassName eq "DedicatedWorkerContext" or $implClassName eq "WorkerContext" or $implClassName eq "SharedWorkerContext") {
742         push(@implContentDecls, <<END);
743     return V8DOMWrapper::getConstructor(type, V8WorkerContext::toNative(info.Holder()));
744 END
745     } else {
746         push(@implContentDecls, "    return v8::Handle<v8::Value>();");
747     }
748
749     push(@implContentDecls, <<END);
750 }
751
752 END
753 }
754
755 sub GenerateNormalAttrGetter
756 {
757     my $attribute = shift;
758     my $dataNode = shift;
759     my $implClassName = shift;
760     my $interfaceName = shift;
761
762     my $attrExt = $attribute->signature->extendedAttributes;
763     my $attrName = $attribute->signature->name;
764     my $attrType = GetTypeFromSignature($attribute->signature);
765     my $nativeType = GetNativeTypeFromSignature($attribute->signature, -1);
766
767     my $getterStringUsesImp = $implClassName ne "SVGNumber";
768     my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implClassName);
769
770     # Getter
771     my $conditionalString = GenerateConditionalString($attribute->signature);
772     push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
773
774     push(@implContentDecls, <<END);
775 static v8::Handle<v8::Value> ${attrName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
776 {
777     INC_STATS(\"DOM.$implClassName.$attrName._get\");
778 END
779
780     if ($svgNativeType) {
781         my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implClassName);
782         if ($svgWrappedNativeType =~ /List/) {
783             push(@implContentDecls, <<END);
784     $svgNativeType* imp = V8${implClassName}::toNative(info.Holder());
785 END
786         } else {
787             push(@implContentDecls, <<END);
788     $svgNativeType* wrapper = V8${implClassName}::toNative(info.Holder());
789     $svgWrappedNativeType& impInstance = wrapper->propertyReference();
790 END
791             if ($getterStringUsesImp) {
792                 push(@implContentDecls, <<END);
793     $svgWrappedNativeType* imp = &impInstance;
794 END
795             }
796         }
797     } elsif ($attrExt->{"v8OnProto"} || $attrExt->{"V8DisallowShadowing"}) {
798         if ($interfaceName eq "DOMWindow") {
799             push(@implContentDecls, <<END);
800     v8::Handle<v8::Object> holder = info.Holder();
801 END
802         } else {
803             # perform lookup first
804             push(@implContentDecls, <<END);
805     v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8${interfaceName}::GetTemplate(), info.This());
806     if (holder.IsEmpty())
807         return v8::Handle<v8::Value>();
808 END
809         }
810         push(@implContentDecls, <<END);
811     ${implClassName}* imp = V8${implClassName}::toNative(holder);
812 END
813     } else {
814         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
815         my $url = $attribute->signature->extendedAttributes->{"URL"};
816         if ($getterStringUsesImp && $reflect && !$url && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
817             # Generate super-compact call for regular attribute getter:
818             my $contentAttributeName = $reflect eq "1" ? lc $attrName : $reflect;
819             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
820             AddToImplIncludes("${namespace}.h");
821             push(@implContentDecls, "    return getElementStringAttr(info, ${namespace}::${contentAttributeName}Attr);\n");
822             push(@implContentDecls, "}\n\n");
823             push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
824             return;
825             # Skip the rest of the function!
826         }
827         push(@implContentDecls, <<END);
828     ${implClassName}* imp = V8${implClassName}::toNative(info.Holder());
829 END
830     }
831
832     # Generate security checks if necessary
833     if ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) {
834         push(@implContentDecls, "    if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->$attrName()))\n    return v8::Handle<v8::Value>();\n\n");
835     } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) {
836         push(@implContentDecls, "    if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->contentDocument()))\n    return v8::Handle<v8::Value>();\n\n");
837     }
838
839     my $useExceptions = 1 if @{$attribute->getterExceptions};
840     if ($useExceptions) {
841         AddToImplIncludes("ExceptionCode.h");
842         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
843     }
844
845     if ($attribute->signature->extendedAttributes->{"v8referenceattr"}) {
846         $attrName = $attribute->signature->extendedAttributes->{"v8referenceattr"};
847     }
848
849     my $returnType = GetTypeFromSignature($attribute->signature);
850
851     my $getterString;
852     if ($getterStringUsesImp) {
853         $getterString = "imp->" . $codeGenerator->GetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute);
854         $getterString .= "ec" if $useExceptions;
855         $getterString .= ")";
856     } else {
857         $getterString = "impInstance";
858     }
859
860     my $result;
861     my $wrapper;
862
863         if ($attribute->signature->type eq "EventListener" && $dataNode->name eq "DOMWindow") {
864         push(@implContentDecls, "    if (!imp->document())\n");
865         push(@implContentDecls, "        return v8::Handle<v8::Value>();\n");
866     }
867
868     if ($useExceptions) {
869         if ($nativeType =~ /^V8Parameter/) {
870           push(@implContentDecls, "    " . ConvertToV8Parameter($attribute->signature, $nativeType, "v", $getterString) . ";\n");
871         } else {
872           push(@implContentDecls, "    $nativeType v = $getterString;\n");
873         }
874         push(@implContentDecls, GenerateSetDOMException("    "));
875         $result = "v";
876         $result .= ".release()" if (IsRefPtrType($returnType));
877     } else {
878         # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
879         $result = $getterString;
880         # Fix amigious conversion problem, by casting to the base type first ($getterString returns a type that inherits from SVGAnimatedEnumeration, not the base class directly).
881         $result = "static_pointer_cast<SVGAnimatedEnumeration>($result)" if $returnType eq "SVGAnimatedEnumeration";
882     }
883  
884     # Special case for readonly or Replaceable attributes (with a few exceptions). This attempts to ensure that JS wrappers don't get
885     # garbage-collected prematurely when their lifetime is strongly tied to their owner. We accomplish this by inserting a reference to
886     # the newly created wrapper into an internal field of the holder object.
887     if (!IsNodeSubType($dataNode) && $attrName ne "self" && (IsWrapperType($returnType) && ($attribute->type =~ /^readonly/ || $attribute->signature->extendedAttributes->{"Replaceable"})
888         && $returnType ne "EventTarget" && $returnType ne "SerializedScriptValue" && $returnType ne "DOMWindow" 
889         && $returnType !~ /SVG/ && $returnType !~ /HTML/ && !IsDOMNodeType($returnType))) {
890         AddIncludesForType($returnType);
891         # Check for a wrapper in the wrapper cache. If there is one, we know that a hidden reference has already
892         # been created. If we don't find a wrapper, we create both a wrapper and a hidden reference.
893         push(@implContentDecls, "    RefPtr<$returnType> result = ${getterString};\n");
894         push(@implContentDecls, "    v8::Handle<v8::Value> wrapper = result.get() ? V8${returnType}::existingWrapper(result.get()) : v8::Handle<v8::Object>();\n");
895         push(@implContentDecls, "    if (wrapper.IsEmpty()) {\n");
896         push(@implContentDecls, "        wrapper = toV8(result.get());\n");
897         push(@implContentDecls, "        if (!wrapper.IsEmpty())\n");
898         if ($dataNode->name eq "DOMWindow") {
899             push(@implContentDecls, "            V8DOMWrapper::setNamedHiddenWindowReference(imp->frame(), \"${attrName}\", wrapper);\n");
900         } else {
901             push(@implContentDecls, "            V8DOMWrapper::setNamedHiddenReference(info.Holder(), \"${attrName}\", wrapper);\n");
902         }
903         push(@implContentDecls, "    }\n");
904         push(@implContentDecls, "    return wrapper;\n");
905         push(@implContentDecls, "}\n\n");
906         push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
907         return;
908     }
909
910     if ($codeGenerator->IsSVGAnimatedType($implClassName) and $codeGenerator->IsSVGTypeNeedingTearOff($attrType)) {
911         AddToImplIncludes("V8$attrType.h");
912         my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($attrType);
913         # Convert from abstract SVGProperty to real type, so the right toJS() method can be invoked.
914         push(@implContentDecls, "    return toV8(static_cast<$svgNativeType*>($result));\n");
915     } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($attrType) and not $implClassName =~ /List$/) {
916         AddToImplIncludes("V8$attrType.h");
917         AddToImplIncludes("SVGPropertyTearOff.h");
918         my $tearOffType = $codeGenerator->GetSVGTypeNeedingTearOff($attrType);
919         if ($codeGenerator->IsSVGTypeWithWritablePropertiesNeedingTearOff($attrType) and not defined $attribute->signature->extendedAttributes->{"Immutable"}) {
920             my $getter = $result;
921             $getter =~ s/imp->//;
922             $getter =~ s/\(\)//;
923
924             my $updateMethod = "&${implClassName}::update" . $codeGenerator->WK_ucfirst($getter);
925
926             my $selfIsTearOffType = $codeGenerator->IsSVGTypeNeedingTearOff($implClassName);
927             if ($selfIsTearOffType) {
928                 AddToImplIncludes("SVGStaticPropertyWithParentTearOff.h");
929                 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyWithParentTearOff<$implClassName, /;
930
931                 if ($result =~ /matrix/ and $implClassName eq "SVGTransform") {
932                     # SVGTransform offers a matrix() method for internal usage that returns an AffineTransform
933                     # and a svgMatrix() method returning a SVGMatrix, used for the bindings.
934                     $result =~ s/matrix/svgMatrix/;
935                 }
936
937                 push(@implContentDecls, "    return toV8(WTF::getPtr(${tearOffType}::create(wrapper, $result, $updateMethod)));\n");
938             } else {
939                 AddToImplIncludes("SVGStaticPropertyTearOff.h");
940                 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyTearOff<$implClassName, /;
941
942                 push(@implContentDecls, "    return toV8(WTF::getPtr(${tearOffType}::create(imp, $result, $updateMethod)));\n");
943             }
944         } elsif ($tearOffType =~ /SVGStaticListPropertyTearOff/) {
945             push(@implContentDecls, "    return toV8(WTF::getPtr(${tearOffType}::create(imp, $result)));\n");
946         } elsif ($tearOffType =~ /SVG(Point|PathSeg)List/) {
947             push(@implContentDecls, "    return toV8(WTF::getPtr($result));\n");
948         } else {
949             push(@implContentDecls, "    return toV8(WTF::getPtr(${tearOffType}::create($result)));\n");
950         }
951     } else {
952         push(@implContentDecls, "    " . ReturnNativeToJSValue($attribute->signature, $result, "    ").";\n");
953     }
954
955     push(@implContentDecls, "}\n\n");  # end of getter
956     push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
957 }
958
959 sub GenerateNormalAttrSetter
960 {
961     my $attribute = shift;
962     my $dataNode = shift;
963     my $implClassName = shift;
964     my $interfaceName = shift;
965
966     AddToImplIncludes("V8BindingMacros.h");
967
968     my $attrName = $attribute->signature->name;
969     my $attrExt = $attribute->signature->extendedAttributes;
970
971     my $conditionalString = GenerateConditionalString($attribute->signature);
972     push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
973
974     push(@implContentDecls, "static void ${attrName}AttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)\n{\n");
975     push(@implContentDecls, "    INC_STATS(\"DOM.$implClassName.$attrName._set\");\n");
976
977     # If the "StrictTypeChecking" extended attribute is present, and the attribute's type is an
978     # interface type, then if the incoming value does not implement that interface, a TypeError is
979     # thrown rather than silently passing NULL to the C++ code.
980     # Per the Web IDL and ECMAScript specifications, incoming values can always be converted to both
981     # strings and numbers, so do not throw TypeError if the attribute is of these types.
982     if ($attribute->signature->extendedAttributes->{"StrictTypeChecking"}) {
983         my $argType = GetTypeFromSignature($attribute->signature);
984         if (IsWrapperType($argType)) {
985             push(@implContentDecls, "    if (!isUndefinedOrNull(value) && !V8${argType}::HasInstance(value)) {\n");
986             push(@implContentDecls, "        V8Proxy::throwTypeError();\n");
987             push(@implContentDecls, "        return;\n");
988             push(@implContentDecls, "    }\n");
989         }
990     }
991
992     my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implClassName);
993     if ($svgNativeType) {
994         my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implClassName);
995         if ($svgWrappedNativeType =~ /List$/) {
996             push(@implContentDecls, <<END);
997     $svgNativeType* imp = V8${implClassName}::toNative(info.Holder());
998 END
999         } else {
1000             push(@implContentDecls, "    $svgNativeType* wrapper = V8${implClassName}::toNative(info.Holder());\n");
1001             push(@implContentDecls, "    if (wrapper->role() == AnimValRole) {\n");
1002             push(@implContentDecls, "        V8Proxy::setDOMException(NO_MODIFICATION_ALLOWED_ERR);\n");
1003             push(@implContentDecls, "        return;\n");
1004             push(@implContentDecls, "    }\n");
1005             push(@implContentDecls, "    $svgWrappedNativeType& impInstance = wrapper->propertyReference();\n");
1006             push(@implContentDecls, "    $svgWrappedNativeType* imp = &impInstance;\n");
1007         }
1008     } elsif ($attrExt->{"v8OnProto"}) {
1009       if ($interfaceName eq "DOMWindow") {
1010         push(@implContentDecls, <<END);
1011     v8::Handle<v8::Object> holder = info.Holder();
1012 END
1013       } else {
1014         # perform lookup first
1015         push(@implContentDecls, <<END);
1016     v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8${interfaceName}::GetTemplate(), info.This());
1017     if (holder.IsEmpty())
1018         return;
1019 END
1020       }
1021     push(@implContentDecls, <<END);
1022     ${implClassName}* imp = V8${implClassName}::toNative(holder);
1023 END
1024     } else {
1025         my $attrType = GetTypeFromSignature($attribute->signature);
1026         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
1027         if ($reflect && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
1028             # Generate super-compact call for regular attribute setter:
1029             my $contentAttributeName = $reflect eq "1" ? lc $attrName : $reflect;
1030             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
1031             AddToImplIncludes("${namespace}.h");
1032             push(@implContentDecls, "    setElementStringAttr(info, ${namespace}::${contentAttributeName}Attr, value);\n");
1033             push(@implContentDecls, "}\n\n");
1034             push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1035             return;
1036             # Skip the rest of the function!
1037         }
1038
1039         push(@implContentDecls, <<END);
1040     ${implClassName}* imp = V8${implClassName}::toNative(info.Holder());
1041 END
1042     }
1043
1044     my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0);
1045     if ($attribute->signature->type eq "EventListener") {
1046         if ($dataNode->name eq "DOMWindow") {
1047             push(@implContentDecls, "    if (!imp->document())\n");
1048             push(@implContentDecls, "        return;\n");
1049         }
1050     } else {
1051         my $value = JSValueToNative($attribute->signature, "value");
1052         if ($nativeType =~ /^V8Parameter/) {
1053           push(@implContentDecls, "    " . ConvertToV8Parameter($attribute->signature, $nativeType, "v", $value, "VOID") . "\n");
1054         } else {
1055           push(@implContentDecls, "    $nativeType v = $value;\n");
1056         }
1057     }
1058
1059     my $result = "v";
1060     my $returnType = GetTypeFromSignature($attribute->signature);
1061     if (IsRefPtrType($returnType)) {
1062         $result = "WTF::getPtr(" . $result . ")";
1063     }
1064
1065     my $useExceptions = 1 if @{$attribute->setterExceptions};
1066
1067     if ($useExceptions) {
1068         AddToImplIncludes("ExceptionCode.h");
1069         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
1070     }
1071
1072     if ($implClassName eq "SVGNumber") {
1073         push(@implContentDecls, "    *imp = $result;\n");
1074     } else {
1075         if ($attribute->signature->type eq "EventListener") {
1076             my $implSetterFunctionName = $codeGenerator->WK_ucfirst($attrName);
1077             AddToImplIncludes("V8AbstractEventListener.h");
1078             if (!IsNodeSubType($dataNode)) {
1079                 push(@implContentDecls, "    transferHiddenDependency(info.Holder(), imp->$attrName(), value, V8${interfaceName}::eventListenerCacheIndex);\n");
1080             }
1081             if ($interfaceName eq "WorkerContext" and $attribute->signature->name eq "onerror") {
1082                 AddToImplIncludes("V8EventListenerList.h");
1083                 AddToImplIncludes("V8WorkerContextErrorHandler.h");
1084                 push(@implContentDecls, "    imp->set$implSetterFunctionName(V8EventListenerList::findOrCreateWrapper<V8WorkerContextErrorHandler>(value, true)");
1085             } elsif ($interfaceName eq "DOMWindow" and $attribute->signature->name eq "onerror") {
1086                 AddToImplIncludes("V8EventListenerList.h");
1087                 AddToImplIncludes("V8WindowErrorHandler.h");
1088                 push(@implContentDecls, "    imp->set$implSetterFunctionName(V8EventListenerList::findOrCreateWrapper<V8WindowErrorHandler>(value, true)");
1089             } else {
1090                 push(@implContentDecls, "    imp->set$implSetterFunctionName(V8DOMWrapper::getEventListener(value, true, ListenerFindOrCreate)");
1091             }
1092         } else {
1093             my $setterExpressionPrefix = $codeGenerator->SetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute);
1094             push(@implContentDecls, "    imp->$setterExpressionPrefix$result");
1095         }
1096         push(@implContentDecls, ", ec") if $useExceptions;
1097         push(@implContentDecls, ");\n");
1098     }
1099
1100     if ($useExceptions) {
1101         push(@implContentDecls, "    if (UNLIKELY(ec))\n");
1102         push(@implContentDecls, "        V8Proxy::setDOMException(ec);\n");
1103     }
1104
1105     if ($svgNativeType) {
1106         if ($useExceptions) {
1107             push(@implContentDecls, "    if (!ec)\n");
1108             push(@implContentDecls, "        wrapper->commitChange();\n");
1109         } else {
1110             push(@implContentDecls, "    wrapper->commitChange();\n");
1111         }
1112     }
1113
1114     push(@implContentDecls, "    return;\n");
1115     push(@implContentDecls, "}\n\n");  # end of setter
1116     push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1117 }
1118
1119 sub GetFunctionTemplateCallbackName
1120 {
1121     my $function = shift;
1122     my $interfaceName = shift;
1123
1124     my $name = $function->signature->name;
1125
1126     if ($function->signature->extendedAttributes->{"Custom"} ||
1127         $function->signature->extendedAttributes->{"V8Custom"}) {
1128         if ($function->signature->extendedAttributes->{"Custom"} &&
1129             $function->signature->extendedAttributes->{"V8Custom"}) {
1130             die "Custom and V8Custom should be mutually exclusive!"
1131         }
1132         return "V8${interfaceName}::${name}Callback";
1133     } else {
1134         return "${interfaceName}Internal::${name}Callback";
1135     }
1136 }
1137
1138 sub GenerateNewFunctionTemplate
1139 {
1140     my $function = shift;
1141     my $interfaceName = shift;
1142     my $signature = shift;
1143
1144     my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
1145     return "v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), $signature)";
1146 }
1147
1148 sub GenerateEventListenerCallback
1149 {
1150     my $implClassName = shift;
1151     my $requiresHiddenDependency = shift;
1152     my $functionName = shift;
1153     my $lookupType = ($functionName eq "add") ? "OrCreate" : "Only";
1154     my $passRefPtrHandling = ($functionName eq "add") ? "" : ".get()";
1155     my $hiddenDependencyAction = ($functionName eq "add") ? "create" : "remove";
1156  
1157     push(@implContentDecls, <<END);
1158 static v8::Handle<v8::Value> ${functionName}EventListenerCallback(const v8::Arguments& args)
1159 {
1160     INC_STATS("DOM.${implClassName}.${functionName}EventListener()");
1161     RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(args[1], false, ListenerFind${lookupType});
1162     if (listener) {
1163         V8${implClassName}::toNative(args.Holder())->${functionName}EventListener(v8ValueToAtomicWebCoreString(args[0]), listener${passRefPtrHandling}, args[2]->BooleanValue());
1164 END
1165     if ($requiresHiddenDependency) {
1166         push(@implContentDecls, <<END);
1167         ${hiddenDependencyAction}HiddenDependency(args.Holder(), args[1], V8${implClassName}::eventListenerCacheIndex);
1168 END
1169     }
1170     push(@implContentDecls, <<END);
1171     }
1172     return v8::Undefined();
1173 }
1174
1175 END
1176 }
1177
1178 sub GenerateParametersCheckExpression
1179 {
1180     my $numParameters = shift;
1181     my $function = shift;
1182
1183     my @andExpression = ();
1184     push(@andExpression, "args.Length() == $numParameters");
1185     my $parameterIndex = 0;
1186     foreach my $parameter (@{$function->parameters}) {
1187         last if $parameterIndex >= $numParameters;
1188         my $value = "args[$parameterIndex]";
1189         my $type = GetTypeFromSignature($parameter);
1190
1191         # Only DOMString or wrapper types are checked.
1192         # For DOMString, Null, Undefined and any Object are accepted too, as
1193         # these are acceptable values for a DOMString argument (any Object can
1194         # be converted to a string via .toString).
1195         if ($codeGenerator->IsStringType($type)) {
1196             push(@andExpression, "(${value}->IsNull() || ${value}->IsUndefined() || ${value}->IsString() || ${value}->IsObject())");
1197         } elsif ($parameter->extendedAttributes->{"Callback"}) {
1198             # For Callbacks only checks if the value is null or object.
1199             push(@andExpression, "(${value}->IsNull() || ${value}->IsObject())");
1200         } elsif (IsWrapperType($type)) {
1201             push(@andExpression, "(${value}->IsNull() || V8${type}::HasInstance($value))");
1202         }
1203
1204         $parameterIndex++;
1205     }
1206     my $res = join(" && ", @andExpression);
1207     $res = "($res)" if @andExpression > 1;
1208     return $res;
1209 }
1210
1211 sub GenerateFunctionParametersCheck
1212 {
1213     my $function = shift;
1214
1215     my @orExpression = ();
1216     my $numParameters = 0;
1217     foreach my $parameter (@{$function->parameters}) {
1218         if ($parameter->extendedAttributes->{"Optional"}) {
1219             push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
1220         }
1221         $numParameters++;
1222     }
1223     push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
1224     return join(" || ", @orExpression);
1225 }
1226
1227 sub GenerateOverloadedFunctionCallback
1228 {
1229     my $function = shift;
1230     my $dataNode = shift;
1231     my $implClassName = shift;
1232
1233     # Generate code for choosing the correct overload to call. Overloads are
1234     # chosen based on the total number of arguments passed and the type of
1235     # values passed in non-primitive argument slots. When more than a single
1236     # overload is applicable, precedence is given according to the order of
1237     # declaration in the IDL.
1238
1239     my $name = $function->signature->name;
1240     push(@implContentDecls, <<END);
1241 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args)
1242 {
1243     INC_STATS(\"DOM.$implClassName.$name\");
1244 END
1245
1246     foreach my $overload (@{$function->{overloads}}) {
1247         my $parametersCheck = GenerateFunctionParametersCheck($overload);
1248         push(@implContentDecls, "    if ($parametersCheck)\n");
1249         push(@implContentDecls, "        return ${name}$overload->{overloadIndex}Callback(args);\n");
1250     }
1251     push(@implContentDecls, <<END);
1252     V8Proxy::throwTypeError();
1253     return notHandledByInterceptor();
1254 END
1255     push(@implContentDecls, "}\n\n");
1256 }
1257
1258 sub GenerateFunctionCallback
1259 {
1260     my $function = shift;
1261     my $dataNode = shift;
1262     my $implClassName = shift;
1263
1264     my $interfaceName = $dataNode->name;
1265     my $name = $function->signature->name;
1266
1267     if (@{$function->{overloads}} > 1) {
1268         # Append a number to an overloaded method's name to make it unique:
1269         $name = $name . $function->{overloadIndex};
1270     }
1271
1272     # Adding and removing event listeners are not standard callback behavior,
1273     # but they are extremely consistent across the various classes that take event listeners,
1274     # so we can generate them as a "special case".
1275     if ($name eq "addEventListener") {
1276         GenerateEventListenerCallback($implClassName, !IsNodeSubType($dataNode), "add");
1277         return;
1278     } elsif ($name eq "removeEventListener") {
1279         GenerateEventListenerCallback($implClassName, !IsNodeSubType($dataNode), "remove");
1280         return;
1281     }
1282
1283     push(@implContentDecls, <<END);
1284 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args)
1285 {
1286     INC_STATS(\"DOM.$implClassName.$name\");
1287 END
1288
1289     my $numParameters = @{$function->parameters};
1290
1291     push(@implContentDecls, GenerateArgumentsCountCheck($function, $dataNode));
1292
1293     my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implClassName);
1294
1295     if ($svgNativeType) {
1296         my $nativeClassName = GetNativeType($implClassName); 
1297         if ($implClassName =~ /List$/) {
1298             push(@implContentDecls, "    $nativeClassName imp = V8${implClassName}::toNative(args.Holder());\n");
1299         } else {
1300             push(@implContentDecls, "    $nativeClassName wrapper = V8${implClassName}::toNative(args.Holder());\n");
1301             push(@implContentDecls, "    if (wrapper->role() == AnimValRole) {\n");
1302             push(@implContentDecls, "        V8Proxy::setDOMException(NO_MODIFICATION_ALLOWED_ERR);\n");
1303             push(@implContentDecls, "        return v8::Handle<v8::Value>();\n");
1304             push(@implContentDecls, "    }\n");
1305             my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implClassName);
1306             push(@implContentDecls, "    $svgWrappedNativeType& impInstance = wrapper->propertyReference();\n");
1307             push(@implContentDecls, "    $svgWrappedNativeType* imp = &impInstance;\n");
1308         }
1309     } elsif (!$function->signature->extendedAttributes->{"ClassMethod"}) {
1310         push(@implContentDecls, <<END);
1311     ${implClassName}* imp = V8${implClassName}::toNative(args.Holder());
1312 END
1313     }
1314
1315     # Check domain security if needed
1316     if (($dataNode->extendedAttributes->{"CheckDomainSecurity"}
1317        || $interfaceName eq "DOMWindow")
1318        && !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
1319     # We have not find real use cases yet.
1320     push(@implContentDecls, <<END);
1321     if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true))
1322         return v8::Handle<v8::Value>();
1323 END
1324     }
1325
1326     my $raisesExceptions = @{$function->raisesExceptions};
1327     if (!$raisesExceptions) {
1328         foreach my $parameter (@{$function->parameters}) {
1329             if ((!$parameter->extendedAttributes->{"Callback"} and TypeCanFailConversion($parameter)) or $parameter->extendedAttributes->{"IsIndex"}) {
1330                 $raisesExceptions = 1;
1331             }
1332         }
1333     }
1334
1335     if ($raisesExceptions) {
1336         AddToImplIncludes("ExceptionCode.h");
1337         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
1338         push(@implContentDecls, "    {\n");
1339         # The brace here is needed to prevent the ensuing 'goto fail's from jumping past constructors
1340         # of objects (like Strings) declared later, causing compile errors. The block scope ends
1341         # right before the label 'fail:'.
1342     }
1343
1344     if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
1345         push(@implContentDecls, <<END);
1346     RefPtr<ScriptArguments> scriptArguments(createScriptArguments(args, $numParameters));
1347     size_t maxStackSize = imp->shouldCaptureFullStackTrace() ? ScriptCallStack::maxCallStackSizeToCapture : 1;
1348     RefPtr<ScriptCallStack> callStack(createScriptCallStack(maxStackSize));
1349     if (!callStack)
1350         return v8::Undefined();
1351 END
1352         AddToImplIncludes("ScriptArguments.h");
1353         AddToImplIncludes("ScriptCallStack.h");
1354         AddToImplIncludes("ScriptCallStackFactory.h");
1355     }
1356     if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) {
1357         push(@implContentDecls, <<END);
1358     if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->getSVGDocument(ec)))
1359         return v8::Handle<v8::Value>();
1360 END
1361     }
1362
1363     my ($parameterCheckString, $paramIndex) = GenerateParametersCheck($function, $implClassName);
1364     push(@implContentDecls, $parameterCheckString);
1365
1366     # Build the function call string.
1367     push(@implContentDecls, GenerateFunctionCallString($function, $paramIndex, "    ", $implClassName));
1368
1369     if ($raisesExceptions) {
1370         push(@implContentDecls, "    }\n");
1371         push(@implContentDecls, "    fail:\n");
1372         push(@implContentDecls, "    V8Proxy::setDOMException(ec);\n");
1373         push(@implContentDecls, "    return v8::Handle<v8::Value>();\n");
1374     }
1375
1376     push(@implContentDecls, "}\n\n");
1377 }
1378
1379 sub GenerateArgumentsCountCheck
1380 {
1381     my $function = shift;
1382     my $dataNode = shift;
1383
1384     my $argumentsCountCheckString = "";
1385     my $requiresAllArguments;
1386     my $requiresAllArgumentsDefault = "";
1387     if (!$dataNode->extendedAttributes->{"LegacyDefaultOptionalArguments"}) {
1388         $requiresAllArgumentsDefault = "Raise";
1389     }
1390     $requiresAllArguments = $function->signature->extendedAttributes->{"RequiresAllArguments"} || $requiresAllArgumentsDefault;
1391     if ($requiresAllArguments) {
1392         my $numMandatoryParams = @{$function->parameters};
1393         foreach my $param (reverse(@{$function->parameters})) {
1394             if ($param->extendedAttributes->{"Optional"}) {
1395                 $numMandatoryParams--;
1396             } else {
1397                 last;
1398             }
1399         }
1400         if ($numMandatoryParams >= 1) {
1401             $argumentsCountCheckString .= "    if (args.Length() < $numMandatoryParams)\n";
1402             if ($requiresAllArguments eq "Raise") {
1403                 $argumentsCountCheckString .= "        return throwError(\"Not enough arguments\", V8Proxy::TypeError);\n";
1404             } else {
1405                 $argumentsCountCheckString .= "        return v8::Handle<v8::Value>();\n";
1406             }
1407         }
1408     }
1409     return $argumentsCountCheckString;
1410 }
1411
1412 sub GenerateParametersCheck
1413 {
1414     my $function = shift;
1415     my $implClassName = shift;
1416
1417     my $parameterCheckString = "";
1418     my $paramIndex = 0;
1419     foreach my $parameter (@{$function->parameters}) {
1420         TranslateParameter($parameter);
1421
1422         my $parameterName = $parameter->name;
1423
1424         # Optional callbacks should be treated differently, because they always have a default value (0),
1425         # and we can reduce the number of overloaded functions that take a different number of parameters.
1426         # Optional arguments with default values [Optional=CallWithDefaultValue] or [Optional=CallWithNullValue] should not generate an early call.
1427         my $optional = $parameter->extendedAttributes->{"Optional"};        
1428         if ($optional && $optional ne "CallWithDefaultValue" && $optional ne "CallWithNullValue" && !$parameter->extendedAttributes->{"Callback"}) {
1429             # Generate early call if there are not enough parameters.
1430             $parameterCheckString .= "    if (args.Length() <= $paramIndex) {\n";
1431             my $functionCall = GenerateFunctionCallString($function, $paramIndex, "    " x 2, $implClassName);
1432             $parameterCheckString .= $functionCall;
1433             $parameterCheckString .= "    }\n";
1434         }
1435
1436         my $parameterMissingPolicy = "MissingIsUndefined";
1437         if ($optional && $optional eq "CallWithNullValue") {
1438             $parameterMissingPolicy = "MissingIsEmpty";
1439         }
1440
1441         AddToImplIncludes("ExceptionCode.h");
1442         my $nativeType = GetNativeTypeFromSignature($parameter, $paramIndex);
1443         if ($parameter->extendedAttributes->{"Callback"}) {
1444             my $className = GetCallbackClassName($parameter->type);
1445             AddToImplIncludes("$className.h");
1446             if ($parameter->extendedAttributes->{"Optional"}) {
1447                 $parameterCheckString .= "    RefPtr<" . $parameter->type . "> $parameterName;\n";
1448                 $parameterCheckString .= "    if (args.Length() > $paramIndex && !args[$paramIndex]->IsNull() && !args[$paramIndex]->IsUndefined()) {\n";
1449                 $parameterCheckString .= "        if (!args[$paramIndex]->IsObject())\n";
1450                 $parameterCheckString .= "            return throwError(TYPE_MISMATCH_ERR);\n";
1451                 $parameterCheckString .= "        $parameterName = ${className}::create(args[$paramIndex], getScriptExecutionContext());\n";
1452                 $parameterCheckString .= "    }\n";
1453             } else {
1454                 $parameterCheckString .= "    if (args.Length() <= $paramIndex || !args[$paramIndex]->IsObject())\n";
1455                 $parameterCheckString .= "        return throwError(TYPE_MISMATCH_ERR);\n";
1456                 $parameterCheckString .= "    RefPtr<" . $parameter->type . "> $parameterName = ${className}::create(args[$paramIndex], getScriptExecutionContext());\n";
1457             }
1458         } elsif ($parameter->type eq "SerializedScriptValue") {
1459             AddToImplIncludes("SerializedScriptValue.h");
1460             $parameterCheckString .= "    bool ${parameterName}DidThrow = false;\n";
1461             $parameterCheckString .= "    $nativeType $parameterName = SerializedScriptValue::create(args[$paramIndex], ${parameterName}DidThrow);\n";
1462             $parameterCheckString .= "    if (${parameterName}DidThrow)\n";
1463             $parameterCheckString .= "        return v8::Undefined();\n";
1464         } elsif (TypeCanFailConversion($parameter)) {
1465             $parameterCheckString .= "    $nativeType $parameterName = " .
1466                  JSValueToNative($parameter, "args[$paramIndex]") . ";\n";
1467             $parameterCheckString .= "    if (UNLIKELY(!$parameterName)) {\n";
1468             $parameterCheckString .= "        ec = TYPE_MISMATCH_ERR;\n";
1469             $parameterCheckString .= "        goto fail;\n";
1470             $parameterCheckString .= "    }\n";
1471         } elsif ($nativeType =~ /^V8Parameter/) {
1472             my $value = JSValueToNative($parameter, "MAYBE_MISSING_PARAMETER(args, $paramIndex, $parameterMissingPolicy)");
1473             $parameterCheckString .= "    " . ConvertToV8Parameter($parameter, $nativeType, $parameterName, $value) . "\n";
1474         } else {
1475             AddToImplIncludes("V8BindingMacros.h");
1476             # If the "StrictTypeChecking" extended attribute is present, and the argument's type is an
1477             # interface type, then if the incoming value does not implement that interface, a TypeError
1478             # is thrown rather than silently passing NULL to the C++ code.
1479             # Per the Web IDL and ECMAScript specifications, incoming values can always be converted
1480             # to both strings and numbers, so do not throw TypeError if the argument is of these
1481             # types.
1482             if ($function->signature->extendedAttributes->{"StrictTypeChecking"}) {
1483                 my $argValue = "args[$paramIndex]";
1484                 my $argType = GetTypeFromSignature($parameter);
1485                 if (IsWrapperType($argType)) {
1486                     $parameterCheckString .= "    if (args.Length() > $paramIndex && !isUndefinedOrNull($argValue) && !V8${argType}::HasInstance($argValue)) {\n";
1487                     $parameterCheckString .= "        V8Proxy::throwTypeError();\n";
1488                     $parameterCheckString .= "        return notHandledByInterceptor();\n";
1489                     $parameterCheckString .= "    }\n";
1490                 }
1491             }
1492             $parameterCheckString .= "    EXCEPTION_BLOCK($nativeType, $parameterName, " .
1493                  JSValueToNative($parameter, "MAYBE_MISSING_PARAMETER(args, $paramIndex, $parameterMissingPolicy)") . ");\n";
1494         }
1495
1496         if ($parameter->extendedAttributes->{"IsIndex"}) {
1497             $parameterCheckString .= "    if (UNLIKELY($parameterName < 0)) {\n";
1498             $parameterCheckString .= "        ec = INDEX_SIZE_ERR;\n";
1499             $parameterCheckString .= "        goto fail;\n";
1500             $parameterCheckString .= "    }\n";
1501         }
1502
1503         $paramIndex++;
1504     }
1505     return ($parameterCheckString, $paramIndex);
1506 }
1507
1508 sub GenerateConstructorCallback
1509 {
1510     my $function = shift;
1511     my $dataNode = shift;
1512     my $implClassName = shift;
1513
1514     my $raisesExceptions = @{$function->raisesExceptions};
1515     if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
1516         $raisesExceptions = 1;
1517     }
1518     if (!$raisesExceptions) {
1519         foreach my $parameter (@{$function->parameters}) {
1520             if ((!$parameter->extendedAttributes->{"Callback"} and TypeCanFailConversion($parameter)) or $parameter->extendedAttributes->{"IsIndex"}) {
1521                 $raisesExceptions = 1;
1522             }
1523         }
1524     }
1525
1526     my @extraArgumentList;
1527     push(@implContent, <<END);
1528 v8::Handle<v8::Value> V8${implClassName}::constructorCallback(const v8::Arguments& args)
1529 {
1530     INC_STATS("DOM.${implClassName}.Constructor");
1531
1532     if (!args.IsConstructCall())
1533         return throwError("DOM object constructor cannot be called as a function.", V8Proxy::TypeError);
1534
1535     if (AllowAllocation::current())
1536         return args.Holder();
1537 END
1538
1539     push(@implContent, GenerateArgumentsCountCheck($function, $dataNode));
1540
1541     if ($raisesExceptions) {
1542         AddToImplIncludes("ExceptionCode.h");
1543         push(@implContent, "\n");
1544         push(@implContent, "    ExceptionCode ec = 0;\n");
1545     }
1546
1547     my ($parameterCheckString, $paramIndex) = GenerateParametersCheck($function, $implClassName);
1548     push(@implContent, $parameterCheckString);
1549
1550     my @contextArgument;
1551     if ($dataNode->extendedAttributes->{"CallWith"} && $dataNode->extendedAttributes->{"CallWith"} eq "ScriptExecutionContext") {
1552         push(@contextArgument, "context");
1553         push(@implContent, <<END);
1554
1555     ScriptExecutionContext* context = getScriptExecutionContext();
1556     if (!context)
1557         return throwError("${implClassName} constructor's associated context is not available", V8Proxy::ReferenceError);
1558 END
1559     }
1560
1561     if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
1562         push(@extraArgumentList, "ec");
1563     }
1564
1565     my @argumentList;
1566     my $index = 0;
1567     foreach my $parameter (@{$function->parameters}) {
1568         last if $index eq $paramIndex;
1569         push(@argumentList, $parameter->name);
1570         $index++;
1571     }
1572
1573     my $argumentString = join(", ", @contextArgument, @argumentList, @extraArgumentList);
1574     push(@implContent, "\n");
1575     push(@implContent, "    RefPtr<${implClassName}> obj = ${implClassName}::create(${argumentString});\n");
1576
1577     if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
1578         push(@implContent, "    if (ec)\n");
1579         push(@implContent, "        goto fail;\n");
1580     }
1581
1582     my $DOMObject = $dataNode->extendedAttributes->{"V8ConstructorSetsActiveDOMWrapper"} ? "ActiveDOMObject" : "DOMObject";
1583     push(@implContent, <<END);
1584
1585     V8DOMWrapper::setDOMWrapper(args.Holder(), &info, obj.get());
1586     obj->ref();
1587     V8DOMWrapper::setJSWrapperFor${DOMObject}(obj.get(), v8::Persistent<v8::Object>::New(args.Holder()));
1588     return args.Holder();
1589 END
1590
1591     if ($raisesExceptions) {
1592         push(@implContent, "  fail:\n");
1593         push(@implContent, "    return throwError(ec);\n");
1594     }
1595
1596     push(@implContent, "}\n");
1597     push(@implContent, "\n");
1598 }
1599
1600 sub GenerateBatchedAttributeData
1601 {
1602     my $dataNode = shift;
1603     my $interfaceName = $dataNode->name;
1604     my $attributes = shift;
1605
1606     foreach my $attribute (@$attributes) {
1607         my $conditionalString = GenerateConditionalString($attribute->signature);
1608         push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
1609         GenerateSingleBatchedAttribute($interfaceName, $attribute, ",", "");
1610         push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
1611     }
1612 }
1613
1614 sub GenerateSingleBatchedAttribute
1615 {
1616     my $interfaceName = shift;
1617     my $attribute = shift;
1618     my $delimiter = shift;
1619     my $indent = shift;
1620     my $attrName = $attribute->signature->name;
1621     my $attrExt = $attribute->signature->extendedAttributes;
1622
1623     # Attributes of type SerializedScriptValue are set in the
1624     # constructor and don't require callbacks.
1625     return if ($attribute->signature->type eq "SerializedScriptValue");
1626
1627     my $accessControl = "v8::DEFAULT";
1628     if ($attrExt->{"DoNotCheckDomainSecurityOnGet"}) {
1629         $accessControl = "v8::ALL_CAN_READ";
1630     } elsif ($attrExt->{"DoNotCheckDomainSecurityOnSet"}) {
1631         $accessControl = "v8::ALL_CAN_WRITE";
1632     } elsif ($attrExt->{"DoNotCheckDomainSecurity"}) {
1633         $accessControl = "v8::ALL_CAN_READ";
1634         if (!($attribute->type =~ /^readonly/) && !($attrExt->{"V8ReadOnly"})) {
1635             $accessControl .= " | v8::ALL_CAN_WRITE";
1636         }
1637     }
1638     if ($attrExt->{"V8DisallowShadowing"}) {
1639         $accessControl .= " | v8::PROHIBITS_OVERWRITING";
1640     }
1641     $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")";
1642
1643     my $customAccessor =
1644         $attrExt->{"Custom"} ||
1645         $attrExt->{"CustomSetter"} ||
1646         $attrExt->{"CustomGetter"} ||
1647         $attrExt->{"V8Custom"} ||
1648         $attrExt->{"V8CustomSetter"} ||
1649         $attrExt->{"V8CustomGetter"} ||
1650         "";
1651     if ($customAccessor eq 1) {
1652         # use the naming convension, interface + (capitalize) attr name
1653         $customAccessor = $interfaceName . "::" . $attrName;
1654     }
1655
1656     my $getter;
1657     my $setter;
1658     my $propAttr = "v8::None";
1659     my $hasCustomSetter = 0;
1660
1661     # Check attributes.
1662     if ($attrExt->{"DontEnum"}) {
1663         $propAttr .= " | v8::DontEnum";
1664     }
1665     if ($attrExt->{"V8DisallowShadowing"}) {
1666         $propAttr .= " | v8::DontDelete";
1667     }
1668
1669     my $on_proto = "0 /* on instance */";
1670     my $data = "0 /* no data */";
1671
1672     # Constructor
1673     if ($attribute->signature->type =~ /Constructor$/) {
1674         my $constructorType = $codeGenerator->StripModule($attribute->signature->type);
1675         $constructorType =~ s/Constructor$//;
1676         AddToImplIncludes("V8${constructorType}.h", $attribute->signature->extendedAttributes->{"Conditional"});
1677         if ($customAccessor) {
1678             $getter = "V8${customAccessor}AccessorGetter";
1679         } else {
1680             $data = "&V8${constructorType}::info";
1681             $getter = "${interfaceName}Internal::${interfaceName}ConstructorGetter";
1682         }
1683         $setter = "0";
1684         $propAttr = "v8::ReadOnly";
1685
1686     } else {
1687         # Default Getter and Setter
1688         $getter = "${interfaceName}Internal::${attrName}AttrGetter";
1689         $setter = "${interfaceName}Internal::${attrName}AttrSetter";
1690
1691         # Custom Setter
1692         if ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
1693             $hasCustomSetter = 1;
1694             $setter = "V8${customAccessor}AccessorSetter";
1695         }
1696
1697         # Custom Getter
1698         if ($attrExt->{"CustomGetter"} || $attrExt->{"V8CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
1699             $getter = "V8${customAccessor}AccessorGetter";
1700         }
1701     }
1702
1703     # Replaceable
1704     if ($attrExt->{"Replaceable"} && !$hasCustomSetter) {
1705         $setter = "0";
1706         # Handle the special case of window.top being marked as Replaceable.
1707         # FIXME: Investigate whether we could treat window.top as replaceable
1708         # and allow shadowing without it being a security hole.
1709         if (!($interfaceName eq "DOMWindow" and $attrName eq "top")) {
1710             $propAttr .= " | v8::ReadOnly";
1711         }
1712     }
1713
1714     # Read only attributes
1715     if ($attribute->type =~ /^readonly/ || $attrExt->{"V8ReadOnly"}) {
1716         $setter = "0";
1717     }
1718
1719     # An accessor can be installed on the proto
1720     if ($attrExt->{"v8OnProto"}) {
1721         $on_proto = "1 /* on proto */";
1722     }
1723
1724     my $commentInfo = "Attribute '$attrName' (Type: '" . $attribute->type .
1725                       "' ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
1726
1727     push(@implContent, $indent . "    \/\/ $commentInfo\n");
1728     push(@implContent, $indent . "    {\"$attrName\", $getter, $setter, $data, $accessControl, static_cast<v8::PropertyAttribute>($propAttr), $on_proto}" . $delimiter . "\n");
1729 }
1730
1731 sub GenerateImplementationIndexer
1732 {
1733     my $dataNode = shift;
1734     my $indexer = shift;
1735     my $interfaceName = $dataNode->name;
1736
1737     # FIXME: Figure out what HasNumericIndexGetter is really supposed to do. Right now, it's only set on WebGL-related files.
1738     my $hasCustomSetter = $dataNode->extendedAttributes->{"HasCustomIndexSetter"} && !$dataNode->extendedAttributes->{"HasNumericIndexGetter"};
1739     my $hasGetter = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
1740
1741     # FIXME: Find a way to not have to special-case HTMLOptionsCollection.
1742     if ($interfaceName eq "HTMLOptionsCollection") {
1743         $hasGetter = 1;
1744     }
1745
1746     # FIXME: Investigate and remove this nastinesss. In V8, named property handling and indexer handling are apparently decoupled,
1747     # which means that object[X] where X is a number doesn't reach named property indexer. So we need to provide
1748     # simplistic, mirrored indexer handling in addition to named property handling.
1749     my $isSpecialCase = exists $indexerSpecialCases{$interfaceName};
1750     if ($isSpecialCase) {
1751         $hasGetter = 1;
1752         if ($dataNode->extendedAttributes->{"DelegatingPutFunction"}) {
1753             $hasCustomSetter = 1;
1754         }
1755     }
1756
1757     if (!$hasGetter) {
1758         return;
1759     }
1760
1761     AddToImplIncludes("V8Collection.h");
1762
1763     my $indexerType = $indexer ? $indexer->type : 0;
1764
1765     # FIXME: Remove this once toV8 helper methods are implemented (see https://bugs.webkit.org/show_bug.cgi?id=32563).
1766     if ($interfaceName eq "WebKitCSSKeyframesRule") {
1767         $indexerType = "WebKitCSSKeyframeRule";
1768     }
1769
1770     # FIXME: The item() getter is not inherited from CSSValueList, seemingly due to the way
1771     # the CodeGenerator->AddMethodsConstantsAndAttributesFromParentClasses() method works,
1772     # so we need to set the indexerType manually in this case.
1773     if ($interfaceName eq "WebKitCSSTransformValue") {
1774         $indexerType = "CSSValue";
1775     }
1776
1777     if ($indexerType && !$hasCustomSetter) {
1778         if ($indexerType eq "DOMString") {
1779             my $conversion = $indexer->extendedAttributes->{"ConvertNullStringTo"};
1780             if ($conversion && $conversion eq "Null") {
1781                 push(@implContent, <<END);
1782     setCollectionStringOrNullIndexedGetter<${interfaceName}>(desc);
1783 END
1784             } else {
1785                 push(@implContent, <<END);
1786     setCollectionStringIndexedGetter<${interfaceName}>(desc);
1787 END
1788             }
1789         } else {
1790             push(@implContent, <<END);
1791     setCollectionIndexedGetter<${interfaceName}, ${indexerType}>(desc);
1792 END
1793             # Include the header for this indexer type, because setCollectionIndexedGetter() requires toV8() for this type.
1794             AddToImplIncludes("V8${indexerType}.h");
1795         }
1796
1797         return;
1798     }
1799
1800     my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
1801     my $hasEnumerator = !$isSpecialCase && IsNodeSubType($dataNode);
1802     my $setOn = "Instance";
1803
1804     # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
1805     # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
1806     # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
1807     # on the object.
1808     if ($interfaceName eq "DOMWindow") {
1809         $setOn = "Prototype";
1810         $hasDeleter = 0;
1811     }
1812
1813     push(@implContent, "    desc->${setOn}Template()->SetIndexedPropertyHandler(V8${interfaceName}::indexedPropertyGetter");
1814     push(@implContent, $hasCustomSetter ? ", V8${interfaceName}::indexedPropertySetter" : ", 0");
1815     push(@implContent, ", 0"); # IndexedPropertyQuery -- not being used at the moment.
1816     push(@implContent, $hasDeleter ? ", V8${interfaceName}::indexedPropertyDeleter" : ", 0");
1817     push(@implContent, ", nodeCollectionIndexedPropertyEnumerator<${interfaceName}>") if $hasEnumerator;
1818     push(@implContent, ");\n");
1819 }
1820
1821 sub GenerateImplementationNamedPropertyGetter
1822 {
1823     my $dataNode = shift;
1824     my $namedPropertyGetter = shift;
1825     my $interfaceName = $dataNode->name;
1826     my $hasCustomGetter = $dataNode->extendedAttributes->{"HasOverridingNameGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
1827
1828     # FIXME: Remove hard-coded HTMLOptionsCollection reference by changing HTMLOptionsCollection to not inherit
1829     # from HTMLCollection per W3C spec (http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/html.html#HTMLOptionsCollection).
1830     if ($interfaceName eq "HTMLOptionsCollection") {
1831         $interfaceName = "HTMLCollection";
1832         $hasCustomGetter = 1;
1833     }
1834
1835     if ($interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") {
1836         $hasCustomGetter = 1;
1837     }
1838
1839     if ($interfaceName eq "HTMLDocument") {
1840         $hasCustomGetter = 0;
1841     }
1842
1843     my $hasGetter = $dataNode->extendedAttributes->{"HasNameGetter"} || $hasCustomGetter;
1844     if (!$hasGetter) {
1845         return;
1846     }
1847
1848     if ($namedPropertyGetter && $namedPropertyGetter->type ne "Node" && !$namedPropertyGetter->extendedAttributes->{"Custom"} && !$hasCustomGetter) {
1849         AddToImplIncludes("V8Collection.h");
1850         my $type = $namedPropertyGetter->type;
1851         push(@implContent, <<END);
1852     setCollectionNamedGetter<${interfaceName}, ${type}>(desc);
1853 END
1854         return;
1855     }
1856
1857     my $hasSetter = $dataNode->extendedAttributes->{"DelegatingPutFunction"};
1858     my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
1859     my $hasEnumerator = $dataNode->extendedAttributes->{"CustomGetPropertyNames"};
1860     my $setOn = "Instance";
1861
1862     # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
1863     # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
1864     # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
1865     # on the object.
1866     if ($interfaceName eq "DOMWindow") {
1867         $setOn = "Prototype";
1868         $hasDeleter = 0;
1869         $hasEnumerator = 0;
1870     }
1871
1872     push(@implContent, "    desc->${setOn}Template()->SetNamedPropertyHandler(V8${interfaceName}::namedPropertyGetter, ");
1873     push(@implContent, $hasSetter ? "V8${interfaceName}::namedPropertySetter, " : "0, ");
1874     # If there is a custom enumerator, there MUST be custom query to properly communicate property attributes.
1875     push(@implContent, $hasEnumerator ? "V8${interfaceName}::namedPropertyQuery, " : "0, ");
1876     push(@implContent, $hasDeleter ? "V8${interfaceName}::namedPropertyDeleter, " : "0, ");
1877     push(@implContent, $hasEnumerator ? "V8${interfaceName}::namedPropertyEnumerator" : "0");
1878     push(@implContent, ");\n");
1879 }
1880
1881 sub GenerateImplementationCustomCall
1882 {
1883     my $dataNode = shift;
1884     my $interfaceName = $dataNode->name;
1885     my $hasCustomCall = $dataNode->extendedAttributes->{"CustomCall"} || $dataNode->extendedAttributes->{"V8CustomCall"};
1886
1887     # FIXME: Remove hard-coded HTMLOptionsCollection reference.
1888     if ($interfaceName eq "HTMLOptionsCollection") {
1889         $interfaceName = "HTMLCollection";
1890         $hasCustomCall = 1;
1891     }
1892
1893     if ($hasCustomCall) {
1894         push(@implContent, "    desc->InstanceTemplate()->SetCallAsFunctionHandler(V8${interfaceName}::callAsFunctionCallback);\n");
1895     }
1896 }
1897
1898 sub GenerateImplementationMasqueradesAsUndefined
1899 {
1900     my $dataNode = shift;
1901     if ($dataNode->extendedAttributes->{"MasqueradesAsUndefined"})
1902     {
1903         push(@implContent, "    desc->InstanceTemplate()->MarkAsUndetectable();\n");
1904     }
1905 }
1906
1907 sub GenerateImplementation
1908 {
1909     my $object = shift;
1910     my $dataNode = shift;
1911     my $interfaceName = $dataNode->name;
1912     my $visibleInterfaceName = GetVisibleInterfaceName($interfaceName);
1913     my $className = "V8$interfaceName";
1914     my $implClassName = $interfaceName;
1915     my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
1916
1917     # - Add default header template
1918     push(@implFixedHeader, GenerateImplementationContentHeader($dataNode));
1919          
1920     AddToImplIncludes("RuntimeEnabledFeatures.h");
1921     AddToImplIncludes("V8Proxy.h");
1922     AddToImplIncludes("V8Binding.h");
1923     AddToImplIncludes("V8BindingState.h");
1924     AddToImplIncludes("V8DOMWrapper.h");
1925     AddToImplIncludes("V8IsolatedContext.h");
1926
1927     AddIncludesForType($interfaceName);
1928
1929     my $toActive = $dataNode->extendedAttributes->{"ActiveDOMObject"} ? "${className}::toActiveDOMObject" : "0";
1930
1931     # Find the super descriptor.
1932     my $parentClass = "";
1933     my $parentClassTemplate = "";
1934     foreach (@{$dataNode->parents}) {
1935         my $parent = $codeGenerator->StripModule($_);
1936         if ($parent eq "EventTarget") {
1937             next;
1938         }
1939         AddToImplIncludes("V8${parent}.h");
1940         $parentClass = "V8" . $parent;
1941         $parentClassTemplate = $parentClass . "::GetTemplate()";
1942         last;
1943     }
1944     push(@implContentDecls, "namespace WebCore {\n\n");
1945     my $parentClassInfo = $parentClass ? "&${parentClass}::info" : "0";
1946     push(@implContentDecls, "WrapperTypeInfo ${className}::info = { ${className}::GetTemplate, ${className}::derefObject, ${toActive}, ${parentClassInfo} };\n\n");   
1947     push(@implContentDecls, "namespace ${interfaceName}Internal {\n\n");
1948     push(@implContentDecls, "template <typename T> void V8_USE(T) { }\n\n");
1949
1950     my $hasConstructors = 0;
1951     my $serializedAttribute;
1952     # Generate property accessors for attributes.
1953     for (my $index = 0; $index < @{$dataNode->attributes}; $index++) {
1954         my $attribute = @{$dataNode->attributes}[$index];
1955         my $attrType = $attribute->signature->type;
1956
1957         # Generate special code for the constructor attributes.
1958         if ($attrType =~ /Constructor$/) {
1959             if (!($attribute->signature->extendedAttributes->{"CustomGetter"} ||
1960                 $attribute->signature->extendedAttributes->{"V8CustomGetter"})) {
1961                 $hasConstructors = 1;
1962             }
1963             next;
1964         }
1965
1966         if ($attrType eq "EventListener" && $interfaceName eq "DOMWindow") {
1967             $attribute->signature->extendedAttributes->{"v8OnProto"} = 1;
1968         }
1969
1970         # Attributes of type SerializedScriptValue are set in the
1971         # constructor and don't require callbacks.
1972         if ($attrType eq "SerializedScriptValue") {
1973             die "Only one attribute of type SerializedScriptValue supported" if $serializedAttribute;
1974             AddToImplIncludes("SerializedScriptValue.h");
1975             $serializedAttribute = $attribute;
1976             next;
1977         }
1978
1979         # Do not generate accessor if this is a custom attribute.  The
1980         # call will be forwarded to a hand-written accessor
1981         # implementation.
1982         if ($attribute->signature->extendedAttributes->{"Custom"} ||
1983             $attribute->signature->extendedAttributes->{"V8Custom"}) {
1984             next;
1985         }
1986
1987         # Generate the accessor.
1988         if (!($attribute->signature->extendedAttributes->{"CustomGetter"} ||
1989             $attribute->signature->extendedAttributes->{"V8CustomGetter"})) {
1990             GenerateNormalAttrGetter($attribute, $dataNode, $implClassName, $interfaceName);
1991         }
1992         if (!$attribute->signature->extendedAttributes->{"CustomSetter"} &&
1993             !$attribute->signature->extendedAttributes->{"V8CustomSetter"} &&
1994             !$attribute->signature->extendedAttributes->{"Replaceable"} &&
1995             $attribute->type !~ /^readonly/ &&
1996             !$attribute->signature->extendedAttributes->{"V8ReadOnly"}) {
1997             GenerateNormalAttrSetter($attribute, $dataNode, $implClassName, $interfaceName);
1998         }
1999     }
2000
2001     if ($hasConstructors) {
2002         GenerateConstructorGetter($implClassName);
2003     }
2004
2005     $codeGenerator->LinkOverloadedFunctions($dataNode);
2006
2007     my $indexer;
2008     my $namedPropertyGetter;
2009     # Generate methods for functions.
2010     foreach my $function (@{$dataNode->functions}) {
2011         if (!($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"V8Custom"})) {
2012             GenerateFunctionCallback($function, $dataNode, $implClassName);
2013             if ($function->{overloadIndex} > 1 && $function->{overloadIndex} == @{$function->{overloads}}) {
2014                 GenerateOverloadedFunctionCallback($function, $dataNode, $implClassName);
2015             }
2016         }
2017
2018         if ($function->signature->name eq "item") {
2019             $indexer = $function->signature;
2020         }
2021
2022         if ($function->signature->name eq "namedItem") {
2023             $namedPropertyGetter = $function->signature;
2024         }
2025
2026         # If the function does not need domain security check, we need to
2027         # generate an access getter that returns different function objects
2028         # for different calling context.
2029         if (($dataNode->extendedAttributes->{"CheckDomainSecurity"} || ($interfaceName eq "DOMWindow")) && $function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
2030             GenerateDomainSafeFunctionGetter($function, $implClassName);
2031         }
2032     }
2033
2034     # Attributes
2035     my $attributes = $dataNode->attributes;
2036
2037     # For the DOMWindow interface we partition the attributes into the
2038     # ones that disallows shadowing and the rest.
2039     my @disallowsShadowing;
2040     # Also separate out attributes that are enabled at runtime so we can process them specially.
2041     my @enabledAtRuntime;
2042     my @normal;
2043     foreach my $attribute (@$attributes) {
2044
2045         if ($interfaceName eq "DOMWindow" && $attribute->signature->extendedAttributes->{"V8DisallowShadowing"}) {
2046             push(@disallowsShadowing, $attribute);
2047         } elsif ($attribute->signature->extendedAttributes->{"EnabledAtRuntime"}) {
2048             push(@enabledAtRuntime, $attribute);
2049         } else {
2050             push(@normal, $attribute);
2051         }
2052     }
2053     $attributes = \@normal;
2054     # Put the attributes that disallow shadowing on the shadow object.
2055     if (@disallowsShadowing) {
2056         push(@implContent, "static const BatchedAttribute shadowAttrs[] = {\n");
2057         GenerateBatchedAttributeData($dataNode, \@disallowsShadowing);
2058         push(@implContent, "};\n\n");
2059     }
2060
2061     my $has_attributes = 0;
2062     if (@$attributes && (@$attributes > 1 || $$attributes[0]->signature->type ne "SerializedScriptValue")) {
2063         $has_attributes = 1;
2064         push(@implContent, "static const BatchedAttribute ${interfaceName}Attrs[] = {\n");
2065         GenerateBatchedAttributeData($dataNode, $attributes);
2066         push(@implContent, "};\n\n");
2067     }
2068
2069     # Setup table of standard callback functions
2070     my $num_callbacks = 0;
2071     my $has_callbacks = 0;
2072     foreach my $function (@{$dataNode->functions}) {
2073         # Only one table entry is needed for overloaded methods:
2074         next if $function->{overloadIndex} > 1;
2075
2076         my $attrExt = $function->signature->extendedAttributes;
2077         # Don't put any nonstandard functions into this table:
2078         if ($attrExt->{"V8OnInstance"}) {
2079             next;
2080         }
2081         if ($attrExt->{"ClassMethod"}) {
2082             next;
2083         }
2084         if ($attrExt->{"EnabledAtRuntime"} || RequiresCustomSignature($function) || $attrExt->{"V8DoNotCheckSignature"}) {
2085             next;
2086         }
2087         if ($attrExt->{"DoNotCheckDomainSecurity"} &&
2088             ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) {
2089             next;
2090         }
2091         if ($attrExt->{"DontEnum"} || $attrExt->{"V8ReadOnly"}) {
2092             next;
2093         }
2094         if (!$has_callbacks) {
2095             $has_callbacks = 1;
2096             push(@implContent, "static const BatchedCallback ${interfaceName}Callbacks[] = {\n");
2097         }
2098         my $name = $function->signature->name;
2099         my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
2100         my $conditionalString = GenerateConditionalString($function->signature);
2101         push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
2102         push(@implContent, <<END);
2103     {"$name", $callback},
2104 END
2105         push(@implContent, "#endif\n") if $conditionalString;
2106         $num_callbacks++;
2107     }
2108     push(@implContent, "};\n\n")  if $has_callbacks;
2109
2110     # Setup constants
2111     my $has_constants = 0;
2112     my @constantsEnabledAtRuntime;
2113     if (@{$dataNode->constants}) {
2114         $has_constants = 1;
2115         push(@implContent, "static const BatchedConstant ${interfaceName}Consts[] = {\n");
2116     }
2117     foreach my $constant (@{$dataNode->constants}) {
2118         my $name = $constant->name;
2119         my $value = $constant->value;
2120         my $attrExt = $constant->extendedAttributes;
2121         if ($attrExt->{"EnabledAtRuntime"}) {
2122             push(@constantsEnabledAtRuntime, $constant);
2123         } else {
2124             # FIXME: we need the static_cast here only because of one constant, NodeFilter.idl
2125             # defines "const unsigned long SHOW_ALL = 0xFFFFFFFF".  It would be better if we
2126             # handled this here, and converted it to a -1 constant in the c++ output.
2127             push(@implContent, <<END);
2128     {"${name}", static_cast<signed int>($value)},
2129 END
2130         }
2131     }
2132     if ($has_constants) {
2133         push(@implContent, "};\n\n");
2134         push(@implContent, $codeGenerator->GenerateCompileTimeCheckForEnumsIfNeeded($dataNode));
2135     }
2136
2137     push(@implContentDecls, "} // namespace ${interfaceName}Internal\n\n");
2138
2139     # In namespace WebCore, add generated implementation for 'CanBeConstructed'.
2140     if ($dataNode->extendedAttributes->{"CanBeConstructed"} && !$dataNode->extendedAttributes->{"CustomConstructor"} && !$dataNode->extendedAttributes->{"V8CustomConstructor"} && !$dataNode->extendedAttributes->{"Constructor"}) {
2141         my $v8ConstructFunction;
2142         my $callWith = $dataNode->extendedAttributes->{"CallWith"};
2143         if ($callWith and $callWith eq "ScriptExecutionContext") {
2144             $v8ConstructFunction = "constructDOMObjectWithScriptExecutionContext";
2145         } else {
2146             $v8ConstructFunction = "constructDOMObject";
2147         }
2148         push(@implContent, <<END);
2149 v8::Handle<v8::Value> ${className}::constructorCallback(const v8::Arguments& args)
2150 {
2151     INC_STATS("DOM.${interfaceName}.Contructor");
2152     return V8Proxy::${v8ConstructFunction}<$interfaceName>(args, &info);
2153 }
2154
2155 END
2156     }
2157
2158     if ($dataNode->extendedAttributes->{"Constructor"}) {
2159         GenerateConstructorCallback($dataNode->constructor, $dataNode, $interfaceName);
2160     }
2161
2162     my $access_check = "";
2163     if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !($interfaceName eq "DOMWindow")) {
2164         $access_check = "instance->SetAccessCheckCallbacks(V8${interfaceName}::namedSecurityCheck, V8${interfaceName}::indexedSecurityCheck, v8::External::Wrap(&V8${interfaceName}::info));";
2165     }
2166
2167     # For the DOMWindow interface, generate the shadow object template
2168     # configuration method.
2169     if ($implClassName eq "DOMWindow") {
2170         push(@implContent, <<END);
2171 static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Persistent<v8::ObjectTemplate> templ)
2172 {
2173     batchConfigureAttributes(templ, v8::Handle<v8::ObjectTemplate>(), shadowAttrs, WTF_ARRAY_LENGTH(shadowAttrs));
2174
2175     // Install a security handler with V8.
2176     templ->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::External::Wrap(&V8DOMWindow::info));
2177     templ->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
2178     return templ;
2179 }
2180 END
2181     }
2182
2183     if (!$parentClassTemplate) {
2184         $parentClassTemplate = "v8::Persistent<v8::FunctionTemplate>()";
2185     }
2186
2187     # Generate the template configuration method
2188     push(@implContent,  <<END);
2189 static v8::Persistent<v8::FunctionTemplate> Configure${className}Template(v8::Persistent<v8::FunctionTemplate> desc)
2190 {
2191     desc->ReadOnlyPrototype();
2192
2193     v8::Local<v8::Signature> defaultSignature;
2194 END
2195     if ($dataNode->extendedAttributes->{"EnabledAtRuntime"}) {
2196         my $enable_function = GetRuntimeEnableFunctionName($dataNode);
2197         push(@implContent, <<END);
2198     if (!${enable_function}())
2199         defaultSignature = configureTemplate(desc, \"\", $parentClassTemplate, V8${interfaceName}::internalFieldCount, 0, 0, 0, 0);
2200     else
2201 END
2202     }
2203     push(@implContent,  <<END);
2204     defaultSignature = configureTemplate(desc, \"${visibleInterfaceName}\", $parentClassTemplate, V8${interfaceName}::internalFieldCount,
2205 END
2206     # Set up our attributes if we have them
2207     if ($has_attributes) {
2208         push(@implContent, <<END);
2209         ${interfaceName}Attrs, WTF_ARRAY_LENGTH(${interfaceName}Attrs),
2210 END
2211     } else {
2212         push(@implContent, <<END);
2213         0, 0,
2214 END
2215     }
2216
2217     if ($has_callbacks) {
2218         push(@implContent, <<END);
2219         ${interfaceName}Callbacks, WTF_ARRAY_LENGTH(${interfaceName}Callbacks));
2220 END
2221     } else {
2222         push(@implContent, <<END);
2223         0, 0);
2224 END
2225     }
2226     
2227     AddToImplIncludes("wtf/UnusedParam.h");
2228     push(@implContent, <<END);
2229     UNUSED_PARAM(defaultSignature); // In some cases, it will not be used.
2230 END
2231
2232     if ($dataNode->extendedAttributes->{"CanBeConstructed"} || $dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"V8CustomConstructor"} || $dataNode->extendedAttributes->{"Constructer"}) {
2233         push(@implContent, <<END);
2234     desc->SetCallHandler(V8${interfaceName}::constructorCallback);
2235 END
2236     }
2237
2238     if ($access_check or @enabledAtRuntime or @{$dataNode->functions} or $has_constants) {
2239         push(@implContent,  <<END);
2240     v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate();
2241     v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate();
2242     UNUSED_PARAM(instance); // In some cases, it will not be used.
2243     UNUSED_PARAM(proto); // In some cases, it will not be used.
2244 END
2245     }
2246
2247     push(@implContent,  "    $access_check\n");
2248
2249     # Setup the enable-at-runtime attrs if we have them
2250     foreach my $runtime_attr (@enabledAtRuntime) {
2251         my $enable_function = GetRuntimeEnableFunctionName($runtime_attr->signature);
2252         my $conditionalString = GenerateConditionalString($runtime_attr->signature);
2253         push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
2254         push(@implContent, "    if (${enable_function}()) {\n");
2255         push(@implContent, "        static const BatchedAttribute attrData =\\\n");
2256         GenerateSingleBatchedAttribute($interfaceName, $runtime_attr, ";", "    ");
2257         push(@implContent, <<END);
2258         configureAttribute(instance, proto, attrData);
2259     }
2260 END
2261         push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
2262     }
2263
2264     # Setup the enable-at-runtime constants if we have them
2265     foreach my $runtime_const (@constantsEnabledAtRuntime) {
2266         my $enable_function = GetRuntimeEnableFunctionName($runtime_const);
2267         my $conditionalString = GenerateConditionalString($runtime_const);
2268         my $name = $runtime_const->name;
2269         my $value = $runtime_const->value;
2270         push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
2271         push(@implContent, "    if (${enable_function}()) {\n");
2272         push(@implContent, <<END);
2273         static const BatchedConstant constData = {"${name}", static_cast<signed int>(${value})};
2274         batchConfigureConstants(desc, proto, &constData, 1);
2275 END
2276         push(@implContent, "    }\n");
2277         push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
2278     }
2279
2280     GenerateImplementationIndexer($dataNode, $indexer);
2281     GenerateImplementationNamedPropertyGetter($dataNode, $namedPropertyGetter);
2282     GenerateImplementationCustomCall($dataNode);
2283     GenerateImplementationMasqueradesAsUndefined($dataNode);
2284
2285     # Define our functions with Set() or SetAccessor()
2286     my $total_functions = 0;
2287     foreach my $function (@{$dataNode->functions}) {
2288         # Only one accessor is needed for overloaded methods:
2289         next if $function->{overloadIndex} > 1;
2290
2291         $total_functions++;
2292         my $attrExt = $function->signature->extendedAttributes;
2293         my $name = $function->signature->name;
2294
2295         my $property_attributes = "v8::DontDelete";
2296         if ($attrExt->{"DontEnum"}) {
2297             $property_attributes .= " | v8::DontEnum";
2298         }
2299         if ($attrExt->{"V8ReadOnly"}) {
2300             $property_attributes .= " | v8::ReadOnly";
2301         }
2302
2303         my $commentInfo = "Function '$name' (ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
2304
2305         my $template = "proto";
2306         if ($attrExt->{"V8OnInstance"}) {
2307             $template = "instance";
2308         }
2309         if ($attrExt->{"ClassMethod"}) {
2310             $template = "desc";
2311         }
2312
2313         my $conditional = "";
2314         if ($attrExt->{"EnabledAtRuntime"}) {
2315             # Only call Set()/SetAccessor() if this method should be enabled
2316             my $enable_function = GetRuntimeEnableFunctionName($function->signature);
2317             $conditional = "if (${enable_function}())\n        ";
2318         }
2319
2320         if ($attrExt->{"DoNotCheckDomainSecurity"} &&
2321             ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) {
2322             # Mark the accessor as ReadOnly and set it on the proto object so
2323             # it can be shadowed. This is really a hack to make it work.
2324             # There are several sceneria to call into the accessor:
2325             #   1) from the same domain: "window.open":
2326             #      the accessor finds the DOM wrapper in the proto chain;
2327             #   2) from the same domain: "window.__proto__.open":
2328             #      the accessor will NOT find a DOM wrapper in the prototype chain
2329             #   3) from another domain: "window.open":
2330             #      the access find the DOM wrapper in the prototype chain
2331             #   "window.__proto__.open" from another domain will fail when
2332             #   accessing '__proto__'
2333             #
2334             # The solution is very hacky and fragile, it really needs to be replaced
2335             # by a better solution.
2336             $property_attributes .= " | v8::ReadOnly";
2337             push(@implContent, <<END);
2338
2339     // $commentInfo
2340     ${conditional}$template->SetAccessor(v8::String::New("$name"), ${interfaceName}Internal::${name}AttrGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>($property_attributes));
2341 END
2342           $num_callbacks++;
2343           next;
2344       }
2345
2346       my $signature = "defaultSignature";
2347       if ($attrExt->{"V8DoNotCheckSignature"} || $attrExt->{"ClassMethod"}) {
2348           $signature = "v8::Local<v8::Signature>()";
2349       }
2350
2351       if (RequiresCustomSignature($function)) {
2352           $signature = "${name}Signature";
2353           push(@implContent, "\n    // Custom Signature '$name'\n", CreateCustomSignature($function));
2354       }
2355
2356       # Normal function call is a template
2357       my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
2358
2359       if ($property_attributes eq "v8::DontDelete") {
2360           $property_attributes = "";
2361       } else {
2362           $property_attributes = ", static_cast<v8::PropertyAttribute>($property_attributes)";
2363       }
2364
2365       if ($template eq "proto" && $conditional eq "" && $signature eq "defaultSignature" && $property_attributes eq "") {
2366           # Standard type of callback, already created in the batch, so skip it here.
2367           next;
2368       }
2369
2370       push(@implContent, <<END);
2371     ${conditional}$template->Set(v8::String::New("$name"), v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), ${signature})$property_attributes);
2372 END
2373       $num_callbacks++;
2374     }
2375
2376     die "Wrong number of callbacks generated for $interfaceName ($num_callbacks, should be $total_functions)" if $num_callbacks != $total_functions;
2377
2378     if ($has_constants) {
2379         push(@implContent, <<END);
2380     batchConfigureConstants(desc, proto, ${interfaceName}Consts, WTF_ARRAY_LENGTH(${interfaceName}Consts));
2381 END
2382     }
2383
2384     # Special cases
2385     if ($interfaceName eq "DOMWindow") {
2386         push(@implContent, <<END);
2387
2388     proto->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
2389     desc->SetHiddenPrototype(true);
2390     instance->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
2391     // Set access check callbacks, but turned off initially.
2392     // When a context is detached from a frame, turn on the access check.
2393     // Turning on checks also invalidates inline caches of the object.
2394     instance->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::External::Wrap(&V8DOMWindow::info), false);
2395 END
2396     }
2397     if ($interfaceName eq "HTMLDocument") {
2398         push(@implContent, <<END);
2399     desc->SetHiddenPrototype(true);
2400 END
2401     }
2402     if ($interfaceName eq "Location") {
2403         push(@implContent, <<END);
2404
2405     // For security reasons, these functions are on the instance instead
2406     // of on the prototype object to ensure that they cannot be overwritten.
2407     instance->SetAccessor(v8::String::New("reload"), V8Location::reloadAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
2408     instance->SetAccessor(v8::String::New("replace"), V8Location::replaceAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
2409     instance->SetAccessor(v8::String::New("assign"), V8Location::assignAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
2410 END
2411     }
2412
2413     my $nativeType = GetNativeTypeForConversions($dataNode, $interfaceName);
2414     push(@implContent, <<END);
2415
2416     // Custom toString template
2417     desc->Set(getToStringName(), getToStringTemplate());
2418     return desc;
2419 }
2420
2421 v8::Persistent<v8::FunctionTemplate> ${className}::GetRawTemplate()
2422 {
2423     V8BindingPerIsolateData* data = V8BindingPerIsolateData::current();
2424     V8BindingPerIsolateData::TemplateMap::iterator result = data->rawTemplateMap().find(&info);
2425     if (result != data->rawTemplateMap().end())
2426         return result->second;
2427
2428     v8::HandleScope handleScope;
2429     v8::Persistent<v8::FunctionTemplate> templ = createRawTemplate();
2430     data->rawTemplateMap().add(&info, templ);
2431     return templ;
2432 }
2433
2434 v8::Persistent<v8::FunctionTemplate> ${className}::GetTemplate()
2435 {
2436     V8BindingPerIsolateData* data = V8BindingPerIsolateData::current();
2437     V8BindingPerIsolateData::TemplateMap::iterator result = data->templateMap().find(&info);
2438     if (result != data->templateMap().end())
2439         return result->second;
2440
2441     v8::HandleScope handleScope;
2442     v8::Persistent<v8::FunctionTemplate> templ =
2443         Configure${className}Template(GetRawTemplate());
2444     data->templateMap().add(&info, templ);
2445     return templ;
2446 }
2447
2448 bool ${className}::HasInstance(v8::Handle<v8::Value> value)
2449 {
2450     return GetRawTemplate()->HasInstance(value);
2451 }
2452
2453 END
2454
2455     if ($dataNode->extendedAttributes->{"ActiveDOMObject"}) {
2456         # MessagePort is handled like an active dom object even though it doesn't inherit
2457         # from ActiveDOMObject, so don't try to cast it to ActiveDOMObject.
2458         my $returnValue = $interfaceName eq "MessagePort" ? "0" : "toNative(object)";
2459         push(@implContent, <<END);
2460 ActiveDOMObject* ${className}::toActiveDOMObject(v8::Handle<v8::Object> object)
2461 {
2462     return ${returnValue};
2463 }      
2464 END
2465     }
2466
2467     if ($implClassName eq "DOMWindow") {
2468         push(@implContent, <<END);
2469 v8::Persistent<v8::ObjectTemplate> V8DOMWindow::GetShadowObjectTemplate()
2470 {
2471     static v8::Persistent<v8::ObjectTemplate> V8DOMWindowShadowObjectCache;
2472     if (V8DOMWindowShadowObjectCache.IsEmpty()) {
2473         V8DOMWindowShadowObjectCache = v8::Persistent<v8::ObjectTemplate>::New(v8::ObjectTemplate::New());
2474         ConfigureShadowObjectTemplate(V8DOMWindowShadowObjectCache);
2475     }
2476     return V8DOMWindowShadowObjectCache;
2477 }
2478 END
2479     }
2480
2481     GenerateToV8Converters($dataNode, $interfaceName, $className, $nativeType, $serializedAttribute);
2482
2483     push(@implContent, <<END);
2484
2485 void ${className}::derefObject(void* object)
2486 {
2487 END
2488
2489     if (IsRefPtrType($interfaceName)) {
2490         push(@implContent, <<END);
2491     static_cast<${nativeType}*>(object)->deref();
2492 END
2493     }
2494
2495     push(@implContent, <<END);
2496 }
2497
2498 } // namespace WebCore
2499 END
2500
2501     my $conditionalString = GenerateConditionalString($dataNode);
2502     push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
2503     
2504     # We've already added the header for this file in implFixedHeader, so remove
2505     # it from implIncludes to ensure we don't #include it twice.
2506     delete $implIncludes{"${className}.h"};
2507 }
2508
2509 sub GenerateHeaderContentHeader
2510 {
2511     my $dataNode = shift;
2512     my $className = "V8" . $dataNode->name;
2513     my $conditionalString = GenerateConditionalString($dataNode);
2514
2515     my @headerContentHeader = split("\r", $headerTemplate);
2516
2517     push(@headerContentHeader, "\n#if ${conditionalString}\n") if $conditionalString;
2518     push(@headerContentHeader, "\n#ifndef ${className}" . "_h");
2519     push(@headerContentHeader, "\n#define ${className}" . "_h\n\n");
2520     return @headerContentHeader;
2521 }
2522
2523 sub GenerateImplementationContentHeader
2524 {
2525     my $dataNode = shift;
2526     my $className = "V8" . $dataNode->name;
2527     my $conditionalString = GenerateConditionalString($dataNode);
2528
2529     my @implContentHeader = split("\r", $headerTemplate);
2530
2531     push(@implContentHeader, "\n#include \"config.h\"\n");
2532     push(@implContentHeader, "#include \"${className}.h\"\n\n");
2533     push(@implContentHeader, "#if ${conditionalString}\n\n") if $conditionalString;
2534     return @implContentHeader;
2535 }
2536
2537 sub GenerateCallbackHeader
2538 {
2539     my $object = shift;
2540     my $dataNode = shift;
2541
2542     my $interfaceName = $dataNode->name;
2543     my $className = "V8$interfaceName";
2544
2545
2546     # - Add default header template
2547     push(@headerContent, GenerateHeaderContentHeader($dataNode));
2548
2549     my @unsortedIncludes = ();
2550     push(@unsortedIncludes, "#include \"ActiveDOMCallback.h\"");
2551     push(@unsortedIncludes, "#include \"$interfaceName.h\"");
2552     push(@unsortedIncludes, "#include \"WorldContextHandle.h\"");
2553     push(@unsortedIncludes, "#include <v8.h>");
2554     push(@unsortedIncludes, "#include <wtf/Forward.h>");
2555     push(@headerContent, join("\n", sort @unsortedIncludes));
2556     
2557     push(@headerContent, "\n\nnamespace WebCore {\n\n");
2558     push(@headerContent, "class ScriptExecutionContext;\n\n");
2559     push(@headerContent, "class $className : public $interfaceName, public ActiveDOMCallback {\n");
2560
2561     push(@headerContent, <<END);
2562 public:
2563     static PassRefPtr<${className}> create(v8::Local<v8::Value> value, ScriptExecutionContext* context)
2564     {
2565         ASSERT(value->IsObject());
2566         ASSERT(context);
2567         return adoptRef(new ${className}(value->ToObject(), context));
2568     }
2569
2570     virtual ~${className}();
2571
2572 END
2573
2574     # Functions
2575     my $numFunctions = @{$dataNode->functions};
2576     if ($numFunctions > 0) {
2577         push(@headerContent, "    // Functions\n");
2578         foreach my $function (@{$dataNode->functions}) {
2579             my @params = @{$function->parameters};
2580             if (!$function->signature->extendedAttributes->{"Custom"} &&
2581                 !(GetNativeType($function->signature->type) eq "bool")) {
2582                     push(@headerContent, "    COMPILE_ASSERT(false)");
2583             }
2584
2585             push(@headerContent, "    virtual " . GetNativeTypeForCallbacks($function->signature->type) . " " . $function->signature->name . "(");
2586
2587             my @args = ();
2588             foreach my $param (@params) {
2589                 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $param->name);
2590             }
2591             push(@headerContent, join(", ", @args));
2592             push(@headerContent, ");\n");
2593         }
2594     }
2595
2596     push(@headerContent, <<END);
2597
2598 private:
2599     ${className}(v8::Local<v8::Object>, ScriptExecutionContext*);
2600
2601     v8::Persistent<v8::Object> m_callback;
2602     WorldContextHandle m_worldContext;
2603 };
2604
2605 END
2606
2607     push(@headerContent, "}\n\n");
2608     push(@headerContent, "#endif // $className" . "_h\n\n");
2609
2610     my $conditionalString = GenerateConditionalString($dataNode);
2611     push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString;
2612 }
2613
2614 sub GenerateCallbackImplementation
2615 {
2616     my $object = shift;
2617     my $dataNode = shift;
2618     my $interfaceName = $dataNode->name;
2619     my $className = "V8$interfaceName";
2620
2621     # - Add default header template
2622     push(@implFixedHeader, GenerateImplementationContentHeader($dataNode));
2623          
2624     AddToImplIncludes("ScriptExecutionContext.h");
2625     AddToImplIncludes("V8Binding.h");
2626     AddToImplIncludes("V8CustomVoidCallback.h");
2627     AddToImplIncludes("V8Proxy.h");
2628
2629     push(@implContent, "#include <wtf/Assertions.h>\n\n");
2630     push(@implContent, "namespace WebCore {\n\n");
2631     push(@implContent, <<END);
2632 ${className}::${className}(v8::Local<v8::Object> callback, ScriptExecutionContext* context)
2633     : ActiveDOMCallback(context)
2634     , m_callback(v8::Persistent<v8::Object>::New(callback))
2635     , m_worldContext(UseCurrentWorld)
2636 {
2637 }
2638
2639 ${className}::~${className}()
2640 {
2641     m_callback.Dispose();
2642 }
2643
2644 END
2645
2646     # Functions
2647     my $numFunctions = @{$dataNode->functions};
2648     if ($numFunctions > 0) {
2649         push(@implContent, "// Functions\n");
2650         foreach my $function (@{$dataNode->functions}) {
2651             my @params = @{$function->parameters};
2652             if ($function->signature->extendedAttributes->{"Custom"} ||
2653                 !(GetNativeTypeForCallbacks($function->signature->type) eq "bool")) {
2654                 next;
2655             }
2656
2657             AddIncludesForType($function->signature->type);
2658             push(@implContent, "\n" . GetNativeTypeForCallbacks($function->signature->type) . " ${className}::" . $function->signature->name . "(");
2659
2660             my @args = ();
2661             foreach my $param (@params) {
2662                 AddIncludesForType($param->type);
2663                 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $param->name);
2664             }
2665             push(@implContent, join(", ", @args));
2666
2667             push(@implContent, ")\n");
2668             push(@implContent, "{\n");
2669             push(@implContent, "    if (!canInvokeCallback())\n");
2670             push(@implContent, "        return true;\n\n");
2671             push(@implContent, "    v8::HandleScope handleScope;\n\n");
2672             push(@implContent, "    v8::Handle<v8::Context> v8Context = toV8Context(scriptExecutionContext(), m_worldContext);\n");
2673             push(@implContent, "    if (v8Context.IsEmpty())\n");
2674             push(@implContent, "        return true;\n\n");
2675             push(@implContent, "    v8::Context::Scope scope(v8Context);\n\n");
2676
2677             @args = ();
2678             foreach my $param (@params) {
2679                 my $paramName = $param->name;
2680                 push(@implContent, "    v8::Handle<v8::Value> ${paramName}Handle = " . NativeToJSValue($param, $paramName) . ";\n");
2681                 push(@implContent, "    if (${paramName}Handle.IsEmpty()) {\n");
2682                 push(@implContent, "        CRASH();\n");
2683                 push(@implContent, "        return true;\n");
2684                 push(@implContent, "    }\n");
2685                 push(@args, "        ${paramName}Handle");
2686             }
2687
2688             if (scalar(@args) > 0) {
2689                 push(@implContent, "\n    v8::Handle<v8::Value> argv[] = {\n");
2690                 push(@implContent, join(",\n", @args));
2691                 push(@implContent, "\n    };\n\n");
2692             } else {
2693                 push(@implContent, "\n    v8::Handle<v8::Value> *argv = 0;\n\n");
2694             }
2695             push(@implContent, "    bool callbackReturnValue = false;\n");
2696             push(@implContent, "    return !invokeCallback(m_callback, " . scalar(@params) . ", argv, callbackReturnValue, scriptExecutionContext());\n");
2697             push(@implContent, "}\n");
2698         }
2699     }
2700
2701     push(@implContent, "\n} // namespace WebCore\n\n");
2702
2703     my $conditionalString = GenerateConditionalString($dataNode);
2704     push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
2705 }
2706
2707 sub GenerateToV8Converters
2708 {
2709     my $dataNode = shift;
2710     my $interfaceName = shift;
2711     my $className = shift;
2712     my $nativeType = shift;
2713     my $serializedAttribute = shift;
2714
2715     my $domMapFunction = GetDomMapFunction($dataNode, $interfaceName);
2716     my $forceNewObjectInput = IsDOMNodeType($interfaceName) ? ", bool forceNewObject" : "";
2717     my $forceNewObjectCall = IsDOMNodeType($interfaceName) ? ", forceNewObject" : "";
2718
2719     push(@implContent, <<END);
2720
2721 v8::Handle<v8::Object> ${className}::wrapSlow(${nativeType}* impl)
2722 {
2723     v8::Handle<v8::Object> wrapper;
2724     V8Proxy* proxy = 0;
2725 END
2726
2727     if (IsNodeSubType($dataNode)) {
2728         push(@implContent, <<END);
2729     if (impl->document()) {
2730         proxy = V8Proxy::retrieve(impl->document()->frame());
2731         if (proxy && static_cast<Node*>(impl->document()) == static_cast<Node*>(impl)) {
2732             if (proxy->windowShell()->context().IsEmpty() && proxy->windowShell()->initContextIfNeeded()) {
2733                 // initContextIfNeeded may have created a wrapper for the object, retry from the start.
2734                 return ${className}::wrap(impl);
2735             }
2736         }
2737     }
2738
2739 END
2740     }
2741
2742     # FIXME: We need a better way of recovering the correct prototype chain
2743     # for every sort of object. For now, we special-case cross-origin visible
2744     # objects (i.e., those with CheckDomainSecurity).
2745     if (IsVisibleAcrossOrigins($dataNode)) {
2746         push(@implContent, <<END);
2747     if (impl->frame()) {
2748         proxy = V8Proxy::retrieve(impl->frame());
2749         if (proxy)
2750             proxy->windowShell()->initContextIfNeeded();
2751     }
2752 END
2753     }
2754
2755     if (IsNodeSubType($dataNode) || IsVisibleAcrossOrigins($dataNode)) {
2756         push(@implContent, <<END);
2757
2758     v8::Handle<v8::Context> context;
2759     if (proxy)
2760         context = proxy->context();
2761
2762     // Enter the node's context and create the wrapper in that context.
2763     if (!context.IsEmpty())
2764         context->Enter();
2765 END
2766     }
2767
2768     push(@implContent, <<END);
2769     wrapper = V8DOMWrapper::instantiateV8Object(proxy, &info, impl);
2770 END
2771     if (IsNodeSubType($dataNode) || IsVisibleAcrossOrigins($dataNode)) {
2772         push(@implContent, <<END);
2773     // Exit the node's context if it was entered.
2774     if (!context.IsEmpty())
2775         context->Exit();
2776 END
2777     }
2778
2779     push(@implContent, <<END);
2780     if (wrapper.IsEmpty())
2781         return wrapper;
2782 END
2783     push(@implContent, "\n    impl->ref();\n") if IsRefPtrType($interfaceName);
2784
2785     # Eagerly deserialize attributes of type SerializedScriptValue
2786     # while we're in the right context.
2787     if ($serializedAttribute) {
2788         die "Attribute of type SerializedScriptValue expected" if $serializedAttribute->signature->type ne "SerializedScriptValue";
2789         my $attrName = $serializedAttribute->signature->name;
2790         my $attrAttr = "v8::DontDelete";
2791         if ($serializedAttribute->type =~ /^readonly/) {
2792             $attrAttr .= " | v8::ReadOnly";
2793         }
2794         $attrAttr = "static_cast<v8::PropertyAttribute>($attrAttr)";
2795         my $getterFunc = $codeGenerator->WK_lcfirst($attrName);
2796         push(@implContent, <<END);
2797     SerializedScriptValue::deserializeAndSetProperty(wrapper, "${attrName}", ${attrAttr}, impl->${getterFunc}());
2798 END
2799     }
2800
2801     push(@implContent, <<END);
2802     v8::Persistent<v8::Object> wrapperHandle = v8::Persistent<v8::Object>::New(wrapper);
2803
2804     if (!hasDependentLifetime)
2805         wrapperHandle.MarkIndependent();
2806 END
2807     if (IsNodeSubType($dataNode)) {
2808         push(@implContent, <<END);
2809     wrapperHandle.SetWrapperClassId(v8DOMSubtreeClassId);
2810 END
2811     }    
2812     push(@implContent, <<END);
2813     ${domMapFunction}.set(impl, wrapperHandle);
2814 END
2815
2816     push(@implContent, <<END);
2817     return wrapper;
2818 }
2819 END
2820 }
2821
2822 sub HasCustomToV8Implementation {
2823     # FIXME: This subroutine is lame. Probably should be an .idl attribute (CustomToV8)?
2824     my $dataNode = shift;
2825     my $interfaceName = shift;
2826
2827     # We generate a custom converter (but JSC doesn't) for the following:
2828     return 1 if $interfaceName eq "CSSStyleSheet";
2829     return 1 if $interfaceName eq "CanvasPixelArray";
2830     return 1 if $interfaceName eq "DOMStringMap";
2831     return 1 if $interfaceName eq "DOMWindow";
2832     return 1 if $interfaceName eq "DOMTokenList";
2833     return 1 if $interfaceName eq "Element";
2834     return 1 if $interfaceName eq "HTMLDocument";
2835     return 1 if $interfaceName eq "HTMLElement";
2836     return 1 if $interfaceName eq "Location";
2837     return 1 if $interfaceName eq "NamedNodeMap";
2838     return 1 if $interfaceName eq "SVGDocument";
2839     return 1 if $interfaceName eq "SVGElement";
2840     return 1 if $interfaceName eq "ScriptProfile";
2841     return 1 if $interfaceName eq "ScriptProfileNode";
2842     return 1 if $interfaceName eq "WorkerContext";
2843     # We don't generate a custom converter (but JSC does) for the following:
2844     return 0 if $interfaceName eq "AbstractWorker";
2845     return 0 if $interfaceName eq "CanvasRenderingContext";
2846     return 0 if $interfaceName eq "SVGElementInstance";
2847     return 0 if $interfaceName eq "NodeList";
2848     return 0 if $interfaceName eq "CSSRuleList";
2849     return 0 if $interfaceName eq "CSSStyleDeclaration";
2850     return 0 if $interfaceName eq "MediaList";
2851     return 0 if $interfaceName eq "StyleSheetList";
2852     return 0 if $interfaceName eq "DOMImplementation";
2853     return 0 if $interfaceName eq "DOMStringMap";
2854     return 0 if $interfaceName eq "DOMTokenList";
2855
2856     # For everything else, do what JSC does.
2857     return $dataNode->extendedAttributes->{"CustomToJS"};
2858 }
2859
2860 sub GetDomMapFunction
2861 {
2862     my $dataNode = shift;
2863     my $type = shift;
2864     return "getDOMSVGElementInstanceMap()" if $type eq "SVGElementInstance";
2865     return "getDOMNodeMap()" if (IsNodeSubType($dataNode));
2866     return "getActiveDOMObjectMap()" if $dataNode->extendedAttributes->{"ActiveDOMObject"};
2867     return "getDOMObjectMap()";
2868 }
2869
2870 sub GetNativeTypeForConversions
2871 {
2872     my $dataNode = shift;
2873     my $type = shift;
2874
2875     $type = $codeGenerator->GetSVGTypeNeedingTearOff($type) if $codeGenerator->IsSVGTypeNeedingTearOff($type); 
2876     return $type;
2877 }
2878
2879 sub GenerateFunctionCallString()
2880 {
2881     my $function = shift;
2882     my $numberOfParameters = shift;
2883     my $indent = shift;
2884     my $implClassName = shift;
2885
2886     my $name = $function->signature->name;
2887     my $returnType = GetTypeFromSignature($function->signature);
2888     my $nativeReturnType = GetNativeType($returnType, 0);
2889     my $result = "";
2890
2891     my $isSVGTearOffType = ($codeGenerator->IsSVGTypeNeedingTearOff($returnType) and not $implClassName =~ /List$/);
2892     $nativeReturnType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($returnType) if $isSVGTearOffType;
2893
2894     if ($function->signature->extendedAttributes->{"v8implname"}) {
2895         $name = $function->signature->extendedAttributes->{"v8implname"};
2896     }
2897
2898     if ($function->signature->extendedAttributes->{"ImplementationFunction"}) {
2899         $name = $function->signature->extendedAttributes->{"ImplementationFunction"};
2900     }
2901
2902     my $functionString = "imp->${name}(";
2903     if ($function->signature->extendedAttributes->{"ClassMethod"}) {
2904         $functionString = "${implClassName}::${name}(";
2905     }
2906
2907     my $index = 0;
2908     my $hasScriptState = 0;
2909
2910     my $callWith = $function->signature->extendedAttributes->{"CallWith"};
2911     if ($callWith) {
2912         my $callWithArg = "COMPILE_ASSERT(false)";
2913         if ($callWith eq "DynamicFrame") {
2914             $result .= $indent . "Frame* enteredFrame = V8Proxy::retrieveFrameForEnteredContext();\n";
2915             $result .= $indent . "if (!enteredFrame)\n";
2916             $result .= $indent . "    return v8::Undefined();\n";
2917             $callWithArg = "enteredFrame";
2918         } elsif ($callWith eq "ScriptState") {
2919             $result .= $indent . "EmptyScriptState state;\n";
2920             $callWithArg = "&state";
2921             $hasScriptState = 1;
2922         } elsif ($callWith eq "ScriptExecutionContext") {
2923             $result .= $indent . "ScriptExecutionContext* scriptContext = getScriptExecutionContext();\n";
2924             $result .= $indent . "if (!scriptContext)\n";
2925             $result .= $indent . "    return v8::Undefined();\n";
2926             $callWithArg = "scriptContext";
2927         }
2928         $functionString .= ", " if $index;
2929         $functionString .= $callWithArg;
2930         $index++;
2931         $numberOfParameters++
2932     }
2933
2934     foreach my $parameter (@{$function->parameters}) {
2935         if ($index eq $numberOfParameters) {
2936             last;
2937         }
2938         $functionString .= ", " if $index;
2939         my $paramName = $parameter->name;
2940         my $paramType = $parameter->type;
2941
2942         if ($parameter->type eq "NodeFilter" || $parameter->type eq "XPathNSResolver") {
2943             $functionString .= "$paramName.get()";
2944         } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($parameter->type) and not $implClassName =~ /List$/) {
2945             $functionString .= "$paramName->propertyReference()";
2946             $result .= $indent . "if (!$paramName) {\n";
2947             $result .= $indent . "    V8Proxy::setDOMException(WebCore::TYPE_MISMATCH_ERR);\n";
2948             $result .= $indent . "    return v8::Handle<v8::Value>();\n";
2949             $result .= $indent . "}\n";
2950         } elsif ($parameter->type eq "SVGMatrix" and $implClassName eq "SVGTransformList") {
2951             $functionString .= "$paramName.get()";
2952         } else {
2953             $functionString .= $paramName;
2954         }
2955         $index++;
2956     }
2957
2958     if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
2959         $functionString .= ", " if $index;
2960         $functionString .= "scriptArguments, callStack";
2961         $index += 2;
2962     }
2963
2964     if ($function->signature->extendedAttributes->{"NeedsUserGestureCheck"}) {
2965         $functionString .= ", " if $index;
2966         $functionString .= "ScriptController::processingUserGesture()";
2967         $index++;
2968         AddToImplIncludes("ScriptController.h");
2969     }
2970
2971     if (@{$function->raisesExceptions}) {
2972         $functionString .= ", " if $index;
2973         $functionString .= "ec";
2974         $index++;
2975     }
2976     $functionString .= ")";
2977
2978     my $return = "result";
2979     my $returnIsRef = IsRefPtrType($returnType);
2980
2981     if ($returnType eq "void") {
2982         $result .= $indent . "$functionString;\n";
2983     } elsif ($hasScriptState or @{$function->raisesExceptions}) {
2984         $result .= $indent . $nativeReturnType . " result = $functionString;\n";
2985     } else {
2986         # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
2987         $return = $functionString;
2988         $returnIsRef = 0;
2989     
2990         if ($implClassName eq "SVGTransformList" and IsRefPtrType($returnType)) {
2991             $return = "WTF::getPtr(" . $return . ")";
2992         }
2993     }
2994
2995     if (@{$function->raisesExceptions}) {
2996         $result .= $indent . "if (UNLIKELY(ec))\n";
2997         $result .= $indent . "    goto fail;\n";
2998     }
2999
3000     if ($hasScriptState) {
3001         $result .= $indent . "if (state.hadException())\n";
3002         $result .= $indent . "    return throwError(state.exception());\n"
3003     }
3004
3005     if ($isSVGTearOffType) {
3006         AddToImplIncludes("V8$returnType.h");
3007         AddToImplIncludes("SVGPropertyTearOff.h");
3008         my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($returnType);
3009         $result .= $indent . "return toV8(WTF::getPtr(${svgNativeType}::create($return)));\n";
3010         return $result;
3011     }
3012
3013     # If the implementing class is a POD type, commit changes
3014     if ($codeGenerator->IsSVGTypeNeedingTearOff($implClassName) and not $implClassName =~ /List$/) {
3015         $result .= $indent . "wrapper->commitChange();\n";
3016     }
3017
3018     $return .= ".release()" if ($returnIsRef);
3019     $result .= $indent . ReturnNativeToJSValue($function->signature, $return, $indent) . ";\n";
3020
3021     return $result;
3022 }
3023
3024
3025 sub GetTypeFromSignature
3026 {
3027     my $signature = shift;
3028
3029     return $codeGenerator->StripModule($signature->type);
3030 }
3031
3032
3033 sub GetNativeTypeFromSignature
3034 {
3035     my $signature = shift;
3036     my $parameterIndex = shift;
3037
3038     my $type = GetTypeFromSignature($signature);
3039
3040     if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) {
3041         # Special-case index arguments because we need to check that they aren't < 0.
3042         return "int";
3043     }
3044
3045     $type = GetNativeType($type, $parameterIndex >= 0 ? 1 : 0);
3046
3047     if ($parameterIndex >= 0 && $type eq "V8Parameter") {
3048         my $mode = "";
3049         if ($signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"}) {
3050             $mode = "WithUndefinedOrNullCheck";
3051         } elsif ($signature->extendedAttributes->{"ConvertNullToNullString"} || $signature->extendedAttributes->{"Reflect"}) {
3052             $mode = "WithNullCheck";
3053         }
3054         $type .= "<$mode>";
3055     }
3056
3057     return $type;
3058 }
3059
3060 sub IsRefPtrType
3061 {
3062     my $type = shift;
3063
3064     return 0 if $type eq "boolean";
3065     return 0 if $type eq "float";
3066     return 0 if $type eq "int";
3067     return 0 if $type eq "Date";
3068     return 0 if $type eq "DOMString";
3069     return 0 if $type eq "double";
3070     return 0 if $type eq "short";
3071     return 0 if $type eq "long";
3072     return 0 if $type eq "unsigned";
3073     return 0 if $type eq "unsigned long";
3074     return 0 if $type eq "unsigned short";
3075
3076     return 1;
3077 }
3078
3079 sub GetNativeType
3080 {
3081     my $type = shift;
3082     my $isParameter = shift;
3083
3084     my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($type);
3085     if ($svgNativeType) {
3086         if ($svgNativeType =~ /List$/) {
3087             return "${svgNativeType}*";
3088         } else {
3089             return "RefPtr<${svgNativeType} >";
3090         }
3091     }
3092
3093     if ($type eq "float" or $type eq "double") {
3094         return $type;
3095     }
3096
3097     return "V8Parameter" if ($type eq "DOMString" or $type eq "DOMUserData") and $isParameter;
3098     return "int" if $type eq "int";
3099     return "int" if $type eq "short" or $type eq "unsigned short";
3100     return "unsigned" if $type eq "unsigned long";
3101     return "int" if $type eq "long";
3102     return "long long" if $type eq "long long";
3103     return "unsigned long long" if $type eq "unsigned long long";
3104     return "bool" if $type eq "boolean";
3105     return "String" if $type eq "DOMString";
3106     return "Range::CompareHow" if $type eq "CompareHow";
3107     return "DOMTimeStamp" if $type eq "DOMTimeStamp";
3108     return "unsigned" if $type eq "unsigned int";
3109     return "Node*" if $type eq "EventTarget" and $isParameter;
3110     return "double" if $type eq "Date";
3111     return "ScriptValue" if $type eq "DOMObject";
3112     return "OptionsObject" if $type eq "OptionsObject";
3113
3114     return "String" if $type eq "DOMUserData";  # FIXME: Temporary hack?
3115
3116     # temporary hack
3117     return "RefPtr<NodeFilter>" if $type eq "NodeFilter";
3118
3119     return "RefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValue";
3120
3121     return "RefPtr<IDBKey>" if $type eq "IDBKey";
3122
3123     # necessary as resolvers could be constructed on fly.
3124     return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver";
3125
3126     return "RefPtr<${type}>" if IsRefPtrType($type) and not $isParameter;
3127
3128     return "RefPtr<MediaQueryListListener>" if $type eq "MediaQueryListListener";
3129
3130     return "RefPtr<DOMStringList>" if $type eq "DOMStringList";
3131
3132     # Default, assume native type is a pointer with same type name as idl type
3133     return "${type}*";
3134 }
3135
3136 sub GetNativeTypeForCallbacks
3137 {
3138     my $type = shift;
3139     return "const String&" if $type eq "DOMString";
3140
3141     # Callbacks use raw pointers, so pass isParameter = 1
3142     return GetNativeType($type, 1);
3143 }
3144
3145 sub TranslateParameter
3146 {
3147     my $signature = shift;
3148
3149     # The IDL uses some pseudo-types which don't really exist.
3150     if ($signature->type eq "TimeoutHandler") {
3151       $signature->type("DOMString");
3152     }
3153 }
3154
3155 sub TypeCanFailConversion
3156 {
3157     my $signature = shift;
3158
3159     my $type = GetTypeFromSignature($signature);
3160
3161     AddToImplIncludes("ExceptionCode.h") if $type eq "Attr";
3162     return 1 if $type eq "Attr";
3163     return 1 if $type eq "VoidCallback";
3164     return 1 if $type eq "IDBKey";
3165     return 0;
3166 }
3167
3168 sub JSValueToNative
3169 {
3170     my $signature = shift;
3171     my $value = shift;
3172
3173     my $type = GetTypeFromSignature($signature);
3174
3175     return "$value" if $type eq "JSObject";
3176     return "$value->BooleanValue()" if $type eq "boolean";
3177     return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $type eq "double";
3178
3179     return "toInt32($value)" if $type eq "long" or $type eq "short";
3180     return "toUInt32($value)" if $type eq "unsigned long" or $type eq "unsigned short";
3181     return "toInt64($value)" if $type eq "unsigned long long" or $type eq "long long";
3182     return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "CompareHow";
3183     return "toWebCoreDate($value)" if $type eq "Date";
3184     return "v8ValueToWebCoreDOMStringList($value)" if $type eq "DOMStringList";
3185
3186     if ($type eq "DOMString" or $type eq "DOMUserData") {
3187         return $value;
3188     }
3189
3190     die "Unexpected SerializedScriptValue" if $type eq "SerializedScriptValue";
3191
3192     if ($type eq "IDBKey") {
3193         AddToImplIncludes("IDBBindingUtilities.h");
3194         AddToImplIncludes("IDBKey.h");
3195         return "createIDBKeyFromValue($value)";
3196     }
3197
3198     if ($type eq "OptionsObject") {
3199         AddToImplIncludes("OptionsObject.h");
3200         return $value;
3201     }
3202
3203     if ($type eq "DOMObject") {
3204         AddToImplIncludes("ScriptValue.h");
3205         return "ScriptValue($value)";
3206     }
3207
3208     if ($type eq "NodeFilter") {
3209         return "V8DOMWrapper::wrapNativeNodeFilter($value)";
3210     }
3211
3212     if ($type eq "MediaQueryListListener") {
3213         AddToImplIncludes("MediaQueryListListener.h");
3214         return "MediaQueryListListener::create(" . $value . ")";
3215     }
3216
3217     # Default, assume autogenerated type conversion routines
3218     if ($type eq "EventTarget") {
3219         AddToImplIncludes("V8Node.h");
3220
3221         # EventTarget is not in DOM hierarchy, but all Nodes are EventTarget.
3222         return "V8Node::HasInstance($value) ? V8Node::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
3223     }
3224
3225     if ($type eq "XPathNSResolver") {
3226         return "V8DOMWrapper::getXPathNSResolver($value)";
3227     }
3228
3229     AddIncludesForType($type);
3230
3231     if (IsDOMNodeType($type)) {
3232         AddToImplIncludes("V8${type}.h");
3233
3234         # Perform type checks on the parameter, if it is expected Node type,
3235         # return NULL.
3236         return "V8${type}::HasInstance($value) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
3237     } else {
3238         AddToImplIncludes("V8$type.h");
3239
3240         # Perform type checks on the parameter, if it is expected Node type,
3241         # return NULL.
3242         return "V8${type}::HasInstance($value) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
3243     }
3244 }
3245
3246 sub GetV8HeaderName
3247 {
3248     my $type = shift;
3249     return "V8Event.h" if $type eq "DOMTimeStamp";
3250     return "EventListener.h" if $type eq "EventListener";
3251     return "EventTarget.h" if $type eq "EventTarget";
3252     return "SerializedScriptValue.h" if $type eq "SerializedScriptValue";
3253     return "ScriptValue.h" if $type eq "DOMObject";
3254     return "V8${type}.h";
3255 }
3256
3257 sub CreateCustomSignature
3258 {
3259     my $function = shift;
3260     my $count = @{$function->parameters};
3261     my $name = $function->signature->name;
3262     my $result = "    const int ${name}Argc = ${count};\n" .
3263       "    v8::Handle<v8::FunctionTemplate> ${name}Argv[${name}Argc] = { ";
3264     my $first = 1;
3265     foreach my $parameter (@{$function->parameters}) {
3266         if ($first) { $first = 0; }
3267         else { $result .= ", "; }
3268         if (IsWrapperType($parameter->type)) {
3269             if ($parameter->type eq "XPathNSResolver") {
3270                 # Special case for XPathNSResolver.  All other browsers accepts a callable,
3271                 # so, even though it's against IDL, accept objects here.
3272                 $result .= "v8::Handle<v8::FunctionTemplate>()";
3273             } else {
3274                 my $type = $parameter->type;
3275                 my $header = GetV8HeaderName($type);
3276                 AddToImplIncludes($header);
3277                 $result .= "V8${type}::GetRawTemplate()";
3278             }
3279         } else {
3280             $result .= "v8::Handle<v8::FunctionTemplate>()";
3281         }
3282     }
3283     $result .= " };\n";
3284     $result .= "    v8::Handle<v8::Signature> ${name}Signature = v8::Signature::New(desc, ${name}Argc, ${name}Argv);\n";
3285     return $result;
3286 }
3287
3288
3289 sub RequiresCustomSignature
3290 {
3291     my $function = shift;
3292     # No signature needed for Custom function
3293     if ($function->signature->extendedAttributes->{"Custom"} ||
3294         $function->signature->extendedAttributes->{"V8Custom"}) {
3295         return 0;
3296     }
3297     # No signature needed for overloaded function
3298     if (@{$function->{overloads}} > 1) {
3299         return 0;
3300     }
3301     # Type checking is performed in the generated code
3302     if ($function->signature->extendedAttributes->{"StrictTypeChecking"}) {
3303       return 0;
3304     }
3305     foreach my $parameter (@{$function->parameters}) {
3306         my $optional = $parameter->extendedAttributes->{"Optional"};
3307         if (($optional && $optional ne "CallWithDefaultValue" && $optional ne "CallWithNullValue") || $parameter->extendedAttributes->{"Callback"}) {
3308             return 0;
3309         }
3310     }
3311
3312     foreach my $parameter (@{$function->parameters}) {
3313         if (IsWrapperType($parameter->type)) {
3314             return 1;
3315         }
3316     }
3317     return 0;
3318 }
3319
3320
3321 # FIXME: Sort this array.
3322 my %non_wrapper_types = (
3323     'float' => 1,
3324     'double' => 1,
3325     'int' => 1,
3326     'unsigned int' => 1,
3327     'short' => 1,
3328     'unsigned short' => 1,
3329     'long' => 1,
3330     'unsigned long' => 1,
3331     'boolean' => 1,
3332     'long long' => 1,
3333     'unsigned long long' => 1,
3334     'DOMString' => 1,
3335     'CompareHow' => 1,
3336     'SerializedScriptValue' => 1,
3337     'DOMTimeStamp' => 1,
3338     'JSObject' => 1,
3339     'DOMObject' => 1,
3340     'EventTarget' => 1,
3341     'NodeFilter' => 1,
3342     'EventListener' => 1,
3343     'IDBKey' => 1,
3344     'OptionsObject' => 1,
3345     'Date' => 1,
3346     'MediaQueryListListener' => 1
3347 );
3348
3349
3350 sub IsWrapperType
3351 {
3352     my $type = $codeGenerator->StripModule(shift);
3353     return !($non_wrapper_types{$type});
3354 }
3355
3356 sub IsDOMNodeType
3357 {
3358     my $type = shift;
3359
3360     return 1 if $type eq 'Attr';
3361     return 1 if $type eq 'CDATASection';
3362     return 1 if $type eq 'Comment';
3363     return 1 if $type eq 'Document';
3364     return 1 if $type eq 'DocumentFragment';
3365     return 1 if $type eq 'DocumentType';
3366     return 1 if $type eq 'Element';
3367     return 1 if $type eq 'EntityReference';
3368     return 1 if $type eq 'HTMLCanvasElement';
3369     return 1 if $type eq 'HTMLDocument';
3370     return 1 if $type eq 'HTMLElement';
3371     return 1 if $type eq 'HTMLUnknownElement';
3372     return 1 if $type eq 'HTMLFormElement';
3373     return 1 if $type eq 'HTMLTableCaptionElement';
3374     return 1 if $type eq 'HTMLTableSectionElement';
3375     return 1 if $type eq 'Node';
3376     return 1 if $type eq 'ProcessingInstruction';
3377     return 1 if $type eq 'SVGElement';
3378     return 1 if $type eq 'SVGDocument';
3379     return 1 if $type eq 'SVGSVGElement';
3380     return 1 if $type eq 'SVGUseElement';
3381     return 1 if $type eq 'Text';
3382
3383     return 0;
3384 }
3385
3386
3387 sub NativeToJSValue
3388 {
3389     my $signature = shift;
3390     my $value = shift;
3391     my $indent = shift;
3392     my $type = GetTypeFromSignature($signature);
3393
3394     return "v8Boolean($value)" if $type eq "boolean";
3395     return "v8::Handle<v8::Value>()" if $type eq "void";     # equivalent to v8::Undefined()
3396
3397     # HTML5 says that unsigned reflected attributes should be in the range
3398     # [0, 2^31). When a value isn't in this range, a default value (or 0)
3399     # should be returned instead.
3400     if ($signature->extendedAttributes->{"Reflect"} and ($type eq "unsigned long" or $type eq "unsigned short")) {
3401         $value =~ s/getUnsignedIntegralAttribute/getIntegralAttribute/g;
3402         return "v8::Integer::NewFromUnsigned(std::max(0, " . $value . "))";
3403     }
3404
3405     # For all the types where we use 'int' as the representation type,
3406     # we use Integer::New which has a fast Smi conversion check.
3407     my $nativeType = GetNativeType($type);
3408     return "v8::Integer::New($value)" if $nativeType eq "int";
3409     return "v8::Integer::NewFromUnsigned($value)" if $nativeType eq "unsigned";
3410
3411     return "v8DateOrNull($value)" if $type eq "Date";
3412     # long long and unsigned long long are not representable in ECMAScript.
3413     return "v8::Number::New(static_cast<double>($value))" if $type eq "long long" or $type eq "unsigned long long" or $type eq "DOMTimeStamp";
3414     return "v8::Number::New($value)" if $codeGenerator->IsPrimitiveType($type);
3415     return "$value.v8Value()" if $nativeType eq "ScriptValue";
3416
3417     if ($codeGenerator->IsStringType($type)) {
3418         my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"};
3419         if (defined $conv) {
3420             return "v8StringOrNull($value)" if $conv eq "Null";
3421             return "v8StringOrUndefined($value)" if $conv eq "Undefined";
3422             return "v8StringOrFalse($value)" if $conv eq "False";
3423
3424             die "Unknown value for ConvertNullStringTo extended attribute";
3425         }
3426         $conv = $signature->extendedAttributes->{"ConvertScriptString"};
3427         return "v8StringOrNull($value)" if $conv;
3428         return "v8String($value)";
3429     }
3430
3431     AddIncludesForType($type);
3432
3433     # special case for non-DOM node interfaces
3434     if (IsDOMNodeType($type)) {
3435         return "toV8(${value}" . ($signature->extendedAttributes->{"ReturnsNew"} ? ", true)" : ")");
3436     }
3437
3438     if ($type eq "EventTarget") {
3439         return "V8DOMWrapper::convertEventTargetToV8Object($value)";
3440     }
3441
3442     if ($type eq "EventListener") {
3443         AddToImplIncludes("V8AbstractEventListener.h");
3444         return "${value} ? v8::Handle<v8::Value>(static_cast<V8AbstractEventListener*>(${value})->getListenerObject(imp->scriptExecutionContext())) : v8::Handle<v8::Value>(v8::Null())";
3445     }
3446
3447     if ($type eq "SerializedScriptValue") {
3448         AddToImplIncludes("$type.h");
3449         return "$value->deserialize()";
3450     }
3451
3452     AddToImplIncludes("wtf/RefCounted.h");
3453     AddToImplIncludes("wtf/RefPtr.h");
3454     AddToImplIncludes("wtf/GetPtr.h");
3455
3456     return "toV8($value)";
3457 }
3458
3459 sub ReturnNativeToJSValue
3460 {
3461     return "return " . NativeToJSValue(@_);
3462 }
3463
3464 # Internal helper
3465 sub WriteData
3466 {
3467     if (defined($IMPL)) {
3468         # Write content to file.
3469         print $IMPL @implContentHeader;
3470
3471         print $IMPL @implFixedHeader;
3472
3473         my @includes = ();
3474         my %implIncludeConditions = ();
3475         foreach my $include (keys %implIncludes) {
3476             my $condition = $implIncludes{$include};
3477             my $checkType = $include;
3478             $checkType =~ s/\.h//;
3479             next if $codeGenerator->IsSVGAnimatedType($checkType);
3480
3481             if ($include =~ /wtf/) {
3482                 $include = "\<$include\>";
3483             } else {
3484                 $include = "\"$include\"";
3485             }
3486
3487             if ($condition eq 1) {
3488                 push @includes, $include;
3489             } else {
3490                 push @{$implIncludeConditions{$condition}}, $include;
3491             }
3492         }
3493         foreach my $include (sort @includes) {
3494             print $IMPL "#include $include\n";
3495         }
3496         foreach my $condition (sort keys %implIncludeConditions) {
3497             print $IMPL "\n#if " . GenerateConditionalStringFromAttributeValue($condition) . "\n";
3498             foreach my $include (sort @{$implIncludeConditions{$condition}}) {
3499                 print $IMPL "#include $include\n";
3500             }
3501             print $IMPL "#endif\n";
3502         }
3503
3504         print $IMPL "\n";
3505         print $IMPL @implContentDecls;
3506         print $IMPL @implContent;
3507         close($IMPL);
3508         undef($IMPL);
3509
3510         %implIncludes = ();
3511         @implFixedHeader = ();
3512         @implHeaderContent = ();
3513         @implContentDecls = ();
3514         @implContent = ();
3515     }
3516
3517     if (defined($HEADER)) {
3518         # Write content to file.
3519         print $HEADER @headerContent;
3520         close($HEADER);
3521         undef($HEADER);
3522
3523         @headerContent = ();
3524     }
3525 }
3526
3527 sub GetVisibleInterfaceName
3528 {
3529     my $interfaceName = shift;
3530
3531     return "DOMException" if $interfaceName eq "DOMCoreException";
3532     return "FormData" if $interfaceName eq "DOMFormData";
3533     return $interfaceName;
3534 }
3535
3536 sub GetCallbackClassName
3537 {
3538     my $interfaceName = shift;
3539
3540     return "V8CustomVoidCallback" if $interfaceName eq "VoidCallback";
3541     return "V8$interfaceName";
3542 }
3543
3544 sub ConvertToV8Parameter
3545 {
3546     my $signature = shift;
3547     my $nativeType = shift;
3548     my $variableName = shift;
3549     my $value = shift;
3550     my $suffix = shift;
3551
3552     die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8Parameter/;
3553     if ($signature->type eq "DOMString") {
3554         AddToImplIncludes("V8BindingMacros.h");
3555         my $macro = "STRING_TO_V8PARAMETER_EXCEPTION_BLOCK";
3556         $macro .= "_$suffix" if $suffix;
3557         return "$macro($nativeType, $variableName, $value);"
3558     } else {
3559         # Don't know how to properly check for conversion exceptions when $parameter->type is "DOMUserData"
3560         return "$nativeType $variableName($value, true);";
3561     }
3562 }
3563
3564 # Returns the RuntimeEnabledFeatures function name that is hooked up to check if a method/attribute is enabled.
3565 sub GetRuntimeEnableFunctionName
3566 {
3567     my $signature = shift;
3568
3569     # If a parameter is given (e.g. "EnabledAtRuntime=FeatureName") return the RuntimeEnabledFeatures::{FeatureName}Enabled() method.
3570     return "RuntimeEnabledFeatures::" . $codeGenerator->WK_lcfirst($signature->extendedAttributes->{"EnabledAtRuntime"}) . "Enabled" if ($signature->extendedAttributes->{"EnabledAtRuntime"} && $signature->extendedAttributes->{"EnabledAtRuntime"} ne "1");
3571
3572     # Otherwise return a function named RuntimeEnabledFeatures::{methodName}Enabled().
3573     return "RuntimeEnabledFeatures::" . $codeGenerator->WK_lcfirst($signature->name) . "Enabled";
3574 }
3575
3576 sub DebugPrint
3577 {
3578     my $output = shift;
3579
3580     print $output;
3581     print "\n";
3582 }