76e8b2f92a5d0d77f40a22b1cf05f50ae3c80b40
[WebKit.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) or $type eq "Date") {
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     my @enabledAtRuntime;
286     foreach my $function (@{$dataNode->functions}) {
287         my $name = $function->signature->name;
288         my $attrExt = $function->signature->extendedAttributes;
289
290         push(@headerContent, <<END);
291   static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments&);
292 END
293         if ($attrExt->{"EnabledAtRuntime"}) {
294             push(@enabledAtRuntime, $function);
295         }
296     }
297     
298     foreach my $attribute (@{$dataNode->attributes}) {
299         my $name = $attribute->signature->name;
300         my $attrExt = $attribute->signature->extendedAttributes;
301         if ($attrExt->{"V8CustomGetter"} || $attrExt->{"CustomGetter"}
302             || $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) {
303             push(@headerContent, <<END);
304   static v8::Handle<v8::Value> ${name}AccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);
305 END
306         }
307         if ($attrExt->{"V8CustomSetter"} || $attrExt->{"CustomSetter"}
308             || $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) {
309             push(@headerContent, <<END);
310   static void ${name}AccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info);
311 END
312         }
313         if ($attrExt->{"EnabledAtRuntime"}) {
314             push(@enabledAtRuntime, $attribute);
315         }
316     }
317
318     GenerateHeaderRuntimeEnablerDeclarations(@enabledAtRuntime);
319     GenerateHeaderCustomCall($dataNode);
320     
321     if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) {
322         push(@headerContent, <<END);
323   static bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType, v8::Local<v8::Value> data);
324   static bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType, v8::Local<v8::Value> data);
325 END
326     }
327
328     push(@headerContent, <<END);
329
330  private:
331   static v8::Persistent<v8::FunctionTemplate> GetTemplate();
332
333   friend class V8ClassIndex;
334 };
335
336 END
337
338     push(@headerContent, "}\n\n");
339     push(@headerContent, "#endif // $className" . "_H\n");
340
341     push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;
342 }
343
344 sub GenerateHeaderRuntimeEnablerDeclarations
345 {
346     my @enabledAtRuntime = @_;
347     
348     foreach my $runtime_attr (@enabledAtRuntime) {
349         my $enabledAtRuntimeConditionalString = GenerateConditionalString($runtime_attr->signature);
350         my $enabler = $codeGenerator->WK_ucfirst($runtime_attr->signature->name);
351         if ($enabledAtRuntimeConditionalString) {
352             push(@headerContent, "\n#if ${enabledAtRuntimeConditionalString}\n");
353         }
354         push(@headerContent, <<END);
355   static bool ${enabler}Enabled();
356 END
357         if ($enabledAtRuntimeConditionalString) {
358             push(@headerContent, "#endif\n");
359         }
360     }
361 }
362
363 sub GenerateHeaderCustomCall
364 {
365     my $dataNode = shift;
366     
367     if ($dataNode->extendedAttributes->{"CustomCall"}) {
368         push(@headerContent, "  static v8::Handle<v8::Value> callAsFunctionCallback(const v8::Arguments&);\n");
369     }
370     if ($dataNode->name eq "Event") {
371         push(@headerContent, "  static v8::Handle<v8::Value> dataTransferAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
372         push(@headerContent, "  static void valueAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info);\n");
373     }
374     if ($dataNode->name eq "Location") {
375         push(@headerContent, "  static v8::Handle<v8::Value> assignAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
376         push(@headerContent, "  static v8::Handle<v8::Value> reloadAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
377         push(@headerContent, "  static v8::Handle<v8::Value> replaceAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
378     }
379 }
380
381 sub GenerateSetDOMException
382 {
383     my $indent = shift;
384     my $result = "";
385
386     $result .= $indent . "if (UNLIKELY(ec)) {\n";
387     $result .= $indent . "    V8Proxy::setDOMException(ec);\n";
388     $result .= $indent . "    return v8::Handle<v8::Value>();\n";
389     $result .= $indent . "}\n";
390
391     return $result;
392 }
393
394 sub IsNodeSubType
395 {
396     my $dataNode = shift;
397     return 1 if ($dataNode->name eq "Node");
398     foreach (@allParents) {
399         my $parent = $codeGenerator->StripModule($_);
400         return 1 if $parent eq "Node";
401     }
402     return 0;
403 }
404
405 sub GetHiddenDependencyIndex
406 {
407     my $dataNode = shift;
408     my $attribute = shift;
409     my $name = $dataNode->name;
410     return "V8Custom::kNodeEventListenerCacheIndex" if IsNodeSubType($dataNode);
411     return "V8Custom::kSVGElementInstanceEventListenerCacheIndex" if $name eq "SVGElementInstance";
412     return "V8Custom::kAbstractWorkerRequestCacheIndex" if $name eq "AbstractWorker";
413     return "V8Custom::kWorkerRequestCacheIndex" if $name eq "Worker";
414     return "V8Custom::kDedicatedWorkerContextRequestCacheIndex" if $name eq "DedicatedWorkerContext";
415     return "V8Custom::kWorkerContextRequestCacheIndex" if $name eq "WorkerContext";
416     return "V8Custom::kWorkerContextRequestCacheIndex" if $name eq "SharedWorkerContext";
417     return "V8Custom::kMessagePortRequestCacheIndex" if $name eq "MessagePort";
418     return "V8Custom::kWebSocketCacheIndex" if $name eq "WebSocket";
419     return "V8Custom::kXMLHttpRequestCacheIndex" if $name eq "XMLHttpRequest";
420     return "V8Custom::kXMLHttpRequestCacheIndex" if $name eq "XMLHttpRequestUpload";
421     return "V8Custom::kDOMApplicationCacheCacheIndex" if $name eq "DOMApplicationCache";
422     return "V8Custom::kNotificationRequestCacheIndex" if $name eq "Notification";
423     return "V8Custom::kDOMWindowEventListenerCacheIndex" if $name eq "DOMWindow";
424     die "Unexpected name " . $name . " when generating " . $attribute;
425 }
426
427 sub HolderToNative
428 {
429     my $dataNode = shift;
430     my $implClassName = shift;
431     my $classIndex = shift;
432     my $holder = shift || "holder";   # optional param
433
434     if (IsNodeSubType($dataNode)) {
435         push(@implContentDecls, <<END);
436     $implClassName* imp = v8DOMWrapperToNode<$implClassName>($holder);
437 END
438
439     } else {
440         push(@implContentDecls, <<END);
441     $implClassName* imp = v8DOMWrapperTo<$implClassName>(V8ClassIndex::$classIndex, $holder);
442 END
443
444   }
445 }
446
447 sub GenerateDomainSafeFunctionGetter
448 {
449     my $function = shift;
450     my $dataNode = shift;
451     my $classIndex = shift;
452     my $implClassName = shift;
453
454     my $className = "V8" . $dataNode->name;
455     my $funcName = $function->signature->name;
456
457     my $signature = "v8::Signature::New(" . $className . "::GetRawTemplate())";
458     if ($function->signature->extendedAttributes->{"V8DoNotCheckSignature"}) {
459         $signature = "v8::Local<v8::Signature>()";
460     }
461
462     my $newTemplateString = GenerateNewFunctionTemplate($function, $dataNode, $signature);
463
464     $implIncludes{"V8Proxy.h"} = 1;
465
466     push(@implContentDecls, <<END);
467   static v8::Handle<v8::Value> ${funcName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) {
468     INC_STATS(\"DOM.$implClassName.$funcName._get\");
469     static v8::Persistent<v8::FunctionTemplate> private_template =
470         v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
471     v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::$classIndex, info.This());
472     if (holder.IsEmpty()) {
473       // can only reach here by 'object.__proto__.func', and it should passed
474       // domain security check already
475
476       return private_template->GetFunction();
477     }
478 END
479
480     HolderToNative($dataNode, $implClassName, $classIndex);
481
482     push(@implContentDecls, <<END);
483     if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false)) {
484       static v8::Persistent<v8::FunctionTemplate> shared_template =
485         v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
486       return shared_template->GetFunction();
487
488     } else {
489       return private_template->GetFunction();
490     }
491   }
492
493 END
494 }
495
496 sub GenerateConstructorGetter
497 {
498     my $implClassName = shift;
499     my $classIndex = shift;
500
501     push(@implContentDecls, <<END);
502   static v8::Handle<v8::Value> ${implClassName}ConstructorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) {
503     INC_STATS(\"DOM.$implClassName.constructors._get\");
504     v8::Handle<v8::Value> data = info.Data();
505     ASSERT(data->IsNumber());
506     V8ClassIndex::V8WrapperType type = V8ClassIndex::FromInt(data->Int32Value());
507 END
508
509     if ($classIndex eq "DOMWINDOW") {
510         push(@implContentDecls, <<END);
511     DOMWindow* window = v8DOMWrapperTo<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder());
512     // Get the proxy corresponding to the DOMWindow if possible to
513     // make sure that the constructor function is constructed in the
514     // context of the DOMWindow and not in the context of the caller.
515     return V8DOMWrapper::getConstructor(type, window);
516 END
517     } elsif ($classIndex eq "DEDICATEDWORKERCONTEXT" or $classIndex eq "WORKERCONTEXT" or $classIndex eq "SHAREDWORKERCONTEXT") {
518         $implIncludes{"WorkerContextExecutionProxy.h"} = 1;
519         push(@implContentDecls, <<END);
520     WorkerContext* workerContext = v8DOMWrapperTo<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder());
521     return V8DOMWrapper::getConstructor(type, workerContext);
522 END
523     } else {
524         push(@implContentDecls, "    return v8::Handle<v8::Value>();");
525     }
526
527     push(@implContentDecls, <<END);
528
529     }
530
531 END
532 }
533
534 sub GenerateNormalAttrGetter
535 {
536     my $attribute = shift;
537     my $dataNode = shift;
538     my $classIndex = shift;
539     my $implClassName = shift;
540     my $interfaceName = shift;
541
542     my $attrExt = $attribute->signature->extendedAttributes;
543
544     my $attrName = $attribute->signature->name;
545     $implIncludes{"V8Proxy.h"} = 1;
546
547     my $attrType = GetTypeFromSignature($attribute->signature);
548     my $attrIsPodType = IsPodType($attrType);
549
550     my $nativeType = GetNativeTypeFromSignature($attribute->signature, -1);
551     my $isPodType = IsPodType($implClassName);
552     my $skipContext = 0;
553
554
555     if ($isPodType) {
556         $implClassName = GetNativeType($implClassName);
557         $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
558     }
559
560     # Special case: SVGZoomEvent's attributes are all read-only
561     if ($implClassName eq "SVGZoomEvent") {
562         $attrIsPodType = 0;
563         $skipContext = 1;
564     }
565
566     # Special case: SVGSVGEelement::viewport is read-only
567     if (($implClassName eq "SVGSVGElement") and ($attrName eq "viewport")) {
568         $attrIsPodType = 0;
569         $skipContext = 1;
570     }
571
572     # Special case for SVGColor
573     if (($implClassName eq "SVGColor") and ($attrName eq "rgbColor")) {
574         $attrIsPodType = 0;
575     }
576
577     my $getterStringUsesImp = $implClassName ne "double";
578
579   # Getter
580     push(@implContentDecls, <<END);
581   static v8::Handle<v8::Value> ${attrName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) {
582     INC_STATS(\"DOM.$implClassName.$attrName._get\");
583 END
584
585     if ($isPodType) {
586         push(@implContentDecls, <<END);
587     V8SVGPODTypeWrapper<$implClassName>* imp_wrapper = v8DOMWrapperTo<V8SVGPODTypeWrapper<$implClassName> >(V8ClassIndex::$classIndex, info.Holder());
588     $implClassName imp_instance = *imp_wrapper;
589 END
590         if ($getterStringUsesImp) {
591             push(@implContentDecls, <<END);
592     $implClassName* imp = &imp_instance;
593 END
594         }
595
596     } elsif ($attrExt->{"v8OnProto"} || $attrExt->{"V8DisallowShadowing"}) {
597       if ($classIndex eq "DOMWINDOW") {
598         push(@implContentDecls, <<END);
599     v8::Handle<v8::Object> holder = info.Holder();
600 END
601       } else {
602         # perform lookup first
603         push(@implContentDecls, <<END);
604     v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::$classIndex, info.This());
605     if (holder.IsEmpty()) return v8::Handle<v8::Value>();
606 END
607       }
608         HolderToNative($dataNode, $implClassName, $classIndex, "info");
609     } else {
610         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
611         if ($getterStringUsesImp && $reflect && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
612             # Generate super-compact call for regular attribute getter:
613             my $contentAttributeName = $reflect eq "1" ? $attrName : $reflect;
614             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
615             $implIncludes{"${namespace}.h"} = 1;
616             push(@implContentDecls, "    return getElementStringAttr(info, ${namespace}::${contentAttributeName}Attr);\n");
617             push(@implContentDecls, "  }\n\n");
618             return;
619             # Skip the rest of the function!
620         }
621         
622         push(@implContentDecls, <<END);
623     v8::Handle<v8::Object> holder = info.Holder();
624 END
625         HolderToNative($dataNode, $implClassName, $classIndex, "info");
626     }
627
628     # Generate security checks if necessary
629     if ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) {
630         push(@implContentDecls, "    if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->$attrName())) return v8::Handle<v8::Value>();\n\n");
631     } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) {
632         push(@implContentDecls, "    if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->contentDocument())) return v8::Handle<v8::Value>();\n\n");
633     }
634
635     my $useExceptions = 1 if @{$attribute->getterExceptions} and !($isPodType);
636     if ($useExceptions) {
637         $implIncludes{"ExceptionCode.h"} = 1;
638         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
639     }
640
641     if ($attribute->signature->extendedAttributes->{"v8referenceattr"}) {
642         $attrName = $attribute->signature->extendedAttributes->{"v8referenceattr"};
643     }
644
645     my $getterFunc = $codeGenerator->WK_lcfirst($attrName);
646
647     if ($codeGenerator->IsSVGAnimatedType($attribute->signature->type)) {
648         # Some SVGFE*Element.idl use 'operator' as attribute name; rewrite as '_operator' to avoid clashes with C/C++
649         $getterFunc = "_" . $getterFunc if ($attrName =~ /operator/);
650         $getterFunc .= "Animated";
651     }
652
653     my $returnType = GetTypeFromSignature($attribute->signature);
654
655     my $getterString;
656     if ($getterStringUsesImp) {
657         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
658         my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
659         if ($reflect || $reflectURL) {
660             my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL);
661             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
662             $implIncludes{"${namespace}.h"} = 1;
663             my $getAttributeFunctionName = $reflectURL ? "getURLAttribute" : "getAttribute";
664             $getterString = "imp->$getAttributeFunctionName(${namespace}::${contentAttributeName}Attr";
665         } else {
666             $getterString = "imp->$getterFunc(";
667         }
668         $getterString .= "ec" if $useExceptions;
669         $getterString .= ")";
670         if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) {
671             $getterString .= ".toInt()";
672         }
673     } else {
674         $getterString = "imp_instance";
675     }
676
677     my $result;
678     my $wrapper;
679
680     if ($attrIsPodType) {
681         $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
682
683         my $getter = $getterString;
684         $getter =~ s/imp->//;
685         $getter =~ s/\(\)//;
686         my $setter = "set" . $codeGenerator->WK_ucfirst($getter);
687
688         my $implClassIsAnimatedType = $codeGenerator->IsSVGAnimatedType($implClassName);
689         if (not $implClassIsAnimatedType and $codeGenerator->IsPodTypeWithWriteableProperties($attrType) and not defined $attribute->signature->extendedAttributes->{"Immutable"}) {
690             if (IsPodType($implClassName)) {
691                 my $wrapper = "V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($getterString, imp_wrapper)";
692                 push(@implContentDecls, "    RefPtr<V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName> > wrapper = $wrapper;\n");
693             } else {
694                 my $wrapper = "V8SVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName>::create(imp, &${implClassName}::$getter, &${implClassName}::$setter)";
695                 push(@implContentDecls, "    RefPtr<V8SVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName> > wrapper = $wrapper;\n");
696             }
697         } else {
698             if ($implClassIsAnimatedType) {
699                 # We can't hash member function pointers, so instead generate
700                 # some hashing material based on the names of the methods.
701                 my $hashhex = substr(Digest::MD5::md5_hex("${implClassName}::$getter ${implClassName}::$setter)"), 0, 8);
702                 my $wrapper = "V8SVGDynamicPODTypeWrapperCache<$nativeType, $implClassName>::lookupOrCreateWrapper(imp, &${implClassName}::$getter, &${implClassName}::$setter, 0x$hashhex)";
703                 push(@implContentDecls, "    RefPtr<V8SVGPODTypeWrapper<" . $nativeType . "> > wrapper = $wrapper;\n");
704             } else {
705                 my $wrapper = GenerateSVGStaticPodTypeWrapper($returnType, $getterString);
706                 push(@implContentDecls, "    RefPtr<V8SVGStaticPODTypeWrapper<" . $nativeType . "> > wrapper = $wrapper;\n");
707             }
708         }
709
710     } else {
711         if ($attribute->signature->type eq "EventListener" && $dataNode->name eq "DOMWindow") {
712             push(@implContentDecls, "    if (!imp->document())\n");
713             push(@implContentDecls, "      return v8::Handle<v8::Value>();\n");
714         }
715
716         if ($useExceptions) {
717             push(@implContentDecls, "    $nativeType v = ");
718             push(@implContentDecls, "$getterString;\n");
719             push(@implContentDecls, GenerateSetDOMException("    "));
720             $result = "v";
721             $result .= ".release()" if (IsRefPtrType($returnType));
722         } else {
723             # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
724             $result = $getterString;
725         }
726     }
727
728     if (IsSVGTypeNeedingContextParameter($attrType) && !$skipContext) {
729         if ($attrIsPodType) {
730             push(@implContentDecls, GenerateSVGContextAssignment($implClassName, "wrapper.get()", "    "));
731         } else {
732             push(@implContentDecls, GenerateSVGContextRetrieval($implClassName, "    "));
733             $result = "V8Proxy::withSVGContext($result, context)";
734         }
735     }
736
737     if ($attrIsPodType) {
738         my $classIndex = uc($attrType);
739         push(@implContentDecls, "    return V8DOMWrapper::convertToV8Object(V8ClassIndex::$classIndex, wrapper.release());\n");
740     } else {
741         push(@implContentDecls, "    " . ReturnNativeToJSValue($attribute->signature, $result, "    ").";\n");
742     }
743
744     push(@implContentDecls, "  }\n\n");  # end of getter
745 }
746
747
748 sub GenerateReplaceableAttrSetter
749 {
750     my $implClassName = shift;
751
752     $implIncludes{"V8Proxy.h"} = 1;
753
754     push(@implContentDecls,
755        "  static void ${attrName}AttrSetter(v8::Local<v8::String> name," .
756        " v8::Local<v8::Value> value, const v8::AccessorInfo& info) {\n");
757
758     push(@implContentDecls, "    INC_STATS(\"DOM.$implClassName.$attrName._set\");\n");
759
760     push(@implContentDecls, "    v8::Local<v8::String> ${attrName}_string = v8::String::New(\"${attrName}\");\n");
761     push(@implContentDecls, "    info.Holder()->Delete(${attrName}_string);\n");
762     push(@implContentDecls, "    info.This()->Set(${attrName}_string, value);\n");
763     push(@implContentDecls, "  }\n\n");
764 }
765
766
767 sub GenerateNormalAttrSetter
768 {
769     my $attribute = shift;
770     my $dataNode = shift;
771     my $classIndex = shift;
772     my $implClassName = shift;
773     my $interfaceName = shift;
774
775     my $attrExt = $attribute->signature->extendedAttributes;
776
777     $implIncludes{"V8Proxy.h"} = 1;
778
779     push(@implContentDecls,
780        "  static void ${attrName}AttrSetter(v8::Local<v8::String> name," .
781        " v8::Local<v8::Value> value, const v8::AccessorInfo& info) {\n");
782
783     push(@implContentDecls, "    INC_STATS(\"DOM.$implClassName.$attrName._set\");\n");
784
785     my $isPodType = IsPodType($implClassName);
786
787     if ($isPodType) {
788         $implClassName = GetNativeType($implClassName);
789         $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
790         push(@implContentDecls, "    V8SVGPODTypeWrapper<$implClassName>* wrapper = v8DOMWrapperTo<V8SVGPODTypeWrapper<$implClassName> >(V8ClassIndex::$classIndex, info.Holder());\n");
791         push(@implContentDecls, "    $implClassName imp_instance = *wrapper;\n");
792         push(@implContentDecls, "    $implClassName* imp = &imp_instance;\n");
793
794     } elsif ($attrExt->{"v8OnProto"}) {
795       if ($classIndex eq "DOMWINDOW") {
796         push(@implContentDecls, <<END);
797     v8::Handle<v8::Object> holder = info.Holder();
798 END
799       } else {
800         # perform lookup first
801         push(@implContentDecls, <<END);
802     v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::$classIndex, info.This());
803     if (holder.IsEmpty()) return;
804 END
805       }
806         HolderToNative($dataNode, $implClassName, $classIndex, "info");
807     } else {
808         my $attrType = GetTypeFromSignature($attribute->signature);
809         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
810         my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
811         if (($reflect || $reflectURL) && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
812             # Generate super-compact call for regular attribute setter:
813             my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL);
814             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
815             $implIncludes{"${namespace}.h"} = 1;
816             push(@implContentDecls, "    setElementStringAttr(info, ${namespace}::${contentAttributeName}Attr, value);\n");
817             push(@implContentDecls, "  }\n\n");
818             return;
819             # Skip the rest of the function!
820         }
821
822         push(@implContentDecls, <<END);
823     v8::Handle<v8::Object> holder = info.Holder();
824 END
825         HolderToNative($dataNode, $implClassName, $classIndex, "info");
826     }
827
828     my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0);
829     if ($attribute->signature->type eq "EventListener") {
830         if ($dataNode->name eq "DOMWindow") {
831             push(@implContentDecls, "    if (!imp->document())\n");
832             push(@implContentDecls, "      return;\n");
833         }
834     } else {
835         push(@implContentDecls, "    $nativeType v = " . JSValueToNative($attribute->signature, "value") . ";\n");
836     }
837
838     my $result = "";
839     if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) {
840         $result .= "WebCore::String::number(";
841     }
842     $result .= "v";
843     if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) {
844         $result .= ")";
845     }
846     my $returnType = GetTypeFromSignature($attribute->signature);
847     if (IsRefPtrType($returnType)) {
848         $result = "WTF::getPtr(" . $result . ")";
849     }
850
851     my $useExceptions = 1 if @{$attribute->setterExceptions} and !($isPodType);
852
853     if ($useExceptions) {
854         $implIncludes{"ExceptionCode.h"} = 1;
855         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
856     }
857
858     if ($implClassName eq "double") {
859         push(@implContentDecls, "    *imp = $result;\n");
860     } else {
861         my $implSetterFunctionName = $codeGenerator->WK_ucfirst($attrName);
862         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
863         my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
864         if ($reflect || $reflectURL) {
865             my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL);
866             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
867             $implIncludes{"${namespace}.h"} = 1;
868             push(@implContentDecls, "    imp->setAttribute(${namespace}::${contentAttributeName}Attr, $result");
869         } elsif ($attribute->signature->type eq "EventListener") {
870             $implIncludes{"V8AbstractEventListener.h"} = 1;
871             $implIncludes{"V8CustomBinding.h"} = 1;
872             $cacheIndex = GetHiddenDependencyIndex($dataNode, $attrName);
873             push(@implContentDecls, "    transferHiddenDependency(holder, imp->$attrName(), value, $cacheIndex);\n");
874             push(@implContentDecls, "    imp->set$implSetterFunctionName(V8DOMWrapper::getEventListener(imp, value, true, ListenerFindOrCreate)");
875         } else {
876             push(@implContentDecls, "    imp->set$implSetterFunctionName($result");
877         }
878         push(@implContentDecls, ", ec") if $useExceptions;
879         push(@implContentDecls, ");\n");
880     }
881
882     if ($useExceptions) {
883         push(@implContentDecls, "    if (UNLIKELY(ec))\n");
884         push(@implContentDecls, "        V8Proxy::setDOMException(ec);\n");
885     }
886
887     if ($isPodType) {
888         push(@implContentDecls, "    wrapper->commitChange(*imp, V8Proxy::svgContext(wrapper));\n");
889     } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
890         $implIncludes{"SVGElement.h"} = 1;
891
892         my $currentObject = "imp";
893         if ($isPodType) {
894             $currentObject = "wrapper";
895         }
896
897         push(@implContentDecls, "    if (SVGElement* context = V8Proxy::svgContext($currentObject)) {\n");
898         push(@implContentDecls, "        context->svgAttributeChanged(imp->associatedAttributeName());\n");
899         push(@implContentDecls, "    }\n");
900     }
901
902     push(@implContentDecls, "    return;\n");
903     push(@implContentDecls, "  }\n\n");  # end of setter
904 }
905
906 sub GetFunctionTemplateCallbackName
907 {
908     $function = shift;
909     $dataNode = shift;
910     
911     my $interfaceName = $dataNode->name;
912     my $name = $function->signature->name;
913
914     if ($function->signature->extendedAttributes->{"Custom"} ||
915         $function->signature->extendedAttributes->{"V8Custom"}) {
916         if ($function->signature->extendedAttributes->{"Custom"} &&
917             $function->signature->extendedAttributes->{"V8Custom"}) {
918             die "Custom and V8Custom should be mutually exclusive!"
919         }
920         return "V8${interfaceName}::${name}Callback";
921     } else {
922         return "${interfaceName}Internal::${name}Callback";
923     }
924 }
925
926 sub GenerateNewFunctionTemplate
927 {
928     $function = shift;
929     $dataNode = shift;
930     $signature = shift;
931
932     my $callback = GetFunctionTemplateCallbackName($function, $dataNode);
933     return "v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), $signature)";
934 }
935
936 sub GenerateFunctionCallback
937 {
938     my $function = shift;
939     my $dataNode = shift;
940     my $classIndex = shift;
941     my $implClassName = shift;
942
943     my $interfaceName = $dataNode->name;
944     my $name = $function->signature->name;
945
946     push(@implContentDecls,
947 "  static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args) {\n" .
948 "    INC_STATS(\"DOM.$implClassName.$name\");\n");
949
950     my $numParameters = @{$function->parameters};
951
952     if ($function->signature->extendedAttributes->{"RequiresAllArguments"}) {
953         push(@implContentDecls,
954             "    if (args.Length() < $numParameters) return v8::Handle<v8::Value>();\n");
955     }
956
957     if (IsPodType($implClassName)) {
958         my $nativeClassName = GetNativeType($implClassName);
959         push(@implContentDecls, "    V8SVGPODTypeWrapper<$nativeClassName>* imp_wrapper = v8DOMWrapperTo<V8SVGPODTypeWrapper<$nativeClassName> >(V8ClassIndex::$classIndex, args.Holder());\n");
960         push(@implContentDecls, "    $nativeClassName imp_instance = *imp_wrapper;\n");
961         push(@implContentDecls, "    $nativeClassName* imp = &imp_instance;\n");
962     } else {
963         push(@implContentDecls, <<END);
964     v8::Handle<v8::Object> holder = args.Holder();
965 END
966         HolderToNative($dataNode, $implClassName, $classIndex);
967     }
968
969   # Check domain security if needed
970     if (($dataNode->extendedAttributes->{"CheckDomainSecurity"}
971        || $interfaceName eq "DOMWindow")
972        && !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
973     # We have not find real use cases yet.
974     push(@implContentDecls,
975 "    if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) {\n".
976 "      return v8::Handle<v8::Value>();\n" .
977 "    }\n");
978     }
979     
980     my $raisesExceptions = @{$function->raisesExceptions};
981     if (!$raisesExceptions) {
982         foreach my $parameter (@{$function->parameters}) {
983             if (TypeCanFailConversion($parameter) or $parameter->extendedAttributes->{"IsIndex"}) {
984                 $raisesExceptions = 1;
985             }
986         }
987     }
988
989     if ($raisesExceptions) {
990         $implIncludes{"ExceptionCode.h"} = 1;
991         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
992         push(@implContentDecls, "    {\n");
993         # The brace here is needed to prevent the ensuing 'goto fail's from jumping past constructors
994         # of objects (like Strings) declared later, causing compile errors. The block scope ends
995         # right before the label 'fail:'.
996     }
997
998     if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
999         push(@implContentDecls,
1000 "    OwnPtr<ScriptCallStack> callStack(ScriptCallStack::create(args, $numParameters));\n".
1001 "    if (!callStack)\n".
1002 "        return v8::Undefined();\n");
1003         $implIncludes{"ScriptCallStack.h"} = 1;
1004     }
1005     if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) {
1006         push(@implContentDecls,
1007 "    if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->getSVGDocument(ec)))\n" .
1008 "      return v8::Handle<v8::Value>();\n");
1009     }
1010
1011     my $paramIndex = 0;
1012     foreach my $parameter (@{$function->parameters}) {
1013         TranslateParameter($parameter);
1014
1015         my $parameterName = $parameter->name;
1016
1017         if ($parameter->extendedAttributes->{"Optional"}) {
1018             # Generate early call if there are not enough parameters.
1019             push(@implContentDecls, "    if (args.Length() <= $paramIndex) {\n");
1020             my $functionCall = GenerateFunctionCallString($function, $paramIndex, "    " x 2, $implClassName);
1021             push(@implContentDecls, $functionCall);
1022             push(@implContentDecls, "    }\n");
1023         }
1024
1025         if (BasicTypeCanFailConversion($parameter)) {
1026             push(@implContentDecls, "    bool ${parameterName}Ok;\n");
1027         }
1028
1029         push(@implContentDecls, "    " . GetNativeTypeFromSignature($parameter, $paramIndex) . " $parameterName = ");
1030         push(@implContentDecls, JSValueToNative($parameter, "args[$paramIndex]",
1031            BasicTypeCanFailConversion($parameter) ?  "${parameterName}Ok" : undef) . ";\n");
1032
1033         if (TypeCanFailConversion($parameter)) {
1034             $implIncludes{"ExceptionCode.h"} = 1;
1035             push(@implContentDecls,
1036 "    if (UNLIKELY(!$parameterName" . (BasicTypeCanFailConversion($parameter) ? "Ok" : "") . ")) {\n" .
1037 "      ec = TYPE_MISMATCH_ERR;\n" .
1038 "      goto fail;\n" .
1039 "    }\n");
1040         }
1041
1042         if ($parameter->extendedAttributes->{"IsIndex"}) {
1043             $implIncludes{"ExceptionCode.h"} = 1;
1044             push(@implContentDecls,
1045 "    if (UNLIKELY($parameterName < 0)) {\n" .
1046 "      ec = INDEX_SIZE_ERR;\n" .
1047 "      goto fail;\n" .
1048 "    }\n");
1049         }
1050
1051         $paramIndex++;
1052     }
1053
1054     # Build the function call string.
1055     my $callString = GenerateFunctionCallString($function, $paramIndex, "    ", $implClassName);
1056     push(@implContentDecls, "$callString");
1057
1058     if ($raisesExceptions) {
1059         push(@implContentDecls, "    }\n");
1060         push(@implContentDecls, "  fail:\n");
1061         push(@implContentDecls, "    V8Proxy::setDOMException(ec);\n");
1062         push(@implContentDecls, "    return v8::Handle<v8::Value>();\n");
1063     }
1064     
1065     push(@implContentDecls, "  }\n\n");
1066 }
1067
1068 sub GenerateBatchedAttributeData
1069 {
1070     my $dataNode = shift;
1071     my $interfaceName = $dataNode->name;
1072     my $attributes = shift;
1073
1074     foreach my $attribute (@$attributes) {
1075         my $conditionalString = GenerateConditionalString($attribute->signature);
1076         push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
1077         GenerateSingleBatchedAttribute($interfaceName, $attribute, ",", "");
1078         push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
1079     }
1080 }
1081
1082 sub GenerateSingleBatchedAttribute
1083 {
1084     my $interfaceName = shift;
1085     my $attribute = shift;
1086     my $delimiter = shift;
1087     my $indent = shift;
1088     my $attrName = $attribute->signature->name;
1089     my $attrExt = $attribute->signature->extendedAttributes;
1090
1091     my $accessControl = "v8::DEFAULT";
1092     if ($attrExt->{"DoNotCheckDomainSecurityOnGet"}) {
1093         $accessControl = "v8::ALL_CAN_READ";
1094     } elsif ($attrExt->{"DoNotCheckDomainSecurityOnSet"}) {
1095         $accessControl = "v8::ALL_CAN_WRITE";
1096     } elsif ($attrExt->{"DoNotCheckDomainSecurity"}) {
1097         $accessControl = "v8::ALL_CAN_READ";
1098         if (!($attribute->type =~ /^readonly/) && !($attrExt->{"V8ReadOnly"})) {
1099             $accessControl .= "|v8::ALL_CAN_WRITE";
1100         }
1101     }
1102     if ($attrExt->{"V8DisallowShadowing"}) {
1103         $accessControl .= "|v8::PROHIBITS_OVERWRITING";
1104     }
1105     $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")";
1106
1107     my $customAccessor =
1108         $attrExt->{"Custom"} ||
1109         $attrExt->{"CustomSetter"} ||
1110         $attrExt->{"CustomGetter"} ||
1111         $attrExt->{"V8Custom"} ||
1112         $attrExt->{"V8CustomSetter"} ||
1113         $attrExt->{"V8CustomGetter"} ||
1114         "";
1115     if ($customAccessor eq 1) {
1116         # use the naming convension, interface + (capitalize) attr name
1117         $customAccessor = $interfaceName . "::" . $attrName;
1118     }
1119
1120     my $getter;
1121     my $setter;
1122     my $propAttr = "v8::None";
1123     my $hasCustomSetter = 0;
1124
1125     # Check attributes.
1126     if ($attrExt->{"DontEnum"}) {
1127         $propAttr .= "|v8::DontEnum";
1128     }
1129     if ($attrExt->{"V8DisallowShadowing"}) {
1130         $propAttr .= "|v8::DontDelete";
1131     }
1132
1133     my $on_proto = "0 /* on instance */";
1134     my $data = "V8ClassIndex::INVALID_CLASS_INDEX /* no data */";
1135
1136     # Constructor
1137     if ($attribute->signature->type =~ /Constructor$/) {
1138         my $constructorType = $codeGenerator->StripModule($attribute->signature->type);
1139         $constructorType =~ s/Constructor$//;
1140         my $constructorIndex = uc($constructorType);
1141         if ($customAccessor) {
1142             $getter = "V8${customAccessor}AccessorGetter";
1143         } else {
1144             $data = "V8ClassIndex::${constructorIndex}";
1145             $getter = "${interfaceName}Internal::${interfaceName}ConstructorGetter";
1146         }
1147         $setter = "0";
1148         $propAttr = "v8::ReadOnly";
1149
1150     } else {
1151         # Default Getter and Setter
1152         $getter = "${interfaceName}Internal::${attrName}AttrGetter";
1153         $setter = "${interfaceName}Internal::${attrName}AttrSetter";
1154
1155         # Custom Setter
1156         if ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
1157             $hasCustomSetter = 1;
1158             $setter = "V8${customAccessor}AccessorSetter";
1159         }
1160
1161         # Custom Getter
1162         if ($attrExt->{"CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
1163             $getter = "V8${customAccessor}AccessorGetter";
1164         }
1165     }
1166
1167     # Replaceable
1168     if ($attrExt->{"Replaceable"} && !$hasCustomSetter) {
1169         $setter = "0";
1170         # Handle the special case of window.top being marked as Replaceable.
1171         # FIXME: Investigate whether we could treat window.top as replaceable
1172         # and allow shadowing without it being a security hole.
1173         if (!($interfaceName eq "DOMWindow" and $attrName eq "top")) {
1174             $propAttr .= "|v8::ReadOnly";
1175         }
1176     }
1177
1178     # Read only attributes
1179     if ($attribute->type =~ /^readonly/ || $attrExt->{"V8ReadOnly"}) {
1180         $setter = "0";
1181     }
1182
1183     # An accessor can be installed on the proto
1184     if ($attrExt->{"v8OnProto"}) {
1185         $on_proto = "1 /* on proto */";
1186     }
1187
1188     my $commentInfo = "Attribute '$attrName' (Type: '" . $attribute->type .
1189                       "' ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
1190
1191     push(@implContent, $indent . "    {\n");
1192     push(@implContent, $indent . "        \/\/ $commentInfo\n");
1193     push(@implContent, $indent . "        \"$attrName\",\n");
1194     push(@implContent, $indent . "        $getter,\n");
1195     push(@implContent, $indent . "        $setter,\n");
1196     push(@implContent, $indent . "        $data,\n");
1197     push(@implContent, $indent . "        $accessControl,\n");
1198     push(@implContent, $indent . "        static_cast<v8::PropertyAttribute>($propAttr),\n");
1199     push(@implContent, $indent . "        $on_proto\n");
1200     push(@implContent, $indent . "    }" . $delimiter . "\n");
1201 END
1202 }
1203
1204 my %indexerSpecialCases = (
1205     "Storage" => 1,
1206     "HTMLAppletElement" => 1,
1207     "HTMLEmbedElement" => 1,
1208     "HTMLObjectElement" => 1
1209 );
1210
1211 sub GenerateImplementationIndexer
1212 {
1213     my $dataNode = shift;
1214     my $indexer = shift;
1215     my $interfaceName = $dataNode->name;
1216
1217     # FIXME: Figure out what HasNumericIndexGetter is really supposed to do. Right now, it's only set on WebGL-related files.
1218     my $hasCustomSetter = $dataNode->extendedAttributes->{"HasCustomIndexSetter"} && !$dataNode->extendedAttributes->{"HasNumericIndexGetter"};
1219     my $hasGetter = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
1220
1221     # FIXME: Find a way to not have to special-case HTMLOptionsCollection.
1222     if ($interfaceName eq "HTMLOptionsCollection") {
1223         $hasGetter = 1;
1224     }
1225     # FIXME: If the parent interface of $dataNode already has
1226     # HasIndexGetter, we don't need to handle the getter here.
1227     if ($interfaceName eq "WebKitCSSTransformValue") {
1228         $hasGetter = 0;
1229     }
1230
1231     # FIXME: Investigate and remove this nastinesss. In V8, named property handling and indexer handling are apparently decoupled,
1232     # which means that object[X] where X is a number doesn't reach named property indexer. So we need to provide
1233     # simplistic, mirrored indexer handling in addition to named property handling.
1234     my $isSpecialCase = exists $indexerSpecialCases{$interfaceName};
1235     if ($isSpecialCase) {
1236         $hasGetter = 1;
1237         $hasCustomSetter = 1;
1238     }
1239
1240     if (!$hasGetter) {
1241         return;
1242     }
1243
1244     $implIncludes{"V8Collection.h"} = 1;
1245
1246     my $indexerType = $indexer ? $indexer->type : 0;
1247
1248     # FIXME: Remove this once toV8 helper methods are implemented (see https://bugs.webkit.org/show_bug.cgi?id=32563).
1249     if ($interfaceName eq "WebKitCSSKeyframesRule") {
1250         $indexerType = "WebKitCSSKeyframeRule";
1251     }
1252
1253     if ($indexerType && !$hasCustomSetter) {
1254         if ($indexerType eq "DOMString") {
1255             my $conversion = $indexer->extendedAttributes->{"ConvertNullStringTo"};
1256             if ($conversion && $conversion eq "Null") {
1257                 push(@implContent, <<END);
1258   setCollectionStringOrNullIndexedGetter<${interfaceName}>(desc);
1259 END
1260             } else {
1261                 push(@implContent, <<END);
1262   setCollectionStringIndexedGetter<${interfaceName}>(desc);
1263 END
1264             }
1265         } else {
1266             my $indexerClassIndex = uc($indexerType);
1267             push(@implContent, <<END);
1268   setCollectionIndexedGetter<${interfaceName}, ${indexerType}>(desc, V8ClassIndex::${indexerClassIndex});
1269 END
1270         }
1271
1272         return;
1273     }
1274
1275     my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
1276     my $hasEnumerator = !$isSpecialCase && IsNodeSubType($dataNode);
1277     my $setOn = "Instance";
1278
1279     # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
1280     # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
1281     # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
1282     # on the object.
1283     if ($interfaceName eq "DOMWindow") {
1284         $setOn = "Prototype";
1285         $hasDeleter = 0;
1286     }
1287
1288     push(@implContent, "  desc->${setOn}Template()->SetIndexedPropertyHandler(V8Custom::v8${interfaceName}IndexedPropertyGetter");
1289     push(@implContent, $hasCustomSetter ? ", V8Custom::v8${interfaceName}IndexedPropertySetter" : ", 0");
1290     push(@implContent, ", 0"); # IndexedPropertyQuery -- not being used at the moment.
1291     push(@implContent, $hasDeleter ? ", V8Custom::v8${interfaceName}IndexedPropertyDeleter" : ", 0");
1292     push(@implContent, ", nodeCollectionIndexedPropertyEnumerator<${interfaceName}>, v8::Integer::New(V8ClassIndex::NODE)") if $hasEnumerator;
1293     push(@implContent, ");\n");
1294 }
1295
1296 sub GenerateImplementationNamedPropertyGetter
1297 {
1298     my $dataNode = shift;
1299     my $namedPropertyGetter = shift;
1300     my $interfaceName = $dataNode->name;
1301     my $hasCustomGetter = $dataNode->extendedAttributes->{"HasOverridingNameGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
1302
1303     # FIXME: Remove hard-coded HTMLOptionsCollection reference by changing HTMLOptionsCollection to not inherit
1304     # from HTMLCollection per W3C spec (http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/html.html#HTMLOptionsCollection).
1305     if ($interfaceName eq "HTMLOptionsCollection") {
1306         $interfaceName = "HTMLCollection";
1307         $hasCustomGetter = 1;
1308     }
1309
1310     my $hasGetter = $dataNode->extendedAttributes->{"HasNameGetter"} || $hasCustomGetter || $namedPropertyGetter;
1311     if (!$hasGetter) {
1312         return;
1313     }
1314
1315     if ($namedPropertyGetter && $namedPropertyGetter->type ne "Node" && !$namedPropertyGetter->extendedAttributes->{"Custom"} && !$hasCustomGetter) {
1316         $implIncludes{"V8Collection.h"} = 1;
1317         my $type = $namedPropertyGetter->type;
1318         my $classIndex = uc($type);
1319         push(@implContent, <<END);
1320   setCollectionNamedGetter<${interfaceName}, ${type}>(desc, V8ClassIndex::${classIndex});
1321 END
1322         return;
1323     }
1324
1325     my $hasSetter = $dataNode->extendedAttributes->{"DelegatingPutFunction"};
1326     # FIXME: Try to remove hard-coded HTMLDocument reference by aligning handling of document.all with JSC bindings.
1327     my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"} || $interfaceName eq "HTMLDocument";
1328     my $hasEnumerator = $dataNode->extendedAttributes->{"CustomGetPropertyNames"};
1329     my $setOn = "Instance";
1330
1331     # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
1332     # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
1333     # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
1334     # on the object.
1335     if ($interfaceName eq "DOMWindow") {
1336         $setOn = "Prototype";
1337         $hasDeleter = 0;
1338         $hasEnumerator = 0;
1339     }
1340
1341     push(@implContent, "  desc->${setOn}Template()->SetNamedPropertyHandler(V8Custom::v8${interfaceName}NamedPropertyGetter, ");
1342     push(@implContent, $hasSetter ? "V8Custom::v8${interfaceName}NamedPropertySetter, " : "0, ");
1343     push(@implContent, "0 ,"); # NamedPropertyQuery -- not being used at the moment.
1344     push(@implContent, $hasDeleter ? "V8Custom::v8${interfaceName}NamedPropertyDeleter, " : "0, ");
1345     push(@implContent, $hasEnumerator ? "V8Custom::v8${interfaceName}NamedPropertyEnumerator" : "0");
1346     push(@implContent, ");\n");
1347 }
1348
1349 sub GenerateImplementationCustomCall
1350 {
1351     my $dataNode = shift;
1352     my $interfaceName = $dataNode->name;
1353     my $hasCustomCall = $dataNode->extendedAttributes->{"CustomCall"};
1354
1355     # FIXME: Remove hard-coded HTMLOptionsCollection reference.
1356     if ($interfaceName eq "HTMLOptionsCollection") {
1357         $interfaceName = "HTMLCollection";
1358         $hasCustomCall = 1;
1359     }
1360
1361     if ($hasCustomCall) {
1362         push(@implContent, "  desc->InstanceTemplate()->SetCallAsFunctionHandler(V8${interfaceName}::callAsFunctionCallback);\n");
1363     }
1364 }
1365
1366 sub GenerateImplementationMasqueradesAsUndefined
1367 {
1368     my $dataNode = shift;
1369     if ($dataNode->extendedAttributes->{"MasqueradesAsUndefined"})
1370     {
1371         push(@implContent, "  desc->InstanceTemplate()->MarkAsUndetectable();\n");
1372     }
1373 }
1374
1375 sub GenerateImplementation
1376 {
1377     my $object = shift;
1378     my $dataNode = shift;
1379     my $interfaceName = $dataNode->name;
1380     my $className = "V8$interfaceName";
1381     my $implClassName = $interfaceName;
1382     my $classIndex = uc($codeGenerator->StripModule($interfaceName));
1383
1384     my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
1385     my $conditionalString = GenerateConditionalString($dataNode);
1386
1387     # - Add default header template
1388     @implContentHeader = split("\r", $headerTemplate);
1389
1390     push(@implFixedHeader,
1391          "#include \"config.h\"\n" .
1392          "#include \"V8Proxy.h\"\n" .
1393          "#include \"V8Binding.h\"\n" .
1394          "#include \"V8BindingState.h\"\n\n" .
1395          "#undef LOG\n\n");
1396
1397     push(@implFixedHeader, "\n#if ${conditionalString}\n\n") if $conditionalString;
1398
1399     if ($className =~ /^V8SVGAnimated/) {
1400         AddIncludesForSVGAnimatedType($interfaceName);
1401     }
1402
1403     $implIncludes{"${className}.h"} = 1;
1404
1405     AddIncludesForType($interfaceName);
1406     $implIncludes{"V8Proxy.h"} = 1;
1407
1408     push(@implContentDecls, "namespace WebCore {\n");
1409     push(@implContentDecls, "namespace ${interfaceName}Internal {\n\n");
1410     push(@implContentDecls, "template <typename T> void V8_USE(T) { }\n\n");
1411
1412     my $hasConstructors = 0;
1413     # Generate property accessors for attributes.
1414     for ($index = 0; $index < @{$dataNode->attributes}; $index++) {
1415         $attribute = @{$dataNode->attributes}[$index];
1416         $attrName = $attribute->signature->name;
1417         $attrType = $attribute->signature->type;
1418
1419         # Generate special code for the constructor attributes.
1420         if ($attrType =~ /Constructor$/) {
1421             if ($attribute->signature->extendedAttributes->{"CustomGetter"}) {
1422                 $implIncludes{"V8CustomBinding.h"} = 1;
1423             } else {
1424                 $hasConstructors = 1;
1425             }
1426             next;
1427         }
1428
1429         if ($attrType eq "EventListener" && $interfaceName eq "DOMWindow") {
1430             $attribute->signature->extendedAttributes->{"v8OnProto"} = 1;
1431         }
1432
1433         # Do not generate accessor if this is a custom attribute.  The
1434         # call will be forwarded to a hand-written accessor
1435         # implementation.
1436         if ($attribute->signature->extendedAttributes->{"Custom"} ||
1437             $attribute->signature->extendedAttributes->{"V8Custom"}) {
1438             $implIncludes{"V8CustomBinding.h"} = 1;
1439             next;
1440         }
1441
1442         # Generate the accessor.
1443         if ($attribute->signature->extendedAttributes->{"CustomGetter"}) {
1444             $implIncludes{"V8CustomBinding.h"} = 1;
1445         } else {
1446             GenerateNormalAttrGetter($attribute, $dataNode, $classIndex, $implClassName, $interfaceName);
1447         }
1448         if ($attribute->signature->extendedAttributes->{"CustomSetter"} ||
1449             $attribute->signature->extendedAttributes->{"V8CustomSetter"}) {
1450             $implIncludes{"V8CustomBinding.h"} = 1;
1451         } elsif ($attribute->signature->extendedAttributes->{"Replaceable"}) {
1452             $dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"} || die "Replaceable attribute can only be used in interface that defines ExtendsDOMGlobalObject attribute!";
1453             # GenerateReplaceableAttrSetter($implClassName);
1454         } elsif ($attribute->type !~ /^readonly/ && !$attribute->signature->extendedAttributes->{"V8ReadOnly"}) {
1455             GenerateNormalAttrSetter($attribute, $dataNode, $classIndex, $implClassName, $interfaceName);
1456         }
1457     }
1458
1459     if ($hasConstructors) {
1460         GenerateConstructorGetter($implClassName, $classIndex);
1461     }
1462
1463     my $indexer;
1464     my $namedPropertyGetter;
1465     # Generate methods for functions.
1466     foreach my $function (@{$dataNode->functions}) {
1467         # hack for addEventListener/RemoveEventListener
1468         # FIXME: avoid naming conflict
1469         if ($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"V8Custom"}) {
1470                 $implIncludes{"V8CustomBinding.h"} = 1;
1471         } else {
1472             GenerateFunctionCallback($function, $dataNode, $classIndex, $implClassName);
1473         }
1474
1475         if ($function->signature->name eq "item") {
1476             $indexer = $function->signature;
1477         }
1478
1479         if ($function->signature->name eq "namedItem") {
1480             $namedPropertyGetter = $function->signature;
1481         }
1482
1483         # If the function does not need domain security check, we need to
1484         # generate an access getter that returns different function objects
1485         # for different calling context.
1486         if (($dataNode->extendedAttributes->{"CheckDomainSecurity"} || ($interfaceName eq "DOMWindow")) && $function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
1487             GenerateDomainSafeFunctionGetter($function, $dataNode, $classIndex, $implClassName);
1488         }
1489     }
1490
1491     # Attributes
1492     my $attributes = $dataNode->attributes;
1493
1494     # For the DOMWindow interface we partition the attributes into the
1495     # ones that disallows shadowing and the rest.
1496     my @disallowsShadowing;
1497     # Also separate out attributes that are enabled at runtime so we can process them specially.
1498     my @enabledAtRuntime;
1499     my @normal;
1500     foreach my $attribute (@$attributes) {
1501
1502         if ($interfaceName eq "DOMWindow" && $attribute->signature->extendedAttributes->{"V8DisallowShadowing"}) {
1503             push(@disallowsShadowing, $attribute);
1504         } elsif ($attribute->signature->extendedAttributes->{"EnabledAtRuntime"}) {
1505             push(@enabledAtRuntime, $attribute);
1506         } else {
1507             push(@normal, $attribute);
1508         }
1509     }
1510     $attributes = \@normal;
1511     # Put the attributes that disallow shadowing on the shadow object.
1512     if (@disallowsShadowing) {
1513         push(@implContent, "static const BatchedAttribute shadow_attrs[] = {\n");
1514         GenerateBatchedAttributeData($dataNode, \@disallowsShadowing);
1515         push(@implContent, "};\n");
1516     }
1517
1518     my $has_attributes = 0;
1519     if (@$attributes) {
1520         $has_attributes = 1;
1521         push(@implContent, "static const BatchedAttribute ${interfaceName}_attrs[] = {\n");
1522         GenerateBatchedAttributeData($dataNode, $attributes);
1523         push(@implContent, "};\n");
1524     }
1525     
1526     # Setup table of standard callback functions
1527     $num_callbacks = 0;
1528     $has_callbacks = 0;
1529     foreach my $function (@{$dataNode->functions}) {
1530         my $attrExt = $function->signature->extendedAttributes;
1531         # Don't put any nonstandard functions into this table:
1532         if ($attrExt->{"V8OnInstance"}) {
1533             next;
1534         }
1535         if ($attrExt->{"EnabledAtRuntime"} || RequiresCustomSignature($function) || $attrExt->{"V8DoNotCheckSignature"}) {
1536             next;
1537         }
1538         if ($attrExt->{"DoNotCheckDomainSecurity"} &&
1539             ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) {
1540             next;
1541         }
1542         if ($attrExt->{"DontEnum"} || $attrExt->{"V8ReadOnly"}) {
1543             next;
1544         }
1545         if (!$has_callbacks) {
1546             $has_callbacks = 1;
1547             push(@implContent, "static const BatchedCallback ${interfaceName}_callbacks[] = {\n");
1548         }
1549         my $name = $function->signature->name;
1550         my $callback = GetFunctionTemplateCallbackName($function, $dataNode);
1551         push(@implContent, <<END);
1552   {"$name", $callback},
1553 END
1554         $num_callbacks++;
1555     }
1556     push(@implContent, "};\n")  if $has_callbacks;
1557
1558     # Setup constants
1559     my $has_constants = 0;
1560     if (@{$dataNode->constants}) {
1561         $has_constants = 1;
1562         push(@implContent, "static const BatchedConstant ${interfaceName}_consts[] = {\n");
1563     }
1564     foreach my $constant (@{$dataNode->constants}) {
1565         my $name = $constant->name;
1566         my $value = $constant->value;
1567         # FIXME: we need the static_cast here only because of one constant, NodeFilter.idl
1568         # defines "const unsigned long SHOW_ALL = 0xFFFFFFFF".  It would be better if we
1569         # handled this here, and converted it to a -1 constant in the c++ output.
1570         push(@implContent, <<END);
1571   { "${name}", static_cast<signed int>($value) },
1572 END
1573     }
1574     if ($has_constants) {
1575         push(@implContent, "};\n");
1576     }
1577
1578     push(@implContentDecls, "} // namespace ${interfaceName}Internal\n\n");
1579
1580     my $access_check = "";
1581     if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !($interfaceName eq "DOMWindow")) {
1582         $access_check = "instance->SetAccessCheckCallbacks(V8${interfaceName}::namedSecurityCheck, V8${interfaceName}::indexedSecurityCheck, v8::Integer::New(V8ClassIndex::ToInt(V8ClassIndex::${classIndex})));";
1583     }
1584
1585     # For the DOMWindow interface, generate the shadow object template
1586     # configuration method.
1587     if ($implClassName eq "DOMWindow") {
1588         push(@implContent, <<END);
1589 static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Persistent<v8::ObjectTemplate> templ) {
1590   batchConfigureAttributes(templ,
1591                            v8::Handle<v8::ObjectTemplate>(),
1592                            shadow_attrs,
1593                            sizeof(shadow_attrs)/sizeof(*shadow_attrs));
1594   return templ;
1595 }
1596 END
1597     }
1598
1599     # find the super descriptor
1600     my $parentClassIndex = "INVALID_CLASS_INDEX";
1601     foreach (@{$dataNode->parents}) {
1602         my $parent = $codeGenerator->StripModule($_);
1603         if ($parent eq "EventTarget") { next; }
1604         $implIncludes{"V8${parent}.h"} = 1;
1605         $parentClassIndex = uc($codeGenerator->StripModule($parent));
1606         last;
1607     }
1608
1609     # find the field count
1610     my $fieldCount = "V8Custom::kDefaultWrapperInternalFieldCount";
1611     if (IsNodeSubType($dataNode)) {
1612         $fieldCount = "V8Custom::kNodeMinimumInternalFieldCount";
1613     }
1614     
1615     # Generate the template configuration method
1616     push(@implContent,  <<END);
1617 static v8::Persistent<v8::FunctionTemplate> Configure${className}Template(v8::Persistent<v8::FunctionTemplate> desc) {
1618   v8::Local<v8::Signature> default_signature = configureTemplate(desc, \"${interfaceName}\",
1619       V8ClassIndex::$parentClassIndex, $fieldCount,
1620 END
1621
1622     # Set up our attributes if we have them
1623     if ($has_attributes) {
1624         push(@implContent, <<END);
1625       ${interfaceName}_attrs, sizeof(${interfaceName}_attrs)/sizeof(*${interfaceName}_attrs),
1626 END
1627     } else {
1628         push(@implContent, <<END);
1629       NULL, 0,
1630 END
1631     }
1632     
1633     if ($has_callbacks) {
1634         push(@implContent, <<END);
1635       ${interfaceName}_callbacks, sizeof(${interfaceName}_callbacks)/sizeof(*${interfaceName}_callbacks));
1636 END
1637     } else {
1638         push(@implContent, <<END);
1639       NULL, 0);
1640 END
1641     }
1642
1643     if ($access_check or @enabledAtRuntime or @{$dataNode->functions} or $has_constants) {
1644     push(@implContent,  <<END);
1645   v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate();
1646   v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate();
1647 END
1648     }
1649
1650     push(@implContent,  "  $access_check\n");
1651     
1652     # Setup the enable-at-runtime attrs if we have them
1653     foreach my $runtime_attr (@enabledAtRuntime) {
1654         $enable_function = $interfaceName . "::" . $codeGenerator->WK_ucfirst($runtime_attr->signature->name);
1655         my $conditionalString = GenerateConditionalString($runtime_attr->signature);
1656         push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
1657         push(@implContent, "    if (V8${enable_function}Enabled()) {\n");
1658         push(@implContent, "        static const BatchedAttribute attrData =\\\n");
1659         GenerateSingleBatchedAttribute($interfaceName, $runtime_attr, ";", "    ");
1660         push(@implContent, <<END);
1661         configureAttribute(instance, proto, attrData);
1662     }
1663 END
1664         push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
1665     }
1666
1667     GenerateImplementationIndexer($dataNode, $indexer);
1668     GenerateImplementationNamedPropertyGetter($dataNode, $namedPropertyGetter);
1669     GenerateImplementationCustomCall($dataNode);
1670     GenerateImplementationMasqueradesAsUndefined($dataNode);
1671
1672     # Define our functions with Set() or SetAccessor()
1673     $total_functions = 0;
1674     foreach my $function (@{$dataNode->functions}) {
1675         $total_functions++;
1676         my $attrExt = $function->signature->extendedAttributes;
1677         my $name = $function->signature->name;
1678
1679         my $property_attributes = "v8::DontDelete";
1680         if ($attrExt->{"DontEnum"}) {
1681             $property_attributes .= "|v8::DontEnum";
1682         }
1683         if ($attrExt->{"V8ReadOnly"}) {
1684             $property_attributes .= "|v8::ReadOnly";
1685         }
1686
1687         my $commentInfo = "Function '$name' (ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
1688
1689         my $template = "proto";
1690         if ($attrExt->{"V8OnInstance"}) {
1691             $template = "instance";
1692         }
1693
1694         my $conditional = "";
1695         if ($attrExt->{"EnabledAtRuntime"}) {
1696             # Only call Set()/SetAccessor() if this method should be enabled
1697             $enable_function = $interfaceName . "::" . $codeGenerator->WK_ucfirst($function->signature->name);
1698             $conditional = "if (V8${enable_function}Enabled())\n";
1699         }
1700
1701         if ($attrExt->{"DoNotCheckDomainSecurity"} &&
1702             ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) {
1703             # Mark the accessor as ReadOnly and set it on the proto object so
1704             # it can be shadowed. This is really a hack to make it work.
1705             # There are several sceneria to call into the accessor:
1706             #   1) from the same domain: "window.open":
1707             #      the accessor finds the DOM wrapper in the proto chain;
1708             #   2) from the same domain: "window.__proto__.open":
1709             #      the accessor will NOT find a DOM wrapper in the prototype chain
1710             #   3) from another domain: "window.open":
1711             #      the access find the DOM wrapper in the prototype chain
1712             #   "window.__proto__.open" from another domain will fail when
1713             #   accessing '__proto__'
1714             #
1715             # The solution is very hacky and fragile, it really needs to be replaced
1716             # by a better solution.
1717             $property_attributes .= "|v8::ReadOnly";
1718             push(@implContent, <<END);
1719
1720   // $commentInfo
1721   $conditional $template->SetAccessor(
1722       v8::String::New("$name"),
1723       ${interfaceName}Internal::${name}AttrGetter,
1724       0,
1725       v8::Handle<v8::Value>(),
1726       v8::ALL_CAN_READ,
1727       static_cast<v8::PropertyAttribute>($property_attributes));
1728 END
1729           $num_callbacks++;
1730           next;
1731       }
1732
1733       my $signature = "default_signature";
1734       if ($attrExt->{"V8DoNotCheckSignature"}){
1735           $signature = "v8::Local<v8::Signature>()";
1736       }
1737
1738       if (RequiresCustomSignature($function)) {
1739           $signature = "${name}_signature";
1740           push(@implContent, "\n  // Custom Signature '$name'\n", CreateCustomSignature($function));
1741       }
1742
1743       # Normal function call is a template
1744       my $callback = GetFunctionTemplateCallbackName($function, $dataNode);
1745       
1746       if ($property_attributes eq "v8::DontDelete") {
1747           $property_attributes = "";
1748       } else {
1749           $property_attributes = ", static_cast<v8::PropertyAttribute>($property_attributes)";
1750       }
1751       
1752       if ($template eq "proto" && $conditional eq "" && $signature eq "default_signature" && $property_attributes eq "") {
1753           # Standard type of callback, already created in the batch, so skip it here.
1754           next;
1755       }
1756       
1757       push(@implContent, <<END);
1758   ${conditional}createCallback($template, "$name", $callback, ${signature}$property_attributes);
1759 END
1760       $num_callbacks++;
1761     }
1762     
1763     die "Wrong number of callbacks generated for $interfaceName ($num_callbacks, should be $total_functions)" if $num_callbacks != $total_functions;
1764
1765     if ($has_constants) {
1766         push(@implContent, <<END);
1767   batchConfigureConstants(desc, proto, ${interfaceName}_consts, sizeof(${interfaceName}_consts)/sizeof(*${interfaceName}_consts));
1768 END
1769     }
1770
1771     push(@implContent, <<END);
1772   return desc;
1773 }
1774
1775 v8::Persistent<v8::FunctionTemplate> ${className}::GetRawTemplate() {
1776   static v8::Persistent<v8::FunctionTemplate> ${className}_raw_cache_ = createRawTemplate();
1777   return ${className}_raw_cache_;
1778 }
1779
1780 v8::Persistent<v8::FunctionTemplate> ${className}::GetTemplate() {
1781   static v8::Persistent<v8::FunctionTemplate> ${className}_cache_ = Configure${className}Template(GetRawTemplate());
1782   return ${className}_cache_;
1783 }
1784
1785 bool ${className}::HasInstance(v8::Handle<v8::Value> value) {
1786   return GetRawTemplate()->HasInstance(value);
1787 }
1788
1789 END
1790
1791     if ($implClassName eq "DOMWindow") {
1792         push(@implContent, <<END);
1793 v8::Persistent<v8::ObjectTemplate> V8DOMWindow::GetShadowObjectTemplate() {
1794   static v8::Persistent<v8::ObjectTemplate> V8DOMWindowShadowObject_cache_;
1795   if (V8DOMWindowShadowObject_cache_.IsEmpty()) {
1796     V8DOMWindowShadowObject_cache_ = v8::Persistent<v8::ObjectTemplate>::New(v8::ObjectTemplate::New());
1797     ConfigureShadowObjectTemplate(V8DOMWindowShadowObject_cache_);
1798   }
1799   return V8DOMWindowShadowObject_cache_;
1800 }
1801 END
1802     }
1803
1804     push(@implContent, <<END);
1805 } // namespace WebCore
1806 END
1807
1808     push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
1809 }
1810
1811
1812 sub GenerateFunctionCallString()
1813 {
1814     my $function = shift;
1815     my $numberOfParameters = shift;
1816     my $indent = shift;
1817     my $implClassName = shift;
1818
1819     my $name = $function->signature->name;
1820     my $isPodType = IsPodType($implClassName);
1821     my $returnType = GetTypeFromSignature($function->signature);
1822     my $returnsPodType = IsPodType($returnType);
1823     my $nativeReturnType = GetNativeType($returnType, 0);
1824     my $result = "";
1825
1826     # Special case: SVG matrix transform methods should not mutate
1827     # the matrix but return a copy
1828     my $copyFirst = 0;
1829     if ($implClassName eq "SVGMatrix" && $function->signature->type eq "SVGMatrix") {
1830         $copyFirst = 1;
1831     }
1832
1833     if ($function->signature->extendedAttributes->{"v8implname"}) {
1834         $name = $function->signature->extendedAttributes->{"v8implname"};
1835     }
1836
1837     if ($function->signature->extendedAttributes->{"ImplementationFunction"}) {
1838         $name = $function->signature->extendedAttributes->{"ImplementationFunction"};
1839     }
1840
1841     my $functionString = "imp->${name}(";
1842
1843     if ($copyFirst) {
1844         $functionString = "result.${name}(";
1845     }
1846
1847     my $returnsListItemPodType = 0;
1848     # SVG lists functions that return POD types require special handling
1849     if (IsSVGListTypeNeedingSpecialHandling($implClassName) && IsSVGListMethod($name) && $returnsPodType) {
1850         $returnsListItemPodType = 1;
1851         $result .= $indent . "SVGList<RefPtr<SVGPODListItem<$nativeReturnType> > >* listImp = imp;\n";
1852         $functionString = "listImp->${name}(";
1853     }
1854
1855     my $first = 1;
1856     my $index = 0;
1857     my $nodeToReturn = 0;
1858
1859     foreach my $parameter (@{$function->parameters}) {
1860         if ($index eq $numberOfParameters) {
1861             last;
1862         }
1863         if ($first) { $first = 0; }
1864         else { $functionString .= ", "; }
1865         my $paramName = $parameter->name;
1866         my $paramType = $parameter->type;
1867
1868         # This is a bit of a hack... we need to convert parameters to methods on SVG lists
1869         # of POD types which are items in the list to appropriate SVGList<> instances
1870         if ($returnsListItemPodType && $paramType . "List" eq $implClassName) {
1871             $paramName = "SVGPODListItem<" . GetNativeType($paramType, 1) . ">::copy($paramName)";
1872         }
1873
1874         if ($parameter->type eq "NodeFilter" || $parameter->type eq "XPathNSResolver") {
1875             $functionString .= "$paramName.get()";
1876         } else {
1877             $functionString .= $paramName;
1878         }
1879
1880         if ($parameter->extendedAttributes->{"Return"}) {
1881             $nodeToReturn = $parameter->name;
1882         }
1883         $index++;
1884     }
1885
1886     if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
1887         $functionString .= ", " if not $first;
1888         $functionString .= "callStack.get()";
1889         if ($first) { $first = 0; }
1890     }
1891
1892     if (@{$function->raisesExceptions}) {
1893         $functionString .= ", " if not $first;
1894         $functionString .= "ec";
1895     }
1896     $functionString .= ")";
1897
1898     my $return = "result";
1899     my $returnIsRef = IsRefPtrType($returnType);
1900
1901     if ($nodeToReturn) {
1902         # Special case for insertBefore, replaceChild, removeChild and
1903         # appendChild functions from Node.
1904         $result .= $indent . "bool success = $functionString;\n";
1905         if (@{$function->raisesExceptions}) {
1906             $result .= $indent . "if (UNLIKELY(ec)) goto fail;\n";
1907         }
1908         $result .= $indent . "if (success)\n";
1909         $result .= $indent . "    " .
1910             "return V8DOMWrapper::convertNodeToV8Object($nodeToReturn);\n";
1911         $result .= $indent . "return v8::Null();\n";
1912         return $result;
1913     } elsif ($returnType eq "void") {
1914         $result .= $indent . "$functionString;\n";
1915     } elsif ($copyFirst) {
1916         $result .=
1917             $indent . GetNativeType($returnType, 0) . " result = *imp;\n" .
1918             $indent . "$functionString;\n";
1919     } elsif ($returnsListItemPodType) {
1920         $result .= $indent . "RefPtr<SVGPODListItem<$nativeReturnType> > result = $functionString;\n";
1921     } elsif (@{$function->raisesExceptions} or $returnsPodType or $isPodType or IsSVGTypeNeedingContextParameter($returnType)) {
1922         $result .= $indent . $nativeReturnType . " result = $functionString;\n";
1923     } else {
1924         # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
1925         $return = $functionString;
1926         $returnIsRef = 0;
1927     }
1928
1929     if (@{$function->raisesExceptions}) {
1930         $result .= $indent . "if (UNLIKELY(ec)) goto fail;\n";
1931     }
1932
1933     # If the return type is a POD type, separate out the wrapper generation
1934     if ($returnsListItemPodType) {
1935         $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = ";
1936         $result .= "V8SVGPODTypeWrapperCreatorForList<" . $nativeReturnType . ">::create($return, imp->associatedAttributeName());\n";
1937         $return = "wrapper";
1938     } elsif ($returnsPodType) {
1939         $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = ";
1940         $result .= GenerateSVGStaticPodTypeWrapper($returnType, $return) . ";\n";
1941         $return = "wrapper";
1942     }
1943
1944     my $generatedSVGContextRetrieval = 0;
1945     # If the return type needs an SVG context, output it
1946     if (IsSVGTypeNeedingContextParameter($returnType)) {
1947         $result .= GenerateSVGContextAssignment($implClassName, $return . ".get()", $indent);
1948         $generatedSVGContextRetrieval = 1;
1949     }
1950
1951     if (IsSVGTypeNeedingContextParameter($implClassName) && $implClassName =~ /List$/ && IsSVGListMutator($name)) {
1952         if (!$generatedSVGContextRetrieval) {
1953             $result .= GenerateSVGContextRetrieval($implClassName, $indent);
1954             $generatedSVGContextRetrieval = 1;
1955         }
1956
1957         $result .= $indent . "context->svgAttributeChanged(imp->associatedAttributeName());\n";
1958         $implIncludes{"SVGElement.h"} = 1;
1959     }
1960
1961     # If the implementing class is a POD type, commit changes
1962     if ($isPodType) {
1963         if (!$generatedSVGContextRetrieval) {
1964             $result .= GenerateSVGContextRetrieval($implClassName, $indent);
1965             $generatedSVGContextRetrieval = 1;
1966         }
1967
1968         $result .= $indent . "imp_wrapper->commitChange(imp_instance, context);\n";
1969     }
1970
1971     if ($returnsPodType) {
1972         my $classIndex = uc($returnType);
1973         $result .= $indent . "return V8DOMWrapper::convertToV8Object(V8ClassIndex::$classIndex, wrapper.release());\n";
1974     } else {
1975         $return .= ".release()" if ($returnIsRef);
1976         $result .= $indent . ReturnNativeToJSValue($function->signature, $return, $indent) . ";\n";
1977     }
1978
1979     return $result;
1980 }
1981
1982
1983 sub GetTypeFromSignature
1984 {
1985     my $signature = shift;
1986
1987     return $codeGenerator->StripModule($signature->type);
1988 }
1989
1990
1991 sub GetNativeTypeFromSignature
1992 {
1993     my $signature = shift;
1994     my $parameterIndex = shift;
1995
1996     my $type = GetTypeFromSignature($signature);
1997
1998     if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) {
1999         # Special-case index arguments because we need to check that they aren't < 0.
2000         return "int";
2001     }
2002
2003     $type = GetNativeType($type, $parameterIndex >= 0 ? 1 : 0);
2004     
2005     if ($parameterIndex >= 0 && $type eq "V8Parameter") {
2006         my $mode = "";
2007         if ($signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"}) {
2008             $mode = "WithUndefinedOrNullCheck";
2009         } elsif ($signature->extendedAttributes->{"ConvertNullToNullString"}) {
2010             $mode = "WithNullCheck";
2011         }
2012         $type .= "<$mode>";
2013     }
2014     
2015     return $type;
2016 }
2017
2018 sub IsRefPtrType
2019 {
2020     my $type = shift;
2021     return 1 if $type eq "Attr";
2022     return 1 if $type eq "CanvasBooleanArray";
2023     return 1 if $type eq "CanvasGradient";
2024     return 1 if $type eq "CanvasObject";
2025     return 1 if $type eq "ClientRect";
2026     return 1 if $type eq "ClientRectList";
2027     return 1 if $type eq "CDATASection";
2028     return 1 if $type eq "Comment";
2029     return 1 if $type eq "CSSRule";
2030     return 1 if $type eq "CSSStyleRule";
2031     return 1 if $type eq "CSSCharsetRule";
2032     return 1 if $type eq "CSSImportRule";
2033     return 1 if $type eq "CSSMediaRule";
2034     return 1 if $type eq "CSSFontFaceRule";
2035     return 1 if $type eq "CSSPageRule";
2036     return 1 if $type eq "CSSPrimitiveValue";
2037     return 1 if $type eq "CSSStyleSheet";
2038     return 1 if $type eq "CSSStyleDeclaration";
2039     return 1 if $type eq "CSSValue";
2040     return 1 if $type eq "CSSRuleList";
2041     return 1 if $type eq "Database";
2042     return 1 if $type eq "Document";
2043     return 1 if $type eq "DocumentFragment";
2044     return 1 if $type eq "DocumentType";
2045     return 1 if $type eq "Element";
2046     return 1 if $type eq "EntityReference";
2047     return 1 if $type eq "Event";
2048     return 1 if $type eq "EventListener";
2049     return 1 if $type eq "FileList";
2050     return 1 if $type eq "HTMLCollection";
2051     return 1 if $type eq "HTMLAllCollection";
2052     return 1 if $type eq "HTMLDocument";
2053     return 1 if $type eq "HTMLElement";
2054     return 1 if $type eq "HTMLOptionsCollection";
2055     return 1 if $type eq "ImageData";
2056     return 1 if $type eq "Media";
2057     return 1 if $type eq "MediaError";
2058     return 1 if $type eq "MimeType";
2059     return 1 if $type eq "Node";
2060     return 1 if $type eq "NodeList";
2061     return 1 if $type eq "NodeFilter";
2062     return 1 if $type eq "NodeIterator";
2063     return 1 if $type eq "NSResolver";
2064     return 1 if $type eq "Plugin";
2065     return 1 if $type eq "ProcessingInstruction";
2066     return 1 if $type eq "Range";
2067     return 1 if $type eq "RGBColor";
2068     return 1 if $type eq "Text";
2069     return 1 if $type eq "TextMetrics";
2070     return 1 if $type eq "TimeRanges";
2071     return 1 if $type eq "TreeWalker";
2072     return 1 if $type eq "WebGLActiveInfo";
2073     return 1 if $type eq "WebGLArray";
2074     return 1 if $type eq "WebGLArrayBuffer";
2075     return 1 if $type eq "WebGLByteArray";
2076     return 1 if $type eq "WebGLBuffer";
2077     return 1 if $type eq "WebGLFloatArray";
2078     return 1 if $type eq "WebGLFramebuffer";
2079     return 1 if $type eq "WebGLIntArray";
2080     return 1 if $type eq "WebGLProgram";
2081     return 1 if $type eq "WebGLRenderbuffer";
2082     return 1 if $type eq "WebGLShader";
2083     return 1 if $type eq "WebGLShortArray";
2084     return 1 if $type eq "WebGLTexture";
2085     return 1 if $type eq "WebGLUniformLocation";
2086     return 1 if $type eq "WebGLUnsignedByteArray";
2087     return 1 if $type eq "WebGLUnsignedIntArray";
2088     return 1 if $type eq "WebGLUnsignedShortArray";
2089     return 1 if $type eq "WebKitCSSMatrix";
2090     return 1 if $type eq "WebKitPoint";
2091     return 1 if $type eq "XPathExpression";
2092     return 1 if $type eq "XPathNSResolver";
2093     return 1 if $type eq "XPathResult";
2094
2095     return 1 if $type eq "SVGElementInstance";
2096     return 1 if $type eq "SVGElementInstanceList";
2097     return 1 if $type =~ /^SVGPathSeg/;
2098
2099     return 1 if $type =~ /^SVGAnimated/;
2100
2101     return 0;
2102 }
2103
2104 sub IsVideoClassName
2105 {
2106     my $class = shift;
2107     return 1 if $class eq "V8HTMLAudioElement";
2108     return 1 if $class eq "V8HTMLMediaElement";
2109     return 1 if $class eq "V8HTMLSourceElement";
2110     return 1 if $class eq "V8HTMLVideoElement";
2111     return 1 if $class eq "V8MediaError";
2112     return 1 if $class eq "V8TimeRanges";
2113
2114     return 0;
2115 }
2116
2117 sub IsWorkerClassName
2118 {
2119     my $class = shift;
2120     return 1 if $class eq "V8Worker";
2121     return 1 if $class eq "V8WorkerContext";
2122     return 1 if $class eq "V8WorkerLocation";
2123     return 1 if $class eq "V8WorkerNavigator";
2124
2125     return 0;
2126 }
2127
2128 sub GetNativeType
2129 {
2130     my $type = shift;
2131     my $isParameter = shift;
2132
2133     if ($type eq "float" or $type eq "double") {
2134         return $type;
2135     }
2136
2137     return "V8Parameter" if ($type eq "DOMString" or $type eq "DOMUserData") and $isParameter;
2138     return "int" if $type eq "int";
2139     return "int" if $type eq "short" or $type eq "unsigned short";
2140     return "unsigned" if $type eq "unsigned long";
2141     return "int" if $type eq "long";
2142     return "unsigned long long" if $type eq "unsigned long long";
2143     return "bool" if $type eq "boolean";
2144     return "String" if $type eq "DOMString";
2145     return "Range::CompareHow" if $type eq "CompareHow";
2146     return "FloatRect" if $type eq "SVGRect";
2147     return "FloatPoint" if $type eq "SVGPoint";
2148     return "TransformationMatrix" if $type eq "SVGMatrix";
2149     return "SVGTransform" if $type eq "SVGTransform";
2150     return "SVGLength" if $type eq "SVGLength";
2151     return "SVGAngle" if $type eq "SVGAngle";
2152     return "double" if $type eq "SVGNumber";
2153     return "SVGPreserveAspectRatio" if $type eq "SVGPreserveAspectRatio";
2154     return "SVGPaint::SVGPaintType" if $type eq "SVGPaintType";
2155     return "DOMTimeStamp" if $type eq "DOMTimeStamp";
2156     return "unsigned" if $type eq "unsigned int";
2157     return "Node*" if $type eq "EventTarget" and $isParameter;
2158     return "double" if $type eq "Date";
2159
2160     return "String" if $type eq "DOMUserData";  # FIXME: Temporary hack?
2161
2162     # temporary hack
2163     return "RefPtr<NodeFilter>" if $type eq "NodeFilter";
2164
2165     # necessary as resolvers could be constructed on fly.
2166     return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver";
2167
2168     return "RefPtr<${type}>" if IsRefPtrType($type) and not $isParameter;
2169
2170     # Default, assume native type is a pointer with same type name as idl type
2171     return "${type}*";
2172 }
2173
2174
2175 my %typeCanFailConversion = (
2176     "Attr" => 1,
2177     "WebGLArray" => 0,
2178     "WebGLBuffer" => 0,
2179     "WebGLByteArray" => 0,
2180     "WebGLFloatArray" => 0,
2181     "WebGLFramebuffer" => 0,
2182     "CanvasGradient" => 0,
2183     "WebGLIntArray" => 0,
2184     "CanvasPixelArray" => 0,
2185     "WebGLProgram" => 0,
2186     "WebGLRenderbuffer" => 0,
2187     "WebGLShader" => 0,
2188     "WebGLShortArray" => 0,
2189     "WebGLTexture" => 0,
2190     "WebGLUniformLocation" => 0,
2191     "CompareHow" => 0,
2192     "DataGridColumn" => 0,
2193     "DOMString" => 0,
2194     "DOMWindow" => 0,
2195     "DocumentType" => 0,
2196     "Element" => 0,
2197     "Event" => 0,
2198     "EventListener" => 0,
2199     "EventTarget" => 0,
2200     "HTMLCanvasElement" => 0,
2201     "HTMLElement" => 0,
2202     "HTMLImageElement" => 0,
2203     "HTMLOptionElement" => 0,
2204     "HTMLVideoElement" => 0,
2205     "Node" => 0,
2206     "NodeFilter" => 0,
2207     "MessagePort" => 0,
2208     "NSResolver" => 0,
2209     "Range" => 0,
2210     "SQLResultSet" => 0,
2211     "Storage" => 0,
2212     "SVGAngle" => 1,
2213     "SVGElement" => 0,
2214     "SVGLength" => 1,
2215     "SVGMatrix" => 1,
2216     "SVGNumber" => 0,
2217     "SVGPaintType" => 0,
2218     "SVGPathSeg" => 0,
2219     "SVGPoint" => 1,
2220     "SVGPreserveAspectRatio" => 1,
2221     "SVGRect" => 1,
2222     "SVGTransform" => 1,
2223     "VoidCallback" => 1,
2224     "WebKitCSSMatrix" => 0,
2225     "WebKitPoint" => 0,
2226     "XPathEvaluator" => 0,
2227     "XPathNSResolver" => 0,
2228     "XPathResult" => 0,
2229     "boolean" => 0,
2230     "double" => 0,
2231     "float" => 0,
2232     "long" => 0,
2233     "unsigned long" => 0,
2234     "unsigned short" => 0,
2235 );
2236
2237
2238 sub TranslateParameter
2239 {
2240     my $signature = shift;
2241
2242     # The IDL uses some pseudo-types which don't really exist.
2243     if ($signature->type eq "TimeoutHandler") {
2244       $signature->type("DOMString");
2245     }
2246 }
2247
2248 sub BasicTypeCanFailConversion
2249 {
2250     my $signature = shift;
2251     my $type = GetTypeFromSignature($signature);
2252
2253     return 1 if $type eq "SVGAngle";
2254     return 1 if $type eq "SVGLength";
2255     return 1 if $type eq "SVGMatrix";
2256     return 1 if $type eq "SVGPoint";
2257     return 1 if $type eq "SVGPreserveAspectRatio";
2258     return 1 if $type eq "SVGRect";
2259     return 1 if $type eq "SVGTransform";
2260     return 0;
2261 }
2262
2263 sub TypeCanFailConversion
2264 {
2265     my $signature = shift;
2266
2267     my $type = GetTypeFromSignature($signature);
2268
2269     $implIncludes{"ExceptionCode.h"} = 1 if $type eq "Attr";
2270
2271     return $typeCanFailConversion{$type} if exists $typeCanFailConversion{$type};
2272
2273     die "Don't know whether a JS value can fail conversion to type $type.";
2274 }
2275
2276 sub JSValueToNative
2277 {
2278     my $signature = shift;
2279     my $value = shift;
2280     my $okParam = shift;
2281     my $maybeOkParam = $okParam ? ", ${okParam}" : "";
2282
2283     my $type = GetTypeFromSignature($signature);
2284
2285     return "$value" if $type eq "JSObject";
2286     return "$value->BooleanValue()" if $type eq "boolean";
2287     return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $type eq "double";
2288     return "$value->NumberValue()" if $type eq "SVGNumber";
2289
2290     return "toInt32($value${maybeOkParam})" if $type eq "unsigned long" or $type eq "unsigned short" or $type eq "long";
2291     return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "CompareHow";
2292     return "static_cast<SVGPaint::SVGPaintType>($value->ToInt32()->Int32Value())" if $type eq "SVGPaintType";
2293     return "toWebCoreDate($value)" if $type eq "Date";
2294
2295     if ($type eq "DOMString" or $type eq "DOMUserData") {
2296         return $value;
2297     }
2298
2299     if ($type eq "SerializedScriptValue") {
2300         $implIncludes{"SerializedScriptValue.h"} = 1;
2301         return "SerializedScriptValue::create($value)";
2302     }
2303
2304     if ($type eq "NodeFilter") {
2305         return "V8DOMWrapper::wrapNativeNodeFilter($value)";
2306     }
2307
2308     if ($type eq "SVGRect") {
2309         $implIncludes{"FloatRect.h"} = 1;
2310     }
2311
2312     if ($type eq "SVGPoint") {
2313         $implIncludes{"FloatPoint.h"} = 1;
2314     }
2315
2316     # Default, assume autogenerated type conversion routines
2317     $implIncludes{"V8Proxy.h"} = 1;
2318     if ($type eq "EventTarget") {
2319         $implIncludes{"V8Node.h"} = 1;
2320
2321         # EventTarget is not in DOM hierarchy, but all Nodes are EventTarget.
2322         return "V8Node::HasInstance($value) ? v8DOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast($value)) : 0";
2323     }
2324
2325     if ($type eq "XPathNSResolver") {
2326         return "V8DOMWrapper::getXPathNSResolver($value)";
2327     }
2328
2329     AddIncludesForType($type);
2330     # $implIncludes{"$type.h"} = 1 unless AvoidInclusionOfType($type);
2331
2332     if (IsDOMNodeType($type)) {
2333         $implIncludes{"V8${type}.h"} = 1;
2334
2335         # Perform type checks on the parameter, if it is expected Node type,
2336         # return NULL.
2337         return "V8${type}::HasInstance($value) ? v8DOMWrapperToNode<${type}>(v8::Handle<v8::Object>::Cast($value)) : 0";
2338     } else {
2339         # TODO: Temporary to avoid Window name conflict.
2340         my $classIndex = uc($type);
2341         my $implClassName = ${type};
2342
2343         $implIncludes{"V8$type.h"} = 1;
2344
2345         if (IsPodType($type)) {
2346             my $nativeType = GetNativeType($type);
2347             $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
2348
2349             return "V8SVGPODTypeUtil::toSVGPODType<${nativeType}>(V8ClassIndex::${classIndex}, $value${maybeOkParam})"
2350         }
2351
2352         $implIncludes{"V8${type}.h"} = 1;
2353
2354         # Perform type checks on the parameter, if it is expected Node type,
2355         # return NULL.
2356         return "V8${type}::HasInstance($value) ? v8DOMWrapperTo<${implClassName}>(V8ClassIndex::${classIndex}, v8::Handle<v8::Object>::Cast($value)) : 0";
2357     }
2358 }
2359
2360
2361 sub GetV8HeaderName
2362 {
2363     my $type = shift;
2364     return "V8" . GetImplementationFileName($type);
2365 }
2366
2367
2368 sub CreateCustomSignature
2369 {
2370     my $function = shift;
2371     my $count = @{$function->parameters};
2372     my $name = $function->signature->name;
2373     my $result = "  const int ${name}_argc = ${count};\n" .
2374       "  v8::Handle<v8::FunctionTemplate> ${name}_argv[${name}_argc] = { ";
2375     my $first = 1;
2376     foreach my $parameter (@{$function->parameters}) {
2377         if ($first) { $first = 0; }
2378         else { $result .= ", "; }
2379         if (IsWrapperType($parameter->type)) {
2380             if ($parameter->type eq "XPathNSResolver") {
2381                 # Special case for XPathNSResolver.  All other browsers accepts a callable,
2382                 # so, even though it's against IDL, accept objects here.
2383                 $result .= "v8::Handle<v8::FunctionTemplate>()";
2384             } else {
2385                 my $type = $parameter->type;
2386                 my $header = GetV8HeaderName($type);
2387                 $implIncludes{$header} = 1;
2388                 $result .= "V8${type}::GetRawTemplate()";
2389             }
2390         } else {
2391             $result .= "v8::Handle<v8::FunctionTemplate>()";
2392         }
2393     }
2394     $result .= " };\n";
2395     $result .= "  v8::Handle<v8::Signature> ${name}_signature = v8::Signature::New(desc, ${name}_argc, ${name}_argv);\n";
2396     return $result;
2397 }
2398
2399
2400 sub RequiresCustomSignature
2401 {
2402     my $function = shift;
2403     # No signature needed for Custom function
2404     if ($function->signature->extendedAttributes->{"Custom"} ||
2405         $function->signature->extendedAttributes->{"V8Custom"}) {
2406         return 0;
2407     }
2408
2409     foreach my $parameter (@{$function->parameters}) {
2410       if (IsWrapperType($parameter->type)) {
2411           return 1;
2412       }
2413     }
2414     return 0;
2415 }
2416
2417
2418 my %non_wrapper_types = (
2419     'float' => 1,
2420     'double' => 1,
2421     'short' => 1,
2422     'unsigned short' => 1,
2423     'long' => 1,
2424     'unsigned long' => 1,
2425     'boolean' => 1,
2426     'DOMString' => 1,
2427     'CompareHow' => 1,
2428     'SVGAngle' => 1,
2429     'SVGRect' => 1,
2430     'SVGPoint' => 1,
2431     'SVGPreserveAspectRatio' => 1,
2432     'SVGMatrix' => 1,
2433     'SVGTransform' => 1,
2434     'SVGLength' => 1,
2435     'SVGNumber' => 1,
2436     'SVGPaintType' => 1,
2437     'DOMTimeStamp' => 1,
2438     'JSObject' => 1,
2439     'EventTarget' => 1,
2440     'NodeFilter' => 1,
2441     'EventListener' => 1
2442 );
2443
2444
2445 sub IsWrapperType
2446 {
2447     my $type = $codeGenerator->StripModule(shift);
2448     return !($non_wrapper_types{$type});
2449 }
2450
2451 sub IsDOMNodeType
2452 {
2453     my $type = shift;
2454
2455     return 1 if $type eq 'Attr';
2456     return 1 if $type eq 'CDATASection';
2457     return 1 if $type eq 'Comment';
2458     return 1 if $type eq 'Document';
2459     return 1 if $type eq 'DocumentFragment';
2460     return 1 if $type eq 'DocumentType';
2461     return 1 if $type eq 'Element';
2462     return 1 if $type eq 'EntityReference';
2463     return 1 if $type eq 'HTMLCanvasElement';
2464     return 1 if $type eq 'HTMLDocument';
2465     return 1 if $type eq 'HTMLElement';
2466     return 1 if $type eq 'HTMLFormElement';
2467     return 1 if $type eq 'HTMLTableCaptionElement';
2468     return 1 if $type eq 'HTMLTableSectionElement';
2469     return 1 if $type eq 'Node';
2470     return 1 if $type eq 'ProcessingInstruction';
2471     return 1 if $type eq 'SVGElement';
2472     return 1 if $type eq 'SVGDocument';
2473     return 1 if $type eq 'SVGSVGElement';
2474     return 1 if $type eq 'SVGUseElement';
2475     return 1 if $type eq 'Text';
2476
2477     return 0;
2478 }
2479
2480
2481 sub ReturnNativeToJSValue
2482 {
2483     my $signature = shift;
2484     my $value = shift;
2485     my $indent = shift;
2486     my $type = GetTypeFromSignature($signature);
2487     my $className= "V8$type";
2488
2489     return "return v8::Date::New(static_cast<double>($value))" if $type eq "DOMTimeStamp";
2490     return "return v8Boolean($value)" if $type eq "boolean";
2491     return "return v8::Handle<v8::Value>()" if $type eq "void";     # equivalent to v8::Undefined()
2492
2493     # For all the types where we use 'int' as the representation type,
2494     # we use Integer::New which has a fast Smi conversion check.
2495     my $nativeType = GetNativeType($type);
2496     return "return v8::Integer::New($value)" if $nativeType eq "int";
2497     return "return v8::Integer::NewFromUnsigned($value)" if $nativeType eq "unsigned";
2498
2499     return "return v8::Number::New($value)" if $codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType";
2500
2501     if ($codeGenerator->IsStringType($type)) {
2502         my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"};
2503         if (defined $conv) {
2504             return "return v8StringOrNull($value)" if $conv eq "Null";
2505             return "return v8StringOrUndefined($value)" if $conv eq "Undefined";
2506             return "return v8StringOrFalse($value)" if $conv eq "False";
2507
2508             die "Unknown value for ConvertNullStringTo extended attribute";
2509         }
2510         return "return v8String($value)";
2511     }
2512
2513     # V8 specific.
2514     my $implClassName = $type;
2515     AddIncludesForType($type);
2516     # $implIncludes{GetImplementationFileName($type)} = 1 unless AvoidInclusionOfType($type);
2517
2518     # special case for non-DOM node interfaces
2519     if (IsDOMNodeType($type)) {
2520         if ($signature->extendedAttributes->{"ReturnsNew"}) {
2521             return "return V8DOMWrapper::convertNewNodeToV8Object($value)";
2522         } else {
2523             return "return V8DOMWrapper::convertNodeToV8Object($value)";
2524         }
2525     }
2526
2527     if ($type eq "EventTarget" or $type eq "SVGElementInstance") {
2528         return "return V8DOMWrapper::convertEventTargetToV8Object($value)";
2529     }
2530
2531     if ($type eq "Event") {
2532         return "return V8DOMWrapper::convertEventToV8Object($value)";
2533     }
2534
2535     if ($type eq "EventListener") {
2536         return "return V8DOMWrapper::convertEventListenerToV8Object(imp->scriptExecutionContext(), $value)";
2537     }
2538
2539     if ($type eq "SerializedScriptValue") {
2540         $implIncludes{"$type.h"} = 1;
2541         return "return v8String($value->toString())";
2542     }
2543
2544     if ($type eq "DedicatedWorkerContext" or $type eq "WorkerContext" or $type eq "SharedWorkerContext") {
2545         $implIncludes{"WorkerContextExecutionProxy.h"} = 1;
2546         return "return WorkerContextExecutionProxy::convertWorkerContextToV8Object($value)";
2547     }
2548
2549     if ($type eq "WorkerLocation" or $type eq "WorkerNavigator" or $type eq "NotificationCenter") {
2550         $implIncludes{"WorkerContextExecutionProxy.h"} = 1;
2551         my $classIndex = uc($type);
2552
2553         return "return WorkerContextExecutionProxy::convertToV8Object(V8ClassIndex::$classIndex, $value)";
2554     }
2555
2556     if ($type eq "Date") {
2557         return "return v8DateOrNull($value);";
2558     }
2559
2560     else {
2561         $implIncludes{"wtf/RefCounted.h"} = 1;
2562         $implIncludes{"wtf/RefPtr.h"} = 1;
2563         $implIncludes{"wtf/GetPtr.h"} = 1;
2564         my $classIndex = uc($type);
2565
2566         if (IsPodType($type)) {
2567             $value = GenerateSVGStaticPodTypeWrapper($type, $value);
2568         }
2569
2570         return "return V8DOMWrapper::convertToV8Object(V8ClassIndex::$classIndex, $value)";
2571     }
2572 }
2573
2574 sub GenerateSVGStaticPodTypeWrapper {
2575     my $type = shift;
2576     my $value = shift;
2577
2578     $implIncludes{"V8$type.h"}=1;
2579     $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
2580
2581     my $nativeType = GetNativeType($type);
2582     return "V8SVGStaticPODTypeWrapper<$nativeType>::create($value)";
2583 }
2584
2585 # Internal helper
2586 sub WriteData
2587 {
2588     if (defined($IMPL)) {
2589         # Write content to file.
2590         print $IMPL @implContentHeader;
2591
2592         print $IMPL @implFixedHeader;
2593
2594         foreach my $implInclude (sort keys(%implIncludes)) {
2595             my $checkType = $implInclude;
2596             $checkType =~ s/\.h//;
2597
2598             print $IMPL "#include \"$implInclude\"\n" unless $codeGenerator->IsSVGAnimatedType($checkType);
2599         }
2600
2601         print $IMPL "\n";
2602         print $IMPL @implContentDecls;
2603         print $IMPL @implContent;
2604         close($IMPL);
2605         undef($IMPL);
2606
2607         %implIncludes = ();
2608         @implFixedHeader = ();
2609         @implHeaderContent = ();
2610         @implContentDecls = ();
2611         @implContent = ();
2612     }
2613
2614     if (defined($HEADER)) {
2615         # Write content to file.
2616         print $HEADER @headerContent;
2617         close($HEADER);
2618         undef($HEADER);
2619
2620         @headerContent = ();
2621     }
2622 }
2623
2624 sub IsSVGTypeNeedingContextParameter
2625 {
2626     my $implClassName = shift;
2627
2628     if ($implClassName =~ /SVG/ and not $implClassName =~ /Element/) {
2629         return 1 unless $implClassName =~ /SVGPaint/ or $implClassName =~ /SVGColor/ or $implClassName =~ /SVGDocument/;
2630     }
2631
2632     return 0;
2633 }
2634
2635 sub GenerateSVGContextAssignment
2636 {
2637     my $srcType = shift;
2638     my $value = shift;
2639     my $indent = shift;
2640
2641     $result = GenerateSVGContextRetrieval($srcType, $indent);
2642     $result .= $indent . "V8Proxy::setSVGContext($value, context);\n";
2643
2644     return $result;
2645 }
2646
2647 sub GenerateSVGContextRetrieval
2648 {
2649     my $srcType = shift;
2650     my $indent = shift;
2651
2652     my $srcIsPodType = IsPodType($srcType);
2653
2654     my $srcObject = "imp";
2655     if ($srcIsPodType) {
2656         $srcObject = "imp_wrapper";
2657     }
2658
2659     my $contextDecl;
2660
2661     if (IsSVGTypeNeedingContextParameter($srcType)) {
2662         $contextDecl = "V8Proxy::svgContext($srcObject)";
2663     } else {
2664         $contextDecl = $srcObject;
2665     }
2666
2667     return $indent . "SVGElement* context = $contextDecl;\n";
2668 }
2669
2670 sub IsSVGListMutator
2671 {
2672     my $functionName = shift;
2673
2674     return 1 if $functionName eq "clear";
2675     return 1 if $functionName eq "initialize";
2676     return 1 if $functionName eq "insertItemBefore";
2677     return 1 if $functionName eq "replaceItem";
2678     return 1 if $functionName eq "removeItem";
2679     return 1 if $functionName eq "appendItem";
2680
2681     return 0;
2682 }
2683
2684 sub IsSVGListMethod
2685 {
2686     my $functionName = shift;
2687
2688     return 1 if $functionName eq "getFirst";
2689     return 1 if $functionName eq "getLast";
2690     return 1 if $functionName eq "getItem";
2691
2692     return IsSVGListMutator($functionName);
2693 }
2694
2695 sub IsSVGListTypeNeedingSpecialHandling
2696 {
2697     my $className = shift;
2698
2699     return 1 if $className eq "SVGPointList";
2700     return 1 if $className eq "SVGTransformList";
2701
2702     return 0;
2703 }
2704
2705 sub DebugPrint
2706 {
2707     my $output = shift;
2708
2709     print $output;
2710     print "\n";
2711 }