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