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