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