OSDN Git Service

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