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