28562f1ab5b088c0f388424a6997411a2e7d77d3
[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         if ($attrExt->{"DoNotCheckDomainSecurity"} &&
1326             ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) {
1327             # Mark the accessor as ReadOnly and set it on the proto object so
1328             # it can be shadowed. This is really a hack to make it work.
1329             # There are several sceneria to call into the accessor:
1330             #   1) from the same domain: "window.open":
1331             #      the accessor finds the DOM wrapper in the proto chain;
1332             #   2) from the same domain: "window.__proto__.open":
1333             #      the accessor will NOT find a DOM wrapper in the prototype chain
1334             #   3) from another domain: "window.open":
1335             #      the access find the DOM wrapper in the prototype chain
1336             #   "window.__proto__.open" from another domain will fail when
1337             #   accessing '__proto__'
1338             #
1339             # The solution is very hacky and fragile, it really needs to be replaced
1340             # by a better solution.
1341             $property_attributes .= "|v8::ReadOnly";
1342             push(@implContent, <<END);
1343
1344   // $commentInfo
1345   $template->SetAccessor(
1346       v8::String::New("$name"),
1347       ${interfaceName}Internal::${name}AttrGetter,
1348       0,
1349       v8::Handle<v8::Value>(),
1350       v8::ALL_CAN_READ,
1351       static_cast<v8::PropertyAttribute>($property_attributes));
1352 END
1353           next;
1354       }
1355
1356       my $signature = "default_signature";
1357       if ($attrExt->{"V8DoNotCheckSignature"}){
1358           $signature = "v8::Local<v8::Signature>()";
1359       }
1360
1361       if (RequiresCustomSignature($function)) {
1362           $signature = "${name}_signature";
1363           push(@implContent, "\n  // Custom Signature '$name'\n", CreateCustomSignature($function));
1364       }
1365
1366       # Normal function call is a template
1367       my $templateFunction = GenerateNewFunctionTemplate($function, $dataNode, $signature);
1368
1369
1370       push(@implContent, <<END);
1371
1372   // $commentInfo
1373   ${template}->Set(
1374       v8::String::New("$name"),
1375       $templateFunction,
1376       static_cast<v8::PropertyAttribute>($property_attributes));
1377 END
1378     }
1379
1380     # set the super descriptor
1381     foreach (@{$dataNode->parents}) {
1382         my $parent = $codeGenerator->StripModule($_);
1383         if ($parent eq "EventTarget") { next; }
1384         $implIncludes{"V8${parent}.h"} = 1;
1385         my $parentClassIndex = uc($codeGenerator->StripModule($parent));
1386         push(@implContent, "  desc->Inherit(V8DOMWrapper::getTemplate(V8ClassIndex::${parentClassIndex}));\n");
1387         last;
1388     }
1389
1390     # Set the class name.  This is used when printing objects.
1391     push(@implContent, "  desc->SetClassName(v8::String::New(\"" . GetClassName(${interfaceName}) . "\"));\n");
1392
1393     if ($has_constants) {
1394         push(@implContent, <<END);
1395   batchConfigureConstants(desc, proto, ${interfaceName}_consts, sizeof(${interfaceName}_consts)/sizeof(*${interfaceName}_consts));
1396 END
1397     }
1398
1399     push(@implContent, <<END);
1400   return desc;
1401 }
1402
1403 v8::Persistent<v8::FunctionTemplate> ${className}::GetRawTemplate() {
1404   static v8::Persistent<v8::FunctionTemplate> ${className}_raw_cache_;
1405   if (${className}_raw_cache_.IsEmpty()) {
1406     v8::HandleScope scope;
1407     v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(V8Proxy::checkNewLegal);
1408     ${className}_raw_cache_ = v8::Persistent<v8::FunctionTemplate>::New(result);
1409   }
1410   return ${className}_raw_cache_;
1411 }
1412
1413 v8::Persistent<v8::FunctionTemplate> ${className}::GetTemplate() {
1414   static v8::Persistent<v8::FunctionTemplate> ${className}_cache_;
1415   if (${className}_cache_.IsEmpty())
1416     ${className}_cache_ = Configure${className}Template(GetRawTemplate());
1417   return ${className}_cache_;
1418 }
1419
1420 bool ${className}::HasInstance(v8::Handle<v8::Value> value) {
1421   return GetRawTemplate()->HasInstance(value);
1422 }
1423
1424 END
1425
1426     if ($implClassName eq "DOMWindow") {
1427         push(@implContent, <<END);
1428 v8::Persistent<v8::ObjectTemplate> V8DOMWindow::GetShadowObjectTemplate() {
1429   static v8::Persistent<v8::ObjectTemplate> V8DOMWindowShadowObject_cache_;
1430   if (V8DOMWindowShadowObject_cache_.IsEmpty()) {
1431     V8DOMWindowShadowObject_cache_ = v8::Persistent<v8::ObjectTemplate>::New(v8::ObjectTemplate::New());
1432     ConfigureShadowObjectTemplate(V8DOMWindowShadowObject_cache_);
1433   }
1434   return V8DOMWindowShadowObject_cache_;
1435 }
1436 END
1437     }
1438
1439     push(@implContent, <<END);
1440 } // namespace WebCore
1441 END
1442
1443     push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
1444 }
1445
1446
1447 sub GenerateFunctionCallString()
1448 {
1449     my $function = shift;
1450     my $numberOfParameters = shift;
1451     my $indent = shift;
1452     my $implClassName = shift;
1453
1454     my $name = $function->signature->name;
1455     my $isPodType = IsPodType($implClassName);
1456     my $returnType = GetTypeFromSignature($function->signature);
1457     my $returnsPodType = IsPodType($returnType);
1458     my $nativeReturnType = GetNativeType($returnType, 0);
1459     my $result = "";
1460
1461     # Special case: SVG matrix transform methods should not mutate
1462     # the matrix but return a copy
1463     my $copyFirst = 0;
1464     if ($implClassName eq "SVGMatrix" && $function->signature->type eq "SVGMatrix") {
1465         $copyFirst = 1;
1466     }
1467
1468     if ($function->signature->extendedAttributes->{"v8implname"}) {
1469         $name = $function->signature->extendedAttributes->{"v8implname"};
1470     }
1471
1472     if ($function->signature->extendedAttributes->{"ImplementationFunction"}) {
1473         $name = $function->signature->extendedAttributes->{"ImplementationFunction"};
1474     }
1475
1476     my $functionString = "imp->${name}(";
1477
1478     if ($copyFirst) {
1479         $functionString = "result.${name}(";
1480     }
1481
1482     my $returnsListItemPodType = 0;
1483     # SVG lists functions that return POD types require special handling
1484     if (IsSVGListTypeNeedingSpecialHandling($implClassName) && IsSVGListMethod($name) && $returnsPodType) {
1485         $returnsListItemPodType = 1;
1486         $result .= $indent . "SVGList<RefPtr<SVGPODListItem<$nativeReturnType> > >* listImp = imp;\n";
1487         $functionString = "listImp->${name}(";
1488     }
1489
1490     my $first = 1;
1491     my $index = 0;
1492     my $nodeToReturn = 0;
1493
1494     foreach my $parameter (@{$function->parameters}) {
1495         if ($index eq $numberOfParameters) {
1496             last;
1497         }
1498         if ($first) { $first = 0; }
1499         else { $functionString .= ", "; }
1500         my $paramName = $parameter->name;
1501         my $paramType = $parameter->type;
1502
1503         # This is a bit of a hack... we need to convert parameters to methods on SVG lists
1504         # of POD types which are items in the list to appropriate SVGList<> instances
1505         if ($returnsListItemPodType && $paramType . "List" eq $implClassName) {
1506             $paramName = "SVGPODListItem<" . GetNativeType($paramType, 1) . ">::copy($paramName)";
1507         }
1508
1509         if ($parameter->type eq "NodeFilter" || $parameter->type eq "XPathNSResolver") {
1510             $functionString .= "$paramName.get()";
1511         } else {
1512             $functionString .= $paramName;
1513         }
1514
1515         if ($parameter->extendedAttributes->{"Return"}) {
1516             $nodeToReturn = $parameter->name;
1517         }
1518         $index++;
1519     }
1520
1521     if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
1522         $functionString .= ", " if not $first;
1523         $functionString .= "&callStack";
1524         if ($first) { $first = 0; }
1525     }
1526
1527     if (@{$function->raisesExceptions}) {
1528         $functionString .= ", " if not $first;
1529         $functionString .= "ec";
1530     }
1531     $functionString .= ")";
1532
1533     if ($nodeToReturn) {
1534         # Special case for insertBefore, replaceChild, removeChild and
1535         # appendChild functions from Node.
1536         $result .= $indent . "bool success = $functionString;\n";
1537         if (@{$function->raisesExceptions}) {
1538             $result .= GenerateSetDOMException($indent);
1539         }
1540         $result .= $indent . "if (success)\n";
1541         $result .= $indent . "    " .
1542             "return V8DOMWrapper::convertNodeToV8Object($nodeToReturn);\n";
1543         $result .= $indent . "return v8::Null();\n";
1544         return $result;
1545     } elsif ($returnType eq "void") {
1546         $result .= $indent . "$functionString;\n";
1547     } elsif ($copyFirst) {
1548         $result .=
1549             $indent . GetNativeType($returnType, 0) . " result = *imp;\n" .
1550             $indent . "$functionString;\n";
1551     } elsif ($returnsListItemPodType) {
1552         $result .= $indent . "RefPtr<SVGPODListItem<$nativeReturnType> > result = $functionString;\n";
1553     } else {
1554         $result .= $indent . $nativeReturnType . " result = $functionString;\n";
1555     }
1556
1557     if (@{$function->raisesExceptions}) {
1558         $result .= GenerateSetDOMException($indent);
1559     }
1560
1561     my $return = "result";
1562
1563     # If the return type is a POD type, separate out the wrapper generation
1564     if ($returnsListItemPodType) {
1565         $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = ";
1566         $result .= "V8SVGPODTypeWrapperCreatorForList<" . $nativeReturnType . ">::create($return, imp->associatedAttributeName());\n";
1567         $return = "wrapper";
1568     } elsif ($returnsPodType) {
1569         $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = ";
1570         $result .= GenerateSVGStaticPodTypeWrapper($returnType, $return) . ";\n";
1571         $return = "wrapper";
1572     }
1573
1574     my $generatedSVGContextRetrieval = 0;
1575     # If the return type needs an SVG context, output it
1576     if (IsSVGTypeNeedingContextParameter($returnType)) {
1577         $result .= GenerateSVGContextAssignment($implClassName, $return . ".get()", $indent);
1578         $generatedSVGContextRetrieval = 1;
1579     }
1580
1581     if (IsSVGTypeNeedingContextParameter($implClassName) && $implClassName =~ /List$/ && IsSVGListMutator($name)) {
1582         if (!$generatedSVGContextRetrieval) {
1583             $result .= GenerateSVGContextRetrieval($implClassName, $indent);
1584             $generatedSVGContextRetrieval = 1;
1585         }
1586
1587         $result .= $indent . "context->svgAttributeChanged(imp->associatedAttributeName());\n";
1588         $implIncludes{"SVGElement.h"} = 1;
1589     }
1590
1591     # If the implementing class is a POD type, commit changes
1592     if ($isPodType) {
1593         if (!$generatedSVGContextRetrieval) {
1594             $result .= GenerateSVGContextRetrieval($implClassName, $indent);
1595             $generatedSVGContextRetrieval = 1;
1596         }
1597
1598         $result .= $indent . "imp_wrapper->commitChange(imp_instance, context);\n";
1599     }
1600
1601     if ($returnsPodType) {
1602         my $classIndex = uc($returnType);
1603         $result .= $indent . "return V8DOMWrapper::convertToV8Object(V8ClassIndex::$classIndex, wrapper.release());\n";
1604     } else {
1605         $return .= ".release()" if (IsRefPtrType($returnType));
1606         $result .= $indent . ReturnNativeToJSValue($function->signature, $return, $indent) . ";\n";
1607     }
1608
1609     return $result;
1610 }
1611
1612
1613 # Get the class name used for printing javascript DOM-object wrappers.
1614 sub GetClassName
1615 {
1616     my $type = shift;
1617     return "HTMLCollection" if $type eq "HTMLAllCollection";
1618     return $type;
1619 }
1620
1621
1622 sub GetTypeFromSignature
1623 {
1624     my $signature = shift;
1625
1626     my $type = $codeGenerator->StripModule($signature->type);
1627     if (($type eq "DOMString") && $signature->extendedAttributes->{"HintAtomic"}) {
1628         $type = "AtomicString";
1629     }
1630
1631     return $type;
1632 }
1633
1634
1635 sub GetNativeTypeFromSignature
1636 {
1637     my $signature = shift;
1638     my $isParameter = shift;
1639
1640     my $type = GetTypeFromSignature($signature);
1641
1642     if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) {
1643         # Special-case index arguments because we need to check that they aren't < 0.
1644         return "int";
1645     }
1646
1647     return GetNativeType($type, $isParameter);
1648 }
1649
1650 sub IsRefPtrType
1651 {
1652     my $type = shift;
1653     return 1 if $type eq "Attr";
1654     return 1 if $type eq "CanvasActiveInfo";
1655     return 1 if $type eq "CanvasArray";
1656     return 1 if $type eq "CanvasArrayBuffer";
1657     return 1 if $type eq "CanvasBooleanArray";
1658     return 1 if $type eq "CanvasByteArray";
1659     return 1 if $type eq "CanvasBuffer";
1660     return 1 if $type eq "CanvasFloatArray";
1661     return 1 if $type eq "CanvasFramebuffer";
1662     return 1 if $type eq "CanvasGradient";
1663     return 1 if $type eq "CanvasIntArray";
1664     return 1 if $type eq "CanvasObject";
1665     return 1 if $type eq "CanvasProgram";
1666     return 1 if $type eq "CanvasRenderbuffer";
1667     return 1 if $type eq "CanvasShader";
1668     return 1 if $type eq "CanvasShortArray";
1669     return 1 if $type eq "CanvasTexture";
1670     return 1 if $type eq "CanvasUnsignedByteArray";
1671     return 1 if $type eq "CanvasUnsignedIntArray";
1672     return 1 if $type eq "CanvasUnsignedShortArray";
1673     return 1 if $type eq "ClientRect";
1674     return 1 if $type eq "ClientRectList";
1675     return 1 if $type eq "CDATASection";
1676     return 1 if $type eq "Comment";
1677     return 1 if $type eq "CSSRule";
1678     return 1 if $type eq "CSSStyleRule";
1679     return 1 if $type eq "CSSCharsetRule";
1680     return 1 if $type eq "CSSImportRule";
1681     return 1 if $type eq "CSSMediaRule";
1682     return 1 if $type eq "CSSFontFaceRule";
1683     return 1 if $type eq "CSSPageRule";
1684     return 1 if $type eq "CSSPrimitiveValue";
1685     return 1 if $type eq "CSSStyleSheet";
1686     return 1 if $type eq "CSSStyleDeclaration";
1687     return 1 if $type eq "CSSValue";
1688     return 1 if $type eq "CSSRuleList";
1689     return 1 if $type eq "Database";
1690     return 1 if $type eq "Document";
1691     return 1 if $type eq "DocumentFragment";
1692     return 1 if $type eq "DocumentType";
1693     return 1 if $type eq "Element";
1694     return 1 if $type eq "EntityReference";
1695     return 1 if $type eq "Event";
1696     return 1 if $type eq "EventListener";
1697     return 1 if $type eq "FileList";
1698     return 1 if $type eq "HTMLCollection";
1699     return 1 if $type eq "HTMLDocument";
1700     return 1 if $type eq "HTMLElement";
1701     return 1 if $type eq "HTMLOptionsCollection";
1702     return 1 if $type eq "ImageData";
1703     return 1 if $type eq "Media";
1704     return 1 if $type eq "MediaError";
1705     return 1 if $type eq "MimeType";
1706     return 1 if $type eq "Node";
1707     return 1 if $type eq "NodeList";
1708     return 1 if $type eq "NodeFilter";
1709     return 1 if $type eq "NodeIterator";
1710     return 1 if $type eq "NSResolver";
1711     return 1 if $type eq "Plugin";
1712     return 1 if $type eq "ProcessingInstruction";
1713     return 1 if $type eq "Range";
1714     return 1 if $type eq "RGBColor";
1715     return 1 if $type eq "Text";
1716     return 1 if $type eq "TextMetrics";
1717     return 1 if $type eq "TimeRanges";
1718     return 1 if $type eq "TreeWalker";
1719     return 1 if $type eq "WebKitCSSMatrix";
1720     return 1 if $type eq "WebKitPoint";
1721     return 1 if $type eq "XPathExpression";
1722     return 1 if $type eq "XPathNSResolver";
1723     return 1 if $type eq "XPathResult";
1724
1725     return 1 if $type eq "SVGAngle";
1726     return 1 if $type eq "SVGElementInstance";
1727     return 1 if $type eq "SVGElementInstanceList";
1728     return 1 if $type =~ /^SVGPathSeg/;
1729
1730     return 1 if $type =~ /^SVGAnimated/;
1731
1732     return 0;
1733 }
1734
1735 sub IsVideoClassName
1736 {
1737     my $class = shift;
1738     return 1 if $class eq "V8HTMLAudioElement";
1739     return 1 if $class eq "V8HTMLMediaElement";
1740     return 1 if $class eq "V8HTMLSourceElement";
1741     return 1 if $class eq "V8HTMLVideoElement";
1742     return 1 if $class eq "V8MediaError";
1743     return 1 if $class eq "V8TimeRanges";
1744
1745     return 0;
1746 }
1747
1748 sub IsWorkerClassName
1749 {
1750     my $class = shift;
1751     return 1 if $class eq "V8Worker";
1752     return 1 if $class eq "V8WorkerContext";
1753     return 1 if $class eq "V8WorkerLocation";
1754     return 1 if $class eq "V8WorkerNavigator";
1755
1756     return 0;
1757 }
1758
1759 sub GetNativeType
1760 {
1761     my $type = shift;
1762     my $isParameter = shift;
1763
1764     if ($type eq "float" or $type eq "AtomicString" or $type eq "double") {
1765         return $type;
1766     }
1767
1768     return "int" if $type eq "int";
1769     return "int" if $type eq "short" or $type eq "unsigned short";
1770     return "unsigned" if $type eq "unsigned long";
1771     return "int" if $type eq "long";
1772     return "unsigned long long" if $type eq "unsigned long long";
1773     return "bool" if $type eq "boolean";
1774     return "String" if $type eq "DOMString";
1775     return "Range::CompareHow" if $type eq "CompareHow";
1776     return "FloatRect" if $type eq "SVGRect";
1777     return "FloatPoint" if $type eq "SVGPoint";
1778     return "TransformationMatrix" if $type eq "SVGMatrix";
1779     return "SVGTransform" if $type eq "SVGTransform";
1780     return "SVGLength" if $type eq "SVGLength";
1781     return "double" if $type eq "SVGNumber";
1782     return "SVGPaint::SVGPaintType" if $type eq "SVGPaintType";
1783     return "DOMTimeStamp" if $type eq "DOMTimeStamp";
1784     return "unsigned" if $type eq "unsigned int";
1785     return "Node*" if $type eq "EventTarget" and $isParameter;
1786
1787     return "String" if $type eq "DOMUserData";  # FIXME: Temporary hack?
1788
1789     # temporary hack
1790     return "RefPtr<NodeFilter>" if $type eq "NodeFilter";
1791
1792     # necessary as resolvers could be constructed on fly.
1793     return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver";
1794
1795     return "RefPtr<${type}>" if IsRefPtrType($type) and not $isParameter;
1796
1797     # Default, assume native type is a pointer with same type name as idl type
1798     return "${type}*";
1799 }
1800
1801
1802 my %typeCanFailConversion = (
1803     "AtomicString" => 0,
1804     "Attr" => 1,
1805     "CanvasArray" => 0,
1806     "CanvasBuffer" => 0,
1807     "CanvasByteArray" => 0,
1808     "CanvasFloatArray" => 0,
1809     "CanvasFramebuffer" => 0,
1810     "CanvasGradient" => 0,
1811     "CanvasIntArray" => 0,
1812     "CanvasPixelArray" => 0,
1813     "CanvasProgram" => 0,
1814     "CanvasRenderbuffer" => 0,
1815     "CanvasShader" => 0,
1816     "CanvasShortArray" => 0,
1817     "CanvasTexture" => 0,
1818     "CompareHow" => 0,
1819     "DataGridColumn" => 0,
1820     "DOMString" => 0,
1821     "DOMWindow" => 0,
1822     "DocumentType" => 0,
1823     "Element" => 0,
1824     "Event" => 0,
1825     "EventListener" => 0,
1826     "EventTarget" => 0,
1827     "HTMLCanvasElement" => 0,
1828     "HTMLElement" => 0,
1829     "HTMLImageElement" => 0,
1830     "HTMLOptionElement" => 0,
1831     "HTMLVideoElement" => 0,
1832     "Node" => 0,
1833     "NodeFilter" => 0,
1834     "MessagePort" => 0,
1835     "NSResolver" => 0,
1836     "Range" => 0,
1837     "SQLResultSet" => 0,
1838     "Storage" => 0,
1839     "SVGAngle" => 0,
1840     "SVGElement" => 0,
1841     "SVGLength" => 1,
1842     "SVGMatrix" => 1,
1843     "SVGNumber" => 0,
1844     "SVGPaintType" => 0,
1845     "SVGPathSeg" => 0,
1846     "SVGPoint" => 1,
1847     "SVGRect" => 1,
1848     "SVGTransform" => 1,
1849     "VoidCallback" => 1,
1850     "WebKitCSSMatrix" => 0,
1851     "WebKitPoint" => 0,
1852     "XPathEvaluator" => 0,
1853     "XPathNSResolver" => 0,
1854     "XPathResult" => 0,
1855     "boolean" => 0,
1856     "double" => 0,
1857     "float" => 0,
1858     "long" => 0,
1859     "unsigned long" => 0,
1860     "unsigned short" => 0,
1861 );
1862
1863
1864 sub TranslateParameter
1865 {
1866     my $signature = shift;
1867
1868     # The IDL uses some pseudo-types which don't really exist.
1869     if ($signature->type eq "TimeoutHandler") {
1870       $signature->type("DOMString");
1871     }
1872 }
1873
1874 sub BasicTypeCanFailConversion
1875 {
1876     my $signature = shift;
1877     my $type = GetTypeFromSignature($signature);
1878
1879     return 1 if $type eq "SVGLength";
1880     return 1 if $type eq "SVGMatrix";
1881     return 1 if $type eq "SVGPoint";
1882     return 1 if $type eq "SVGRect";
1883     return 1 if $type eq "SVGTransform";
1884     return 0;
1885 }
1886
1887 sub TypeCanFailConversion
1888 {
1889     my $signature = shift;
1890
1891     my $type = GetTypeFromSignature($signature);
1892
1893     $implIncludes{"ExceptionCode.h"} = 1 if $type eq "Attr";
1894
1895     return $typeCanFailConversion{$type} if exists $typeCanFailConversion{$type};
1896
1897     die "Don't know whether a JS value can fail conversion to type $type.";
1898 }
1899
1900 sub JSValueToNative
1901 {
1902     my $signature = shift;
1903     my $value = shift;
1904     my $okParam = shift;
1905     my $maybeOkParam = $okParam ? ", ${okParam}" : "";
1906
1907     my $type = GetTypeFromSignature($signature);
1908
1909     return "$value" if $type eq "JSObject";
1910     return "$value->BooleanValue()" if $type eq "boolean";
1911     return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $type eq "double";
1912     return "$value->NumberValue()" if $type eq "SVGNumber";
1913
1914     return "toInt32($value${maybeOkParam})" if $type eq "unsigned long" or $type eq "unsigned short" or $type eq "long";
1915     return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "CompareHow";
1916     return "static_cast<SVGPaint::SVGPaintType>($value->ToInt32()->Int32Value())" if $type eq "SVGPaintType";
1917
1918     if ($type eq "AtomicString") {
1919         return "v8ValueToAtomicWebCoreStringWithNullCheck($value)" if $signature->extendedAttributes->{"ConvertNullToNullString"};
1920         return "v8ValueToAtomicWebCoreString($value)";
1921     }
1922
1923     return "toWebCoreString($value)" if $type eq "DOMUserData";
1924     if ($type eq "DOMString") {
1925         return "toWebCoreStringWithNullCheck($value)" if $signature->extendedAttributes->{"ConvertNullToNullString"};
1926         return "toWebCoreStringWithNullOrUndefinedCheck($value)" if $signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"};
1927         return "toWebCoreString($value)";
1928     }
1929
1930     if ($type eq "SerializedScriptValue") {
1931         $implIncludes{"SerializedScriptValue.h"} = 1;
1932         return "SerializedScriptValue::create($value)";
1933     }
1934
1935     if ($type eq "NodeFilter") {
1936         return "V8DOMWrapper::wrapNativeNodeFilter($value)";
1937     }
1938
1939     if ($type eq "SVGRect") {
1940         $implIncludes{"FloatRect.h"} = 1;
1941     }
1942
1943     if ($type eq "SVGPoint") {
1944         $implIncludes{"FloatPoint.h"} = 1;
1945     }
1946
1947     # Default, assume autogenerated type conversion routines
1948     $implIncludes{"V8Proxy.h"} = 1;
1949     if ($type eq "EventTarget") {
1950         $implIncludes{"V8Node.h"} = 1;
1951
1952         # EventTarget is not in DOM hierarchy, but all Nodes are EventTarget.
1953         return "V8Node::HasInstance($value) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast($value)) : 0";
1954     }
1955
1956     if ($type eq "XPathNSResolver") {
1957         return "V8DOMWrapper::getXPathNSResolver($value)";
1958     }
1959
1960     AddIncludesForType($type);
1961     # $implIncludes{"$type.h"} = 1 unless AvoidInclusionOfType($type);
1962
1963     if (IsDOMNodeType($type)) {
1964         $implIncludes{"V8${type}.h"} = 1;
1965
1966         # Perform type checks on the parameter, if it is expected Node type,
1967         # return NULL.
1968         return "V8${type}::HasInstance($value) ? V8DOMWrapper::convertDOMWrapperToNode<${type}>(v8::Handle<v8::Object>::Cast($value)) : 0";
1969     } else {
1970         # TODO: Temporary to avoid Window name conflict.
1971         my $classIndex = uc($type);
1972         my $implClassName = ${type};
1973
1974         $implIncludes{"V8$type.h"} = 1;
1975
1976         if (IsPodType($type)) {
1977             my $nativeType = GetNativeType($type);
1978             $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
1979
1980             return "V8SVGPODTypeUtil::toSVGPODType<${nativeType}>(V8ClassIndex::${classIndex}, $value${maybeOkParam})"
1981         }
1982
1983         $implIncludes{"V8${type}.h"} = 1;
1984
1985         # Perform type checks on the parameter, if it is expected Node type,
1986         # return NULL.
1987         return "V8${type}::HasInstance($value) ? V8DOMWrapper::convertToNativeObject<${implClassName}>(V8ClassIndex::${classIndex}, v8::Handle<v8::Object>::Cast($value)) : 0";
1988     }
1989 }
1990
1991
1992 sub GetV8HeaderName
1993 {
1994     my $type = shift;
1995     return "V8" . GetImplementationFileName($type);
1996 }
1997
1998
1999 sub CreateCustomSignature
2000 {
2001     my $function = shift;
2002     my $count = @{$function->parameters};
2003     my $name = $function->signature->name;
2004     my $result = "  const int ${name}_argc = ${count};\n" .
2005       "  v8::Handle<v8::FunctionTemplate> ${name}_argv[${name}_argc] = { ";
2006     my $first = 1;
2007     foreach my $parameter (@{$function->parameters}) {
2008         if ($first) { $first = 0; }
2009         else { $result .= ", "; }
2010         if (IsWrapperType($parameter->type)) {
2011             if ($parameter->type eq "XPathNSResolver") {
2012                 # Special case for XPathNSResolver.  All other browsers accepts a callable,
2013                 # so, even though it's against IDL, accept objects here.
2014                 $result .= "v8::Handle<v8::FunctionTemplate>()";
2015             } else {
2016                 my $type = $parameter->type;
2017                 my $header = GetV8HeaderName($type);
2018                 $implIncludes{$header} = 1;
2019                 $result .= "V8${type}::GetRawTemplate()";
2020             }
2021         } else {
2022             $result .= "v8::Handle<v8::FunctionTemplate>()";
2023         }
2024     }
2025     $result .= " };\n";
2026     $result .= "  v8::Handle<v8::Signature> ${name}_signature = v8::Signature::New(desc, ${name}_argc, ${name}_argv);\n";
2027     return $result;
2028 }
2029
2030
2031 sub RequiresCustomSignature
2032 {
2033     my $function = shift;
2034     # No signature needed for Custom function
2035     if ($function->signature->extendedAttributes->{"Custom"} ||
2036         $function->signature->extendedAttributes->{"V8Custom"}) {
2037         return 0;
2038     }
2039
2040     foreach my $parameter (@{$function->parameters}) {
2041       if (IsWrapperType($parameter->type)) {
2042           return 1;
2043       }
2044     }
2045     return 0;
2046 }
2047
2048
2049 my %non_wrapper_types = (
2050     'float' => 1,
2051     'AtomicString' => 1,
2052     'double' => 1,
2053     'short' => 1,
2054     'unsigned short' => 1,
2055     'long' => 1,
2056     'unsigned long' => 1,
2057     'boolean' => 1,
2058     'DOMString' => 1,
2059     'CompareHow' => 1,
2060     'SVGRect' => 1,
2061     'SVGPoint' => 1,
2062     'SVGMatrix' => 1,
2063     'SVGTransform' => 1,
2064     'SVGLength' => 1,
2065     'SVGNumber' => 1,
2066     'SVGPaintType' => 1,
2067     'DOMTimeStamp' => 1,
2068     'JSObject' => 1,
2069     'EventTarget' => 1,
2070     'NodeFilter' => 1,
2071     'EventListener' => 1
2072 );
2073
2074
2075 sub IsWrapperType
2076 {
2077     my $type = $codeGenerator->StripModule(shift);
2078     return !($non_wrapper_types{$type});
2079 }
2080
2081 sub IsDOMNodeType
2082 {
2083     my $type = shift;
2084
2085     return 1 if $type eq 'Attr';
2086     return 1 if $type eq 'CDATASection';
2087     return 1 if $type eq 'Comment';
2088     return 1 if $type eq 'Document';
2089     return 1 if $type eq 'DocumentFragment';
2090     return 1 if $type eq 'DocumentType';
2091     return 1 if $type eq 'Element';
2092     return 1 if $type eq 'EntityReference';
2093     return 1 if $type eq 'HTMLCanvasElement';
2094     return 1 if $type eq 'HTMLDocument';
2095     return 1 if $type eq 'HTMLElement';
2096     return 1 if $type eq 'HTMLFormElement';
2097     return 1 if $type eq 'HTMLTableCaptionElement';
2098     return 1 if $type eq 'HTMLTableSectionElement';
2099     return 1 if $type eq 'Node';
2100     return 1 if $type eq 'ProcessingInstruction';
2101     return 1 if $type eq 'SVGElement';
2102     return 1 if $type eq 'SVGDocument';
2103     return 1 if $type eq 'SVGSVGElement';
2104     return 1 if $type eq 'SVGUseElement';
2105     return 1 if $type eq 'Text';
2106
2107     return 0;
2108 }
2109
2110
2111 sub ReturnNativeToJSValue
2112 {
2113     my $signature = shift;
2114     my $value = shift;
2115     my $indent = shift;
2116     my $type = GetTypeFromSignature($signature);
2117     my $className= "V8$type";
2118
2119     return "return v8::Date::New(static_cast<double>($value))" if $type eq "DOMTimeStamp";
2120     return "return $value ? v8::True() : v8::False()" if $type eq "boolean";
2121     return "return v8::Undefined()" if $type eq "void";
2122
2123     # For all the types where we use 'int' as the representation type,
2124     # we use Integer::New which has a fast Smi conversion check.
2125     my $nativeType = GetNativeType($type);
2126     return "return v8::Integer::New($value)" if $nativeType eq "int";
2127     return "return v8::Integer::NewFromUnsigned($value)" if $nativeType eq "unsigned";
2128
2129     return "return v8::Number::New($value)" if $codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType";
2130
2131     if ($codeGenerator->IsStringType($type)) {
2132         my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"};
2133         if (defined $conv) {
2134             return "return v8StringOrNull($value)" if $conv eq "Null";
2135             return "return v8StringOrUndefined($value)" if $conv eq "Undefined";
2136             return "return v8StringOrFalse($value)" if $conv eq "False";
2137
2138             die "Unknown value for ConvertNullStringTo extended attribute";
2139         }
2140         return "return v8String($value)";
2141     }
2142
2143     # V8 specific.
2144     my $implClassName = $type;
2145     AddIncludesForType($type);
2146     # $implIncludes{GetImplementationFileName($type)} = 1 unless AvoidInclusionOfType($type);
2147
2148     # special case for non-DOM node interfaces
2149     if (IsDOMNodeType($type)) {
2150         return "return V8DOMWrapper::convertNodeToV8Object($value)";
2151     }
2152
2153     if ($type eq "EventTarget" or $type eq "SVGElementInstance") {
2154         return "return V8DOMWrapper::convertEventTargetToV8Object($value)";
2155     }
2156
2157     if ($type eq "Event") {
2158         return "return V8DOMWrapper::convertEventToV8Object($value)";
2159     }
2160
2161     if ($type eq "EventListener") {
2162         return "return V8DOMWrapper::convertEventListenerToV8Object($value)";
2163     }
2164
2165     if ($type eq "SerializedScriptValue") {
2166         $implIncludes{"$type.h"} = 1;
2167         return "return v8String($value->toString())";
2168     }
2169
2170     if ($type eq "DedicatedWorkerContext" or $type eq "WorkerContext" or $type eq "SharedWorkerContext") {
2171         $implIncludes{"WorkerContextExecutionProxy.h"} = 1;
2172         return "return WorkerContextExecutionProxy::convertWorkerContextToV8Object($value)";
2173     }
2174
2175     if ($type eq "WorkerLocation" or $type eq "WorkerNavigator" or $type eq "NotificationCenter") {
2176         $implIncludes{"WorkerContextExecutionProxy.h"} = 1;
2177         my $classIndex = uc($type);
2178
2179         return "return WorkerContextExecutionProxy::convertToV8Object(V8ClassIndex::$classIndex, $value)";
2180     }
2181
2182     else {
2183         $implIncludes{"wtf/RefCounted.h"} = 1;
2184         $implIncludes{"wtf/RefPtr.h"} = 1;
2185         $implIncludes{"wtf/GetPtr.h"} = 1;
2186         my $classIndex = uc($type);
2187
2188         if (IsPodType($type)) {
2189             $value = GenerateSVGStaticPodTypeWrapper($type, $value);
2190         }
2191
2192         return "return V8DOMWrapper::convertToV8Object(V8ClassIndex::$classIndex, $value)";
2193     }
2194 }
2195
2196 sub GenerateSVGStaticPodTypeWrapper {
2197     my $type = shift;
2198     my $value = shift;
2199
2200     $implIncludes{"V8$type.h"}=1;
2201     $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
2202
2203     my $nativeType = GetNativeType($type);
2204     return "V8SVGStaticPODTypeWrapper<$nativeType>::create($value)";
2205 }
2206
2207 # Internal helper
2208 sub WriteData
2209 {
2210     if (defined($IMPL)) {
2211         # Write content to file.
2212         print $IMPL @implContentHeader;
2213
2214         print $IMPL @implFixedHeader;
2215
2216         foreach my $implInclude (sort keys(%implIncludes)) {
2217             my $checkType = $implInclude;
2218             $checkType =~ s/\.h//;
2219
2220             print $IMPL "#include \"$implInclude\"\n" unless $codeGenerator->IsSVGAnimatedType($checkType);
2221         }
2222
2223         print $IMPL "\n";
2224         print $IMPL @implContentDecls;
2225         print $IMPL @implContent;
2226         close($IMPL);
2227         undef($IMPL);
2228
2229         %implIncludes = ();
2230         @implFixedHeader = ();
2231         @implHeaderContent = ();
2232         @implContentDecls = ();
2233         @implContent = ();
2234     }
2235
2236     if (defined($HEADER)) {
2237         # Write content to file.
2238         print $HEADER @headerContent;
2239         close($HEADER);
2240         undef($HEADER);
2241
2242         @headerContent = ();
2243     }
2244 }
2245
2246 sub IsSVGTypeNeedingContextParameter
2247 {
2248     my $implClassName = shift;
2249
2250     if ($implClassName =~ /SVG/ and not $implClassName =~ /Element/) {
2251         return 1 unless $implClassName =~ /SVGPaint/ or $implClassName =~ /SVGColor/ or $implClassName =~ /SVGDocument/;
2252     }
2253
2254     return 0;
2255 }
2256
2257 sub GenerateSVGContextAssignment
2258 {
2259     my $srcType = shift;
2260     my $value = shift;
2261     my $indent = shift;
2262
2263     $result = GenerateSVGContextRetrieval($srcType, $indent);
2264     $result .= $indent . "V8Proxy::setSVGContext($value, context);\n";
2265
2266     return $result;
2267 }
2268
2269 sub GenerateSVGContextRetrieval
2270 {
2271     my $srcType = shift;
2272     my $indent = shift;
2273
2274     my $srcIsPodType = IsPodType($srcType);
2275
2276     my $srcObject = "imp";
2277     if ($srcIsPodType) {
2278         $srcObject = "imp_wrapper";
2279     }
2280
2281     my $contextDecl;
2282
2283     if (IsSVGTypeNeedingContextParameter($srcType)) {
2284         $contextDecl = "V8Proxy::svgContext($srcObject)";
2285     } else {
2286         $contextDecl = $srcObject;
2287     }
2288
2289     return $indent . "SVGElement* context = $contextDecl;\n";
2290 }
2291
2292 sub IsSVGListMutator
2293 {
2294     my $functionName = shift;
2295
2296     return 1 if $functionName eq "clear";
2297     return 1 if $functionName eq "initialize";
2298     return 1 if $functionName eq "insertItemBefore";
2299     return 1 if $functionName eq "replaceItem";
2300     return 1 if $functionName eq "removeItem";
2301     return 1 if $functionName eq "appendItem";
2302
2303     return 0;
2304 }
2305
2306 sub IsSVGListMethod
2307 {
2308     my $functionName = shift;
2309
2310     return 1 if $functionName eq "getFirst";
2311     return 1 if $functionName eq "getLast";
2312     return 1 if $functionName eq "getItem";
2313
2314     return IsSVGListMutator($functionName);
2315 }
2316
2317 sub IsSVGListTypeNeedingSpecialHandling
2318 {
2319     my $className = shift;
2320
2321     return 1 if $className eq "SVGPointList";
2322     return 1 if $className eq "SVGTransformList";
2323
2324     return 0;
2325 }
2326
2327 sub DebugPrint
2328 {
2329     my $output = shift;
2330
2331     print $output;
2332     print "\n";
2333 }