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