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