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