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