Not reviewed, build fix.
[WebKit.git] / WebCore / bindings / scripts / CodeGeneratorJS.pm
1 #
2 # Copyright (C) 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3 # Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
4 # Copyright (C) 2006, 2007 Samuel Weinig <sam@webkit.org>
5 # Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
6 # Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
7 # Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
8
9 # This library is free software; you can redistribute it and/or
10 # modify it under the terms of the GNU Library General Public
11 # License as published by the Free Software Foundation; either
12 # version 2 of the License, or (at your option) any later version.
13 #
14 # This library is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 # Library General Public License for more details.
18 #
19 # You should have received a copy of the GNU Library General Public License
20 # aint with this library; see the file COPYING.LIB.  If not, write to
21 # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 # Boston, MA 02110-1301, USA.
23
24 package CodeGeneratorJS;
25
26 use File::stat;
27
28 my $module = "";
29 my $outputDir = "";
30 my $writeDependencies = 0;
31
32 my @headerContentHeader = ();
33 my @headerContent = ();
34 my %headerIncludes = ();
35
36 my @implContentHeader = ();
37 my @implContent = ();
38 my %implIncludes = ();
39 my @depsContent = ();
40 my $numCachedAttributes = 0;
41 my $currentCachedAttribute = 0;
42
43 # Default .h template
44 my $headerTemplate = << "EOF";
45 /*
46     This file is part of the WebKit open source project.
47     This file has been generated by generate-bindings.pl. DO NOT MODIFY!
48
49     This library is free software; you can redistribute it and/or
50     modify it under the terms of the GNU Library General Public
51     License as published by the Free Software Foundation; either
52     version 2 of the License, or (at your option) any later version.
53
54     This library is distributed in the hope that it will be useful,
55     but WITHOUT ANY WARRANTY; without even the implied warranty of
56     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
57     Library General Public License for more details.
58
59     You should have received a copy of the GNU Library General Public License
60     along with this library; see the file COPYING.LIB.  If not, write to
61     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
62     Boston, MA 02110-1301, USA.
63 */
64 EOF
65
66 # Default constructor
67 sub new
68 {
69     my $object = shift;
70     my $reference = { };
71
72     $codeGenerator = shift;
73     $outputDir = shift;
74     shift; # $useLayerOnTop
75     shift; # $preprocessor
76     $writeDependencies = 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 sub leftShift($$) {
91     my ($value, $distance) = @_;
92     return (($value << $distance) & 0xFFFFFFFF);
93 }
94
95 # Params: 'domClass' struct
96 sub GenerateInterface
97 {
98     my $object = shift;
99     my $dataNode = shift;
100     my $defines = shift;
101
102     # Start actual generation
103     $object->GenerateHeader($dataNode);
104     $object->GenerateImplementation($dataNode);
105
106     my $name = $dataNode->name;
107
108     # Open files for writing
109     my $headerFileName = "$outputDir/JS$name.h";
110     my $implFileName = "$outputDir/JS$name.cpp";
111     my $depsFileName = "$outputDir/JS$name.dep";
112
113     # Remove old dependency file.
114     unlink($depsFileName);
115
116     open($IMPL, ">$implFileName") || die "Couldn't open file $implFileName";
117     open($HEADER, ">$headerFileName") || die "Couldn't open file $headerFileName";
118     if (@depsContent) {
119         open($DEPS, ">$depsFileName") || die "Couldn't open file $depsFileName";
120     }
121 }
122
123 # Params: 'idlDocument' struct
124 sub GenerateModule
125 {
126     my $object = shift;
127     my $dataNode = shift;
128
129     $module = $dataNode->module;
130 }
131
132 sub GetParentClassName
133 {
134     my $dataNode = shift;
135
136     return $dataNode->extendedAttributes->{"LegacyParent"} if $dataNode->extendedAttributes->{"LegacyParent"};
137     return "DOMObjectWithGlobalPointer" if (@{$dataNode->parents} eq 0);
138     return "JS" . $codeGenerator->StripModule($dataNode->parents(0));
139 }
140
141 sub GetVisibleClassName
142 {
143     my $className = shift;
144
145     return "DOMException" if $className eq "DOMCoreException";
146     return $className;
147 }
148
149 sub AvoidInclusionOfType
150 {
151     my $type = shift;
152
153     # Special case: SVGRect.h / SVGPoint.h / SVGNumber.h / SVGMatrix.h do not exist.
154     return 1 if $type eq "SVGRect" or $type eq "SVGPoint" or $type eq "SVGNumber" or $type eq "SVGMatrix";
155     return 0;
156 }
157
158 sub IndexGetterReturnsStrings
159 {
160     my $type = shift;
161
162     return 1 if $type eq "CSSStyleDeclaration" or $type eq "MediaList" or $type eq "CSSVariablesDeclaration";
163     return 0;
164 }
165
166 sub AddIncludesForType
167 {
168     my $type = $codeGenerator->StripModule(shift);
169
170     # When we're finished with the one-file-per-class
171     # reorganization, we won't need these special cases.
172     if ($codeGenerator->IsPrimitiveType($type) or AvoidInclusionOfType($type)
173         or $type eq "DOMString" or $type eq "DOMObject" or $type eq "Array") {
174     } elsif ($type =~ /SVGPathSeg/) {
175         $joinedName = $type;
176         $joinedName =~ s/Abs|Rel//;
177         $implIncludes{"${joinedName}.h"} = 1;
178     } elsif ($type eq "XPathNSResolver") {
179         $implIncludes{"JSXPathNSResolver.h"} = 1;
180         $implIncludes{"JSCustomXPathNSResolver.h"} = 1;
181     } else {
182         # default, include the same named file
183         $implIncludes{"${type}.h"} = 1;
184     }
185
186     # additional includes (things needed to compile the bindings but not the header)
187
188     if ($type eq "CanvasRenderingContext2D") {
189         $implIncludes{"CanvasGradient.h"} = 1;
190         $implIncludes{"CanvasPattern.h"} = 1;
191         $implIncludes{"CanvasStyle.h"} = 1;
192     }
193
194     if ($type eq "CanvasGradient" or $type eq "XPathNSResolver" or $type eq "MessagePort") {
195         $implIncludes{"PlatformString.h"} = 1;
196     }
197
198     if ($type eq "Document") {
199         $implIncludes{"NodeFilter.h"} = 1;
200     }
201 }
202
203 sub AddIncludesForSVGAnimatedType
204 {
205     my $type = shift;
206     $type =~ s/SVGAnimated//;
207
208     if ($type eq "Point" or $type eq "Rect") {
209         $implIncludes{"Float$type.h"} = 1;
210     } elsif ($type eq "String") {
211         $implIncludes{"PlatformString.h"} = 1;
212     }
213 }
214
215 sub AddClassForwardIfNeeded
216 {
217     my $implClassName = shift;
218
219     # SVGAnimatedLength/Number/etc. are typedefs to SVGAnimatedTemplate, so don't use class forwards for them!
220     push(@headerContent, "class $implClassName;\n\n") unless $codeGenerator->IsSVGAnimatedType($implClassName);
221 }
222
223 sub IsSVGTypeNeedingContextParameter
224 {
225     my $implClassName = shift;
226
227     return 0 unless $implClassName =~ /SVG/;
228     return 0 if $implClassName =~ /Element/;
229     my @noContextNeeded = ("SVGPaint", "SVGColor", "SVGDocument", "SVGZoomEvent");
230     foreach (@noContextNeeded) {
231         return 0 if $implClassName eq $_;
232     }
233     return 1;
234 }
235
236 sub HashValueForClassAndName
237 {
238     my $class = shift;
239     my $name = shift;
240
241     # SVG Filter enums live in WebCore namespace (platform/graphics/)
242     if ($class =~ /^SVGFE*/ or $class =~ /^SVGComponentTransferFunctionElement$/) {
243         return "WebCore::$name";
244     }
245
246     return "${class}::$name";
247 }
248
249 sub hashTableAccessor
250 {
251     my $noStaticTables = shift;
252     my $className = shift;
253     if ($noStaticTables) {
254         return "get${className}Table(exec)";
255     } else {
256         return "&${className}Table";
257     }
258 }
259
260 sub prototypeHashTableAccessor
261 {
262     my $noStaticTables = shift;
263     my $className = shift;
264     if ($noStaticTables) {
265         return "get${className}PrototypeTable(exec)";
266     } else {
267         return "&${className}PrototypeTable";
268     }
269 }
270
271 sub GenerateGetOwnPropertySlotBody
272 {
273     my ($dataNode, $interfaceName, $className, $implClassName, $hasAttributes, $inlined) = @_;
274
275     my $namespaceMaybe = ($inlined ? "JSC::" : "");
276
277     my @getOwnPropertySlotImpl = ();
278
279     if ($interfaceName eq "NamedNodeMap" or $interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") {
280         push(@getOwnPropertySlotImpl, "    ${namespaceMaybe}JSValue proto = prototype();\n");
281         push(@getOwnPropertySlotImpl, "    if (proto.isObject() && static_cast<${namespaceMaybe}JSObject*>(asObject(proto))->hasProperty(exec, propertyName))\n");
282         push(@getOwnPropertySlotImpl, "        return false;\n\n");
283     }
284
285     my $manualLookupGetterGeneration = sub {
286         my $requiresManualLookup = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasNameGetter"};
287         if ($requiresManualLookup) {
288             push(@getOwnPropertySlotImpl, "    const ${namespaceMaybe}HashEntry* entry = ${className}Table.entry(exec, propertyName);\n");
289             push(@getOwnPropertySlotImpl, "    if (entry) {\n");
290             push(@getOwnPropertySlotImpl, "        slot.setCustom(this, entry->propertyGetter());\n");
291             push(@getOwnPropertySlotImpl, "        return true;\n");
292             push(@getOwnPropertySlotImpl, "    }\n");
293         }
294     };
295
296     if (!$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
297         &$manualLookupGetterGeneration();
298     }
299
300     if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
301         push(@getOwnPropertySlotImpl, "    bool ok;\n");
302         push(@getOwnPropertySlotImpl, "    unsigned index = propertyName.toUInt32(&ok, false);\n");
303
304         # If the item function returns a string then we let the ConvertNullStringTo handle the cases
305         # where the index is out of range.
306         if (IndexGetterReturnsStrings($implClassName)) {
307             push(@getOwnPropertySlotImpl, "    if (ok) {\n");
308         } else {
309             push(@getOwnPropertySlotImpl, "    if (ok && index < static_cast<$implClassName*>(impl())->length()) {\n");
310         }
311         if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
312             push(@getOwnPropertySlotImpl, "        slot.setValue(getByIndex(exec, index));\n");
313         } else {
314             push(@getOwnPropertySlotImpl, "        slot.setCustomIndex(this, index, indexGetter);\n");
315         }
316         push(@getOwnPropertySlotImpl, "        return true;\n");
317         push(@getOwnPropertySlotImpl, "    }\n");
318     }
319
320     if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
321         push(@getOwnPropertySlotImpl, "    if (canGetItemsForName(exec, static_cast<$implClassName*>(impl()), propertyName)) {\n");
322         push(@getOwnPropertySlotImpl, "        slot.setCustom(this, nameGetter);\n");
323         push(@getOwnPropertySlotImpl, "        return true;\n");
324         push(@getOwnPropertySlotImpl, "    }\n");
325         if ($inlined) {
326             $headerIncludes{"AtomicString.h"} = 1;
327         } else {
328             $implIncludes{"AtomicString.h"} = 1;
329         }
330     }
331
332     if ($dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
333         &$manualLookupGetterGeneration();
334     }
335
336     if ($dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}) {
337         push(@getOwnPropertySlotImpl, "    if (getOwnPropertySlotDelegate(exec, propertyName, slot))\n");
338         push(@getOwnPropertySlotImpl, "        return true;\n");
339     }
340
341     if ($hasAttributes) {
342         if ($inlined) {
343             die "Cannot inline if NoStaticTables is set." if ($dataNode->extendedAttributes->{"NoStaticTables"});
344             push(@getOwnPropertySlotImpl, "    return ${namespaceMaybe}getStaticValueSlot<$className, Base>(exec, s_info.staticPropHashTable, this, propertyName, slot);\n");
345         } else {
346             push(@getOwnPropertySlotImpl, "    return ${namespaceMaybe}getStaticValueSlot<$className, Base>(exec, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n");
347         }
348     } else {
349         push(@getOwnPropertySlotImpl, "    return Base::getOwnPropertySlot(exec, propertyName, slot);\n");
350     }
351
352     return @getOwnPropertySlotImpl;
353 }
354
355 sub GenerateGetOwnPropertyDescriptorBody
356 {
357     my ($dataNode, $interfaceName, $className, $implClassName, $hasAttributes, $inlined) = @_;
358     
359     my $namespaceMaybe = ($inlined ? "JSC::" : "");
360     
361     my @getOwnPropertyDescriptorImpl = ();
362     if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) {
363         if ($interfaceName eq "DOMWindow") {
364             push(@implContent, "    if (!static_cast<$className*>(thisObject)->allowsAccessFrom(exec))\n");
365         } else {
366             push(@implContent, "    if (!allowsAccessFromFrame(exec, static_cast<$className*>(thisObject)->impl()->frame()))\n");
367         }
368         push(@implContent, "        return false;\n");
369     }
370     
371     if ($interfaceName eq "NamedNodeMap" or $interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") {
372         push(@getOwnPropertyDescriptorImpl, "    ${namespaceMaybe}JSValue proto = prototype();\n");
373         push(@getOwnPropertyDescriptorImpl, "    if (proto.isObject() && static_cast<${namespaceMaybe}JSObject*>(asObject(proto))->hasProperty(exec, propertyName))\n");
374         push(@getOwnPropertyDescriptorImpl, "        return false;\n\n");
375     }
376     
377     my $manualLookupGetterGeneration = sub {
378         my $requiresManualLookup = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasNameGetter"};
379         if ($requiresManualLookup) {
380             push(@getOwnPropertyDescriptorImpl, "    const ${namespaceMaybe}HashEntry* entry = ${className}Table.entry(exec, propertyName);\n");
381             push(@getOwnPropertyDescriptorImpl, "    if (entry) {\n");
382             push(@getOwnPropertyDescriptorImpl, "        PropertySlot slot;\n");
383             push(@getOwnPropertyDescriptorImpl, "        slot.setCustom(this, entry->propertyGetter());\n");
384             push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());\n");
385             push(@getOwnPropertyDescriptorImpl, "        return true;\n");
386             push(@getOwnPropertyDescriptorImpl, "    }\n");
387         }
388     };
389     
390     if (!$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
391         &$manualLookupGetterGeneration();
392     }
393     
394     if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
395         push(@getOwnPropertyDescriptorImpl, "    bool ok;\n");
396         push(@getOwnPropertyDescriptorImpl, "    unsigned index = propertyName.toUInt32(&ok, false);\n");
397         push(@getOwnPropertyDescriptorImpl, "    if (ok && index < static_cast<$implClassName*>(impl())->length()) {\n");
398         if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
399             # Assume that if there's a setter, the index will be writable
400             if ($dataNode->extendedAttributes->{"HasIndexSetter"} || $dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
401                 push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(getByIndex(exec, index), ${namespaceMaybe}DontDelete);\n");
402             } else {
403                 push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(getByIndex(exec, index), ${namespaceMaybe}DontDelete | ${namespaceMaybe}ReadOnly);\n");
404             }
405         } else {
406             push(@getOwnPropertyDescriptorImpl, "        ${namespaceMaybe}PropertySlot slot;\n");
407             push(@getOwnPropertyDescriptorImpl, "        slot.setCustomIndex(this, index, indexGetter);\n");
408             # Assume that if there's a setter, the index will be writable
409             if ($dataNode->extendedAttributes->{"HasIndexSetter"} || $dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
410                 push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(slot.getValue(exec, propertyName), ${namespaceMaybe}DontDelete);\n");
411             } else {
412                 push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(slot.getValue(exec, propertyName), ${namespaceMaybe}DontDelete | ${namespaceMaybe}ReadOnly);\n");
413             }
414         }
415         push(@getOwnPropertyDescriptorImpl, "        return true;\n");
416         push(@getOwnPropertyDescriptorImpl, "    }\n");
417     }
418     
419     if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
420         push(@getOwnPropertyDescriptorImpl, "    if (canGetItemsForName(exec, static_cast<$implClassName*>(impl()), propertyName)) {\n");
421         push(@getOwnPropertyDescriptorImpl, "        ${namespaceMaybe}PropertySlot slot;\n");
422         push(@getOwnPropertyDescriptorImpl, "        slot.setCustom(this, nameGetter);\n");
423         push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);\n");
424         push(@getOwnPropertyDescriptorImpl, "        return true;\n");
425         push(@getOwnPropertyDescriptorImpl, "    }\n");
426         if ($inlined) {
427             $headerIncludes{"AtomicString.h"} = 1;
428         } else {
429             $implIncludes{"AtomicString.h"} = 1;
430         }
431     }
432     
433     if ($dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
434         &$manualLookupGetterGeneration();
435     }
436     
437     if ($dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}) {
438         push(@getOwnPropertyDescriptorImpl, "    if (getOwnPropertyDescriptorDelegate(exec, propertyName, descriptor))\n");
439         push(@getOwnPropertyDescriptorImpl, "        return true;\n");
440     }
441     
442     if ($hasAttributes) {
443         if ($inlined) {
444             die "Cannot inline if NoStaticTables is set." if ($dataNode->extendedAttributes->{"NoStaticTables"});
445             push(@getOwnPropertyDescriptorImpl, "    return ${namespaceMaybe}getStaticValueDescriptor<$className, Base>(exec, s_info.staticPropHashTable, this, propertyName, descriptor);\n");
446         } else {
447             push(@getOwnPropertyDescriptorImpl, "    return ${namespaceMaybe}getStaticValueDescriptor<$className, Base>(exec, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");
448         }
449     } else {
450         push(@getOwnPropertyDescriptorImpl, "    return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);\n");
451     }
452     
453     return @getOwnPropertyDescriptorImpl;
454 }
455
456 sub GenerateHeader
457 {
458     my $object = shift;
459     my $dataNode = shift;
460
461     my $interfaceName = $dataNode->name;
462     my $className = "JS$interfaceName";
463     my $implClassName = $interfaceName;
464     my @ancestorInterfaceNames = ();
465     my %structureFlags = ();
466
467     # We only support multiple parents with SVG (for now).
468     if (@{$dataNode->parents} > 1) {
469         die "A class can't have more than one parent" unless $interfaceName =~ /SVG/;
470         $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@ancestorInterfaceNames);
471     }
472
473     my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
474     my $hasRealParent = @{$dataNode->parents} > 0;
475     my $hasParent = $hasLegacyParent || $hasRealParent;
476     my $parentClassName = GetParentClassName($dataNode);
477     my $conditional = $dataNode->extendedAttributes->{"Conditional"};
478     my $eventTarget = $dataNode->extendedAttributes->{"EventTarget"};
479     my $needsMarkChildren = $dataNode->extendedAttributes->{"CustomMarkFunction"} || $dataNode->extendedAttributes->{"EventTarget"};
480     
481     # - Add default header template
482     @headerContentHeader = split("\r", $headerTemplate);
483
484     # - Add header protection
485     push(@headerContentHeader, "\n#ifndef $className" . "_h");
486     push(@headerContentHeader, "\n#define $className" . "_h\n\n");
487
488     my $conditionalString;
489     if ($conditional) {
490         $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
491         push(@headerContentHeader, "#if ${conditionalString}\n\n");
492     }
493
494     if ($hasParent) {
495         $headerIncludes{"$parentClassName.h"} = 1;
496     } else {
497         $headerIncludes{"JSDOMBinding.h"} = 1;
498         $headerIncludes{"<runtime/JSGlobalObject.h>"} = 1;
499         $headerIncludes{"<runtime/ObjectPrototype.h>"} = 1;
500     }
501
502     if ($dataNode->extendedAttributes->{"CustomCall"}) {
503         $headerIncludes{"<runtime/CallData.h>"} = 1;
504     }
505
506     if ($dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"}) {
507         $headerIncludes{"<runtime/Lookup.h>"} = 1;
508         $headerIncludes{"<wtf/AlwaysInline.h>"} = 1;
509     }
510
511     if ($hasParent && $dataNode->extendedAttributes->{"GenerateNativeConverter"}) {
512         $headerIncludes{"$implClassName.h"} = 1;
513     }
514
515     $headerIncludes{"SVGElement.h"} = 1 if $className =~ /^JSSVG/;
516
517     # Get correct pass/store types respecting PODType flag
518     my $podType = $dataNode->extendedAttributes->{"PODType"};
519     my $implType = $podType ? "JSSVGPODTypeWrapper<$podType> " : $implClassName;
520     $headerIncludes{"$podType.h"} = 1 if $podType and $podType ne "float";
521
522     $headerIncludes{"JSSVGPODTypeWrapper.h"} = 1 if $podType;
523
524     my $numConstants = @{$dataNode->constants};
525     my $numAttributes = @{$dataNode->attributes};
526     my $numFunctions = @{$dataNode->functions};
527
528     push(@headerContent, "\nnamespace WebCore {\n\n");
529
530     # Implementation class forward declaration
531     AddClassForwardIfNeeded($implClassName) unless $podType;
532     AddClassForwardIfNeeded("JSDOMWindowShell") if $interfaceName eq "DOMWindow";
533
534     # Class declaration
535     push(@headerContent, "class $className : public $parentClassName {\n");
536     push(@headerContent, "    typedef $parentClassName Base;\n");
537     push(@headerContent, "public:\n");
538
539     # Constructor
540     if ($interfaceName eq "DOMWindow") {
541         push(@headerContent, "    $className(NonNullPassRefPtr<JSC::Structure>, PassRefPtr<$implType>, JSDOMWindowShell*);\n");
542     } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
543         push(@headerContent, "    $className(NonNullPassRefPtr<JSC::Structure>, PassRefPtr<$implType>);\n");
544     } else {
545         push(@headerContent, "    $className(NonNullPassRefPtr<JSC::Structure>, JSDOMGlobalObject*, PassRefPtr<$implType>);\n");
546     }
547
548     # Destructor
549     push(@headerContent, "    virtual ~$className();\n") if (!$hasParent or $eventTarget or $interfaceName eq "DOMWindow");
550
551     # Prototype
552     push(@headerContent, "    static JSC::JSObject* createPrototype(JSC::ExecState*, JSC::JSGlobalObject*);\n") unless ($dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"});
553
554     $implIncludes{"${className}Custom.h"} = 1 if $dataNode->extendedAttributes->{"CustomHeader"} || $dataNode->extendedAttributes->{"CustomPutFunction"} || $dataNode->extendedAttributes->{"DelegatingPutFunction"};
555
556     my $hasGetter = $numAttributes > 0 
557                  || !($dataNode->extendedAttributes->{"OmitConstructor"}
558                  || $dataNode->extendedAttributes->{"CustomConstructor"})
559                  || $dataNode->extendedAttributes->{"HasIndexGetter"}
560                  || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}
561                  || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}
562                  || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}
563                  || $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}
564                  || $dataNode->extendedAttributes->{"HasNameGetter"}
565                  || $dataNode->extendedAttributes->{"HasOverridingNameGetter"};
566
567     # Getters
568     if ($hasGetter) {
569         push(@headerContent, "    virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);\n");
570         push(@headerContent, "    virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&);\n");
571         push(@headerContent, "    virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);\n") if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) && !$dataNode->extendedAttributes->{"HasOverridingNameGetter"};
572         push(@headerContent, "    bool getOwnPropertySlotDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"};
573         push(@headerContent, "    bool getOwnPropertyDescriptorDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n") if $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"};
574         $structureFlags{"JSC::OverridesGetOwnPropertySlot"} = 1;
575     }
576
577     # Check if we have any writable properties
578     my $hasReadWriteProperties = 0;
579     foreach (@{$dataNode->attributes}) {
580         if ($_->type !~ /^readonly\ attribute$/) {
581             $hasReadWriteProperties = 1;
582         }
583     }
584
585     my $hasSetter = $hasReadWriteProperties
586                  || $dataNode->extendedAttributes->{"CustomPutFunction"}
587                  || $dataNode->extendedAttributes->{"DelegatingPutFunction"}
588                  || $dataNode->extendedAttributes->{"HasCustomIndexSetter"};
589
590     # Getters
591     if ($hasSetter) {
592         push(@headerContent, "    virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);\n");
593         push(@headerContent, "    virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValue);\n") if $dataNode->extendedAttributes->{"HasCustomIndexSetter"};
594         push(@headerContent, "    bool putDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, JSC::PutPropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingPutFunction"};
595     }
596
597     # Class info
598     push(@headerContent, "    virtual const JSC::ClassInfo* classInfo() const { return &s_info; }\n");
599     push(@headerContent, "    static const JSC::ClassInfo s_info;\n\n");
600
601     # Structure ID
602     if ($interfaceName eq "DOMWindow") {
603         $structureFlags{"JSC::ImplementsHasInstance"} = 1;
604         $structureFlags{"JSC::NeedsThisConversion"} = 1;
605     }
606     push(@headerContent,
607         "    static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype)\n" .
608         "    {\n" .
609         "        return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount);\n" .
610         "    }\n\n");
611
612     # markChildren function
613     if ($needsMarkChildren) {
614         push(@headerContent, "    virtual void markChildren(JSC::MarkStack&);\n\n");
615         $structureFlags{"JSC::OverridesMarkChildren"} = 1;
616     }
617
618     # Custom pushEventHandlerScope function
619     push(@headerContent, "    virtual void pushEventHandlerScope(JSC::ExecState*, JSC::ScopeChain&) const;\n\n") if $dataNode->extendedAttributes->{"CustomPushEventHandlerScope"};
620
621     # Custom call functions
622     push(@headerContent, "    virtual JSC::CallType getCallData(JSC::CallData&);\n\n") if $dataNode->extendedAttributes->{"CustomCall"};
623
624     # Custom deleteProperty function
625     push(@headerContent, "    virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&);\n") if $dataNode->extendedAttributes->{"CustomDeleteProperty"};
626
627     # Custom getPropertyNames function exists on DOMWindow
628     if ($interfaceName eq "DOMWindow") {
629         push(@headerContent, "    virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n");
630         $structureFlags{"JSC::OverridesGetPropertyNames"} = 1;
631     }
632
633     # Custom defineProperty function exists on DOMWindow
634     push(@headerContent, "    virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&, bool shouldThrow);\n") if $interfaceName eq "DOMWindow";
635
636     # Custom getOwnPropertyNames function
637     if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"} || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
638         push(@headerContent, "    virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n");
639         $structureFlags{"JSC::OverridesGetPropertyNames"} = 1;       
640     }
641
642     # Custom defineGetter function
643     push(@headerContent, "    virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomDefineGetter"};
644
645     # Custom defineSetter function
646     push(@headerContent, "    virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomDefineSetter"};
647
648     # Custom lookupGetter function
649     push(@headerContent, "    virtual JSC::JSValue lookupGetter(JSC::ExecState*, const JSC::Identifier& propertyName);\n") if $dataNode->extendedAttributes->{"CustomLookupGetter"};
650
651     # Custom lookupSetter function
652     push(@headerContent, "    virtual JSC::JSValue lookupSetter(JSC::ExecState*, const JSC::Identifier& propertyName);\n") if $dataNode->extendedAttributes->{"CustomLookupSetter"};
653
654     # Override toBoolean to return false for objects that want to 'MasqueradesAsUndefined'.
655     if ($dataNode->extendedAttributes->{"MasqueradesAsUndefined"}) {
656         push(@headerContent, "    virtual bool toBoolean(JSC::ExecState*) const { return false; };\n");
657         $structureFlags{"JSC::MasqueradesAsUndefined"} = 1;
658     }
659
660     # Constructor object getter
661     push(@headerContent, "    static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*);\n") if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"}));
662
663     my $numCustomFunctions = 0;
664     my $numCustomAttributes = 0;
665
666     # Attribute and function enums
667     if ($numAttributes > 0) {
668         foreach (@{$dataNode->attributes}) {
669             my $attribute = $_;
670             $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"};
671             $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"CustomGetter"} || $attribute->signature->extendedAttributes->{"JSCCustomGetter"};
672             $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"CustomSetter"} || $attribute->signature->extendedAttributes->{"JSCCustomSetter"};
673             if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) {
674                 push(@headerContent, "    static const unsigned " . $attribute->signature->name . "Slot = $numCachedAttributes + Base::AnonymousSlotCount;\n");
675                 $numCachedAttributes++;
676             }
677         }
678     }
679
680     if ($numCachedAttributes > 0) {
681         push(@headerContent, "    using $parentClassName" . "::putAnonymousValue;\n");
682         push(@headerContent, "    using $parentClassName" . "::getAnonymousValue;\n");
683     }
684     if ($numCustomAttributes > 0) {
685         push(@headerContent, "\n    // Custom attributes\n");
686
687         foreach my $attribute (@{$dataNode->attributes}) {
688             if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"}) {
689                 push(@headerContent, "    JSC::JSValue " . $codeGenerator->WK_lcfirst($attribute->signature->name) . "(JSC::ExecState*) const;\n");
690                 if ($attribute->type !~ /^readonly/) {
691                     push(@headerContent, "    void set" . $codeGenerator->WK_ucfirst($attribute->signature->name) . "(JSC::ExecState*, JSC::JSValue);\n");
692                 }
693             } elsif ($attribute->signature->extendedAttributes->{"CustomGetter"} || $attribute->signature->extendedAttributes->{"JSCCustomGetter"}) {
694                 push(@headerContent, "    JSC::JSValue " . $codeGenerator->WK_lcfirst($attribute->signature->name) . "(JSC::ExecState*) const;\n");
695             } elsif ($attribute->signature->extendedAttributes->{"CustomSetter"} || $attribute->signature->extendedAttributes->{"JSCCustomSetter"}) {
696                 if ($attribute->type !~ /^readonly/) {
697                     push(@headerContent, "    void set" . $codeGenerator->WK_ucfirst($attribute->signature->name) . "(JSC::ExecState*, JSC::JSValue);\n");
698                 }
699             }
700         }
701     }
702
703     foreach my $function (@{$dataNode->functions}) {
704         $numCustomFunctions++ if $function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"JSCCustom"};
705     }
706
707     if ($numCustomFunctions > 0) {
708         push(@headerContent, "\n    // Custom functions\n");
709         foreach my $function (@{$dataNode->functions}) {
710             if ($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"JSCCustom"}) {
711                 my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementationFunction"} || $codeGenerator->WK_lcfirst($function->signature->name);
712                 push(@headerContent, "    JSC::JSValue " . $functionImplementationName . "(JSC::ExecState*, const JSC::ArgList&);\n");
713             }
714         }
715     }
716
717     if (!$hasParent) {
718         # Extra space after JSSVGPODTypeWrapper<> to make RefPtr<Wrapper<> > compile.
719         my $implType = $podType ? "JSSVGPODTypeWrapper<$podType> " : $implClassName;
720         push(@headerContent, "    $implType* impl() const { return m_impl.get(); }\n\n");
721         push(@headerContent, "private:\n");
722         push(@headerContent, "    RefPtr<$implType> m_impl;\n");
723     } elsif ($dataNode->extendedAttributes->{"GenerateNativeConverter"}) {
724         push(@headerContent, "    $implClassName* impl() const\n");
725         push(@headerContent, "    {\n");
726         push(@headerContent, "        return static_cast<$implClassName*>(Base::impl());\n");
727         push(@headerContent, "    }\n");
728     }
729     
730     # anonymous slots
731     if ($numCachedAttributes) {
732         push(@headerContent, "public:\n");
733         push(@headerContent, "    static const unsigned AnonymousSlotCount = $numCachedAttributes + Base::AnonymousSlotCount;\n");
734     }
735
736     # structure flags
737     push(@headerContent, "protected:\n");
738     push(@headerContent, "    static const unsigned StructureFlags = ");
739     foreach my $structureFlag (keys %structureFlags) {
740         push(@headerContent, $structureFlag . " | ");
741     }
742     push(@headerContent, "Base::StructureFlags;\n");
743
744     # Index getter
745     if ($dataNode->extendedAttributes->{"HasIndexGetter"}) {
746         push(@headerContent, "    static JSC::JSValue indexGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n");
747     }
748     if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
749         push(@headerContent, "    JSC::JSValue getByIndex(JSC::ExecState*, unsigned index);\n");
750         
751     }
752     
753     # Index setter
754     if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
755         push(@headerContent, "    void indexSetter(JSC::ExecState*, unsigned index, JSC::JSValue);\n");
756     }
757     # Name getter
758     if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
759         push(@headerContent, "private:\n");
760         push(@headerContent, "    static bool canGetItemsForName(JSC::ExecState*, $implClassName*, const JSC::Identifier&);\n");
761         push(@headerContent, "    static JSC::JSValue nameGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n");
762     }
763
764     push(@headerContent, "};\n\n");
765
766     if ($dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"} && !$dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}) {
767         push(@headerContent, "ALWAYS_INLINE bool ${className}::getOwnPropertySlot(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertySlot& slot)\n");
768         push(@headerContent, "{\n");
769         push(@headerContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 1));
770         push(@headerContent, "}\n\n");
771         push(@headerContent, "ALWAYS_INLINE bool ${className}::getOwnPropertyDescriptor(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertyDescriptor& descriptor)\n");
772         push(@headerContent, "{\n");
773         push(@headerContent, GenerateGetOwnPropertyDescriptorBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 1));
774         push(@headerContent, "}\n\n");
775     }
776
777     if (!$hasParent || $dataNode->extendedAttributes->{"GenerateToJS"} || $dataNode->extendedAttributes->{"CustomToJS"}) {
778         if ($podType) {
779             push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, JSSVGPODTypeWrapper<$podType>*, SVGElement*);\n");
780         } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
781             push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType*, SVGElement* context);\n");
782         } else {
783             push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType*);\n");
784         }
785     }
786     if (!$hasParent || $dataNode->extendedAttributes->{"GenerateNativeConverter"}) {
787         if ($podType) {
788             push(@headerContent, "$podType to${interfaceName}(JSC::JSValue);\n");
789         } elsif ($interfaceName eq "NodeFilter") {
790             push(@headerContent, "PassRefPtr<NodeFilter> toNodeFilter(JSC::JSValue);\n");
791         } else {
792             push(@headerContent, "$implClassName* to${interfaceName}(JSC::JSValue);\n");
793         }
794     }
795     if ($interfaceName eq "Node" or $interfaceName eq "Element" or $interfaceName eq "Text" or $interfaceName eq "CDATASection") {
796         push(@headerContent, "JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject*, $interfaceName*);\n");
797     }
798     
799     push(@headerContent, "\n");
800
801     # Add prototype declaration.
802     %structureFlags = ();
803     push(@headerContent, "class ${className}Prototype : public JSC::JSObject {\n");
804     push(@headerContent, "    typedef JSC::JSObject Base;\n");
805     push(@headerContent, "public:\n");
806     if ($interfaceName eq "DOMWindow") {
807         push(@headerContent, "    void* operator new(size_t);\n");
808     } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
809         push(@headerContent, "    void* operator new(size_t, JSC::JSGlobalData*);\n");
810     } else {
811         push(@headerContent, "    static JSC::JSObject* self(JSC::ExecState*, JSC::JSGlobalObject*);\n");
812     }
813     push(@headerContent, "    virtual const JSC::ClassInfo* classInfo() const { return &s_info; }\n");
814     push(@headerContent, "    static const JSC::ClassInfo s_info;\n");
815     if ($numFunctions > 0 || $numConstants > 0 || $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) {
816         push(@headerContent, "    virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n");
817         push(@headerContent, "    virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n");
818         push(@headerContent, "    bool getOwnPropertySlotDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"};
819         push(@headerContent, "    bool getOwnPropertyDescriptorDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n") if $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"};
820         $structureFlags{"JSC::OverridesGetOwnPropertySlot"} = 1;
821     }
822     if ($dataNode->extendedAttributes->{"CustomMarkFunction"} or $needsMarkChildren) {
823         $structureFlags{"JSC::OverridesMarkChildren"} = 1;
824     }
825     push(@headerContent,
826         "    static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype)\n" .
827         "    {\n" .
828         "        return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount);\n" .
829         "    }\n");
830     if ($dataNode->extendedAttributes->{"DelegatingPrototypePutFunction"}) {
831         push(@headerContent, "    virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);\n");
832         push(@headerContent, "    bool putDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, JSC::PutPropertySlot&);\n");
833     }
834
835     # Custom defineGetter function
836     push(@headerContent, "    virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomPrototypeDefineGetter"};
837
838     push(@headerContent, "    ${className}Prototype(NonNullPassRefPtr<JSC::Structure> structure) : JSC::JSObject(structure) { }\n");
839
840     # structure flags
841     push(@headerContent, "protected:\n");
842     push(@headerContent, "    static const unsigned StructureFlags = ");
843     foreach my $structureFlag (keys %structureFlags) {
844         push(@headerContent, $structureFlag . " | ");
845     }
846     push(@headerContent, "Base::StructureFlags;\n");
847
848     push(@headerContent, "};\n\n");
849
850     if ($numFunctions > 0) {
851         push(@headerContent,"// Functions\n\n");
852         foreach my $function (@{$dataNode->functions}) {
853             my $functionName = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($function->signature->name);
854             push(@headerContent, "JSC::JSValue JSC_HOST_CALL ${functionName}(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);\n");
855         }
856     }
857
858     if ($numAttributes > 0 || !($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
859         push(@headerContent,"// Attributes\n\n");
860         foreach my $attribute (@{$dataNode->attributes}) {
861             my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
862             push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n");
863             unless ($attribute->type =~ /readonly/) {
864                 my $setter = "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
865                 push(@headerContent, "void ${setter}(JSC::ExecState*, JSC::JSObject*, JSC::JSValue);\n");
866             }
867         }
868         
869         if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
870             my $getter = "js" . $interfaceName . "Constructor";
871             push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n");
872         }
873     }
874
875     if ($numConstants > 0) {
876         push(@headerContent,"// Constants\n\n");
877         foreach my $constant (@{$dataNode->constants}) {
878             my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);
879             push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n");
880         }
881     }
882
883     push(@headerContent, "\n} // namespace WebCore\n\n");
884     push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditional;
885     push(@headerContent, "#endif\n");
886
887     # - Generate dependencies.
888     if ($writeDependencies && @ancestorInterfaceNames) {
889         push(@depsContent, "$className.h : ", join(" ", map { "$_.idl" } @ancestorInterfaceNames), "\n");
890         push(@depsContent, map { "$_.idl :\n" } @ancestorInterfaceNames); 
891     }
892 }
893
894 sub GenerateImplementation
895 {
896     my ($object, $dataNode) = @_;
897
898     my $interfaceName = $dataNode->name;
899     my $className = "JS$interfaceName";
900     my $implClassName = $interfaceName;
901
902     my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
903     my $hasRealParent = @{$dataNode->parents} > 0;
904     my $hasParent = $hasLegacyParent || $hasRealParent;
905     my $parentClassName = GetParentClassName($dataNode);
906     my $conditional = $dataNode->extendedAttributes->{"Conditional"};
907     my $visibleClassName = GetVisibleClassName($interfaceName);
908     my $eventTarget = $dataNode->extendedAttributes->{"EventTarget"};
909     my $needsMarkChildren = $dataNode->extendedAttributes->{"CustomMarkFunction"} || $dataNode->extendedAttributes->{"EventTarget"};
910
911     # - Add default header template
912     @implContentHeader = split("\r", $headerTemplate);
913
914     push(@implContentHeader, "\n#include \"config.h\"\n");
915     my $conditionalString;
916     if ($conditional) {
917         $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
918         push(@implContentHeader, "\n#if ${conditionalString}\n\n");
919     }
920     push(@implContentHeader, "#include \"$className.h\"\n\n");
921
922     AddIncludesForSVGAnimatedType($interfaceName) if $className =~ /^JSSVGAnimated/;
923
924     $implIncludes{"<wtf/GetPtr.h>"} = 1;
925     $implIncludes{"<runtime/PropertyNameArray.h>"} = 1 if $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"};
926
927     AddIncludesForType($interfaceName);
928
929     @implContent = ();
930
931     push(@implContent, "\nusing namespace JSC;\n\n");
932     push(@implContent, "namespace WebCore {\n\n");
933
934     push(@implContent, "ASSERT_CLASS_FITS_IN_CELL($className);\n\n");
935
936     # - Add all attributes in a hashtable definition
937     my $numAttributes = @{$dataNode->attributes};
938     $numAttributes++ if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"}));
939
940     if ($numAttributes > 0) {
941         my $hashSize = $numAttributes;
942         my $hashName = $className . "Table";
943
944         my @hashKeys = ();
945         my @hashSpecials = ();
946         my @hashValue1 = ();
947         my @hashValue2 = ();
948         my %conditionals = ();
949
950         my @entries = ();
951
952         foreach my $attribute (@{$dataNode->attributes}) {
953             my $name = $attribute->signature->name;
954             push(@hashKeys, $name);
955
956             my @specials = ();
957             push(@specials, "DontDelete") unless $attribute->signature->extendedAttributes->{"Deletable"};
958             push(@specials, "DontEnum") if $attribute->signature->extendedAttributes->{"DontEnum"};
959             push(@specials, "ReadOnly") if $attribute->type =~ /readonly/;
960             my $special = (@specials > 0) ? join("|", @specials) : "0";
961             push(@hashSpecials, $special);
962
963             my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
964             push(@hashValue1, $getter);
965     
966             if ($attribute->type =~ /readonly/) {
967                 push(@hashValue2, "0");
968             } else {
969                 my $setter = "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
970                 push(@hashValue2, $setter);
971             }
972
973             my $conditional = $attribute->signature->extendedAttributes->{"Conditional"};
974             if ($conditional) {
975                 $conditionals{$name} = $conditional;
976             }
977         }
978
979         if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
980             push(@hashKeys, "constructor");
981             my $getter = "js" . $interfaceName . "Constructor";
982             push(@hashValue1, $getter);
983             push(@hashValue2, "0");
984             push(@hashSpecials, "DontEnum|ReadOnly"); # FIXME: Setting the constructor should be possible.
985         }
986
987         $object->GenerateHashTable($hashName, $hashSize,
988                                    \@hashKeys, \@hashSpecials,
989                                    \@hashValue1, \@hashValue2,
990                                    \%conditionals);
991     }
992
993     my $numConstants = @{$dataNode->constants};
994     my $numFunctions = @{$dataNode->functions};
995
996     # - Add all constants
997     if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
998         $hashSize = $numConstants;
999         $hashName = $className . "ConstructorTable";
1000
1001         @hashKeys = ();
1002         @hashValue1 = ();
1003         @hashValue2 = ();
1004         @hashSpecials = ();
1005
1006         # FIXME: we should not need a function for every constant.
1007         foreach my $constant (@{$dataNode->constants}) {
1008             push(@hashKeys, $constant->name);
1009             my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);
1010             push(@hashValue1, $getter);
1011             push(@hashValue2, "0");
1012             push(@hashSpecials, "DontDelete|ReadOnly");
1013         }
1014
1015         $object->GenerateHashTable($hashName, $hashSize,
1016                                    \@hashKeys, \@hashSpecials,
1017                                    \@hashValue1, \@hashValue2);
1018
1019         my $protoClassName;
1020         $protoClassName = "${className}Prototype";
1021
1022         push(@implContent, constructorFor($className, $protoClassName, $interfaceName, $visibleClassName, $dataNode->extendedAttributes->{"CanBeConstructed"}));
1023     }
1024
1025     # - Add functions and constants to a hashtable definition
1026     $hashSize = $numFunctions + $numConstants;
1027     $hashName = $className . "PrototypeTable";
1028
1029     @hashKeys = ();
1030     @hashValue1 = ();
1031     @hashValue2 = ();
1032     @hashSpecials = ();
1033
1034     # FIXME: we should not need a function for every constant.
1035     foreach my $constant (@{$dataNode->constants}) {
1036         push(@hashKeys, $constant->name);
1037         my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);
1038         push(@hashValue1, $getter);
1039         push(@hashValue2, "0");
1040         push(@hashSpecials, "DontDelete|ReadOnly");
1041     }
1042
1043     foreach my $function (@{$dataNode->functions}) {
1044         my $name = $function->signature->name;
1045         push(@hashKeys, $name);
1046
1047         my $value = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($name);
1048         push(@hashValue1, $value);
1049
1050         my $numParameters = @{$function->parameters};
1051         push(@hashValue2, $numParameters);
1052
1053         my @specials = ();
1054         push(@specials, "DontDelete") unless $function->signature->extendedAttributes->{"Deletable"};
1055         push(@specials, "DontEnum") if $function->signature->extendedAttributes->{"DontEnum"};
1056         push(@specials, "Function");
1057         my $special = (@specials > 0) ? join("|", @specials) : "0";
1058         push(@hashSpecials, $special);
1059     }
1060
1061     $object->GenerateHashTable($hashName, $hashSize,
1062                                \@hashKeys, \@hashSpecials,
1063                                \@hashValue1, \@hashValue2);
1064
1065     if ($dataNode->extendedAttributes->{"NoStaticTables"}) {
1066         push(@implContent, "static const HashTable* get${className}PrototypeTable(ExecState* exec)\n");
1067         push(@implContent, "{\n");
1068         push(@implContent, "    return getHashTableForGlobalData(exec->globalData(), &${className}PrototypeTable);\n");
1069         push(@implContent, "}\n");
1070         push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleClassName}Prototype\", 0, 0, get${className}PrototypeTable };\n\n");
1071     } else {
1072         push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleClassName}Prototype\", 0, &${className}PrototypeTable, 0 };\n\n");
1073     }
1074     if ($interfaceName eq "DOMWindow") {
1075         push(@implContent, "void* ${className}Prototype::operator new(size_t size)\n");
1076         push(@implContent, "{\n");
1077         push(@implContent, "    return JSDOMWindow::commonJSGlobalData()->heap.allocate(size);\n");
1078         push(@implContent, "}\n\n");
1079     } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
1080         push(@implContent, "void* ${className}Prototype::operator new(size_t size, JSGlobalData* globalData)\n");
1081         push(@implContent, "{\n");
1082         push(@implContent, "    return globalData->heap.allocate(size);\n");
1083         push(@implContent, "}\n\n");
1084     } else {
1085         push(@implContent, "JSObject* ${className}Prototype::self(ExecState* exec, JSGlobalObject* globalObject)\n");
1086         push(@implContent, "{\n");
1087         push(@implContent, "    return getDOMPrototype<${className}>(exec, globalObject);\n");
1088         push(@implContent, "}\n\n");
1089     }
1090     if ($numConstants > 0 || $numFunctions > 0 || $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) {
1091         push(@implContent, "bool ${className}Prototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n");
1092         push(@implContent, "{\n");
1093
1094         if ($dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) {
1095             push(@implContent, "    if (getOwnPropertySlotDelegate(exec, propertyName, slot))\n");
1096             push(@implContent, "        return true;\n");
1097         }
1098
1099         if ($numConstants eq 0 && $numFunctions eq 0) {
1100             push(@implContent, "    return Base::getOwnPropertySlot(exec, propertyName, slot);\n");        
1101         } elsif ($numConstants eq 0) {
1102             push(@implContent, "    return getStaticFunctionSlot<JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n");
1103         } elsif ($numFunctions eq 0) {
1104             push(@implContent, "    return getStaticValueSlot<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n");
1105         } else {
1106             push(@implContent, "    return getStaticPropertySlot<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n");
1107         }
1108         push(@implContent, "}\n\n");
1109
1110         push(@implContent, "bool ${className}Prototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\n");
1111         push(@implContent, "{\n");
1112         
1113         if ($dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) {
1114             push(@implContent, "    if (getOwnPropertyDescriptorDelegate(exec, propertyName, descriptor))\n");
1115             push(@implContent, "        return true;\n");
1116         }
1117         
1118         if ($numConstants eq 0 && $numFunctions eq 0) {
1119             push(@implContent, "    return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);\n");        
1120         } elsif ($numConstants eq 0) {
1121             push(@implContent, "    return getStaticFunctionDescriptor<JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");
1122         } elsif ($numFunctions eq 0) {
1123             push(@implContent, "    return getStaticValueDescriptor<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");
1124         } else {
1125             push(@implContent, "    return getStaticPropertyDescriptor<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");
1126         }
1127         push(@implContent, "}\n\n");
1128     }
1129
1130     if ($dataNode->extendedAttributes->{"DelegatingPrototypePutFunction"}) {
1131         push(@implContent, "void ${className}Prototype::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)\n");
1132         push(@implContent, "{\n");
1133         push(@implContent, "    if (putDelegate(exec, propertyName, value, slot))\n");
1134         push(@implContent, "        return;\n");
1135         push(@implContent, "    Base::put(exec, propertyName, value, slot);\n");
1136         push(@implContent, "}\n\n");
1137     }
1138
1139     # - Initialize static ClassInfo object
1140     if ($numAttributes > 0 && $dataNode->extendedAttributes->{"NoStaticTables"}) {
1141         push(@implContent, "static const HashTable* get${className}Table(ExecState* exec)\n");
1142         push(@implContent, "{\n");
1143         push(@implContent, "    return getHashTableForGlobalData(exec->globalData(), &${className}Table);\n");
1144         push(@implContent, "}\n");
1145     }
1146     push(@implContent, "const ClassInfo $className" . "::s_info = { \"${visibleClassName}\", ");
1147     if ($hasParent) {
1148         push(@implContent, "&" . $parentClassName . "::s_info, ");
1149     } else {
1150         push(@implContent, "0, ");
1151     }
1152
1153     if ($numAttributes > 0 && !$dataNode->extendedAttributes->{"NoStaticTables"}) {
1154         push(@implContent, "&${className}Table");
1155     } else {
1156         push(@implContent, "0");
1157     }
1158     if ($numAttributes > 0 && $dataNode->extendedAttributes->{"NoStaticTables"}) {
1159         push(@implContent, ", get${className}Table ");
1160     } else {
1161         push(@implContent, ", 0 ");
1162     }
1163     push(@implContent, "};\n\n");
1164
1165     # Get correct pass/store types respecting PODType flag
1166     my $podType = $dataNode->extendedAttributes->{"PODType"};
1167     my $implType = $podType ? "JSSVGPODTypeWrapper<$podType> " : $implClassName;
1168
1169     # Constructor
1170     if ($interfaceName eq "DOMWindow") {
1171         AddIncludesForType("JSDOMWindowShell");
1172         push(@implContent, "${className}::$className(NonNullPassRefPtr<Structure> structure, PassRefPtr<$implType> impl, JSDOMWindowShell* shell)\n");
1173         push(@implContent, "    : $parentClassName(structure, impl, shell)\n");
1174     } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
1175         AddIncludesForType($interfaceName);
1176         push(@implContent, "${className}::$className(NonNullPassRefPtr<Structure> structure, PassRefPtr<$implType> impl)\n");
1177         push(@implContent, "    : $parentClassName(structure, impl)\n");
1178     } else {
1179         push(@implContent, "${className}::$className(NonNullPassRefPtr<Structure> structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl)\n");
1180         if ($hasParent) {
1181             push(@implContent, "    : $parentClassName(structure, globalObject, impl)\n");
1182         } else {
1183             push(@implContent, "    : $parentClassName(structure, globalObject)\n");
1184             push(@implContent, "    , m_impl(impl)\n");
1185         }
1186     }
1187     push(@implContent, "{\n");
1188     if ($numCachedAttributes > 0) {
1189         push(@implContent, "    for (unsigned i = Base::AnonymousSlotCount; i < AnonymousSlotCount; i++)\n");
1190         push(@implContent, "        putAnonymousValue(i, JSValue());\n");
1191     }
1192     push(@implContent, "}\n\n");
1193
1194     # Destructor
1195     if (!$hasParent || $eventTarget) {
1196         push(@implContent, "${className}::~$className()\n");
1197         push(@implContent, "{\n");
1198
1199         if ($eventTarget) {
1200             $implIncludes{"RegisteredEventListener.h"} = 1;
1201             push(@implContent, "    impl()->invalidateJSEventListeners(this);\n");
1202         }
1203
1204         if (!$dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"}) {
1205             if ($interfaceName eq "Node") {
1206                  push(@implContent, "    forgetDOMNode(this, impl(), impl()->document());\n");
1207             } else {
1208                 push(@implContent, "    forgetDOMObject(this, impl());\n");
1209             }
1210
1211             push(@implContent, "    JSSVGContextCache::forgetWrapper(this);\n") if IsSVGTypeNeedingContextParameter($implClassName);
1212         }
1213
1214         push(@implContent, "}\n\n");
1215     }
1216
1217     if ($needsMarkChildren && !$dataNode->extendedAttributes->{"CustomMarkFunction"}) {
1218         push(@implContent, "void ${className}::markChildren(MarkStack& markStack)\n");
1219         push(@implContent, "{\n");
1220         push(@implContent, "    Base::markChildren(markStack);\n");
1221         push(@implContent, "    impl()->markJSEventListeners(markStack);\n");
1222         push(@implContent, "}\n\n");
1223     }
1224
1225     if (!$dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"}) {
1226         push(@implContent, "JSObject* ${className}::createPrototype(ExecState* exec, JSGlobalObject* globalObject)\n");
1227         push(@implContent, "{\n");
1228         if ($hasParent && $parentClassName ne "JSC::DOMNodeFilter") {
1229             push(@implContent, "    return new (exec) ${className}Prototype(${className}Prototype::createStructure(${parentClassName}Prototype::self(exec, globalObject)));\n");
1230         } else {
1231             push(@implContent, "    return new (exec) ${className}Prototype(${className}Prototype::createStructure(globalObject->objectPrototype()));\n");
1232         }
1233         push(@implContent, "}\n\n");
1234     }
1235
1236     my $hasGetter = $numAttributes > 0 
1237                  || !($dataNode->extendedAttributes->{"OmitConstructor"} 
1238                  || $dataNode->extendedAttributes->{"CustomConstructor"})
1239                  || $dataNode->extendedAttributes->{"HasIndexGetter"}
1240                  || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}
1241                  || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}
1242                  || $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}
1243                  || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}
1244                  || $dataNode->extendedAttributes->{"HasNameGetter"}
1245                  || $dataNode->extendedAttributes->{"HasOverridingNameGetter"};
1246
1247     # Attributes
1248     if ($hasGetter) {
1249         if (!$dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"} && !$dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}) {
1250             push(@implContent, "bool ${className}::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n");
1251             push(@implContent, "{\n");
1252             push(@implContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 0));
1253             push(@implContent, "}\n\n");
1254             push(@implContent, "bool ${className}::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\n");
1255             push(@implContent, "{\n");
1256             push(@implContent, GenerateGetOwnPropertyDescriptorBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 0));
1257             push(@implContent, "}\n\n");
1258         }
1259
1260         if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) 
1261                 && !$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
1262             push(@implContent, "bool ${className}::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)\n");
1263             push(@implContent, "{\n");
1264             push(@implContent, "    if (propertyName < static_cast<$implClassName*>(impl())->length()) {\n");
1265             if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
1266                 push(@implContent, "        slot.setValue(getByIndex(exec, propertyName));\n");
1267             } else {
1268                 push(@implContent, "        slot.setCustomIndex(this, propertyName, indexGetter);\n");
1269             }
1270             push(@implContent, "        return true;\n");
1271             push(@implContent, "    }\n");
1272             push(@implContent, "    return getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);\n");
1273             push(@implContent, "}\n\n");
1274         }
1275         
1276         if ($numAttributes > 0) {
1277             foreach my $attribute (@{$dataNode->attributes}) {
1278                 my $name = $attribute->signature->name;
1279                 my $type = $codeGenerator->StripModule($attribute->signature->type);
1280                 my $getFunctionName = "js" . $interfaceName .  $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
1281                 my $implGetterFunctionName = $codeGenerator->WK_lcfirst($name);
1282
1283                 my $conditional = $attribute->signature->extendedAttributes->{"Conditional"};
1284                 if ($conditional) {
1285                     $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
1286                     push(@implContent, "#if ${conditionalString}\n");
1287                 }
1288
1289                 push(@implContent, "JSValue ${getFunctionName}(ExecState* exec, const Identifier&, const PropertySlot& slot)\n");
1290                 push(@implContent, "{\n");
1291                 push(@implContent, "    ${className}* castedThis = static_cast<$className*>(asObject(slot.slotBase()));\n");
1292
1293                 my $implClassNameForValueConversion = "";
1294                 if (!$podType and ($codeGenerator->IsSVGAnimatedType($implClassName) or $attribute->type !~ /^readonly/)) {
1295                     $implClassNameForValueConversion = $implClassName;
1296                 }
1297
1298                 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && 
1299                         !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurity"} &&
1300                         !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurityOnGet"}) {
1301                     push(@implContent, "    if (!castedThis->allowsAccessFrom(exec))\n");
1302                     push(@implContent, "        return jsUndefined();\n");
1303                 }
1304
1305                 if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"} || $attribute->signature->extendedAttributes->{"CustomGetter"} || $attribute->signature->extendedAttributes->{"JSCCustomGetter"}) {
1306                     push(@implContent, "    return castedThis->$implGetterFunctionName(exec);\n");
1307                 } elsif ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) {
1308                     $implIncludes{"JSDOMBinding.h"} = 1;
1309                     push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");
1310                     push(@implContent, "    return checkNodeSecurity(exec, imp->$implGetterFunctionName()) ? " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$implGetterFunctionName()", "castedThis") . " : jsUndefined();\n");
1311                 } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) {
1312                     $implIncludes{"Document.h"} = 1;
1313                     $implIncludes{"JSDOMBinding.h"} = 1;
1314                     push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");
1315                     push(@implContent, "    return checkNodeSecurity(exec, imp->contentDocument()) ? " . NativeToJSValue($attribute->signature,  0, $implClassName, $implClassNameForValueConversion, "imp->$implGetterFunctionName()", "castedThis") . " : jsUndefined();\n");
1316                 } elsif ($type eq "EventListener") {
1317                     $implIncludes{"EventListener.h"} = 1;
1318                     push(@implContent, "    UNUSED_PARAM(exec);\n");
1319                     push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");
1320                     push(@implContent, "    if (EventListener* listener = imp->$implGetterFunctionName()) {\n");
1321                     push(@implContent, "        if (const JSEventListener* jsListener = JSEventListener::cast(listener)) {\n");
1322                     if ($implClassName eq "Document" || $implClassName eq "WorkerContext" || $implClassName eq "SharedWorkerContext" || $implClassName eq "DedicatedWorkerContext") {
1323                         push(@implContent, "            if (JSObject* jsFunction = jsListener->jsFunction(imp))\n");
1324                     } else {
1325                         push(@implContent, "            if (JSObject* jsFunction = jsListener->jsFunction(imp->scriptExecutionContext()))\n");
1326                     }
1327                     push(@implContent, "                return jsFunction;\n");
1328                     push(@implContent, "        }\n");
1329                     push(@implContent, "    }\n");
1330                     push(@implContent, "    return jsNull();\n");
1331                 } elsif ($attribute->signature->type =~ /Constructor$/) {
1332                     my $constructorType = $codeGenerator->StripModule($attribute->signature->type);
1333                     $constructorType =~ s/Constructor$//;
1334                     # Constructor attribute is only used by DOMWindow.idl, so it's correct to pass castedThis as the global object
1335                     # Once DOMObjects have a back-pointer to the globalObject we can pass castedThis->globalObject()
1336                     push(@implContent, "    return JS" . $constructorType . "::getConstructor(exec, castedThis);\n");
1337                 } elsif (!@{$attribute->getterExceptions}) {
1338                     push(@implContent, "    UNUSED_PARAM(exec);\n");
1339                     my $cacheIndex = 0;
1340                     if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) {
1341                         $cacheIndex = $currentCachedAttribute;
1342                         $currentCachedAttribute++;
1343                         push(@implContent, "    if (JSValue cachedValue = castedThis->getAnonymousValue(" . $className . "::" . $attribute->signature->name . "Slot))\n");
1344                         push(@implContent, "        return cachedValue;\n");
1345                     }
1346                     if ($podType) {
1347                         push(@implContent, "    $podType imp(*castedThis->impl());\n");
1348                         if ($podType eq "float") { # Special case for JSSVGNumber
1349                             push(@implContent, "    JSValue result =  " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp", "castedThis") . ";\n");
1350                         } else {
1351                             push(@implContent, "    JSValue result =  " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$implGetterFunctionName()", "castedThis") . ";\n");
1352                         }
1353                     } else {
1354                         push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");
1355                         my $value;
1356                         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
1357                         my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
1358                         if ($reflect || $reflectURL) {
1359                             my $contentAttributeName = (($reflect || $reflectURL) eq "1") ? $name : ($reflect || $reflectURL);
1360                             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
1361                             $implIncludes{"${namespace}.h"} = 1;
1362                             my $getAttributeFunctionName = $reflectURL ? "getURLAttribute" : "getAttribute";
1363                             $value = "imp->$getAttributeFunctionName(${namespace}::${contentAttributeName}Attr)"
1364                         } else {
1365                             $value = "imp->$implGetterFunctionName()";
1366                         }
1367                         my $jsType = NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, $value, "castedThis");
1368                         if ($codeGenerator->IsSVGAnimatedType($type)) {
1369                             push(@implContent, "    RefPtr<$type> obj = $jsType;\n");
1370                             push(@implContent, "    JSValue result =  toJS(exec, castedThis->globalObject(), obj.get(), imp);\n");
1371                         } else {
1372                             push(@implContent, "    JSValue result = $jsType;\n");
1373                         }
1374                     }
1375                     
1376                     push(@implContent, "    castedThis->putAnonymousValue(" . $className . "::" . $attribute->signature->name . "Slot, result);\n") if ($attribute->signature->extendedAttributes->{"CachedAttribute"});
1377                     push(@implContent, "    return result;\n");
1378
1379                 } else {
1380                     push(@implContent, "    ExceptionCode ec = 0;\n");                    
1381                     if ($podType) {
1382                         push(@implContent, "    $podType imp(*castedThis->impl());\n");
1383                         push(@implContent, "    JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$implGetterFunctionName(ec)", "castedThis") . ";\n");
1384                     } else {
1385                         push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");
1386                         push(@implContent, "    JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$implGetterFunctionName(ec)", "castedThis") . ";\n");
1387                     }
1388
1389                     push(@implContent, "    setDOMException(exec, ec);\n");
1390                     push(@implContent, "    return result;\n");
1391                 }
1392
1393                 push(@implContent, "}\n");
1394
1395                 if ($conditional) {
1396                     push(@implContent, "#endif\n");
1397                 }
1398
1399                 push(@implContent, "\n");
1400             }
1401
1402             if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
1403                 my $constructorFunctionName = "js" . $interfaceName . "Constructor";
1404
1405                 push(@implContent, "JSValue ${constructorFunctionName}(ExecState* exec, const Identifier&, const PropertySlot& slot)\n");
1406                 push(@implContent, "{\n");
1407                 push(@implContent, "    ${className}* domObject = static_cast<$className*>(asObject(slot.slotBase()));\n");
1408                 push(@implContent, "    return ${className}::getConstructor(exec, domObject->globalObject());\n");
1409                 push(@implContent, "}\n");
1410             }
1411         }
1412
1413         # Check if we have any writable attributes
1414         my $hasReadWriteProperties = 0;
1415         foreach my $attribute (@{$dataNode->attributes}) {
1416             $hasReadWriteProperties = 1 if $attribute->type !~ /^readonly/;
1417         }
1418
1419         my $hasSetter = $hasReadWriteProperties
1420                      || $dataNode->extendedAttributes->{"DelegatingPutFunction"}
1421                      || $dataNode->extendedAttributes->{"HasCustomIndexSetter"};
1422
1423         if ($hasSetter) {
1424             if (!$dataNode->extendedAttributes->{"CustomPutFunction"}) {
1425                 push(@implContent, "void ${className}::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)\n");
1426                 push(@implContent, "{\n");
1427                 if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
1428                     push(@implContent, "    bool ok;\n");
1429                     push(@implContent, "    unsigned index = propertyName.toUInt32(&ok, false);\n");
1430                     push(@implContent, "    if (ok) {\n");
1431                     push(@implContent, "        indexSetter(exec, index, value);\n");
1432                     push(@implContent, "        return;\n");
1433                     push(@implContent, "    }\n");
1434                 }
1435                 if ($dataNode->extendedAttributes->{"DelegatingPutFunction"}) {
1436                     push(@implContent, "    if (putDelegate(exec, propertyName, value, slot))\n");
1437                     push(@implContent, "        return;\n");
1438                 }
1439
1440                 if ($hasReadWriteProperties) {
1441                     push(@implContent, "    lookupPut<$className, Base>(exec, propertyName, value, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, slot);\n");
1442                 } else {
1443                     push(@implContent, "    Base::put(exec, propertyName, value, slot);\n");
1444                 }
1445                 push(@implContent, "}\n\n");
1446             }
1447
1448             if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
1449                 push(@implContent, "void ${className}::put(ExecState* exec, unsigned propertyName, JSValue value)\n");
1450                 push(@implContent, "{\n");
1451                 push(@implContent, "    indexSetter(exec, propertyName, value);\n");
1452                 push(@implContent, "    return;\n");
1453                 push(@implContent, "}\n\n");
1454             }
1455
1456             if ($hasReadWriteProperties) {
1457                 foreach my $attribute (@{$dataNode->attributes}) {
1458                     if ($attribute->type !~ /^readonly/) {
1459                         my $name = $attribute->signature->name;
1460                         my $type = $codeGenerator->StripModule($attribute->signature->type);
1461                         my $putFunctionName = "setJS" . $interfaceName .  $codeGenerator->WK_ucfirst($name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
1462                         my $implSetterFunctionName = $codeGenerator->WK_ucfirst($name);
1463
1464                         push(@implContent, "void ${putFunctionName}(ExecState* exec, JSObject* thisObject, JSValue value)\n");
1465                         push(@implContent, "{\n");
1466
1467                         if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
1468                             if ($interfaceName eq "DOMWindow") {
1469                                 push(@implContent, "    if (!static_cast<$className*>(thisObject)->allowsAccessFrom(exec))\n");
1470                             } else {
1471                                 push(@implContent, "    if (!allowsAccessFromFrame(exec, static_cast<$className*>(thisObject)->impl()->frame()))\n");
1472                             }
1473                             push(@implContent, "        return;\n");
1474                         }
1475
1476                         if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"} || $attribute->signature->extendedAttributes->{"CustomSetter"} || $attribute->signature->extendedAttributes->{"JSCCustomSetter"}) {
1477                             push(@implContent, "    static_cast<$className*>(thisObject)->set$implSetterFunctionName(exec, value);\n");
1478                         } elsif ($type eq "EventListener") {
1479                             $implIncludes{"JSEventListener.h"} = 1;
1480                             push(@implContent, "    UNUSED_PARAM(exec);\n");
1481                             push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(thisObject)->impl());\n");
1482                             push(@implContent, "    imp->set$implSetterFunctionName(createJSAttributeEventListener(exec, value, thisObject));\n");
1483                         } elsif ($attribute->signature->type =~ /Constructor$/) {
1484                             my $constructorType = $attribute->signature->type;
1485                             $constructorType =~ s/Constructor$//;
1486                             $implIncludes{"JS" . $constructorType . ".h"} = 1;
1487                             push(@implContent, "    // Shadowing a built-in constructor\n");
1488                             push(@implContent, "    static_cast<$className*>(thisObject)->putDirect(Identifier(exec, \"$name\"), value);\n");
1489                         } elsif ($attribute->signature->extendedAttributes->{"Replaceable"}) {
1490                             push(@implContent, "    // Shadowing a built-in object\n");
1491                             push(@implContent, "    static_cast<$className*>(thisObject)->putDirect(Identifier(exec, \"$name\"), value);\n");
1492                         } else {
1493                             push(@implContent, "    $className* castedThisObj = static_cast<$className*>(thisObject);\n");
1494                             push(@implContent, "    $implType* imp = static_cast<$implType*>(castedThisObj->impl());\n");
1495                             if ($podType) {
1496                                 push(@implContent, "    $podType podImp(*imp);\n");
1497                                 if ($podType eq "float") { # Special case for JSSVGNumber
1498                                     push(@implContent, "    podImp = " . JSValueToNative($attribute->signature, "value") . ";\n");
1499                                 } else {
1500                                     push(@implContent, "    podImp.set$implSetterFunctionName(" . JSValueToNative($attribute->signature, "value") . ");\n");
1501                                 }
1502                                 push(@implContent, "    imp->commitChange(podImp, castedThisObj);\n");
1503                             } else {
1504                                 my $nativeValue = JSValueToNative($attribute->signature, "value");
1505                                 push(@implContent, "    ExceptionCode ec = 0;\n") if @{$attribute->setterExceptions};
1506                                 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
1507                                 my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
1508                                 if ($reflect || $reflectURL) {
1509                                     my $contentAttributeName = (($reflect || $reflectURL) eq "1") ? $name : ($reflect || $reflectURL);
1510                                     my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
1511                                     $implIncludes{"${namespace}.h"} = 1;
1512                                     push(@implContent, "    imp->setAttribute(${namespace}::${contentAttributeName}Attr, $nativeValue");
1513                                 } else {
1514                                     push(@implContent, "    imp->set$implSetterFunctionName($nativeValue");
1515                                 }
1516                                 push(@implContent, ", ec") if @{$attribute->setterExceptions};
1517                                 push(@implContent, ");\n");
1518                                 push(@implContent, "    setDOMException(exec, ec);\n") if @{$attribute->setterExceptions};
1519                                 if (IsSVGTypeNeedingContextParameter($implClassName)) {
1520                                     push(@implContent, "    JSSVGContextCache::propagateSVGDOMChange(castedThisObj, imp->associatedAttributeName());\n");
1521                                 }
1522                             }
1523                         }
1524                         
1525                         push(@implContent, "}\n\n");
1526                     }
1527                 }
1528             }
1529         }
1530     }
1531
1532     if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) && !$dataNode->extendedAttributes->{"CustomGetPropertyNames"}) {
1533         push(@implContent, "void ${className}::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)\n");
1534         push(@implContent, "{\n");
1535         if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
1536             push(@implContent, "    for (unsigned i = 0; i < static_cast<${implClassName}*>(impl())->length(); ++i)\n");
1537             push(@implContent, "        propertyNames.add(Identifier::from(exec, i));\n");
1538         }
1539         push(@implContent, "     Base::getOwnPropertyNames(exec, propertyNames, mode);\n");
1540         push(@implContent, "}\n\n");
1541     }
1542
1543     if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
1544         push(@implContent, "JSValue ${className}::getConstructor(ExecState* exec, JSGlobalObject* globalObject)\n{\n");
1545         push(@implContent, "    return getDOMConstructor<${className}Constructor>(exec, static_cast<JSDOMGlobalObject*>(globalObject));\n");
1546         push(@implContent, "}\n\n");
1547     }
1548
1549     # Functions
1550     if ($numFunctions > 0) {
1551         foreach my $function (@{$dataNode->functions}) {
1552             AddIncludesForType($function->signature->type);
1553
1554             my $functionName = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($function->signature->name);
1555             my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementationFunction"} || $codeGenerator->WK_lcfirst($function->signature->name);
1556
1557             push(@implContent, "JSValue JSC_HOST_CALL ${functionName}(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)\n");
1558             push(@implContent, "{\n");
1559             push(@implContent, "    UNUSED_PARAM(args);\n");
1560
1561             $implIncludes{"<runtime/Error.h>"} = 1;
1562
1563             if ($interfaceName eq "DOMWindow") {
1564                 push(@implContent, "    $className* castedThisObj = toJSDOMWindow(thisValue.toThisObject(exec));\n");
1565                 push(@implContent, "    if (!castedThisObj)\n");
1566                 push(@implContent, "        return throwError(exec, TypeError);\n");
1567             } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
1568                 push(@implContent, "    $className* castedThisObj = to${className}(thisValue.toThisObject(exec));\n");
1569                 push(@implContent, "    if (!castedThisObj)\n");
1570                 push(@implContent, "        return throwError(exec, TypeError);\n");
1571             } else {
1572                 push(@implContent, "    if (!thisValue.inherits(&${className}::s_info))\n");
1573                 push(@implContent, "        return throwError(exec, TypeError);\n");
1574                 push(@implContent, "    $className* castedThisObj = static_cast<$className*>(asObject(thisValue));\n");
1575             }
1576
1577             if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && 
1578                 !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
1579                 push(@implContent, "    if (!castedThisObj->allowsAccessFrom(exec))\n");
1580                 push(@implContent, "        return jsUndefined();\n");
1581             }
1582
1583             # Special case for JSSVGLengthList / JSSVGTransformList / JSSVGPointList / JSSVGNumberList
1584             # Instead of having JSSVG*Custom.cpp implementations for the SVGList interface for all of these
1585             # classes, we directly forward the calls to JSSVGPODListCustom, which centralizes the otherwise
1586             # duplicated code for the JSSVG*List classes mentioned above.
1587             my $svgPODListType;
1588             if ($implClassName =~ /SVG.*List/) {
1589                 $svgPODListType = $implClassName;
1590                 $svgPODListType =~ s/List$//;
1591                 $svgPODListType = "" unless $codeGenerator->IsPodType($svgPODListType);
1592                 
1593                 # Ignore additional (non-SVGList) SVGTransformList methods, that are not handled through JSSVGPODListCustom
1594                 $svgPODListType = "" if $functionImplementationName =~ /createSVGTransformFromMatrix/;
1595                 $svgPODListType = "" if $functionImplementationName =~ /consolidate/;
1596             }
1597
1598             if ($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"JSCCustom"}) {
1599                 push(@implContent, "    return castedThisObj->" . $functionImplementationName . "(exec, args);\n");
1600             } elsif ($svgPODListType) {
1601                 $implIncludes{"JS${svgPODListType}.h"} = 1;
1602                 $implIncludes{"JSSVGPODListCustom.h"} = 1;
1603                 push(@implContent, "    return JSSVGPODListCustom::$functionImplementationName<$className, " . GetNativeType($svgPODListType)
1604                                  . ">(castedThisObj, exec, args, to" . $svgPODListType . ");\n");
1605             } else {
1606                 push(@implContent, "    $implType* imp = static_cast<$implType*>(castedThisObj->impl());\n");
1607                 push(@implContent, "    $podType podImp(*imp);\n") if $podType;
1608
1609                 my $numParameters = @{$function->parameters};
1610
1611                 if ($function->signature->extendedAttributes->{"RequiresAllArguments"}) {
1612                         push(@implContent, "    if (args.size() < $numParameters)\n");
1613                         push(@implContent, "        return jsUndefined();\n");
1614                 }
1615
1616                 if (@{$function->raisesExceptions}) {
1617                     push(@implContent, "    ExceptionCode ec = 0;\n");
1618                 }
1619
1620                 if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) {
1621                     push(@implContent, "    if (!checkNodeSecurity(exec, imp->getSVGDocument(" . (@{$function->raisesExceptions} ? "ec" : "") .")))\n");
1622                     push(@implContent, "        return jsUndefined();\n");
1623                     $implIncludes{"JSDOMBinding.h"} = 1;
1624                 }
1625
1626                 my $paramIndex = 0;
1627                 my $functionString = ($podType ? "podImp." : "imp->") . $functionImplementationName . "(";
1628
1629                 my $hasOptionalArguments = 0;
1630
1631                 if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
1632                     push(@implContent, "    ScriptCallStack callStack(exec, args, $numParameters);\n");
1633                     $implIncludes{"ScriptCallStack.h"} = 1;
1634                 }
1635
1636                 foreach my $parameter (@{$function->parameters}) {
1637                     if (!$hasOptionalArguments && $parameter->extendedAttributes->{"Optional"}) {
1638                         push(@implContent, "\n    int argsCount = args.size();\n");
1639                         $hasOptionalArguments = 1;
1640                     }
1641
1642                     if ($hasOptionalArguments) {
1643                         push(@implContent, "    if (argsCount < " . ($paramIndex + 1) . ") {\n");
1644                         GenerateImplementationFunctionCall($function, $functionString, $paramIndex, "    " x 2, $podType, $implClassName);
1645                         push(@implContent, "    }\n\n");
1646                     }
1647
1648                     my $name = $parameter->name;
1649                     
1650                     if ($parameter->type eq "XPathNSResolver") {
1651                         push(@implContent, "    RefPtr<XPathNSResolver> customResolver;\n");
1652                         push(@implContent, "    XPathNSResolver* resolver = toXPathNSResolver(args.at($paramIndex));\n");
1653                         push(@implContent, "    if (!resolver) {\n");
1654                         push(@implContent, "        customResolver = JSCustomXPathNSResolver::create(exec, args.at($paramIndex));\n");
1655                         push(@implContent, "        if (exec->hadException())\n");
1656                         push(@implContent, "            return jsUndefined();\n");
1657                         push(@implContent, "        resolver = customResolver.get();\n");
1658                         push(@implContent, "    }\n");
1659                     } else {
1660                         push(@implContent, "    " . GetNativeTypeFromSignature($parameter) . " $name = " . JSValueToNative($parameter, "args.at($paramIndex)") . ";\n");
1661
1662                         # If a parameter is "an index" and it's negative it should throw an INDEX_SIZE_ERR exception.
1663                         # But this needs to be done in the bindings, because the type is unsigned and the fact that it
1664                         # was negative will be lost by the time we're inside the DOM.
1665                         if ($parameter->extendedAttributes->{"IsIndex"}) {
1666                             $implIncludes{"ExceptionCode.h"} = 1;
1667                             push(@implContent, "    if ($name < 0) {\n");
1668                             push(@implContent, "        setDOMException(exec, INDEX_SIZE_ERR);\n");
1669                             push(@implContent, "        return jsUndefined();\n");
1670                             push(@implContent, "    }\n");
1671                         }
1672                     }
1673
1674                     $functionString .= ", " if $paramIndex;
1675
1676                     if ($parameter->type eq "NodeFilter") {
1677                         $functionString .= "$name.get()";
1678                     } else {
1679                         $functionString .= $name;
1680                     }
1681                     $paramIndex++;
1682                 }
1683
1684                 if ($function->signature->extendedAttributes->{"NeedsUserGestureCheck"}) {
1685                     $functionString .= ", " if $paramIndex;
1686                     $functionString .= "processingUserGesture(exec)";
1687                     $paramIndex++;
1688                 }
1689
1690                 push(@implContent, "\n");
1691                 GenerateImplementationFunctionCall($function, $functionString, $paramIndex, "    ", $podType, $implClassName);
1692             }
1693             push(@implContent, "}\n\n");
1694         }
1695     }
1696
1697     if ($numConstants > 0) {
1698         push(@implContent, "// Constant getters\n\n");
1699
1700         foreach my $constant (@{$dataNode->constants}) {
1701             my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);
1702
1703             # FIXME: this casts into int to match our previous behavior which turned 0xFFFFFFFF in -1 for NodeFilter.SHOW_ALL
1704             push(@implContent, "JSValue ${getter}(ExecState* exec, const Identifier&, const PropertySlot&)\n");
1705             push(@implContent, "{\n");
1706             push(@implContent, "    return jsNumber(exec, static_cast<int>(" . $constant->value . "));\n");
1707             push(@implContent, "}\n\n");
1708         }
1709     }
1710
1711     if ($dataNode->extendedAttributes->{"HasIndexGetter"}) {
1712         push(@implContent, "\nJSValue ${className}::indexGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)\n");
1713         push(@implContent, "{\n");
1714         push(@implContent, "    ${className}* thisObj = static_cast<$className*>(asObject(slot.slotBase()));\n");
1715         if (IndexGetterReturnsStrings($implClassName)) {
1716             $implIncludes{"KURL.h"} = 1;
1717             push(@implContent, "    return jsStringOrNull(exec, thisObj->impl()->item(slot.index()));\n");
1718         } else {
1719             push(@implContent, "    return toJS(exec, thisObj->globalObject(), static_cast<$implClassName*>(thisObj->impl())->item(slot.index()));\n");
1720         }
1721         push(@implContent, "}\n");
1722         if ($interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") {
1723             $implIncludes{"JSNode.h"} = 1;
1724             $implIncludes{"Node.h"} = 1;
1725         }
1726     }
1727     
1728     if ($dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
1729         push(@implContent, "\nJSValue ${className}::getByIndex(ExecState* exec, unsigned index)\n");
1730         push(@implContent, "{\n");
1731         push(@implContent, "    return jsNumber(exec, static_cast<$implClassName*>(impl())->item(index));\n");
1732         push(@implContent, "}\n");
1733         if ($interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") {
1734             $implIncludes{"JSNode.h"} = 1;
1735             $implIncludes{"Node.h"} = 1;
1736         }
1737     }
1738
1739     if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateToJS"}) and !$dataNode->extendedAttributes->{"CustomToJS"}) {
1740         if ($podType) {
1741             push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, JSSVGPODTypeWrapper<$podType>* object, SVGElement* context)\n");
1742         } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
1743             push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* object, SVGElement* context)\n");
1744         } else {
1745             push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* object)\n");
1746         }
1747         push(@implContent, "{\n");
1748         if ($podType) {
1749             push(@implContent, "    return getDOMObjectWrapper<$className, JSSVGPODTypeWrapper<$podType> >(exec, globalObject, object, context);\n");
1750         } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
1751             push(@implContent, "    return getDOMObjectWrapper<$className>(exec, globalObject, object, context);\n");
1752         } else {
1753             push(@implContent, "    return getDOMObjectWrapper<$className>(exec, globalObject, object);\n");
1754         }
1755         push(@implContent, "}\n");
1756     }
1757
1758     if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateNativeConverter"}) and !$dataNode->extendedAttributes->{"CustomNativeConverter"}) {
1759         if ($podType) {
1760             push(@implContent, "$podType to${interfaceName}(JSC::JSValue value)\n");
1761         } else {
1762             push(@implContent, "$implClassName* to${interfaceName}(JSC::JSValue value)\n");
1763         }
1764
1765         push(@implContent, "{\n");
1766
1767         push(@implContent, "    return value.inherits(&${className}::s_info) ? " . ($podType ? "($podType) *" : "") . "static_cast<$className*>(asObject(value))->impl() : ");
1768         if ($podType and $podType ne "float") {
1769             push(@implContent, "$podType();\n}\n");
1770         } else {
1771             push(@implContent, "0;\n}\n");
1772         }
1773     }
1774
1775     push(@implContent, "\n}\n");
1776
1777     push(@implContent, "\n#endif // ${conditionalString}\n") if $conditional;
1778 }
1779
1780 sub GenerateImplementationFunctionCall()
1781 {
1782     my $function = shift;
1783     my $functionString = shift;
1784     my $paramIndex = shift;
1785     my $indent = shift;
1786     my $podType = shift;
1787     my $implClassName = shift;
1788
1789     if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
1790         $functionString .= ", " if $paramIndex;
1791         ++$paramIndex;
1792         $functionString .= "&callStack";
1793     }
1794
1795     if (@{$function->raisesExceptions}) {
1796         $functionString .= ", " if $paramIndex;
1797         $functionString .= "ec";
1798     }
1799     $functionString .= ")";
1800
1801     if ($function->signature->type eq "void") {
1802         push(@implContent, $indent . "$functionString;\n");
1803         push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions};
1804         push(@implContent, $indent . "imp->commitChange(podImp, castedThisObj);\n") if $podType;
1805         push(@implContent, $indent . "return jsUndefined();\n");
1806     } else {
1807         push(@implContent, "\n" . $indent . "JSC::JSValue result = " . NativeToJSValue($function->signature, 1, $implClassName, "", $functionString, "castedThisObj") . ";\n");
1808         push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions};
1809
1810         if ($podType and not $function->signature->extendedAttributes->{"Immutable"}) {
1811             # Immutable methods do not commit changes back to the instance, thus producing
1812             # a new instance rather than mutating existing one.
1813             push(@implContent, $indent . "imp->commitChange(podImp, castedThisObj);\n");
1814         }
1815
1816         push(@implContent, $indent . "return result;\n");
1817     }
1818 }
1819
1820 sub GetNativeTypeFromSignature
1821 {
1822     my $signature = shift;
1823     my $type = $codeGenerator->StripModule($signature->type);
1824
1825     if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) {
1826         # Special-case index arguments because we need to check that they aren't < 0.
1827         return "int";
1828     }
1829
1830     return GetNativeType($type);
1831 }
1832
1833 my %nativeType = (
1834     "CompareHow" => "Range::CompareHow",
1835     "DOMString" => "const UString&",
1836     "NodeFilter" => "RefPtr<NodeFilter>",
1837     "SVGAngle" => "SVGAngle",
1838     "SVGLength" => "SVGLength",
1839     "SVGMatrix" => "AffineTransform",
1840     "SVGNumber" => "float",
1841     "SVGPaintType" => "SVGPaint::SVGPaintType",
1842     "SVGPreserveAspectRatio" => "SVGPreserveAspectRatio",
1843     "SVGPoint" => "FloatPoint",
1844     "SVGRect" => "FloatRect",
1845     "SVGTransform" => "SVGTransform",
1846     "boolean" => "bool",
1847     "double" => "double",
1848     "float" => "float",
1849     "long" => "int",
1850     "unsigned long" => "unsigned",
1851     "unsigned short" => "unsigned short",
1852     "long long" => "long long",
1853     "unsigned long long" => "unsigned long long",
1854 );
1855
1856 sub GetNativeType
1857 {
1858     my $type = shift;
1859
1860     return $nativeType{$type} if exists $nativeType{$type};
1861
1862     # For all other types, the native type is a pointer with same type name as the IDL type.
1863     return "${type}*";
1864 }
1865
1866 sub JSValueToNative
1867 {
1868     my $signature = shift;
1869     my $value = shift;
1870
1871     my $type = $codeGenerator->StripModule($signature->type);
1872
1873     return "$value.toBoolean(exec)" if $type eq "boolean";
1874     return "$value.toNumber(exec)" if $type eq "double";
1875     return "$value.toFloat(exec)" if $type eq "float" or $type eq "SVGNumber";
1876     return "$value.toInt32(exec)" if $type eq "unsigned long" or $type eq "long" or $type eq "unsigned short";
1877     return "static_cast<$type>($value.toInteger(exec))" if $type eq "long long" or $type eq "unsigned long long";
1878
1879     return "valueToDate(exec, $value)" if $type eq "Date";
1880     return "static_cast<Range::CompareHow>($value.toInt32(exec))" if $type eq "CompareHow";
1881     return "static_cast<SVGPaint::SVGPaintType>($value.toInt32(exec))" if $type eq "SVGPaintType";
1882
1883     if ($type eq "DOMString") {
1884         return "valueToStringWithNullCheck(exec, $value)" if $signature->extendedAttributes->{"ConvertNullToNullString"};
1885         return "valueToStringWithUndefinedOrNullCheck(exec, $value)" if $signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"};
1886         return "$value.toString(exec)";
1887     }
1888
1889     if ($type eq "SerializedScriptValue" or $type eq "any") {
1890         $implIncludes{"SerializedScriptValue.h"} = 1;
1891         return "SerializedScriptValue::create(exec, $value)";
1892     }
1893
1894     $implIncludes{"FloatPoint.h"} = 1 if $type eq "SVGPoint";
1895     $implIncludes{"FloatRect.h"} = 1 if $type eq "SVGRect";
1896     $implIncludes{"HTMLOptionElement.h"} = 1 if $type eq "HTMLOptionElement";
1897     $implIncludes{"JSCustomVoidCallback.h"} = 1 if $type eq "VoidCallback";
1898     $implIncludes{"Event.h"} = 1 if $type eq "Event";
1899
1900     # Default, assume autogenerated type conversion routines
1901     $implIncludes{"JS$type.h"} = 1;
1902     return "to$type($value)";
1903 }
1904
1905 sub NativeToJSValue
1906 {
1907     my $signature = shift;
1908     my $inFunctionCall = shift;
1909     my $implClassName = shift;
1910     my $implClassNameForValueConversion = shift;
1911     my $value = shift;
1912     my $thisValue = shift;
1913
1914     my $type = $codeGenerator->StripModule($signature->type);
1915
1916     return "jsBoolean($value)" if $type eq "boolean";
1917
1918     # Need to check Date type before IsPrimitiveType().
1919     if ($type eq "Date") {
1920         return "jsDateOrNull(exec, $value)";
1921     }
1922     if ($codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType" or $type eq "DOMTimeStamp") {
1923         $implIncludes{"<runtime/JSNumberCell.h>"} = 1;
1924         return "jsNumber(exec, $value)";
1925     }
1926
1927     if ($codeGenerator->IsStringType($type)) {
1928         $implIncludes{"KURL.h"} = 1;
1929         my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"};
1930         if (defined $conv) {
1931             return "jsStringOrNull(exec, $value)" if $conv eq "Null";
1932             return "jsStringOrUndefined(exec, $value)" if $conv eq "Undefined";
1933             return "jsStringOrFalse(exec, $value)" if $conv eq "False";
1934
1935             die "Unknown value for ConvertNullStringTo extended attribute";
1936         }
1937         $implIncludes{"<runtime/JSString.h>"} = 1;
1938         return "jsString(exec, $value)";
1939     }
1940     
1941     my $globalObject = "$thisValue->globalObject()";
1942     if ($codeGenerator->IsPodType($type)) {
1943         $implIncludes{"JS$type.h"} = 1;
1944
1945         my $nativeType = GetNativeType($type);
1946
1947         my $getter = $value;
1948         $getter =~ s/imp->//;
1949         $getter =~ s/\(\)//;
1950
1951         my $setter = "set" . $codeGenerator->WK_ucfirst($getter);
1952
1953         # Function calls will never return 'modifyable' POD types (ie. SVGRect getBBox()) - no need to keep track changes to the returned SVGRect
1954         if ($inFunctionCall eq 0
1955             and not $codeGenerator->IsSVGAnimatedType($implClassName)
1956             and $codeGenerator->IsPodTypeWithWriteableProperties($type)
1957             and not defined $signature->extendedAttributes->{"Immutable"}) {
1958             if ($codeGenerator->IsPodType($implClassName)) {
1959                 return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($value, $thisValue->impl()).get(), JSSVGContextCache::svgContextForDOMObject(castedThis))";
1960             } else {
1961                 return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName>::create(imp, &${implClassName}::$getter, &${implClassName}::$setter).get(), imp)";
1962             }
1963         }
1964
1965         if ($implClassNameForValueConversion eq "") {
1966             return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), 0 /* no context on purpose */)";
1967         } else {
1968             return "toJS(exec, $globalObject, JSSVGDynamicPODTypeWrapperCache<$nativeType, $implClassNameForValueConversion>::lookupOrCreateWrapper(imp, &${implClassNameForValueConversion}::$getter, &${implClassNameForValueConversion}::$setter).get(), JSSVGContextCache::svgContextForDOMObject(castedThis));"
1969         }
1970     }
1971
1972     if ($codeGenerator->IsSVGAnimatedType($type)) {
1973         # Some SVGFE*Element.idl use 'operator' as attribute name, rewrite as '_operator' to avoid clashes with C/C++
1974         $value =~ s/operator\(\)/_operator\(\)/ if ($value =~ /operator/);
1975         $value =~ s/\(\)//;
1976         $value .= "Animated()";
1977     }
1978
1979     if ($type eq "CSSStyleDeclaration") {
1980         $implIncludes{"CSSMutableStyleDeclaration.h"} = 1;
1981     }
1982
1983     if ($type eq "NodeList") {
1984         $implIncludes{"NameNodeList.h"} = 1;
1985     }
1986
1987     if ($type eq "DOMObject") {
1988         $implIncludes{"JSCanvasRenderingContext2D.h"} = 1;
1989     } elsif ($type =~ /SVGPathSeg/) {
1990         $implIncludes{"JS$type.h"} = 1;
1991         $joinedName = $type;
1992         $joinedName =~ s/Abs|Rel//;
1993         $implIncludes{"$joinedName.h"} = 1;
1994     } elsif ($type eq "SerializedScriptValue" or $type eq "any") {
1995         $implIncludes{"SerializedScriptValue.h"} = 1;
1996         return "$value ? $value->deserialize(exec, castedThis->globalObject()) : jsNull()";
1997     } else {
1998         # Default, include header with same name.
1999         $implIncludes{"JS$type.h"} = 1;
2000         $implIncludes{"$type.h"} = 1;
2001     }
2002
2003     return $value if $codeGenerator->IsSVGAnimatedType($type);
2004
2005     if (IsSVGTypeNeedingContextParameter($type)) {
2006         my $contextPtr = IsSVGTypeNeedingContextParameter($implClassName) ? "JSSVGContextCache::svgContextForDOMObject(castedThis)" : "imp";
2007         return "toJS(exec, $globalObject, WTF::getPtr($value), $contextPtr)";
2008     }
2009
2010     if ($signature->extendedAttributes->{"ReturnsNew"}) {        
2011         return "toJSNewlyCreated(exec, $globalObject, WTF::getPtr($value))";
2012     }
2013
2014     return "toJS(exec, $globalObject, WTF::getPtr($value))";
2015 }
2016
2017 sub ceilingToPowerOf2
2018 {
2019     my ($size) = @_;
2020
2021     my $powerOf2 = 1;
2022     while ($size > $powerOf2) {
2023         $powerOf2 <<= 1;
2024     }
2025
2026     return $powerOf2;
2027 }
2028
2029 # Internal Helper
2030 sub GenerateHashTable
2031 {
2032     my $object = shift;
2033
2034     my $name = shift;
2035     my $size = shift;
2036     my $keys = shift;
2037     my $specials = shift;
2038     my $value1 = shift;
2039     my $value2 = shift;
2040     my $conditionals = shift;
2041
2042     # Generate size data for two hash tables
2043     # - The 'perfect' size makes a table large enough for perfect hashing
2044     # - The 'compact' size uses the legacy table format for smaller table sizes
2045
2046     # Perfect size
2047     my @hashes = ();
2048     foreach my $key (@{$keys}) {
2049         push @hashes, $object->GenerateHashValue($key);
2050     }
2051
2052     # Compact size
2053     my @table = ();
2054     my @links = ();
2055
2056     my $compactSize = ceilingToPowerOf2($size * 2);
2057
2058     my $maxDepth = 0;
2059     my $collisions = 0;
2060     my $numEntries = $compactSize;
2061
2062     my $i = 0;
2063     foreach (@{$keys}) {
2064         my $depth = 0;
2065         my $h = $object->GenerateHashValue($_) % $numEntries;
2066
2067         while (defined($table[$h])) {
2068             if (defined($links[$h])) {
2069                 $h = $links[$h];
2070                 $depth++;
2071             } else {
2072                 $collisions++;
2073                 $links[$h] = $compactSize;
2074                 $h = $compactSize;
2075                 $compactSize++;
2076             }
2077         }
2078
2079         $table[$h] = $i;
2080
2081         $i++;
2082         $maxDepth = $depth if ($depth > $maxDepth);
2083     }
2084
2085     # Collect hashtable information
2086     my $perfectSize;
2087 tableSizeLoop:
2088     for ($perfectSize = ceilingToPowerOf2(scalar @{$keys}); ; $perfectSize += $perfectSize) {
2089         my @table = ();
2090         my $i = 0;
2091         foreach my $hash (@hashes) {
2092             my $h = $hash % $perfectSize;
2093             next tableSizeLoop if defined $table[$h];
2094             $table[$h] = $i++;
2095         }
2096         last;
2097     }
2098
2099     # Start outputing the hashtables
2100     my $nameEntries = "${name}Values";
2101     $nameEntries =~ s/:/_/g;
2102
2103     if (($name =~ /Prototype/) or ($name =~ /Constructor/)) {
2104         my $type = $name;
2105         my $implClass;
2106
2107         if ($name =~ /Prototype/) {
2108             $type =~ s/Prototype.*//;
2109             $implClass = $type; $implClass =~ s/Wrapper$//;
2110             push(@implContent, "/* Hash table for prototype */\n");
2111         } else {
2112             $type =~ s/Constructor.*//;
2113             $implClass = $type; $implClass =~ s/Constructor$//;
2114             push(@implContent, "/* Hash table for constructor */\n");
2115         }
2116     } else {
2117         push(@implContent, "/* Hash table */\n");
2118     }
2119
2120     # Dump the hash table
2121     my $count = scalar @{$keys} + 1;
2122     push(@implContent, "\nstatic const HashTableValue $nameEntries\[$count\] =\n\{\n");
2123     $i = 0;
2124     foreach my $key (@{$keys}) {
2125         my $conditional;
2126
2127         if ($conditionals) {
2128             $conditional = $conditionals->{$key};
2129         }
2130         if ($conditional) {
2131             my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
2132             push(@implContent, "#if ${conditionalString}\n");
2133         }
2134         push(@implContent, "    { \"$key\", @$specials[$i], (intptr_t)@$value1[$i], (intptr_t)@$value2[$i] },\n");
2135         if ($conditional) {
2136             push(@implContent, "#endif\n");
2137         }
2138         ++$i;
2139     }
2140     push(@implContent, "    { 0, 0, 0, 0 }\n");
2141     push(@implContent, "};\n\n");
2142     my $perfectSizeMask = $perfectSize - 1;
2143     my $compactSizeMask = $numEntries - 1;
2144     push(@implContent, "static JSC_CONST_HASHTABLE HashTable $name =\n");
2145     push(@implContent, "#if ENABLE(PERFECT_HASH_SIZE)\n");
2146     push(@implContent, "    { $perfectSizeMask, $nameEntries, 0 };\n");
2147     push(@implContent, "#else\n");
2148     push(@implContent, "    { $compactSize, $compactSizeMask, $nameEntries, 0 };\n");
2149     push(@implContent, "#endif\n\n");
2150 }
2151
2152 # Internal helper
2153 sub GenerateHashValue
2154 {
2155     my $object = shift;
2156
2157     @chars = split(/ */, $_[0]);
2158
2159     # This hash is designed to work on 16-bit chunks at a time. But since the normal case
2160     # (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they
2161     # were 16-bit chunks, which should give matching results
2162
2163     my $EXP2_32 = 4294967296;
2164
2165     my $hash = 0x9e3779b9;
2166     my $l    = scalar @chars; #I wish this was in Ruby --- Maks
2167     my $rem  = $l & 1;
2168     $l = $l >> 1;
2169
2170     my $s = 0;
2171
2172     # Main loop
2173     for (; $l > 0; $l--) {
2174         $hash   += ord($chars[$s]);
2175         my $tmp = leftShift(ord($chars[$s+1]), 11) ^ $hash;
2176         $hash   = (leftShift($hash, 16)% $EXP2_32) ^ $tmp;
2177         $s += 2;
2178         $hash += $hash >> 11;
2179         $hash %= $EXP2_32;
2180     }
2181
2182     # Handle end case
2183     if ($rem != 0) {
2184         $hash += ord($chars[$s]);
2185         $hash ^= (leftShift($hash, 11)% $EXP2_32);
2186         $hash += $hash >> 17;
2187     }
2188
2189     # Force "avalanching" of final 127 bits
2190     $hash ^= leftShift($hash, 3);
2191     $hash += ($hash >> 5);
2192     $hash = ($hash% $EXP2_32);
2193     $hash ^= (leftShift($hash, 2)% $EXP2_32);
2194     $hash += ($hash >> 15);
2195     $hash = $hash% $EXP2_32;
2196     $hash ^= (leftShift($hash, 10)% $EXP2_32);
2197
2198     # this avoids ever returning a hash code of 0, since that is used to
2199     # signal "hash not computed yet", using a value that is likely to be
2200     # effectively the same as 0 when the low bits are masked
2201     $hash = 0x80000000 if ($hash == 0);
2202
2203     return $hash;
2204 }
2205
2206 # Internal helper
2207 sub WriteData
2208 {
2209     if (defined($IMPL)) {
2210         # Write content to file.
2211         print $IMPL @implContentHeader;
2212
2213         my @includes = ();
2214         foreach my $include (keys %implIncludes) {
2215             my $checkType = $include;
2216             $checkType =~ s/\.h//;
2217             next if $codeGenerator->IsSVGAnimatedType($checkType);
2218
2219             $include = "\"$include\"" unless $include =~ /^["<]/; # "
2220             push @includes, $include;
2221         }
2222         foreach my $include (sort @includes) {
2223             print $IMPL "#include $include\n";
2224         }
2225
2226         print $IMPL @implContent;
2227         close($IMPL);
2228         undef($IMPL);
2229
2230         @implContentHeader = ();
2231         @implContent = ();
2232         %implIncludes = ();
2233     }
2234
2235     if (defined($HEADER)) {
2236         # Write content to file.
2237         print $HEADER @headerContentHeader;
2238
2239         my @includes = ();
2240         foreach my $include (keys %headerIncludes) {
2241             $include = "\"$include\"" unless $include =~ /^["<]/; # "
2242             push @includes, $include;
2243         }
2244         foreach my $include (sort @includes) {
2245             print $HEADER "#include $include\n";
2246         }
2247
2248         print $HEADER @headerContent;
2249         close($HEADER);
2250         undef($HEADER);
2251
2252         @headerContentHeader = ();
2253         @headerContent = ();
2254         %headerIncludes = ();
2255     }
2256
2257     if (defined($DEPS)) {
2258         # Write dependency file.
2259         print $DEPS @depsContent;
2260         close($DEPS);
2261         undef($DEPS);
2262
2263         @depsContent = ();
2264     }
2265 }
2266
2267 sub constructorFor
2268 {
2269     my $className = shift;
2270     my $protoClassName = shift;
2271     my $interfaceName = shift;
2272     my $visibleClassName = shift;
2273     my $canConstruct = shift;
2274     my $constructorClassName = "${className}Constructor";
2275
2276 my $implContent = << "EOF";
2277 class ${constructorClassName} : public DOMConstructorObject {
2278 public:
2279     ${constructorClassName}(ExecState* exec, JSDOMGlobalObject* globalObject)
2280         : DOMConstructorObject(${constructorClassName}::createStructure(globalObject->objectPrototype()), globalObject)
2281     {
2282         putDirect(exec->propertyNames().prototype, ${protoClassName}::self(exec, globalObject), None);
2283     }
2284     virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
2285     virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
2286     virtual const ClassInfo* classInfo() const { return &s_info; }
2287     static const ClassInfo s_info;
2288
2289     static PassRefPtr<Structure> createStructure(JSValue proto) 
2290     { 
2291         return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); 
2292     }
2293     
2294 protected:
2295     static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | DOMConstructorObject::StructureFlags;
2296 EOF
2297
2298     if ($canConstruct) {
2299 $implContent .= << "EOF";
2300     static JSObject* construct${interfaceName}(ExecState* exec, JSObject* constructor, const ArgList&)
2301     {
2302         return asObject(toJS(exec, static_cast<${constructorClassName}*>(constructor)->globalObject(), ${interfaceName}::create()));
2303     }
2304     virtual ConstructType getConstructData(ConstructData& constructData)
2305     {
2306         constructData.native.function = construct${interfaceName};
2307         return ConstructTypeHost;
2308     }
2309 EOF
2310     }
2311
2312 $implContent .= << "EOF";
2313 };
2314
2315 const ClassInfo ${constructorClassName}::s_info = { "${visibleClassName}Constructor", 0, &${constructorClassName}Table, 0 };
2316
2317 bool ${constructorClassName}::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
2318 {
2319     return getStaticValueSlot<${constructorClassName}, DOMObject>(exec, &${constructorClassName}Table, this, propertyName, slot);
2320 }
2321
2322 bool ${constructorClassName}::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
2323 {
2324     return getStaticValueDescriptor<${constructorClassName}, DOMObject>(exec, &${constructorClassName}Table, this, propertyName, descriptor);
2325 }
2326
2327 EOF
2328
2329     $implJSCInclude{"JSNumberCell.h"} = 1; # FIXME: What is this for?
2330
2331     return $implContent;
2332 }
2333
2334 1;