OSDN Git Service

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