2009-11-13 Vitaly Repeshko <vitalyr@chromium.org>
[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         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
532         if ($getterStringUsesImp && $reflect && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
533             # Generate super-compact call for regular attribute getter:
534             my $contentAttributeName = $reflect eq "1" ? $attrName : $reflect;
535             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
536             $implIncludes{"${namespace}.h"} = 1;
537             push(@implContentDecls, "    return getElementStringAttr(info, ${namespace}::${contentAttributeName}Attr);\n");
538             push(@implContentDecls, "  }\n\n");
539             return;
540             # Skip the rest of the function!
541         }
542         
543         push(@implContentDecls, <<END);
544     v8::Handle<v8::Object> holder = info.Holder();
545 END
546         HolderToNative($dataNode, $implClassName, $classIndex, "info");
547     }
548
549     # Generate security checks if necessary
550     if ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) {
551         push(@implContentDecls, "    if (!V8Proxy::checkNodeSecurity(imp->$attrName())) return v8::Handle<v8::Value>();\n\n");
552     } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) {
553         push(@implContentDecls, "    if (!V8Proxy::checkNodeSecurity(imp->contentDocument())) return v8::Handle<v8::Value>();\n\n");
554     }
555
556     my $useExceptions = 1 if @{$attribute->getterExceptions} and !($isPodType);
557     if ($useExceptions) {
558         $implIncludes{"ExceptionCode.h"} = 1;
559         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
560     }
561
562     if ($attribute->signature->extendedAttributes->{"v8referenceattr"}) {
563         $attrName = $attribute->signature->extendedAttributes->{"v8referenceattr"};
564     }
565
566     my $getterFunc = $codeGenerator->WK_lcfirst($attrName);
567     $getterFunc .= "Animated" if $codeGenerator->IsSVGAnimatedType($attribute->signature->type);
568
569     my $returnType = GetTypeFromSignature($attribute->signature);
570
571     my $getterString;
572     if ($getterStringUsesImp) {
573         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
574         my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
575         if ($reflect || $reflectURL) {
576             my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL);
577             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
578             $implIncludes{"${namespace}.h"} = 1;
579             my $getAttributeFunctionName = $reflectURL ? "getURLAttribute" : "getAttribute";
580             $getterString = "imp->$getAttributeFunctionName(${namespace}::${contentAttributeName}Attr";
581         } else {
582             $getterString = "imp->$getterFunc(";
583         }
584         $getterString .= "ec" if $useExceptions;
585         $getterString .= ")";
586         if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) {
587             $getterString .= ".toInt()";
588         }
589     } else {
590         $getterString = "imp_instance";
591     }
592
593     my $result;
594     my $wrapper;
595
596     if ($attrIsPodType) {
597         $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
598
599         my $getter = $getterString;
600         $getter =~ s/imp->//;
601         $getter =~ s/\(\)//;
602         my $setter = "set" . $codeGenerator->WK_ucfirst($getter);
603
604         my $implClassIsAnimatedType = $codeGenerator->IsSVGAnimatedType($implClassName);
605         if (not $implClassIsAnimatedType and $codeGenerator->IsPodTypeWithWriteableProperties($attrType) and not defined $attribute->signature->extendedAttributes->{"Immutable"}) {
606             if (IsPodType($implClassName)) {
607                 my $wrapper = "V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($getterString, imp_wrapper)";
608                 push(@implContentDecls, "    RefPtr<V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName> > wrapper = $wrapper;\n");
609             } else {
610                 my $wrapper = "V8SVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName>::create(imp, &${implClassName}::$getter, &${implClassName}::$setter)";
611                 push(@implContentDecls, "    RefPtr<V8SVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName> > wrapper = $wrapper;\n");
612             }
613         } else {
614             if ($implClassIsAnimatedType) {
615                 # We can't hash member function pointers, so instead generate
616                 # some hashing material based on the names of the methods.
617                 my $hashhex = substr(Digest::MD5::md5_hex("${implClassName}::$getter ${implClassName}::$setter)"), 0, 8);
618                 my $wrapper = "V8SVGDynamicPODTypeWrapperCache<$nativeType, $implClassName>::lookupOrCreateWrapper(imp, &${implClassName}::$getter, &${implClassName}::$setter, 0x$hashhex)";
619                 push(@implContentDecls, "    RefPtr<V8SVGPODTypeWrapper<" . $nativeType . "> > wrapper = $wrapper;\n");
620             } else {
621                 my $wrapper = GenerateSVGStaticPodTypeWrapper($returnType, $getterString);
622                 push(@implContentDecls, "    RefPtr<V8SVGStaticPODTypeWrapper<" . $nativeType . "> > wrapper = $wrapper;\n");
623             }
624         }
625
626     } else {
627         if ($attribute->signature->type eq "EventListener" && $dataNode->name eq "DOMWindow") {
628             push(@implContentDecls, "    if (!imp->document())\n");
629             push(@implContentDecls, "      return v8::Handle<v8::Value>();\n");
630         }
631
632         if ($useExceptions) {
633             push(@implContentDecls, "    $nativeType v = ");
634             push(@implContentDecls, "$getterString;\n");
635             push(@implContentDecls, GenerateSetDOMException("    "));
636             $result = "v";
637             $result .= ".release()" if (IsRefPtrType($returnType));
638         } else {
639             # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
640             $result = $getterString;
641         }
642     }
643
644     if (IsSVGTypeNeedingContextParameter($attrType) && !$skipContext) {
645         my $resultObject = $result;
646         if ($attrIsPodType) {
647             $resultObject = "wrapper";
648         }
649         push(@implContentDecls, GenerateSVGContextRetrieval($implClassName, "    "));
650         $result = "V8Proxy::withSVGContext($resultObject, context)";
651     }
652
653     if ($attrIsPodType) {
654         my $classIndex = uc($attrType);
655         push(@implContentDecls, "    return V8DOMWrapper::convertToV8Object(V8ClassIndex::$classIndex, wrapper.release());\n");
656     } else {
657         push(@implContentDecls, "    " . ReturnNativeToJSValue($attribute->signature, $result, "    ").";\n");
658     }
659
660     push(@implContentDecls, "  }\n\n");  # end of getter
661 }
662
663
664 sub GenerateReplaceableAttrSetter
665 {
666     my $implClassName = shift;
667
668     $implIncludes{"V8Proxy.h"} = 1;
669
670     push(@implContentDecls,
671        "  static void ${attrName}AttrSetter(v8::Local<v8::String> name," .
672        " v8::Local<v8::Value> value, const v8::AccessorInfo& info) {\n");
673
674     push(@implContentDecls, "    INC_STATS(\"DOM.$implClassName.$attrName._set\");\n");
675
676     push(@implContentDecls, "    v8::Local<v8::String> ${attrName}_string = v8::String::New(\"${attrName}\");\n");
677     push(@implContentDecls, "    info.Holder()->Delete(${attrName}_string);\n");
678     push(@implContentDecls, "    info.This()->Set(${attrName}_string, value);\n");
679     push(@implContentDecls, "  }\n\n");
680 }
681
682
683 sub GenerateNormalAttrSetter
684 {
685     my $attribute = shift;
686     my $dataNode = shift;
687     my $classIndex = shift;
688     my $implClassName = shift;
689     my $interfaceName = shift;
690
691     my $attrExt = $attribute->signature->extendedAttributes;
692
693     $implIncludes{"V8Proxy.h"} = 1;
694
695     push(@implContentDecls,
696        "  static void ${attrName}AttrSetter(v8::Local<v8::String> name," .
697        " v8::Local<v8::Value> value, const v8::AccessorInfo& info) {\n");
698
699     push(@implContentDecls, "    INC_STATS(\"DOM.$implClassName.$attrName._set\");\n");
700
701     my $isPodType = IsPodType($implClassName);
702
703     if ($isPodType) {
704         $implClassName = GetNativeType($implClassName);
705         $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
706         push(@implContentDecls, "    V8SVGPODTypeWrapper<$implClassName>* wrapper = v8DOMWrapperTo<V8SVGPODTypeWrapper<$implClassName> >(V8ClassIndex::$classIndex, info.Holder());\n");
707         push(@implContentDecls, "    $implClassName imp_instance = *wrapper;\n");
708         push(@implContentDecls, "    $implClassName* imp = &imp_instance;\n");
709
710     } elsif ($attrExt->{"v8OnProto"}) {
711       if ($classIndex eq "DOMWINDOW") {
712         push(@implContentDecls, <<END);
713     v8::Handle<v8::Object> holder = info.Holder();
714 END
715       } else {
716         # perform lookup first
717         push(@implContentDecls, <<END);
718     v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::$classIndex, info.This());
719     if (holder.IsEmpty()) return;
720 END
721       }
722         HolderToNative($dataNode, $implClassName, $classIndex, "info");
723     } else {
724         my $attrType = GetTypeFromSignature($attribute->signature);
725         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
726         my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
727         if (($reflect || $reflectURL) && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
728             # Generate super-compact call for regular attribute setter:
729             my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL);
730             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
731             $implIncludes{"${namespace}.h"} = 1;
732             push(@implContentDecls, "    setElementStringAttr(info, ${namespace}::${contentAttributeName}Attr, value);\n");
733             push(@implContentDecls, "  }\n\n");
734             return;
735             # Skip the rest of the function!
736         }
737
738         push(@implContentDecls, <<END);
739     v8::Handle<v8::Object> holder = info.Holder();
740 END
741         HolderToNative($dataNode, $implClassName, $classIndex, "info");
742     }
743
744     my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0);
745     if ($attribute->signature->type eq "EventListener") {
746         if ($dataNode->name eq "DOMWindow") {
747             push(@implContentDecls, "    if (!imp->document())\n");
748             push(@implContentDecls, "      return;\n");
749         }
750     } else {
751         push(@implContentDecls, "    $nativeType v = " . JSValueToNative($attribute->signature, "value") . ";\n");
752     }
753
754     my $result = "";
755     if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) {
756         $result .= "WebCore::String::number(";
757     }
758     $result .= "v";
759     if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) {
760         $result .= ")";
761     }
762     my $returnType = GetTypeFromSignature($attribute->signature);
763     if (IsRefPtrType($returnType)) {
764         $result = "WTF::getPtr(" . $result . ")";
765     }
766
767     my $useExceptions = 1 if @{$attribute->setterExceptions} and !($isPodType);
768
769     if ($useExceptions) {
770         $implIncludes{"ExceptionCode.h"} = 1;
771         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
772     }
773
774     if ($implClassName eq "double") {
775         push(@implContentDecls, "    *imp = $result;\n");
776     } else {
777         my $implSetterFunctionName = $codeGenerator->WK_ucfirst($attrName);
778         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
779         my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
780         if ($reflect || $reflectURL) {
781             my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL);
782             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
783             $implIncludes{"${namespace}.h"} = 1;
784             push(@implContentDecls, "    imp->setAttribute(${namespace}::${contentAttributeName}Attr, $result");
785         } elsif ($attribute->signature->type eq "EventListener") {
786             $implIncludes{"V8AbstractEventListener.h"} = 1;
787             $implIncludes{"V8CustomBinding.h"} = 1;
788             $cacheIndex = GetHiddenDependencyIndex($dataNode, $attrName);
789             push(@implContentDecls, "    transferHiddenDependency(holder, imp->$attrName(), value, $cacheIndex);\n");
790             push(@implContentDecls, "    imp->set$implSetterFunctionName(V8DOMWrapper::getEventListener(imp, value, true, ListenerFindOrCreate)");
791         } else {
792             push(@implContentDecls, "    imp->set$implSetterFunctionName($result");
793         }
794         push(@implContentDecls, ", ec") if $useExceptions;
795         push(@implContentDecls, ");\n");
796     }
797
798     if ($useExceptions) {
799         push(@implContentDecls, "    if (UNLIKELY(ec))\n");
800         push(@implContentDecls, "        V8Proxy::setDOMException(ec);\n");
801     }
802
803     if ($isPodType) {
804         push(@implContentDecls, "    wrapper->commitChange(*imp, V8Proxy::svgContext(wrapper));\n");
805     } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
806         $implIncludes{"SVGElement.h"} = 1;
807
808         my $currentObject = "imp";
809         if ($isPodType) {
810             $currentObject = "wrapper";
811         }
812
813         push(@implContentDecls, "    if (SVGElement* context = V8Proxy::svgContext($currentObject)) {\n");
814         push(@implContentDecls, "        context->svgAttributeChanged(imp->associatedAttributeName());\n");
815         push(@implContentDecls, "    }\n");
816     }
817
818     push(@implContentDecls, "    return;\n");
819     push(@implContentDecls, "  }\n\n");  # end of setter
820 }
821
822 sub GetFunctionTemplateCallbackName
823 {
824     $function = shift;
825     $dataNode = shift;
826     
827     my $interfaceName = $dataNode->name;
828     my $name = $function->signature->name;
829
830     if ($function->signature->extendedAttributes->{"Custom"} ||
831         $function->signature->extendedAttributes->{"V8Custom"}) {
832         if ($function->signature->extendedAttributes->{"Custom"} &&
833             $function->signature->extendedAttributes->{"V8Custom"}) {
834             die "Custom and V8Custom should be mutually exclusive!"
835         }
836         my $customFunc = $function->signature->extendedAttributes->{"Custom"} ||
837                          $function->signature->extendedAttributes->{"V8Custom"};
838         if ($customFunc eq 1) {
839             $customFunc = $interfaceName . $codeGenerator->WK_ucfirst($name);
840         }
841         return "V8Custom::v8${customFunc}Callback";
842     } else {
843         return "${interfaceName}Internal::${name}Callback";
844     }
845 }
846
847 sub GenerateNewFunctionTemplate
848 {
849     $function = shift;
850     $dataNode = shift;
851     $signature = shift;
852
853     my $callback = GetFunctionTemplateCallbackName($function, $dataNode);
854     return "v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), $signature)";
855 }
856
857 sub GenerateFunctionCallback
858 {
859     my $function = shift;
860     my $dataNode = shift;
861     my $classIndex = shift;
862     my $implClassName = shift;
863
864     my $interfaceName = $dataNode->name;
865     my $name = $function->signature->name;
866
867     push(@implContentDecls,
868 "  static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args) {\n" .
869 "    INC_STATS(\"DOM.$implClassName.$name\");\n");
870
871     my $numParameters = @{$function->parameters};
872
873     if ($function->signature->extendedAttributes->{"RequiresAllArguments"}) {
874         push(@implContentDecls,
875             "    if (args.Length() < $numParameters) return v8::Handle<v8::Value>();\n");
876     }
877
878     if (IsPodType($implClassName)) {
879         my $nativeClassName = GetNativeType($implClassName);
880         push(@implContentDecls, "    V8SVGPODTypeWrapper<$nativeClassName>* imp_wrapper = v8DOMWrapperTo<V8SVGPODTypeWrapper<$nativeClassName> >(V8ClassIndex::$classIndex, args.Holder());\n");
881         push(@implContentDecls, "    $nativeClassName imp_instance = *imp_wrapper;\n");
882         push(@implContentDecls, "    $nativeClassName* imp = &imp_instance;\n");
883     } else {
884         push(@implContentDecls, <<END);
885     v8::Handle<v8::Object> holder = args.Holder();
886 END
887         HolderToNative($dataNode, $implClassName, $classIndex);
888     }
889
890   # Check domain security if needed
891     if (($dataNode->extendedAttributes->{"CheckDomainSecurity"}
892        || $interfaceName eq "DOMWindow")
893        && !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
894     # We have not find real use cases yet.
895     push(@implContentDecls,
896 "    if (!V8Proxy::canAccessFrame(imp->frame(), true)) {\n".
897 "      return v8::Handle<v8::Value>();\n" .
898 "    }\n");
899     }
900     
901     my $raisesExceptions = @{$function->raisesExceptions};
902     if (!$raisesExceptions) {
903         foreach my $parameter (@{$function->parameters}) {
904             if (TypeCanFailConversion($parameter) or $parameter->extendedAttributes->{"IsIndex"}) {
905                 $raisesExceptions = 1;
906             }
907         }
908     }
909
910     if ($raisesExceptions) {
911         $implIncludes{"ExceptionCode.h"} = 1;
912         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
913         push(@implContentDecls, "    {\n");
914         # The brace here is needed to prevent the ensuing 'goto fail's from jumping past constructors
915         # of objects (like Strings) declared later, causing compile errors. The block scope ends
916         # right before the label 'fail:'.
917     }
918
919     if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
920         push(@implContentDecls,
921 "    OwnPtr<ScriptCallStack> callStack(ScriptCallStack::create(args, $numParameters));\n".
922 "    if (!callStack)\n".
923 "        return v8::Undefined();\n");
924         $implIncludes{"ScriptCallStack.h"} = 1;
925     }
926     if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) {
927         push(@implContentDecls,
928 "    if (!V8Proxy::checkNodeSecurity(imp->getSVGDocument(ec)))\n" .
929 "      return v8::Handle<v8::Value>();\n");
930     }
931
932     my $paramIndex = 0;
933     foreach my $parameter (@{$function->parameters}) {
934         TranslateParameter($parameter);
935
936         my $parameterName = $parameter->name;
937
938         if ($parameter->extendedAttributes->{"Optional"}) {
939             # Generate early call if there are not enough parameters.
940             push(@implContentDecls, "    if (args.Length() <= $paramIndex) {\n");
941             my $functionCall = GenerateFunctionCallString($function, $paramIndex, "    " x 2, $implClassName);
942             push(@implContentDecls, $functionCall);
943             push(@implContentDecls, "    }\n");
944         }
945
946         if (BasicTypeCanFailConversion($parameter)) {
947             push(@implContentDecls, "    bool ${parameterName}Ok;\n");
948         }
949
950         push(@implContentDecls, "    " . GetNativeTypeFromSignature($parameter, 1) . " $parameterName = ");
951         push(@implContentDecls, JSValueToNative($parameter, "args[$paramIndex]",
952            BasicTypeCanFailConversion($parameter) ?  "${parameterName}Ok" : undef) . ";\n");
953
954         if (TypeCanFailConversion($parameter)) {
955             $implIncludes{"ExceptionCode.h"} = 1;
956             push(@implContentDecls,
957 "    if (UNLIKELY(!$parameterName" . (BasicTypeCanFailConversion($parameter) ? "Ok" : "") . ")) {\n" .
958 "      ec = TYPE_MISMATCH_ERR;\n" .
959 "      goto fail;\n" .
960 "    }\n");
961         }
962
963         if ($parameter->extendedAttributes->{"IsIndex"}) {
964             $implIncludes{"ExceptionCode.h"} = 1;
965             push(@implContentDecls,
966 "    if (UNLIKELY($parameterName < 0)) {\n" .
967 "      ec = INDEX_SIZE_ERR;\n" .
968 "      goto fail;\n" .
969 "    }\n");
970         }
971
972         $paramIndex++;
973     }
974
975     # Build the function call string.
976     my $callString = GenerateFunctionCallString($function, $paramIndex, "    ", $implClassName);
977     push(@implContentDecls, "$callString");
978
979     if ($raisesExceptions) {
980         push(@implContentDecls, "    }\n");
981         push(@implContentDecls, "  fail:\n");
982         push(@implContentDecls, "    V8Proxy::setDOMException(ec);\n");
983         push(@implContentDecls, "    return v8::Handle<v8::Value>();\n");
984     }
985     
986     push(@implContentDecls, "  }\n\n");
987 }
988
989 sub GenerateBatchedAttributeData
990 {
991     my $dataNode = shift;
992     my $interfaceName = $dataNode->name;
993     my $attributes = shift;
994
995     foreach my $attribute (@$attributes) {
996         my $conditionalString = GenerateConditionalString($attribute->signature);
997         push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
998         GenerateSingleBatchedAttribute($interfaceName, $attribute, ",", "");
999         push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
1000     }
1001 }
1002
1003 sub GenerateSingleBatchedAttribute
1004 {
1005     my $interfaceName = shift;
1006     my $attribute = shift;
1007     my $delimiter = shift;
1008     my $indent = shift;
1009     my $attrName = $attribute->signature->name;
1010     my $attrExt = $attribute->signature->extendedAttributes;
1011
1012     my $accessControl = "v8::DEFAULT";
1013     if ($attrExt->{"DoNotCheckDomainSecurityOnGet"}) {
1014         $accessControl = "v8::ALL_CAN_READ";
1015     } elsif ($attrExt->{"DoNotCheckDomainSecurityOnSet"}) {
1016         $accessControl = "v8::ALL_CAN_WRITE";
1017     } elsif ($attrExt->{"DoNotCheckDomainSecurity"}) {
1018         $accessControl = "v8::ALL_CAN_READ";
1019         if (!($attribute->type =~ /^readonly/) && !($attrExt->{"V8ReadOnly"})) {
1020             $accessControl .= "|v8::ALL_CAN_WRITE";
1021         }
1022     }
1023     if ($attrExt->{"V8DisallowShadowing"}) {
1024         $accessControl .= "|v8::PROHIBITS_OVERWRITING";
1025     }
1026     $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")";
1027
1028     my $customAccessor =
1029         $attrExt->{"Custom"} ||
1030         $attrExt->{"CustomSetter"} ||
1031         $attrExt->{"CustomGetter"} ||
1032         $attrExt->{"V8Custom"} ||
1033         $attrExt->{"V8CustomSetter"} ||
1034         $attrExt->{"V8CustomGetter"} ||
1035         "";
1036     if ($customAccessor eq 1) {
1037         # use the naming convension, interface + (capitalize) attr name
1038         $customAccessor = $interfaceName . $codeGenerator->WK_ucfirst($attrName);
1039     }
1040
1041     my $getter;
1042     my $setter;
1043     my $propAttr = "v8::None";
1044     my $hasCustomSetter = 0;
1045
1046     # Check attributes.
1047     if ($attrExt->{"DontEnum"}) {
1048         $propAttr .= "|v8::DontEnum";
1049     }
1050     if ($attrExt->{"V8DisallowShadowing"}) {
1051         $propAttr .= "|v8::DontDelete";
1052     }
1053
1054     my $on_proto = "0 /* on instance */";
1055     my $data = "V8ClassIndex::INVALID_CLASS_INDEX /* no data */";
1056
1057     # Constructor
1058     if ($attribute->signature->type =~ /Constructor$/) {
1059         my $constructorType = $codeGenerator->StripModule($attribute->signature->type);
1060         $constructorType =~ s/Constructor$//;
1061         my $constructorIndex = uc($constructorType);
1062         if ($customAccessor) {
1063             $getter = "V8Custom::v8${customAccessor}AccessorGetter";
1064         } else {
1065             $data = "V8ClassIndex::${constructorIndex}";
1066             $getter = "${interfaceName}Internal::${interfaceName}ConstructorGetter";
1067         }
1068         $setter = "0";
1069         $propAttr = "v8::ReadOnly";
1070
1071     } else {
1072         # Default Getter and Setter
1073         $getter = "${interfaceName}Internal::${attrName}AttrGetter";
1074         $setter = "${interfaceName}Internal::${attrName}AttrSetter";
1075
1076         # Custom Setter
1077         if ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
1078             $hasCustomSetter = 1;
1079             $setter = "V8Custom::v8${customAccessor}AccessorSetter";
1080         }
1081
1082         # Custom Getter
1083         if ($attrExt->{"CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
1084             $getter = "V8Custom::v8${customAccessor}AccessorGetter";
1085         }
1086     }
1087
1088     # Replaceable
1089     if ($attrExt->{"Replaceable"} && !$hasCustomSetter) {
1090         $setter = "0";
1091         # Handle the special case of window.top being marked as Replaceable.
1092         # FIXME: Investigate whether we could treat window.top as replaceable
1093         # and allow shadowing without it being a security hole.
1094         if (!($interfaceName eq "DOMWindow" and $attrName eq "top")) {
1095             $propAttr .= "|v8::ReadOnly";
1096         }
1097     }
1098
1099     # Read only attributes
1100     if ($attribute->type =~ /^readonly/ || $attrExt->{"V8ReadOnly"}) {
1101         $setter = "0";
1102     }
1103
1104     # An accessor can be installed on the proto
1105     if ($attrExt->{"v8OnProto"}) {
1106         $on_proto = "1 /* on proto */";
1107     }
1108
1109     my $commentInfo = "Attribute '$attrName' (Type: '" . $attribute->type .
1110                       "' ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
1111
1112     push(@implContent, $indent . "    {\n");
1113     push(@implContent, $indent . "        \/\/ $commentInfo\n");
1114     push(@implContent, $indent . "        \"$attrName\",\n");
1115     push(@implContent, $indent . "        $getter,\n");
1116     push(@implContent, $indent . "        $setter,\n");
1117     push(@implContent, $indent . "        $data,\n");
1118     push(@implContent, $indent . "        $accessControl,\n");
1119     push(@implContent, $indent . "        static_cast<v8::PropertyAttribute>($propAttr),\n");
1120     push(@implContent, $indent . "        $on_proto\n");
1121     push(@implContent, $indent . "    }" . $delimiter . "\n");
1122 END
1123 }
1124
1125 sub GenerateImplementation
1126 {
1127     my $object = shift;
1128     my $dataNode = shift;
1129     my $interfaceName = $dataNode->name;
1130     my $className = "V8$interfaceName";
1131     my $implClassName = $interfaceName;
1132     my $classIndex = uc($codeGenerator->StripModule($interfaceName));
1133
1134     my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
1135     my $conditionalString = GenerateConditionalString($dataNode);
1136
1137     # - Add default header template
1138     @implContentHeader = split("\r", $headerTemplate);
1139
1140     push(@implFixedHeader,
1141          "#include \"config.h\"\n" .
1142          "#include \"V8Proxy.h\"\n" .
1143          "#include \"V8Binding.h\"\n\n" .
1144          "#undef LOG\n\n");
1145
1146     push(@implFixedHeader, "\n#if ${conditionalString}\n\n") if $conditionalString;
1147
1148     if ($className =~ /^V8SVGAnimated/) {
1149         AddIncludesForSVGAnimatedType($interfaceName);
1150     }
1151
1152     $implIncludes{"${className}.h"} = 1;
1153
1154     AddIncludesForType($interfaceName);
1155     $implIncludes{"V8Proxy.h"} = 1;
1156
1157     push(@implContentDecls, "namespace WebCore {\n");
1158     push(@implContentDecls, "namespace ${interfaceName}Internal {\n\n");
1159     push(@implContentDecls, "template <typename T> void V8_USE(T) { }\n\n");
1160
1161     my $hasConstructors = 0;
1162
1163     # Generate property accessors for attributes.
1164     for ($index = 0; $index < @{$dataNode->attributes}; $index++) {
1165         $attribute = @{$dataNode->attributes}[$index];
1166         $attrName = $attribute->signature->name;
1167         $attrType = $attribute->signature->type;
1168
1169         # Generate special code for the constructor attributes.
1170         if ($attrType =~ /Constructor$/) {
1171             if ($attribute->signature->extendedAttributes->{"CustomGetter"}) {
1172                 $implIncludes{"V8CustomBinding.h"} = 1;
1173             } else {
1174                 $hasConstructors = 1;
1175             }
1176             next;
1177         }
1178
1179         if ($attrType eq "EventListener" && $interfaceName eq "DOMWindow") {
1180             $attribute->signature->extendedAttributes->{"v8OnProto"} = 1;
1181         }
1182
1183         # Do not generate accessor if this is a custom attribute.  The
1184         # call will be forwarded to a hand-written accessor
1185         # implementation.
1186         if ($attribute->signature->extendedAttributes->{"Custom"} ||
1187             $attribute->signature->extendedAttributes->{"V8Custom"}) {
1188             $implIncludes{"V8CustomBinding.h"} = 1;
1189             next;
1190         }
1191
1192         # Generate the accessor.
1193         if ($attribute->signature->extendedAttributes->{"CustomGetter"}) {
1194             $implIncludes{"V8CustomBinding.h"} = 1;
1195         } else {
1196             GenerateNormalAttrGetter($attribute, $dataNode, $classIndex, $implClassName, $interfaceName);
1197         }
1198         if ($attribute->signature->extendedAttributes->{"CustomSetter"} ||
1199             $attribute->signature->extendedAttributes->{"V8CustomSetter"}) {
1200             $implIncludes{"V8CustomBinding.h"} = 1;
1201         } elsif ($attribute->signature->extendedAttributes->{"Replaceable"}) {
1202             $dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"} || die "Replaceable attribute can only be used in interface that defines ExtendsDOMGlobalObject attribute!";
1203             # GenerateReplaceableAttrSetter($implClassName);
1204         } elsif ($attribute->type !~ /^readonly/ && !$attribute->signature->extendedAttributes->{"V8ReadOnly"}) {
1205             GenerateNormalAttrSetter($attribute, $dataNode, $classIndex, $implClassName, $interfaceName);
1206         }
1207     }
1208
1209     if ($hasConstructors) {
1210         GenerateConstructorGetter($implClassName, $classIndex);
1211     }
1212
1213     # Generate methods for functions.
1214     foreach my $function (@{$dataNode->functions}) {
1215         # hack for addEventListener/RemoveEventListener
1216         # FIXME: avoid naming conflict
1217         if ($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"V8Custom"}) {
1218                 $implIncludes{"V8CustomBinding.h"} = 1;
1219         } else {
1220             GenerateFunctionCallback($function, $dataNode, $classIndex, $implClassName);
1221         }
1222
1223         # If the function does not need domain security check, we need to
1224         # generate an access getter that returns different function objects
1225         # for different calling context.
1226         if (($dataNode->extendedAttributes->{"CheckDomainSecurity"} || ($interfaceName eq "DOMWindow")) && $function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
1227             GenerateDomainSafeFunctionGetter($function, $dataNode, $classIndex, $implClassName);
1228         }
1229     }
1230
1231     # Attributes
1232     my $attributes = $dataNode->attributes;
1233
1234     # For the DOMWindow interface we partition the attributes into the
1235     # ones that disallows shadowing and the rest.
1236     my @disallowsShadowing;
1237     # Also separate out attributes that are enabled at runtime so we can process them specially.
1238     my @enabledAtRuntime;
1239     my @normal;
1240     foreach my $attribute (@$attributes) {
1241         if ($interfaceName eq "DOMWindow" && $attribute->signature->extendedAttributes->{"V8DisallowShadowing"}) {
1242             push(@disallowsShadowing, $attribute);
1243         } elsif ($attribute->signature->extendedAttributes->{"EnabledAtRuntime"}) {
1244             push(@enabledAtRuntime, $attribute);
1245         } else {
1246             push(@normal, $attribute);
1247         }
1248     }
1249     $attributes = \@normal;
1250     # Put the attributes that disallow shadowing on the shadow object.
1251     if (@disallowsShadowing) {
1252         push(@implContent, "static const BatchedAttribute shadow_attrs[] = {\n");
1253         GenerateBatchedAttributeData($dataNode, \@disallowsShadowing);
1254         push(@implContent, "};\n");
1255     }
1256
1257     my $has_attributes = 0;
1258     if (@$attributes) {
1259         $has_attributes = 1;
1260         push(@implContent, "static const BatchedAttribute ${interfaceName}_attrs[] = {\n");
1261         GenerateBatchedAttributeData($dataNode, $attributes);
1262         push(@implContent, "};\n");
1263     }
1264     
1265     # Setup table of standard callback functions
1266     $num_callbacks = 0;
1267     $has_callbacks = 0;
1268     foreach my $function (@{$dataNode->functions}) {
1269         my $attrExt = $function->signature->extendedAttributes;
1270         # Don't put any nonstandard functions into this table:
1271         if ($attrExt->{"V8OnInstance"}) {
1272             next;
1273         }
1274         if ($attrExt->{"EnabledAtRuntime"} || RequiresCustomSignature($function) || $attrExt->{"V8DoNotCheckSignature"}) {
1275             next;
1276         }
1277         if ($attrExt->{"DoNotCheckDomainSecurity"} &&
1278             ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) {
1279             next;
1280         }
1281         if ($attrExt->{"DontEnum"} || $attrExt->{"V8ReadOnly"}) {
1282             next;
1283         }
1284         if (!$has_callbacks) {
1285             $has_callbacks = 1;
1286             push(@implContent, "static const BatchedCallback ${interfaceName}_callbacks[] = {\n");
1287         }
1288         my $name = $function->signature->name;
1289         my $callback = GetFunctionTemplateCallbackName($function, $dataNode);
1290         push(@implContent, <<END);
1291   {"$name", $callback},
1292 END
1293         $num_callbacks++;
1294     }
1295     push(@implContent, "};\n")  if $has_callbacks;
1296
1297     # Setup constants
1298     my $has_constants = 0;
1299     if (@{$dataNode->constants}) {
1300         $has_constants = 1;
1301         push(@implContent, "static const BatchedConstant ${interfaceName}_consts[] = {\n");
1302     }
1303     foreach my $constant (@{$dataNode->constants}) {
1304         my $name = $constant->name;
1305         my $value = $constant->value;
1306         # FIXME: we need the static_cast here only because of one constant, NodeFilter.idl
1307         # defines "const unsigned long SHOW_ALL = 0xFFFFFFFF".  It would be better if we
1308         # handled this here, and converted it to a -1 constant in the c++ output.
1309         push(@implContent, <<END);
1310   { "${name}", static_cast<signed int>($value) },
1311 END
1312     }
1313     if ($has_constants) {
1314         push(@implContent, "};\n");
1315     }
1316
1317     push(@implContentDecls, "} // namespace ${interfaceName}Internal\n\n");
1318
1319     my $access_check = "";
1320     if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !($interfaceName eq "DOMWindow")) {
1321         $access_check = "instance->SetAccessCheckCallbacks(V8Custom::v8${interfaceName}NamedSecurityCheck, V8Custom::v8${interfaceName}IndexedSecurityCheck, v8::Integer::New(V8ClassIndex::ToInt(V8ClassIndex::${classIndex})));";
1322     }
1323
1324     # For the DOMWindow interface, generate the shadow object template
1325     # configuration method.
1326     if ($implClassName eq "DOMWindow") {
1327         push(@implContent, <<END);
1328 static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Persistent<v8::ObjectTemplate> templ) {
1329   batchConfigureAttributes(templ,
1330                            v8::Handle<v8::ObjectTemplate>(),
1331                            shadow_attrs,
1332                            sizeof(shadow_attrs)/sizeof(*shadow_attrs));
1333   return templ;
1334 }
1335 END
1336     }
1337
1338     # find the super descriptor
1339     my $parentClassIndex = "INVALID_CLASS_INDEX";
1340     foreach (@{$dataNode->parents}) {
1341         my $parent = $codeGenerator->StripModule($_);
1342         if ($parent eq "EventTarget") { next; }
1343         $implIncludes{"V8${parent}.h"} = 1;
1344         $parentClassIndex = uc($codeGenerator->StripModule($parent));
1345         last;
1346     }
1347
1348     # find the field count
1349     my $fieldCount = "V8Custom::kDefaultWrapperInternalFieldCount";
1350     if (IsNodeSubType($dataNode)) {
1351         $fieldCount = "V8Custom::kNodeMinimumInternalFieldCount";
1352     }
1353     
1354     # Generate the template configuration method
1355     push(@implContent,  <<END);
1356 static v8::Persistent<v8::FunctionTemplate> Configure${className}Template(v8::Persistent<v8::FunctionTemplate> desc) {
1357   v8::Local<v8::Signature> default_signature = configureTemplate(desc, \"${interfaceName}\",
1358       V8ClassIndex::$parentClassIndex, $fieldCount,
1359 END
1360
1361     # Set up our attributes if we have them
1362     if ($has_attributes) {
1363         push(@implContent, <<END);
1364       ${interfaceName}_attrs, sizeof(${interfaceName}_attrs)/sizeof(*${interfaceName}_attrs),
1365 END
1366     } else {
1367         push(@implContent, <<END);
1368       NULL, 0,
1369 END
1370     }
1371     
1372     if ($has_callbacks) {
1373         push(@implContent, <<END);
1374       ${interfaceName}_callbacks, sizeof(${interfaceName}_callbacks)/sizeof(*${interfaceName}_callbacks));
1375 END
1376     } else {
1377         push(@implContent, <<END);
1378       NULL, 0);
1379 END
1380     }
1381
1382     if ($access_check or @enabledAtRuntime or @{$dataNode->functions} or $has_constants) {
1383     push(@implContent,  <<END);
1384   v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate();
1385   v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate();
1386 END
1387     }
1388
1389     push(@implContent,  "  $access_check\n");
1390     
1391     # Setup the enable-at-runtime attrs if we have them
1392     foreach my $runtime_attr (@enabledAtRuntime) {
1393         $enable_function = $interfaceName . $codeGenerator->WK_ucfirst($runtime_attr->signature->name);
1394         my $conditionalString = GenerateConditionalString($runtime_attr->signature);
1395         push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
1396         push(@implContent, "    if (V8Custom::v8${enable_function}Enabled()) {\n");
1397         push(@implContent, "        static const BatchedAttribute attrData =\\\n");
1398         GenerateSingleBatchedAttribute($interfaceName, $runtime_attr, ";", "    ");
1399         push(@implContent, <<END);
1400         configureAttribute(instance, proto, attrData);
1401     }
1402 END
1403         push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
1404     }
1405
1406     # Define our functions with Set() or SetAccessor()
1407     $total_functions = 0;
1408     foreach my $function (@{$dataNode->functions}) {
1409         $total_functions++;
1410         my $attrExt = $function->signature->extendedAttributes;
1411         my $name = $function->signature->name;
1412
1413         my $property_attributes = "v8::DontDelete";
1414         if ($attrExt->{"DontEnum"}) {
1415             $property_attributes .= "|v8::DontEnum";
1416         }
1417         if ($attrExt->{"V8ReadOnly"}) {
1418             $property_attributes .= "|v8::ReadOnly";
1419         }
1420
1421         my $commentInfo = "Function '$name' (ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
1422
1423         my $template = "proto";
1424         if ($attrExt->{"V8OnInstance"}) {
1425             $template = "instance";
1426         }
1427
1428         my $conditional = "";
1429         if ($attrExt->{"EnabledAtRuntime"}) {
1430             # Only call Set()/SetAccessor() if this method should be enabled
1431             $enable_function = $interfaceName . $codeGenerator->WK_ucfirst($function->signature->name);
1432             $conditional = "if (V8Custom::v8${enable_function}Enabled())\n";
1433         }
1434
1435         if ($attrExt->{"DoNotCheckDomainSecurity"} &&
1436             ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) {
1437             # Mark the accessor as ReadOnly and set it on the proto object so
1438             # it can be shadowed. This is really a hack to make it work.
1439             # There are several sceneria to call into the accessor:
1440             #   1) from the same domain: "window.open":
1441             #      the accessor finds the DOM wrapper in the proto chain;
1442             #   2) from the same domain: "window.__proto__.open":
1443             #      the accessor will NOT find a DOM wrapper in the prototype chain
1444             #   3) from another domain: "window.open":
1445             #      the access find the DOM wrapper in the prototype chain
1446             #   "window.__proto__.open" from another domain will fail when
1447             #   accessing '__proto__'
1448             #
1449             # The solution is very hacky and fragile, it really needs to be replaced
1450             # by a better solution.
1451             $property_attributes .= "|v8::ReadOnly";
1452             push(@implContent, <<END);
1453
1454   // $commentInfo
1455   $conditional $template->SetAccessor(
1456       v8::String::New("$name"),
1457       ${interfaceName}Internal::${name}AttrGetter,
1458       0,
1459       v8::Handle<v8::Value>(),
1460       v8::ALL_CAN_READ,
1461       static_cast<v8::PropertyAttribute>($property_attributes));
1462 END
1463           $num_callbacks++;
1464           next;
1465       }
1466
1467       my $signature = "default_signature";
1468       if ($attrExt->{"V8DoNotCheckSignature"}){
1469           $signature = "v8::Local<v8::Signature>()";
1470       }
1471
1472       if (RequiresCustomSignature($function)) {
1473           $signature = "${name}_signature";
1474           push(@implContent, "\n  // Custom Signature '$name'\n", CreateCustomSignature($function));
1475       }
1476
1477       # Normal function call is a template
1478       my $callback = GetFunctionTemplateCallbackName($function, $dataNode);
1479       
1480       if ($property_attributes eq "v8::DontDelete") {
1481           $property_attributes = "";
1482       } else {
1483           $property_attributes = ", static_cast<v8::PropertyAttribute>($property_attributes)";
1484       }
1485       
1486       if ($template eq "proto" && $conditional eq "" && $signature eq "default_signature" && $property_attributes eq "") {
1487           # Standard type of callback, already created in the batch, so skip it here.
1488           next;
1489       }
1490       
1491       push(@implContent, <<END);
1492   ${conditional}createCallback($template, "$name", $callback, ${signature}$property_attributes);
1493 END
1494       $num_callbacks++;
1495     }
1496     
1497     die "Wrong number of callbacks generated for $interfaceName ($num_callbacks, should be $total_functions)" if $num_callbacks != $total_functions;
1498
1499     if ($has_constants) {
1500         push(@implContent, <<END);
1501   batchConfigureConstants(desc, proto, ${interfaceName}_consts, sizeof(${interfaceName}_consts)/sizeof(*${interfaceName}_consts));
1502 END
1503     }
1504
1505     push(@implContent, <<END);
1506   return desc;
1507 }
1508
1509 v8::Persistent<v8::FunctionTemplate> ${className}::GetRawTemplate() {
1510   static v8::Persistent<v8::FunctionTemplate> ${className}_raw_cache_ = createRawTemplate();
1511   return ${className}_raw_cache_;
1512 }
1513
1514 v8::Persistent<v8::FunctionTemplate> ${className}::GetTemplate() {
1515   static v8::Persistent<v8::FunctionTemplate> ${className}_cache_ = Configure${className}Template(GetRawTemplate());
1516   return ${className}_cache_;
1517 }
1518
1519 bool ${className}::HasInstance(v8::Handle<v8::Value> value) {
1520   return GetRawTemplate()->HasInstance(value);
1521 }
1522
1523 END
1524
1525     if ($implClassName eq "DOMWindow") {
1526         push(@implContent, <<END);
1527 v8::Persistent<v8::ObjectTemplate> V8DOMWindow::GetShadowObjectTemplate() {
1528   static v8::Persistent<v8::ObjectTemplate> V8DOMWindowShadowObject_cache_;
1529   if (V8DOMWindowShadowObject_cache_.IsEmpty()) {
1530     V8DOMWindowShadowObject_cache_ = v8::Persistent<v8::ObjectTemplate>::New(v8::ObjectTemplate::New());
1531     ConfigureShadowObjectTemplate(V8DOMWindowShadowObject_cache_);
1532   }
1533   return V8DOMWindowShadowObject_cache_;
1534 }
1535 END
1536     }
1537
1538     push(@implContent, <<END);
1539 } // namespace WebCore
1540 END
1541
1542     push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
1543 }
1544
1545
1546 sub GenerateFunctionCallString()
1547 {
1548     my $function = shift;
1549     my $numberOfParameters = shift;
1550     my $indent = shift;
1551     my $implClassName = shift;
1552
1553     my $name = $function->signature->name;
1554     my $isPodType = IsPodType($implClassName);
1555     my $returnType = GetTypeFromSignature($function->signature);
1556     my $returnsPodType = IsPodType($returnType);
1557     my $nativeReturnType = GetNativeType($returnType, 0);
1558     my $result = "";
1559
1560     # Special case: SVG matrix transform methods should not mutate
1561     # the matrix but return a copy
1562     my $copyFirst = 0;
1563     if ($implClassName eq "SVGMatrix" && $function->signature->type eq "SVGMatrix") {
1564         $copyFirst = 1;
1565     }
1566
1567     if ($function->signature->extendedAttributes->{"v8implname"}) {
1568         $name = $function->signature->extendedAttributes->{"v8implname"};
1569     }
1570
1571     if ($function->signature->extendedAttributes->{"ImplementationFunction"}) {
1572         $name = $function->signature->extendedAttributes->{"ImplementationFunction"};
1573     }
1574
1575     my $functionString = "imp->${name}(";
1576
1577     if ($copyFirst) {
1578         $functionString = "result.${name}(";
1579     }
1580
1581     my $returnsListItemPodType = 0;
1582     # SVG lists functions that return POD types require special handling
1583     if (IsSVGListTypeNeedingSpecialHandling($implClassName) && IsSVGListMethod($name) && $returnsPodType) {
1584         $returnsListItemPodType = 1;
1585         $result .= $indent . "SVGList<RefPtr<SVGPODListItem<$nativeReturnType> > >* listImp = imp;\n";
1586         $functionString = "listImp->${name}(";
1587     }
1588
1589     my $first = 1;
1590     my $index = 0;
1591     my $nodeToReturn = 0;
1592
1593     foreach my $parameter (@{$function->parameters}) {
1594         if ($index eq $numberOfParameters) {
1595             last;
1596         }
1597         if ($first) { $first = 0; }
1598         else { $functionString .= ", "; }
1599         my $paramName = $parameter->name;
1600         my $paramType = $parameter->type;
1601
1602         # This is a bit of a hack... we need to convert parameters to methods on SVG lists
1603         # of POD types which are items in the list to appropriate SVGList<> instances
1604         if ($returnsListItemPodType && $paramType . "List" eq $implClassName) {
1605             $paramName = "SVGPODListItem<" . GetNativeType($paramType, 1) . ">::copy($paramName)";
1606         }
1607
1608         if ($parameter->type eq "NodeFilter" || $parameter->type eq "XPathNSResolver") {
1609             $functionString .= "$paramName.get()";
1610         } else {
1611             $functionString .= $paramName;
1612         }
1613
1614         if ($parameter->extendedAttributes->{"Return"}) {
1615             $nodeToReturn = $parameter->name;
1616         }
1617         $index++;
1618     }
1619
1620     if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
1621         $functionString .= ", " if not $first;
1622         $functionString .= "callStack.get()";
1623         if ($first) { $first = 0; }
1624     }
1625
1626     if (@{$function->raisesExceptions}) {
1627         $functionString .= ", " if not $first;
1628         $functionString .= "ec";
1629     }
1630     $functionString .= ")";
1631
1632     my $return = "result";
1633     my $returnIsRef = IsRefPtrType($returnType);
1634
1635     if ($nodeToReturn) {
1636         # Special case for insertBefore, replaceChild, removeChild and
1637         # appendChild functions from Node.
1638         $result .= $indent . "bool success = $functionString;\n";
1639         if (@{$function->raisesExceptions}) {
1640             $result .= $indent . "if (UNLIKELY(ec)) goto fail;\n";
1641         }
1642         $result .= $indent . "if (success)\n";
1643         $result .= $indent . "    " .
1644             "return V8DOMWrapper::convertNodeToV8Object($nodeToReturn);\n";
1645         $result .= $indent . "return v8::Null();\n";
1646         return $result;
1647     } elsif ($returnType eq "void") {
1648         $result .= $indent . "$functionString;\n";
1649     } elsif ($copyFirst) {
1650         $result .=
1651             $indent . GetNativeType($returnType, 0) . " result = *imp;\n" .
1652             $indent . "$functionString;\n";
1653     } elsif ($returnsListItemPodType) {
1654         $result .= $indent . "RefPtr<SVGPODListItem<$nativeReturnType> > result = $functionString;\n";
1655     } elsif (@{$function->raisesExceptions} or $returnsPodType or $isPodType or IsSVGTypeNeedingContextParameter($returnType)) {
1656         $result .= $indent . $nativeReturnType . " result = $functionString;\n";
1657     } else {
1658         # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
1659         $return = $functionString;
1660         $returnIsRef = 0;
1661     }
1662
1663     if (@{$function->raisesExceptions}) {
1664         $result .= $indent . "if (UNLIKELY(ec)) goto fail;\n";
1665     }
1666
1667     # If the return type is a POD type, separate out the wrapper generation
1668     if ($returnsListItemPodType) {
1669         $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = ";
1670         $result .= "V8SVGPODTypeWrapperCreatorForList<" . $nativeReturnType . ">::create($return, imp->associatedAttributeName());\n";
1671         $return = "wrapper";
1672     } elsif ($returnsPodType) {
1673         $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = ";
1674         $result .= GenerateSVGStaticPodTypeWrapper($returnType, $return) . ";\n";
1675         $return = "wrapper";
1676     }
1677
1678     my $generatedSVGContextRetrieval = 0;
1679     # If the return type needs an SVG context, output it
1680     if (IsSVGTypeNeedingContextParameter($returnType)) {
1681         $result .= GenerateSVGContextAssignment($implClassName, $return . ".get()", $indent);
1682         $generatedSVGContextRetrieval = 1;
1683     }
1684
1685     if (IsSVGTypeNeedingContextParameter($implClassName) && $implClassName =~ /List$/ && IsSVGListMutator($name)) {
1686         if (!$generatedSVGContextRetrieval) {
1687             $result .= GenerateSVGContextRetrieval($implClassName, $indent);
1688             $generatedSVGContextRetrieval = 1;
1689         }
1690
1691         $result .= $indent . "context->svgAttributeChanged(imp->associatedAttributeName());\n";
1692         $implIncludes{"SVGElement.h"} = 1;
1693     }
1694
1695     # If the implementing class is a POD type, commit changes
1696     if ($isPodType) {
1697         if (!$generatedSVGContextRetrieval) {
1698             $result .= GenerateSVGContextRetrieval($implClassName, $indent);
1699             $generatedSVGContextRetrieval = 1;
1700         }
1701
1702         $result .= $indent . "imp_wrapper->commitChange(imp_instance, context);\n";
1703     }
1704
1705     if ($returnsPodType) {
1706         my $classIndex = uc($returnType);
1707         $result .= $indent . "return V8DOMWrapper::convertToV8Object(V8ClassIndex::$classIndex, wrapper.release());\n";
1708     } else {
1709         $return .= ".release()" if ($returnIsRef);
1710         $result .= $indent . ReturnNativeToJSValue($function->signature, $return, $indent) . ";\n";
1711     }
1712
1713     return $result;
1714 }
1715
1716
1717 sub GetTypeFromSignature
1718 {
1719     my $signature = shift;
1720
1721     my $type = $codeGenerator->StripModule($signature->type);
1722     if (($type eq "DOMString") && ($signature->extendedAttributes->{"HintAtomic"} || $signature->extendedAttributes->{"Reflect"})) {
1723         $type = "AtomicString";
1724     }
1725
1726     return $type;
1727 }
1728
1729
1730 sub GetNativeTypeFromSignature
1731 {
1732     my $signature = shift;
1733     my $isParameter = shift;
1734
1735     my $type = GetTypeFromSignature($signature);
1736
1737     if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) {
1738         # Special-case index arguments because we need to check that they aren't < 0.
1739         return "int";
1740     }
1741
1742     return GetNativeType($type, $isParameter);
1743 }
1744
1745 sub IsRefPtrType
1746 {
1747     my $type = shift;
1748     return 1 if $type eq "Attr";
1749     return 1 if $type eq "WebGLActiveInfo";
1750     return 1 if $type eq "WebGLArray";
1751     return 1 if $type eq "WebGLArrayBuffer";
1752     return 1 if $type eq "CanvasBooleanArray";
1753     return 1 if $type eq "WebGLByteArray";
1754     return 1 if $type eq "WebGLBuffer";
1755     return 1 if $type eq "WebGLFloatArray";
1756     return 1 if $type eq "WebGLFramebuffer";
1757     return 1 if $type eq "CanvasGradient";
1758     return 1 if $type eq "WebGLIntArray";
1759     return 1 if $type eq "CanvasObject";
1760     return 1 if $type eq "WebGLProgram";
1761     return 1 if $type eq "WebGLRenderbuffer";
1762     return 1 if $type eq "WebGLShader";
1763     return 1 if $type eq "WebGLShortArray";
1764     return 1 if $type eq "WebGLTexture";
1765     return 1 if $type eq "WebGLUnsignedByteArray";
1766     return 1 if $type eq "WebGLUnsignedIntArray";
1767     return 1 if $type eq "WebGLUnsignedShortArray";
1768     return 1 if $type eq "ClientRect";
1769     return 1 if $type eq "ClientRectList";
1770     return 1 if $type eq "CDATASection";
1771     return 1 if $type eq "Comment";
1772     return 1 if $type eq "CSSRule";
1773     return 1 if $type eq "CSSStyleRule";
1774     return 1 if $type eq "CSSCharsetRule";
1775     return 1 if $type eq "CSSImportRule";
1776     return 1 if $type eq "CSSMediaRule";
1777     return 1 if $type eq "CSSFontFaceRule";
1778     return 1 if $type eq "CSSPageRule";
1779     return 1 if $type eq "CSSPrimitiveValue";
1780     return 1 if $type eq "CSSStyleSheet";
1781     return 1 if $type eq "CSSStyleDeclaration";
1782     return 1 if $type eq "CSSValue";
1783     return 1 if $type eq "CSSRuleList";
1784     return 1 if $type eq "Database";
1785     return 1 if $type eq "Document";
1786     return 1 if $type eq "DocumentFragment";
1787     return 1 if $type eq "DocumentType";
1788     return 1 if $type eq "Element";
1789     return 1 if $type eq "EntityReference";
1790     return 1 if $type eq "Event";
1791     return 1 if $type eq "EventListener";
1792     return 1 if $type eq "FileList";
1793     return 1 if $type eq "HTMLCollection";
1794     return 1 if $type eq "HTMLAllCollection";
1795     return 1 if $type eq "HTMLDocument";
1796     return 1 if $type eq "HTMLElement";
1797     return 1 if $type eq "HTMLOptionsCollection";
1798     return 1 if $type eq "ImageData";
1799     return 1 if $type eq "Media";
1800     return 1 if $type eq "MediaError";
1801     return 1 if $type eq "MimeType";
1802     return 1 if $type eq "Node";
1803     return 1 if $type eq "NodeList";
1804     return 1 if $type eq "NodeFilter";
1805     return 1 if $type eq "NodeIterator";
1806     return 1 if $type eq "NSResolver";
1807     return 1 if $type eq "Plugin";
1808     return 1 if $type eq "ProcessingInstruction";
1809     return 1 if $type eq "Range";
1810     return 1 if $type eq "RGBColor";
1811     return 1 if $type eq "Text";
1812     return 1 if $type eq "TextMetrics";
1813     return 1 if $type eq "TimeRanges";
1814     return 1 if $type eq "TreeWalker";
1815     return 1 if $type eq "WebKitCSSMatrix";
1816     return 1 if $type eq "WebKitPoint";
1817     return 1 if $type eq "XPathExpression";
1818     return 1 if $type eq "XPathNSResolver";
1819     return 1 if $type eq "XPathResult";
1820
1821     return 1 if $type eq "SVGAngle";
1822     return 1 if $type eq "SVGElementInstance";
1823     return 1 if $type eq "SVGElementInstanceList";
1824     return 1 if $type =~ /^SVGPathSeg/;
1825
1826     return 1 if $type =~ /^SVGAnimated/;
1827
1828     return 0;
1829 }
1830
1831 sub IsVideoClassName
1832 {
1833     my $class = shift;
1834     return 1 if $class eq "V8HTMLAudioElement";
1835     return 1 if $class eq "V8HTMLMediaElement";
1836     return 1 if $class eq "V8HTMLSourceElement";
1837     return 1 if $class eq "V8HTMLVideoElement";
1838     return 1 if $class eq "V8MediaError";
1839     return 1 if $class eq "V8TimeRanges";
1840
1841     return 0;
1842 }
1843
1844 sub IsWorkerClassName
1845 {
1846     my $class = shift;
1847     return 1 if $class eq "V8Worker";
1848     return 1 if $class eq "V8WorkerContext";
1849     return 1 if $class eq "V8WorkerLocation";
1850     return 1 if $class eq "V8WorkerNavigator";
1851
1852     return 0;
1853 }
1854
1855 sub GetNativeType
1856 {
1857     my $type = shift;
1858     my $isParameter = shift;
1859
1860     if ($type eq "float" or $type eq "AtomicString" or $type eq "double") {
1861         return $type;
1862     }
1863
1864     return "int" if $type eq "int";
1865     return "int" if $type eq "short" or $type eq "unsigned short";
1866     return "unsigned" if $type eq "unsigned long";
1867     return "int" if $type eq "long";
1868     return "unsigned long long" if $type eq "unsigned long long";
1869     return "bool" if $type eq "boolean";
1870     return "String" if $type eq "DOMString";
1871     return "Range::CompareHow" if $type eq "CompareHow";
1872     return "FloatRect" if $type eq "SVGRect";
1873     return "FloatPoint" if $type eq "SVGPoint";
1874     return "TransformationMatrix" if $type eq "SVGMatrix";
1875     return "SVGTransform" if $type eq "SVGTransform";
1876     return "SVGLength" if $type eq "SVGLength";
1877     return "double" if $type eq "SVGNumber";
1878     return "SVGPaint::SVGPaintType" if $type eq "SVGPaintType";
1879     return "DOMTimeStamp" if $type eq "DOMTimeStamp";
1880     return "unsigned" if $type eq "unsigned int";
1881     return "Node*" if $type eq "EventTarget" and $isParameter;
1882
1883     return "String" if $type eq "DOMUserData";  # FIXME: Temporary hack?
1884
1885     # temporary hack
1886     return "RefPtr<NodeFilter>" if $type eq "NodeFilter";
1887
1888     # necessary as resolvers could be constructed on fly.
1889     return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver";
1890
1891     return "RefPtr<${type}>" if IsRefPtrType($type) and not $isParameter;
1892
1893     # Default, assume native type is a pointer with same type name as idl type
1894     return "${type}*";
1895 }
1896
1897
1898 my %typeCanFailConversion = (
1899     "AtomicString" => 0,
1900     "Attr" => 1,
1901     "WebGLArray" => 0,
1902     "WebGLBuffer" => 0,
1903     "WebGLByteArray" => 0,
1904     "WebGLFloatArray" => 0,
1905     "WebGLFramebuffer" => 0,
1906     "CanvasGradient" => 0,
1907     "WebGLIntArray" => 0,
1908     "CanvasPixelArray" => 0,
1909     "WebGLProgram" => 0,
1910     "WebGLRenderbuffer" => 0,
1911     "WebGLShader" => 0,
1912     "WebGLShortArray" => 0,
1913     "WebGLTexture" => 0,
1914     "CompareHow" => 0,
1915     "DataGridColumn" => 0,
1916     "DOMString" => 0,
1917     "DOMWindow" => 0,
1918     "DocumentType" => 0,
1919     "Element" => 0,
1920     "Event" => 0,
1921     "EventListener" => 0,
1922     "EventTarget" => 0,
1923     "HTMLCanvasElement" => 0,
1924     "HTMLElement" => 0,
1925     "HTMLImageElement" => 0,
1926     "HTMLOptionElement" => 0,
1927     "HTMLVideoElement" => 0,
1928     "Node" => 0,
1929     "NodeFilter" => 0,
1930     "MessagePort" => 0,
1931     "NSResolver" => 0,
1932     "Range" => 0,
1933     "SQLResultSet" => 0,
1934     "Storage" => 0,
1935     "SVGAngle" => 0,
1936     "SVGElement" => 0,
1937     "SVGLength" => 1,
1938     "SVGMatrix" => 1,
1939     "SVGNumber" => 0,
1940     "SVGPaintType" => 0,
1941     "SVGPathSeg" => 0,
1942     "SVGPoint" => 1,
1943     "SVGRect" => 1,
1944     "SVGTransform" => 1,
1945     "VoidCallback" => 1,
1946     "WebKitCSSMatrix" => 0,
1947     "WebKitPoint" => 0,
1948     "XPathEvaluator" => 0,
1949     "XPathNSResolver" => 0,
1950     "XPathResult" => 0,
1951     "boolean" => 0,
1952     "double" => 0,
1953     "float" => 0,
1954     "long" => 0,
1955     "unsigned long" => 0,
1956     "unsigned short" => 0,
1957 );
1958
1959
1960 sub TranslateParameter
1961 {
1962     my $signature = shift;
1963
1964     # The IDL uses some pseudo-types which don't really exist.
1965     if ($signature->type eq "TimeoutHandler") {
1966       $signature->type("DOMString");
1967     }
1968 }
1969
1970 sub BasicTypeCanFailConversion
1971 {
1972     my $signature = shift;
1973     my $type = GetTypeFromSignature($signature);
1974
1975     return 1 if $type eq "SVGLength";
1976     return 1 if $type eq "SVGMatrix";
1977     return 1 if $type eq "SVGPoint";
1978     return 1 if $type eq "SVGRect";
1979     return 1 if $type eq "SVGTransform";
1980     return 0;
1981 }
1982
1983 sub TypeCanFailConversion
1984 {
1985     my $signature = shift;
1986
1987     my $type = GetTypeFromSignature($signature);
1988
1989     $implIncludes{"ExceptionCode.h"} = 1 if $type eq "Attr";
1990
1991     return $typeCanFailConversion{$type} if exists $typeCanFailConversion{$type};
1992
1993     die "Don't know whether a JS value can fail conversion to type $type.";
1994 }
1995
1996 sub JSValueToNative
1997 {
1998     my $signature = shift;
1999     my $value = shift;
2000     my $okParam = shift;
2001     my $maybeOkParam = $okParam ? ", ${okParam}" : "";
2002
2003     my $type = GetTypeFromSignature($signature);
2004
2005     return "$value" if $type eq "JSObject";
2006     return "$value->BooleanValue()" if $type eq "boolean";
2007     return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $type eq "double";
2008     return "$value->NumberValue()" if $type eq "SVGNumber";
2009
2010     return "toInt32($value${maybeOkParam})" if $type eq "unsigned long" or $type eq "unsigned short" or $type eq "long";
2011     return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "CompareHow";
2012     return "static_cast<SVGPaint::SVGPaintType>($value->ToInt32()->Int32Value())" if $type eq "SVGPaintType";
2013
2014     if ($type eq "AtomicString") {
2015         return "toAtomicWebCoreStringWithNullCheck($value)" if $signature->extendedAttributes->{"ConvertNullToNullString"};
2016         return "v8ValueToAtomicWebCoreString($value)";
2017     }
2018
2019     if ($type eq "DOMUserData") {
2020         return "toWebCoreString(args, $1)" if $value =~ /args\[(\d+)]/;
2021         return "toWebCoreString($value)";
2022     }
2023     if ($type eq "DOMString") {
2024         return "toWebCoreStringWithNullCheck($value)" if $signature->extendedAttributes->{"ConvertNullToNullString"};
2025         return "toWebCoreStringWithNullOrUndefinedCheck($value)" if $signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"};
2026         
2027         return "toWebCoreString(args, $1)" if $value =~ /args\[(\d+)]/;
2028         return "toWebCoreString($value)";
2029     }
2030
2031     if ($type eq "SerializedScriptValue") {
2032         $implIncludes{"SerializedScriptValue.h"} = 1;
2033         return "SerializedScriptValue::create($value)";
2034     }
2035
2036     if ($type eq "NodeFilter") {
2037         return "V8DOMWrapper::wrapNativeNodeFilter($value)";
2038     }
2039
2040     if ($type eq "SVGRect") {
2041         $implIncludes{"FloatRect.h"} = 1;
2042     }
2043
2044     if ($type eq "SVGPoint") {
2045         $implIncludes{"FloatPoint.h"} = 1;
2046     }
2047
2048     # Default, assume autogenerated type conversion routines
2049     $implIncludes{"V8Proxy.h"} = 1;
2050     if ($type eq "EventTarget") {
2051         $implIncludes{"V8Node.h"} = 1;
2052
2053         # EventTarget is not in DOM hierarchy, but all Nodes are EventTarget.
2054         return "V8Node::HasInstance($value) ? v8DOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast($value)) : 0";
2055     }
2056
2057     if ($type eq "XPathNSResolver") {
2058         return "V8DOMWrapper::getXPathNSResolver($value)";
2059     }
2060
2061     AddIncludesForType($type);
2062     # $implIncludes{"$type.h"} = 1 unless AvoidInclusionOfType($type);
2063
2064     if (IsDOMNodeType($type)) {
2065         $implIncludes{"V8${type}.h"} = 1;
2066
2067         # Perform type checks on the parameter, if it is expected Node type,
2068         # return NULL.
2069         return "V8${type}::HasInstance($value) ? v8DOMWrapperToNode<${type}>(v8::Handle<v8::Object>::Cast($value)) : 0";
2070     } else {
2071         # TODO: Temporary to avoid Window name conflict.
2072         my $classIndex = uc($type);
2073         my $implClassName = ${type};
2074
2075         $implIncludes{"V8$type.h"} = 1;
2076
2077         if (IsPodType($type)) {
2078             my $nativeType = GetNativeType($type);
2079             $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
2080
2081             return "V8SVGPODTypeUtil::toSVGPODType<${nativeType}>(V8ClassIndex::${classIndex}, $value${maybeOkParam})"
2082         }
2083
2084         $implIncludes{"V8${type}.h"} = 1;
2085
2086         # Perform type checks on the parameter, if it is expected Node type,
2087         # return NULL.
2088         return "V8${type}::HasInstance($value) ? v8DOMWrapperTo<${implClassName}>(V8ClassIndex::${classIndex}, v8::Handle<v8::Object>::Cast($value)) : 0";
2089     }
2090 }
2091
2092
2093 sub GetV8HeaderName
2094 {
2095     my $type = shift;
2096     return "V8" . GetImplementationFileName($type);
2097 }
2098
2099
2100 sub CreateCustomSignature
2101 {
2102     my $function = shift;
2103     my $count = @{$function->parameters};
2104     my $name = $function->signature->name;
2105     my $result = "  const int ${name}_argc = ${count};\n" .
2106       "  v8::Handle<v8::FunctionTemplate> ${name}_argv[${name}_argc] = { ";
2107     my $first = 1;
2108     foreach my $parameter (@{$function->parameters}) {
2109         if ($first) { $first = 0; }
2110         else { $result .= ", "; }
2111         if (IsWrapperType($parameter->type)) {
2112             if ($parameter->type eq "XPathNSResolver") {
2113                 # Special case for XPathNSResolver.  All other browsers accepts a callable,
2114                 # so, even though it's against IDL, accept objects here.
2115                 $result .= "v8::Handle<v8::FunctionTemplate>()";
2116             } else {
2117                 my $type = $parameter->type;
2118                 my $header = GetV8HeaderName($type);
2119                 $implIncludes{$header} = 1;
2120                 $result .= "V8${type}::GetRawTemplate()";
2121             }
2122         } else {
2123             $result .= "v8::Handle<v8::FunctionTemplate>()";
2124         }
2125     }
2126     $result .= " };\n";
2127     $result .= "  v8::Handle<v8::Signature> ${name}_signature = v8::Signature::New(desc, ${name}_argc, ${name}_argv);\n";
2128     return $result;
2129 }
2130
2131
2132 sub RequiresCustomSignature
2133 {
2134     my $function = shift;
2135     # No signature needed for Custom function
2136     if ($function->signature->extendedAttributes->{"Custom"} ||
2137         $function->signature->extendedAttributes->{"V8Custom"}) {
2138         return 0;
2139     }
2140
2141     foreach my $parameter (@{$function->parameters}) {
2142       if (IsWrapperType($parameter->type)) {
2143           return 1;
2144       }
2145     }
2146     return 0;
2147 }
2148
2149
2150 my %non_wrapper_types = (
2151     'float' => 1,
2152     'AtomicString' => 1,
2153     'double' => 1,
2154     'short' => 1,
2155     'unsigned short' => 1,
2156     'long' => 1,
2157     'unsigned long' => 1,
2158     'boolean' => 1,
2159     'DOMString' => 1,
2160     'CompareHow' => 1,
2161     'SVGRect' => 1,
2162     'SVGPoint' => 1,
2163     'SVGMatrix' => 1,
2164     'SVGTransform' => 1,
2165     'SVGLength' => 1,
2166     'SVGNumber' => 1,
2167     'SVGPaintType' => 1,
2168     'DOMTimeStamp' => 1,
2169     'JSObject' => 1,
2170     'EventTarget' => 1,
2171     'NodeFilter' => 1,
2172     'EventListener' => 1
2173 );
2174
2175
2176 sub IsWrapperType
2177 {
2178     my $type = $codeGenerator->StripModule(shift);
2179     return !($non_wrapper_types{$type});
2180 }
2181
2182 sub IsDOMNodeType
2183 {
2184     my $type = shift;
2185
2186     return 1 if $type eq 'Attr';
2187     return 1 if $type eq 'CDATASection';
2188     return 1 if $type eq 'Comment';
2189     return 1 if $type eq 'Document';
2190     return 1 if $type eq 'DocumentFragment';
2191     return 1 if $type eq 'DocumentType';
2192     return 1 if $type eq 'Element';
2193     return 1 if $type eq 'EntityReference';
2194     return 1 if $type eq 'HTMLCanvasElement';
2195     return 1 if $type eq 'HTMLDocument';
2196     return 1 if $type eq 'HTMLElement';
2197     return 1 if $type eq 'HTMLFormElement';
2198     return 1 if $type eq 'HTMLTableCaptionElement';
2199     return 1 if $type eq 'HTMLTableSectionElement';
2200     return 1 if $type eq 'Node';
2201     return 1 if $type eq 'ProcessingInstruction';
2202     return 1 if $type eq 'SVGElement';
2203     return 1 if $type eq 'SVGDocument';
2204     return 1 if $type eq 'SVGSVGElement';
2205     return 1 if $type eq 'SVGUseElement';
2206     return 1 if $type eq 'Text';
2207
2208     return 0;
2209 }
2210
2211
2212 sub ReturnNativeToJSValue
2213 {
2214     my $signature = shift;
2215     my $value = shift;
2216     my $indent = shift;
2217     my $type = GetTypeFromSignature($signature);
2218     my $className= "V8$type";
2219
2220     return "return v8::Date::New(static_cast<double>($value))" if $type eq "DOMTimeStamp";
2221     return "return v8Boolean($value)" if $type eq "boolean";
2222     return "return v8::Handle<v8::Value>()" if $type eq "void";     # equivalent to v8::Undefined()
2223
2224     # For all the types where we use 'int' as the representation type,
2225     # we use Integer::New which has a fast Smi conversion check.
2226     my $nativeType = GetNativeType($type);
2227     return "return v8::Integer::New($value)" if $nativeType eq "int";
2228     return "return v8::Integer::NewFromUnsigned($value)" if $nativeType eq "unsigned";
2229
2230     return "return v8::Number::New($value)" if $codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType";
2231
2232     if ($codeGenerator->IsStringType($type)) {
2233         my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"};
2234         if (defined $conv) {
2235             return "return v8StringOrNull($value)" if $conv eq "Null";
2236             return "return v8StringOrUndefined($value)" if $conv eq "Undefined";
2237             return "return v8StringOrFalse($value)" if $conv eq "False";
2238
2239             die "Unknown value for ConvertNullStringTo extended attribute";
2240         }
2241         return "return v8String($value)";
2242     }
2243
2244     # V8 specific.
2245     my $implClassName = $type;
2246     AddIncludesForType($type);
2247     # $implIncludes{GetImplementationFileName($type)} = 1 unless AvoidInclusionOfType($type);
2248
2249     # special case for non-DOM node interfaces
2250     if (IsDOMNodeType($type)) {
2251         if ($signature->extendedAttributes->{"ReturnsNew"}) {
2252             return "return V8DOMWrapper::convertNewNodeToV8Object($value)";
2253         } else {
2254             return "return V8DOMWrapper::convertNodeToV8Object($value)";
2255         }
2256     }
2257
2258     if ($type eq "EventTarget" or $type eq "SVGElementInstance") {
2259         return "return V8DOMWrapper::convertEventTargetToV8Object($value)";
2260     }
2261
2262     if ($type eq "Event") {
2263         return "return V8DOMWrapper::convertEventToV8Object($value)";
2264     }
2265
2266     if ($type eq "EventListener") {
2267         return "return V8DOMWrapper::convertEventListenerToV8Object(imp->scriptExecutionContext(), $value)";
2268     }
2269
2270     if ($type eq "SerializedScriptValue") {
2271         $implIncludes{"$type.h"} = 1;
2272         return "return v8String($value->toString())";
2273     }
2274
2275     if ($type eq "DedicatedWorkerContext" or $type eq "WorkerContext" or $type eq "SharedWorkerContext") {
2276         $implIncludes{"WorkerContextExecutionProxy.h"} = 1;
2277         return "return WorkerContextExecutionProxy::convertWorkerContextToV8Object($value)";
2278     }
2279
2280     if ($type eq "WorkerLocation" or $type eq "WorkerNavigator" or $type eq "NotificationCenter") {
2281         $implIncludes{"WorkerContextExecutionProxy.h"} = 1;
2282         my $classIndex = uc($type);
2283
2284         return "return WorkerContextExecutionProxy::convertToV8Object(V8ClassIndex::$classIndex, $value)";
2285     }
2286
2287     else {
2288         $implIncludes{"wtf/RefCounted.h"} = 1;
2289         $implIncludes{"wtf/RefPtr.h"} = 1;
2290         $implIncludes{"wtf/GetPtr.h"} = 1;
2291         my $classIndex = uc($type);
2292
2293         if (IsPodType($type)) {
2294             $value = GenerateSVGStaticPodTypeWrapper($type, $value);
2295         }
2296
2297         return "return V8DOMWrapper::convertToV8Object(V8ClassIndex::$classIndex, $value)";
2298     }
2299 }
2300
2301 sub GenerateSVGStaticPodTypeWrapper {
2302     my $type = shift;
2303     my $value = shift;
2304
2305     $implIncludes{"V8$type.h"}=1;
2306     $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
2307
2308     my $nativeType = GetNativeType($type);
2309     return "V8SVGStaticPODTypeWrapper<$nativeType>::create($value)";
2310 }
2311
2312 # Internal helper
2313 sub WriteData
2314 {
2315     if (defined($IMPL)) {
2316         # Write content to file.
2317         print $IMPL @implContentHeader;
2318
2319         print $IMPL @implFixedHeader;
2320
2321         foreach my $implInclude (sort keys(%implIncludes)) {
2322             my $checkType = $implInclude;
2323             $checkType =~ s/\.h//;
2324
2325             print $IMPL "#include \"$implInclude\"\n" unless $codeGenerator->IsSVGAnimatedType($checkType);
2326         }
2327
2328         print $IMPL "\n";
2329         print $IMPL @implContentDecls;
2330         print $IMPL @implContent;
2331         close($IMPL);
2332         undef($IMPL);
2333
2334         %implIncludes = ();
2335         @implFixedHeader = ();
2336         @implHeaderContent = ();
2337         @implContentDecls = ();
2338         @implContent = ();
2339     }
2340
2341     if (defined($HEADER)) {
2342         # Write content to file.
2343         print $HEADER @headerContent;
2344         close($HEADER);
2345         undef($HEADER);
2346
2347         @headerContent = ();
2348     }
2349 }
2350
2351 sub IsSVGTypeNeedingContextParameter
2352 {
2353     my $implClassName = shift;
2354
2355     if ($implClassName =~ /SVG/ and not $implClassName =~ /Element/) {
2356         return 1 unless $implClassName =~ /SVGPaint/ or $implClassName =~ /SVGColor/ or $implClassName =~ /SVGDocument/;
2357     }
2358
2359     return 0;
2360 }
2361
2362 sub GenerateSVGContextAssignment
2363 {
2364     my $srcType = shift;
2365     my $value = shift;
2366     my $indent = shift;
2367
2368     $result = GenerateSVGContextRetrieval($srcType, $indent);
2369     $result .= $indent . "V8Proxy::setSVGContext($value, context);\n";
2370
2371     return $result;
2372 }
2373
2374 sub GenerateSVGContextRetrieval
2375 {
2376     my $srcType = shift;
2377     my $indent = shift;
2378
2379     my $srcIsPodType = IsPodType($srcType);
2380
2381     my $srcObject = "imp";
2382     if ($srcIsPodType) {
2383         $srcObject = "imp_wrapper";
2384     }
2385
2386     my $contextDecl;
2387
2388     if (IsSVGTypeNeedingContextParameter($srcType)) {
2389         $contextDecl = "V8Proxy::svgContext($srcObject)";
2390     } else {
2391         $contextDecl = $srcObject;
2392     }
2393
2394     return $indent . "SVGElement* context = $contextDecl;\n";
2395 }
2396
2397 sub IsSVGListMutator
2398 {
2399     my $functionName = shift;
2400
2401     return 1 if $functionName eq "clear";
2402     return 1 if $functionName eq "initialize";
2403     return 1 if $functionName eq "insertItemBefore";
2404     return 1 if $functionName eq "replaceItem";
2405     return 1 if $functionName eq "removeItem";
2406     return 1 if $functionName eq "appendItem";
2407
2408     return 0;
2409 }
2410
2411 sub IsSVGListMethod
2412 {
2413     my $functionName = shift;
2414
2415     return 1 if $functionName eq "getFirst";
2416     return 1 if $functionName eq "getLast";
2417     return 1 if $functionName eq "getItem";
2418
2419     return IsSVGListMutator($functionName);
2420 }
2421
2422 sub IsSVGListTypeNeedingSpecialHandling
2423 {
2424     my $className = shift;
2425
2426     return 1 if $className eq "SVGPointList";
2427     return 1 if $className eq "SVGTransformList";
2428
2429     return 0;
2430 }
2431
2432 sub DebugPrint
2433 {
2434     my $output = shift;
2435
2436     print $output;
2437     print "\n";
2438 }