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