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