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