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