9553b8bff2703fc17091b9f241f7d37ebc63914b
[WebKit-https.git] / WebCore / bindings / scripts / CodeGeneratorV8.pm
1
2 # Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
3 # Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
4 # Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
5 # Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
6 # Copyright (C) 2006 Apple Computer, Inc.
7 # Copyright (C) 2007, 2008, 2009 Google Inc.
8 # Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
9 #
10 # This library is free software; you can redistribute it and/or
11 # modify it under the terms of the GNU Library General Public
12 # License as published by the Free Software Foundation; either
13 # version 2 of the License, or (at your option) any later version.
14 #
15 # This library is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 # Library General Public License for more details.
19 #
20 # You should have received a copy of the GNU Library General Public License
21 # along 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 # Workaround for V8 bindings difference where RGBColor is not a POD type.
88 sub IsPodType
89 {
90     my $type = shift;
91     return $codeGenerator->IsPodType($type);
92 }
93
94 # Params: 'domClass' struct
95 sub GenerateInterface
96 {
97     my $object = shift;
98     my $dataNode = shift;
99     my $defines = shift;
100
101     # Start actual generation
102     if ($dataNode->extendedAttributes->{"Callback"}) {
103         $object->GenerateCallbackHeader($dataNode);
104         $object->GenerateCallbackImplementation($dataNode);
105     } else {
106         $object->GenerateHeader($dataNode);
107         $object->GenerateImplementation($dataNode);
108     }
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 AvoidInclusionOfType
130 {
131     my $type = shift;
132
133     # Special case: SVGRect.h / SVGPoint.h / SVGNumber.h / SVGMatrix.h do not exist.
134     return 1 if $type eq "SVGRect" or $type eq "SVGPoint" or $type eq "SVGNumber" or $type eq "SVGMatrix";
135     return 0;
136 }
137
138 sub AddIncludesForType
139 {
140     my $type = $codeGenerator->StripModule(shift);
141
142     # When we're finished with the one-file-per-class
143     # reorganization, we won't need these special cases.
144     if (!$codeGenerator->IsPrimitiveType($type) and !AvoidInclusionOfType($type) and $type ne "Date") {
145         # default, include the same named file
146         $implIncludes{GetV8HeaderName(${type})} = 1;
147
148         if ($type =~ /SVGPathSeg/) {
149             $joinedName = $type;
150             $joinedName =~ s/Abs|Rel//;
151             $implIncludes{"${joinedName}.h"} = 1;
152         }
153     }
154
155     # additional includes (things needed to compile the bindings but not the header)
156
157     if ($type eq "CanvasRenderingContext2D") {
158         $implIncludes{"CanvasGradient.h"} = 1;
159         $implIncludes{"CanvasPattern.h"} = 1;
160         $implIncludes{"CanvasStyle.h"} = 1;
161     }
162
163     if ($type eq "CanvasGradient" or $type eq "XPathNSResolver") {
164         $implIncludes{"PlatformString.h"} = 1;
165     }
166
167     if ($type eq "CSSStyleDeclaration") {
168         $implIncludes{"CSSMutableStyleDeclaration.h"} = 1;
169     }
170
171     if ($type eq "Plugin" or $type eq "PluginArray" or $type eq "MimeTypeArray") {
172         # So we can get String -> AtomicString conversion for namedItem().
173         $implIncludes{"AtomicString.h"} = 1;
174     }
175 }
176
177 sub AddIncludesForSVGAnimatedType
178 {
179     my $type = shift;
180     $type =~ s/SVGAnimated//;
181
182     if ($type eq "Point" or $type eq "Rect") {
183         $implIncludes{"Float$type.h"} = 1;
184     } elsif ($type eq "String") {
185         $implIncludes{"PlatformString.h"} = 1;
186     }
187
188     $implIncludes{"SVGAnimatedTemplate.h"} = 1;
189 }
190
191 # If the node has a [Conditional=XXX] attribute, returns an "ENABLE(XXX)" string for use in an #if.
192 sub GenerateConditionalString
193 {
194     my $node = shift;
195     my $conditional = $node->extendedAttributes->{"Conditional"};
196     if ($conditional) {
197         if ($conditional =~ /&/) {
198             return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
199         } elsif ($conditional =~ /\|/) {
200             return "ENABLE(" . join(") || ENABLE(", split(/\|/, $conditional)) . ")";
201         } else {
202             return "ENABLE(" . $conditional . ")";
203         }
204     } else {
205         return "";
206     }
207 }
208
209 sub LinkOverloadedFunctions
210 {
211     my $dataNode = shift;
212
213     # Identifies overloaded functions and for each function adds an array with
214     # links to its respective overloads (including itself).
215     my %nameToFunctionsMap = ();
216     foreach my $function (@{$dataNode->functions}) {
217         my $name = $function->signature->name;
218         $nameToFunctionsMap{$name} = [] if !exists $nameToFunctionsMap{$name};
219         push(@{$nameToFunctionsMap{$name}}, $function);
220         $function->{overloads} = $nameToFunctionsMap{$name};
221         $function->{overloadIndex} = @{$nameToFunctionsMap{$name}};
222     }
223
224 }
225
226 sub GenerateHeader
227 {
228     my $object = shift;
229     my $dataNode = shift;
230
231     my $interfaceName = $dataNode->name;
232     my $className = "V8$interfaceName";
233     my $implClassName = $interfaceName;
234
235     # Copy contents of parent classes except the first parent or if it is
236     # EventTarget.
237     $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@allParents, 1);
238
239     my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
240
241     # - Add default header template
242     push(@headerContent, GenerateHeaderContentHeader($dataNode));
243
244     # Get correct pass/store types respecting PODType flag
245     my $podType = $dataNode->extendedAttributes->{"PODType"};
246
247     my %headerInclues = ();
248     $headerIncludes{"$podType.h"} = 1 if $podType and ($podType ne "double" and $podType ne "float" and $podType ne "RGBA32");
249     $headerIncludes{"StringHash.h"} = 1;
250     $headerIncludes{"WrapperTypeInfo.h"} = 1;
251     my $headerClassInclude = GetHeaderClassInclude($implClassName);
252     $headerIncludes{$headerClassInclude} = 1 if $headerClassInclude ne "";
253
254     foreach my $headerInclude (sort keys(%headerIncludes)) {
255         push(@headerContent, "#include \"${headerInclude}\"\n");
256     }
257
258     push(@headerContent, "#include <v8.h>\n");
259     push(@headerContent, "#include <wtf/HashMap.h>\n");
260     
261     push(@headerContent, "\nnamespace WebCore {\n");
262     if ($podType) {
263         push(@headerContent, "\ntemplate<typename PODType> class V8SVGPODTypeWrapper;\n");
264     }
265     push(@headerContent, "\nclass $className {\n");
266
267     my $nativeType = GetNativeTypeForConversions($interfaceName);
268     if ($podType) {
269         $nativeType = "V8SVGPODTypeWrapper<${nativeType} >";
270     }
271     my $forceNewObjectParameter = IsDOMNodeType($interfaceName) ? ", bool forceNewObject = false" : "";
272     push(@headerContent, <<END);
273
274 public:
275     static bool HasInstance(v8::Handle<v8::Value> value);
276     static v8::Persistent<v8::FunctionTemplate> GetRawTemplate();
277     static v8::Persistent<v8::FunctionTemplate> GetTemplate();
278     static ${nativeType}* toNative(v8::Handle<v8::Object>);
279     static v8::Handle<v8::Object> wrap(${nativeType}*${forceNewObjectParameter});
280     static void derefObject(void*);
281     static WrapperTypeInfo info;
282 END
283     if (IsActiveDomType($implClassName)) {
284         push(@headerContent, "    static ActiveDOMObject* toActiveDOMObject(v8::Handle<v8::Object>);\n");
285     }
286
287     if ($implClassName eq "DOMWindow") {
288         push(@headerContent, <<END);
289     static v8::Persistent<v8::ObjectTemplate> GetShadowObjectTemplate();
290 END
291     }
292
293     my @enabledAtRuntime;
294     foreach my $function (@{$dataNode->functions}) {
295         my $name = $function->signature->name;
296         my $attrExt = $function->signature->extendedAttributes;
297
298         if ($attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
299             push(@headerContent, <<END);
300     static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments&);
301 END
302         }
303
304         if ($attrExt->{"EnabledAtRuntime"}) {
305             push(@enabledAtRuntime, $function);
306         }
307     }
308
309     if ($dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"CanBeConstructed"}) {
310         push(@headerContent, <<END);
311     static v8::Handle<v8::Value> constructorCallback(const v8::Arguments& args);
312 END
313     }
314
315     foreach my $attribute (@{$dataNode->attributes}) {
316         my $name = $attribute->signature->name;
317         my $attrExt = $attribute->signature->extendedAttributes;
318         if ($attrExt->{"V8CustomGetter"} || $attrExt->{"CustomGetter"}
319             || $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) {
320             push(@headerContent, <<END);
321     static v8::Handle<v8::Value> ${name}AccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);
322 END
323         }
324         if ($attrExt->{"V8CustomSetter"} || $attrExt->{"CustomSetter"}
325             || $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) {
326             push(@headerContent, <<END);
327     static void ${name}AccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info);
328 END
329         }
330         if ($attrExt->{"EnabledAtRuntime"}) {
331             push(@enabledAtRuntime, $attribute);
332         }
333     }
334
335     GenerateHeaderNamedAndIndexedPropertyAccessors($dataNode);
336     GenerateHeaderCustomCall($dataNode);
337     GenerateHeaderCustomInternalFieldIndices($dataNode);
338
339     if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) {
340         push(@headerContent, <<END);
341     static bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType, v8::Local<v8::Value> data);
342     static bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType, v8::Local<v8::Value> data);
343 END
344     }
345
346     push(@headerContent, <<END);
347 };
348
349 v8::Handle<v8::Value> toV8(${nativeType}*${forceNewObjectParameter});
350 END
351     if (IsRefPtrType($implClassName)) {
352         push(@headerContent, <<END);
353 v8::Handle<v8::Value> toV8(PassRefPtr<${nativeType} >${forceNewObjectParameter});
354 END
355     }
356
357     push(@headerContent, "}\n\n");
358     push(@headerContent, "#endif // $className" . "_h\n");
359
360     my $conditionalString = GenerateConditionalString($dataNode);
361     push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;
362 }
363
364 sub GetInternalFields
365 {
366     my $dataNode = shift;
367     my $name = $dataNode->name;
368     
369     my @customInternalFields = ();
370  
371     # We can't ask whether a parent type has a given extendedAttribute, so special-case Node, AbstractWorker and WorkerContext to include all sub-types.
372     # FIXME: SVGElementInstance should probably have the EventTarget extended attribute, but doesn't.
373     if ($dataNode->extendedAttributes->{"EventTarget"} || IsNodeSubType($dataNode) || IsSubType($dataNode, "AbstractWorker") || IsSubType($dataNode, "WorkerContext")
374         || $name eq "SVGElementInstance") {
375         push(@customInternalFields, "eventListenerCacheIndex");
376     }
377
378     if (IsSubType($dataNode, "Document")) {
379         push(@customInternalFields, "implementationIndex");
380         if ($name eq "HTMLDocument") {
381             push(@customInternalFields, ("markerIndex", "shadowIndex"));
382         }
383     } elsif ($name eq "DOMWindow") {
384         push(@customInternalFields, "enteredIsolatedWorldIndex");
385     }
386     return @customInternalFields;
387 }
388
389 sub GetHeaderClassInclude
390 {
391     my $className = shift;
392     if ($className =~ /SVGPathSeg/) {
393         $className =~ s/Abs|Rel//;
394     }
395     return "" if (AvoidInclusionOfType($className));
396     return "SVGAnimatedTemplate.h" if ($codeGenerator->IsSVGAnimatedType($className));
397     return "${className}.h";
398 }
399
400 sub GenerateHeaderCustomInternalFieldIndices
401 {
402     my $dataNode = shift;
403     my @customInternalFields = GetInternalFields($dataNode);
404     my $customFieldCounter = 0;
405     foreach my $customInternalField (@customInternalFields) {
406         push(@headerContent, <<END);
407     static const int ${customInternalField} = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
408 END
409         $customFieldCounter++;
410     }
411     push(@headerContent, <<END);
412     static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
413 END
414 }
415
416 my %indexerSpecialCases = (
417     "Storage" => 1,
418     "HTMLAppletElement" => 1,
419     "HTMLDocument" => 1,
420     "HTMLEmbedElement" => 1,
421     "HTMLObjectElement" => 1
422 );
423
424 sub GenerateHeaderNamedAndIndexedPropertyAccessors
425 {
426     my $dataNode = shift;
427     my $interfaceName = $dataNode->name;
428     my $hasCustomIndexedGetter = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
429     my $hasCustomIndexedSetter = $dataNode->extendedAttributes->{"HasCustomIndexSetter"} && !$dataNode->extendedAttributes->{"HasNumericIndexGetter"};
430     my $hasCustomNamedGetter = $dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
431     my $hasCustomNamedSetter = $dataNode->extendedAttributes->{"DelegatingPutFunction"};
432     my $hasCustomDeleters = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
433     my $hasCustomEnumerator = $dataNode->extendedAttributes->{"CustomGetPropertyNames"};
434     if ($interfaceName eq "HTMLOptionsCollection") {
435         $interfaceName = "HTMLCollection";
436         $hasCustomIndexedGetter = 1;
437         $hasCustomNamedGetter = 1;
438     }
439     if ($interfaceName eq "DOMWindow") {
440         $hasCustomDeleterr = 0;
441         $hasEnumerator = 0;
442     }
443     if ($interfaceName eq "HTMLSelectElement" || $interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") {
444         $hasCustomNamedGetter = 1;
445     }
446     my $isIndexerSpecialCase = exists $indexerSpecialCases{$interfaceName};
447
448     if ($hasCustomIndexedGetter || $isIndexerSpecialCase) {
449         push(@headerContent, <<END);
450     static v8::Handle<v8::Value> indexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info);
451 END
452     }
453
454     if ($isIndexerSpecialCase || $hasCustomIndexedSetter) {
455         push(@headerContent, <<END);
456     static v8::Handle<v8::Value> indexedPropertySetter(uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info);
457 END
458     }
459     if ($hasCustomDeleters) {
460         push(@headerContent, <<END);
461     static v8::Handle<v8::Boolean> indexedPropertyDeleter(uint32_t index, const v8::AccessorInfo& info);
462 END
463     }
464     if ($hasCustomNamedGetter) {
465         push(@headerContent, <<END);
466     static v8::Handle<v8::Value> namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);
467 END
468     }
469     if ($hasCustomNamedSetter) {
470         push(@headerContent, <<END);
471     static v8::Handle<v8::Value> namedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info);
472 END
473     }
474     if ($hasCustomDeleters || $interfaceName eq "HTMLDocument") {
475         push(@headerContent, <<END);
476     static v8::Handle<v8::Boolean> namedPropertyDeleter(v8::Local<v8::String> name, const v8::AccessorInfo& info);
477 END
478     }
479     if ($hasCustomEnumerator) {
480         push(@headerContent, <<END);
481     static v8::Handle<v8::Array> namedPropertyEnumerator(const v8::AccessorInfo& info);
482 END
483     }
484 }
485
486 sub GenerateHeaderCustomCall
487 {
488     my $dataNode = shift;
489
490     if ($dataNode->extendedAttributes->{"CustomCall"}) {
491         push(@headerContent, "    static v8::Handle<v8::Value> callAsFunctionCallback(const v8::Arguments&);\n");
492     }
493     if ($dataNode->name eq "Event") {
494         push(@headerContent, "    static v8::Handle<v8::Value> dataTransferAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
495         push(@headerContent, "    static void valueAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info);\n");
496     }
497     if ($dataNode->name eq "Location") {
498         push(@headerContent, "    static v8::Handle<v8::Value> assignAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
499         push(@headerContent, "    static v8::Handle<v8::Value> reloadAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
500         push(@headerContent, "    static v8::Handle<v8::Value> replaceAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
501     }
502 }
503
504 sub GenerateSetDOMException
505 {
506     my $indent = shift;
507     my $result = "";
508
509     $result .= $indent . "if (UNLIKELY(ec)) {\n";
510     $result .= $indent . "    V8Proxy::setDOMException(ec);\n";
511     $result .= $indent . "    return v8::Handle<v8::Value>();\n";
512     $result .= $indent . "}\n";
513
514     return $result;
515 }
516
517 sub IsSubType
518 {
519     my $dataNode = shift;
520     my $parentType = shift;
521     return 1 if ($dataNode->name eq $parentType);
522     foreach (@allParents) {
523         my $parent = $codeGenerator->StripModule($_);
524         return 1 if $parent eq $parentType;
525     }
526     return 0;
527 }
528
529 sub IsNodeSubType
530 {
531     my $dataNode = shift;
532     return IsSubType($dataNode, "Node");
533 }
534
535 sub GenerateDomainSafeFunctionGetter
536 {
537     my $function = shift;
538     my $implClassName = shift;
539
540     my $className = "V8" . $implClassName;
541     my $funcName = $function->signature->name;
542
543     my $signature = "v8::Signature::New(" . $className . "::GetRawTemplate())";
544     if ($function->signature->extendedAttributes->{"V8DoNotCheckSignature"}) {
545         $signature = "v8::Local<v8::Signature>()";
546     }
547
548     my $newTemplateString = GenerateNewFunctionTemplate($function, $implClassName, $signature);
549
550     push(@implContentDecls, <<END);
551 static v8::Handle<v8::Value> ${funcName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
552 {
553     INC_STATS(\"DOM.$implClassName.$funcName._get\");
554     static v8::Persistent<v8::FunctionTemplate> privateTemplate = v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
555     v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(${className}::GetTemplate(), info.This());
556     if (holder.IsEmpty()) {
557         // can only reach here by 'object.__proto__.func', and it should passed
558         // domain security check already
559         return privateTemplate->GetFunction();
560     }
561     ${implClassName}* imp = ${className}::toNative(holder);
562     if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false)) {
563         static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
564         return sharedTemplate->GetFunction();
565     }
566     return privateTemplate->GetFunction();
567 }
568
569 END
570 }
571
572 sub GenerateConstructorGetter
573 {
574     my $implClassName = shift;
575
576     push(@implContentDecls, <<END);
577 static v8::Handle<v8::Value> ${implClassName}ConstructorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
578 {
579     INC_STATS(\"DOM.$implClassName.constructors._get\");
580     v8::Handle<v8::Value> data = info.Data();
581     ASSERT(data->IsExternal() || data->IsNumber());
582     WrapperTypeInfo* type = WrapperTypeInfo::unwrap(data);
583 END
584
585     if ($implClassName eq "DOMWindow") {
586         push(@implContentDecls, <<END);
587     // Get the proxy corresponding to the DOMWindow if possible to
588     // make sure that the constructor function is constructed in the
589     // context of the DOMWindow and not in the context of the caller.
590     return V8DOMWrapper::getConstructor(type, V8DOMWindow::toNative(info.Holder()));
591 END
592     } elsif ($implClassName eq "DedicatedWorkerContext" or $implClassName eq "WorkerContext" or $implClassName eq "SharedWorkerContext") {
593         push(@implContentDecls, <<END);
594     return V8DOMWrapper::getConstructor(type, V8WorkerContext::toNative(info.Holder()));
595 END
596     } else {
597         push(@implContentDecls, "    return v8::Handle<v8::Value>();");
598     }
599
600     push(@implContentDecls, <<END);
601 }
602
603 END
604 }
605
606 sub GenerateNormalAttrGetter
607 {
608     my $attribute = shift;
609     my $dataNode = shift;
610     my $implClassName = shift;
611     my $interfaceName = shift;
612
613     my $attrExt = $attribute->signature->extendedAttributes;
614
615     my $attrName = $attribute->signature->name;
616
617     my $attrType = GetTypeFromSignature($attribute->signature);
618     my $attrIsPodType = IsPodType($attrType);
619
620     my $nativeType = GetNativeTypeFromSignature($attribute->signature, -1);
621     my $isPodType = IsPodType($implClassName);
622     my $skipContext = 0;
623
624     if ($isPodType) {
625         $implClassName = GetNativeType($implClassName);
626         $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
627     }
628
629     # Special case: SVGZoomEvent's attributes are all read-only
630     if ($implClassName eq "SVGZoomEvent") {
631         $attrIsPodType = 0;
632         $skipContext = 1;
633     }
634
635     # Special case: SVGSVGEelement::viewport is read-only
636     if (($implClassName eq "SVGSVGElement") and ($attrName eq "viewport")) {
637         $attrIsPodType = 0;
638         $skipContext = 1;
639     }
640
641     # Special case for SVGColor
642     if (($implClassName eq "SVGColor") and ($attrName eq "rgbColor")) {
643         $attrIsPodType = 0;
644     }
645
646     my $getterStringUsesImp = $implClassName ne "float";
647
648   # Getter
649     push(@implContentDecls, <<END);
650 static v8::Handle<v8::Value> ${attrName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
651 {
652     INC_STATS(\"DOM.$implClassName.$attrName._get\");
653 END
654
655     if ($isPodType) {
656         push(@implContentDecls, <<END);
657     V8SVGPODTypeWrapper<$implClassName>* impWrapper = V8SVGPODTypeWrapper<$implClassName>::toNative(info.Holder());
658     $implClassName impInstance = *impWrapper;
659 END
660         if ($getterStringUsesImp) {
661             push(@implContentDecls, <<END);
662     $implClassName* imp = &impInstance;
663 END
664         }
665
666     } elsif ($attrExt->{"v8OnProto"} || $attrExt->{"V8DisallowShadowing"}) {
667         if ($interfaceName eq "DOMWindow") {
668             push(@implContentDecls, <<END);
669     v8::Handle<v8::Object> holder = info.Holder();
670 END
671         } else {
672             # perform lookup first
673             push(@implContentDecls, <<END);
674     v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8${interfaceName}::GetTemplate(), info.This());
675     if (holder.IsEmpty())
676         return v8::Handle<v8::Value>();
677 END
678         }
679         push(@implContentDecls, <<END);
680     ${implClassName}* imp = V8${implClassName}::toNative(holder);
681 END
682     } else {
683         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
684         if ($getterStringUsesImp && $reflect && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
685             # Generate super-compact call for regular attribute getter:
686             my $contentAttributeName = $reflect eq "1" ? $attrName : $reflect;
687             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
688             $implIncludes{"${namespace}.h"} = 1;
689             push(@implContentDecls, "    return getElementStringAttr(info, ${namespace}::${contentAttributeName}Attr);\n");
690             push(@implContentDecls, "}\n\n");
691             return;
692             # Skip the rest of the function!
693         }
694         push(@implContentDecls, <<END);
695     ${implClassName}* imp = V8${implClassName}::toNative(info.Holder());
696 END
697     }
698
699     # Generate security checks if necessary
700     if ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) {
701         push(@implContentDecls, "    if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->$attrName()))\n    return v8::Handle<v8::Value>();\n\n");
702     } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) {
703         push(@implContentDecls, "    if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->contentDocument()))\n    return v8::Handle<v8::Value>();\n\n");
704     }
705
706     my $useExceptions = 1 if @{$attribute->getterExceptions} and !($isPodType);
707     if ($useExceptions) {
708         $implIncludes{"ExceptionCode.h"} = 1;
709         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
710     }
711
712     if ($attribute->signature->extendedAttributes->{"v8referenceattr"}) {
713         $attrName = $attribute->signature->extendedAttributes->{"v8referenceattr"};
714     }
715
716     my $getterFunc = $codeGenerator->WK_lcfirst($attrName);
717
718     if ($codeGenerator->IsSVGAnimatedType($attribute->signature->type)) {
719         # Some SVGFE*Element.idl use 'operator' as attribute name; rewrite as '_operator' to avoid clashes with C/C++
720         $getterFunc = "_" . $getterFunc if ($attrName =~ /operator/);
721         $getterFunc .= "Animated";
722     }
723
724     my $returnType = GetTypeFromSignature($attribute->signature);
725
726     my $getterString;
727     if ($getterStringUsesImp) {
728         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
729         my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
730         if ($reflect || $reflectURL) {
731             my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL);
732             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
733             $implIncludes{"${namespace}.h"} = 1;
734             my $getAttributeFunctionName = $reflectURL ? "getURLAttribute" : "getAttribute";
735             $getterString = "imp->$getAttributeFunctionName(${namespace}::${contentAttributeName}Attr";
736         } else {
737             $getterString = "imp->$getterFunc(";
738         }
739         $getterString .= "ec" if $useExceptions;
740         $getterString .= ")";
741         if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) {
742             $getterString .= ".toInt()";
743         }
744     } else {
745         $getterString = "impInstance";
746     }
747
748     my $result;
749     my $wrapper;
750
751     if ($attrIsPodType) {
752         $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
753
754         my $getter = $getterString;
755         $getter =~ s/imp->//;
756         $getter =~ s/\(\)//;
757         my $setter = "set" . $codeGenerator->WK_ucfirst($getter);
758
759         my $implClassIsAnimatedType = $codeGenerator->IsSVGAnimatedType($implClassName);
760         if (not $implClassIsAnimatedType and $codeGenerator->IsPodTypeWithWriteableProperties($attrType) and not defined $attribute->signature->extendedAttributes->{"Immutable"}) {
761             if (IsPodType($implClassName)) {
762                 my $wrapper = "V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($getterString, impWrapper)";
763                 push(@implContentDecls, "    RefPtr<V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName> > wrapper = $wrapper;\n");
764             } else {
765                 my $wrapper = "V8SVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName>::create(imp, &${implClassName}::$getter, &${implClassName}::$setter)";
766                 push(@implContentDecls, "    RefPtr<V8SVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName> > wrapper = $wrapper;\n");
767             }
768         } else {
769             if ($implClassIsAnimatedType) {
770                 # We can't hash member function pointers, so instead generate
771                 # some hashing material based on the names of the methods.
772                 my $hashhex = substr(Digest::MD5::md5_hex("${implClassName}::$getter ${implClassName}::$setter)"), 0, 8);
773                 my $wrapper = "V8SVGDynamicPODTypeWrapperCache<$nativeType, $implClassName>::lookupOrCreateWrapper(imp, &${implClassName}::$getter, &${implClassName}::$setter, 0x$hashhex)";
774                 push(@implContentDecls, "    RefPtr<V8SVGPODTypeWrapper<" . $nativeType . "> > wrapper = $wrapper;\n");
775             } else {
776                 my $wrapper = GenerateSVGStaticPodTypeWrapper($returnType, $getterString);
777                 push(@implContentDecls, "    RefPtr<V8SVGStaticPODTypeWrapper<" . $nativeType . "> > wrapper = $wrapper;\n");
778             }
779         }
780
781     } else {
782         if ($attribute->signature->type eq "EventListener" && $dataNode->name eq "DOMWindow") {
783             push(@implContentDecls, "    if (!imp->document())\n");
784             push(@implContentDecls, "        return v8::Handle<v8::Value>();\n");
785         }
786
787         if ($useExceptions) {
788             push(@implContentDecls, "    $nativeType v = ");
789             push(@implContentDecls, "$getterString;\n");
790             push(@implContentDecls, GenerateSetDOMException("    "));
791             $result = "v";
792             $result .= ".release()" if (IsRefPtrType($returnType));
793         } else {
794             # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
795             $result = $getterString;
796         }
797  
798         # Special case for readonly or Replaceable attributes (with a few exceptions). This attempts to ensure that JS wrappers don't get
799         # garbage-collected prematurely when their lifetime is strongly tied to their owner. We accomplish this by inserting a reference to
800         # the newly created wrapper into an internal field of the holder object.
801         if (!IsNodeSubType($dataNode) && $attrName ne "self" && (IsWrapperType($returnType) && ($attribute->type =~ /^readonly/ || $attribute->signature->extendedAttributes->{"Replaceable"})
802             && $returnType ne "EventTarget" && $returnType ne "SerializedScriptValue" && $returnType ne "DOMWindow" 
803             && $returnType !~ /SVG/ && $returnType !~ /HTML/ && !IsDOMNodeType($returnType))) {
804             AddIncludesForType($returnType);
805             my $domMapFunction = GetDomMapFunction(0, $returnType);
806             # Check for a wrapper in the wrapper cache. If there is one, we know that a hidden reference has already
807             # been created. If we don't find a wrapper, we create both a wrapper and a hidden reference.
808             push(@implContentDecls, "    RefPtr<$returnType> result = ${getterString};\n");
809             push(@implContentDecls, "    v8::Handle<v8::Value> wrapper = result.get() ? ${domMapFunction}.get(result.get()) : v8::Handle<v8::Value>();\n");
810             push(@implContentDecls, "    if (wrapper.IsEmpty()) {\n");
811             push(@implContentDecls, "        wrapper = toV8(result.get());\n");
812             push(@implContentDecls, "        if (!wrapper.IsEmpty())\n");
813             if ($dataNode->name eq "DOMWindow") {
814                 push(@implContentDecls, "            V8DOMWrapper::setHiddenWindowReference(imp->frame(), wrapper);\n");
815             } else {
816                 push(@implContentDecls, "            V8DOMWrapper::setHiddenReference(info.Holder(), wrapper);\n");
817             }
818             push(@implContentDecls, "    }\n");
819             push(@implContentDecls, "    return wrapper;\n");
820             push(@implContentDecls, "}\n\n");
821             return;
822         }
823     }
824
825     if (IsSVGTypeNeedingContextParameter($attrType) && !$skipContext) {
826         if ($attrIsPodType) {
827             push(@implContentDecls, GenerateSVGContextAssignment($implClassName, "wrapper.get()", "    "));
828         } else {
829             push(@implContentDecls, GenerateSVGContextRetrieval($implClassName, "    "));
830             # The templating associated with passing withSVGContext()'s return value directly into toV8 can get compilers confused,
831             # so just manually set the return value to a PassRefPtr of the expected type.
832             push(@implContentDecls, "    PassRefPtr<$attrType> resultAsPassRefPtr = V8Proxy::withSVGContext($result, context);\n");
833             $result = "resultAsPassRefPtr";
834         }
835     }
836
837     if ($attrIsPodType) {
838         $implIncludes{"V8${attrType}.h"} = 1;
839         push(@implContentDecls, "    return toV8(wrapper.release().get());\n");
840     } else {
841         push(@implContentDecls, "    " . ReturnNativeToJSValue($attribute->signature, $result, "    ").";\n");
842     }
843
844     push(@implContentDecls, "}\n\n");  # end of getter
845 }
846
847 sub GenerateNormalAttrSetter
848 {
849     my $attribute = shift;
850     my $dataNode = shift;
851     my $implClassName = shift;
852     my $interfaceName = shift;
853
854     my $attrExt = $attribute->signature->extendedAttributes;
855
856     push(@implContentDecls, "static void ${attrName}AttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)\n{\n");
857     push(@implContentDecls, "    INC_STATS(\"DOM.$implClassName.$attrName._set\");\n");
858
859     my $isPodType = IsPodType($implClassName);
860
861     if ($isPodType) {
862         $implClassName = GetNativeType($implClassName);
863         $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
864         push(@implContentDecls, "    V8SVGPODTypeWrapper<$implClassName>* wrapper = V8SVGPODTypeWrapper<$implClassName>::toNative(info.Holder());\n");
865         push(@implContentDecls, "    $implClassName impInstance = *wrapper;\n");
866         push(@implContentDecls, "    $implClassName* imp = &impInstance;\n");
867
868     } elsif ($attrExt->{"v8OnProto"}) {
869       if ($interfaceName eq "DOMWindow") {
870         push(@implContentDecls, <<END);
871     v8::Handle<v8::Object> holder = info.Holder();
872 END
873       } else {
874         # perform lookup first
875         push(@implContentDecls, <<END);
876     v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8${interfaceName}::GetTemplate(), info.This());
877     if (holder.IsEmpty())
878         return;
879 END
880       }
881     push(@implContentDecls, <<END);
882     ${implClassName}* imp = V8${implClassName}::toNative(holder);
883 END
884     } else {
885         my $attrType = GetTypeFromSignature($attribute->signature);
886         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
887         my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
888         if (($reflect || $reflectURL) && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
889             # Generate super-compact call for regular attribute setter:
890             my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL);
891             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
892             $implIncludes{"${namespace}.h"} = 1;
893             push(@implContentDecls, "    setElementStringAttr(info, ${namespace}::${contentAttributeName}Attr, value);\n");
894             push(@implContentDecls, "}\n\n");
895             return;
896             # Skip the rest of the function!
897         }
898
899         push(@implContentDecls, <<END);
900     ${implClassName}* imp = V8${implClassName}::toNative(info.Holder());
901 END
902     }
903
904     my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0);
905     if ($attribute->signature->type eq "EventListener") {
906         if ($dataNode->name eq "DOMWindow") {
907             push(@implContentDecls, "    if (!imp->document())\n");
908             push(@implContentDecls, "        return;\n");
909         }
910     } else {
911         push(@implContentDecls, "    $nativeType v = " . JSValueToNative($attribute->signature, "value") . ";\n");
912     }
913
914     my $result = "";
915     if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) {
916         $result .= "WebCore::String::number(";
917     }
918     $result .= "v";
919     if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) {
920         $result .= ")";
921     }
922     my $returnType = GetTypeFromSignature($attribute->signature);
923     if (IsRefPtrType($returnType)) {
924         $result = "WTF::getPtr(" . $result . ")";
925     }
926
927     my $useExceptions = 1 if @{$attribute->setterExceptions} and !($isPodType);
928
929     if ($useExceptions) {
930         $implIncludes{"ExceptionCode.h"} = 1;
931         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
932     }
933
934     if ($implClassName eq "float") {
935         push(@implContentDecls, "    *imp = $result;\n");
936     } else {
937         my $implSetterFunctionName = $codeGenerator->WK_ucfirst($attrName);
938         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
939         my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
940         if ($reflect || $reflectURL) {
941             my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL);
942             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
943             $implIncludes{"${namespace}.h"} = 1;
944             push(@implContentDecls, "    imp->setAttribute(${namespace}::${contentAttributeName}Attr, $result");
945         } elsif ($attribute->signature->type eq "EventListener") {
946             $implIncludes{"V8AbstractEventListener.h"} = 1;
947             push(@implContentDecls, "    transferHiddenDependency(info.Holder(), imp->$attrName(), value, V8${interfaceName}::eventListenerCacheIndex);\n");
948             if ($interfaceName eq "WorkerContext" and $attribute->signature->name eq "onerror") {
949                 $implIncludes{"V8EventListenerList.h"} = 1;
950                 $implIncludes{"V8WorkerContextErrorHandler.h"} = 1;
951                 push(@implContentDecls, "    imp->set$implSetterFunctionName(V8EventListenerList::findOrCreateWrapper<V8WorkerContextErrorHandler>(value, true)");
952             } else {
953                 push(@implContentDecls, "    imp->set$implSetterFunctionName(V8DOMWrapper::getEventListener(value, true, ListenerFindOrCreate)");
954             }
955         } else {
956             push(@implContentDecls, "    imp->set$implSetterFunctionName($result");
957         }
958         push(@implContentDecls, ", ec") if $useExceptions;
959         push(@implContentDecls, ");\n");
960     }
961
962     if ($useExceptions) {
963         push(@implContentDecls, "    if (UNLIKELY(ec))\n");
964         push(@implContentDecls, "        V8Proxy::setDOMException(ec);\n");
965     }
966
967     if ($isPodType) {
968         push(@implContentDecls, "    wrapper->commitChange(*imp, V8Proxy::svgContext(wrapper));\n");
969     } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
970         $implIncludes{"SVGElement.h"} = 1;
971
972         my $currentObject = "imp";
973         if ($isPodType) {
974             $currentObject = "wrapper";
975         }
976
977         push(@implContentDecls, "    if (SVGElement* context = V8Proxy::svgContext($currentObject))\n");
978         push(@implContentDecls, "        context->svgAttributeChanged(imp->associatedAttributeName());\n");
979     }
980
981     push(@implContentDecls, "    return;\n");
982     push(@implContentDecls, "}\n\n");  # end of setter
983 }
984
985 sub GetFunctionTemplateCallbackName
986 {
987     $function = shift;
988     $interfaceName = shift;
989
990     my $name = $function->signature->name;
991
992     if ($function->signature->extendedAttributes->{"Custom"} ||
993         $function->signature->extendedAttributes->{"V8Custom"}) {
994         if ($function->signature->extendedAttributes->{"Custom"} &&
995             $function->signature->extendedAttributes->{"V8Custom"}) {
996             die "Custom and V8Custom should be mutually exclusive!"
997         }
998         return "V8${interfaceName}::${name}Callback";
999     } else {
1000         return "${interfaceName}Internal::${name}Callback";
1001     }
1002 }
1003
1004 sub GenerateNewFunctionTemplate
1005 {
1006     $function = shift;
1007     $interfaceName = shift;
1008     $signature = shift;
1009
1010     my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
1011     return "v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), $signature)";
1012 }
1013
1014 sub GenerateEventListenerCallback
1015 {
1016     my $implClassName = shift;
1017     my $functionName = shift;
1018     my $lookupType = ($functionName eq "add") ? "OrCreate" : "Only";
1019     my $passRefPtrHandling = ($functionName eq "add") ? "" : ".get()";
1020     my $hiddenDependencyAction = ($functionName eq "add") ? "create" : "remove";
1021  
1022     push(@implContentDecls, <<END);
1023 static v8::Handle<v8::Value> ${functionName}EventListenerCallback(const v8::Arguments& args)
1024 {
1025     INC_STATS("DOM.${implClassName}.${functionName}EventListener()");
1026     RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(args[1], false, ListenerFind${lookupType});
1027     if (listener) {
1028         V8${implClassName}::toNative(args.Holder())->${functionName}EventListener(v8ValueToAtomicWebCoreString(args[0]), listener${passRefPtrHandling}, args[2]->BooleanValue());
1029         ${hiddenDependencyAction}HiddenDependency(args.Holder(), args[1], V8${implClassName}::eventListenerCacheIndex);
1030     }
1031     return v8::Undefined();
1032 }
1033
1034 END
1035 }
1036
1037 sub GenerateParametersCheckExpression
1038 {
1039     my $numParameters = shift;
1040     my $function = shift;
1041
1042     my @andExpression = ();
1043     push(@andExpression, "args.Length() == $numParameters");
1044     my $parameterIndex = 0;
1045     foreach $parameter (@{$function->parameters}) {
1046         last if $parameterIndex >= $numParameters;
1047         my $value = "args[$parameterIndex]";
1048         my $type = GetTypeFromSignature($parameter);
1049
1050         # Only DOMString or wrapper types are checked.
1051         # For DOMString, Null, Undefined and any Object are accepted too, as
1052         # these are acceptable values for a DOMString argument (any Object can
1053         # be converted to a string via .toString).
1054         push(@andExpression, "(${value}->IsNull() || ${value}->IsUndefined() || ${value}->IsString() || ${value}->IsObject())") if $codeGenerator->IsStringType($type);
1055         push(@andExpression, "(${value}->IsNull() || V8${type}::HasInstance($value))") if IsWrapperType($type);
1056
1057         $parameterIndex++;
1058     }
1059     my $res = join(" && ", @andExpression);
1060     $res = "($res)" if @andExpression > 1;
1061     return $res;
1062 }
1063
1064 sub GenerateFunctionParametersCheck
1065 {
1066     my $function = shift;
1067
1068     my @orExpression = ();
1069     my $numParameters = 0;
1070     foreach $parameter (@{$function->parameters}) {
1071         if ($parameter->extendedAttributes->{"Optional"}) {
1072             push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
1073         }
1074         $numParameters++;
1075     }
1076     push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
1077     return join(" || ", @orExpression);
1078 }
1079
1080 sub GenerateOverloadedFunctionCallback
1081 {
1082     my $function = shift;
1083     my $dataNode = shift;
1084     my $implClassName = shift;
1085
1086     # Generate code for choosing the correct overload to call. Overloads are
1087     # chosen based on the total number of arguments passed and the type of
1088     # values passed in non-primitive argument slots. When more than a single
1089     # overload is applicable, precedence is given according to the order of
1090     # declaration in the IDL.
1091
1092     my $name = $function->signature->name;
1093     push(@implContentDecls, <<END);
1094 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args)
1095 {
1096     INC_STATS(\"DOM.$implClassName.$name\");
1097 END
1098
1099     foreach my $overload (@{$function->{overloads}}) {
1100         my $parametersCheck = GenerateFunctionParametersCheck($overload);
1101         push(@implContentDecls, "    if ($parametersCheck)\n");
1102         push(@implContentDecls, "        return ${name}$overload->{overloadIndex}Callback(args);\n");
1103     }
1104     push(@implContentDecls, <<END);
1105     V8Proxy::setDOMException(SYNTAX_ERR);
1106     return notHandledByInterceptor();
1107 END
1108     push(@implContentDecls, "}\n\n");
1109 }
1110
1111 sub GenerateFunctionCallback
1112 {
1113     my $function = shift;
1114     my $dataNode = shift;
1115     my $implClassName = shift;
1116
1117     my $interfaceName = $dataNode->name;
1118     my $name = $function->signature->name;
1119
1120     if (@{$function->{overloads}} > 1) {
1121         # Append a number to an overloaded method's name to make it unique:
1122         $name = $name . $function->{overloadIndex};
1123     }
1124
1125     # Adding and removing event listeners are not standard callback behavior,
1126     # but they are extremely consistent across the various classes that take event listeners,
1127     # so we can generate them as a "special case".
1128     if ($name eq "addEventListener") {
1129         GenerateEventListenerCallback($implClassName, "add");
1130         return;
1131     } elsif ($name eq "removeEventListener") {
1132         GenerateEventListenerCallback($implClassName, "remove");
1133         return;
1134     }
1135
1136     push(@implContentDecls, <<END);
1137 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args)
1138 {
1139     INC_STATS(\"DOM.$implClassName.$name\");
1140 END
1141
1142     my $numParameters = @{$function->parameters};
1143
1144     if ($function->signature->extendedAttributes->{"RequiresAllArguments"}) {
1145         push(@implContentDecls, "    if (args.Length() < $numParameters)\n    return v8::Handle<v8::Value>();\n");
1146     }
1147
1148     if (IsPodType($implClassName)) {
1149         my $nativeClassName = GetNativeType($implClassName);
1150         push(@implContentDecls, "    V8SVGPODTypeWrapper<$nativeClassName>* impWrapper = V8SVGPODTypeWrapper<$nativeClassName>::toNative(args.Holder());\n");
1151         push(@implContentDecls, "    $nativeClassName impInstance = *impWrapper;\n");
1152         push(@implContentDecls, "    $nativeClassName* imp = &impInstance;\n");
1153     } else {
1154         push(@implContentDecls, <<END);
1155     ${implClassName}* imp = V8${implClassName}::toNative(args.Holder());
1156 END
1157     }
1158
1159     # Check domain security if needed
1160     if (($dataNode->extendedAttributes->{"CheckDomainSecurity"}
1161        || $interfaceName eq "DOMWindow")
1162        && !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
1163     # We have not find real use cases yet.
1164     push(@implContentDecls, <<END);
1165     if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true))
1166         return v8::Handle<v8::Value>();
1167 END
1168     }
1169
1170     my $raisesExceptions = @{$function->raisesExceptions};
1171     if (!$raisesExceptions) {
1172         foreach my $parameter (@{$function->parameters}) {
1173             if (TypeCanFailConversion($parameter) or $parameter->extendedAttributes->{"IsIndex"}) {
1174                 $raisesExceptions = 1;
1175             }
1176         }
1177     }
1178
1179     if ($raisesExceptions) {
1180         $implIncludes{"ExceptionCode.h"} = 1;
1181         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
1182         push(@implContentDecls, "    {\n");
1183         # The brace here is needed to prevent the ensuing 'goto fail's from jumping past constructors
1184         # of objects (like Strings) declared later, causing compile errors. The block scope ends
1185         # right before the label 'fail:'.
1186     }
1187
1188     if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
1189         push(@implContentDecls, <<END);
1190     OwnPtr<ScriptCallStack> callStack(ScriptCallStack::create(args, $numParameters));
1191     if (!callStack)
1192         return v8::Undefined();
1193 END
1194         $implIncludes{"ScriptCallStack.h"} = 1;
1195     }
1196     if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) {
1197         push(@implContentDecls, <<END);
1198     if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->getSVGDocument(ec)))
1199         return v8::Handle<v8::Value>();
1200 END
1201     }
1202
1203     my $paramIndex = 0;
1204     foreach my $parameter (@{$function->parameters}) {
1205         TranslateParameter($parameter);
1206
1207         my $parameterName = $parameter->name;
1208
1209         if ($parameter->extendedAttributes->{"Optional"}) {
1210             # Generate early call if there are not enough parameters.
1211             push(@implContentDecls, "    if (args.Length() <= $paramIndex) {\n");
1212             my $functionCall = GenerateFunctionCallString($function, $paramIndex, "    " x 2, $implClassName);
1213             push(@implContentDecls, $functionCall);
1214             push(@implContentDecls, "    }\n");
1215         }
1216
1217         if ($parameter->type eq "SerializedScriptValue") {
1218             $implIncludes{"SerializedScriptValue.h"} = 1;
1219             push(@implContentDecls, "    bool ${parameterName}DidThrow = false;\n");
1220         } elsif (BasicTypeCanFailConversion($parameter)) {
1221             push(@implContentDecls, "    bool ${parameterName}Ok;\n");
1222         }
1223
1224         push(@implContentDecls, "    " . GetNativeTypeFromSignature($parameter, $paramIndex) . " $parameterName = ");
1225
1226         if ($parameter->type eq "SerializedScriptValue") {
1227             push(@implContentDecls, "SerializedScriptValue::create(args[$paramIndex], ${parameterName}DidThrow);\n");
1228             push(@implContentDecls, "    if (${parameterName}DidThrow)\n");
1229             push(@implContentDecls, "        return v8::Undefined();\n");
1230         } else {
1231             push(@implContentDecls, JSValueToNative($parameter, "args[$paramIndex]",
1232                                                     BasicTypeCanFailConversion($parameter) ?  "${parameterName}Ok" : undef) . ";\n");
1233         }
1234
1235         if (TypeCanFailConversion($parameter)) {
1236             $implIncludes{"ExceptionCode.h"} = 1;
1237             push(@implContentDecls,
1238 "    if (UNLIKELY(!$parameterName" . (BasicTypeCanFailConversion($parameter) ? "Ok" : "") . ")) {\n" .
1239 "        ec = TYPE_MISMATCH_ERR;\n" .
1240 "        goto fail;\n" .
1241 "    }\n");
1242         }
1243
1244         if ($parameter->extendedAttributes->{"IsIndex"}) {
1245             $implIncludes{"ExceptionCode.h"} = 1;
1246             push(@implContentDecls,
1247 "    if (UNLIKELY($parameterName < 0)) {\n" .
1248 "        ec = INDEX_SIZE_ERR;\n" .
1249 "        goto fail;\n" .
1250 "    }\n");
1251         }
1252
1253         $paramIndex++;
1254     }
1255
1256     # Build the function call string.
1257     my $callString = GenerateFunctionCallString($function, $paramIndex, "    ", $implClassName);
1258     push(@implContentDecls, "$callString");
1259
1260     if ($raisesExceptions) {
1261         push(@implContentDecls, "    }\n");
1262         push(@implContentDecls, "    fail:\n");
1263         push(@implContentDecls, "    V8Proxy::setDOMException(ec);\n");
1264         push(@implContentDecls, "    return v8::Handle<v8::Value>();\n");
1265     }
1266
1267     push(@implContentDecls, "}\n\n");
1268 }
1269
1270 sub GenerateBatchedAttributeData
1271 {
1272     my $dataNode = shift;
1273     my $interfaceName = $dataNode->name;
1274     my $attributes = shift;
1275
1276     foreach my $attribute (@$attributes) {
1277         my $conditionalString = GenerateConditionalString($attribute->signature);
1278         push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
1279         GenerateSingleBatchedAttribute($interfaceName, $attribute, ",", "");
1280         push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
1281     }
1282 }
1283
1284 sub GenerateSingleBatchedAttribute
1285 {
1286     my $interfaceName = shift;
1287     my $attribute = shift;
1288     my $delimiter = shift;
1289     my $indent = shift;
1290     my $attrName = $attribute->signature->name;
1291     my $attrExt = $attribute->signature->extendedAttributes;
1292
1293     # Attributes of type SerializedScriptValue are set in the
1294     # constructor and don't require callbacks.
1295     return if ($attribute->signature->type eq "SerializedScriptValue");
1296
1297     my $accessControl = "v8::DEFAULT";
1298     if ($attrExt->{"DoNotCheckDomainSecurityOnGet"}) {
1299         $accessControl = "v8::ALL_CAN_READ";
1300     } elsif ($attrExt->{"DoNotCheckDomainSecurityOnSet"}) {
1301         $accessControl = "v8::ALL_CAN_WRITE";
1302     } elsif ($attrExt->{"DoNotCheckDomainSecurity"}) {
1303         $accessControl = "v8::ALL_CAN_READ";
1304         if (!($attribute->type =~ /^readonly/) && !($attrExt->{"V8ReadOnly"})) {
1305             $accessControl .= " | v8::ALL_CAN_WRITE";
1306         }
1307     }
1308     if ($attrExt->{"V8DisallowShadowing"}) {
1309         $accessControl .= " | v8::PROHIBITS_OVERWRITING";
1310     }
1311     $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")";
1312
1313     my $customAccessor =
1314         $attrExt->{"Custom"} ||
1315         $attrExt->{"CustomSetter"} ||
1316         $attrExt->{"CustomGetter"} ||
1317         $attrExt->{"V8Custom"} ||
1318         $attrExt->{"V8CustomSetter"} ||
1319         $attrExt->{"V8CustomGetter"} ||
1320         "";
1321     if ($customAccessor eq 1) {
1322         # use the naming convension, interface + (capitalize) attr name
1323         $customAccessor = $interfaceName . "::" . $attrName;
1324     }
1325
1326     my $getter;
1327     my $setter;
1328     my $propAttr = "v8::None";
1329     my $hasCustomSetter = 0;
1330
1331     # Check attributes.
1332     if ($attrExt->{"DontEnum"}) {
1333         $propAttr .= " | v8::DontEnum";
1334     }
1335     if ($attrExt->{"V8DisallowShadowing"}) {
1336         $propAttr .= " | v8::DontDelete";
1337     }
1338
1339     my $on_proto = "0 /* on instance */";
1340     my $data = "0 /* no data */";
1341
1342     # Constructor
1343     if ($attribute->signature->type =~ /Constructor$/) {
1344         my $constructorType = $codeGenerator->StripModule($attribute->signature->type);
1345         $constructorType =~ s/Constructor$//;
1346         $implIncludes{"V8${constructorType}.h"} = 1;
1347         if ($customAccessor) {
1348             $getter = "V8${customAccessor}AccessorGetter";
1349         } else {
1350             $data = "&V8${constructorType}::info";
1351             $getter = "${interfaceName}Internal::${interfaceName}ConstructorGetter";
1352         }
1353         $setter = "0";
1354         $propAttr = "v8::ReadOnly";
1355
1356     } else {
1357         # Default Getter and Setter
1358         $getter = "${interfaceName}Internal::${attrName}AttrGetter";
1359         $setter = "${interfaceName}Internal::${attrName}AttrSetter";
1360
1361         # Custom Setter
1362         if ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
1363             $hasCustomSetter = 1;
1364             $setter = "V8${customAccessor}AccessorSetter";
1365         }
1366
1367         # Custom Getter
1368         if ($attrExt->{"CustomGetter"} || $attrExt->{"V8CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
1369             $getter = "V8${customAccessor}AccessorGetter";
1370         }
1371     }
1372
1373     # Replaceable
1374     if ($attrExt->{"Replaceable"} && !$hasCustomSetter) {
1375         $setter = "0";
1376         # Handle the special case of window.top being marked as Replaceable.
1377         # FIXME: Investigate whether we could treat window.top as replaceable
1378         # and allow shadowing without it being a security hole.
1379         if (!($interfaceName eq "DOMWindow" and $attrName eq "top")) {
1380             $propAttr .= " | v8::ReadOnly";
1381         }
1382     }
1383
1384     # Read only attributes
1385     if ($attribute->type =~ /^readonly/ || $attrExt->{"V8ReadOnly"}) {
1386         $setter = "0";
1387     }
1388
1389     # An accessor can be installed on the proto
1390     if ($attrExt->{"v8OnProto"}) {
1391         $on_proto = "1 /* on proto */";
1392     }
1393
1394     my $commentInfo = "Attribute '$attrName' (Type: '" . $attribute->type .
1395                       "' ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
1396
1397     push(@implContent, $indent . "    \/\/ $commentInfo\n");
1398     push(@implContent, $indent . "    {\"$attrName\", $getter, $setter, $data, $accessControl, static_cast<v8::PropertyAttribute>($propAttr), $on_proto}" . $delimiter . "\n");
1399 }
1400
1401 sub GenerateImplementationIndexer
1402 {
1403     my $dataNode = shift;
1404     my $indexer = shift;
1405     my $interfaceName = $dataNode->name;
1406
1407     # FIXME: Figure out what HasNumericIndexGetter is really supposed to do. Right now, it's only set on WebGL-related files.
1408     my $hasCustomSetter = $dataNode->extendedAttributes->{"HasCustomIndexSetter"} && !$dataNode->extendedAttributes->{"HasNumericIndexGetter"};
1409     my $hasGetter = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
1410
1411     # FIXME: Find a way to not have to special-case HTMLOptionsCollection.
1412     if ($interfaceName eq "HTMLOptionsCollection") {
1413         $hasGetter = 1;
1414     }
1415     # FIXME: If the parent interface of $dataNode already has
1416     # HasIndexGetter, we don't need to handle the getter here.
1417     if ($interfaceName eq "WebKitCSSTransformValue") {
1418         $hasGetter = 0;
1419     }
1420
1421     # FIXME: Investigate and remove this nastinesss. In V8, named property handling and indexer handling are apparently decoupled,
1422     # which means that object[X] where X is a number doesn't reach named property indexer. So we need to provide
1423     # simplistic, mirrored indexer handling in addition to named property handling.
1424     my $isSpecialCase = exists $indexerSpecialCases{$interfaceName};
1425     if ($isSpecialCase) {
1426         $hasGetter = 1;
1427         if ($dataNode->extendedAttributes->{"DelegatingPutFunction"}) {
1428             $hasCustomSetter = 1;
1429         }
1430     }
1431
1432     if (!$hasGetter) {
1433         return;
1434     }
1435
1436     $implIncludes{"V8Collection.h"} = 1;
1437
1438     my $indexerType = $indexer ? $indexer->type : 0;
1439
1440     # FIXME: Remove this once toV8 helper methods are implemented (see https://bugs.webkit.org/show_bug.cgi?id=32563).
1441     if ($interfaceName eq "WebKitCSSKeyframesRule") {
1442         $indexerType = "WebKitCSSKeyframeRule";
1443     }
1444
1445     if ($indexerType && !$hasCustomSetter) {
1446         if ($indexerType eq "DOMString") {
1447             my $conversion = $indexer->extendedAttributes->{"ConvertNullStringTo"};
1448             if ($conversion && $conversion eq "Null") {
1449                 push(@implContent, <<END);
1450     setCollectionStringOrNullIndexedGetter<${interfaceName}>(desc);
1451 END
1452             } else {
1453                 push(@implContent, <<END);
1454     setCollectionStringIndexedGetter<${interfaceName}>(desc);
1455 END
1456             }
1457         } else {
1458             push(@implContent, <<END);
1459     setCollectionIndexedGetter<${interfaceName}, ${indexerType}>(desc);
1460 END
1461             # Include the header for this indexer type, because setCollectionIndexedGetter() requires toV8() for this type.
1462             $implIncludes{"V8${indexerType}.h"} = 1;
1463         }
1464
1465         return;
1466     }
1467
1468     my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
1469     my $hasEnumerator = !$isSpecialCase && IsNodeSubType($dataNode);
1470     my $setOn = "Instance";
1471
1472     # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
1473     # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
1474     # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
1475     # on the object.
1476     if ($interfaceName eq "DOMWindow") {
1477         $setOn = "Prototype";
1478         $hasDeleter = 0;
1479     }
1480
1481     push(@implContent, "    desc->${setOn}Template()->SetIndexedPropertyHandler(V8${interfaceName}::indexedPropertyGetter");
1482     push(@implContent, $hasCustomSetter ? ", V8${interfaceName}::indexedPropertySetter" : ", 0");
1483     push(@implContent, ", 0"); # IndexedPropertyQuery -- not being used at the moment.
1484     push(@implContent, $hasDeleter ? ", V8${interfaceName}::indexedPropertyDeleter" : ", 0");
1485     push(@implContent, ", nodeCollectionIndexedPropertyEnumerator<${interfaceName}>") if $hasEnumerator;
1486     push(@implContent, ");\n");
1487 }
1488
1489 sub GenerateImplementationNamedPropertyGetter
1490 {
1491     my $dataNode = shift;
1492     my $namedPropertyGetter = shift;
1493     my $interfaceName = $dataNode->name;
1494     my $hasCustomGetter = $dataNode->extendedAttributes->{"HasOverridingNameGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
1495
1496     # FIXME: Remove hard-coded HTMLOptionsCollection reference by changing HTMLOptionsCollection to not inherit
1497     # from HTMLCollection per W3C spec (http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/html.html#HTMLOptionsCollection).
1498     if ($interfaceName eq "HTMLOptionsCollection") {
1499         $interfaceName = "HTMLCollection";
1500         $hasCustomGetter = 1;
1501     }
1502
1503     if ($interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") {
1504         $hasCustomGetter = 1;
1505     }
1506
1507     my $hasGetter = $dataNode->extendedAttributes->{"HasNameGetter"} || $hasCustomGetter || $namedPropertyGetter;
1508     if (!$hasGetter) {
1509         return;
1510     }
1511
1512     if ($namedPropertyGetter && $namedPropertyGetter->type ne "Node" && !$namedPropertyGetter->extendedAttributes->{"Custom"} && !$hasCustomGetter) {
1513         $implIncludes{"V8Collection.h"} = 1;
1514         my $type = $namedPropertyGetter->type;
1515         push(@implContent, <<END);
1516     setCollectionNamedGetter<${interfaceName}, ${type}>(desc);
1517 END
1518         return;
1519     }
1520
1521     my $hasSetter = $dataNode->extendedAttributes->{"DelegatingPutFunction"};
1522     # FIXME: Try to remove hard-coded HTMLDocument reference by aligning handling of document.all with JSC bindings.
1523     my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"} || $interfaceName eq "HTMLDocument";
1524     my $hasEnumerator = $dataNode->extendedAttributes->{"CustomGetPropertyNames"};
1525     my $setOn = "Instance";
1526
1527     # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
1528     # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
1529     # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
1530     # on the object.
1531     if ($interfaceName eq "DOMWindow") {
1532         $setOn = "Prototype";
1533         $hasDeleter = 0;
1534         $hasEnumerator = 0;
1535     }
1536
1537     push(@implContent, "    desc->${setOn}Template()->SetNamedPropertyHandler(V8${interfaceName}::namedPropertyGetter, ");
1538     push(@implContent, $hasSetter ? "V8${interfaceName}::namedPropertySetter, " : "0, ");
1539     push(@implContent, "0, "); # NamedPropertyQuery -- not being used at the moment.
1540     push(@implContent, $hasDeleter ? "V8${interfaceName}::namedPropertyDeleter, " : "0, ");
1541     push(@implContent, $hasEnumerator ? "V8${interfaceName}::namedPropertyEnumerator" : "0");
1542     push(@implContent, ");\n");
1543 }
1544
1545 sub GenerateImplementationCustomCall
1546 {
1547     my $dataNode = shift;
1548     my $interfaceName = $dataNode->name;
1549     my $hasCustomCall = $dataNode->extendedAttributes->{"CustomCall"};
1550
1551     # FIXME: Remove hard-coded HTMLOptionsCollection reference.
1552     if ($interfaceName eq "HTMLOptionsCollection") {
1553         $interfaceName = "HTMLCollection";
1554         $hasCustomCall = 1;
1555     }
1556
1557     if ($hasCustomCall) {
1558         push(@implContent, "    desc->InstanceTemplate()->SetCallAsFunctionHandler(V8${interfaceName}::callAsFunctionCallback);\n");
1559     }
1560 }
1561
1562 sub GenerateImplementationMasqueradesAsUndefined
1563 {
1564     my $dataNode = shift;
1565     if ($dataNode->extendedAttributes->{"MasqueradesAsUndefined"})
1566     {
1567         push(@implContent, "    desc->InstanceTemplate()->MarkAsUndetectable();\n");
1568     }
1569 }
1570
1571 sub GenerateImplementation
1572 {
1573     my $object = shift;
1574     my $dataNode = shift;
1575     my $interfaceName = $dataNode->name;
1576     my $visibleInterfaceName = GetVisibleInterfaceName($interfaceName);
1577     my $className = "V8$interfaceName";
1578     my $implClassName = $interfaceName;
1579
1580     my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
1581
1582     # - Add default header template
1583     push(@implFixedHeader, GenerateImplementationContentHeader($dataNode));
1584          
1585     $implIncludes{"RuntimeEnabledFeatures.h"} = 1;
1586     $implIncludes{"V8Proxy.h"} = 1;
1587     $implIncludes{"V8Binding.h"} = 1;
1588     $implIncludes{"V8BindingState.h"} = 1;
1589     $implIncludes{"V8DOMWrapper.h"} = 1;
1590     $implIncludes{"V8IsolatedContext.h"} = 1;
1591
1592     if ($className =~ /^V8SVGAnimated/) {
1593         AddIncludesForSVGAnimatedType($interfaceName);
1594     }
1595
1596     AddIncludesForType($interfaceName);
1597
1598     my $toActive = IsActiveDomType($interfaceName) ? "${className}::toActiveDOMObject" : "0";
1599
1600     push(@implContentDecls, "namespace WebCore {\n\n");
1601     push(@implContentDecls, "WrapperTypeInfo ${className}::info = { ${className}::GetTemplate, ${className}::derefObject, ${toActive} };\n\n");   
1602     push(@implContentDecls, "namespace ${interfaceName}Internal {\n\n");
1603     push(@implContentDecls, "template <typename T> void V8_USE(T) { }\n\n");
1604
1605     my $hasConstructors = 0;
1606     my $serializedAttribute;
1607     # Generate property accessors for attributes.
1608     for ($index = 0; $index < @{$dataNode->attributes}; $index++) {
1609         $attribute = @{$dataNode->attributes}[$index];
1610         $attrName = $attribute->signature->name;
1611         $attrType = $attribute->signature->type;
1612
1613         # Generate special code for the constructor attributes.
1614         if ($attrType =~ /Constructor$/) {
1615             if (!($attribute->signature->extendedAttributes->{"CustomGetter"} ||
1616                 $attribute->signature->extendedAttributes->{"V8CustomGetter"})) {
1617                 $hasConstructors = 1;
1618             }
1619             next;
1620         }
1621
1622         if ($attrType eq "EventListener" && $interfaceName eq "DOMWindow") {
1623             $attribute->signature->extendedAttributes->{"v8OnProto"} = 1;
1624         }
1625
1626         # Attributes of type SerializedScriptValue are set in the
1627         # constructor and don't require callbacks.
1628         if ($attrType eq "SerializedScriptValue") {
1629             die "Only one attribute of type SerializedScriptValue supported" if $serializedAttribute;
1630             $implIncludes{"SerializedScriptValue.h"} = 1;
1631             $serializedAttribute = $attribute;
1632             next;
1633         }
1634
1635         # Do not generate accessor if this is a custom attribute.  The
1636         # call will be forwarded to a hand-written accessor
1637         # implementation.
1638         if ($attribute->signature->extendedAttributes->{"Custom"} ||
1639             $attribute->signature->extendedAttributes->{"V8Custom"}) {
1640             next;
1641         }
1642
1643         # Generate the accessor.
1644         if (!($attribute->signature->extendedAttributes->{"CustomGetter"} ||
1645             $attribute->signature->extendedAttributes->{"V8CustomGetter"})) {
1646             GenerateNormalAttrGetter($attribute, $dataNode, $implClassName, $interfaceName);
1647         }
1648         if (!$attribute->signature->extendedAttributes->{"CustomSetter"} &&
1649             !$attribute->signature->extendedAttributes->{"V8CustomSetter"} &&
1650             !$attribute->signature->extendedAttributes->{"Replaceable"} &&
1651             $attribute->type !~ /^readonly/ &&
1652             !$attribute->signature->extendedAttributes->{"V8ReadOnly"}) {
1653             GenerateNormalAttrSetter($attribute, $dataNode, $implClassName, $interfaceName);
1654         }
1655     }
1656
1657     if ($hasConstructors) {
1658         GenerateConstructorGetter($implClassName);
1659     }
1660
1661     LinkOverloadedFunctions($dataNode);
1662
1663     my $indexer;
1664     my $namedPropertyGetter;
1665     # Generate methods for functions.
1666     foreach my $function (@{$dataNode->functions}) {
1667         if (!($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"V8Custom"})) {
1668             GenerateFunctionCallback($function, $dataNode, $implClassName);
1669             if ($function->{overloadIndex} > 1 && $function->{overloadIndex} == @{$function->{overloads}}) {
1670                 GenerateOverloadedFunctionCallback($function, $dataNode, $implClassName);
1671             }
1672         }
1673
1674         if ($function->signature->name eq "item") {
1675             $indexer = $function->signature;
1676         }
1677
1678         if ($function->signature->name eq "namedItem") {
1679             $namedPropertyGetter = $function->signature;
1680         }
1681
1682         # If the function does not need domain security check, we need to
1683         # generate an access getter that returns different function objects
1684         # for different calling context.
1685         if (($dataNode->extendedAttributes->{"CheckDomainSecurity"} || ($interfaceName eq "DOMWindow")) && $function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
1686             GenerateDomainSafeFunctionGetter($function, $implClassName);
1687         }
1688     }
1689
1690     # Attributes
1691     my $attributes = $dataNode->attributes;
1692
1693     # For the DOMWindow interface we partition the attributes into the
1694     # ones that disallows shadowing and the rest.
1695     my @disallowsShadowing;
1696     # Also separate out attributes that are enabled at runtime so we can process them specially.
1697     my @enabledAtRuntime;
1698     my @normal;
1699     foreach my $attribute (@$attributes) {
1700
1701         if ($interfaceName eq "DOMWindow" && $attribute->signature->extendedAttributes->{"V8DisallowShadowing"}) {
1702             push(@disallowsShadowing, $attribute);
1703         } elsif ($attribute->signature->extendedAttributes->{"EnabledAtRuntime"}) {
1704             push(@enabledAtRuntime, $attribute);
1705         } else {
1706             push(@normal, $attribute);
1707         }
1708     }
1709     $attributes = \@normal;
1710     # Put the attributes that disallow shadowing on the shadow object.
1711     if (@disallowsShadowing) {
1712         push(@implContent, "static const BatchedAttribute shadowAttrs[] = {\n");
1713         GenerateBatchedAttributeData($dataNode, \@disallowsShadowing);
1714         push(@implContent, "};\n");
1715     }
1716
1717     my $has_attributes = 0;
1718     if (@$attributes) {
1719         $has_attributes = 1;
1720         push(@implContent, "static const BatchedAttribute ${interfaceName}Attrs[] = {\n");
1721         GenerateBatchedAttributeData($dataNode, $attributes);
1722         push(@implContent, "};\n");
1723     }
1724
1725     # Setup table of standard callback functions
1726     $num_callbacks = 0;
1727     $has_callbacks = 0;
1728     foreach my $function (@{$dataNode->functions}) {
1729         # Only one table entry is needed for overloaded methods:
1730         next if $function->{overloadIndex} > 1;
1731
1732         my $attrExt = $function->signature->extendedAttributes;
1733         # Don't put any nonstandard functions into this table:
1734         if ($attrExt->{"V8OnInstance"}) {
1735             next;
1736         }
1737         if ($attrExt->{"EnabledAtRuntime"} || RequiresCustomSignature($function) || $attrExt->{"V8DoNotCheckSignature"}) {
1738             next;
1739         }
1740         if ($attrExt->{"DoNotCheckDomainSecurity"} &&
1741             ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) {
1742             next;
1743         }
1744         if ($attrExt->{"DontEnum"} || $attrExt->{"V8ReadOnly"}) {
1745             next;
1746         }
1747         if (!$has_callbacks) {
1748             $has_callbacks = 1;
1749             push(@implContent, "static const BatchedCallback ${interfaceName}Callbacks[] = {\n");
1750         }
1751         my $name = $function->signature->name;
1752         my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
1753         push(@implContent, <<END);
1754     {"$name", $callback},
1755 END
1756         $num_callbacks++;
1757     }
1758     push(@implContent, "};\n")  if $has_callbacks;
1759
1760     # Setup constants
1761     my $has_constants = 0;
1762     if (@{$dataNode->constants}) {
1763         $has_constants = 1;
1764         push(@implContent, "static const BatchedConstant ${interfaceName}Consts[] = {\n");
1765     }
1766     foreach my $constant (@{$dataNode->constants}) {
1767         my $name = $constant->name;
1768         my $value = $constant->value;
1769         # FIXME: we need the static_cast here only because of one constant, NodeFilter.idl
1770         # defines "const unsigned long SHOW_ALL = 0xFFFFFFFF".  It would be better if we
1771         # handled this here, and converted it to a -1 constant in the c++ output.
1772         push(@implContent, <<END);
1773     {"${name}", static_cast<signed int>($value)},
1774 END
1775     }
1776     if ($has_constants) {
1777         push(@implContent, "};\n");
1778     }
1779
1780     push(@implContentDecls, "} // namespace ${interfaceName}Internal\n\n");
1781
1782     # In namespace WebCore, add generated implementation for 'CanBeConstructed'.
1783     if ($dataNode->extendedAttributes->{"CanBeConstructed"} && !$dataNode->extendedAttributes->{"CustomConstructor"}) {
1784         my $v8ConstructFunction;
1785         my $callWith = $dataNode->extendedAttributes->{"CallWith"};
1786         if ($callWith and $callWith eq "ScriptExecutionContext") {
1787             $v8ConstructFunction = "constructDOMObjectWithScriptExecutionContext";
1788         } else {
1789             $v8ConstructFunction = "constructDOMObject";
1790         }
1791         push(@implContent, <<END);
1792 v8::Handle<v8::Value> ${className}::constructorCallback(const v8::Arguments& args)
1793 {
1794     INC_STATS("DOM.${interfaceName}.Contructor");
1795     return V8Proxy::${v8ConstructFunction}<$interfaceName>(args, &info);
1796 }
1797 END
1798    }
1799
1800     my $access_check = "";
1801     if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !($interfaceName eq "DOMWindow")) {
1802         $access_check = "instance->SetAccessCheckCallbacks(V8${interfaceName}::namedSecurityCheck, V8${interfaceName}::indexedSecurityCheck, v8::External::Wrap(&V8${interfaceName}::info));";
1803     }
1804
1805     # For the DOMWindow interface, generate the shadow object template
1806     # configuration method.
1807     if ($implClassName eq "DOMWindow") {
1808         push(@implContent, <<END);
1809 static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Persistent<v8::ObjectTemplate> templ)
1810 {
1811     batchConfigureAttributes(templ, v8::Handle<v8::ObjectTemplate>(), shadowAttrs, sizeof(shadowAttrs) / sizeof(*shadowAttrs));
1812
1813     // Install a security handler with V8.
1814     templ->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::External::Wrap(&V8DOMWindow::info));
1815     templ->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
1816     return templ;
1817 }
1818 END
1819     }
1820
1821     # find the super descriptor
1822     my $parentClassTemplate = "";
1823     foreach (@{$dataNode->parents}) {
1824         my $parent = $codeGenerator->StripModule($_);
1825         if ($parent eq "EventTarget") { next; }
1826         $implIncludes{"V8${parent}.h"} = 1;
1827         $parentClassTemplate = "V8" . $parent . "::GetTemplate()";
1828         last;
1829     }
1830     if (!$parentClassTemplate) {
1831         $parentClassTemplate = "v8::Persistent<v8::FunctionTemplate>()";
1832     }
1833
1834     # Generate the template configuration method
1835     push(@implContent,  <<END);
1836 static v8::Persistent<v8::FunctionTemplate> Configure${className}Template(v8::Persistent<v8::FunctionTemplate> desc)
1837 {
1838     v8::Local<v8::Signature> defaultSignature = configureTemplate(desc, \"${visibleInterfaceName}\", $parentClassTemplate, V8${interfaceName}::internalFieldCount,
1839 END
1840     # Set up our attributes if we have them
1841     if ($has_attributes) {
1842         push(@implContent, <<END);
1843         ${interfaceName}Attrs, sizeof(${interfaceName}Attrs) / sizeof(*${interfaceName}Attrs),
1844 END
1845     } else {
1846         push(@implContent, <<END);
1847         0, 0,
1848 END
1849     }
1850
1851     if ($has_callbacks) {
1852         push(@implContent, <<END);
1853         ${interfaceName}Callbacks, sizeof(${interfaceName}Callbacks) / sizeof(*${interfaceName}Callbacks));
1854 END
1855     } else {
1856         push(@implContent, <<END);
1857         0, 0);
1858 END
1859     }
1860
1861     if ($dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"CanBeConstructed"}) {
1862         push(@implContent, <<END);
1863         desc->SetCallHandler(V8${interfaceName}::constructorCallback);
1864 END
1865     }
1866
1867     if ($access_check or @enabledAtRuntime or @{$dataNode->functions} or $has_constants) {
1868         push(@implContent,  <<END);
1869     v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate();
1870     v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate();
1871 END
1872     }
1873
1874     push(@implContent,  "    $access_check\n");
1875
1876     # Setup the enable-at-runtime attrs if we have them
1877     foreach my $runtime_attr (@enabledAtRuntime) {
1878         # A function named RuntimeEnabledFeatures::{methodName}Enabled() need to be written by hand.
1879         $enable_function = "RuntimeEnabledFeatures::" . $codeGenerator->WK_lcfirst($runtime_attr->signature->name) . "Enabled";
1880         my $conditionalString = GenerateConditionalString($runtime_attr->signature);
1881         push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
1882         push(@implContent, "    if (${enable_function}()) {\n");
1883         push(@implContent, "        static const BatchedAttribute attrData =\\\n");
1884         GenerateSingleBatchedAttribute($interfaceName, $runtime_attr, ";", "    ");
1885         push(@implContent, <<END);
1886         configureAttribute(instance, proto, attrData);
1887     }
1888 END
1889         push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
1890     }
1891
1892     GenerateImplementationIndexer($dataNode, $indexer);
1893     GenerateImplementationNamedPropertyGetter($dataNode, $namedPropertyGetter);
1894     GenerateImplementationCustomCall($dataNode);
1895     GenerateImplementationMasqueradesAsUndefined($dataNode);
1896
1897     # Define our functions with Set() or SetAccessor()
1898     $total_functions = 0;
1899     foreach my $function (@{$dataNode->functions}) {
1900         # Only one accessor is needed for overloaded methods:
1901         next if $function->{overloadIndex} > 1;
1902
1903         $total_functions++;
1904         my $attrExt = $function->signature->extendedAttributes;
1905         my $name = $function->signature->name;
1906
1907         my $property_attributes = "v8::DontDelete";
1908         if ($attrExt->{"DontEnum"}) {
1909             $property_attributes .= " | v8::DontEnum";
1910         }
1911         if ($attrExt->{"V8ReadOnly"}) {
1912             $property_attributes .= " | v8::ReadOnly";
1913         }
1914
1915         my $commentInfo = "Function '$name' (ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
1916
1917         my $template = "proto";
1918         if ($attrExt->{"V8OnInstance"}) {
1919             $template = "instance";
1920         }
1921
1922         my $conditional = "";
1923         if ($attrExt->{"EnabledAtRuntime"}) {
1924             # Only call Set()/SetAccessor() if this method should be enabled
1925             $enable_function = "RuntimeEnabledFeatures::" . $codeGenerator->WK_lcfirst($function->signature->name) . "Enabled";
1926             $conditional = "if (${enable_function}())\n        ";
1927         }
1928
1929         if ($attrExt->{"DoNotCheckDomainSecurity"} &&
1930             ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) {
1931             # Mark the accessor as ReadOnly and set it on the proto object so
1932             # it can be shadowed. This is really a hack to make it work.
1933             # There are several sceneria to call into the accessor:
1934             #   1) from the same domain: "window.open":
1935             #      the accessor finds the DOM wrapper in the proto chain;
1936             #   2) from the same domain: "window.__proto__.open":
1937             #      the accessor will NOT find a DOM wrapper in the prototype chain
1938             #   3) from another domain: "window.open":
1939             #      the access find the DOM wrapper in the prototype chain
1940             #   "window.__proto__.open" from another domain will fail when
1941             #   accessing '__proto__'
1942             #
1943             # The solution is very hacky and fragile, it really needs to be replaced
1944             # by a better solution.
1945             $property_attributes .= " | v8::ReadOnly";
1946             push(@implContent, <<END);
1947
1948     // $commentInfo
1949     ${conditional}$template->SetAccessor(v8::String::New("$name"), ${interfaceName}Internal::${name}AttrGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>($property_attributes));
1950 END
1951           $num_callbacks++;
1952           next;
1953       }
1954
1955       my $signature = "defaultSignature";
1956       if ($attrExt->{"V8DoNotCheckSignature"}) {
1957           $signature = "v8::Local<v8::Signature>()";
1958       }
1959
1960       if (RequiresCustomSignature($function)) {
1961           $signature = "${name}Signature";
1962           push(@implContent, "\n    // Custom Signature '$name'\n", CreateCustomSignature($function));
1963       }
1964
1965       # Normal function call is a template
1966       my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
1967
1968       if ($property_attributes eq "v8::DontDelete") {
1969           $property_attributes = "";
1970       } else {
1971           $property_attributes = ", static_cast<v8::PropertyAttribute>($property_attributes)";
1972       }
1973
1974       if ($template eq "proto" && $conditional eq "" && $signature eq "defaultSignature" && $property_attributes eq "") {
1975           # Standard type of callback, already created in the batch, so skip it here.
1976           next;
1977       }
1978
1979       push(@implContent, <<END);
1980     ${conditional}$template->Set(v8::String::New("$name"), v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), ${signature})$property_attributes);
1981 END
1982       $num_callbacks++;
1983     }
1984
1985     die "Wrong number of callbacks generated for $interfaceName ($num_callbacks, should be $total_functions)" if $num_callbacks != $total_functions;
1986
1987     if ($has_constants) {
1988         push(@implContent, <<END);
1989     batchConfigureConstants(desc, proto, ${interfaceName}Consts, sizeof(${interfaceName}Consts) / sizeof(*${interfaceName}Consts));
1990 END
1991     }
1992
1993     # Special cases
1994     if ($interfaceName eq "DOMWindow") {
1995         push(@implContent, <<END);
1996
1997     proto->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
1998     desc->SetHiddenPrototype(true);
1999     instance->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
2000     // Set access check callbacks, but turned off initially.
2001     // When a context is detached from a frame, turn on the access check.
2002     // Turning on checks also invalidates inline caches of the object.
2003     instance->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::External::Wrap(&V8DOMWindow::info), false);
2004 END
2005     }
2006     if ($interfaceName eq "Location") {
2007         push(@implContent, <<END);
2008
2009     // For security reasons, these functions are on the instance instead
2010     // of on the prototype object to ensure that they cannot be overwritten.
2011     instance->SetAccessor(v8::String::New("reload"), V8Location::reloadAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
2012     instance->SetAccessor(v8::String::New("replace"), V8Location::replaceAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
2013     instance->SetAccessor(v8::String::New("assign"), V8Location::assignAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
2014 END
2015     }
2016
2017     my $nativeType = GetNativeTypeForConversions($interfaceName);
2018     if ($dataNode->extendedAttributes->{"PODType"}) {
2019         $nativeType = "V8SVGPODTypeWrapper<${nativeType}>";
2020     }
2021     push(@implContent, <<END);
2022
2023     // Custom toString template
2024     desc->Set(getToStringName(), getToStringTemplate());
2025     return desc;
2026 }
2027
2028 v8::Persistent<v8::FunctionTemplate> ${className}::GetRawTemplate()
2029 {
2030     static v8::Persistent<v8::FunctionTemplate> ${className}RawCache = createRawTemplate();
2031     return ${className}RawCache;
2032 }
2033
2034 v8::Persistent<v8::FunctionTemplate> ${className}::GetTemplate()\
2035 {
2036     static v8::Persistent<v8::FunctionTemplate> ${className}Cache = Configure${className}Template(GetRawTemplate());
2037     return ${className}Cache;
2038 }
2039
2040 ${nativeType}* ${className}::toNative(v8::Handle<v8::Object> object)
2041 {
2042     return reinterpret_cast<${nativeType}*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex));
2043 }
2044
2045 bool ${className}::HasInstance(v8::Handle<v8::Value> value)
2046 {
2047     return GetRawTemplate()->HasInstance(value);
2048 }
2049
2050 END
2051
2052     if (IsActiveDomType($interfaceName)) {
2053         # MessagePort is handled like an active dom object even though it doesn't inherit
2054         # from ActiveDOMObject, so don't try to cast it to ActiveDOMObject.
2055         my $returnValue = $interfaceName eq "MessagePort" ? "0" : "toNative(object)";
2056         push(@implContent, <<END);
2057 ActiveDOMObject* ${className}::toActiveDOMObject(v8::Handle<v8::Object> object)
2058 {
2059     return ${returnValue};
2060 }      
2061 END
2062     }
2063
2064     if ($implClassName eq "DOMWindow") {
2065         push(@implContent, <<END);
2066 v8::Persistent<v8::ObjectTemplate> V8DOMWindow::GetShadowObjectTemplate()
2067 {
2068     static v8::Persistent<v8::ObjectTemplate> V8DOMWindowShadowObjectCache;
2069     if (V8DOMWindowShadowObjectCache.IsEmpty()) {
2070         V8DOMWindowShadowObjectCache = v8::Persistent<v8::ObjectTemplate>::New(v8::ObjectTemplate::New());
2071         ConfigureShadowObjectTemplate(V8DOMWindowShadowObjectCache);
2072     }
2073     return V8DOMWindowShadowObjectCache;
2074 }
2075 END
2076     }
2077
2078     GenerateToV8Converters($dataNode, $interfaceName, $className, $nativeType, $serializedAttribute);
2079
2080     push(@implContent, <<END);
2081
2082 void ${className}::derefObject(void* object)
2083 {
2084 END
2085
2086     if (IsRefPtrType($interfaceName)) {
2087         push(@implContent, <<END);
2088     static_cast<${nativeType}*>(object)->deref();
2089 END
2090     }
2091
2092     push(@implContent, <<END);
2093 }
2094
2095 } // namespace WebCore
2096 END
2097
2098     my $conditionalString = GenerateConditionalString($dataNode);
2099     push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
2100     
2101     # We've already added the header for this file in implFixedHeader, so remove
2102     # it from implIncludes to ensure we don't #include it twice.
2103     delete $implIncludes{"${className}.h"};
2104 }
2105
2106 sub GenerateHeaderContentHeader
2107 {
2108     my $dataNode = shift;
2109     my $className = "V8" . $dataNode->name;
2110     my $conditionalString = GenerateConditionalString($dataNode);
2111
2112     my @headerContentHeader = split("\r", $headerTemplate);
2113
2114     push(@headerContentHeader, "\n#if ${conditionalString}\n") if $conditionalString;
2115     push(@headerContentHeader, "\n#ifndef ${className}" . "_h");
2116     push(@headerContentHeader, "\n#define ${className}" . "_h\n\n");
2117     return @headerContentHeader;
2118 }
2119
2120 sub GenerateImplementationContentHeader
2121 {
2122     my $dataNode = shift;
2123     my $className = "V8" . $dataNode->name;
2124     my $conditionalString = GenerateConditionalString($dataNode);
2125
2126     my @implContentHeader = split("\r", $headerTemplate);
2127
2128     push(@implContentHeader, "\n#include \"config.h\"\n");
2129     push(@implContentHeader, "#include \"${className}.h\"\n\n");
2130     push(@implContentHeader, "#if ${conditionalString}\n\n") if $conditionalString;
2131     return @implContentHeader;
2132 }
2133
2134 sub GenerateCallbackHeader
2135 {
2136     my $object = shift;
2137     my $dataNode = shift;
2138
2139     my $interfaceName = $dataNode->name;
2140     my $className = "V8$interfaceName";
2141
2142
2143     # - Add default header template
2144     push(@headerContent, GenerateHeaderContentHeader($dataNode));
2145
2146     if ("$interfaceName.h" lt "WorldContextHandle.h") {
2147         push(@headerContent, "#include \"$interfaceName.h\"\n");
2148         push(@headerContent, "#include \"WorldContextHandle.h\"\n");
2149     } else {
2150         push(@headerContent, "#include \"WorldContextHandle.h\"\n");
2151         push(@headerContent, "#include \"$interfaceName.h\"\n");
2152     }
2153     push(@headerContent, "#include <v8.h>\n");
2154     push(@headerContent, "#include <wtf/Forward.h>\n");
2155     
2156     push(@headerContent, "\nnamespace WebCore {\n\n");
2157     push(@headerContent, "class Frame;\n\n");
2158     push(@headerContent, "class $className : public $interfaceName {\n");
2159
2160     push(@headerContent, <<END);
2161 public:
2162     static PassRefPtr<${className}> create(v8::Local<v8::Value> value, Frame* frame)
2163     {
2164         ASSERT(value->IsObject());
2165         return adoptRef(new ${className}(value->ToObject(), frame));
2166     }
2167
2168     virtual ~${className}();
2169
2170 END
2171
2172     # Functions
2173     my $numFunctions = @{$dataNode->functions};
2174     if ($numFunctions > 0) {
2175         push(@headerContent, "    // Functions\n");
2176         foreach my $function (@{$dataNode->functions}) {
2177             my @params = @{$function->parameters};
2178             if (!$function->signature->extendedAttributes->{"Custom"} &&
2179                 !(GetNativeType($function->signature->type) eq "bool")) {
2180                     push(@headerContent, "    COMPILE_ASSERT(false)");
2181             }
2182
2183             push(@headerContent, "    virtual " . GetNativeTypeForCallbacks($function->signature->type) . " " . $function->signature->name . "(ScriptExecutionContext*");
2184             foreach my $param (@params) {
2185                 push(@headerContent, ", " . GetNativeTypeForCallbacks($param->type) . " " . $param->name);
2186             }
2187
2188             push(@headerContent, ");\n");
2189         }
2190     }
2191
2192     push(@headerContent, <<END);
2193
2194 private:
2195     ${className}(v8::Local<v8::Object>, Frame*);
2196
2197     v8::Persistent<v8::Object> m_callback;
2198     RefPtr<Frame> m_frame;
2199     WorldContextHandle m_worldContext;
2200 };
2201
2202 END
2203
2204     push(@headerContent, "}\n\n");
2205     push(@headerContent, "#endif // $className" . "_h\n\n");
2206
2207     my $conditionalString = GenerateConditionalString($dataNode);
2208     push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString;
2209 }
2210
2211 sub GenerateCallbackImplementation
2212 {
2213     my $object = shift;
2214     my $dataNode = shift;
2215     my $interfaceName = $dataNode->name;
2216     my $className = "V8$interfaceName";
2217
2218     # - Add default header template
2219     push(@implFixedHeader, GenerateImplementationContentHeader($dataNode));
2220          
2221     $implIncludes{"Frame.h"} = 1;
2222     $implIncludes{"ScriptExecutionContext.h"} = 1;
2223     $implIncludes{"V8CustomVoidCallback.h"} = 1;
2224
2225     push(@implContent, "namespace WebCore {\n\n");
2226     push(@implContent, <<END);
2227 ${className}::${className}(v8::Local<v8::Object> callback, Frame* frame)
2228     : m_callback(v8::Persistent<v8::Object>::New(callback))
2229     , m_frame(frame)
2230     , m_worldContext(UseCurrentWorld)
2231 {
2232 }
2233
2234 ${className}::~${className}()
2235 {
2236     m_callback.Dispose();
2237 }
2238
2239 END
2240
2241     # Functions
2242     my $numFunctions = @{$dataNode->functions};
2243     if ($numFunctions > 0) {
2244         push(@implContent, "// Functions\n");
2245         foreach my $function (@{$dataNode->functions}) {
2246             my @params = @{$function->parameters};
2247             if ($function->signature->extendedAttributes->{"Custom"} ||
2248                 !(GetNativeTypeForCallbacks($function->signature->type) eq "bool")) {
2249                 next;
2250             }
2251
2252             AddIncludesForType($function->signature->type);
2253             push(@implContent, "\n" . GetNativeTypeForCallbacks($function->signature->type) . " ${className}::" . $function->signature->name . "(ScriptExecutionContext* context");
2254
2255             foreach my $param (@params) {
2256                 AddIncludesForType($param->type);
2257                 push(@implContent, ", " . GetNativeTypeForCallbacks($param->type) . " " . $param->name);
2258             }
2259
2260             push(@implContent, ")\n");
2261             push(@implContent, "{\n");
2262             push(@implContent, "    v8::HandleScope handleScope;\n\n");
2263             push(@implContent, "    v8::Handle<v8::Context> v8Context = toV8Context(context, m_worldContext);\n");
2264             push(@implContent, "    if (v8Context.IsEmpty())\n");
2265             push(@implContent, "        return true;\n\n");
2266             push(@implContent, "    v8::Context::Scope scope(v8Context);\n\n");
2267             push(@implContent, "    v8::Handle<v8::Value> argv[] = {\n");
2268
2269             my @argvs = ();
2270             foreach my $param (@params) {
2271                 my $paramName = $param->name;
2272                 push(@argvs, "        toV8(${paramName})");
2273             }
2274             push(@implContent, join(",\n", @argvs));
2275
2276             push(@implContent, "\n    };\n\n");
2277             push(@implContent, "    RefPtr<Frame> protect(m_frame);\n\n");
2278             push(@implContent, "    bool callbackReturnValue = false;\n");
2279             push(@implContent, "    return !invokeCallback(m_callback, " . scalar(@params). ", argv, callbackReturnValue);\n");
2280             push(@implContent, "}\n");
2281         }
2282     }
2283
2284     push(@implContent, "\n} // namespace WebCore\n\n");
2285
2286     my $conditionalString = GenerateConditionalString($dataNode);
2287     push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
2288 }
2289
2290 sub GenerateToV8Converters
2291 {
2292     my $dataNode = shift;
2293     my $interfaceName = shift;
2294     my $className = shift;
2295     my $nativeType = shift;
2296     my $serializedAttribute = shift;
2297
2298     my $domMapFunction = GetDomMapFunction($dataNode, $interfaceName);
2299     my $forceNewObjectInput = IsDOMNodeType($interfaceName) ? ", bool forceNewObject" : "";
2300     my $forceNewObjectCall = IsDOMNodeType($interfaceName) ? ", forceNewObject" : "";
2301
2302     push(@implContent, <<END);
2303
2304 v8::Handle<v8::Object> ${className}::wrap(${nativeType}* impl${forceNewObjectInput})
2305 {
2306     v8::Handle<v8::Object> wrapper;
2307     V8Proxy* proxy = 0;
2308 END
2309
2310     if (IsNodeSubType($dataNode)) {
2311         push(@implContent, <<END);
2312     if (impl->document()) {
2313         proxy = V8Proxy::retrieve(impl->document()->frame());
2314         if (proxy && static_cast<Node*>(impl->document()) == static_cast<Node*>(impl))
2315             proxy->windowShell()->initContextIfNeeded();
2316     }
2317
2318 END
2319     }
2320
2321     if ($domMapFunction) {
2322         push(@implContent, "    if (!forceNewObject) {\n") if IsDOMNodeType($interfaceName);
2323         if (IsNodeSubType($dataNode)) {
2324             push(@implContent, "        wrapper = V8DOMWrapper::getWrapper(impl);\n");
2325         } else {
2326             push(@implContent, "        wrapper = ${domMapFunction}.get(impl);\n");
2327         }
2328         push(@implContent, <<END);
2329         if (!wrapper.IsEmpty())
2330             return wrapper;
2331 END
2332         push(@implContent, "    }\n") if IsDOMNodeType($interfaceName);
2333     }
2334     if (IsNodeSubType($dataNode)) {
2335         push(@implContent, <<END);
2336
2337     v8::Handle<v8::Context> context;
2338     if (proxy)
2339         context = proxy->context();
2340
2341     // Enter the node's context and create the wrapper in that context.
2342     if (!context.IsEmpty())
2343         context->Enter();
2344 END
2345     }
2346
2347     push(@implContent, <<END);
2348     wrapper = V8DOMWrapper::instantiateV8Object(proxy, &info, impl);
2349 END
2350     if (IsNodeSubType($dataNode)) {
2351         push(@implContent, <<END);
2352     // Exit the node's context if it was entered.
2353     if (!context.IsEmpty())
2354         context->Exit();
2355 END
2356     }
2357
2358     push(@implContent, <<END);
2359     if (wrapper.IsEmpty())
2360         return wrapper;
2361 END
2362     push(@implContent, "\n    impl->ref();\n") if IsRefPtrType($interfaceName);
2363
2364     # Eagerly deserialize attributes of type SerializedScriptValue
2365     # while we're in the right context.
2366     if ($serializedAttribute) {
2367         die "Attribute of type SerializedScriptValue expected" if $serializedAttribute->signature->type ne "SerializedScriptValue";
2368         my $attrName = $serializedAttribute->signature->name;
2369         my $attrAttr = "v8::DontDelete";
2370         if ($serializedAttribute->type =~ /^readonly/) {
2371             $attrAttr .= " | v8::ReadOnly";
2372         }
2373         $attrAttr = "static_cast<v8::PropertyAttribute>($attrAttr)";
2374         my $getterFunc = $codeGenerator->WK_lcfirst($attrName);
2375         push(@implContent, <<END);
2376     SerializedScriptValue::deserializeAndSetProperty(wrapper, "${attrName}", ${attrAttr}, impl->${getterFunc}());
2377 END
2378     }
2379
2380     if ($domMapFunction) {
2381         push(@implContent, <<END);
2382     ${domMapFunction}.set(impl, v8::Persistent<v8::Object>::New(wrapper));
2383 END
2384     }
2385
2386     push(@implContent, <<END);
2387     return wrapper;
2388 }
2389 END
2390
2391     if (IsRefPtrType($interfaceName)) {
2392         push(@implContent, <<END);
2393
2394 v8::Handle<v8::Value> toV8(PassRefPtr<${nativeType} > impl${forceNewObjectInput})
2395 {
2396     return toV8(impl.get()${forceNewObjectCall});
2397 }
2398 END
2399     }
2400
2401     if (!HasCustomToV8Implementation($dataNode, $interfaceName)) {
2402         push(@implContent, <<END);
2403
2404 v8::Handle<v8::Value> toV8(${nativeType}* impl${forceNewObjectInput})
2405 {
2406     if (!impl)
2407         return v8::Null();
2408     return ${className}::wrap(impl${forceNewObjectCall});
2409 }
2410 END
2411     }
2412 }
2413
2414 sub HasCustomToV8Implementation {
2415     # FIXME: This subroutine is lame. Probably should be an .idl attribute (CustomToV8)?
2416     $dataNode = shift;
2417     $interfaceName = shift;
2418
2419     # We generate a custom converter (but JSC doesn't) for the following:
2420     return 1 if $interfaceName eq "CSSStyleSheet";
2421     return 1 if $interfaceName eq "CanvasPixelArray";
2422     return 1 if $interfaceName eq "DOMWindow";
2423     return 1 if $interfaceName eq "Element";
2424     return 1 if $interfaceName eq "HTMLDocument";
2425     return 1 if $interfaceName eq "HTMLElement";
2426     return 1 if $interfaceName eq "Location";
2427     return 1 if $interfaceName eq "NamedNodeMap";
2428     return 1 if $interfaceName eq "SVGDocument";
2429     return 1 if $interfaceName eq "SVGElement";
2430     return 1 if $interfaceName eq "ScriptProfile";
2431     return 1 if $interfaceName eq "ScriptProfileNode";
2432     return 1 if $interfaceName eq "WorkerContext";
2433     # We don't generate a custom converter (but JSC does) for the following:
2434     return 0 if $interfaceName eq "AbstractWorker";
2435     return 0 if $interfaceName eq "CanvasRenderingContext";
2436     return 0 if $interfaceName eq "ImageData";
2437     return 0 if $interfaceName eq "SVGElementInstance";
2438
2439     # For everything else, do what JSC does.
2440     return $dataNode->extendedAttributes->{"CustomToJS"};
2441 }
2442
2443 sub GetDomMapFunction
2444 {
2445     my $dataNode = shift;
2446     my $type = shift;
2447     return "getDOMSVGElementInstanceMap()" if $type eq "SVGElementInstance";
2448     return "getDOMNodeMap()" if ($dataNode && IsNodeSubType($dataNode));
2449     # Only use getDOMSVGObjectWithContextMap() for non-node svg objects
2450     return "getDOMSVGObjectWithContextMap()" if $type =~ /SVG/;
2451     return "" if $type eq "DOMImplementation";
2452     return "getActiveDOMObjectMap()" if IsActiveDomType($type);
2453     return "getDOMObjectMap()";
2454 }
2455
2456 sub IsActiveDomType
2457 {
2458     # FIXME: Consider making this an .idl attribute.
2459     my $type = shift;
2460     return 1 if $type eq "EventSource";
2461     return 1 if $type eq "MessagePort";
2462     return 1 if $type eq "XMLHttpRequest";
2463     return 1 if $type eq "WebSocket";
2464     return 1 if $type eq "Worker";
2465     return 1 if $type eq "SharedWorker";
2466     return 0;
2467 }
2468
2469 sub GetNativeTypeForConversions
2470 {
2471     my $type = shift;
2472     return "FloatRect" if $type eq "SVGRect";
2473     return "FloatPoint" if $type eq "SVGPoint";
2474     return "AffineTransform" if $type eq "SVGMatrix";
2475     return "float" if $type eq "SVGNumber";
2476     return $type;
2477 }
2478
2479 sub GenerateFunctionCallString()
2480 {
2481     my $function = shift;
2482     my $numberOfParameters = shift;
2483     my $indent = shift;
2484     my $implClassName = shift;
2485
2486     my $name = $function->signature->name;
2487     my $isPodType = IsPodType($implClassName);
2488     my $returnType = GetTypeFromSignature($function->signature);
2489     my $returnsPodType = IsPodType($returnType);
2490     my $nativeReturnType = GetNativeType($returnType, 0);
2491     my $result = "";
2492
2493     # Special case: SVG matrix transform methods should not mutate
2494     # the matrix but return a copy
2495     my $copyFirst = 0;
2496     if ($implClassName eq "SVGMatrix" && $function->signature->type eq "SVGMatrix") {
2497         $copyFirst = 1;
2498     }
2499
2500     if ($function->signature->extendedAttributes->{"v8implname"}) {
2501         $name = $function->signature->extendedAttributes->{"v8implname"};
2502     }
2503
2504     if ($function->signature->extendedAttributes->{"ImplementationFunction"}) {
2505         $name = $function->signature->extendedAttributes->{"ImplementationFunction"};
2506     }
2507
2508     my $functionString = "imp->${name}(";
2509
2510     if ($copyFirst) {
2511         $functionString = "result.${name}(";
2512     }
2513
2514     my $returnsListItemPodType = 0;
2515     # SVG lists functions that return POD types require special handling
2516     if (IsSVGListTypeNeedingSpecialHandling($implClassName) && IsSVGListMethod($name) && $returnsPodType) {
2517         $returnsListItemPodType = 1;
2518         $result .= $indent . "SVGList<RefPtr<SVGPODListItem<$nativeReturnType> > >* listImp = imp;\n";
2519         $functionString = "listImp->${name}(";
2520     }
2521
2522     my $index = 0;
2523     my $hasScriptState = 0;
2524
2525     my $callWith = $function->signature->extendedAttributes->{"CallWith"};
2526     if ($callWith) {
2527         my $callWithArg = "COMPILE_ASSERT(false)";
2528         if ($callWith eq "DynamicFrame") {
2529             $result .= $indent . "Frame* enteredFrame = V8Proxy::retrieveFrameForEnteredContext();\n";
2530             $result .= $indent . "if (!enteredFrame)\n";
2531             $result .= $indent . "    return v8::Undefined();\n";
2532             $callWithArg = "enteredFrame";
2533         } elsif ($callWith eq "ScriptState") {
2534             $result .= $indent . "EmptyScriptState state;\n";
2535             $callWithArg = "&state";
2536             $hasScriptState = 1;
2537         }
2538         $functionString .= ", " if $index;
2539         $functionString .= $callWithArg;
2540         $index++;
2541         $numberOfParameters++
2542     }
2543
2544     foreach my $parameter (@{$function->parameters}) {
2545         if ($index eq $numberOfParameters) {
2546             last;
2547         }
2548         $functionString .= ", " if $index;
2549         my $paramName = $parameter->name;
2550         my $paramType = $parameter->type;
2551
2552         # This is a bit of a hack... we need to convert parameters to methods on SVG lists
2553         # of POD types which are items in the list to appropriate SVGList<> instances
2554         if ($returnsListItemPodType && $paramType . "List" eq $implClassName) {
2555             $paramName = "SVGPODListItem<" . GetNativeType($paramType, 1) . ">::copy($paramName)";
2556         }
2557
2558         if ($parameter->type eq "NodeFilter" || $parameter->type eq "XPathNSResolver") {
2559             $functionString .= "$paramName.get()";
2560         } else {
2561             $functionString .= $paramName;
2562         }
2563         $index++;
2564     }
2565
2566     if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
2567         $functionString .= ", " if $index;
2568         $functionString .= "callStack.get()";
2569         $index++;
2570     }
2571
2572     if ($function->signature->extendedAttributes->{"NeedsUserGestureCheck"}) {
2573         $functionString .= ", " if $index;
2574         # FIXME: We need to pass DOMWrapperWorld as a parameter.
2575         # See http://trac.webkit.org/changeset/54182
2576         $functionString .= "processingUserGesture()";
2577         $index++;
2578     }
2579
2580     if (@{$function->raisesExceptions}) {
2581         $functionString .= ", " if $index;
2582         $functionString .= "ec";
2583         $index++;
2584     }
2585     $functionString .= ")";
2586
2587     my $return = "result";
2588     my $returnIsRef = IsRefPtrType($returnType);
2589
2590     if ($returnType eq "void") {
2591         $result .= $indent . "$functionString;\n";
2592     } elsif ($copyFirst) {
2593         $result .= $indent . GetNativeType($returnType, 0) . " result = *imp;\n" . $indent . "$functionString;\n";
2594     } elsif ($returnsListItemPodType) {
2595         $result .= $indent . "RefPtr<SVGPODListItem<$nativeReturnType> > result = $functionString;\n";
2596     } elsif ($hasScriptState or @{$function->raisesExceptions} or $returnsPodType or $isPodType or IsSVGTypeNeedingContextParameter($returnType)) {
2597         $result .= $indent . $nativeReturnType . " result = $functionString;\n";
2598     } else {
2599         # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
2600         $return = $functionString;
2601         $returnIsRef = 0;
2602     }
2603
2604     if (@{$function->raisesExceptions}) {
2605         $result .= $indent . "if (UNLIKELY(ec))\n";
2606         $result .= $indent . "    goto fail;\n";
2607     }
2608
2609     if ($hasScriptState) {
2610         $result .= $indent . "if (state.hadException())\n";
2611         $result .= $indent . "    return throwError(state.exception());\n"
2612     }
2613
2614     # If the return type is a POD type, separate out the wrapper generation
2615     if ($returnsListItemPodType) {
2616         $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = ";
2617         $result .= "V8SVGPODTypeWrapperCreatorForList<" . $nativeReturnType . ">::create($return, imp->associatedAttributeName());\n";
2618         $return = "wrapper";
2619     } elsif ($returnsPodType) {
2620         $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = ";
2621         $result .= GenerateSVGStaticPodTypeWrapper($returnType, $return) . ";\n";
2622         $return = "wrapper";
2623     }
2624
2625     my $generatedSVGContextRetrieval = 0;
2626     # If the return type needs an SVG context, output it
2627     if (IsSVGTypeNeedingContextParameter($returnType)) {
2628         $result .= GenerateSVGContextAssignment($implClassName, $return . ".get()", $indent);
2629         $generatedSVGContextRetrieval = 1;
2630     }
2631
2632     if (IsSVGTypeNeedingContextParameter($implClassName) && $implClassName =~ /List$/ && IsSVGListMutator($name)) {
2633         if (!$generatedSVGContextRetrieval) {
2634             $result .= GenerateSVGContextRetrieval($implClassName, $indent);
2635             $generatedSVGContextRetrieval = 1;
2636         }
2637
2638         $result .= $indent . "context->svgAttributeChanged(imp->associatedAttributeName());\n";
2639         $implIncludes{"SVGElement.h"} = 1;
2640     }
2641
2642     # If the implementing class is a POD type, commit changes
2643     if ($isPodType) {
2644         if (!$generatedSVGContextRetrieval) {
2645             $result .= GenerateSVGContextRetrieval($implClassName, $indent);
2646             $generatedSVGContextRetrieval = 1;
2647         }
2648
2649         $result .= $indent . "impWrapper->commitChange(impInstance, context);\n";
2650     }
2651
2652     if ($returnsPodType) {
2653         $implIncludes{"V8${returnType}.h"} = 1;
2654         $result .= $indent . "return toV8(wrapper.release());\n";
2655     } else {
2656         $return .= ".release()" if ($returnIsRef);
2657         $result .= $indent . ReturnNativeToJSValue($function->signature, $return, $indent) . ";\n";
2658     }
2659
2660     return $result;
2661 }
2662
2663
2664 sub GetTypeFromSignature
2665 {
2666     my $signature = shift;
2667
2668     return $codeGenerator->StripModule($signature->type);
2669 }
2670
2671
2672 sub GetNativeTypeFromSignature
2673 {
2674     my $signature = shift;
2675     my $parameterIndex = shift;
2676
2677     my $type = GetTypeFromSignature($signature);
2678
2679     if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) {
2680         # Special-case index arguments because we need to check that they aren't < 0.
2681         return "int";
2682     }
2683
2684     $type = GetNativeType($type, $parameterIndex >= 0 ? 1 : 0);
2685
2686     if ($parameterIndex >= 0 && $type eq "V8Parameter") {
2687         my $mode = "";
2688         if ($signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"}) {
2689             $mode = "WithUndefinedOrNullCheck";
2690         } elsif ($signature->extendedAttributes->{"ConvertNullToNullString"}) {
2691             $mode = "WithNullCheck";
2692         }
2693         $type .= "<$mode>";
2694     }
2695
2696     return $type;
2697 }
2698
2699 sub IsRefPtrType
2700 {
2701     my $type = shift;
2702
2703     return 0 if $type eq "boolean";
2704     return 0 if $type eq "float";
2705     return 0 if $type eq "int";
2706     return 0 if $type eq "Date";
2707     return 0 if $type eq "DOMString";
2708     return 0 if $type eq "double";
2709     return 0 if $type eq "short";
2710     return 0 if $type eq "long";
2711     return 0 if $type eq "unsigned";
2712     return 0 if $type eq "unsigned long";
2713     return 0 if $type eq "unsigned short";
2714     return 0 if $type eq "SVGAnimatedPoints";
2715
2716     return 1;
2717 }
2718
2719 sub GetNativeType
2720 {
2721     my $type = shift;
2722     my $isParameter = shift;
2723
2724     if ($type eq "float" or $type eq "double") {
2725         return $type;
2726     }
2727
2728     return "V8Parameter" if ($type eq "DOMString" or $type eq "DOMUserData") and $isParameter;
2729     return "int" if $type eq "int";
2730     return "int" if $type eq "short" or $type eq "unsigned short";
2731     return "unsigned" if $type eq "unsigned long";
2732     return "int" if $type eq "long";
2733     return "long long" if $type eq "long long";
2734     return "unsigned long long" if $type eq "unsigned long long";
2735     return "bool" if $type eq "boolean";
2736     return "String" if $type eq "DOMString";
2737     return "Range::CompareHow" if $type eq "CompareHow";
2738     return "FloatRect" if $type eq "SVGRect";
2739     return "FloatPoint" if $type eq "SVGPoint";
2740     return "AffineTransform" if $type eq "SVGMatrix";
2741     return "SVGTransform" if $type eq "SVGTransform";
2742     return "SVGLength" if $type eq "SVGLength";
2743     return "SVGAngle" if $type eq "SVGAngle";
2744     return "float" if $type eq "SVGNumber";
2745     return "SVGPreserveAspectRatio" if $type eq "SVGPreserveAspectRatio";
2746     return "SVGPaint::SVGPaintType" if $type eq "SVGPaintType";
2747     return "DOMTimeStamp" if $type eq "DOMTimeStamp";
2748     return "unsigned" if $type eq "unsigned int";
2749     return "Node*" if $type eq "EventTarget" and $isParameter;
2750     return "double" if $type eq "Date";
2751     return "ScriptValue" if $type eq "DOMObject";
2752
2753     return "String" if $type eq "DOMUserData";  # FIXME: Temporary hack?
2754
2755     # temporary hack
2756     return "RefPtr<NodeFilter>" if $type eq "NodeFilter";
2757
2758     return "RefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValue";
2759
2760     # necessary as resolvers could be constructed on fly.
2761     return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver";
2762
2763     return "RefPtr<${type}>" if IsRefPtrType($type) and not $isParameter;
2764
2765     # Default, assume native type is a pointer with same type name as idl type
2766     return "${type}*";
2767 }
2768
2769 sub GetNativeTypeForCallbacks
2770 {
2771     my $type = shift;
2772     return "const String&" if $type eq "DOMString";
2773
2774     # Callbacks use raw pointers, so pass isParameter = 1
2775     return GetNativeType($type, 1);
2776 }
2777
2778 sub TranslateParameter
2779 {
2780     my $signature = shift;
2781
2782     # The IDL uses some pseudo-types which don't really exist.
2783     if ($signature->type eq "TimeoutHandler") {
2784       $signature->type("DOMString");
2785     }
2786 }
2787
2788 sub BasicTypeCanFailConversion
2789 {
2790     my $signature = shift;
2791     my $type = GetTypeFromSignature($signature);
2792
2793     return 1 if $type eq "SVGAngle";
2794     return 1 if $type eq "SVGLength";
2795     return 1 if $type eq "SVGMatrix";
2796     return 1 if $type eq "SVGPoint";
2797     return 1 if $type eq "SVGPreserveAspectRatio";
2798     return 1 if $type eq "SVGRect";
2799     return 1 if $type eq "SVGTransform";
2800     return 0;
2801 }
2802
2803 sub TypeCanFailConversion
2804 {
2805     my $signature = shift;
2806
2807     my $type = GetTypeFromSignature($signature);
2808
2809     $implIncludes{"ExceptionCode.h"} = 1 if $type eq "Attr";
2810     return 1 if $type eq "Attr";
2811     return 1 if $type eq "VoidCallback";
2812     return BasicTypeCanFailConversion($signature);
2813 }
2814
2815 sub JSValueToNative
2816 {
2817     my $signature = shift;
2818     my $value = shift;
2819     my $okParam = shift;
2820     my $maybeOkParam = $okParam ? ", ${okParam}" : "";
2821
2822     my $type = GetTypeFromSignature($signature);
2823
2824     return "$value" if $type eq "JSObject";
2825     return "$value->BooleanValue()" if $type eq "boolean";
2826     return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $type eq "double";
2827     return "$value->NumberValue()" if $type eq "SVGNumber";
2828
2829     return "toInt32($value${maybeOkParam})" if $type eq "unsigned long" or $type eq "unsigned short" or $type eq "long";
2830     return "toInt64($value)" if $type eq "unsigned long long" or $type eq "long long";
2831     return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "CompareHow";
2832     return "static_cast<SVGPaint::SVGPaintType>($value->ToInt32()->Int32Value())" if $type eq "SVGPaintType";
2833     return "toWebCoreDate($value)" if $type eq "Date";
2834
2835     if ($type eq "DOMString" or $type eq "DOMUserData") {
2836         return $value;
2837     }
2838
2839     die "Unexpected SerializedScriptValue" if $type eq "SerializedScriptValue";
2840
2841     if ($type eq "DOMObject") {
2842         $implIncludes{"ScriptValue.h"} = 1;
2843         return "ScriptValue($value)";
2844     }
2845
2846     if ($type eq "NodeFilter") {
2847         return "V8DOMWrapper::wrapNativeNodeFilter($value)";
2848     }
2849
2850     if ($type eq "SVGRect") {
2851         $implIncludes{"FloatRect.h"} = 1;
2852     }
2853
2854     if ($type eq "SVGPoint") {
2855         $implIncludes{"FloatPoint.h"} = 1;
2856     }
2857
2858     # Default, assume autogenerated type conversion routines
2859     if ($type eq "EventTarget") {
2860         $implIncludes{"V8Node.h"} = 1;
2861
2862         # EventTarget is not in DOM hierarchy, but all Nodes are EventTarget.
2863         return "V8Node::HasInstance($value) ? V8Node::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
2864     }
2865
2866     if ($type eq "XPathNSResolver") {
2867         return "V8DOMWrapper::getXPathNSResolver($value)";
2868     }
2869
2870     AddIncludesForType($type);
2871
2872     if (IsDOMNodeType($type)) {
2873         $implIncludes{"V8${type}.h"} = 1;
2874
2875         # Perform type checks on the parameter, if it is expected Node type,
2876         # return NULL.
2877         return "V8${type}::HasInstance($value) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
2878     } else {
2879         $implIncludes{"V8$type.h"} = 1;
2880
2881         if (IsPodType($type)) {
2882             my $nativeType = GetNativeType($type);
2883             $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
2884
2885             return "V8SVGPODTypeUtil::toSVGPODType<${nativeType}>(&V8${type}::info, $value${maybeOkParam})"
2886         }
2887
2888         $implIncludes{"V8${type}.h"} = 1;
2889
2890         # Perform type checks on the parameter, if it is expected Node type,
2891         # return NULL.
2892         return "V8${type}::HasInstance($value) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
2893     }
2894 }
2895
2896 sub GetV8HeaderName
2897 {
2898     my $type = shift;
2899     return "V8Event.h" if $type eq "DOMTimeStamp";
2900     return "EventListener.h" if $type eq "EventListener";
2901     return "EventTarget.h" if $type eq "EventTarget";
2902     return "SerializedScriptValue.h" if $type eq "SerializedScriptValue";
2903     return "ScriptValue.h" if $type eq "DOMObject";
2904     return "V8${type}.h";
2905 }
2906
2907 sub CreateCustomSignature
2908 {
2909     my $function = shift;
2910     my $count = @{$function->parameters};
2911     my $name = $function->signature->name;
2912     my $result = "    const int ${name}Argc = ${count};\n" .
2913       "    v8::Handle<v8::FunctionTemplate> ${name}Argv[${name}Argc] = { ";
2914     my $first = 1;
2915     foreach my $parameter (@{$function->parameters}) {
2916         if ($first) { $first = 0; }
2917         else { $result .= ", "; }
2918         if (IsWrapperType($parameter->type)) {
2919             if ($parameter->type eq "XPathNSResolver") {
2920                 # Special case for XPathNSResolver.  All other browsers accepts a callable,
2921                 # so, even though it's against IDL, accept objects here.
2922                 $result .= "v8::Handle<v8::FunctionTemplate>()";
2923             } else {
2924                 my $type = $parameter->type;
2925                 my $header = GetV8HeaderName($type);
2926                 $implIncludes{$header} = 1;
2927                 $result .= "V8${type}::GetRawTemplate()";
2928             }
2929         } else {
2930             $result .= "v8::Handle<v8::FunctionTemplate>()";
2931         }
2932     }
2933     $result .= " };\n";
2934     $result .= "    v8::Handle<v8::Signature> ${name}Signature = v8::Signature::New(desc, ${name}Argc, ${name}Argv);\n";
2935     return $result;
2936 }
2937
2938
2939 sub RequiresCustomSignature
2940 {
2941     my $function = shift;
2942     # No signature needed for Custom function
2943     if ($function->signature->extendedAttributes->{"Custom"} ||
2944         $function->signature->extendedAttributes->{"V8Custom"}) {
2945         return 0;
2946     }
2947     # No signature needed for overloaded function
2948     if (@{$function->{overloads}} > 1) {
2949         return 0;
2950     }
2951
2952     foreach my $parameter (@{$function->parameters}) {
2953         if ($parameter->extendedAttributes->{"Optional"}) {
2954             return 0;
2955         }
2956     }
2957
2958     foreach my $parameter (@{$function->parameters}) {
2959         if (IsWrapperType($parameter->type)) {
2960             return 1;
2961         }
2962     }
2963     return 0;
2964 }
2965
2966
2967 # FIXME: Sort this array.
2968 my %non_wrapper_types = (
2969     'float' => 1,
2970     'double' => 1,
2971     'int' => 1,
2972     'unsigned int' => 1,
2973     'short' => 1,
2974     'unsigned short' => 1,
2975     'long' => 1,
2976     'unsigned long' => 1,
2977     'boolean' => 1,
2978     'long long' => 1,
2979     'unsigned long long' => 1,
2980     'DOMString' => 1,
2981     'CompareHow' => 1,
2982     'SerializedScriptValue' => 1,
2983     'SVGAngle' => 1,
2984     'SVGRect' => 1,
2985     'SVGPoint' => 1,
2986     'SVGPreserveAspectRatio' => 1,
2987     'SVGMatrix' => 1,
2988     'SVGTransform' => 1,
2989     'SVGLength' => 1,
2990     'SVGNumber' => 1,
2991     'SVGPaintType' => 1,
2992     'DOMTimeStamp' => 1,
2993     'JSObject' => 1,
2994     'DOMObject' => 1,
2995     'EventTarget' => 1,
2996     'NodeFilter' => 1,
2997     'EventListener' => 1
2998 );
2999
3000
3001 sub IsWrapperType
3002 {
3003     my $type = $codeGenerator->StripModule(shift);
3004     return !($non_wrapper_types{$type});
3005 }
3006
3007 sub IsDOMNodeType
3008 {
3009     my $type = shift;
3010
3011     return 1 if $type eq 'Attr';
3012     return 1 if $type eq 'CDATASection';
3013     return 1 if $type eq 'Comment';
3014     return 1 if $type eq 'Document';
3015     return 1 if $type eq 'DocumentFragment';
3016     return 1 if $type eq 'DocumentType';
3017     return 1 if $type eq 'Element';
3018     return 1 if $type eq 'EntityReference';
3019     return 1 if $type eq 'HTMLCanvasElement';
3020     return 1 if $type eq 'HTMLDocument';
3021     return 1 if $type eq 'HTMLElement';
3022     return 1 if $type eq 'HTMLFormElement';
3023     return 1 if $type eq 'HTMLTableCaptionElement';
3024     return 1 if $type eq 'HTMLTableSectionElement';
3025     return 1 if $type eq 'Node';
3026     return 1 if $type eq 'ProcessingInstruction';
3027     return 1 if $type eq 'SVGElement';
3028     return 1 if $type eq 'SVGDocument';
3029     return 1 if $type eq 'SVGSVGElement';
3030     return 1 if $type eq 'SVGUseElement';
3031     return 1 if $type eq 'Text';
3032
3033     return 0;
3034 }
3035
3036
3037 sub ReturnNativeToJSValue
3038 {
3039     my $signature = shift;
3040     my $value = shift;
3041     my $indent = shift;
3042     my $type = GetTypeFromSignature($signature);
3043
3044     return "return v8::Date::New(static_cast<double>($value))" if $type eq "DOMTimeStamp";
3045     return "return v8Boolean($value)" if $type eq "boolean";
3046     return "return v8::Handle<v8::Value>()" if $type eq "void";     # equivalent to v8::Undefined()
3047
3048     # For all the types where we use 'int' as the representation type,
3049     # we use Integer::New which has a fast Smi conversion check.
3050     my $nativeType = GetNativeType($type);
3051     return "return v8::Integer::New($value)" if $nativeType eq "int";
3052     return "return v8::Integer::NewFromUnsigned($value)" if $nativeType eq "unsigned";
3053
3054     return "return v8DateOrNull($value)" if $type eq "Date";
3055     # long long and unsigned long long are not representable in ECMAScript.
3056     return "return v8::Number::New(static_cast<double>($value))" if $type eq "long long" or $type eq "unsigned long long";
3057     return "return v8::Number::New($value)" if $codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType";
3058     return "return $value.v8Value()" if $nativeType eq "ScriptValue";
3059
3060     if ($codeGenerator->IsStringType($type)) {
3061         my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"};
3062         if (defined $conv) {
3063             return "return v8StringOrNull($value)" if $conv eq "Null";
3064             return "return v8StringOrUndefined($value)" if $conv eq "Undefined";
3065             return "return v8StringOrFalse($value)" if $conv eq "False";
3066
3067             die "Unknown value for ConvertNullStringTo extended attribute";
3068         }
3069         $conv = $signature->extendedAttributes->{"ConvertScriptString"};
3070         return "v8StringOrNull(exec, $value)" if $conv;
3071         return "return v8String($value)";
3072     }
3073
3074     AddIncludesForType($type);
3075
3076     # special case for non-DOM node interfaces
3077     if (IsDOMNodeType($type)) {
3078         return "return toV8(${value}" . ($signature->extendedAttributes->{"ReturnsNew"} ? ", true)" : ")");
3079     }
3080
3081     if ($type eq "EventTarget") {
3082         return "return V8DOMWrapper::convertEventTargetToV8Object($value)";
3083     }
3084
3085     if ($type eq "EventListener") {
3086         $implIncludes{"V8AbstractEventListener.h"} = 1;
3087         return "return ${value} ? v8::Handle<v8::Value>(static_cast<V8AbstractEventListener*>(${value})->getListenerObject(imp->scriptExecutionContext())) : v8::Handle<v8::Value>(v8::Null())";
3088     }
3089
3090     if ($type eq "SerializedScriptValue") {
3091         $implIncludes{"$type.h"} = 1;
3092         return "return $value->deserialize()";
3093     }
3094
3095     $implIncludes{"wtf/RefCounted.h"} = 1;
3096     $implIncludes{"wtf/RefPtr.h"} = 1;
3097     $implIncludes{"wtf/GetPtr.h"} = 1;
3098
3099     if (IsPodType($type)) {
3100         $value = GenerateSVGStaticPodTypeWrapper($type, $value) . ".get()";
3101     }
3102
3103     return "return toV8($value)";
3104 }
3105
3106 sub GenerateSVGStaticPodTypeWrapper {
3107     my $type = shift;
3108     my $value = shift;
3109
3110     $implIncludes{"V8$type.h"}=1;
3111     $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
3112
3113     my $nativeType = GetNativeType($type);
3114     return "V8SVGStaticPODTypeWrapper<$nativeType>::create($value)";
3115 }
3116
3117 # Internal helper
3118 sub WriteData
3119 {
3120     if (defined($IMPL)) {
3121         # Write content to file.
3122         print $IMPL @implContentHeader;
3123
3124         print $IMPL @implFixedHeader;
3125
3126         foreach my $implInclude (sort keys(%implIncludes)) {
3127             my $checkType = $implInclude;
3128             $checkType =~ s/\.h//;
3129
3130             if ($implInclude =~ /wtf/) {
3131                 print $IMPL "#include \<$implInclude\>\n";
3132             } else {
3133                 print $IMPL "#include \"$implInclude\"\n" unless $codeGenerator->IsSVGAnimatedType($checkType);
3134             }
3135         }
3136
3137         print $IMPL "\n";
3138         print $IMPL @implContentDecls;
3139         print $IMPL @implContent;
3140         close($IMPL);
3141         undef($IMPL);
3142
3143         %implIncludes = ();
3144         @implFixedHeader = ();
3145         @implHeaderContent = ();
3146         @implContentDecls = ();
3147         @implContent = ();
3148     }
3149
3150     if (defined($HEADER)) {
3151         # Write content to file.
3152         print $HEADER @headerContent;
3153         close($HEADER);
3154         undef($HEADER);
3155
3156         @headerContent = ();
3157     }
3158 }
3159
3160 sub IsSVGTypeNeedingContextParameter
3161 {
3162     my $implClassName = shift;
3163
3164     if ($implClassName =~ /SVG/ and not $implClassName =~ /Element/) {
3165         return 1 unless $implClassName =~ /SVGPaint/ or $implClassName =~ /SVGColor/ or $implClassName =~ /SVGDocument/;
3166     }
3167
3168     return 0;
3169 }
3170
3171 sub GenerateSVGContextAssignment
3172 {
3173     my $srcType = shift;
3174     my $value = shift;
3175     my $indent = shift;
3176
3177     $result = GenerateSVGContextRetrieval($srcType, $indent);
3178     $result .= $indent . "V8Proxy::setSVGContext($value, context);\n";
3179
3180     return $result;
3181 }
3182
3183 sub GenerateSVGContextRetrieval
3184 {
3185     my $srcType = shift;
3186     my $indent = shift;
3187
3188     my $srcIsPodType = IsPodType($srcType);
3189
3190     my $srcObject = "imp";
3191     if ($srcIsPodType) {
3192         $srcObject = "impWrapper";
3193     }
3194
3195     my $contextDecl;
3196
3197     if (IsSVGTypeNeedingContextParameter($srcType)) {
3198         $contextDecl = "V8Proxy::svgContext($srcObject)";
3199     } else {
3200         $contextDecl = $srcObject;
3201     }
3202
3203     return $indent . "SVGElement* context = $contextDecl;\n";
3204 }
3205
3206 sub IsSVGListMutator
3207 {
3208     my $functionName = shift;
3209
3210     return 1 if $functionName eq "clear";
3211     return 1 if $functionName eq "initialize";
3212     return 1 if $functionName eq "insertItemBefore";
3213     return 1 if $functionName eq "replaceItem";
3214     return 1 if $functionName eq "removeItem";
3215     return 1 if $functionName eq "appendItem";
3216
3217     return 0;
3218 }
3219
3220 sub IsSVGListMethod
3221 {
3222     my $functionName = shift;
3223
3224     return 1 if $functionName eq "getFirst";
3225     return 1 if $functionName eq "getLast";
3226     return 1 if $functionName eq "getItem";
3227
3228     return IsSVGListMutator($functionName);
3229 }
3230
3231 sub IsSVGListTypeNeedingSpecialHandling
3232 {
3233     my $className = shift;
3234
3235     return 1 if $className eq "SVGPointList";
3236     return 1 if $className eq "SVGTransformList";
3237
3238     return 0;
3239 }
3240
3241 sub GetVisibleInterfaceName
3242 {
3243     my $interfaceName = shift;
3244
3245     return "DOMException" if $interfaceName eq "DOMCoreException";
3246     return "FormData" if $interfaceName eq "DOMFormData";
3247     return $interfaceName;
3248 }
3249
3250 sub DebugPrint
3251 {
3252     my $output = shift;
3253
3254     print $output;
3255     print "\n";
3256 }