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