OSDN Git Service

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