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