bd609714f9ccc1ea82ef1e0f02b586501c8fa41a
[WebKit-https.git] / WebCore / bindings / scripts / CodeGeneratorV8.pm
1
2 # Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
3 # Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
4 # Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
5 # Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
6 # Copyright (C) 2006 Apple Computer, Inc.
7 # Copyright (C) 2007, 2008, 2009 Google Inc.
8 # Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
9 #
10 # This library is free software; you can redistribute it and/or
11 # modify it under the terms of the GNU Library General Public
12 # License as published by the Free Software Foundation; either
13 # version 2 of the License, or (at your option) any later version.
14 #
15 # This library is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 # Library General Public License for more details.
19 #
20 # You should have received a copy of the GNU Library General Public License
21 # aint with this library; see the file COPYING.LIB.  If not, write to
22 # the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 # Boston, MA 02111-1307, USA.
24 #
25
26 package CodeGeneratorV8;
27
28 use File::stat;
29 use Digest::MD5;
30
31 my $module = "";
32 my $outputDir = "";
33
34 my @headerContent = ();
35 my @implContentHeader = ();
36 my @implFixedHeader = ();
37 my @implContent = ();
38 my @implContentDecls = ();
39 my %implIncludes = ();
40
41 my @allParents = ();
42
43 # Default .h template
44 my $headerTemplate = << "EOF";
45 /*
46     This file is part of the WebKit open source project.
47     This file has been generated by generate-bindings.pl. DO NOT MODIFY!
48
49     This library is free software; you can redistribute it and/or
50     modify it under the terms of the GNU Library General Public
51     License as published by the Free Software Foundation; either
52     version 2 of the License, or (at your option) any later version.
53
54     This library is distributed in the hope that it will be useful,
55     but WITHOUT ANY WARRANTY; without even the implied warranty of
56     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
57     Library General Public License for more details.
58
59     You should have received a copy of the GNU Library General Public License
60     along with this library; see the file COPYING.LIB.  If not, write to
61     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
62     Boston, MA 02111-1307, USA.
63 */
64 EOF
65
66 # Default constructor
67 sub new
68 {
69     my $object = shift;
70     my $reference = { };
71
72     $codeGenerator = shift;
73     $outputDir = shift;
74
75     bless($reference, $object);
76     return $reference;
77 }
78
79 sub finish
80 {
81     my $object = shift;
82
83     # Commit changes!
84     $object->WriteData();
85 }
86
87 sub leftShift($$) {
88     my ($value, $distance) = @_;
89     return (($value << $distance) & 0xFFFFFFFF);
90 }
91
92 # Workaround for V8 bindings difference where RGBColor is not a POD type.
93 sub IsPodType
94 {
95     my $type = shift;
96     return $codeGenerator->IsPodType($type);
97 }
98
99 # Params: 'domClass' struct
100 sub GenerateInterface
101 {
102     my $object = shift;
103     my $dataNode = shift;
104     my $defines = shift;
105
106     # Start actual generation
107     $object->GenerateHeader($dataNode);
108     $object->GenerateImplementation($dataNode);
109
110     my $name = $dataNode->name;
111
112     # Open files for writing
113     my $headerFileName = "$outputDir/V8$name.h";
114     my $implFileName = "$outputDir/V8$name.cpp";
115
116     open($IMPL, ">$implFileName") || die "Couldn't open file $implFileName";
117     open($HEADER, ">$headerFileName") || die "Couldn't open file $headerFileName";
118 }
119
120 # Params: 'idlDocument' struct
121 sub GenerateModule
122 {
123     my $object = shift;
124     my $dataNode = shift;
125
126     $module = $dataNode->module;
127 }
128
129 sub GetLegacyHeaderIncludes
130 {
131     my $legacyParent = shift;
132
133     die "Don't know what headers to include for module $module";
134 }
135
136 sub AvoidInclusionOfType
137 {
138     my $type = shift;
139
140     # Special case: SVGRect.h / SVGPoint.h / SVGNumber.h / SVGMatrix.h do not exist.
141     return 1 if $type eq "SVGRect" or $type eq "SVGPoint" or $type eq "SVGNumber" or $type eq "SVGMatrix";
142     return 0;
143 }
144
145 sub UsesManualToJSImplementation
146 {
147     my $type = shift;
148
149     return 1 if $type eq "SVGPathSeg";
150     return 0;
151 }
152
153 sub AddIncludesForType
154 {
155     my $type = $codeGenerator->StripModule(shift);
156
157     # When we're finished with the one-file-per-class
158     # reorganization, we won't need these special cases.
159     if ($codeGenerator->IsPrimitiveType($type) or AvoidInclusionOfType($type)) {
160     } elsif ($type =~ /SVGPathSeg/) {
161         $joinedName = $type;
162         $joinedName =~ s/Abs|Rel//;
163         $implIncludes{"${joinedName}.h"} = 1;
164     } else {
165         # default, include the same named file
166         $implIncludes{GetImplementationFileName(${type})} = 1;
167     }
168
169     # additional includes (things needed to compile the bindings but not the header)
170
171     if ($type eq "CanvasRenderingContext2D") {
172         $implIncludes{"CanvasGradient.h"} = 1;
173         $implIncludes{"CanvasPattern.h"} = 1;
174         $implIncludes{"CanvasStyle.h"} = 1;
175     }
176
177     if ($type eq "CanvasGradient" or $type eq "XPathNSResolver") {
178         $implIncludes{"PlatformString.h"} = 1;
179     }
180
181     if ($type eq "CSSStyleDeclaration") {
182         $implIncludes{"CSSMutableStyleDeclaration.h"} = 1;
183     }
184
185     if ($type eq "Plugin" or $type eq "PluginArray" or $type eq "MimeTypeArray") {
186         # So we can get String -> AtomicString conversion for namedItem().
187         $implIncludes{"AtomicString.h"} = 1;
188     }
189 }
190
191 sub AddIncludesForSVGAnimatedType
192 {
193     my $type = shift;
194     $type =~ s/SVGAnimated//;
195
196     if ($type eq "Point" or $type eq "Rect") {
197         $implIncludes{"Float$type.h"} = 1;
198     } elsif ($type eq "String") {
199         $implIncludes{"PlatformString.h"} = 1;
200     }
201
202     $implIncludes{"SVGAnimatedTemplate.h"} = 1;
203 }
204
205 sub AddClassForwardIfNeeded
206 {
207     my $implClassName = shift;
208
209     # SVGAnimatedLength/Number/etc.. are typedefs to SVGAnimtatedTemplate, so don't use class forwards for them!
210     push(@headerContent, "class $implClassName;\n\n") unless $codeGenerator->IsSVGAnimatedType($implClassName);
211 }
212
213 sub GetImplementationFileName
214 {
215     my $iface = shift;
216     return "Event.h" if $iface eq "DOMTimeStamp";
217     return "NamedAttrMap.h" if $iface eq "NamedNodeMap";
218     return "NameNodeList.h" if $iface eq "NodeList";
219     return "XMLHttpRequest.h" if $iface eq "XMLHttpRequest";
220
221     return "${iface}.h";
222 }
223
224 # If the node has a [Conditional=XXX] attribute, returns an "ENABLE(XXX)" string for use in an #if.
225 sub GenerateConditionalString
226 {
227     my $node = shift;
228     my $conditional = $node->extendedAttributes->{"Conditional"};
229     if ($conditional) {
230         return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
231     } else {
232         return "";
233     }
234 }
235
236 sub GenerateHeader
237 {
238     my $object = shift;
239     my $dataNode = shift;
240
241     my $interfaceName = $dataNode->name;
242     my $className = "V8$interfaceName";
243     my $implClassName = $interfaceName;
244
245     # Copy contents of parent classes except the first parent or if it is
246     # EventTarget.
247     $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@allParents, 1);
248
249     my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
250     my $conditionalString = GenerateConditionalString($dataNode);
251
252     # - Add default header template
253     @headerContent = split("\r", $headerTemplate);
254
255     push(@headerContent, "\n#if ${conditionalString}\n\n") if $conditionalString;
256     push(@headerContent, "\n#ifndef $className" . "_H");
257     push(@headerContent, "\n#define $className" . "_H\n\n");
258
259     # Get correct pass/store types respecting PODType flag
260     my $podType = $dataNode->extendedAttributes->{"PODType"};
261     my $passType = $podType ? "JSSVGPODTypeWrapper<$podType>*" : "$implClassName*";
262
263     push(@headerContent, "#include \"$podType.h\"\n") if $podType and ($podType ne "double" and $podType ne "float" and $podType ne "RGBA32");
264
265     push(@headerContent, "#include <v8.h>\n");
266     push(@headerContent, "#include <wtf/HashMap.h>\n");
267     push(@headerContent, "#include \"StringHash.h\"\n");
268
269     push(@headerContent, "\nnamespace WebCore {\n\n");
270     push(@headerContent, "class V8ClassIndex;\n");
271     push(@headerContent, "\nclass $className {\n");
272     push(@headerContent, <<END);
273
274  public:
275   static bool HasInstance(v8::Handle<v8::Value> value);
276   static v8::Persistent<v8::FunctionTemplate> GetRawTemplate();
277 END
278
279     if ($implClassName eq "DOMWindow") {
280       push(@headerContent, <<END);
281   static v8::Persistent<v8::ObjectTemplate> GetShadowObjectTemplate();
282 END
283     }
284
285     push(@headerContent, <<END);
286
287  private:
288   static v8::Persistent<v8::FunctionTemplate> GetTemplate();
289
290   friend class V8ClassIndex;
291 };
292
293 END
294
295     push(@headerContent, "}\n\n");
296     push(@headerContent, "#endif // $className" . "_H\n");
297
298     push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;
299 }
300
301
302 sub GenerateSetDOMException
303 {
304     my $indent = shift;
305     my $result = "";
306
307     $result .= $indent . "if (UNLIKELY(ec)) {\n";
308     $result .= $indent . "    V8Proxy::setDOMException(ec);\n";
309     $result .= $indent . "    return v8::Handle<v8::Value>();\n";
310     $result .= $indent . "}\n";
311
312     return $result;
313 }
314
315 sub IsNodeSubType
316 {
317     my $dataNode = shift;
318     return 1 if ($dataNode->name eq "Node");
319     foreach (@allParents) {
320         my $parent = $codeGenerator->StripModule($_);
321         return 1 if $parent eq "Node";
322     }
323     return 0;
324 }
325
326 sub GetHiddenDependencyIndex
327 {
328     my $dataNode = shift;
329     my $attribute = shift;
330     my $name = $dataNode->name;
331     return "V8Custom::kNodeEventListenerCacheIndex" if IsNodeSubType($dataNode);
332     return "V8Custom::kSVGElementInstanceEventListenerCacheIndex" if $name eq "SVGElementInstance";
333     return "V8Custom::kAbstractWorkerRequestCacheIndex" if $name eq "AbstractWorker";
334     return "V8Custom::kWorkerRequestCacheIndex" if $name eq "Worker";
335     return "V8Custom::kDedicatedWorkerContextRequestCacheIndex" if $name eq "DedicatedWorkerContext";
336     return "V8Custom::kWorkerContextRequestCacheIndex" if $name eq "WorkerContext";
337     return "V8Custom::kWorkerContextRequestCacheIndex" if $name eq "SharedWorkerContext";
338     return "V8Custom::kMessagePortRequestCacheIndex" if $name eq "MessagePort";
339     return "V8Custom::kWebSocketCacheIndex" if $name eq "WebSocket";
340     return "V8Custom::kXMLHttpRequestCacheIndex" if $name eq "XMLHttpRequest";
341     return "V8Custom::kXMLHttpRequestCacheIndex" if $name eq "XMLHttpRequestUpload";
342     return "V8Custom::kDOMApplicationCacheCacheIndex" if $name eq "DOMApplicationCache";
343     return "V8Custom::kNotificationRequestCacheIndex" if $name eq "Notification";
344     return "V8Custom::kDOMWindowEventListenerCacheIndex" if $name eq "DOMWindow";
345     die "Unexpected name " . $name . " when generating " . $attribute;
346 }
347
348 sub HolderToNative
349 {
350     my $dataNode = shift;
351     my $implClassName = shift;
352     my $classIndex = shift;
353     my $holder = shift || "holder";   # optional param
354
355     if (IsNodeSubType($dataNode)) {
356         push(@implContentDecls, <<END);
357     $implClassName* imp = v8DOMWrapperToNode<$implClassName>($holder);
358 END
359
360     } else {
361         push(@implContentDecls, <<END);
362     $implClassName* imp = v8DOMWrapperTo<$implClassName>(V8ClassIndex::$classIndex, $holder);
363 END
364
365   }
366 }
367
368 sub GenerateDomainSafeFunctionGetter
369 {
370     my $function = shift;
371     my $dataNode = shift;
372     my $classIndex = shift;
373     my $implClassName = shift;
374
375     my $className = "V8" . $dataNode->name;
376     my $funcName = $function->signature->name;
377
378     my $signature = "v8::Signature::New(" . $className . "::GetRawTemplate())";
379     if ($function->signature->extendedAttributes->{"V8DoNotCheckSignature"}) {
380         $signature = "v8::Local<v8::Signature>()";
381     }
382
383     my $newTemplateString = GenerateNewFunctionTemplate($function, $dataNode, $signature);
384
385     $implIncludes{"V8Proxy.h"} = 1;
386
387     push(@implContentDecls, <<END);
388   static v8::Handle<v8::Value> ${funcName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) {
389     INC_STATS(\"DOM.$implClassName.$funcName._get\");
390     static v8::Persistent<v8::FunctionTemplate> private_template =
391         v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
392     v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::$classIndex, info.This());
393     if (holder.IsEmpty()) {
394       // can only reach here by 'object.__proto__.func', and it should passed
395       // domain security check already
396
397       return private_template->GetFunction();
398     }
399 END
400
401     HolderToNative($dataNode, $implClassName, $classIndex);
402
403     push(@implContentDecls, <<END);
404     if (!V8Proxy::canAccessFrame(imp->frame(), false)) {
405       static v8::Persistent<v8::FunctionTemplate> shared_template =
406         v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
407       return shared_template->GetFunction();
408
409     } else {
410       return private_template->GetFunction();
411     }
412   }
413
414 END
415 }
416
417 sub GenerateConstructorGetter
418 {
419     my $implClassName = shift;
420     my $classIndex = shift;
421
422     push(@implContentDecls, <<END);
423   static v8::Handle<v8::Value> ${implClassName}ConstructorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) {
424     INC_STATS(\"DOM.$implClassName.constructors._get\");
425     v8::Handle<v8::Value> data = info.Data();
426     ASSERT(data->IsNumber());
427     V8ClassIndex::V8WrapperType type = V8ClassIndex::FromInt(data->Int32Value());
428 END
429
430     if ($classIndex eq "DOMWINDOW") {
431         push(@implContentDecls, <<END);
432     DOMWindow* window = v8DOMWrapperTo<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder());
433     // Get the proxy corresponding to the DOMWindow if possible to
434     // make sure that the constructor function is constructed in the
435     // context of the DOMWindow and not in the context of the caller.
436     return V8DOMWrapper::getConstructor(type, window);
437 END
438     } elsif ($classIndex eq "DEDICATEDWORKERCONTEXT" or $classIndex eq "WORKERCONTEXT" or $classIndex eq "SHAREDWORKERCONTEXT") {
439         $implIncludes{"WorkerContextExecutionProxy.h"} = 1;
440         push(@implContentDecls, <<END);
441     WorkerContext* workerContext = v8DOMWrapperTo<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder());
442     return V8DOMWrapper::getConstructor(type, workerContext);
443 END
444     } else {
445         push(@implContentDecls, "    return v8::Handle<v8::Value>();");
446     }
447
448     push(@implContentDecls, <<END);
449
450     }
451
452 END
453 }
454
455 sub GenerateNormalAttrGetter
456 {
457     my $attribute = shift;
458     my $dataNode = shift;
459     my $classIndex = shift;
460     my $implClassName = shift;
461     my $interfaceName = shift;
462
463     my $attrExt = $attribute->signature->extendedAttributes;
464
465     my $attrName = $attribute->signature->name;
466     $implIncludes{"V8Proxy.h"} = 1;
467
468     my $attrType = GetTypeFromSignature($attribute->signature);
469     my $attrIsPodType = IsPodType($attrType);
470
471     my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0);
472     my $isPodType = IsPodType($implClassName);
473     my $skipContext = 0;
474
475
476     if ($isPodType) {
477         $implClassName = GetNativeType($implClassName);
478         $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
479     }
480
481     # Special case: SVGZoomEvent's attributes are all read-only
482     if ($implClassName eq "SVGZoomEvent") {
483         $attrIsPodType = 0;
484         $skipContext = 1;
485     }
486
487     # Special case: SVGSVGEelement::viewport is read-only
488     if (($implClassName eq "SVGSVGElement") and ($attrName eq "viewport")) {
489         $attrIsPodType = 0;
490         $skipContext = 1;
491     }
492
493     # Special case for SVGColor
494     if (($implClassName eq "SVGColor") and ($attrName eq "rgbColor")) {
495         $attrIsPodType = 0;
496     }
497
498     my $getterStringUsesImp = $implClassName ne "double";
499
500   # Getter
501     push(@implContentDecls, <<END);
502   static v8::Handle<v8::Value> ${attrName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) {
503     INC_STATS(\"DOM.$implClassName.$attrName._get\");
504 END
505
506     if ($isPodType) {
507         push(@implContentDecls, <<END);
508     V8SVGPODTypeWrapper<$implClassName>* imp_wrapper = v8DOMWrapperTo<V8SVGPODTypeWrapper<$implClassName> >(V8ClassIndex::$classIndex, info.Holder());
509     $implClassName imp_instance = *imp_wrapper;
510 END
511         if ($getterStringUsesImp) {
512             push(@implContentDecls, <<END);
513     $implClassName* imp = &imp_instance;
514 END
515         }
516
517     } elsif ($attrExt->{"v8OnProto"} || $attrExt->{"V8DisallowShadowing"}) {
518       if ($classIndex eq "DOMWINDOW") {
519         push(@implContentDecls, <<END);
520     v8::Handle<v8::Object> holder = info.Holder();
521 END
522       } else {
523         # perform lookup first
524         push(@implContentDecls, <<END);
525     v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::$classIndex, info.This());
526     if (holder.IsEmpty()) return v8::Handle<v8::Value>();
527 END
528       }
529         HolderToNative($dataNode, $implClassName, $classIndex, "info");
530     } else {
531         push(@implContentDecls, <<END);
532     v8::Handle<v8::Object> holder = info.Holder();
533 END
534         HolderToNative($dataNode, $implClassName, $classIndex, "info");
535     }
536
537     # Generate security checks if necessary
538     if ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) {
539         push(@implContentDecls, "    if (!V8Proxy::checkNodeSecurity(imp->$attrName())) return v8::Handle<v8::Value>();\n\n");
540     } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) {
541         push(@implContentDecls, "    if (!V8Proxy::checkNodeSecurity(imp->contentDocument())) return v8::Handle<v8::Value>();\n\n");
542     }
543
544     my $useExceptions = 1 if @{$attribute->getterExceptions} and !($isPodType);
545     if ($useExceptions) {
546         $implIncludes{"ExceptionCode.h"} = 1;
547         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
548     }
549
550     if ($attribute->signature->extendedAttributes->{"v8referenceattr"}) {
551         $attrName = $attribute->signature->extendedAttributes->{"v8referenceattr"};
552     }
553
554     my $getterFunc = $codeGenerator->WK_lcfirst($attrName);
555     $getterFunc .= "Animated" if $codeGenerator->IsSVGAnimatedType($attribute->signature->type);
556
557     my $returnType = GetTypeFromSignature($attribute->signature);
558
559     my $getterString;
560     if ($getterStringUsesImp) {
561         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
562         my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
563         if ($reflect || $reflectURL) {
564             my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL);
565             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
566             $implIncludes{"${namespace}.h"} = 1;
567             my $getAttributeFunctionName = $reflectURL ? "getURLAttribute" : "getAttribute";
568             $getterString = "imp->$getAttributeFunctionName(${namespace}::${contentAttributeName}Attr";
569         } else {
570             $getterString = "imp->$getterFunc(";
571         }
572         $getterString .= "ec" if $useExceptions;
573         $getterString .= ")";
574         if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) {
575             $getterString .= ".toInt()";
576         }
577     } else {
578         $getterString = "imp_instance";
579     }
580
581     my $result;
582     my $wrapper;
583
584     if ($attrIsPodType) {
585         $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
586
587         my $getter = $getterString;
588         $getter =~ s/imp->//;
589         $getter =~ s/\(\)//;
590         my $setter = "set" . $codeGenerator->WK_ucfirst($getter);
591
592         my $implClassIsAnimatedType = $codeGenerator->IsSVGAnimatedType($implClassName);
593         if (not $implClassIsAnimatedType and $codeGenerator->IsPodTypeWithWriteableProperties($attrType) and not defined $attribute->signature->extendedAttributes->{"Immutable"}) {
594             if (IsPodType($implClassName)) {
595                 my $wrapper = "V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($getterString, imp_wrapper)";
596                 push(@implContentDecls, "    RefPtr<V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName> > wrapper = $wrapper;\n");
597             } else {
598                 my $wrapper = "V8SVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName>::create(imp, &${implClassName}::$getter, &${implClassName}::$setter)";
599                 push(@implContentDecls, "    RefPtr<V8SVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName> > wrapper = $wrapper;\n");
600             }
601         } else {
602             if ($implClassIsAnimatedType) {
603                 # We can't hash member function pointers, so instead generate
604                 # some hashing material based on the names of the methods.
605                 my $hashhex = substr(Digest::MD5::md5_hex("${implClassName}::$getter ${implClassName}::$setter)"), 0, 8);
606                 my $wrapper = "V8SVGDynamicPODTypeWrapperCache<$nativeType, $implClassName>::lookupOrCreateWrapper(imp, &${implClassName}::$getter, &${implClassName}::$setter, 0x$hashhex)";
607                 push(@implContentDecls, "    RefPtr<V8SVGPODTypeWrapper<" . $nativeType . "> > wrapper = $wrapper;\n");
608             } else {
609                 my $wrapper = GenerateSVGStaticPodTypeWrapper($returnType, $getterString);
610                 push(@implContentDecls, "    RefPtr<V8SVGStaticPODTypeWrapper<" . $nativeType . "> > wrapper = $wrapper;\n");
611             }
612         }
613
614     } else {
615         if ($attribute->signature->type eq "EventListener" && $dataNode->name eq "DOMWindow") {
616             push(@implContentDecls, "    if (!imp->document())\n");
617             push(@implContentDecls, "      return v8::Handle<v8::Value>();\n");
618         }
619
620         if ($useExceptions) {
621             push(@implContentDecls, "    $nativeType v = ");
622             push(@implContentDecls, "$getterString;\n");
623             push(@implContentDecls, GenerateSetDOMException("    "));
624             $result = "v";
625             $result .= ".release()" if (IsRefPtrType($returnType));
626         } else {
627             # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
628             $result = $getterString;
629         }
630     }
631
632     if (IsSVGTypeNeedingContextParameter($attrType) && !$skipContext) {
633         my $resultObject = $result;
634         if ($attrIsPodType) {
635             $resultObject = "wrapper";
636         }
637         $resultObject = "WTF::getPtr(" . $resultObject . ")";
638         push(@implContentDecls, GenerateSVGContextAssignment($implClassName, $resultObject, "    "));
639     }
640
641     if ($attrIsPodType) {
642         my $classIndex = uc($attrType);
643         push(@implContentDecls, "    return V8DOMWrapper::convertToV8Object(V8ClassIndex::$classIndex, wrapper.release());\n");
644     } else {
645         push(@implContentDecls, "    " . ReturnNativeToJSValue($attribute->signature, $result, "    ").";\n");
646     }
647
648     push(@implContentDecls, "  }\n\n");  # end of getter
649 }
650
651
652 sub GenerateReplaceableAttrSetter
653 {
654     my $implClassName = shift;
655
656     $implIncludes{"V8Proxy.h"} = 1;
657
658     push(@implContentDecls,
659        "  static void ${attrName}AttrSetter(v8::Local<v8::String> name," .
660        " v8::Local<v8::Value> value, const v8::AccessorInfo& info) {\n");
661
662     push(@implContentDecls, "    INC_STATS(\"DOM.$implClassName.$attrName._set\");\n");
663
664     push(@implContentDecls, "    v8::Local<v8::String> ${attrName}_string = v8::String::New(\"${attrName}\");\n");
665     push(@implContentDecls, "    info.Holder()->Delete(${attrName}_string);\n");
666     push(@implContentDecls, "    info.This()->Set(${attrName}_string, value);\n");
667     push(@implContentDecls, "  }\n\n");
668 }
669
670
671 sub GenerateNormalAttrSetter
672 {
673     my $attribute = shift;
674     my $dataNode = shift;
675     my $classIndex = shift;
676     my $implClassName = shift;
677     my $interfaceName = shift;
678
679     my $attrExt = $attribute->signature->extendedAttributes;
680
681     $implIncludes{"V8Proxy.h"} = 1;
682
683     push(@implContentDecls,
684        "  static void ${attrName}AttrSetter(v8::Local<v8::String> name," .
685        " v8::Local<v8::Value> value, const v8::AccessorInfo& info) {\n");
686
687     push(@implContentDecls, "    INC_STATS(\"DOM.$implClassName.$attrName._set\");\n");
688
689     my $isPodType = IsPodType($implClassName);
690
691     if ($isPodType) {
692         $implClassName = GetNativeType($implClassName);
693         $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
694         push(@implContentDecls, "    V8SVGPODTypeWrapper<$implClassName>* wrapper = v8DOMWrapperTo<V8SVGPODTypeWrapper<$implClassName> >(V8ClassIndex::$classIndex, info.Holder());\n");
695         push(@implContentDecls, "    $implClassName imp_instance = *wrapper;\n");
696         push(@implContentDecls, "    $implClassName* imp = &imp_instance;\n");
697
698     } elsif ($attrExt->{"v8OnProto"}) {
699       if ($classIndex eq "DOMWINDOW") {
700         push(@implContentDecls, <<END);
701     v8::Handle<v8::Object> holder = info.Holder();
702 END
703       } else {
704         # perform lookup first
705         push(@implContentDecls, <<END);
706     v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::$classIndex, info.This());
707     if (holder.IsEmpty()) return;
708 END
709       }
710         HolderToNative($dataNode, $implClassName, $classIndex, "info");
711     } else {
712         push(@implContentDecls, <<END);
713     v8::Handle<v8::Object> holder = info.Holder();
714 END
715         HolderToNative($dataNode, $implClassName, $classIndex, "info");
716     }
717
718     my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0);
719     if ($attribute->signature->type eq "EventListener") {
720         if ($dataNode->name eq "DOMWindow") {
721             push(@implContentDecls, "    if (!imp->document())\n");
722             push(@implContentDecls, "      return;\n");
723         }
724     } else {
725         push(@implContentDecls, "    $nativeType v = " . JSValueToNative($attribute->signature, "value") . ";\n");
726     }
727
728     my $result = "";
729     if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) {
730         $result .= "WebCore::String::number(";
731     }
732     $result .= "v";
733     if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) {
734         $result .= ")";
735     }
736     my $returnType = GetTypeFromSignature($attribute->signature);
737     if (IsRefPtrType($returnType)) {
738         $result = "WTF::getPtr(" . $result . ")";
739     }
740
741     my $useExceptions = 1 if @{$attribute->setterExceptions} and !($isPodType);
742
743     if ($useExceptions) {
744         $implIncludes{"ExceptionCode.h"} = 1;
745         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
746     }
747
748     if ($implClassName eq "double") {
749         push(@implContentDecls, "    *imp = $result;\n");
750     } else {
751         my $implSetterFunctionName = $codeGenerator->WK_ucfirst($attrName);
752         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
753         my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
754         if ($reflect || $reflectURL) {
755             my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL);
756             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
757             $implIncludes{"${namespace}.h"} = 1;
758             push(@implContentDecls, "    imp->setAttribute(${namespace}::${contentAttributeName}Attr, $result");
759         } elsif ($attribute->signature->type eq "EventListener") {
760             $implIncludes{"V8AbstractEventListener.h"} = 1;
761             $implIncludes{"V8CustomBinding.h"} = 1;
762             $cacheIndex = GetHiddenDependencyIndex($dataNode, $attrName);
763             push(@implContentDecls, "    transferHiddenDependency(holder, imp->$attrName(), value, $cacheIndex);\n");
764             push(@implContentDecls, "    imp->set$implSetterFunctionName(V8DOMWrapper::getEventListener(imp, value, true, ListenerFindOrCreate)");
765         } else {
766             push(@implContentDecls, "    imp->set$implSetterFunctionName($result");
767         }
768         push(@implContentDecls, ", ec") if $useExceptions;
769         push(@implContentDecls, ");\n");
770     }
771
772     if ($useExceptions) {
773         push(@implContentDecls, "    if (UNLIKELY(ec))\n");
774         push(@implContentDecls, "        V8Proxy::setDOMException(ec);\n");
775     }
776
777     if ($isPodType) {
778         push(@implContentDecls, "    wrapper->commitChange(*imp, V8Proxy::svgContext(wrapper));\n");
779     } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
780         $implIncludes{"SVGElement.h"} = 1;
781
782         my $currentObject = "imp";
783         if ($isPodType) {
784             $currentObject = "wrapper";
785         }
786
787         push(@implContentDecls, "    if (SVGElement* context = V8Proxy::svgContext($currentObject)) {\n");
788         push(@implContentDecls, "        context->svgAttributeChanged(imp->associatedAttributeName());\n");
789         push(@implContentDecls, "    }\n");
790     }
791
792     push(@implContentDecls, "    return;\n");
793     push(@implContentDecls, "  }\n\n");  # end of setter
794 }
795
796 sub GetFunctionTemplateCallbackName
797 {
798     $function = shift;
799     $dataNode = shift;
800     
801     my $interfaceName = $dataNode->name;
802     my $name = $function->signature->name;
803
804     if ($function->signature->extendedAttributes->{"Custom"} ||
805         $function->signature->extendedAttributes->{"V8Custom"}) {
806         if ($function->signature->extendedAttributes->{"Custom"} &&
807             $function->signature->extendedAttributes->{"V8Custom"}) {
808             die "Custom and V8Custom should be mutually exclusive!"
809         }
810         my $customFunc = $function->signature->extendedAttributes->{"Custom"} ||
811                          $function->signature->extendedAttributes->{"V8Custom"};
812         if ($customFunc eq 1) {
813             $customFunc = $interfaceName . $codeGenerator->WK_ucfirst($name);
814         }
815         return "V8Custom::v8${customFunc}Callback";
816     } else {
817         return "${interfaceName}Internal::${name}Callback";
818     }
819 }
820
821 sub GenerateNewFunctionTemplate
822 {
823     $function = shift;
824     $dataNode = shift;
825     $signature = shift;
826
827     my $callback = GetFunctionTemplateCallbackName($function, $dataNode);
828     return "v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), $signature)";
829 }
830
831 sub GenerateFunctionCallback
832 {
833     my $function = shift;
834     my $dataNode = shift;
835     my $classIndex = shift;
836     my $implClassName = shift;
837
838     my $interfaceName = $dataNode->name;
839     my $name = $function->signature->name;
840
841     push(@implContentDecls,
842 "  static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args) {\n" .
843 "    INC_STATS(\"DOM.$implClassName.$name\");\n");
844
845     my $numParameters = @{$function->parameters};
846
847     if ($function->signature->extendedAttributes->{"RequiresAllArguments"}) {
848         push(@implContentDecls,
849             "    if (args.Length() < $numParameters) return v8::Handle<v8::Value>();\n");
850     }
851
852     if (IsPodType($implClassName)) {
853         my $nativeClassName = GetNativeType($implClassName);
854         push(@implContentDecls, "    V8SVGPODTypeWrapper<$nativeClassName>* imp_wrapper = v8DOMWrapperTo<V8SVGPODTypeWrapper<$nativeClassName> >(V8ClassIndex::$classIndex, args.Holder());\n");
855         push(@implContentDecls, "    $nativeClassName imp_instance = *imp_wrapper;\n");
856         push(@implContentDecls, "    $nativeClassName* imp = &imp_instance;\n");
857     } else {
858         push(@implContentDecls, <<END);
859     v8::Handle<v8::Object> holder = args.Holder();
860 END
861         HolderToNative($dataNode, $implClassName, $classIndex);
862     }
863
864   # Check domain security if needed
865     if (($dataNode->extendedAttributes->{"CheckDomainSecurity"}
866        || $interfaceName eq "DOMWindow")
867        && !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
868     # We have not find real use cases yet.
869     push(@implContentDecls,
870 "    if (!V8Proxy::canAccessFrame(imp->frame(), true)) {\n".
871 "      return v8::Handle<v8::Value>();\n" .
872 "    }\n");
873     }
874
875
876     if (@{$function->raisesExceptions}) {
877         $implIncludes{"ExceptionCode.h"} = 1;
878         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
879     }
880
881     if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
882         push(@implContentDecls,
883 "    OwnPtr<ScriptCallStack> callStack(ScriptCallStack::create(args, $numParameters));\n".
884 "    if (!callStack)\n".
885 "        return v8::Undefined();\n");
886         $implIncludes{"ScriptCallStack.h"} = 1;
887     }
888     if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) {
889         push(@implContentDecls,
890 "    if (!V8Proxy::checkNodeSecurity(imp->getSVGDocument(ec)))\n" .
891 "      return v8::Handle<v8::Value>();\n");
892     }
893
894     my $paramIndex = 0;
895     foreach my $parameter (@{$function->parameters}) {
896         TranslateParameter($parameter);
897
898         my $parameterName = $parameter->name;
899
900         if ($parameter->extendedAttributes->{"Optional"}) {
901             # Generate early call if there are not enough parameters.
902             push(@implContentDecls, "    if (args.Length() <= $paramIndex) {\n");
903             my $functionCall = GenerateFunctionCallString($function, $paramIndex, "    " x 2, $implClassName);
904             push(@implContentDecls, $functionCall);
905             push(@implContentDecls, "    }\n");
906         }
907
908         if (BasicTypeCanFailConversion($parameter)) {
909             push(@implContentDecls, "    bool ${parameterName}Ok;\n");
910         }
911
912         push(@implContentDecls, "    " . GetNativeTypeFromSignature($parameter, 1) . " $parameterName = ");
913         push(@implContentDecls, JSValueToNative($parameter, "args[$paramIndex]",
914            BasicTypeCanFailConversion($parameter) ?  "${parameterName}Ok" : undef) . ";\n");
915
916         if (TypeCanFailConversion($parameter)) {
917             $implIncludes{"ExceptionCode.h"} = 1;
918             push(@implContentDecls,
919 "    if (UNLIKELY(!$parameterName" . (BasicTypeCanFailConversion($parameter) ? "Ok" : "") . ")) {\n" .
920 "      V8Proxy::setDOMException(TYPE_MISMATCH_ERR);\n" .
921 "      return v8::Handle<v8::Value>();\n" .
922 "    }\n");
923         }
924
925         if ($parameter->extendedAttributes->{"IsIndex"}) {
926             $implIncludes{"ExceptionCode.h"} = 1;
927             push(@implContentDecls,
928 "    if (UNLIKELY($parameterName < 0)) {\n" .
929 "      V8Proxy::setDOMException(INDEX_SIZE_ERR);\n" .
930 "      return v8::Handle<v8::Value>();\n" .
931 "    }\n");
932         }
933
934         $paramIndex++;
935     }
936
937     # Build the function call string.
938     my $callString = GenerateFunctionCallString($function, $paramIndex, "    ", $implClassName);
939     push(@implContentDecls, "$callString");
940     push(@implContentDecls, "  }\n\n");
941 }
942
943 sub GenerateBatchedAttributeData
944 {
945     my $dataNode = shift;
946     my $interfaceName = $dataNode->name;
947     my $attributes = shift;
948
949     foreach my $attribute (@$attributes) {
950         my $conditionalString = GenerateConditionalString($attribute->signature);
951         push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
952         GenerateSingleBatchedAttribute($interfaceName, $attribute, ",", "");
953         push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
954     }
955 }
956
957 sub GenerateSingleBatchedAttribute
958 {
959     my $interfaceName = shift;
960     my $attribute = shift;
961     my $delimiter = shift;
962     my $indent = shift;
963     my $attrName = $attribute->signature->name;
964     my $attrExt = $attribute->signature->extendedAttributes;
965
966     my $accessControl = "v8::DEFAULT";
967     if ($attrExt->{"DoNotCheckDomainSecurityOnGet"}) {
968         $accessControl = "v8::ALL_CAN_READ";
969     } elsif ($attrExt->{"DoNotCheckDomainSecurityOnSet"}) {
970         $accessControl = "v8::ALL_CAN_WRITE";
971     } elsif ($attrExt->{"DoNotCheckDomainSecurity"}) {
972         $accessControl = "v8::ALL_CAN_READ";
973         if (!($attribute->type =~ /^readonly/) && !($attrExt->{"V8ReadOnly"})) {
974             $accessControl .= "|v8::ALL_CAN_WRITE";
975         }
976     }
977     if ($attrExt->{"V8DisallowShadowing"}) {
978         $accessControl .= "|v8::PROHIBITS_OVERWRITING";
979     }
980     $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")";
981
982     my $customAccessor =
983         $attrExt->{"Custom"} ||
984         $attrExt->{"CustomSetter"} ||
985         $attrExt->{"CustomGetter"} ||
986         $attrExt->{"V8Custom"} ||
987         $attrExt->{"V8CustomSetter"} ||
988         $attrExt->{"V8CustomGetter"} ||
989         "";
990     if ($customAccessor eq 1) {
991         # use the naming convension, interface + (capitalize) attr name
992         $customAccessor = $interfaceName . $codeGenerator->WK_ucfirst($attrName);
993     }
994
995     my $getter;
996     my $setter;
997     my $propAttr = "v8::None";
998     my $hasCustomSetter = 0;
999
1000     # Check attributes.
1001     if ($attrExt->{"DontEnum"}) {
1002         $propAttr .= "|v8::DontEnum";
1003     }
1004     if ($attrExt->{"V8DisallowShadowing"}) {
1005         $propAttr .= "|v8::DontDelete";
1006     }
1007
1008     my $on_proto = "0 /* on instance */";
1009     my $data = "V8ClassIndex::INVALID_CLASS_INDEX /* no data */";
1010
1011     # Constructor
1012     if ($attribute->signature->type =~ /Constructor$/) {
1013         my $constructorType = $codeGenerator->StripModule($attribute->signature->type);
1014         $constructorType =~ s/Constructor$//;
1015         my $constructorIndex = uc($constructorType);
1016         if ($customAccessor) {
1017             $getter = "V8Custom::v8${customAccessor}AccessorGetter";
1018         } else {
1019             $data = "V8ClassIndex::${constructorIndex}";
1020             $getter = "${interfaceName}Internal::${interfaceName}ConstructorGetter";
1021         }
1022         $setter = "0";
1023         $propAttr = "v8::ReadOnly";
1024
1025     } else {
1026         # Default Getter and Setter
1027         $getter = "${interfaceName}Internal::${attrName}AttrGetter";
1028         $setter = "${interfaceName}Internal::${attrName}AttrSetter";
1029
1030         # Custom Setter
1031         if ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
1032             $hasCustomSetter = 1;
1033             $setter = "V8Custom::v8${customAccessor}AccessorSetter";
1034         }
1035
1036         # Custom Getter
1037         if ($attrExt->{"CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
1038             $getter = "V8Custom::v8${customAccessor}AccessorGetter";
1039         }
1040     }
1041
1042     # Replaceable
1043     if ($attrExt->{"Replaceable"} && !$hasCustomSetter) {
1044         $setter = "0";
1045         # Handle the special case of window.top being marked as Replaceable.
1046         # FIXME: Investigate whether we could treat window.top as replaceable
1047         # and allow shadowing without it being a security hole.
1048         if (!($interfaceName eq "DOMWindow" and $attrName eq "top")) {
1049             $propAttr .= "|v8::ReadOnly";
1050         }
1051     }
1052
1053     # Read only attributes
1054     if ($attribute->type =~ /^readonly/ || $attrExt->{"V8ReadOnly"}) {
1055         $setter = "0";
1056     }
1057
1058     # An accessor can be installed on the proto
1059     if ($attrExt->{"v8OnProto"}) {
1060         $on_proto = "1 /* on proto */";
1061     }
1062
1063     my $commentInfo = "Attribute '$attrName' (Type: '" . $attribute->type .
1064                       "' ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
1065
1066     push(@implContent, $indent . "    {\n");
1067     push(@implContent, $indent . "        \/\/ $commentInfo\n");
1068     push(@implContent, $indent . "        \"$attrName\",\n");
1069     push(@implContent, $indent . "        $getter,\n");
1070     push(@implContent, $indent . "        $setter,\n");
1071     push(@implContent, $indent . "        $data,\n");
1072     push(@implContent, $indent . "        $accessControl,\n");
1073     push(@implContent, $indent . "        static_cast<v8::PropertyAttribute>($propAttr),\n");
1074     push(@implContent, $indent . "        $on_proto\n");
1075     push(@implContent, $indent . "    }" . $delimiter . "\n");
1076 END
1077 }
1078
1079 sub GenerateImplementation
1080 {
1081     my $object = shift;
1082     my $dataNode = shift;
1083     my $interfaceName = $dataNode->name;
1084     my $className = "V8$interfaceName";
1085     my $implClassName = $interfaceName;
1086     my $classIndex = uc($codeGenerator->StripModule($interfaceName));
1087
1088     my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
1089     my $conditionalString = GenerateConditionalString($dataNode);
1090
1091     # - Add default header template
1092     @implContentHeader = split("\r", $headerTemplate);
1093
1094     push(@implFixedHeader,
1095          "#include \"config.h\"\n" .
1096          "#include \"V8Proxy.h\"\n" .
1097          "#include \"V8Binding.h\"\n\n" .
1098          "#undef LOG\n\n");
1099
1100     push(@implFixedHeader, "\n#if ${conditionalString}\n\n") if $conditionalString;
1101
1102     if ($className =~ /^V8SVGAnimated/) {
1103         AddIncludesForSVGAnimatedType($interfaceName);
1104     }
1105
1106     $implIncludes{"${className}.h"} = 1;
1107
1108     AddIncludesForType($interfaceName);
1109     $implIncludes{"V8Proxy.h"} = 1;
1110
1111     push(@implContentDecls, "namespace WebCore {\n");
1112     push(@implContentDecls, "namespace ${interfaceName}Internal {\n\n");
1113     push(@implContentDecls, "template <typename T> void V8_USE(T) { }\n\n");
1114
1115     my $hasConstructors = 0;
1116
1117     # Generate property accessors for attributes.
1118     for ($index = 0; $index < @{$dataNode->attributes}; $index++) {
1119         $attribute = @{$dataNode->attributes}[$index];
1120         $attrName = $attribute->signature->name;
1121         $attrType = $attribute->signature->type;
1122
1123         # Generate special code for the constructor attributes.
1124         if ($attrType =~ /Constructor$/) {
1125             if ($attribute->signature->extendedAttributes->{"CustomGetter"}) {
1126                 $implIncludes{"V8CustomBinding.h"} = 1;
1127             } else {
1128                 $hasConstructors = 1;
1129             }
1130             next;
1131         }
1132
1133         if ($attrType eq "EventListener" && $interfaceName eq "DOMWindow") {
1134             $attribute->signature->extendedAttributes->{"v8OnProto"} = 1;
1135         }
1136
1137         # Do not generate accessor if this is a custom attribute.  The
1138         # call will be forwarded to a hand-written accessor
1139         # implementation.
1140         if ($attribute->signature->extendedAttributes->{"Custom"} ||
1141             $attribute->signature->extendedAttributes->{"V8Custom"}) {
1142             $implIncludes{"V8CustomBinding.h"} = 1;
1143             next;
1144         }
1145
1146         # Generate the accessor.
1147         if ($attribute->signature->extendedAttributes->{"CustomGetter"}) {
1148             $implIncludes{"V8CustomBinding.h"} = 1;
1149         } else {
1150             GenerateNormalAttrGetter($attribute, $dataNode, $classIndex, $implClassName, $interfaceName);
1151         }
1152         if ($attribute->signature->extendedAttributes->{"CustomSetter"} ||
1153             $attribute->signature->extendedAttributes->{"V8CustomSetter"}) {
1154             $implIncludes{"V8CustomBinding.h"} = 1;
1155         } elsif ($attribute->signature->extendedAttributes->{"Replaceable"}) {
1156             $dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"} || die "Replaceable attribute can only be used in interface that defines ExtendsDOMGlobalObject attribute!";
1157             # GenerateReplaceableAttrSetter($implClassName);
1158         } elsif ($attribute->type !~ /^readonly/ && !$attribute->signature->extendedAttributes->{"V8ReadOnly"}) {
1159             GenerateNormalAttrSetter($attribute, $dataNode, $classIndex, $implClassName, $interfaceName);
1160         }
1161     }
1162
1163     if ($hasConstructors) {
1164         GenerateConstructorGetter($implClassName, $classIndex);
1165     }
1166
1167     # Generate methods for functions.
1168     foreach my $function (@{$dataNode->functions}) {
1169         # hack for addEventListener/RemoveEventListener
1170         # FIXME: avoid naming conflict
1171         if ($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"V8Custom"}) {
1172                 $implIncludes{"V8CustomBinding.h"} = 1;
1173         } else {
1174             GenerateFunctionCallback($function, $dataNode, $classIndex, $implClassName);
1175         }
1176
1177         # If the function does not need domain security check, we need to
1178         # generate an access getter that returns different function objects
1179         # for different calling context.
1180         if (($dataNode->extendedAttributes->{"CheckDomainSecurity"} || ($interfaceName eq "DOMWindow")) && $function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
1181             GenerateDomainSafeFunctionGetter($function, $dataNode, $classIndex, $implClassName);
1182         }
1183     }
1184
1185     # Attributes
1186     my $attributes = $dataNode->attributes;
1187
1188     # For the DOMWindow interface we partition the attributes into the
1189     # ones that disallows shadowing and the rest.
1190     my @disallowsShadowing;
1191     # Also separate out attributes that are enabled at runtime so we can process them specially.
1192     my @enabledAtRuntime;
1193     my @normal;
1194     foreach my $attribute (@$attributes) {
1195         if ($interfaceName eq "DOMWindow" && $attribute->signature->extendedAttributes->{"V8DisallowShadowing"}) {
1196             push(@disallowsShadowing, $attribute);
1197         } elsif ($attribute->signature->extendedAttributes->{"EnabledAtRuntime"}) {
1198             push(@enabledAtRuntime, $attribute);
1199         } else {
1200             push(@normal, $attribute);
1201         }
1202     }
1203     $attributes = \@normal;
1204     # Put the attributes that disallow shadowing on the shadow object.
1205     if (@disallowsShadowing) {
1206         push(@implContent, "static const BatchedAttribute shadow_attrs[] = {\n");
1207         GenerateBatchedAttributeData($dataNode, \@disallowsShadowing);
1208         push(@implContent, "};\n");
1209     }
1210
1211     my $has_attributes = 0;
1212     if (@$attributes) {
1213         $has_attributes = 1;
1214         push(@implContent, "static const BatchedAttribute ${interfaceName}_attrs[] = {\n");
1215         GenerateBatchedAttributeData($dataNode, $attributes);
1216         push(@implContent, "};\n");
1217     }
1218     
1219     # Setup table of standard callback functions
1220     $num_callbacks = 0;
1221     $has_callbacks = 0;
1222     foreach my $function (@{$dataNode->functions}) {
1223         my $attrExt = $function->signature->extendedAttributes;
1224         # Don't put any nonstandard functions into this table:
1225         if ($attrExt->{"V8OnInstance"}) {
1226             next;
1227         }
1228         if ($attrExt->{"EnabledAtRuntime"} || RequiresCustomSignature($function) || $attrExt->{"V8DoNotCheckSignature"}) {
1229             next;
1230         }
1231         if ($attrExt->{"DoNotCheckDomainSecurity"} &&
1232             ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) {
1233             next;
1234         }
1235         if ($attrExt->{"DontEnum"} || $attrExt->{"V8ReadOnly"}) {
1236             next;
1237         }
1238         if (!$has_callbacks) {
1239             $has_callbacks = 1;
1240             push(@implContent, "static const BatchedCallback ${interfaceName}_callbacks[] = {\n");
1241         }
1242         my $name = $function->signature->name;
1243         my $callback = GetFunctionTemplateCallbackName($function, $dataNode);
1244         push(@implContent, <<END);
1245   {"$name", $callback},
1246 END
1247         $num_callbacks++;
1248     }
1249     push(@implContent, "};\n")  if $has_callbacks;
1250
1251     # Setup constants
1252     my $has_constants = 0;
1253     if (@{$dataNode->constants}) {
1254         $has_constants = 1;
1255         push(@implContent, "static const BatchedConstant ${interfaceName}_consts[] = {\n");
1256     }
1257     foreach my $constant (@{$dataNode->constants}) {
1258         my $name = $constant->name;
1259         my $value = $constant->value;
1260         # FIXME: we need the static_cast here only because of one constant, NodeFilter.idl
1261         # defines "const unsigned long SHOW_ALL = 0xFFFFFFFF".  It would be better if we
1262         # handled this here, and converted it to a -1 constant in the c++ output.
1263         push(@implContent, <<END);
1264   { "${name}", static_cast<signed int>($value) },
1265 END
1266     }
1267     if ($has_constants) {
1268         push(@implContent, "};\n");
1269     }
1270
1271     push(@implContentDecls, "} // namespace ${interfaceName}Internal\n\n");
1272
1273     my $access_check = "";
1274     if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !($interfaceName eq "DOMWindow")) {
1275         $access_check = "instance->SetAccessCheckCallbacks(V8Custom::v8${interfaceName}NamedSecurityCheck, V8Custom::v8${interfaceName}IndexedSecurityCheck, v8::Integer::New(V8ClassIndex::ToInt(V8ClassIndex::${classIndex})));";
1276     }
1277
1278     # For the DOMWindow interface, generate the shadow object template
1279     # configuration method.
1280     if ($implClassName eq "DOMWindow") {
1281         push(@implContent, <<END);
1282 static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Persistent<v8::ObjectTemplate> templ) {
1283   batchConfigureAttributes(templ,
1284                            v8::Handle<v8::ObjectTemplate>(),
1285                            shadow_attrs,
1286                            sizeof(shadow_attrs)/sizeof(*shadow_attrs));
1287   return templ;
1288 }
1289 END
1290     }
1291
1292     # find the super descriptor
1293     my $parentClassIndex = "INVALID_CLASS_INDEX";
1294     foreach (@{$dataNode->parents}) {
1295         my $parent = $codeGenerator->StripModule($_);
1296         if ($parent eq "EventTarget") { next; }
1297         $implIncludes{"V8${parent}.h"} = 1;
1298         $parentClassIndex = uc($codeGenerator->StripModule($parent));
1299         last;
1300     }
1301
1302     # find the field count
1303     my $fieldCount = "V8Custom::kDefaultWrapperInternalFieldCount";
1304     if (IsNodeSubType($dataNode)) {
1305         $fieldCount = "V8Custom::kNodeMinimumInternalFieldCount";
1306     }
1307     
1308     # Generate the template configuration method
1309     push(@implContent,  <<END);
1310 static v8::Persistent<v8::FunctionTemplate> Configure${className}Template(v8::Persistent<v8::FunctionTemplate> desc) {
1311   v8::Local<v8::Signature> default_signature = configureTemplate(desc, \"${interfaceName}\",
1312       V8ClassIndex::$parentClassIndex, $fieldCount,
1313 END
1314
1315     # Set up our attributes if we have them
1316     if ($has_attributes) {
1317         push(@implContent, <<END);
1318       ${interfaceName}_attrs, sizeof(${interfaceName}_attrs)/sizeof(*${interfaceName}_attrs),
1319 END
1320     } else {
1321         push(@implContent, <<END);
1322       NULL, 0,
1323 END
1324     }
1325     
1326     if ($has_callbacks) {
1327         push(@implContent, <<END);
1328       ${interfaceName}_callbacks, sizeof(${interfaceName}_callbacks)/sizeof(*${interfaceName}_callbacks));
1329 END
1330     } else {
1331         push(@implContent, <<END);
1332       NULL, 0);
1333 END
1334     }
1335
1336     if ($access_check or @enabledAtRuntime or @{$dataNode->functions} or $has_constants) {
1337     push(@implContent,  <<END);
1338   v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate();
1339   v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate();
1340 END
1341     }
1342
1343     push(@implContent,  "  $access_check\n");
1344     
1345     # Setup the enable-at-runtime attrs if we have them
1346     foreach my $runtime_attr (@enabledAtRuntime) {
1347         $enable_function = $interfaceName . $codeGenerator->WK_ucfirst($runtime_attr->signature->name);
1348         my $conditionalString = GenerateConditionalString($runtime_attr->signature);
1349         push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
1350         push(@implContent, "    if (V8Custom::v8${enable_function}Enabled()) {\n");
1351         push(@implContent, "        static const BatchedAttribute attrData =\\\n");
1352         GenerateSingleBatchedAttribute($interfaceName, $runtime_attr, ";", "    ");
1353         push(@implContent, <<END);
1354         configureAttribute(instance, proto, attrData);
1355     }
1356 END
1357         push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
1358     }
1359
1360     # Define our functions with Set() or SetAccessor()
1361     $total_functions = 0;
1362     foreach my $function (@{$dataNode->functions}) {
1363         $total_functions++;
1364         my $attrExt = $function->signature->extendedAttributes;
1365         my $name = $function->signature->name;
1366
1367         my $property_attributes = "v8::DontDelete";
1368         if ($attrExt->{"DontEnum"}) {
1369             $property_attributes .= "|v8::DontEnum";
1370         }
1371         if ($attrExt->{"V8ReadOnly"}) {
1372             $property_attributes .= "|v8::ReadOnly";
1373         }
1374
1375         my $commentInfo = "Function '$name' (ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
1376
1377         my $template = "proto";
1378         if ($attrExt->{"V8OnInstance"}) {
1379             $template = "instance";
1380         }
1381
1382         my $conditional = "";
1383         if ($attrExt->{"EnabledAtRuntime"}) {
1384             # Only call Set()/SetAccessor() if this method should be enabled
1385             $enable_function = $interfaceName . $codeGenerator->WK_ucfirst($function->signature->name);
1386             $conditional = "if (V8Custom::v8${enable_function}Enabled())\n";
1387         }
1388
1389         if ($attrExt->{"DoNotCheckDomainSecurity"} &&
1390             ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) {
1391             # Mark the accessor as ReadOnly and set it on the proto object so
1392             # it can be shadowed. This is really a hack to make it work.
1393             # There are several sceneria to call into the accessor:
1394             #   1) from the same domain: "window.open":
1395             #      the accessor finds the DOM wrapper in the proto chain;
1396             #   2) from the same domain: "window.__proto__.open":
1397             #      the accessor will NOT find a DOM wrapper in the prototype chain
1398             #   3) from another domain: "window.open":
1399             #      the access find the DOM wrapper in the prototype chain
1400             #   "window.__proto__.open" from another domain will fail when
1401             #   accessing '__proto__'
1402             #
1403             # The solution is very hacky and fragile, it really needs to be replaced
1404             # by a better solution.
1405             $property_attributes .= "|v8::ReadOnly";
1406             push(@implContent, <<END);
1407
1408   // $commentInfo
1409   $conditional $template->SetAccessor(
1410       v8::String::New("$name"),
1411       ${interfaceName}Internal::${name}AttrGetter,
1412       0,
1413       v8::Handle<v8::Value>(),
1414       v8::ALL_CAN_READ,
1415       static_cast<v8::PropertyAttribute>($property_attributes));
1416 END
1417           $num_callbacks++;
1418           next;
1419       }
1420
1421       my $signature = "default_signature";
1422       if ($attrExt->{"V8DoNotCheckSignature"}){
1423           $signature = "v8::Local<v8::Signature>()";
1424       }
1425
1426       if (RequiresCustomSignature($function)) {
1427           $signature = "${name}_signature";
1428           push(@implContent, "\n  // Custom Signature '$name'\n", CreateCustomSignature($function));
1429       }
1430
1431       # Normal function call is a template
1432       my $callback = GetFunctionTemplateCallbackName($function, $dataNode);
1433       
1434       if ($property_attributes eq "v8::DontDelete") {
1435           $property_attributes = "";
1436       } else {
1437           $property_attributes = ", static_cast<v8::PropertyAttribute>($property_attributes)";
1438       }
1439       
1440       if ($template eq "proto" && $conditional eq "" && $signature eq "default_signature" && $property_attributes eq "") {
1441           # Standard type of callback, already created in the batch, so skip it here.
1442           next;
1443       }
1444       
1445       push(@implContent, <<END);
1446   ${conditional}createCallback($template, "$name", $callback, ${signature}$property_attributes);
1447 END
1448       $num_callbacks++;
1449     }
1450     
1451     die "Wrong number of callbacks generated for $interfaceName ($num_callbacks, should be $total_functions)" if $num_callbacks != $total_functions;
1452
1453     if ($has_constants) {
1454         push(@implContent, <<END);
1455   batchConfigureConstants(desc, proto, ${interfaceName}_consts, sizeof(${interfaceName}_consts)/sizeof(*${interfaceName}_consts));
1456 END
1457     }
1458
1459     push(@implContent, <<END);
1460   return desc;
1461 }
1462
1463 v8::Persistent<v8::FunctionTemplate> ${className}::GetRawTemplate() {
1464   static v8::Persistent<v8::FunctionTemplate> ${className}_raw_cache_ = createRawTemplate();
1465   return ${className}_raw_cache_;
1466 }
1467
1468 v8::Persistent<v8::FunctionTemplate> ${className}::GetTemplate() {
1469   static v8::Persistent<v8::FunctionTemplate> ${className}_cache_ = Configure${className}Template(GetRawTemplate());
1470   return ${className}_cache_;
1471 }
1472
1473 bool ${className}::HasInstance(v8::Handle<v8::Value> value) {
1474   return GetRawTemplate()->HasInstance(value);
1475 }
1476
1477 END
1478
1479     if ($implClassName eq "DOMWindow") {
1480         push(@implContent, <<END);
1481 v8::Persistent<v8::ObjectTemplate> V8DOMWindow::GetShadowObjectTemplate() {
1482   static v8::Persistent<v8::ObjectTemplate> V8DOMWindowShadowObject_cache_;
1483   if (V8DOMWindowShadowObject_cache_.IsEmpty()) {
1484     V8DOMWindowShadowObject_cache_ = v8::Persistent<v8::ObjectTemplate>::New(v8::ObjectTemplate::New());
1485     ConfigureShadowObjectTemplate(V8DOMWindowShadowObject_cache_);
1486   }
1487   return V8DOMWindowShadowObject_cache_;
1488 }
1489 END
1490     }
1491
1492     push(@implContent, <<END);
1493 } // namespace WebCore
1494 END
1495
1496     push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
1497 }
1498
1499
1500 sub GenerateFunctionCallString()
1501 {
1502     my $function = shift;
1503     my $numberOfParameters = shift;
1504     my $indent = shift;
1505     my $implClassName = shift;
1506
1507     my $name = $function->signature->name;
1508     my $isPodType = IsPodType($implClassName);
1509     my $returnType = GetTypeFromSignature($function->signature);
1510     my $returnsPodType = IsPodType($returnType);
1511     my $nativeReturnType = GetNativeType($returnType, 0);
1512     my $result = "";
1513
1514     # Special case: SVG matrix transform methods should not mutate
1515     # the matrix but return a copy
1516     my $copyFirst = 0;
1517     if ($implClassName eq "SVGMatrix" && $function->signature->type eq "SVGMatrix") {
1518         $copyFirst = 1;
1519     }
1520
1521     if ($function->signature->extendedAttributes->{"v8implname"}) {
1522         $name = $function->signature->extendedAttributes->{"v8implname"};
1523     }
1524
1525     if ($function->signature->extendedAttributes->{"ImplementationFunction"}) {
1526         $name = $function->signature->extendedAttributes->{"ImplementationFunction"};
1527     }
1528
1529     my $functionString = "imp->${name}(";
1530
1531     if ($copyFirst) {
1532         $functionString = "result.${name}(";
1533     }
1534
1535     my $returnsListItemPodType = 0;
1536     # SVG lists functions that return POD types require special handling
1537     if (IsSVGListTypeNeedingSpecialHandling($implClassName) && IsSVGListMethod($name) && $returnsPodType) {
1538         $returnsListItemPodType = 1;
1539         $result .= $indent . "SVGList<RefPtr<SVGPODListItem<$nativeReturnType> > >* listImp = imp;\n";
1540         $functionString = "listImp->${name}(";
1541     }
1542
1543     my $first = 1;
1544     my $index = 0;
1545     my $nodeToReturn = 0;
1546
1547     foreach my $parameter (@{$function->parameters}) {
1548         if ($index eq $numberOfParameters) {
1549             last;
1550         }
1551         if ($first) { $first = 0; }
1552         else { $functionString .= ", "; }
1553         my $paramName = $parameter->name;
1554         my $paramType = $parameter->type;
1555
1556         # This is a bit of a hack... we need to convert parameters to methods on SVG lists
1557         # of POD types which are items in the list to appropriate SVGList<> instances
1558         if ($returnsListItemPodType && $paramType . "List" eq $implClassName) {
1559             $paramName = "SVGPODListItem<" . GetNativeType($paramType, 1) . ">::copy($paramName)";
1560         }
1561
1562         if ($parameter->type eq "NodeFilter" || $parameter->type eq "XPathNSResolver") {
1563             $functionString .= "$paramName.get()";
1564         } else {
1565             $functionString .= $paramName;
1566         }
1567
1568         if ($parameter->extendedAttributes->{"Return"}) {
1569             $nodeToReturn = $parameter->name;
1570         }
1571         $index++;
1572     }
1573
1574     if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
1575         $functionString .= ", " if not $first;
1576         $functionString .= "callStack.get()";
1577         if ($first) { $first = 0; }
1578     }
1579
1580     if (@{$function->raisesExceptions}) {
1581         $functionString .= ", " if not $first;
1582         $functionString .= "ec";
1583     }
1584     $functionString .= ")";
1585
1586     my $return = "result";
1587     my $returnIsRef = IsRefPtrType($returnType);
1588
1589     if ($nodeToReturn) {
1590         # Special case for insertBefore, replaceChild, removeChild and
1591         # appendChild functions from Node.
1592         $result .= $indent . "bool success = $functionString;\n";
1593         if (@{$function->raisesExceptions}) {
1594             $result .= GenerateSetDOMException($indent);
1595         }
1596         $result .= $indent . "if (success)\n";
1597         $result .= $indent . "    " .
1598             "return V8DOMWrapper::convertNodeToV8Object($nodeToReturn);\n";
1599         $result .= $indent . "return v8::Null();\n";
1600         return $result;
1601     } elsif ($returnType eq "void") {
1602         $result .= $indent . "$functionString;\n";
1603     } elsif ($copyFirst) {
1604         $result .=
1605             $indent . GetNativeType($returnType, 0) . " result = *imp;\n" .
1606             $indent . "$functionString;\n";
1607     } elsif ($returnsListItemPodType) {
1608         $result .= $indent . "RefPtr<SVGPODListItem<$nativeReturnType> > result = $functionString;\n";
1609     } elsif (@{$function->raisesExceptions} or $returnsPodType or $isPodType or IsSVGTypeNeedingContextParameter($returnType)) {
1610         $result .= $indent . $nativeReturnType . " result = $functionString;\n";
1611     } else {
1612         # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
1613         $return = $functionString;
1614         $returnIsRef = 0;
1615     }
1616
1617     if (@{$function->raisesExceptions}) {
1618         $result .= GenerateSetDOMException($indent);
1619     }
1620
1621     # If the return type is a POD type, separate out the wrapper generation
1622     if ($returnsListItemPodType) {
1623         $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = ";
1624         $result .= "V8SVGPODTypeWrapperCreatorForList<" . $nativeReturnType . ">::create($return, imp->associatedAttributeName());\n";
1625         $return = "wrapper";
1626     } elsif ($returnsPodType) {
1627         $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = ";
1628         $result .= GenerateSVGStaticPodTypeWrapper($returnType, $return) . ";\n";
1629         $return = "wrapper";
1630     }
1631
1632     my $generatedSVGContextRetrieval = 0;
1633     # If the return type needs an SVG context, output it
1634     if (IsSVGTypeNeedingContextParameter($returnType)) {
1635         $result .= GenerateSVGContextAssignment($implClassName, $return . ".get()", $indent);
1636         $generatedSVGContextRetrieval = 1;
1637     }
1638
1639     if (IsSVGTypeNeedingContextParameter($implClassName) && $implClassName =~ /List$/ && IsSVGListMutator($name)) {
1640         if (!$generatedSVGContextRetrieval) {
1641             $result .= GenerateSVGContextRetrieval($implClassName, $indent);
1642             $generatedSVGContextRetrieval = 1;
1643         }
1644
1645         $result .= $indent . "context->svgAttributeChanged(imp->associatedAttributeName());\n";
1646         $implIncludes{"SVGElement.h"} = 1;
1647     }
1648
1649     # If the implementing class is a POD type, commit changes
1650     if ($isPodType) {
1651         if (!$generatedSVGContextRetrieval) {
1652             $result .= GenerateSVGContextRetrieval($implClassName, $indent);
1653             $generatedSVGContextRetrieval = 1;
1654         }
1655
1656         $result .= $indent . "imp_wrapper->commitChange(imp_instance, context);\n";
1657     }
1658
1659     if ($returnsPodType) {
1660         my $classIndex = uc($returnType);
1661         $result .= $indent . "return V8DOMWrapper::convertToV8Object(V8ClassIndex::$classIndex, wrapper.release());\n";
1662     } else {
1663         $return .= ".release()" if ($returnIsRef);
1664         $result .= $indent . ReturnNativeToJSValue($function->signature, $return, $indent) . ";\n";
1665     }
1666
1667     return $result;
1668 }
1669
1670
1671 sub GetTypeFromSignature
1672 {
1673     my $signature = shift;
1674
1675     my $type = $codeGenerator->StripModule($signature->type);
1676     if (($type eq "DOMString") && ($signature->extendedAttributes->{"HintAtomic"} || $signature->extendedAttributes->{"Reflect"})) {
1677         $type = "AtomicString";
1678     }
1679
1680     return $type;
1681 }
1682
1683
1684 sub GetNativeTypeFromSignature
1685 {
1686     my $signature = shift;
1687     my $isParameter = shift;
1688
1689     my $type = GetTypeFromSignature($signature);
1690
1691     if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) {
1692         # Special-case index arguments because we need to check that they aren't < 0.
1693         return "int";
1694     }
1695
1696     return GetNativeType($type, $isParameter);
1697 }
1698
1699 sub IsRefPtrType
1700 {
1701     my $type = shift;
1702     return 1 if $type eq "Attr";
1703     return 1 if $type eq "WebGLActiveInfo";
1704     return 1 if $type eq "WebGLArray";
1705     return 1 if $type eq "WebGLArrayBuffer";
1706     return 1 if $type eq "CanvasBooleanArray";
1707     return 1 if $type eq "WebGLByteArray";
1708     return 1 if $type eq "WebGLBuffer";
1709     return 1 if $type eq "WebGLFloatArray";
1710     return 1 if $type eq "WebGLFramebuffer";
1711     return 1 if $type eq "CanvasGradient";
1712     return 1 if $type eq "WebGLIntArray";
1713     return 1 if $type eq "CanvasObject";
1714     return 1 if $type eq "WebGLProgram";
1715     return 1 if $type eq "WebGLRenderbuffer";
1716     return 1 if $type eq "WebGLShader";
1717     return 1 if $type eq "WebGLShortArray";
1718     return 1 if $type eq "WebGLTexture";
1719     return 1 if $type eq "WebGLUnsignedByteArray";
1720     return 1 if $type eq "WebGLUnsignedIntArray";
1721     return 1 if $type eq "WebGLUnsignedShortArray";
1722     return 1 if $type eq "ClientRect";
1723     return 1 if $type eq "ClientRectList";
1724     return 1 if $type eq "CDATASection";
1725     return 1 if $type eq "Comment";
1726     return 1 if $type eq "CSSRule";
1727     return 1 if $type eq "CSSStyleRule";
1728     return 1 if $type eq "CSSCharsetRule";
1729     return 1 if $type eq "CSSImportRule";
1730     return 1 if $type eq "CSSMediaRule";
1731     return 1 if $type eq "CSSFontFaceRule";
1732     return 1 if $type eq "CSSPageRule";
1733     return 1 if $type eq "CSSPrimitiveValue";
1734     return 1 if $type eq "CSSStyleSheet";
1735     return 1 if $type eq "CSSStyleDeclaration";
1736     return 1 if $type eq "CSSValue";
1737     return 1 if $type eq "CSSRuleList";
1738     return 1 if $type eq "Database";
1739     return 1 if $type eq "Document";
1740     return 1 if $type eq "DocumentFragment";
1741     return 1 if $type eq "DocumentType";
1742     return 1 if $type eq "Element";
1743     return 1 if $type eq "EntityReference";
1744     return 1 if $type eq "Event";
1745     return 1 if $type eq "EventListener";
1746     return 1 if $type eq "FileList";
1747     return 1 if $type eq "HTMLCollection";
1748     return 1 if $type eq "HTMLAllCollection";
1749     return 1 if $type eq "HTMLDocument";
1750     return 1 if $type eq "HTMLElement";
1751     return 1 if $type eq "HTMLOptionsCollection";
1752     return 1 if $type eq "ImageData";
1753     return 1 if $type eq "Media";
1754     return 1 if $type eq "MediaError";
1755     return 1 if $type eq "MimeType";
1756     return 1 if $type eq "Node";
1757     return 1 if $type eq "NodeList";
1758     return 1 if $type eq "NodeFilter";
1759     return 1 if $type eq "NodeIterator";
1760     return 1 if $type eq "NSResolver";
1761     return 1 if $type eq "Plugin";
1762     return 1 if $type eq "ProcessingInstruction";
1763     return 1 if $type eq "Range";
1764     return 1 if $type eq "RGBColor";
1765     return 1 if $type eq "Text";
1766     return 1 if $type eq "TextMetrics";
1767     return 1 if $type eq "TimeRanges";
1768     return 1 if $type eq "TreeWalker";
1769     return 1 if $type eq "WebKitCSSMatrix";
1770     return 1 if $type eq "WebKitPoint";
1771     return 1 if $type eq "XPathExpression";
1772     return 1 if $type eq "XPathNSResolver";
1773     return 1 if $type eq "XPathResult";
1774
1775     return 1 if $type eq "SVGAngle";
1776     return 1 if $type eq "SVGElementInstance";
1777     return 1 if $type eq "SVGElementInstanceList";
1778     return 1 if $type =~ /^SVGPathSeg/;
1779
1780     return 1 if $type =~ /^SVGAnimated/;
1781
1782     return 0;
1783 }
1784
1785 sub IsVideoClassName
1786 {
1787     my $class = shift;
1788     return 1 if $class eq "V8HTMLAudioElement";
1789     return 1 if $class eq "V8HTMLMediaElement";
1790     return 1 if $class eq "V8HTMLSourceElement";
1791     return 1 if $class eq "V8HTMLVideoElement";
1792     return 1 if $class eq "V8MediaError";
1793     return 1 if $class eq "V8TimeRanges";
1794
1795     return 0;
1796 }
1797
1798 sub IsWorkerClassName
1799 {
1800     my $class = shift;
1801     return 1 if $class eq "V8Worker";
1802     return 1 if $class eq "V8WorkerContext";
1803     return 1 if $class eq "V8WorkerLocation";
1804     return 1 if $class eq "V8WorkerNavigator";
1805
1806     return 0;
1807 }
1808
1809 sub GetNativeType
1810 {
1811     my $type = shift;
1812     my $isParameter = shift;
1813
1814     if ($type eq "float" or $type eq "AtomicString" or $type eq "double") {
1815         return $type;
1816     }
1817
1818     return "int" if $type eq "int";
1819     return "int" if $type eq "short" or $type eq "unsigned short";
1820     return "unsigned" if $type eq "unsigned long";
1821     return "int" if $type eq "long";
1822     return "unsigned long long" if $type eq "unsigned long long";
1823     return "bool" if $type eq "boolean";
1824     return "String" if $type eq "DOMString";
1825     return "Range::CompareHow" if $type eq "CompareHow";
1826     return "FloatRect" if $type eq "SVGRect";
1827     return "FloatPoint" if $type eq "SVGPoint";
1828     return "TransformationMatrix" if $type eq "SVGMatrix";
1829     return "SVGTransform" if $type eq "SVGTransform";
1830     return "SVGLength" if $type eq "SVGLength";
1831     return "double" if $type eq "SVGNumber";
1832     return "SVGPaint::SVGPaintType" if $type eq "SVGPaintType";
1833     return "DOMTimeStamp" if $type eq "DOMTimeStamp";
1834     return "unsigned" if $type eq "unsigned int";
1835     return "Node*" if $type eq "EventTarget" and $isParameter;
1836
1837     return "String" if $type eq "DOMUserData";  # FIXME: Temporary hack?
1838
1839     # temporary hack
1840     return "RefPtr<NodeFilter>" if $type eq "NodeFilter";
1841
1842     # necessary as resolvers could be constructed on fly.
1843     return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver";
1844
1845     return "RefPtr<${type}>" if IsRefPtrType($type) and not $isParameter;
1846
1847     # Default, assume native type is a pointer with same type name as idl type
1848     return "${type}*";
1849 }
1850
1851
1852 my %typeCanFailConversion = (
1853     "AtomicString" => 0,
1854     "Attr" => 1,
1855     "WebGLArray" => 0,
1856     "WebGLBuffer" => 0,
1857     "WebGLByteArray" => 0,
1858     "WebGLFloatArray" => 0,
1859     "WebGLFramebuffer" => 0,
1860     "CanvasGradient" => 0,
1861     "WebGLIntArray" => 0,
1862     "CanvasPixelArray" => 0,
1863     "WebGLProgram" => 0,
1864     "WebGLRenderbuffer" => 0,
1865     "WebGLShader" => 0,
1866     "WebGLShortArray" => 0,
1867     "WebGLTexture" => 0,
1868     "CompareHow" => 0,
1869     "DataGridColumn" => 0,
1870     "DOMString" => 0,
1871     "DOMWindow" => 0,
1872     "DocumentType" => 0,
1873     "Element" => 0,
1874     "Event" => 0,
1875     "EventListener" => 0,
1876     "EventTarget" => 0,
1877     "HTMLCanvasElement" => 0,
1878     "HTMLElement" => 0,
1879     "HTMLImageElement" => 0,
1880     "HTMLOptionElement" => 0,
1881     "HTMLVideoElement" => 0,
1882     "Node" => 0,
1883     "NodeFilter" => 0,
1884     "MessagePort" => 0,
1885     "NSResolver" => 0,
1886     "Range" => 0,
1887     "SQLResultSet" => 0,
1888     "Storage" => 0,
1889     "SVGAngle" => 0,
1890     "SVGElement" => 0,
1891     "SVGLength" => 1,
1892     "SVGMatrix" => 1,
1893     "SVGNumber" => 0,
1894     "SVGPaintType" => 0,
1895     "SVGPathSeg" => 0,
1896     "SVGPoint" => 1,
1897     "SVGRect" => 1,
1898     "SVGTransform" => 1,
1899     "VoidCallback" => 1,
1900     "WebKitCSSMatrix" => 0,
1901     "WebKitPoint" => 0,
1902     "XPathEvaluator" => 0,
1903     "XPathNSResolver" => 0,
1904     "XPathResult" => 0,
1905     "boolean" => 0,
1906     "double" => 0,
1907     "float" => 0,
1908     "long" => 0,
1909     "unsigned long" => 0,
1910     "unsigned short" => 0,
1911 );
1912
1913
1914 sub TranslateParameter
1915 {
1916     my $signature = shift;
1917
1918     # The IDL uses some pseudo-types which don't really exist.
1919     if ($signature->type eq "TimeoutHandler") {
1920       $signature->type("DOMString");
1921     }
1922 }
1923
1924 sub BasicTypeCanFailConversion
1925 {
1926     my $signature = shift;
1927     my $type = GetTypeFromSignature($signature);
1928
1929     return 1 if $type eq "SVGLength";
1930     return 1 if $type eq "SVGMatrix";
1931     return 1 if $type eq "SVGPoint";
1932     return 1 if $type eq "SVGRect";
1933     return 1 if $type eq "SVGTransform";
1934     return 0;
1935 }
1936
1937 sub TypeCanFailConversion
1938 {
1939     my $signature = shift;
1940
1941     my $type = GetTypeFromSignature($signature);
1942
1943     $implIncludes{"ExceptionCode.h"} = 1 if $type eq "Attr";
1944
1945     return $typeCanFailConversion{$type} if exists $typeCanFailConversion{$type};
1946
1947     die "Don't know whether a JS value can fail conversion to type $type.";
1948 }
1949
1950 sub JSValueToNative
1951 {
1952     my $signature = shift;
1953     my $value = shift;
1954     my $okParam = shift;
1955     my $maybeOkParam = $okParam ? ", ${okParam}" : "";
1956
1957     my $type = GetTypeFromSignature($signature);
1958
1959     return "$value" if $type eq "JSObject";
1960     return "$value->BooleanValue()" if $type eq "boolean";
1961     return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $type eq "double";
1962     return "$value->NumberValue()" if $type eq "SVGNumber";
1963
1964     return "toInt32($value${maybeOkParam})" if $type eq "unsigned long" or $type eq "unsigned short" or $type eq "long";
1965     return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "CompareHow";
1966     return "static_cast<SVGPaint::SVGPaintType>($value->ToInt32()->Int32Value())" if $type eq "SVGPaintType";
1967
1968     if ($type eq "AtomicString") {
1969         return "toAtomicWebCoreStringWithNullCheck($value)" if $signature->extendedAttributes->{"ConvertNullToNullString"};
1970         return "v8ValueToAtomicWebCoreString($value)";
1971     }
1972
1973     if ($type eq "DOMUserData") {
1974         return "toWebCoreString(args, $1)" if $value =~ /args\[(\d+)]/;
1975         return "toWebCoreString($value)";
1976     }
1977     if ($type eq "DOMString") {
1978         return "toWebCoreStringWithNullCheck($value)" if $signature->extendedAttributes->{"ConvertNullToNullString"};
1979         return "toWebCoreStringWithNullOrUndefinedCheck($value)" if $signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"};
1980         
1981         return "toWebCoreString(args, $1)" if $value =~ /args\[(\d+)]/;
1982         return "toWebCoreString($value)";
1983     }
1984
1985     if ($type eq "SerializedScriptValue") {
1986         $implIncludes{"SerializedScriptValue.h"} = 1;
1987         return "SerializedScriptValue::create($value)";
1988     }
1989
1990     if ($type eq "NodeFilter") {
1991         return "V8DOMWrapper::wrapNativeNodeFilter($value)";
1992     }
1993
1994     if ($type eq "SVGRect") {
1995         $implIncludes{"FloatRect.h"} = 1;
1996     }
1997
1998     if ($type eq "SVGPoint") {
1999         $implIncludes{"FloatPoint.h"} = 1;
2000     }
2001
2002     # Default, assume autogenerated type conversion routines
2003     $implIncludes{"V8Proxy.h"} = 1;
2004     if ($type eq "EventTarget") {
2005         $implIncludes{"V8Node.h"} = 1;
2006
2007         # EventTarget is not in DOM hierarchy, but all Nodes are EventTarget.
2008         return "V8Node::HasInstance($value) ? v8DOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast($value)) : 0";
2009     }
2010
2011     if ($type eq "XPathNSResolver") {
2012         return "V8DOMWrapper::getXPathNSResolver($value)";
2013     }
2014
2015     AddIncludesForType($type);
2016     # $implIncludes{"$type.h"} = 1 unless AvoidInclusionOfType($type);
2017
2018     if (IsDOMNodeType($type)) {
2019         $implIncludes{"V8${type}.h"} = 1;
2020
2021         # Perform type checks on the parameter, if it is expected Node type,
2022         # return NULL.
2023         return "V8${type}::HasInstance($value) ? v8DOMWrapperToNode<${type}>(v8::Handle<v8::Object>::Cast($value)) : 0";
2024     } else {
2025         # TODO: Temporary to avoid Window name conflict.
2026         my $classIndex = uc($type);
2027         my $implClassName = ${type};
2028
2029         $implIncludes{"V8$type.h"} = 1;
2030
2031         if (IsPodType($type)) {
2032             my $nativeType = GetNativeType($type);
2033             $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
2034
2035             return "V8SVGPODTypeUtil::toSVGPODType<${nativeType}>(V8ClassIndex::${classIndex}, $value${maybeOkParam})"
2036         }
2037
2038         $implIncludes{"V8${type}.h"} = 1;
2039
2040         # Perform type checks on the parameter, if it is expected Node type,
2041         # return NULL.
2042         return "V8${type}::HasInstance($value) ? v8DOMWrapperTo<${implClassName}>(V8ClassIndex::${classIndex}, v8::Handle<v8::Object>::Cast($value)) : 0";
2043     }
2044 }
2045
2046
2047 sub GetV8HeaderName
2048 {
2049     my $type = shift;
2050     return "V8" . GetImplementationFileName($type);
2051 }
2052
2053
2054 sub CreateCustomSignature
2055 {
2056     my $function = shift;
2057     my $count = @{$function->parameters};
2058     my $name = $function->signature->name;
2059     my $result = "  const int ${name}_argc = ${count};\n" .
2060       "  v8::Handle<v8::FunctionTemplate> ${name}_argv[${name}_argc] = { ";
2061     my $first = 1;
2062     foreach my $parameter (@{$function->parameters}) {
2063         if ($first) { $first = 0; }
2064         else { $result .= ", "; }
2065         if (IsWrapperType($parameter->type)) {
2066             if ($parameter->type eq "XPathNSResolver") {
2067                 # Special case for XPathNSResolver.  All other browsers accepts a callable,
2068                 # so, even though it's against IDL, accept objects here.
2069                 $result .= "v8::Handle<v8::FunctionTemplate>()";
2070             } else {
2071                 my $type = $parameter->type;
2072                 my $header = GetV8HeaderName($type);
2073                 $implIncludes{$header} = 1;
2074                 $result .= "V8${type}::GetRawTemplate()";
2075             }
2076         } else {
2077             $result .= "v8::Handle<v8::FunctionTemplate>()";
2078         }
2079     }
2080     $result .= " };\n";
2081     $result .= "  v8::Handle<v8::Signature> ${name}_signature = v8::Signature::New(desc, ${name}_argc, ${name}_argv);\n";
2082     return $result;
2083 }
2084
2085
2086 sub RequiresCustomSignature
2087 {
2088     my $function = shift;
2089     # No signature needed for Custom function
2090     if ($function->signature->extendedAttributes->{"Custom"} ||
2091         $function->signature->extendedAttributes->{"V8Custom"}) {
2092         return 0;
2093     }
2094
2095     foreach my $parameter (@{$function->parameters}) {
2096       if (IsWrapperType($parameter->type)) {
2097           return 1;
2098       }
2099     }
2100     return 0;
2101 }
2102
2103
2104 my %non_wrapper_types = (
2105     'float' => 1,
2106     'AtomicString' => 1,
2107     'double' => 1,
2108     'short' => 1,
2109     'unsigned short' => 1,
2110     'long' => 1,
2111     'unsigned long' => 1,
2112     'boolean' => 1,
2113     'DOMString' => 1,
2114     'CompareHow' => 1,
2115     'SVGRect' => 1,
2116     'SVGPoint' => 1,
2117     'SVGMatrix' => 1,
2118     'SVGTransform' => 1,
2119     'SVGLength' => 1,
2120     'SVGNumber' => 1,
2121     'SVGPaintType' => 1,
2122     'DOMTimeStamp' => 1,
2123     'JSObject' => 1,
2124     'EventTarget' => 1,
2125     'NodeFilter' => 1,
2126     'EventListener' => 1
2127 );
2128
2129
2130 sub IsWrapperType
2131 {
2132     my $type = $codeGenerator->StripModule(shift);
2133     return !($non_wrapper_types{$type});
2134 }
2135
2136 sub IsDOMNodeType
2137 {
2138     my $type = shift;
2139
2140     return 1 if $type eq 'Attr';
2141     return 1 if $type eq 'CDATASection';
2142     return 1 if $type eq 'Comment';
2143     return 1 if $type eq 'Document';
2144     return 1 if $type eq 'DocumentFragment';
2145     return 1 if $type eq 'DocumentType';
2146     return 1 if $type eq 'Element';
2147     return 1 if $type eq 'EntityReference';
2148     return 1 if $type eq 'HTMLCanvasElement';
2149     return 1 if $type eq 'HTMLDocument';
2150     return 1 if $type eq 'HTMLElement';
2151     return 1 if $type eq 'HTMLFormElement';
2152     return 1 if $type eq 'HTMLTableCaptionElement';
2153     return 1 if $type eq 'HTMLTableSectionElement';
2154     return 1 if $type eq 'Node';
2155     return 1 if $type eq 'ProcessingInstruction';
2156     return 1 if $type eq 'SVGElement';
2157     return 1 if $type eq 'SVGDocument';
2158     return 1 if $type eq 'SVGSVGElement';
2159     return 1 if $type eq 'SVGUseElement';
2160     return 1 if $type eq 'Text';
2161
2162     return 0;
2163 }
2164
2165
2166 sub ReturnNativeToJSValue
2167 {
2168     my $signature = shift;
2169     my $value = shift;
2170     my $indent = shift;
2171     my $type = GetTypeFromSignature($signature);
2172     my $className= "V8$type";
2173
2174     return "return v8::Date::New(static_cast<double>($value))" if $type eq "DOMTimeStamp";
2175     return "return v8Boolean($value)" if $type eq "boolean";
2176     return "return v8::Handle<v8::Value>()" if $type eq "void";     # equivalent to v8::Undefined()
2177
2178     # For all the types where we use 'int' as the representation type,
2179     # we use Integer::New which has a fast Smi conversion check.
2180     my $nativeType = GetNativeType($type);
2181     return "return v8::Integer::New($value)" if $nativeType eq "int";
2182     return "return v8::Integer::NewFromUnsigned($value)" if $nativeType eq "unsigned";
2183
2184     return "return v8::Number::New($value)" if $codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType";
2185
2186     if ($codeGenerator->IsStringType($type)) {
2187         my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"};
2188         if (defined $conv) {
2189             return "return v8StringOrNull($value)" if $conv eq "Null";
2190             return "return v8StringOrUndefined($value)" if $conv eq "Undefined";
2191             return "return v8StringOrFalse($value)" if $conv eq "False";
2192
2193             die "Unknown value for ConvertNullStringTo extended attribute";
2194         }
2195         return "return v8String($value)";
2196     }
2197
2198     # V8 specific.
2199     my $implClassName = $type;
2200     AddIncludesForType($type);
2201     # $implIncludes{GetImplementationFileName($type)} = 1 unless AvoidInclusionOfType($type);
2202
2203     # special case for non-DOM node interfaces
2204     if (IsDOMNodeType($type)) {
2205         if ($signature->extendedAttributes->{"ReturnsNew"}) {
2206             return "return V8DOMWrapper::convertNewNodeToV8Object($value)";
2207         } else {
2208             return "return V8DOMWrapper::convertNodeToV8Object($value)";
2209         }
2210     }
2211
2212     if ($type eq "EventTarget" or $type eq "SVGElementInstance") {
2213         return "return V8DOMWrapper::convertEventTargetToV8Object($value)";
2214     }
2215
2216     if ($type eq "Event") {
2217         return "return V8DOMWrapper::convertEventToV8Object($value)";
2218     }
2219
2220     if ($type eq "EventListener") {
2221         return "return V8DOMWrapper::convertEventListenerToV8Object(imp->scriptExecutionContext(), $value)";
2222     }
2223
2224     if ($type eq "SerializedScriptValue") {
2225         $implIncludes{"$type.h"} = 1;
2226         return "return v8String($value->toString())";
2227     }
2228
2229     if ($type eq "DedicatedWorkerContext" or $type eq "WorkerContext" or $type eq "SharedWorkerContext") {
2230         $implIncludes{"WorkerContextExecutionProxy.h"} = 1;
2231         return "return WorkerContextExecutionProxy::convertWorkerContextToV8Object($value)";
2232     }
2233
2234     if ($type eq "WorkerLocation" or $type eq "WorkerNavigator" or $type eq "NotificationCenter") {
2235         $implIncludes{"WorkerContextExecutionProxy.h"} = 1;
2236         my $classIndex = uc($type);
2237
2238         return "return WorkerContextExecutionProxy::convertToV8Object(V8ClassIndex::$classIndex, $value)";
2239     }
2240
2241     else {
2242         $implIncludes{"wtf/RefCounted.h"} = 1;
2243         $implIncludes{"wtf/RefPtr.h"} = 1;
2244         $implIncludes{"wtf/GetPtr.h"} = 1;
2245         my $classIndex = uc($type);
2246
2247         if (IsPodType($type)) {
2248             $value = GenerateSVGStaticPodTypeWrapper($type, $value);
2249         }
2250
2251         return "return V8DOMWrapper::convertToV8Object(V8ClassIndex::$classIndex, $value)";
2252     }
2253 }
2254
2255 sub GenerateSVGStaticPodTypeWrapper {
2256     my $type = shift;
2257     my $value = shift;
2258
2259     $implIncludes{"V8$type.h"}=1;
2260     $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
2261
2262     my $nativeType = GetNativeType($type);
2263     return "V8SVGStaticPODTypeWrapper<$nativeType>::create($value)";
2264 }
2265
2266 # Internal helper
2267 sub WriteData
2268 {
2269     if (defined($IMPL)) {
2270         # Write content to file.
2271         print $IMPL @implContentHeader;
2272
2273         print $IMPL @implFixedHeader;
2274
2275         foreach my $implInclude (sort keys(%implIncludes)) {
2276             my $checkType = $implInclude;
2277             $checkType =~ s/\.h//;
2278
2279             print $IMPL "#include \"$implInclude\"\n" unless $codeGenerator->IsSVGAnimatedType($checkType);
2280         }
2281
2282         print $IMPL "\n";
2283         print $IMPL @implContentDecls;
2284         print $IMPL @implContent;
2285         close($IMPL);
2286         undef($IMPL);
2287
2288         %implIncludes = ();
2289         @implFixedHeader = ();
2290         @implHeaderContent = ();
2291         @implContentDecls = ();
2292         @implContent = ();
2293     }
2294
2295     if (defined($HEADER)) {
2296         # Write content to file.
2297         print $HEADER @headerContent;
2298         close($HEADER);
2299         undef($HEADER);
2300
2301         @headerContent = ();
2302     }
2303 }
2304
2305 sub IsSVGTypeNeedingContextParameter
2306 {
2307     my $implClassName = shift;
2308
2309     if ($implClassName =~ /SVG/ and not $implClassName =~ /Element/) {
2310         return 1 unless $implClassName =~ /SVGPaint/ or $implClassName =~ /SVGColor/ or $implClassName =~ /SVGDocument/;
2311     }
2312
2313     return 0;
2314 }
2315
2316 sub GenerateSVGContextAssignment
2317 {
2318     my $srcType = shift;
2319     my $value = shift;
2320     my $indent = shift;
2321
2322     $result = GenerateSVGContextRetrieval($srcType, $indent);
2323     $result .= $indent . "V8Proxy::setSVGContext($value, context);\n";
2324
2325     return $result;
2326 }
2327
2328 sub GenerateSVGContextRetrieval
2329 {
2330     my $srcType = shift;
2331     my $indent = shift;
2332
2333     my $srcIsPodType = IsPodType($srcType);
2334
2335     my $srcObject = "imp";
2336     if ($srcIsPodType) {
2337         $srcObject = "imp_wrapper";
2338     }
2339
2340     my $contextDecl;
2341
2342     if (IsSVGTypeNeedingContextParameter($srcType)) {
2343         $contextDecl = "V8Proxy::svgContext($srcObject)";
2344     } else {
2345         $contextDecl = $srcObject;
2346     }
2347
2348     return $indent . "SVGElement* context = $contextDecl;\n";
2349 }
2350
2351 sub IsSVGListMutator
2352 {
2353     my $functionName = shift;
2354
2355     return 1 if $functionName eq "clear";
2356     return 1 if $functionName eq "initialize";
2357     return 1 if $functionName eq "insertItemBefore";
2358     return 1 if $functionName eq "replaceItem";
2359     return 1 if $functionName eq "removeItem";
2360     return 1 if $functionName eq "appendItem";
2361
2362     return 0;
2363 }
2364
2365 sub IsSVGListMethod
2366 {
2367     my $functionName = shift;
2368
2369     return 1 if $functionName eq "getFirst";
2370     return 1 if $functionName eq "getLast";
2371     return 1 if $functionName eq "getItem";
2372
2373     return IsSVGListMutator($functionName);
2374 }
2375
2376 sub IsSVGListTypeNeedingSpecialHandling
2377 {
2378     my $className = shift;
2379
2380     return 1 if $className eq "SVGPointList";
2381     return 1 if $className eq "SVGTransformList";
2382
2383     return 0;
2384 }
2385
2386 sub DebugPrint
2387 {
2388     my $output = shift;
2389
2390     print $output;
2391     print "\n";
2392 }