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