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