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