Make [CanBeConstructed] IDL redundant
[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 ($type eq "DOMString[]") {
295         # FIXME: Add proper support for T[], T[]?, sequence<T>
296         $includesRef->{"JSDOMStringList.h"} = 1;
297     } elsif ($isCallback) {
298         $includesRef->{"JS${type}.h"} = 1;
299     } else {
300         # default, include the same named file
301         $includesRef->{"${type}.h"} = 1;
302     }
303 }
304
305 # FIXME: This method will go away once all SVG animated properties are converted to the new scheme.
306 sub AddIncludesForSVGAnimatedType
307 {
308     my $type = shift;
309     $type =~ s/SVGAnimated//;
310
311     if ($type eq "Point" or $type eq "Rect") {
312         $implIncludes{"Float$type.h"} = 1;
313     } elsif ($type eq "String") {
314         $implIncludes{"PlatformString.h"} = 1;
315     }
316 }
317
318 sub AddToImplIncludes
319 {
320     my $header = shift;
321     my $conditional = shift;
322
323     if (not $conditional) {
324         $implIncludes{$header} = 1;
325     } elsif (not exists($implIncludes{$header})) {
326         $implIncludes{$header} = $conditional;
327     } else {
328         my $oldValue = $implIncludes{$header};
329         if ($oldValue ne 1) {
330             my %newValue = ();
331             $newValue{$conditional} = 1;
332             foreach my $condition (split(/\|/, $oldValue)) {
333                 $newValue{$condition} = 1;
334             }
335             $implIncludes{$header} = join("|", sort keys %newValue);
336         }
337     }
338 }
339
340 sub IsScriptProfileType
341 {
342     my $type = shift;
343     return 1 if ($type eq "ScriptProfileNode");
344     return 0;
345 }
346
347 sub AddTypedefForScriptProfileType
348 {
349     my $type = shift;
350     (my $jscType = $type) =~ s/Script//;
351
352     push(@headerContent, "typedef JSC::$jscType $type;\n\n");
353 }
354
355 sub AddClassForwardIfNeeded
356 {
357     my $implClassName = shift;
358
359     # SVGAnimatedLength/Number/etc. are typedefs to SVGAnimatedTemplate, so don't use class forwards for them!
360     unless ($codeGenerator->IsSVGAnimatedType($implClassName) or IsScriptProfileType($implClassName)) {
361         push(@headerContent, "class $implClassName;\n\n");
362     # ScriptProfile and ScriptProfileNode are typedefs to JSC::Profile and JSC::ProfileNode.
363     } elsif (IsScriptProfileType($implClassName)) {
364         $headerIncludes{"<profiler/ProfileNode.h>"} = 1;
365         AddTypedefForScriptProfileType($implClassName);
366     }
367 }
368
369 sub HashValueForClassAndName
370 {
371     my $class = shift;
372     my $name = shift;
373
374     # SVG Filter enums live in WebCore namespace (platform/graphics/)
375     if ($class =~ /^SVGFE*/ or $class =~ /^SVGComponentTransferFunctionElement$/) {
376         return "WebCore::$name";
377     }
378
379     return "${class}::$name";
380 }
381
382 sub hashTableAccessor
383 {
384     my $noStaticTables = shift;
385     my $className = shift;
386     if ($noStaticTables) {
387         return "get${className}Table(exec)";
388     } else {
389         return "&${className}Table";
390     }
391 }
392
393 sub prototypeHashTableAccessor
394 {
395     my $noStaticTables = shift;
396     my $className = shift;
397     if ($noStaticTables) {
398         return "get${className}PrototypeTable(exec)";
399     } else {
400         return "&${className}PrototypeTable";
401     }
402 }
403
404 sub GenerateConditionalStringFromAttributeValue
405 {
406     my $conditional = shift;
407     if ($conditional =~ /&/) {
408         return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
409     } elsif ($conditional =~ /\|/) {
410         return "ENABLE(" . join(") || ENABLE(", split(/\|/, $conditional)) . ")";
411     } else {
412         return "ENABLE(" . $conditional . ")";
413     }
414 }
415
416 sub GenerateConditionalString
417 {
418     my $node = shift;
419     my $conditional = $node->extendedAttributes->{"Conditional"};
420     if ($conditional) {
421         return GenerateConditionalStringFromAttributeValue($conditional);
422     } else {
423         return "";
424     }
425 }
426
427 sub GenerateGetOwnPropertySlotBody
428 {
429     my ($dataNode, $interfaceName, $className, $implClassName, $hasAttributes, $inlined) = @_;
430
431     my $namespaceMaybe = ($inlined ? "JSC::" : "");
432
433     my @getOwnPropertySlotImpl = ();
434
435     if ($interfaceName eq "NamedNodeMap" or $interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") {
436         push(@getOwnPropertySlotImpl, "    ${namespaceMaybe}JSValue proto = thisObject->prototype();\n");
437         push(@getOwnPropertySlotImpl, "    if (proto.isObject() && static_cast<${namespaceMaybe}JSObject*>(asObject(proto))->hasProperty(exec, propertyName))\n");
438         push(@getOwnPropertySlotImpl, "        return false;\n\n");
439     }
440
441     my $manualLookupGetterGeneration = sub {
442         my $requiresManualLookup = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasNameGetter"};
443         if ($requiresManualLookup) {
444             push(@getOwnPropertySlotImpl, "    const ${namespaceMaybe}HashEntry* entry = ${className}Table.entry(exec, propertyName);\n");
445             push(@getOwnPropertySlotImpl, "    if (entry) {\n");
446             push(@getOwnPropertySlotImpl, "        slot.setCustom(thisObject, entry->propertyGetter());\n");
447             push(@getOwnPropertySlotImpl, "        return true;\n");
448             push(@getOwnPropertySlotImpl, "    }\n");
449         }
450     };
451
452     if (!$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
453         &$manualLookupGetterGeneration();
454     }
455
456     if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
457         push(@getOwnPropertySlotImpl, "    bool ok;\n");
458         push(@getOwnPropertySlotImpl, "    unsigned index = propertyName.toUInt32(ok);\n");
459
460         # If the item function returns a string then we let the ConvertNullStringTo handle the cases
461         # where the index is out of range.
462         if (IndexGetterReturnsStrings($implClassName)) {
463             push(@getOwnPropertySlotImpl, "    if (ok) {\n");
464         } else {
465             push(@getOwnPropertySlotImpl, "    if (ok && index < static_cast<$implClassName*>(thisObject->impl())->length()) {\n");
466         }
467         if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
468             push(@getOwnPropertySlotImpl, "        slot.setValue(thisObject->getByIndex(exec, index));\n");
469         } else {
470             push(@getOwnPropertySlotImpl, "        slot.setCustomIndex(thisObject, index, indexGetter);\n");
471         }
472         push(@getOwnPropertySlotImpl, "        return true;\n");
473         push(@getOwnPropertySlotImpl, "    }\n");
474     }
475
476     if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
477         push(@getOwnPropertySlotImpl, "    if (canGetItemsForName(exec, static_cast<$implClassName*>(thisObject->impl()), propertyName)) {\n");
478         push(@getOwnPropertySlotImpl, "        slot.setCustom(thisObject, thisObject->nameGetter);\n");
479         push(@getOwnPropertySlotImpl, "        return true;\n");
480         push(@getOwnPropertySlotImpl, "    }\n");
481         if ($inlined) {
482             $headerIncludes{"wtf/text/AtomicString.h"} = 1;
483         } else {
484             $implIncludes{"wtf/text/AtomicString.h"} = 1;
485         }
486     }
487
488     if ($dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
489         &$manualLookupGetterGeneration();
490     }
491
492     if ($dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}) {
493         push(@getOwnPropertySlotImpl, "    if (thisObject->getOwnPropertySlotDelegate(exec, propertyName, slot))\n");
494         push(@getOwnPropertySlotImpl, "        return true;\n");
495     }
496
497     if ($hasAttributes) {
498         if ($inlined) {
499             die "Cannot inline if NoStaticTables is set." if ($dataNode->extendedAttributes->{"NoStaticTables"});
500             push(@getOwnPropertySlotImpl, "    return ${namespaceMaybe}getStaticValueSlot<$className, Base>(exec, s_info.staticPropHashTable, thisObject, propertyName, slot);\n");
501         } else {
502             push(@getOwnPropertySlotImpl, "    return ${namespaceMaybe}getStaticValueSlot<$className, Base>(exec, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", thisObject, propertyName, slot);\n");
503         }
504     } else {
505         push(@getOwnPropertySlotImpl, "    return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);\n");
506     }
507
508     return @getOwnPropertySlotImpl;
509 }
510
511 sub GenerateGetOwnPropertyDescriptorBody
512 {
513     my ($dataNode, $interfaceName, $className, $implClassName, $hasAttributes, $inlined) = @_;
514     
515     my $namespaceMaybe = ($inlined ? "JSC::" : "");
516     
517     my @getOwnPropertyDescriptorImpl = ();
518     if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) {
519         if ($interfaceName eq "DOMWindow") {
520             push(@implContent, "    if (!static_cast<$className*>(thisObject)->allowsAccessFrom(exec))\n");
521         } else {
522             push(@implContent, "    if (!allowsAccessFromFrame(exec, static_cast<$className*>(thisObject)->impl()->frame()))\n");
523         }
524         push(@implContent, "        return false;\n");
525     }
526     
527     if ($interfaceName eq "NamedNodeMap" or $interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") {
528         push(@getOwnPropertyDescriptorImpl, "    ${namespaceMaybe}JSValue proto = prototype();\n");
529         push(@getOwnPropertyDescriptorImpl, "    if (proto.isObject() && static_cast<${namespaceMaybe}JSObject*>(asObject(proto))->hasProperty(exec, propertyName))\n");
530         push(@getOwnPropertyDescriptorImpl, "        return false;\n\n");
531     }
532     
533     my $manualLookupGetterGeneration = sub {
534         my $requiresManualLookup = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasNameGetter"};
535         if ($requiresManualLookup) {
536             push(@getOwnPropertyDescriptorImpl, "    const ${namespaceMaybe}HashEntry* entry = ${className}Table.entry(exec, propertyName);\n");
537             push(@getOwnPropertyDescriptorImpl, "    if (entry) {\n");
538             push(@getOwnPropertyDescriptorImpl, "        PropertySlot slot;\n");
539             push(@getOwnPropertyDescriptorImpl, "        slot.setCustom(this, entry->propertyGetter());\n");
540             push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());\n");
541             push(@getOwnPropertyDescriptorImpl, "        return true;\n");
542             push(@getOwnPropertyDescriptorImpl, "    }\n");
543         }
544     };
545     
546     if (!$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
547         &$manualLookupGetterGeneration();
548     }
549     
550     if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
551         push(@getOwnPropertyDescriptorImpl, "    bool ok;\n");
552         push(@getOwnPropertyDescriptorImpl, "    unsigned index = propertyName.toUInt32(ok);\n");
553         push(@getOwnPropertyDescriptorImpl, "    if (ok && index < static_cast<$implClassName*>(impl())->length()) {\n");
554         if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
555             # Assume that if there's a setter, the index will be writable
556             if ($dataNode->extendedAttributes->{"HasIndexSetter"} || $dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
557                 push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(getByIndex(exec, index), ${namespaceMaybe}DontDelete);\n");
558             } else {
559                 push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(getByIndex(exec, index), ${namespaceMaybe}DontDelete | ${namespaceMaybe}ReadOnly);\n");
560             }
561         } else {
562             push(@getOwnPropertyDescriptorImpl, "        ${namespaceMaybe}PropertySlot slot;\n");
563             push(@getOwnPropertyDescriptorImpl, "        slot.setCustomIndex(this, index, indexGetter);\n");
564             # Assume that if there's a setter, the index will be writable
565             if ($dataNode->extendedAttributes->{"HasIndexSetter"} || $dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
566                 push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(slot.getValue(exec, propertyName), ${namespaceMaybe}DontDelete);\n");
567             } else {
568                 push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(slot.getValue(exec, propertyName), ${namespaceMaybe}DontDelete | ${namespaceMaybe}ReadOnly);\n");
569             }
570         }
571         push(@getOwnPropertyDescriptorImpl, "        return true;\n");
572         push(@getOwnPropertyDescriptorImpl, "    }\n");
573     }
574     
575     if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
576         push(@getOwnPropertyDescriptorImpl, "    if (canGetItemsForName(exec, static_cast<$implClassName*>(impl()), propertyName)) {\n");
577         push(@getOwnPropertyDescriptorImpl, "        ${namespaceMaybe}PropertySlot slot;\n");
578         push(@getOwnPropertyDescriptorImpl, "        slot.setCustom(this, nameGetter);\n");
579         push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);\n");
580         push(@getOwnPropertyDescriptorImpl, "        return true;\n");
581         push(@getOwnPropertyDescriptorImpl, "    }\n");
582         if ($inlined) {
583             $headerIncludes{"wtf/text/AtomicString.h"} = 1;
584         } else {
585             $implIncludes{"wtf/text/AtomicString.h"} = 1;
586         }
587     }
588     
589     if ($dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
590         &$manualLookupGetterGeneration();
591     }
592     
593     if ($dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}) {
594         push(@getOwnPropertyDescriptorImpl, "    if (getOwnPropertyDescriptorDelegate(exec, propertyName, descriptor))\n");
595         push(@getOwnPropertyDescriptorImpl, "        return true;\n");
596     }
597     
598     if ($hasAttributes) {
599         if ($inlined) {
600             die "Cannot inline if NoStaticTables is set." if ($dataNode->extendedAttributes->{"NoStaticTables"});
601             push(@getOwnPropertyDescriptorImpl, "    return ${namespaceMaybe}getStaticValueDescriptor<$className, Base>(exec, s_info.staticPropHashTable, this, propertyName, descriptor);\n");
602         } else {
603             push(@getOwnPropertyDescriptorImpl, "    return ${namespaceMaybe}getStaticValueDescriptor<$className, Base>(exec, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");
604         }
605     } else {
606         push(@getOwnPropertyDescriptorImpl, "    return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);\n");
607     }
608     
609     return @getOwnPropertyDescriptorImpl;
610 }
611
612 sub GenerateHeaderContentHeader
613 {
614     my $dataNode = shift;
615     my $className = "JS" . $dataNode->name;
616
617     my @headerContentHeader = split("\r", $headerTemplate);
618
619     # - Add header protection
620     push(@headerContentHeader, "\n#ifndef $className" . "_h");
621     push(@headerContentHeader, "\n#define $className" . "_h\n\n");
622
623     my $conditionalString = GenerateConditionalString($dataNode);
624     push(@headerContentHeader, "#if ${conditionalString}\n\n") if $conditionalString;
625     return @headerContentHeader;
626 }
627
628 sub GenerateImplementationContentHeader
629 {
630     my $dataNode = shift;
631     my $className = "JS" . $dataNode->name;
632
633     my @implContentHeader = split("\r", $headerTemplate);
634
635     push(@implContentHeader, "\n#include \"config.h\"\n");
636     my $conditionalString = GenerateConditionalString($dataNode);
637     push(@implContentHeader, "\n#if ${conditionalString}\n\n") if $conditionalString;
638     push(@implContentHeader, "#include \"$className.h\"\n\n");
639     return @implContentHeader;
640 }
641
642 my %usesToJSNewlyCreated = (
643     "CDATASection" => 1,
644     "Element" => 1,
645     "Node" => 1,
646     "Text" => 1,
647     "Touch" => 1,
648     "TouchList" => 1
649 );
650
651 sub GenerateHeader
652 {
653     my $object = shift;
654     my $dataNode = shift;
655
656     my $interfaceName = $dataNode->name;
657     my $className = "JS$interfaceName";
658     my $implClassName = $interfaceName;
659     my @ancestorInterfaceNames = ();
660     my %structureFlags = ();
661
662     # We only support multiple parents with SVG (for now).
663     if (@{$dataNode->parents} > 1) {
664         die "A class can't have more than one parent" unless $interfaceName =~ /SVG/;
665         $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@ancestorInterfaceNames);
666     }
667
668     my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
669     my $hasRealParent = @{$dataNode->parents} > 0;
670     my $hasParent = $hasLegacyParent || $hasRealParent;
671     my $parentClassName = GetParentClassName($dataNode);
672     my $eventTarget = $dataNode->extendedAttributes->{"EventTarget"};
673     my $needsMarkChildren = $dataNode->extendedAttributes->{"CustomMarkFunction"} || $dataNode->extendedAttributes->{"EventTarget"};
674     
675     # - Add default header template and header protection
676     push(@headerContentHeader, GenerateHeaderContentHeader($dataNode));
677
678     if ($hasParent) {
679         $headerIncludes{"$parentClassName.h"} = 1;
680     } else {
681         $headerIncludes{"JSDOMBinding.h"} = 1;
682         $headerIncludes{"<runtime/JSGlobalObject.h>"} = 1;
683         $headerIncludes{"<runtime/ObjectPrototype.h>"} = 1;
684     }
685
686     if ($dataNode->extendedAttributes->{"CustomCall"}) {
687         $headerIncludes{"<runtime/CallData.h>"} = 1;
688     }
689
690     if ($dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"}) {
691         $headerIncludes{"<runtime/Lookup.h>"} = 1;
692         $headerIncludes{"<wtf/AlwaysInline.h>"} = 1;
693     }
694
695     if ($hasParent && $dataNode->extendedAttributes->{"GenerateNativeConverter"}) {
696         $headerIncludes{"$implClassName.h"} = 1;
697     }
698     
699     $headerIncludes{"<runtime/JSObject.h>"} = 1;
700     $headerIncludes{"SVGElement.h"} = 1 if $className =~ /^JSSVG/;
701
702     my $implType = $implClassName;
703     my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implType);
704     $implType = $svgNativeType if $svgNativeType;
705
706     my $svgPropertyOrListPropertyType;
707     $svgPropertyOrListPropertyType = $svgPropertyType if $svgPropertyType;
708     $svgPropertyOrListPropertyType = $svgListPropertyType if $svgListPropertyType;
709
710     my $numConstants = @{$dataNode->constants};
711     my $numAttributes = @{$dataNode->attributes};
712     my $numFunctions = @{$dataNode->functions};
713
714     push(@headerContent, "\nnamespace WebCore {\n\n");
715
716     if ($codeGenerator->IsSVGAnimatedType($implClassName)) {
717         $headerIncludes{"$implClassName.h"} = 1;
718     } else {
719         # Implementation class forward declaration
720         if ($interfaceName eq "DOMWindow" || $dataNode->extendedAttributes->{"IsWorkerContext"}) {
721             AddClassForwardIfNeeded($implClassName) unless $svgPropertyOrListPropertyType;
722         }
723     }
724
725     AddClassForwardIfNeeded("JSDOMWindowShell") if $interfaceName eq "DOMWindow";
726
727     # Class declaration
728     push(@headerContent, "class $className : public $parentClassName {\n");
729
730     # Static create methods
731     push(@headerContent, "public:\n");
732     push(@headerContent, "    typedef $parentClassName Base;\n");
733     if ($interfaceName eq "DOMWindow") {
734         push(@headerContent, "    static $className* create(JSC::JSGlobalData& globalData, JSC::Structure* structure, PassRefPtr<$implType> impl, JSDOMWindowShell* windowShell)\n");
735         push(@headerContent, "    {\n");
736         push(@headerContent, "        $className* ptr = new (JSC::allocateCell<$className>(globalData.heap)) ${className}(globalData, structure, impl, windowShell);\n");
737         push(@headerContent, "        ptr->finishCreation(globalData, windowShell);\n");
738         push(@headerContent, "        return ptr;\n");
739         push(@headerContent, "    }\n\n");
740     } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
741         push(@headerContent, "    static $className* create(JSC::JSGlobalData& globalData, JSC::Structure* structure, PassRefPtr<$implType> impl)\n");
742         push(@headerContent, "    {\n");
743         push(@headerContent, "        $className* ptr = new (JSC::allocateCell<$className>(globalData.heap)) ${className}(globalData, structure, impl);\n");
744         push(@headerContent, "        ptr->finishCreation(globalData);\n");
745         push(@headerContent, "        return ptr;\n");
746         push(@headerContent, "    }\n\n");
747     } else {
748         AddIncludesForTypeInHeader($implType) unless $svgPropertyOrListPropertyType;
749         push(@headerContent, "    static $className* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl)\n");
750         push(@headerContent, "    {\n");
751         push(@headerContent, "        $className* ptr = new (JSC::allocateCell<$className>(globalObject->globalData().heap)) $className(structure, globalObject, impl);\n");
752         push(@headerContent, "        ptr->finishCreation(globalObject->globalData());\n");
753         push(@headerContent, "        return ptr;\n");
754         push(@headerContent, "    }\n\n");
755     }
756
757     # Prototype
758     push(@headerContent, "    static JSC::JSObject* createPrototype(JSC::ExecState*, JSC::JSGlobalObject*);\n") unless ($dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"});
759
760     $headerTrailingIncludes{"${className}Custom.h"} = 1 if $dataNode->extendedAttributes->{"CustomHeader"};
761
762     $implIncludes{"${className}Custom.h"} = 1 if !$dataNode->extendedAttributes->{"CustomHeader"} && ($dataNode->extendedAttributes->{"CustomPutFunction"} || $dataNode->extendedAttributes->{"DelegatingPutFunction"});
763
764     my $hasGetter = $numAttributes > 0 
765                  || !$dataNode->extendedAttributes->{"OmitConstructor"}
766                  || $dataNode->extendedAttributes->{"HasIndexGetter"}
767                  || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}
768                  || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}
769                  || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}
770                  || $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}
771                  || $dataNode->extendedAttributes->{"HasNameGetter"}
772                  || $dataNode->extendedAttributes->{"HasOverridingNameGetter"};
773
774     # Getters
775     if ($hasGetter) {
776         push(@headerContent, "    static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);\n");
777         push(@headerContent, "    virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&);\n");
778         push(@headerContent, "    static bool getOwnPropertySlotByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);\n") if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) && !$dataNode->extendedAttributes->{"HasOverridingNameGetter"};
779         push(@headerContent, "    bool getOwnPropertySlotDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"};
780         push(@headerContent, "    bool getOwnPropertyDescriptorDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n") if $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"};
781         $structureFlags{"JSC::OverridesGetOwnPropertySlot"} = 1;
782     }
783
784     # Check if we have any writable properties
785     my $hasReadWriteProperties = 0;
786     foreach (@{$dataNode->attributes}) {
787         if ($_->type !~ /^readonly\ attribute$/) {
788             $hasReadWriteProperties = 1;
789         }
790     }
791
792     my $hasSetter = $hasReadWriteProperties
793                  || $dataNode->extendedAttributes->{"CustomPutFunction"}
794                  || $dataNode->extendedAttributes->{"DelegatingPutFunction"}
795                  || $dataNode->extendedAttributes->{"HasCustomIndexSetter"};
796
797     # Getters
798     if ($hasSetter) {
799         push(@headerContent, "    static void put(JSC::JSCell*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);\n");
800         push(@headerContent, "    static void putByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::JSValue);\n") if $dataNode->extendedAttributes->{"HasCustomIndexSetter"};
801         push(@headerContent, "    bool putDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, JSC::PutPropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingPutFunction"};
802     }
803
804     # Class info
805     push(@headerContent, "    static const JSC::ClassInfo s_info;\n\n");
806
807     # Structure ID
808     if ($interfaceName eq "DOMWindow") {
809         $structureFlags{"JSC::ImplementsHasInstance"} = 1;
810     }
811     push(@headerContent, "    static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)\n");
812     push(@headerContent, "    {\n");
813     if ($interfaceName eq "DOMWindow" || $dataNode->extendedAttributes->{"IsWorkerContext"}) {
814         push(@headerContent, "        return JSC::Structure::create(globalData, globalObject, prototype, JSC::TypeInfo(JSC::GlobalObjectType, StructureFlags), &s_info);\n");
815     } else {
816         push(@headerContent, "        return JSC::Structure::create(globalData, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), &s_info);\n");
817     }
818     push(@headerContent, "    }\n\n");
819
820     # Custom pushEventHandlerScope function
821     push(@headerContent, "    virtual JSC::ScopeChainNode* pushEventHandlerScope(JSC::ExecState*, JSC::ScopeChainNode*) const;\n\n") if $dataNode->extendedAttributes->{"CustomPushEventHandlerScope"};
822
823     # Custom call functions
824     push(@headerContent, "    static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&);\n\n") if $dataNode->extendedAttributes->{"CustomCall"};
825
826     # Custom deleteProperty function
827     push(@headerContent, "    static bool deleteProperty(JSC::JSCell*, JSC::ExecState*, const JSC::Identifier&);\n") if $dataNode->extendedAttributes->{"CustomDeleteProperty"};
828
829     # Custom getPropertyNames function exists on DOMWindow
830     if ($interfaceName eq "DOMWindow") {
831         push(@headerContent, "    static void getPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n");
832         $structureFlags{"JSC::OverridesGetPropertyNames"} = 1;
833     }
834
835     # Custom defineProperty function exists on DOMWindow
836     push(@headerContent, "    virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&, bool shouldThrow);\n") if $interfaceName eq "DOMWindow";
837
838     # Custom getOwnPropertyNames function
839     if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"} || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
840         push(@headerContent, "    static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n");
841         $structureFlags{"JSC::OverridesGetPropertyNames"} = 1;       
842     }
843
844     # Custom defineGetter function
845     push(@headerContent, "    static void defineGetter(JSC::JSObject*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomDefineGetter"};
846
847     # Custom defineSetter function
848     push(@headerContent, "    static void defineSetter(JSC::JSObject*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomDefineSetter"};
849
850     # Override toBoolean to return false for objects that want to 'MasqueradesAsUndefined'.
851     if ($dataNode->extendedAttributes->{"MasqueradesAsUndefined"}) {
852         push(@headerContent, "    virtual bool toBoolean(JSC::ExecState*) const { return false; };\n");
853         $structureFlags{"JSC::MasqueradesAsUndefined"} = 1;
854     }
855
856     # Constructor object getter
857     push(@headerContent, "    static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*);\n") if !$dataNode->extendedAttributes->{"OmitConstructor"};
858
859     my $numCustomFunctions = 0;
860     my $numCustomAttributes = 0;
861
862     # Attribute and function enums
863     if ($numAttributes > 0) {
864         foreach (@{$dataNode->attributes}) {
865             my $attribute = $_;
866             $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"};
867             $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"CustomGetter"} || $attribute->signature->extendedAttributes->{"JSCCustomGetter"};
868             $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"CustomSetter"} || $attribute->signature->extendedAttributes->{"JSCCustomSetter"};
869             if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) {
870                 push(@headerContent, "    JSC::WriteBarrier<JSC::Unknown> m_" . $attribute->signature->name . ";\n");
871                 $numCachedAttributes++;
872                 $needsMarkChildren = 1;
873             }
874         }
875     }
876
877     # visit function
878     if ($needsMarkChildren) {
879         push(@headerContent, "    static void visitChildren(JSCell*, JSC::SlotVisitor&);\n\n");
880         $structureFlags{"JSC::OverridesVisitChildren"} = 1;
881     }
882
883     if ($numCustomAttributes > 0) {
884         push(@headerContent, "\n    // Custom attributes\n");
885
886         foreach my $attribute (@{$dataNode->attributes}) {
887             if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"}) {
888                 push(@headerContent, "    JSC::JSValue " . $codeGenerator->WK_lcfirst($attribute->signature->name) . "(JSC::ExecState*) const;\n");
889                 if ($attribute->type !~ /^readonly/) {
890                     push(@headerContent, "    void set" . $codeGenerator->WK_ucfirst($attribute->signature->name) . "(JSC::ExecState*, JSC::JSValue);\n");
891                 }
892             } elsif ($attribute->signature->extendedAttributes->{"CustomGetter"} || $attribute->signature->extendedAttributes->{"JSCCustomGetter"}) {
893                 push(@headerContent, "    JSC::JSValue " . $codeGenerator->WK_lcfirst($attribute->signature->name) . "(JSC::ExecState*) const;\n");
894             } elsif ($attribute->signature->extendedAttributes->{"CustomSetter"} || $attribute->signature->extendedAttributes->{"JSCCustomSetter"}) {
895                 if ($attribute->type !~ /^readonly/) {
896                     push(@headerContent, "    void set" . $codeGenerator->WK_ucfirst($attribute->signature->name) . "(JSC::ExecState*, JSC::JSValue);\n");
897                 }
898             }
899         }
900     }
901
902     foreach my $function (@{$dataNode->functions}) {
903         $numCustomFunctions++ if $function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"JSCCustom"};
904     }
905
906     if ($numCustomFunctions > 0) {
907         push(@headerContent, "\n    // Custom functions\n");
908         foreach my $function (@{$dataNode->functions}) {
909             next unless $function->signature->extendedAttributes->{"Custom"} or $function->signature->extendedAttributes->{"JSCCustom"};
910             next if $function->{overloads} && $function->{overloadIndex} != 1;
911             my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementationFunction"} || $codeGenerator->WK_lcfirst($function->signature->name);
912             push(@headerContent, "    JSC::JSValue " . $functionImplementationName . "(JSC::ExecState*);\n");
913         }
914     }
915
916     if (!$hasParent) {
917         push(@headerContent, "    $implType* impl() const { return m_impl.get(); }\n\n");
918         push(@headerContent, "private:\n");
919         push(@headerContent, "    RefPtr<$implType> m_impl;\n");
920     } elsif ($dataNode->extendedAttributes->{"GenerateNativeConverter"}) {
921         push(@headerContent, "    $implClassName* impl() const\n");
922         push(@headerContent, "    {\n");
923         push(@headerContent, "        return static_cast<$implClassName*>(Base::impl());\n");
924         push(@headerContent, "    }\n");
925     }
926
927     push(@headerContent, "protected:\n");
928     # Constructor
929     if ($interfaceName eq "DOMWindow") {
930         push(@headerContent, "    $className(JSC::JSGlobalData&, JSC::Structure*, PassRefPtr<$implType>, JSDOMWindowShell*);\n");
931     } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
932         push(@headerContent, "    $className(JSC::JSGlobalData&, JSC::Structure*, PassRefPtr<$implType>);\n");
933     } else {
934         push(@headerContent, "    $className(JSC::Structure*, JSDOMGlobalObject*, PassRefPtr<$implType>);\n");
935         push(@headerContent, "    void finishCreation(JSC::JSGlobalData&);\n");
936     }
937
938     # structure flags
939     push(@headerContent, "    static const unsigned StructureFlags = ");
940     foreach my $structureFlag (keys %structureFlags) {
941         push(@headerContent, $structureFlag . " | ");
942     }
943     push(@headerContent, "Base::StructureFlags;\n");
944
945     # Index getter
946     if ($dataNode->extendedAttributes->{"HasIndexGetter"}) {
947         push(@headerContent, "    static JSC::JSValue indexGetter(JSC::ExecState*, JSC::JSValue, unsigned);\n");
948     }
949     if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
950         push(@headerContent, "    JSC::JSValue getByIndex(JSC::ExecState*, unsigned index);\n");
951         
952     }
953     
954     # Index setter
955     if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
956         push(@headerContent, "    void indexSetter(JSC::ExecState*, unsigned index, JSC::JSValue);\n");
957     }
958     # Name getter
959     if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
960         push(@headerContent, "private:\n");
961         push(@headerContent, "    static bool canGetItemsForName(JSC::ExecState*, $implClassName*, const JSC::Identifier&);\n");
962         push(@headerContent, "    static JSC::JSValue nameGetter(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&);\n");
963     }
964
965     push(@headerContent, "};\n\n");
966
967     if ($dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"} && !$dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}) {
968         push(@headerContent, "ALWAYS_INLINE bool ${className}::getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertySlot& slot)\n");
969         push(@headerContent, "{\n");
970         push(@headerContent, "    ${className}* thisObject = static_cast<${className}*>(cell);\n");
971         push(@headerContent, "    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\n");
972         push(@headerContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 1));
973         push(@headerContent, "}\n\n");
974         push(@headerContent, "ALWAYS_INLINE bool ${className}::getOwnPropertyDescriptor(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertyDescriptor& descriptor)\n");
975         push(@headerContent, "{\n");
976         push(@headerContent, "    ASSERT_GC_OBJECT_INHERITS(this, &s_info);\n");
977         push(@headerContent, GenerateGetOwnPropertyDescriptorBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 1));
978         push(@headerContent, "}\n\n");
979     }
980
981     if ($dataNode->extendedAttributes->{"GenerateIsReachable"} || 
982         $dataNode->extendedAttributes->{"CustomIsReachable"} || 
983         $dataNode->extendedAttributes->{"CustomFinalize"} ||
984         $dataNode->extendedAttributes->{"ActiveDOMObject"}) {
985         push(@headerContent, "class JS${implType}Owner : public JSC::WeakHandleOwner {\n");
986         push(@headerContent, "    virtual bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::SlotVisitor&);\n");
987         push(@headerContent, "    virtual void finalize(JSC::Handle<JSC::Unknown>, void* context);\n");
988         push(@headerContent, "};\n");
989         push(@headerContent, "\n");
990         push(@headerContent, "inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld*, $implType*)\n");
991         push(@headerContent, "{\n");
992         push(@headerContent, "    DEFINE_STATIC_LOCAL(JS${implType}Owner, js${implType}Owner, ());\n");
993         push(@headerContent, "    return &js${implType}Owner;\n");
994         push(@headerContent, "}\n");
995         push(@headerContent, "\n");
996         push(@headerContent, "inline void* wrapperContext(DOMWrapperWorld* world, $implType*)\n");
997         push(@headerContent, "{\n");
998         push(@headerContent, "    return world;\n");
999         push(@headerContent, "}\n");
1000         push(@headerContent, "\n");
1001     }
1002
1003     if (!$hasParent || $dataNode->extendedAttributes->{"GenerateToJS"} || $dataNode->extendedAttributes->{"CustomToJS"}) {
1004         push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType*);\n");
1005     }
1006     if (!$hasParent || $dataNode->extendedAttributes->{"GenerateNativeConverter"}) {
1007         if ($interfaceName eq "NodeFilter") {
1008             push(@headerContent, "PassRefPtr<NodeFilter> toNodeFilter(JSC::JSGlobalData&, JSC::JSValue);\n");
1009         } else {
1010             push(@headerContent, "$implType* to${interfaceName}(JSC::JSValue);\n");
1011         }
1012     }
1013     if ($usesToJSNewlyCreated{$interfaceName}) {
1014         push(@headerContent, "JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject*, $interfaceName*);\n");
1015     }
1016     
1017     push(@headerContent, "\n");
1018
1019     # Add prototype declaration.
1020     %structureFlags = ();
1021     push(@headerContent, "class ${className}Prototype : public JSC::JSNonFinalObject {\n");
1022     push(@headerContent, "public:\n");
1023     push(@headerContent, "    typedef JSC::JSNonFinalObject Base;\n");
1024     if ($interfaceName ne "DOMWindow" && !$dataNode->extendedAttributes->{"IsWorkerContext"}) {
1025         push(@headerContent, "    static JSC::JSObject* self(JSC::ExecState*, JSC::JSGlobalObject*);\n");
1026     }
1027
1028     push(@headerContent, "    static ${className}Prototype* create(JSC::JSGlobalData& globalData, JSC::JSGlobalObject* globalObject, JSC::Structure* structure)\n");
1029     push(@headerContent, "    {\n");
1030     push(@headerContent, "        ${className}Prototype* ptr = new (JSC::allocateCell<${className}Prototype>(globalData.heap)) ${className}Prototype(globalData, globalObject, structure);\n");
1031     push(@headerContent, "        ptr->finishCreation(globalData);\n");
1032     push(@headerContent, "        return ptr;\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, "    static bool getOwnPropertySlot(JSC::JSCell*, 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), &s_info);\n" .
1050         "    }\n");
1051     if ($dataNode->extendedAttributes->{"DelegatingPrototypePutFunction"}) {
1052         push(@headerContent, "    static void put(JSC::JSCell*, 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, "    static void defineGetter(JSC::JSObject*, 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) { }\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     if ($dataNode->extendedAttributes->{"JSCustomConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"} || !$dataNode->extendedAttributes->{"OmitConstructor"}) {
1073         $headerIncludes{"JSDOMBinding.h"} = 1;
1074         GenerateConstructorDeclaration(\@headerContent, $className, $dataNode);
1075     }
1076
1077     if ($numFunctions > 0) {
1078         push(@headerContent,"// Functions\n\n");
1079         foreach my $function (@{$dataNode->functions}) {
1080             next if $function->{overloadIndex} && $function->{overloadIndex} > 1;
1081             my $functionName = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($function->signature->name);
1082             push(@headerContent, "JSC::EncodedJSValue JSC_HOST_CALL ${functionName}(JSC::ExecState*);\n");
1083         }
1084     }
1085
1086     if ($numAttributes > 0 || !$dataNode->extendedAttributes->{"OmitConstructor"}) {
1087         push(@headerContent,"// Attributes\n\n");
1088         foreach my $attribute (@{$dataNode->attributes}) {
1089             my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
1090             push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&);\n");
1091             unless ($attribute->type =~ /readonly/) {
1092                 my $setter = "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
1093                 push(@headerContent, "void ${setter}(JSC::ExecState*, JSC::JSObject*, JSC::JSValue);\n");
1094             }
1095         }
1096         
1097         if (!$dataNode->extendedAttributes->{"OmitConstructor"}) {
1098             my $getter = "js" . $interfaceName . "Constructor";
1099             push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&);\n");
1100         }
1101
1102         if ($dataNode->extendedAttributes->{"ReplaceableConstructor"}) {
1103             my $constructorFunctionName = "setJS" . $interfaceName . "Constructor";
1104             push(@headerContent, "void ${constructorFunctionName}(JSC::ExecState*, JSC::JSObject*, JSC::JSValue);\n");
1105         }
1106     }
1107
1108     if ($numConstants > 0) {
1109         push(@headerContent,"// Constants\n\n");
1110         foreach my $constant (@{$dataNode->constants}) {
1111             my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);
1112             push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&);\n");
1113         }
1114     }
1115
1116     my $conditionalString = GenerateConditionalString($dataNode);
1117     push(@headerContent, "\n} // namespace WebCore\n\n");
1118     push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;
1119     push(@headerContent, "#endif\n");
1120
1121     # - Generate dependencies.
1122     if ($writeDependencies && @ancestorInterfaceNames) {
1123         push(@depsContent, "$className.h : ", join(" ", map { "$_.idl" } @ancestorInterfaceNames), "\n");
1124         push(@depsContent, map { "$_.idl :\n" } @ancestorInterfaceNames); 
1125     }
1126 }
1127
1128 sub GenerateAttributesHashTable($$)
1129 {
1130     my ($object, $dataNode) = @_;
1131
1132     # FIXME: These should be functions on $dataNode.
1133     my $interfaceName = $dataNode->name;
1134     my $className = "JS$interfaceName";
1135     
1136     # - Add all attributes in a hashtable definition
1137     my $numAttributes = @{$dataNode->attributes};
1138     $numAttributes++ if !$dataNode->extendedAttributes->{"OmitConstructor"};
1139
1140     return 0  if !$numAttributes;
1141
1142     my $hashSize = $numAttributes;
1143     my $hashName = $className . "Table";
1144
1145     my @hashKeys = ();
1146     my @hashSpecials = ();
1147     my @hashValue1 = ();
1148     my @hashValue2 = ();
1149     my %conditionals = ();
1150
1151     my @entries = ();
1152
1153     foreach my $attribute (@{$dataNode->attributes}) {
1154         my $name = $attribute->signature->name;
1155         push(@hashKeys, $name);
1156
1157         my @specials = ();
1158         push(@specials, "DontDelete") unless $attribute->signature->extendedAttributes->{"Deletable"};
1159         push(@specials, "DontEnum") if $attribute->signature->extendedAttributes->{"DontEnum"};
1160         push(@specials, "ReadOnly") if $attribute->type =~ /readonly/;
1161         my $special = (@specials > 0) ? join(" | ", @specials) : "0";
1162         push(@hashSpecials, $special);
1163
1164         my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
1165         push(@hashValue1, $getter);
1166
1167         if ($attribute->type =~ /readonly/) {
1168             push(@hashValue2, "0");
1169         } else {
1170             my $setter = "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
1171             push(@hashValue2, $setter);
1172         }
1173
1174         my $conditional = $attribute->signature->extendedAttributes->{"Conditional"};
1175         if ($conditional) {
1176             $conditionals{$name} = $conditional;
1177         }
1178     }
1179
1180     if (!$dataNode->extendedAttributes->{"OmitConstructor"}) {
1181         push(@hashKeys, "constructor");
1182         my $getter = "js" . $interfaceName . "Constructor";
1183         push(@hashValue1, $getter);
1184         if ($dataNode->extendedAttributes->{"ReplaceableConstructor"}) {
1185             my $setter = "setJS" . $interfaceName . "Constructor";
1186             push(@hashValue2, $setter);
1187             push(@hashSpecials, "DontEnum | DontDelete");
1188         } else {            
1189             push(@hashValue2, "0");
1190             push(@hashSpecials, "DontEnum | ReadOnly");
1191         }
1192     }
1193
1194     $object->GenerateHashTable($hashName, $hashSize,
1195                                \@hashKeys, \@hashSpecials,
1196                                \@hashValue1, \@hashValue2,
1197                                \%conditionals);
1198     return $numAttributes;
1199 }
1200
1201 sub GenerateParametersCheckExpression
1202 {
1203     my $numParameters = shift;
1204     my $function = shift;
1205
1206     my @andExpression = ();
1207     push(@andExpression, "argsCount == $numParameters");
1208     my $parameterIndex = 0;
1209     my %usedArguments = ();
1210     foreach my $parameter (@{$function->parameters}) {
1211         last if $parameterIndex >= $numParameters;
1212         my $value = "arg$parameterIndex";
1213         my $type = $codeGenerator->StripModule($parameter->type);
1214
1215         # Only DOMString or wrapper types are checked.
1216         # For DOMString, Null, Undefined and any Object are accepted too, as
1217         # these are acceptable values for a DOMString argument (any Object can
1218         # be converted to a string via .toString).
1219         if ($codeGenerator->IsStringType($type)) {
1220             push(@andExpression, "(${value}.isUndefinedOrNull() || ${value}.isString() || ${value}.isObject())");
1221             $usedArguments{$parameterIndex} = 1;
1222         } elsif ($parameter->extendedAttributes->{"Callback"}) {
1223             # For Callbacks only checks if the value is null or object.
1224             push(@andExpression, "(${value}.isNull() || ${value}.isObject())");
1225             $usedArguments{$parameterIndex} = 1;
1226         } elsif (IsArrayType($type)) {
1227             # FIXME: Add proper support for T[], T[]?, sequence<T>
1228             push(@andExpression, "(${value}.isNull() || (${value}.isObject() && asObject(${value})->inherits(&JSArray::s_info)))");
1229             $usedArguments{$parameterIndex} = 1;
1230         } elsif (!IsNativeType($type)) {
1231             push(@andExpression, "(${value}.isNull() || (${value}.isObject() && asObject(${value})->inherits(&JS${type}::s_info)))");
1232             $usedArguments{$parameterIndex} = 1;
1233         }
1234         $parameterIndex++;
1235     }
1236     my $res = join(" && ", @andExpression);
1237     $res = "($res)" if @andExpression > 1;
1238     return ($res, keys %usedArguments);
1239 }
1240
1241 sub GenerateFunctionParametersCheck
1242 {
1243     my $function = shift;
1244
1245     my @orExpression = ();
1246     my $numParameters = 0;
1247     my @neededArguments = ();
1248
1249     foreach my $parameter (@{$function->parameters}) {
1250         if ($parameter->extendedAttributes->{"Optional"}) {
1251             my ($expression, @usedArguments) = GenerateParametersCheckExpression($numParameters, $function);
1252             push(@orExpression, $expression);
1253             push(@neededArguments, @usedArguments);
1254         }
1255         $numParameters++;
1256     }
1257     my ($expression, @usedArguments) = GenerateParametersCheckExpression($numParameters, $function);
1258     push(@orExpression, $expression);
1259     push(@neededArguments, @usedArguments);
1260     return (join(" || ", @orExpression), @neededArguments);
1261 }
1262
1263 sub GenerateOverloadedPrototypeFunction
1264 {
1265     my $function = shift;
1266     my $dataNode = shift;
1267     my $implClassName = shift;
1268
1269     # Generate code for choosing the correct overload to call. Overloads are
1270     # chosen based on the total number of arguments passed and the type of
1271     # values passed in non-primitive argument slots. When more than a single
1272     # overload is applicable, precedence is given according to the order of
1273     # declaration in the IDL.
1274
1275     my $functionName = "js${implClassName}PrototypeFunction" . $codeGenerator->WK_ucfirst($function->signature->name);
1276
1277     push(@implContent, "EncodedJSValue JSC_HOST_CALL ${functionName}(ExecState* exec)\n");
1278     push(@implContent, <<END);
1279 {
1280     size_t argsCount = exec->argumentCount();
1281 END
1282
1283     my %fetchedArguments = ();
1284
1285     foreach my $overload (@{$function->{overloads}}) {
1286         my ($parametersCheck, @neededArguments) = GenerateFunctionParametersCheck($overload);
1287
1288         foreach my $parameterIndex (@neededArguments) {
1289             next if exists $fetchedArguments{$parameterIndex};
1290             push(@implContent, "    JSValue arg$parameterIndex(exec->argument($parameterIndex));\n");
1291             $fetchedArguments{$parameterIndex} = 1;
1292         }
1293
1294         push(@implContent, "    if ($parametersCheck)\n");
1295         push(@implContent, "        return ${functionName}$overload->{overloadIndex}(exec);\n");
1296     }
1297     push(@implContent, <<END);
1298     return throwVMTypeError(exec);
1299 }
1300
1301 END
1302 }
1303
1304 sub GenerateImplementation
1305 {
1306     my ($object, $dataNode) = @_;
1307
1308     my $interfaceName = $dataNode->name;
1309     my $className = "JS$interfaceName";
1310     my $implClassName = $interfaceName;
1311
1312     my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
1313     my $hasRealParent = @{$dataNode->parents} > 0;
1314     my $hasParent = $hasLegacyParent || $hasRealParent;
1315     my $parentClassName = GetParentClassName($dataNode);
1316     my $visibleClassName = GetVisibleClassName($interfaceName);
1317     my $eventTarget = $dataNode->extendedAttributes->{"EventTarget"};
1318     my $needsMarkChildren = $dataNode->extendedAttributes->{"CustomMarkFunction"} || $dataNode->extendedAttributes->{"EventTarget"};
1319
1320     # - Add default header template
1321     push(@implContentHeader, GenerateImplementationContentHeader($dataNode));
1322
1323     AddIncludesForSVGAnimatedType($interfaceName) if $className =~ /^JSSVGAnimated/;
1324
1325     $implIncludes{"<wtf/GetPtr.h>"} = 1;
1326     $implIncludes{"<runtime/PropertyNameArray.h>"} = 1 if $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"};
1327
1328     AddIncludesForTypeInImpl($interfaceName);
1329
1330     @implContent = ();
1331
1332     push(@implContent, "\nusing namespace JSC;\n\n");
1333     push(@implContent, "namespace WebCore {\n\n");
1334
1335     push(@implContent, "ASSERT_CLASS_FITS_IN_CELL($className);\n\n");
1336
1337     my $numAttributes = GenerateAttributesHashTable($object, $dataNode);
1338
1339     my $numConstants = @{$dataNode->constants};
1340     my $numFunctions = @{$dataNode->functions};
1341
1342     # - Add all constants
1343     if (!$dataNode->extendedAttributes->{"OmitConstructor"}) {
1344         my $hashSize = $numConstants;
1345         my $hashName = $className . "ConstructorTable";
1346
1347         my @hashKeys = ();
1348         my @hashValue1 = ();
1349         my @hashValue2 = ();
1350         my @hashSpecials = ();
1351
1352         # FIXME: we should not need a function for every constant.
1353         foreach my $constant (@{$dataNode->constants}) {
1354             push(@hashKeys, $constant->name);
1355             my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);
1356             push(@hashValue1, $getter);
1357             push(@hashValue2, "0");
1358             push(@hashSpecials, "DontDelete | ReadOnly");
1359         }
1360
1361         $object->GenerateHashTable($hashName, $hashSize,
1362                                    \@hashKeys, \@hashSpecials,
1363                                    \@hashValue1, \@hashValue2);
1364
1365         push(@implContent, $codeGenerator->GenerateCompileTimeCheckForEnumsIfNeeded($dataNode));
1366
1367         my $protoClassName = "${className}Prototype";
1368         GenerateConstructorDefinition(\@implContent, $className, $protoClassName, $interfaceName, $visibleClassName, $dataNode);
1369     }
1370
1371     # - Add functions and constants to a hashtable definition
1372     my $hashSize = $numFunctions + $numConstants;
1373     my $hashName = $className . "PrototypeTable";
1374
1375     my @hashKeys = ();
1376     my @hashValue1 = ();
1377     my @hashValue2 = ();
1378     my @hashSpecials = ();
1379     my %conditionals = ();
1380
1381     # FIXME: we should not need a function for every constant.
1382     foreach my $constant (@{$dataNode->constants}) {
1383         push(@hashKeys, $constant->name);
1384         my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);
1385         push(@hashValue1, $getter);
1386         push(@hashValue2, "0");
1387         push(@hashSpecials, "DontDelete | ReadOnly");
1388     }
1389
1390     foreach my $function (@{$dataNode->functions}) {
1391         next if $function->{overloadIndex} && $function->{overloadIndex} > 1;
1392         my $name = $function->signature->name;
1393         push(@hashKeys, $name);
1394
1395         my $value = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($name);
1396         push(@hashValue1, $value);
1397
1398         my $numParameters = @{$function->parameters};
1399         push(@hashValue2, $numParameters);
1400
1401         my @specials = ();
1402         push(@specials, "DontDelete") unless $function->signature->extendedAttributes->{"Deletable"};
1403         push(@specials, "DontEnum") if $function->signature->extendedAttributes->{"DontEnum"};
1404         push(@specials, "Function");
1405         my $special = (@specials > 0) ? join(" | ", @specials) : "0";
1406         push(@hashSpecials, $special);
1407
1408         my $conditional = $function->signature->extendedAttributes->{"Conditional"};
1409         if ($conditional) {
1410             $conditionals{$name} = $conditional;
1411         }
1412     }
1413
1414     $object->GenerateHashTable($hashName, $hashSize,
1415                                \@hashKeys, \@hashSpecials,
1416                                \@hashValue1, \@hashValue2,
1417                                \%conditionals);
1418
1419     if ($dataNode->extendedAttributes->{"NoStaticTables"}) {
1420         push(@implContent, "static const HashTable* get${className}PrototypeTable(ExecState* exec)\n");
1421         push(@implContent, "{\n");
1422         push(@implContent, "    return getHashTableForGlobalData(exec->globalData(), &${className}PrototypeTable);\n");
1423         push(@implContent, "}\n\n");
1424         push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleClassName}Prototype\", &JSC::JSNonFinalObject::s_info, 0, get${className}PrototypeTable, CREATE_METHOD_TABLE(${className}Prototype) };\n\n");
1425     } else {
1426         push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleClassName}Prototype\", &JSC::JSNonFinalObject::s_info, &${className}PrototypeTable, 0, CREATE_METHOD_TABLE(${className}Prototype) };\n\n");
1427     }
1428     if ($interfaceName ne "DOMWindow" && !$dataNode->extendedAttributes->{"IsWorkerContext"}) {
1429         push(@implContent, "JSObject* ${className}Prototype::self(ExecState* exec, JSGlobalObject* globalObject)\n");
1430         push(@implContent, "{\n");
1431         push(@implContent, "    return getDOMPrototype<${className}>(exec, globalObject);\n");
1432         push(@implContent, "}\n\n");
1433     }
1434     if ($numConstants > 0 || $numFunctions > 0 || $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) {
1435         push(@implContent, "bool ${className}Prototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n");
1436         push(@implContent, "{\n");
1437         push(@implContent, "    ${className}Prototype* thisObject = static_cast<${className}Prototype*>(cell);\n");
1438
1439         if ($dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) {
1440             push(@implContent, "    if (thisObject->getOwnPropertySlotDelegate(exec, propertyName, slot))\n");
1441             push(@implContent, "        return true;\n");
1442         }
1443
1444         if ($numConstants eq 0 && $numFunctions eq 0) {
1445             push(@implContent, "    return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);\n");        
1446         } elsif ($numConstants eq 0) {
1447             push(@implContent, "    return getStaticFunctionSlot<JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", thisObject, propertyName, slot);\n");
1448         } elsif ($numFunctions eq 0) {
1449             push(@implContent, "    return getStaticValueSlot<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", thisObject, propertyName, slot);\n");
1450         } else {
1451             push(@implContent, "    return getStaticPropertySlot<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", thisObject, propertyName, slot);\n");
1452         }
1453         push(@implContent, "}\n\n");
1454
1455         push(@implContent, "bool ${className}Prototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\n");
1456         push(@implContent, "{\n");
1457         
1458         if ($dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) {
1459             push(@implContent, "    if (getOwnPropertyDescriptorDelegate(exec, propertyName, descriptor))\n");
1460             push(@implContent, "        return true;\n");
1461         }
1462         
1463         if ($numConstants eq 0 && $numFunctions eq 0) {
1464             push(@implContent, "    return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);\n");        
1465         } elsif ($numConstants eq 0) {
1466             push(@implContent, "    return getStaticFunctionDescriptor<JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");
1467         } elsif ($numFunctions eq 0) {
1468             push(@implContent, "    return getStaticValueDescriptor<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");
1469         } else {
1470             push(@implContent, "    return getStaticPropertyDescriptor<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");
1471         }
1472         push(@implContent, "}\n\n");
1473     }
1474
1475     if ($dataNode->extendedAttributes->{"DelegatingPrototypePutFunction"}) {
1476         push(@implContent, "void ${className}Prototype::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)\n");
1477         push(@implContent, "{\n");
1478         push(@implContent, "    ${className}Prototype* thisObject = static_cast<${className}Prototype*>(cell);\n");
1479         push(@implContent, "    if (thisObject->putDelegate(exec, propertyName, value, slot))\n");
1480         push(@implContent, "        return;\n");
1481         push(@implContent, "    Base::put(thisObject, exec, propertyName, value, slot);\n");
1482         push(@implContent, "}\n\n");
1483     }
1484
1485     # - Initialize static ClassInfo object
1486     if ($numAttributes > 0 && $dataNode->extendedAttributes->{"NoStaticTables"}) {
1487         push(@implContent, "static const HashTable* get${className}Table(ExecState* exec)\n");
1488         push(@implContent, "{\n");
1489         push(@implContent, "    return getHashTableForGlobalData(exec->globalData(), &${className}Table);\n");
1490         push(@implContent, "}\n\n");
1491     }
1492
1493     push(@implContent, "const ClassInfo $className" . "::s_info = { \"${visibleClassName}\", &" . $parentClassName . "::s_info, ");
1494
1495     if ($numAttributes > 0 && !$dataNode->extendedAttributes->{"NoStaticTables"}) {
1496         push(@implContent, "&${className}Table");
1497     } else {
1498         push(@implContent, "0");
1499     }
1500     if ($numAttributes > 0 && $dataNode->extendedAttributes->{"NoStaticTables"}) {
1501         push(@implContent, ", get${className}Table ");
1502     } else {
1503         push(@implContent, ", 0 ");
1504     }
1505     push(@implContent, ", CREATE_METHOD_TABLE($className) };\n\n");
1506
1507     my $implType = $implClassName;
1508     my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implType);
1509     $implType = $svgNativeType if $svgNativeType;
1510
1511     my $svgPropertyOrListPropertyType;
1512     $svgPropertyOrListPropertyType = $svgPropertyType if $svgPropertyType;
1513     $svgPropertyOrListPropertyType = $svgListPropertyType if $svgListPropertyType;
1514
1515     # Constructor
1516     if ($interfaceName eq "DOMWindow") {
1517         AddIncludesForTypeInImpl("JSDOMWindowShell");
1518         push(@implContent, "${className}::$className(JSGlobalData& globalData, Structure* structure, PassRefPtr<$implType> impl, JSDOMWindowShell* shell)\n");
1519         push(@implContent, "    : $parentClassName(globalData, structure, impl, shell)\n");
1520         push(@implContent, "{\n");
1521         push(@implContent, "}\n\n");
1522     } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
1523         AddIncludesForTypeInImpl($interfaceName);
1524         push(@implContent, "${className}::$className(JSGlobalData& globalData, Structure* structure, PassRefPtr<$implType> impl)\n");
1525         push(@implContent, "    : $parentClassName(globalData, structure, impl)\n");
1526         push(@implContent, "{\n");
1527         push(@implContent, "}\n\n");
1528     } else {
1529         push(@implContent, "${className}::$className(Structure* structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl)\n");
1530         if ($hasParent) {
1531             push(@implContent, "    : $parentClassName(structure, globalObject, impl)\n");
1532         } else {
1533             push(@implContent, "    : $parentClassName(structure, globalObject)\n");
1534             push(@implContent, "    , m_impl(impl)\n");
1535         }
1536         push(@implContent, "{\n");
1537         push(@implContent, "}\n\n");
1538
1539         push(@implContent, "void ${className}::finishCreation(JSGlobalData& globalData)\n");
1540         push(@implContent, "{\n");
1541         push(@implContent, "    Base::finishCreation(globalData);\n");
1542         push(@implContent, "    ASSERT(inherits(&s_info));\n");
1543         push(@implContent, "}\n\n");
1544     }
1545
1546     if (!$dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"}) {
1547         push(@implContent, "JSObject* ${className}::createPrototype(ExecState* exec, JSGlobalObject* globalObject)\n");
1548         push(@implContent, "{\n");
1549         if ($hasParent && $parentClassName ne "JSC::DOMNodeFilter") {
1550             push(@implContent, "    return ${className}Prototype::create(exec->globalData(), globalObject, ${className}Prototype::createStructure(exec->globalData(), globalObject, ${parentClassName}Prototype::self(exec, globalObject)));\n");
1551         } else {
1552             push(@implContent, "    return ${className}Prototype::create(exec->globalData(), globalObject, ${className}Prototype::createStructure(globalObject->globalData(), globalObject, globalObject->objectPrototype()));\n");
1553         }
1554         push(@implContent, "}\n\n");
1555     }
1556
1557     my $hasGetter = $numAttributes > 0 
1558                  || !$dataNode->extendedAttributes->{"OmitConstructor"} 
1559                  || $dataNode->extendedAttributes->{"HasIndexGetter"}
1560                  || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}
1561                  || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}
1562                  || $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}
1563                  || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}
1564                  || $dataNode->extendedAttributes->{"HasNameGetter"}
1565                  || $dataNode->extendedAttributes->{"HasOverridingNameGetter"};
1566
1567     # Attributes
1568     if ($hasGetter) {
1569         if (!$dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"} && !$dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}) {
1570             push(@implContent, "bool ${className}::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n");
1571             push(@implContent, "{\n");
1572             push(@implContent, "    ${className}* thisObject = static_cast<${className}*>(cell);\n");
1573             push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\n");
1574             push(@implContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 0));
1575             push(@implContent, "}\n\n");
1576             push(@implContent, "bool ${className}::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\n");
1577             push(@implContent, "{\n");
1578             push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(this, &s_info);\n");
1579             push(@implContent, GenerateGetOwnPropertyDescriptorBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 0));
1580             push(@implContent, "}\n\n");
1581         }
1582
1583         if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) 
1584                 && !$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
1585             push(@implContent, "bool ${className}::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, PropertySlot& slot)\n");
1586             push(@implContent, "{\n");
1587             push(@implContent, "    ${className}* thisObject = static_cast<${className}*>(cell);\n");
1588             push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\n");
1589             push(@implContent, "    if (propertyName < static_cast<$implClassName*>(thisObject->impl())->length()) {\n");
1590             if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
1591                 push(@implContent, "        slot.setValue(thisObject->getByIndex(exec, propertyName));\n");
1592             } else {
1593                 push(@implContent, "        slot.setCustomIndex(thisObject, propertyName, thisObject->indexGetter);\n");
1594             }
1595             push(@implContent, "        return true;\n");
1596             push(@implContent, "    }\n");
1597             push(@implContent, "    return thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, Identifier::from(exec, propertyName), slot);\n");
1598             push(@implContent, "}\n\n");
1599         }
1600         
1601         if ($numAttributes > 0) {
1602             foreach my $attribute (@{$dataNode->attributes}) {
1603                 my $name = $attribute->signature->name;
1604                 my $type = $codeGenerator->StripModule($attribute->signature->type);
1605                 my $getFunctionName = "js" . $interfaceName .  $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
1606                 my $implGetterFunctionName = $codeGenerator->WK_lcfirst($name);
1607
1608                 my $attributeConditionalString = GenerateConditionalString($attribute->signature);
1609                 push(@implContent, "#if ${attributeConditionalString}\n") if $attributeConditionalString;
1610
1611                 push(@implContent, "JSValue ${getFunctionName}(ExecState* exec, JSValue slotBase, const Identifier&)\n");
1612                 push(@implContent, "{\n");
1613                 push(@implContent, "    ${className}* castedThis = static_cast<$className*>(asObject(slotBase));\n");
1614
1615                 if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) {
1616                     $needsMarkChildren = 1;
1617                 }
1618
1619                 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && 
1620                         !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurity"} &&
1621                         !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurityOnGet"}) {
1622                     push(@implContent, "    if (!castedThis->allowsAccessFrom(exec))\n");
1623                     push(@implContent, "        return jsUndefined();\n");
1624                 }
1625
1626                 if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"} || $attribute->signature->extendedAttributes->{"CustomGetter"} || $attribute->signature->extendedAttributes->{"JSCCustomGetter"}) {
1627                     push(@implContent, "    return castedThis->$implGetterFunctionName(exec);\n");
1628                 } elsif ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) {
1629                     $implIncludes{"JSDOMBinding.h"} = 1;
1630                     push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");
1631                     push(@implContent, "    return checkNodeSecurity(exec, imp->$implGetterFunctionName()) ? " . NativeToJSValue($attribute->signature, 0, $implClassName, "imp->$implGetterFunctionName()", "castedThis") . " : jsUndefined();\n");
1632                 } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) {
1633                     $implIncludes{"Document.h"} = 1;
1634                     $implIncludes{"JSDOMBinding.h"} = 1;
1635                     push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");
1636                     push(@implContent, "    return checkNodeSecurity(exec, imp->contentDocument()) ? " . NativeToJSValue($attribute->signature, 0, $implClassName, "imp->$implGetterFunctionName()", "castedThis") . " : jsUndefined();\n");
1637                 } elsif ($type eq "EventListener") {
1638                     $implIncludes{"EventListener.h"} = 1;
1639                     push(@implContent, "    UNUSED_PARAM(exec);\n");
1640                     push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");
1641                     push(@implContent, "    if (EventListener* listener = imp->$implGetterFunctionName()) {\n");
1642                     push(@implContent, "        if (const JSEventListener* jsListener = JSEventListener::cast(listener)) {\n");
1643                     if ($implClassName eq "Document" || $implClassName eq "WorkerContext" || $implClassName eq "SharedWorkerContext" || $implClassName eq "DedicatedWorkerContext") {
1644                         push(@implContent, "            if (JSObject* jsFunction = jsListener->jsFunction(imp))\n");
1645                     } else {
1646                         push(@implContent, "            if (JSObject* jsFunction = jsListener->jsFunction(imp->scriptExecutionContext()))\n");
1647                     }
1648                     push(@implContent, "                return jsFunction;\n");
1649                     push(@implContent, "        }\n");
1650                     push(@implContent, "    }\n");
1651                     push(@implContent, "    return jsNull();\n");
1652                 } elsif ($attribute->signature->type =~ /Constructor$/) {
1653                     my $constructorType = $codeGenerator->StripModule($attribute->signature->type);
1654                     $constructorType =~ s/Constructor$//;
1655                     # Constructor attribute is only used by DOMWindow.idl, so it's correct to pass castedThis as the global object
1656                     # Once JSDOMWrappers have a back-pointer to the globalObject we can pass castedThis->globalObject()
1657                     push(@implContent, "    return JS" . $constructorType . "::getConstructor(exec, castedThis);\n");
1658                 } elsif (!@{$attribute->getterExceptions}) {
1659                     push(@implContent, "    UNUSED_PARAM(exec);\n");
1660                     my $cacheIndex = 0;
1661                     if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) {
1662                         $cacheIndex = $currentCachedAttribute;
1663                         $currentCachedAttribute++;
1664                         push(@implContent, "    if (JSValue cachedValue = m_" . $attribute->signature->name . ".get())\n");
1665                         push(@implContent, "        return cachedValue;\n");
1666                     }
1667
1668                     if ($svgListPropertyType) {
1669                         push(@implContent, "    JSValue result =  " . NativeToJSValue($attribute->signature, 0, $implClassName, "castedThis->impl()->$implGetterFunctionName()", "castedThis") . ";\n");
1670                     } elsif ($svgPropertyOrListPropertyType) {
1671                         push(@implContent, "    $svgPropertyOrListPropertyType& imp = castedThis->impl()->propertyReference();\n");
1672                         if ($svgPropertyOrListPropertyType eq "float") { # Special case for JSSVGNumber
1673                             push(@implContent, "    JSValue result =  " . NativeToJSValue($attribute->signature, 0, $implClassName, "imp", "castedThis") . ";\n");
1674                         } else {
1675                             push(@implContent, "    JSValue result =  " . NativeToJSValue($attribute->signature, 0, $implClassName, "imp.$implGetterFunctionName()", "castedThis") . ";\n");
1676                         }
1677                     } else {
1678                         my $getterExpression = "imp->" . $codeGenerator->GetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute) . ")";
1679                         my $jsType = NativeToJSValue($attribute->signature, 0, $implClassName, $getterExpression, "castedThis");
1680                         push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");
1681                         if ($codeGenerator->IsSVGAnimatedType($type)) {
1682                             push(@implContent, "    RefPtr<$type> obj = $jsType;\n");
1683                             push(@implContent, "    JSValue result =  toJS(exec, castedThis->globalObject(), obj.get());\n");
1684                         } else {
1685                             push(@implContent, "    JSValue result = $jsType;\n");
1686                         }
1687                     }
1688                     
1689                     push(@implContent, "    m_" . $attribute->signature->name . ".set(exec->globalData(), this, result);\n") if ($attribute->signature->extendedAttributes->{"CachedAttribute"});
1690                     push(@implContent, "    return result;\n");
1691
1692                 } else {
1693                     push(@implContent, "    ExceptionCode ec = 0;\n");                    
1694                     if ($svgPropertyOrListPropertyType) {
1695                         push(@implContent, "    $svgPropertyOrListPropertyType imp(*castedThis->impl());\n");
1696                         push(@implContent, "    JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "imp.$implGetterFunctionName(ec)", "castedThis") . ";\n");
1697                     } else {
1698                         push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");
1699                         push(@implContent, "    JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "imp->$implGetterFunctionName(ec)", "castedThis") . ";\n");
1700                     }
1701
1702                     push(@implContent, "    setDOMException(exec, ec);\n");
1703                     push(@implContent, "    return result;\n");
1704                 }
1705
1706                 push(@implContent, "}\n\n");
1707
1708                 push(@implContent, "#endif\n") if $attributeConditionalString;
1709
1710                 push(@implContent, "\n");
1711             }
1712
1713             if (!$dataNode->extendedAttributes->{"OmitConstructor"}) {
1714                 my $constructorFunctionName = "js" . $interfaceName . "Constructor";
1715
1716                 push(@implContent, "JSValue ${constructorFunctionName}(ExecState* exec, JSValue slotBase, const Identifier&)\n");
1717                 push(@implContent, "{\n");
1718                 push(@implContent, "    ${className}* domObject = static_cast<$className*>(asObject(slotBase));\n");
1719
1720                 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) {
1721                     push(@implContent, "    if (!domObject->allowsAccessFrom(exec))\n");
1722                     push(@implContent, "        return jsUndefined();\n");
1723                 }
1724
1725                 push(@implContent, "    return ${className}::getConstructor(exec, domObject->globalObject());\n");
1726                 push(@implContent, "}\n\n");
1727             }
1728         }
1729
1730         # Check if we have any writable attributes
1731         my $hasReadWriteProperties = 0;
1732         foreach my $attribute (@{$dataNode->attributes}) {
1733             $hasReadWriteProperties = 1 if $attribute->type !~ /^readonly/;
1734         }
1735
1736         my $hasSetter = $hasReadWriteProperties
1737                      || $dataNode->extendedAttributes->{"DelegatingPutFunction"}
1738                      || $dataNode->extendedAttributes->{"HasCustomIndexSetter"};
1739
1740         if ($hasSetter) {
1741             if (!$dataNode->extendedAttributes->{"CustomPutFunction"}) {
1742                 push(@implContent, "void ${className}::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)\n");
1743                 push(@implContent, "{\n");
1744                 push(@implContent, "    ${className}* thisObject = static_cast<${className}*>(cell);\n");
1745                 push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\n");
1746                 if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
1747                     push(@implContent, "    bool ok;\n");
1748                     push(@implContent, "    unsigned index = propertyName.toUInt32(ok);\n");
1749                     push(@implContent, "    if (ok) {\n");
1750                     push(@implContent, "        thisObject->indexSetter(exec, index, value);\n");
1751                     push(@implContent, "        return;\n");
1752                     push(@implContent, "    }\n");
1753                 }
1754                 if ($dataNode->extendedAttributes->{"DelegatingPutFunction"}) {
1755                     push(@implContent, "    if (thisObject->putDelegate(exec, propertyName, value, slot))\n");
1756                     push(@implContent, "        return;\n");
1757                 }
1758
1759                 if ($hasReadWriteProperties) {
1760                     push(@implContent, "    lookupPut<$className, Base>(exec, propertyName, value, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", thisObject, slot);\n");
1761                 } else {
1762                     push(@implContent, "    Base::put(thisObject, exec, propertyName, value, slot);\n");
1763                 }
1764                 push(@implContent, "}\n\n");
1765             }
1766
1767             if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
1768                 push(@implContent, "void ${className}::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value)\n");
1769                 push(@implContent, "{\n");
1770                 push(@implContent, "    ${className}* thisObject = static_cast<${className}*>(cell);\n");
1771                 push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\n");
1772                 push(@implContent, "    thisObject->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                             # $constructorType ~= /Constructor$/ indicates that it is NamedConstructor.
1821                             # We do not generate the header file for NamedConstructor of class XXXX,
1822                             # since we generate the NamedConstructor declaration into the header file of class XXXX.
1823                             if ($constructorType ne "DOMObject" and $constructorType !~ /Constructor$/) {
1824                                 AddToImplIncludes("JS" . $constructorType . ".h", $attribute->signature->extendedAttributes->{"Conditional"});
1825                             }
1826                             push(@implContent, "    // Shadowing a built-in constructor\n");
1827                             if ($interfaceName eq "DOMWindow" && $className eq "JSblah") {
1828                                 # FIXME: This branch never executes and should be removed.
1829                                 push(@implContent, "    static_cast<$className*>(thisObject)->putDirect(exec->globalData(), exec->propertyNames().constructor, value);\n");
1830                             } else {
1831                                 push(@implContent, "    static_cast<$className*>(thisObject)->putDirect(exec->globalData(), Identifier(exec, \"$name\"), value);\n");
1832                             }
1833                         } elsif ($attribute->signature->extendedAttributes->{"Replaceable"}) {
1834                             push(@implContent, "    // Shadowing a built-in object\n");
1835                             push(@implContent, "    static_cast<$className*>(thisObject)->putDirect(exec->globalData(), Identifier(exec, \"$name\"), value);\n");
1836                         } else {
1837                             push(@implContent, "    $className* castedThis = static_cast<$className*>(thisObject);\n");
1838                             push(@implContent, "    $implType* imp = static_cast<$implType*>(castedThis->impl());\n");
1839                             push(@implContent, "    ExceptionCode ec = 0;\n") if @{$attribute->setterExceptions};
1840
1841                             # If the "StrictTypeChecking" extended attribute is present, and the attribute's type is an
1842                             # interface type, then if the incoming value does not implement that interface, a TypeError
1843                             # is thrown rather than silently passing NULL to the C++ code.
1844                             # Per the Web IDL and ECMAScript specifications, incoming values can always be converted to
1845                             # both strings and numbers, so do not throw TypeError if the attribute is of these types.
1846                             if ($attribute->signature->extendedAttributes->{"StrictTypeChecking"}) {
1847                                 $implIncludes{"<runtime/Error.h>"} = 1;
1848
1849                                 my $argType = $attribute->signature->type;
1850                                 if (!IsNativeType($argType)) {
1851                                     push(@implContent, "    if (!value.isUndefinedOrNull() && !value.inherits(&JS${argType}::s_info)) {\n");
1852                                     push(@implContent, "        throwVMTypeError(exec);\n");
1853                                     push(@implContent, "        return;\n");
1854                                     push(@implContent, "    };\n");
1855                                 }
1856                             }
1857
1858                             my $nativeValue = JSValueToNative($attribute->signature, "value");
1859                             if ($svgPropertyOrListPropertyType) {
1860                                 if ($svgPropertyType) {
1861                                     push(@implContent, "    if (imp->role() == AnimValRole) {\n");
1862                                     push(@implContent, "        setDOMException(exec, NO_MODIFICATION_ALLOWED_ERR);\n");
1863                                     push(@implContent, "        return;\n");
1864                                     push(@implContent, "    }\n");
1865                                     $implIncludes{"ExceptionCode.h"} = 1;
1866                                 }
1867                                 push(@implContent, "    $svgPropertyOrListPropertyType& podImp = imp->propertyReference();\n");
1868                                 if ($svgPropertyOrListPropertyType eq "float") { # Special case for JSSVGNumber
1869                                     push(@implContent, "    podImp = $nativeValue;\n");
1870                                 } else {
1871                                     push(@implContent, "    podImp.set$implSetterFunctionName($nativeValue");
1872                                     push(@implContent, ", ec") if @{$attribute->setterExceptions};
1873                                     push(@implContent, ");\n");
1874                                     push(@implContent, "    setDOMException(exec, ec);\n") if @{$attribute->setterExceptions};
1875                                 }
1876                                 if ($svgPropertyType) {
1877                                     if (@{$attribute->setterExceptions}) {
1878                                         push(@implContent, "    if (!ec)\n"); 
1879                                         push(@implContent, "        imp->commitChange();\n");
1880                                     } else {
1881                                         push(@implContent, "    imp->commitChange();\n");
1882                                     }
1883                                 }
1884                             } else {
1885                                 my $setterExpressionPrefix = $codeGenerator->SetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute);
1886                                 push(@implContent, "    imp->$setterExpressionPrefix$nativeValue");
1887                                 push(@implContent, ", ec") if @{$attribute->setterExceptions};
1888                                 push(@implContent, ");\n");
1889                                 push(@implContent, "    setDOMException(exec, ec);\n") if @{$attribute->setterExceptions};
1890                             }
1891                         }
1892                         
1893                         push(@implContent, "}\n\n");
1894
1895                         push(@implContent, "#endif\n") if $attributeConditionalString;
1896
1897                         push(@implContent, "\n");
1898                     }
1899                 }
1900             }
1901             
1902             if ($dataNode->extendedAttributes->{"ReplaceableConstructor"}) {
1903                 my $constructorFunctionName = "setJS" . $interfaceName . "Constructor";
1904                 
1905                 push(@implContent, "void ${constructorFunctionName}(ExecState* exec, JSObject* thisObject, JSValue value)\n");
1906                 push(@implContent, "{\n");
1907                 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) {
1908                     if ($interfaceName eq "DOMWindow") {
1909                         push(@implContent, "    if (!static_cast<$className*>(thisObject)->allowsAccessFrom(exec))\n");
1910                     } else {
1911                         push(@implContent, "    if (!allowsAccessFromFrame(exec, static_cast<$className*>(thisObject)->impl()->frame()))\n");
1912                     }
1913                     push(@implContent, "        return;\n");
1914                 }
1915
1916                 push(@implContent, "    // Shadowing a built-in constructor\n");
1917
1918                 if ($interfaceName eq "DOMWindow") {
1919                     push(@implContent, "    static_cast<$className*>(thisObject)->putDirect(exec->globalData(), exec->propertyNames().constructor, value);\n");
1920                 } else {
1921                     die "No way to handle interface with ReplaceableConstructor extended attribute: $interfaceName";
1922                 }
1923                 push(@implContent, "}\n\n");
1924             }        
1925         }
1926     }
1927
1928     if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) && !$dataNode->extendedAttributes->{"CustomGetPropertyNames"}) {
1929         push(@implContent, "void ${className}::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)\n");
1930         push(@implContent, "{\n");
1931         push(@implContent, "    ${className}* thisObject = static_cast<${className}*>(object);\n");
1932         push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\n");
1933         if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
1934             push(@implContent, "    for (unsigned i = 0; i < static_cast<${implClassName}*>(thisObject->impl())->length(); ++i)\n");
1935             push(@implContent, "        propertyNames.add(Identifier::from(exec, i));\n");
1936         }
1937         push(@implContent, "     Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode);\n");
1938         push(@implContent, "}\n\n");
1939     }
1940
1941     if (!$dataNode->extendedAttributes->{"OmitConstructor"}) {
1942         push(@implContent, "JSValue ${className}::getConstructor(ExecState* exec, JSGlobalObject* globalObject)\n{\n");
1943         push(@implContent, "    return getDOMConstructor<${className}Constructor>(exec, static_cast<JSDOMGlobalObject*>(globalObject));\n");
1944         push(@implContent, "}\n\n");
1945     }
1946
1947     # Functions
1948     if ($numFunctions > 0) {
1949         foreach my $function (@{$dataNode->functions}) {
1950             AddIncludesForTypeInImpl($function->signature->type);
1951
1952             my $functionName = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($function->signature->name);
1953             my $isCustom = $function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"JSCCustom"};
1954             my $isOverloaded = $function->{overloads} && @{$function->{overloads}} > 1;
1955
1956             next if $isCustom && $isOverloaded && $function->{overloadIndex} > 1;
1957
1958             if (!$isCustom && $isOverloaded) {
1959                 # Append a number to an overloaded method's name to make it unique:
1960                 $functionName = $functionName . $function->{overloadIndex};
1961                 # Make this function static to avoid compiler warnings, since we
1962                 # don't generate a prototype for it in the header.
1963                 push(@implContent, "static ");
1964             }
1965             
1966             my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementationFunction"} || $codeGenerator->WK_lcfirst($function->signature->name);
1967
1968             my $conditional = $function->signature->extendedAttributes->{"Conditional"};
1969             if ($conditional) {
1970                 my $conditionalString = GenerateConditionalStringFromAttributeValue($conditional);
1971                 push(@implContent, "#if ${conditionalString}\n");
1972             }
1973
1974             push(@implContent, "EncodedJSValue JSC_HOST_CALL ${functionName}(ExecState* exec)\n");
1975             push(@implContent, "{\n");
1976
1977             $implIncludes{"<runtime/Error.h>"} = 1;
1978
1979             if ($interfaceName eq "DOMWindow") {
1980                 push(@implContent, "    $className* castedThis = toJSDOMWindow(exec->hostThisValue().toThisObject(exec));\n");
1981                 push(@implContent, "    if (!castedThis)\n");
1982                 push(@implContent, "        return throwVMTypeError(exec);\n");
1983             } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
1984                 push(@implContent, "    $className* castedThis = to${className}(exec->hostThisValue().toThisObject(exec));\n");
1985                 push(@implContent, "    if (!castedThis)\n");
1986                 push(@implContent, "        return throwVMTypeError(exec);\n");
1987             } else {
1988                 push(@implContent, "    JSValue thisValue = exec->hostThisValue();\n");
1989                 push(@implContent, "    if (!thisValue.inherits(&${className}::s_info))\n");
1990                 push(@implContent, "        return throwVMTypeError(exec);\n");
1991                 push(@implContent, "    $className* castedThis = static_cast<$className*>(asObject(thisValue));\n");
1992             }
1993             push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(castedThis, &${className}::s_info);\n");
1994
1995             if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && 
1996                 !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
1997                 push(@implContent, "    if (!castedThis->allowsAccessFrom(exec))\n");
1998                 push(@implContent, "        return JSValue::encode(jsUndefined());\n");
1999             }
2000
2001             if ($isCustom) {
2002                 push(@implContent, "    return JSValue::encode(castedThis->" . $functionImplementationName . "(exec));\n");
2003             } else {
2004                 push(@implContent, "    $implType* imp = static_cast<$implType*>(castedThis->impl());\n");
2005                 if ($svgPropertyType) {
2006                     push(@implContent, "    if (imp->role() == AnimValRole) {\n");
2007                     push(@implContent, "        setDOMException(exec, NO_MODIFICATION_ALLOWED_ERR);\n");
2008                     push(@implContent, "        return JSValue::encode(jsUndefined());\n");
2009                     push(@implContent, "    }\n");
2010                     push(@implContent, "    $svgPropertyType& podImp = imp->propertyReference();\n");
2011                     $implIncludes{"ExceptionCode.h"} = 1;
2012                 }
2013
2014                 GenerateArgumentsCountCheck(\@implContent, $function, $dataNode);
2015
2016                 if (@{$function->raisesExceptions}) {
2017                     push(@implContent, "    ExceptionCode ec = 0;\n");
2018                 }
2019
2020                 if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) {
2021                     push(@implContent, "    if (!checkNodeSecurity(exec, imp->getSVGDocument(" . (@{$function->raisesExceptions} ? "ec" : "") .")))\n");
2022                     push(@implContent, "        return JSValue::encode(jsUndefined());\n");
2023                     $implIncludes{"JSDOMBinding.h"} = 1;
2024                 }
2025
2026                 if ($function->signature->name eq "addEventListener") {
2027                     push(@implContent, GenerateEventListenerCall($className, "add"));
2028                 } elsif ($function->signature->name eq "removeEventListener") {
2029                     push(@implContent, GenerateEventListenerCall($className, "remove"));
2030                 } else {
2031                     my $numParameters = @{$function->parameters};
2032                     my ($functionString, $paramIndex) = GenerateParametersCheck(\@implContent, $function, $dataNode, $numParameters, $implClassName, $functionImplementationName, $svgPropertyType, $svgPropertyOrListPropertyType, $svgListPropertyType);
2033                     GenerateImplementationFunctionCall($function, $functionString, $paramIndex, "    ", $svgPropertyType, $implClassName);
2034                 }
2035             }
2036
2037             push(@implContent, "}\n\n");
2038
2039             if (!$isCustom && $isOverloaded && $function->{overloadIndex} == @{$function->{overloads}}) {
2040                 # Generate a function dispatching call to the rest of the overloads.
2041                 GenerateOverloadedPrototypeFunction($function, $dataNode, $implClassName);
2042             }
2043
2044             if ($conditional) {
2045                 push(@implContent, "#endif\n\n");
2046             }
2047         }
2048         
2049         if ($needsMarkChildren && !$dataNode->extendedAttributes->{"CustomMarkFunction"}) {
2050             push(@implContent, "void ${className}::visitChildren(JSCell* cell, SlotVisitor& visitor)\n");
2051             push(@implContent, "{\n");
2052             push(@implContent, "    ${className}* thisObject = static_cast<${className}*>(cell);\n");
2053             push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\n");
2054             push(@implContent, "    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);\n");
2055             push(@implContent, "    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());\n");
2056             push(@implContent, "    Base::visitChildren(thisObject, visitor);\n");
2057             if ($dataNode->extendedAttributes->{"EventTarget"}) {
2058                 push(@implContent, "    thisObject->impl()->visitJSEventListeners(visitor);\n");
2059             }
2060             if ($numCachedAttributes > 0) {
2061                 foreach (@{$dataNode->attributes}) {
2062                     my $attribute = $_;
2063                     if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) {
2064                         push(@implContent, "    if (thisObject->m_" . $attribute->signature->name . ")\n");
2065                         push(@implContent, "        visitor.append(&thisObject->m_" . $attribute->signature->name . ");\n");
2066                     }
2067                 }
2068             }
2069             push(@implContent, "}\n\n");
2070         }
2071         die "Can't generate binding for class with cached attribute and custom mark." if (($numCachedAttributes > 0) and ($dataNode->extendedAttributes->{"CustomMarkFunction"}));
2072     }
2073
2074     if ($numConstants > 0) {
2075         push(@implContent, "// Constant getters\n\n");
2076
2077         foreach my $constant (@{$dataNode->constants}) {
2078             my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);
2079
2080             # FIXME: this casts into int to match our previous behavior which turned 0xFFFFFFFF in -1 for NodeFilter.SHOW_ALL
2081             push(@implContent, "JSValue ${getter}(ExecState* exec, JSValue, const Identifier&)\n");
2082             push(@implContent, "{\n");
2083             if ($constant->type eq "DOMString") {
2084                 push(@implContent, "    return jsStringOrNull(exec, String(" . $constant->value . "));\n");
2085             } else {
2086                 push(@implContent, "    UNUSED_PARAM(exec);\n");
2087                 push(@implContent, "    return jsNumber(static_cast<int>(" . $constant->value . "));\n");
2088             }
2089             push(@implContent, "}\n\n");
2090         }
2091     }
2092
2093     if ($dataNode->extendedAttributes->{"HasIndexGetter"}) {
2094         push(@implContent, "\nJSValue ${className}::indexGetter(ExecState* exec, JSValue slotBase, unsigned index)\n");
2095         push(@implContent, "{\n");
2096         push(@implContent, "    ${className}* thisObj = static_cast<$className*>(asObject(slotBase));\n");
2097         push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(thisObj, &s_info);\n");
2098         if (IndexGetterReturnsStrings($implClassName)) {
2099             $implIncludes{"KURL.h"} = 1;
2100             push(@implContent, "    return jsStringOrNull(exec, thisObj->impl()->item(index));\n");
2101         } else {
2102             push(@implContent, "    return toJS(exec, thisObj->globalObject(), static_cast<$implClassName*>(thisObj->impl())->item(index));\n");
2103         }
2104         push(@implContent, "}\n\n");
2105         if ($interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") {
2106             $implIncludes{"JSNode.h"} = 1;
2107             $implIncludes{"Node.h"} = 1;
2108         }
2109     }
2110     
2111     if ($dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
2112         push(@implContent, "\nJSValue ${className}::getByIndex(ExecState*, unsigned index)\n");
2113         push(@implContent, "{\n");
2114         push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(this, &s_info);\n");
2115         push(@implContent, "    double result = static_cast<$implClassName*>(impl())->item(index);\n");
2116         # jsNumber conversion doesn't suppress signalling NaNs, so enforce that here.
2117         push(@implContent, "    if (isnan(result))\n");
2118         push(@implContent, "        return jsNaN();\n");
2119         push(@implContent, "    return JSValue(result);\n");
2120         push(@implContent, "}\n\n");
2121         if ($interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") {
2122             $implIncludes{"JSNode.h"} = 1;
2123             $implIncludes{"Node.h"} = 1;
2124         }
2125     }
2126
2127     if ($dataNode->extendedAttributes->{"GenerateIsReachable"} || $dataNode->extendedAttributes->{"ActiveDOMObject"}) {
2128         push(@implContent, "static inline bool isObservable(JS${implType}* js${implType})\n");
2129         push(@implContent, "{\n");
2130         push(@implContent, "    if (js${implType}->hasCustomProperties())\n");
2131         push(@implContent, "        return true;\n");
2132         if ($eventTarget) {
2133             push(@implContent, "    if (js${implType}->impl()->hasEventListeners())\n");
2134             push(@implContent, "        return true;\n");
2135         }
2136         push(@implContent, "    return false;\n");
2137         push(@implContent, "}\n\n");
2138
2139         push(@implContent, "bool JS${implType}Owner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)\n");
2140         push(@implContent, "{\n");
2141         push(@implContent, "    JS${implType}* js${implType} = static_cast<JS${implType}*>(handle.get().asCell());\n");
2142         # All ActiveDOMObjects implement hasPendingActivity(), but not all of them
2143         # increment their C++ reference counts when hasPendingActivity() becomes
2144         # true. As a result, ActiveDOMObjects can be prematurely destroyed before
2145         # their pending activities complete. To wallpaper over this bug, JavaScript
2146         # wrappers unconditionally keep ActiveDOMObjects with pending activity alive.
2147         # FIXME: Fix this lifetime issue in the DOM, and move this hasPendingActivity
2148         # check below the isObservable check.
2149         if ($dataNode->extendedAttributes->{"ActiveDOMObject"}) {
2150             push(@implContent, "    if (js${implType}->impl()->hasPendingActivity())\n");
2151             push(@implContent, "        return true;\n");
2152         }
2153         push(@implContent, "    if (!isObservable(js${implType}))\n");
2154         push(@implContent, "        return false;\n");
2155         if ($dataNode->extendedAttributes->{"GenerateIsReachable"}) {
2156             my $rootString;
2157             if ($dataNode->extendedAttributes->{"GenerateIsReachable"} eq "Impl") {
2158                 $rootString  = "    ${implType}* root = js${implType}->impl();\n";
2159             } elsif ($dataNode->extendedAttributes->{"GenerateIsReachable"} eq "ImplContext") {
2160                 $rootString  = "    WebGLRenderingContext* root = js${implType}->impl()->context();\n";
2161             } elsif ($dataNode->extendedAttributes->{"GenerateIsReachable"} eq "ImplFrame") {
2162                 $rootString  = "    Frame* root = js${implType}->impl()->frame();\n";
2163                 $rootString .= "    if (!root)\n";
2164                 $rootString .= "        return false;\n";
2165             } elsif ($dataNode->extendedAttributes->{"GenerateIsReachable"} eq "ImplDocument") {
2166                 $rootString  = "    Document* root = js${implType}->impl()->document();\n";
2167                 $rootString .= "    if (!root)\n";
2168                 $rootString .= "        return false;\n";
2169             } elsif ($dataNode->extendedAttributes->{"GenerateIsReachable"} eq "ImplElementRoot") {
2170                 $rootString  = "    Element* element = js${implType}->impl()->element();\n";
2171                 $rootString .= "    if (!element)\n";
2172                 $rootString .= "        return false;\n";
2173                 $rootString .= "    void* root = WebCore::root(element);\n";
2174             } elsif ($interfaceName eq "CanvasRenderingContext") {
2175                 $rootString  = "    void* root = WebCore::root(js${implType}->impl()->canvas());\n";
2176             } elsif ($interfaceName eq "HTMLCollection") {
2177                 $rootString  = "    void* root = WebCore::root(js${implType}->impl()->base());\n";
2178             } else {
2179                 $rootString  = "    void* root = WebCore::root(js${implType}->impl());\n";
2180             }
2181
2182             push(@implContent, $rootString);
2183             push(@implContent, "    return visitor.containsOpaqueRoot(root);\n");
2184         } else {
2185             push(@implContent, "    UNUSED_PARAM(visitor);\n");
2186             push(@implContent, "    return false;\n");
2187         }
2188         push(@implContent, "}\n\n");
2189     }
2190
2191     if (!$dataNode->extendedAttributes->{"CustomFinalize"} &&
2192         ($dataNode->extendedAttributes->{"GenerateIsReachable"} || 
2193          $dataNode->extendedAttributes->{"CustomIsReachable"} ||
2194          $dataNode->extendedAttributes->{"ActiveDOMObject"})) {
2195         push(@implContent, "void JS${implType}Owner::finalize(JSC::Handle<JSC::Unknown> handle, void* context)\n");
2196         push(@implContent, "{\n");
2197         push(@implContent, "    JS${implType}* js${implType} = static_cast<JS${implType}*>(handle.get().asCell());\n");
2198         push(@implContent, "    DOMWrapperWorld* world = static_cast<DOMWrapperWorld*>(context);\n");
2199         push(@implContent, "    uncacheWrapper(world, js${implType}->impl(), js${implType});\n");
2200         push(@implContent, "}\n\n");
2201     }
2202
2203     if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateToJS"}) and !$dataNode->extendedAttributes->{"CustomToJS"}) {
2204         push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* impl)\n");
2205         push(@implContent, "{\n");
2206         if ($svgPropertyType) {
2207             push(@implContent, "    return wrap<$className, $implType>(exec, globalObject, impl);\n");
2208         } else {
2209             push(@implContent, "    return wrap<$className>(exec, globalObject, impl);\n");
2210         }
2211         push(@implContent, "}\n\n");
2212     }
2213
2214     if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateNativeConverter"}) and !$dataNode->extendedAttributes->{"CustomNativeConverter"}) {
2215         push(@implContent, "$implType* to${interfaceName}(JSC::JSValue value)\n");
2216         push(@implContent, "{\n");
2217         push(@implContent, "    return value.inherits(&${className}::s_info) ? static_cast<$className*>(asObject(value))->impl() : 0");
2218         push(@implContent, ";\n}\n");
2219     }
2220
2221     if ($parentClassName eq "JSArrayBufferView") {
2222         push(@implContent, <<END);
2223     void ${implType}::neuterBinding(ScriptExecutionContext*) {
2224     }
2225 END
2226     }
2227
2228
2229     push(@implContent, "\n}\n");
2230
2231     my $conditionalString = GenerateConditionalString($dataNode);
2232     push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
2233 }
2234
2235 sub GenerateArgumentsCountCheck
2236 {
2237     my $outputArray = shift;
2238     my $function = shift;
2239     my $dataNode = shift;
2240
2241     my $numMandatoryParams = @{$function->parameters};
2242     foreach my $param (reverse(@{$function->parameters})) {
2243         if ($param->extendedAttributes->{"Optional"}) {
2244             $numMandatoryParams--;
2245         } else {
2246             last;
2247         }
2248     }
2249     if ($numMandatoryParams >= 1)
2250     {
2251         push(@$outputArray, "    if (exec->argumentCount() < $numMandatoryParams)\n");
2252         if ($function->signature->extendedAttributes->{"RequiresAllArguments"}) {
2253             push(@$outputArray, "        return JSValue::encode(jsUndefined());\n");
2254         } else {
2255             push(@$outputArray, "        return throwVMError(exec, createTypeError(exec, \"Not enough arguments\"));\n");
2256         }
2257     }
2258 }
2259
2260 sub GenerateParametersCheck
2261 {
2262     my $outputArray = shift;
2263     my $function = shift;
2264     my $dataNode = shift;
2265     my $numParameters = shift;
2266     my $implClassName = shift;
2267     my $functionImplementationName = shift;
2268     my $svgPropertyType = shift;
2269     my $svgPropertyOrListPropertyType = shift;
2270     my $svgListPropertyType = shift;
2271
2272     my $paramIndex = 0;
2273     my $argsIndex = 0;
2274     my $hasOptionalArguments = 0;
2275
2276     my $functionString = (($svgPropertyOrListPropertyType and !$svgListPropertyType) ? "podImp." : "imp->") . $functionImplementationName . "(";
2277
2278     if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
2279         push(@$outputArray, "    RefPtr<ScriptArguments> scriptArguments(createScriptArguments(exec, $numParameters));\n");
2280         push(@$outputArray, "    size_t maxStackSize = imp->shouldCaptureFullStackTrace() ? ScriptCallStack::maxCallStackSizeToCapture : 1;\n");
2281         push(@$outputArray, "    RefPtr<ScriptCallStack> callStack(createScriptCallStack(exec, maxStackSize));\n");
2282         $implIncludes{"ScriptArguments.h"} = 1;
2283         $implIncludes{"ScriptCallStack.h"} = 1;
2284         $implIncludes{"ScriptCallStackFactory.h"} = 1;
2285     }
2286
2287     my $callWith = $function->signature->extendedAttributes->{"CallWith"};
2288     if ($callWith and !$function->signature->extendedAttributes->{"Constructor"}) {
2289         my $callWithArg = "COMPILE_ASSERT(false)";
2290         if ($callWith eq "DynamicFrame") {
2291             push(@$outputArray, "    Frame* dynamicFrame = toDynamicFrame(exec);\n");
2292             push(@$outputArray, "    if (!dynamicFrame)\n");
2293             push(@$outputArray, "        return JSValue::encode(jsUndefined());\n");
2294             $callWithArg = "dynamicFrame";
2295         } elsif ($callWith eq "ScriptState") {
2296             $callWithArg = "exec";
2297         } elsif ($callWith eq "ScriptExecutionContext") {
2298             push(@$outputArray, "    ScriptExecutionContext* scriptContext = static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext();\n");
2299             push(@$outputArray, "    if (!scriptContext)\n");
2300             push(@$outputArray, "        return JSValue::encode(jsUndefined());\n");
2301             $callWithArg = "scriptContext"; 
2302         }
2303         $functionString .= ", " if $paramIndex;
2304         $functionString .= $callWithArg;
2305         $paramIndex++;
2306     }
2307
2308     $implIncludes{"ExceptionCode.h"} = 1;
2309     $implIncludes{"JSDOMBinding.h"} = 1;
2310
2311     foreach my $parameter (@{$function->parameters}) {
2312         # Optional callbacks should be treated differently, because they always have a default value (0),
2313         # and we can reduce the number of overloaded functions that take a different number of parameters.
2314         # Optional arguments with [Optional=CallWithDefaultValue] or [Optional=CallWithNullValue]
2315         # should not generate an early call.
2316         my $optional = $parameter->extendedAttributes->{"Optional"};
2317         if ($optional && $optional ne "CallWithDefaultValue" && $optional ne "CallWithNullValue" && !$parameter->extendedAttributes->{"Callback"}) {
2318             # Generate early call if there are enough parameters.
2319             if (!$hasOptionalArguments) {
2320                 push(@$outputArray, "\n    size_t argsCount = exec->argumentCount();\n");
2321                 $hasOptionalArguments = 1;
2322             }
2323             push(@$outputArray, "    if (argsCount <= $argsIndex) {\n");
2324             GenerateImplementationFunctionCall($function, $functionString, $paramIndex, "    " x 2, $svgPropertyType, $implClassName);
2325             push(@$outputArray, "    }\n\n");
2326         }
2327
2328         my $name = $parameter->name;
2329         my $argType = $codeGenerator->StripModule($parameter->type);
2330
2331         if ($argType eq "XPathNSResolver") {
2332             push(@$outputArray, "    RefPtr<XPathNSResolver> customResolver;\n");
2333             push(@$outputArray, "    XPathNSResolver* resolver = toXPathNSResolver(exec->argument($argsIndex));\n");
2334             push(@$outputArray, "    if (!resolver) {\n");
2335             push(@$outputArray, "        customResolver = JSCustomXPathNSResolver::create(exec, exec->argument($argsIndex));\n");
2336             push(@$outputArray, "        if (exec->hadException())\n");
2337             push(@$outputArray, "            return JSValue::encode(jsUndefined());\n");
2338             push(@$outputArray, "        resolver = customResolver.get();\n");
2339             push(@$outputArray, "    }\n");
2340         } elsif ($parameter->extendedAttributes->{"Callback"}) {
2341             my $callbackClassName = GetCallbackClassName($argType);
2342             $implIncludes{"$callbackClassName.h"} = 1;
2343             if ($parameter->extendedAttributes->{"Optional"}) {
2344                 push(@$outputArray, "    RefPtr<$argType> $name;\n");
2345                 push(@$outputArray, "    if (exec->argumentCount() > $argsIndex && !exec->argument($argsIndex).isUndefinedOrNull()) {\n");
2346                 push(@$outputArray, "        if (!exec->argument($argsIndex).isObject()) {\n");
2347                 push(@$outputArray, "            setDOMException(exec, TYPE_MISMATCH_ERR);\n");
2348                 push(@$outputArray, "            return JSValue::encode(jsUndefined());\n");
2349                 push(@$outputArray, "        }\n");
2350                 push(@$outputArray, "        $name = ${callbackClassName}::create(asObject(exec->argument($argsIndex)), castedThis->globalObject());\n");
2351                 push(@$outputArray, "    }\n");
2352             } else {
2353                 push(@$outputArray, "    if (exec->argumentCount() <= $argsIndex || !exec->argument($argsIndex).isObject()) {\n");
2354                 push(@$outputArray, "        setDOMException(exec, TYPE_MISMATCH_ERR);\n");
2355                 push(@$outputArray, "        return JSValue::encode(jsUndefined());\n");
2356                 push(@$outputArray, "    }\n");
2357                 push(@$outputArray, "    RefPtr<$argType> $name = ${callbackClassName}::create(asObject(exec->argument($argsIndex)), castedThis->globalObject());\n");
2358             }
2359         } else {
2360             # If the "StrictTypeChecking" extended attribute is present, and the argument's type is an
2361             # interface type, then if the incoming value does not implement that interface, a TypeError
2362             # is thrown rather than silently passing NULL to the C++ code.
2363             # Per the Web IDL and ECMAScript semantics, incoming values can always be converted to both
2364             # strings and numbers, so do not throw TypeError if the argument is of these types.
2365             if ($function->signature->extendedAttributes->{"StrictTypeChecking"}) {
2366                 $implIncludes{"<runtime/Error.h>"} = 1;
2367
2368                 my $argValue = "exec->argument($argsIndex)";
2369                 if (!IsNativeType($argType)) {
2370                     push(@$outputArray, "    if (exec->argumentCount() > $argsIndex && !${argValue}.isUndefinedOrNull() && !${argValue}.inherits(&JS${argType}::s_info))\n");
2371                     push(@$outputArray, "        return throwVMTypeError(exec);\n");
2372                 }
2373             }
2374
2375             my $optional = $parameter->extendedAttributes->{"Optional"};
2376             my $parameterMissingPolicy = "MissingIsUndefined";
2377             if ($optional && $optional eq "CallWithNullValue") {
2378                 $parameterMissingPolicy = "MissingIsEmpty";
2379             }
2380
2381             push(@$outputArray, "    " . GetNativeTypeFromSignature($parameter) . " $name(" . JSValueToNative($parameter, "MAYBE_MISSING_PARAMETER(exec, $argsIndex, $parameterMissingPolicy)") . ");\n");
2382
2383             # If a parameter is "an index" and it's negative it should throw an INDEX_SIZE_ERR exception.
2384             # But this needs to be done in the bindings, because the type is unsigned and the fact that it
2385             # was negative will be lost by the time we're inside the DOM.
2386             if ($parameter->extendedAttributes->{"IsIndex"}) {
2387                 push(@$outputArray, "    if ($name < 0) {\n");
2388                 push(@$outputArray, "        setDOMException(exec, INDEX_SIZE_ERR);\n");
2389                 push(@$outputArray, "        return JSValue::encode(jsUndefined());\n");
2390                 push(@$outputArray, "    }\n");
2391             }
2392
2393             # Check if the type conversion succeeded.
2394             push(@$outputArray, "    if (exec->hadException())\n");
2395             push(@$outputArray, "        return JSValue::encode(jsUndefined());\n");
2396
2397             if ($codeGenerator->IsSVGTypeNeedingTearOff($argType) and not $implClassName =~ /List$/) {
2398                 push(@$outputArray, "    if (!$name) {\n");
2399                 push(@$outputArray, "        setDOMException(exec, TYPE_MISMATCH_ERR);\n");
2400                 push(@$outputArray, "        return JSValue::encode(jsUndefined());\n");
2401                 push(@$outputArray, "    }\n");
2402             }
2403         }
2404
2405         $functionString .= ", " if $paramIndex;
2406
2407         if ($argType eq "NodeFilter") {
2408             $functionString .= "$name.get()";
2409         } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($argType) and not $implClassName =~ /List$/) {
2410             $functionString .= "$name->propertyReference()";
2411         } else {
2412             $functionString .= $name;
2413         }
2414         $argsIndex++;
2415         $paramIndex++;
2416     }
2417
2418     if ($function->signature->extendedAttributes->{"NeedsUserGestureCheck"}) {
2419         $functionString .= ", " if $paramIndex;
2420         $functionString .= "ScriptController::processingUserGesture()";
2421         $paramIndex++;
2422         $implIncludes{"ScriptController.h"} = 1;
2423     }
2424
2425     return ($functionString, $paramIndex);
2426 }
2427
2428 sub GenerateCallbackHeader
2429 {
2430     my $object = shift;
2431     my $dataNode = shift;
2432
2433     my $interfaceName = $dataNode->name;
2434     my $className = "JS$interfaceName";
2435
2436     # - Add default header template and header protection
2437     push(@headerContentHeader, GenerateHeaderContentHeader($dataNode));
2438
2439     $headerIncludes{"ActiveDOMCallback.h"} = 1;
2440     $headerIncludes{"$interfaceName.h"} = 1;
2441     $headerIncludes{"JSCallbackData.h"} = 1;
2442     $headerIncludes{"<wtf/Forward.h>"} = 1;
2443
2444     push(@headerContent, "\nnamespace WebCore {\n\n");
2445     push(@headerContent, "class $className : public $interfaceName, public ActiveDOMCallback {\n");
2446     push(@headerContent, "public:\n");
2447
2448     # The static create() method.
2449     push(@headerContent, "    static PassRefPtr<$className> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject)\n");
2450     push(@headerContent, "    {\n");
2451     push(@headerContent, "        return adoptRef(new $className(callback, globalObject));\n");
2452     push(@headerContent, "    }\n\n");
2453
2454     # Destructor
2455     push(@headerContent, "    virtual ~$className();\n");
2456
2457     # Functions
2458     my $numFunctions = @{$dataNode->functions};
2459     if ($numFunctions > 0) {
2460         push(@headerContent, "\n    // Functions\n");
2461         foreach my $function (@{$dataNode->functions}) {
2462             my @params = @{$function->parameters};
2463             if (!$function->signature->extendedAttributes->{"Custom"} &&
2464                 !(GetNativeType($function->signature->type) eq "bool")) {
2465                 push(@headerContent, "    COMPILE_ASSERT(false)");
2466             }
2467
2468             push(@headerContent, "    virtual " . GetNativeType($function->signature->type) . " " . $function->signature->name . "(");
2469
2470             my @args = ();
2471             foreach my $param (@params) {
2472                 push(@args, GetNativeType($param->type) . " " . $param->name);
2473             }
2474             push(@headerContent, join(", ", @args));
2475
2476             push(@headerContent, ");\n");
2477         }
2478     }
2479
2480     push(@headerContent, "\nprivate:\n");
2481
2482     # Constructor
2483     push(@headerContent, "    $className(JSC::JSObject* callback, JSDOMGlobalObject*);\n\n");
2484
2485     # Private members
2486     push(@headerContent, "    JSCallbackData* m_data;\n");
2487     push(@headerContent, "};\n\n");
2488
2489     push(@headerContent, "} // namespace WebCore\n\n");
2490     my $conditionalString = GenerateConditionalString($dataNode);
2491     push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;
2492     push(@headerContent, "#endif\n");
2493 }
2494
2495 sub GenerateCallbackImplementation
2496 {
2497     my ($object, $dataNode) = @_;
2498
2499     my $interfaceName = $dataNode->name;
2500     my $className = "JS$interfaceName";
2501
2502     # - Add default header template
2503     push(@implContentHeader, GenerateImplementationContentHeader($dataNode));
2504
2505     $implIncludes{"ScriptExecutionContext.h"} = 1;
2506     $implIncludes{"<runtime/JSLock.h>"} = 1;
2507
2508     @implContent = ();
2509
2510     push(@implContent, "\nusing namespace JSC;\n\n");
2511     push(@implContent, "namespace WebCore {\n\n");
2512
2513     # Constructor
2514     push(@implContent, "${className}::${className}(JSObject* callback, JSDOMGlobalObject* globalObject)\n");
2515     push(@implContent, "    : ActiveDOMCallback(globalObject->scriptExecutionContext())\n");
2516     push(@implContent, "    , m_data(new JSCallbackData(callback, globalObject))\n");
2517     push(@implContent, "{\n");
2518     push(@implContent, "}\n\n");
2519
2520     # Destructor
2521     push(@implContent, "${className}::~${className}()\n");
2522     push(@implContent, "{\n");
2523     push(@implContent, "    ScriptExecutionContext* context = scriptExecutionContext();\n");
2524     push(@implContent, "    // When the context is destroyed, all tasks with a reference to a callback\n");
2525     push(@implContent, "    // should be deleted. So if the context is 0, we are on the context thread.\n");
2526     push(@implContent, "    if (!context || context->isContextThread())\n");
2527     push(@implContent, "        delete m_data;\n");
2528     push(@implContent, "    else\n");
2529     push(@implContent, "        context->postTask(DeleteCallbackDataTask::create(m_data));\n");
2530     push(@implContent, "#ifndef NDEBUG\n");
2531     push(@implContent, "    m_data = 0;\n");
2532     push(@implContent, "#endif\n");
2533     push(@implContent, "}\n");
2534
2535     # Functions
2536     my $numFunctions = @{$dataNode->functions};
2537     if ($numFunctions > 0) {
2538         push(@implContent, "\n// Functions\n");
2539         foreach my $function (@{$dataNode->functions}) {
2540             my @params = @{$function->parameters};
2541             if ($function->signature->extendedAttributes->{"Custom"} ||
2542                 !(GetNativeType($function->signature->type) eq "bool")) {
2543                 next;
2544             }
2545
2546             AddIncludesForTypeInImpl($function->signature->type);
2547             push(@implContent, "\n" . GetNativeType($function->signature->type) . " ${className}::" . $function->signature->name . "(");
2548
2549             my @args = ();
2550             foreach my $param (@params) {
2551                 AddIncludesForTypeInImpl($param->type, 1);
2552                 push(@args, GetNativeType($param->type) . " " . $param->name);
2553             }
2554             push(@implContent, join(", ", @args));
2555             push(@implContent, ")\n");
2556
2557             push(@implContent, "{\n");
2558             push(@implContent, "    if (!canInvokeCallback())\n");
2559             push(@implContent, "        return true;\n\n");
2560             push(@implContent, "    RefPtr<$className> protect(this);\n\n");
2561             push(@implContent, "    JSLock lock(SilenceAssertionsOnly);\n\n");
2562             push(@implContent, "    ExecState* exec = m_data->globalObject()->globalExec();\n");
2563             push(@implContent, "    MarkedArgumentBuffer args;\n");
2564
2565             foreach my $param (@params) {
2566                 my $paramName = $param->name;
2567                 if ($param->type eq "DOMString") {
2568                     push(@implContent, "    args.append(jsString(exec, ${paramName}));\n");
2569                 } else {
2570                     push(@implContent, "    args.append(toJS(exec, m_data->globalObject(), ${paramName}));\n");
2571                 }
2572             }
2573
2574             push(@implContent, "\n    bool raisedException = false;\n");
2575             push(@implContent, "    m_data->invokeCallback(args, &raisedException);\n");
2576             push(@implContent, "    return !raisedException;\n");
2577             push(@implContent, "}\n");
2578         }
2579     }
2580
2581     push(@implContent, "\n}\n");
2582     my $conditionalString = GenerateConditionalString($dataNode);
2583     push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
2584 }
2585
2586 sub GenerateImplementationFunctionCall()
2587 {
2588     my $function = shift;
2589     my $functionString = shift;
2590     my $paramIndex = shift;
2591     my $indent = shift;
2592     my $svgPropertyType = shift;
2593     my $implClassName = shift;
2594
2595     if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
2596         $functionString .= ", " if $paramIndex;
2597         $paramIndex += 2;
2598         $functionString .= "scriptArguments, callStack";
2599     }
2600
2601     if (@{$function->raisesExceptions}) {
2602         $functionString .= ", " if $paramIndex;
2603         $functionString .= "ec";
2604     }
2605     $functionString .= ")";
2606
2607     if ($function->signature->type eq "void") {
2608         push(@implContent, $indent . "$functionString;\n");
2609         push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions};
2610
2611         if ($svgPropertyType) {
2612             if (@{$function->raisesExceptions}) {
2613                 push(@implContent, $indent . "if (!ec)\n"); 
2614                 push(@implContent, $indent . "    imp->commitChange();\n");
2615             } else {
2616                 push(@implContent, $indent . "imp->commitChange();\n");
2617             }
2618         }
2619
2620         push(@implContent, $indent . "return JSValue::encode(jsUndefined());\n");
2621     } else {
2622         push(@implContent, "\n" . $indent . "JSC::JSValue result = " . NativeToJSValue($function->signature, 1, $implClassName, $functionString, "castedThis") . ";\n");
2623         push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions};
2624
2625         my $callWith = $function->signature->extendedAttributes->{"CallWith"};
2626         if ($callWith and $callWith eq "ScriptState") {
2627             push(@implContent, $indent . "if (exec->hadException())\n");
2628             push(@implContent, $indent . "    return JSValue::encode(jsUndefined());\n");
2629         }
2630
2631         push(@implContent, $indent . "return JSValue::encode(result);\n");
2632     }
2633 }
2634
2635 sub GetNativeTypeFromSignature
2636 {
2637     my $signature = shift;
2638     my $type = $codeGenerator->StripModule($signature->type);
2639
2640     if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) {
2641         # Special-case index arguments because we need to check that they aren't < 0.
2642         return "int";
2643     }
2644
2645     return GetNativeType($type);
2646 }
2647
2648 my %nativeType = (
2649     "CompareHow" => "Range::CompareHow",
2650     "DOMString" => "const String&",
2651     # FIXME: Add proper support for T[], T[]?, sequence<T>
2652     "DOMString[]" => "DOMStringList*",
2653     "DOMObject" => "ScriptValue",
2654     "NodeFilter" => "RefPtr<NodeFilter>",
2655     "SerializedScriptValue" => "RefPtr<SerializedScriptValue>",
2656     "IDBKey" => "RefPtr<IDBKey>",
2657     "boolean" => "bool",
2658     "double" => "double",
2659     "float" => "float",
2660     "short" => "short",
2661     "long" => "int",
2662     "unsigned long" => "unsigned",
2663     "unsigned short" => "unsigned short",
2664     "long long" => "long long",
2665     "unsigned long long" => "unsigned long long",
2666     "MediaQueryListListener" => "RefPtr<MediaQueryListListener>",
2667     "DOMTimeStamp" => "DOMTimeStamp"
2668 );
2669
2670 sub GetNativeType
2671 {
2672     my $type = shift;
2673
2674     my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($type);
2675     return "${svgNativeType}*" if $svgNativeType;
2676     return $nativeType{$type} if exists $nativeType{$type};
2677
2678     # For all other types, the native type is a pointer with same type name as the IDL type.
2679     return "${type}*";
2680 }
2681
2682 sub GetSVGPropertyTypes
2683 {
2684     my $implType = shift;
2685
2686     my $svgPropertyType;
2687     my $svgListPropertyType;
2688     my $svgNativeType;
2689
2690     return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $implType =~ /SVG/;
2691     
2692     $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implType);
2693     return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $svgNativeType;
2694
2695     # Append space to avoid compilation errors when using  PassRefPtr<$svgNativeType>
2696     $svgNativeType = "$svgNativeType ";
2697
2698     my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implType);
2699     if ($svgNativeType =~ /SVGPropertyTearOff/) {
2700         $svgPropertyType = $svgWrappedNativeType;
2701         $headerIncludes{"$svgWrappedNativeType.h"} = 1;
2702         $headerIncludes{"SVGAnimatedPropertyTearOff.h"} = 1;
2703     } elsif ($svgNativeType =~ /SVGListPropertyTearOff/ or $svgNativeType =~ /SVGStaticListPropertyTearOff/) {
2704         $svgListPropertyType = $svgWrappedNativeType;
2705         $headerIncludes{"$svgWrappedNativeType.h"} = 1;
2706         $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;
2707     } elsif ($svgNativeType =~ /SVGTransformListPropertyTearOff/) {
2708         $svgListPropertyType = $svgWrappedNativeType;
2709         $headerIncludes{"$svgWrappedNativeType.h"} = 1;
2710         $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;
2711         $headerIncludes{"SVGTransformListPropertyTearOff.h"} = 1;
2712     } elsif ($svgNativeType =~ /SVGPathSegListPropertyTearOff/) {
2713         $svgListPropertyType = $svgWrappedNativeType;
2714         $headerIncludes{"$svgWrappedNativeType.h"} = 1;
2715         $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;
2716         $headerIncludes{"SVGPathSegListPropertyTearOff.h"} = 1;
2717     }
2718
2719     return ($svgPropertyType, $svgListPropertyType, $svgNativeType);
2720 }
2721
2722 sub IsNativeType
2723 {
2724     my $type = shift;
2725     return exists $nativeType{$type};
2726 }
2727
2728 sub IsArrayType
2729 {
2730     my $type = shift;
2731     # FIXME: Add proper support for T[], T[]?, sequence<T>.
2732     return $type =~ m/\[\]$/;
2733 }
2734
2735 sub JSValueToNative
2736 {
2737     my $signature = shift;
2738     my $value = shift;
2739
2740     my $conditional = $signature->extendedAttributes->{"Conditional"};
2741     my $type = $codeGenerator->StripModule($signature->type);
2742
2743     return "$value.toBoolean(exec)" if $type eq "boolean";
2744     return "$value.toNumber(exec)" if $type eq "double";
2745     return "$value.toFloat(exec)" if $type eq "float";
2746     return "$value.toInt32(exec)" if $type eq "long" or $type eq "short";
2747     return "$value.toUInt32(exec)" if $type eq "unsigned long" or $type eq "unsigned short";
2748     return "static_cast<$type>($value.toInteger(exec))" if $type eq "long long" or $type eq "unsigned long long";
2749
2750     return "valueToDate(exec, $value)" if $type eq "Date";
2751     return "static_cast<Range::CompareHow>($value.toInt32(exec))" if $type eq "CompareHow";
2752
2753     if ($type eq "DOMString") {
2754         return "valueToStringWithNullCheck(exec, $value)" if $signature->extendedAttributes->{"ConvertNullToNullString"} || $signature->extendedAttributes->{"Reflect"};
2755         return "valueToStringWithUndefinedOrNullCheck(exec, $value)" if $signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"};
2756         return "ustringToString($value.isEmpty() ? UString() : $value.toString(exec))";
2757     }
2758
2759     if ($type eq "DOMObject") {
2760         return "exec->globalData(), $value";
2761     }
2762
2763     if ($type eq "NodeFilter") {
2764         AddToImplIncludes("JS$type.h", $conditional);
2765         return "to$type(exec->globalData(), $value)";
2766     }
2767
2768     if ($type eq "MediaQueryListListener") {
2769         AddToImplIncludes("MediaQueryListListener.h", $conditional);
2770         return "MediaQueryListListener::create(ScriptValue(exec->globalData(), " . $value ."))";
2771     }
2772
2773     if ($type eq "SerializedScriptValue" or $type eq "any") {
2774         AddToImplIncludes("SerializedScriptValue.h", $conditional);
2775         return "SerializedScriptValue::create(exec, $value)";
2776     }
2777
2778     if ($type eq "IDBKey") {
2779         AddToImplIncludes("IDBBindingUtilities.h", $conditional);
2780         AddToImplIncludes("IDBKey.h", $conditional);
2781         return "createIDBKeyFromValue(exec, $value)";
2782     }
2783
2784     if ($type eq "DOMString[]") {
2785         AddToImplIncludes("JSDOMStringList.h", $conditional);
2786         return "toDOMStringList($value)";
2787     }
2788
2789     AddToImplIncludes("HTMLOptionElement.h", $conditional) if $type eq "HTMLOptionElement";
2790     AddToImplIncludes("JSCustomVoidCallback.h", $conditional) if $type eq "VoidCallback";
2791     AddToImplIncludes("Event.h", $conditional) if $type eq "Event";
2792
2793     # Default, assume autogenerated type conversion routines
2794     AddToImplIncludes("JS$type.h", $conditional);
2795     return "to$type($value)";
2796 }
2797
2798 sub NativeToJSValue
2799 {
2800     my $signature = shift;
2801     my $inFunctionCall = shift;
2802     my $implClassName = shift;
2803     my $value = shift;
2804     my $thisValue = shift;
2805
2806     my $conditional = $signature->extendedAttributes->{"Conditional"};
2807     my $type = $codeGenerator->StripModule($signature->type);
2808
2809     return "jsBoolean($value)" if $type eq "boolean";
2810
2811     # Need to check Date type before IsPrimitiveType().
2812     if ($type eq "Date") {
2813         return "jsDateOrNull(exec, $value)";
2814     }
2815
2816     if ($signature->extendedAttributes->{"Reflect"} and ($type eq "unsigned long" or $type eq "unsigned short")) {
2817         $value =~ s/getUnsignedIntegralAttribute/getIntegralAttribute/g;
2818         return "jsNumber(std::max(0, " . $value . "))";
2819     }
2820
2821     if ($codeGenerator->IsPrimitiveType($type) or $type eq "DOMTimeStamp") {
2822         return "jsNumber($value)";
2823     }
2824
2825     if ($codeGenerator->IsStringType($type)) {
2826         AddToImplIncludes("KURL.h", $conditional);
2827         my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"};
2828         if (defined $conv) {
2829             return "jsStringOrNull(exec, $value)" if $conv eq "Null";
2830             return "jsStringOrUndefined(exec, $value)" if $conv eq "Undefined";
2831             return "jsStringOrFalse(exec, $value)" if $conv eq "False";
2832
2833             die "Unknown value for ConvertNullStringTo extended attribute";
2834         }
2835         $conv = $signature->extendedAttributes->{"ConvertScriptString"};
2836         return "jsOwnedStringOrNull(exec, $value)" if $conv;
2837         AddToImplIncludes("<runtime/JSString.h>", $conditional);
2838         return "jsString(exec, $value)";
2839     }
2840     
2841     my $globalObject = "$thisValue->globalObject()";
2842
2843     if ($type eq "CSSStyleDeclaration") {
2844         AddToImplIncludes("CSSMutableStyleDeclaration.h", $conditional);
2845     }
2846
2847     if ($type eq "NodeList") {
2848         AddToImplIncludes("NameNodeList.h", $conditional);
2849     }
2850
2851     if ($type eq "DOMObject") {
2852         if ($implClassName eq "Document") {
2853             AddToImplIncludes("JSCanvasRenderingContext2D.h", $conditional);
2854         } else {
2855             return "($value.hasNoValue() ? jsNull() : $value.jsValue())";
2856         }
2857     } elsif ($type =~ /SVGPathSeg/) {
2858         AddToImplIncludes("JS$type.h", $conditional);
2859         my $joinedName = $type;
2860         $joinedName =~ s/Abs|Rel//;
2861         AddToImplIncludes("$joinedName.h", $conditional);
2862     } elsif ($type eq "SerializedScriptValue" or $type eq "any") {
2863         AddToImplIncludes("SerializedScriptValue.h", $conditional);
2864         return "$value ? $value->deserialize(exec, castedThis->globalObject()) : jsNull()";
2865     } else {
2866         # Default, include header with same name.
2867         AddToImplIncludes("JS$type.h", $conditional);
2868         AddToImplIncludes("$type.h", $conditional) if not $codeGenerator->AvoidInclusionOfType($type);
2869     }
2870
2871     return $value if $codeGenerator->IsSVGAnimatedType($type);
2872
2873     if ($signature->extendedAttributes->{"ReturnsNew"}) {        
2874         return "toJSNewlyCreated(exec, $globalObject, WTF::getPtr($value))";
2875     }
2876
2877     if ($codeGenerator->IsSVGAnimatedType($implClassName)) {
2878         # Convert from abstract SVGProperty to real type, so the right toJS() method can be invoked.
2879         $value = "static_cast<" . GetNativeType($type) . ">($value)";
2880     } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($type) and not $implClassName =~ /List$/) {
2881         my $tearOffType = $codeGenerator->GetSVGTypeNeedingTearOff($type);
2882         if ($codeGenerator->IsSVGTypeWithWritablePropertiesNeedingTearOff($type) and $inFunctionCall eq 0 and not defined $signature->extendedAttributes->{"Immutable"}) {
2883             my $getter = $value;
2884             $getter =~ s/imp\.//;
2885             $getter =~ s/imp->//;
2886             $getter =~ s/\(\)//;
2887             my $updateMethod = "&${implClassName}::update" . $codeGenerator->WK_ucfirst($getter);
2888
2889             my $selfIsTearOffType = $codeGenerator->IsSVGTypeNeedingTearOff($implClassName);
2890             if ($selfIsTearOffType) {
2891                 AddToImplIncludes("SVGStaticPropertyWithParentTearOff.h", $conditional);
2892                 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyWithParentTearOff<$implClassName, /;
2893
2894                 if ($value =~ /matrix/ and $implClassName eq "SVGTransform") {
2895                     # SVGTransform offers a matrix() method for internal usage that returns an AffineTransform
2896                     # and a svgMatrix() method returning a SVGMatrix, used for the bindings.
2897                     $value =~ s/matrix/svgMatrix/;
2898                 }
2899
2900                 $value = "${tearOffType}::create(castedThis->impl(), $value, $updateMethod)";
2901             } else {
2902                 AddToImplIncludes("SVGStaticPropertyTearOff.h", $conditional);
2903                 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyTearOff<$implClassName, /;
2904                 $value = "${tearOffType}::create(imp, $value, $updateMethod)";
2905             }
2906         } elsif ($tearOffType =~ /SVGStaticListPropertyTearOff/) {
2907             $value = "${tearOffType}::create(imp, $value)";
2908         } elsif (not $tearOffType =~ /SVG(Point|PathSeg)List/) {
2909             $value = "${tearOffType}::create($value)";
2910         }
2911     }
2912
2913     return "toJS(exec, $globalObject, WTF::getPtr($value))";
2914 }
2915
2916 sub ceilingToPowerOf2
2917 {
2918     my ($size) = @_;
2919
2920     my $powerOf2 = 1;
2921     while ($size > $powerOf2) {
2922         $powerOf2 <<= 1;
2923     }
2924
2925     return $powerOf2;
2926 }
2927
2928 # Internal Helper
2929 sub GenerateHashTable
2930 {
2931     my $object = shift;
2932
2933     my $name = shift;
2934     my $size = shift;
2935     my $keys = shift;
2936     my $specials = shift;
2937     my $value1 = shift;
2938     my $value2 = shift;
2939     my $conditionals = shift;
2940
2941     # Generate size data for compact' size hash table
2942
2943     my @table = ();
2944     my @links = ();
2945
2946     my $compactSize = ceilingToPowerOf2($size * 2);
2947
2948     my $maxDepth = 0;
2949     my $collisions = 0;
2950     my $numEntries = $compactSize;
2951
2952     my $i = 0;
2953     foreach (@{$keys}) {
2954         my $depth = 0;
2955         my $h = $object->GenerateHashValue($_) % $numEntries;
2956
2957         while (defined($table[$h])) {
2958             if (defined($links[$h])) {
2959                 $h = $links[$h];
2960                 $depth++;
2961             } else {
2962                 $collisions++;
2963                 $links[$h] = $compactSize;
2964                 $h = $compactSize;
2965                 $compactSize++;
2966             }
2967         }
2968
2969         $table[$h] = $i;
2970
2971         $i++;
2972         $maxDepth = $depth if ($depth > $maxDepth);
2973     }
2974
2975     # Start outputing the hashtables
2976     my $nameEntries = "${name}Values";
2977     $nameEntries =~ s/:/_/g;
2978
2979     if (($name =~ /Prototype/) or ($name =~ /Constructor/)) {
2980         my $type = $name;
2981         my $implClass;
2982
2983         if ($name =~ /Prototype/) {
2984             $type =~ s/Prototype.*//;
2985             $implClass = $type; $implClass =~ s/Wrapper$//;
2986             push(@implContent, "/* Hash table for prototype */\n");
2987         } else {
2988             $type =~ s/Constructor.*//;
2989             $implClass = $type; $implClass =~ s/Constructor$//;
2990             push(@implContent, "/* Hash table for constructor */\n");
2991         }
2992     } else {
2993         push(@implContent, "/* Hash table */\n");
2994     }
2995
2996     # Dump the hash table
2997     push(@implContent, "#if ENABLE(JIT)\n");
2998     push(@implContent, "#define THUNK_GENERATOR(generator) , generator\n");
2999     push(@implContent, "#else\n");
3000     push(@implContent, "#define THUNK_GENERATOR(generator)\n");
3001     push(@implContent, "#endif\n");
3002     push(@implContent, "#if ENABLE(DFG_JIT)\n");
3003     push(@implContent, "#define INTRINSIC(intrinsic) , intrinsic\n");
3004     push(@implContent, "#else\n");
3005     push(@implContent, "#define INTRINSIC(intrinsic)\n");
3006     push(@implContent, "#endif\n");
3007     push(@implContent, "\nstatic const HashTableValue $nameEntries\[\] =\n\{\n");
3008     $i = 0;
3009     foreach my $key (@{$keys}) {
3010         my $conditional;
3011         my $targetType;
3012
3013         if ($conditionals) {
3014             $conditional = $conditionals->{$key};
3015         }
3016         if ($conditional) {
3017             my $conditionalString = GenerateConditionalStringFromAttributeValue($conditional);
3018             push(@implContent, "#if ${conditionalString}\n");
3019         }
3020         
3021         if ("@$specials[$i]" =~ m/Function/) {
3022             $targetType = "static_cast<NativeFunction>";
3023         } else {
3024             $targetType = "static_cast<PropertySlot::GetValueFunc>";
3025         }
3026         push(@implContent, "    { \"$key\", @$specials[$i], (intptr_t)" . $targetType . "(@$value1[$i]), (intptr_t)@$value2[$i] THUNK_GENERATOR(0) INTRINSIC(DFG::NoIntrinsic) },\n");
3027         if ($conditional) {
3028             push(@implContent, "#endif\n");
3029         }
3030         ++$i;
3031     }
3032     push(@implContent, "    { 0, 0, 0, 0 THUNK_GENERATOR(0) INTRINSIC(DFG::NoIntrinsic) }\n");
3033     push(@implContent, "};\n\n");
3034     push(@implContent, "#undef THUNK_GENERATOR\n");
3035     my $compactSizeMask = $numEntries - 1;
3036     push(@implContent, "static JSC_CONST_HASHTABLE HashTable $name = { $compactSize, $compactSizeMask, $nameEntries, 0 };\n");
3037 }
3038
3039 # Paul Hsieh's SuperFastHash
3040 # http://www.azillionmonkeys.com/qed/hash.html
3041 sub GenerateHashValue
3042 {
3043     my $object = shift;
3044
3045     my @chars = split(/ */, $_[0]);
3046
3047     # This hash is designed to work on 16-bit chunks at a time. But since the normal case
3048     # (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they
3049     # were 16-bit chunks, which should give matching results
3050     
3051     my $EXP2_32 = 4294967296;
3052     
3053     my $hash = 0x9e3779b9;
3054     my $l    = scalar @chars; #I wish this was in Ruby --- Maks
3055     my $rem  = $l & 1;
3056     $l = $l >> 1;
3057     
3058     my $s = 0;
3059     
3060     # Main loop
3061     for (; $l > 0; $l--) {
3062         $hash   += ord($chars[$s]);
3063         my $tmp = leftShift(ord($chars[$s+1]), 11) ^ $hash;
3064         $hash   = (leftShift($hash, 16)% $EXP2_32) ^ $tmp;
3065         $s += 2;
3066         $hash += $hash >> 11;
3067         $hash %= $EXP2_32;
3068     }
3069     
3070     # Handle end case
3071     if ($rem != 0) {
3072         $hash += ord($chars[$s]);
3073         $hash ^= (leftShift($hash, 11)% $EXP2_32);
3074         $hash += $hash >> 17;
3075     }
3076     
3077     # Force "avalanching" of final 127 bits
3078     $hash ^= leftShift($hash, 3);
3079     $hash += ($hash >> 5);
3080     $hash = ($hash% $EXP2_32);
3081     $hash ^= (leftShift($hash, 2)% $EXP2_32);
3082     $hash += ($hash >> 15);
3083     $hash = $hash% $EXP2_32;
3084     $hash ^= (leftShift($hash, 10)% $EXP2_32);
3085     
3086     # Save 8 bits for StringImpl to use as flags.
3087     $hash &= 0xffffff;
3088     
3089     # This avoids ever returning a hash code of 0, since that is used to
3090     # signal "hash not computed yet". Setting the high bit maintains
3091     # reasonable fidelity to a hash code of 0 because it is likely to yield
3092     # exactly 0 when hash lookup masks out the high bits.
3093     $hash = (0x80000000 >> 8) if ($hash == 0);
3094     
3095     return $hash;
3096 }
3097
3098 # Internal helper
3099 sub WriteData
3100 {
3101     if (defined($IMPL)) {
3102         # Write content to file.
3103         print $IMPL @implContentHeader;
3104
3105         my @includes = ();
3106         my %implIncludeConditions = ();
3107         foreach my $include (keys %implIncludes) {
3108             my $condition = $implIncludes{$include};
3109             my $checkType = $include;
3110             $checkType =~ s/\.h//;
3111             next if $codeGenerator->IsSVGAnimatedType($checkType);
3112
3113             $include = "\"$include\"" unless $include =~ /^["<]/; # "
3114
3115             if ($condition eq 1) {
3116                 push @includes, $include;
3117             } else {
3118                 push @{$implIncludeConditions{$condition}}, $include;
3119             }
3120         }
3121         foreach my $include (sort @includes) {
3122             print $IMPL "#include $include\n";
3123         }
3124         foreach my $condition (sort keys %implIncludeConditions) {
3125             print $IMPL "\n#if " . GenerateConditionalStringFromAttributeValue($condition) . "\n";
3126             foreach my $include (sort @{$implIncludeConditions{$condition}}) {
3127                 print $IMPL "#include $include\n";
3128             }
3129             print $IMPL "#endif\n";
3130         }
3131
3132         print $IMPL @implContent;
3133         close($IMPL);
3134         undef($IMPL);
3135
3136         @implContentHeader = ();
3137         @implContent = ();
3138         %implIncludes = ();
3139     }
3140
3141     if (defined($HEADER)) {
3142         # Write content to file.
3143         print $HEADER @headerContentHeader;
3144
3145         my @includes = ();
3146         foreach my $include (keys %headerIncludes) {
3147             $include = "\"$include\"" unless $include =~ /^["<]/; # "
3148             push @includes, $include;
3149         }
3150         foreach my $include (sort @includes) {
3151             print $HEADER "#include $include\n";
3152         }
3153
3154         print $HEADER @headerContent;
3155
3156         @includes = ();
3157         foreach my $include (keys %headerTrailingIncludes) {
3158             $include = "\"$include\"" unless $include =~ /^["<]/; # "
3159             push @includes, $include;
3160         }
3161         foreach my $include (sort @includes) {
3162             print $HEADER "#include $include\n";
3163         }
3164
3165         close($HEADER);
3166         undef($HEADER);
3167
3168         @headerContentHeader = ();
3169         @headerContent = ();
3170         %headerIncludes = ();
3171         %headerTrailingIncludes = ();
3172     }
3173
3174     if (defined($DEPS)) {
3175         # Write dependency file.
3176         print $DEPS @depsContent;
3177         close($DEPS);
3178         undef($DEPS);
3179
3180         @depsContent = ();
3181     }
3182 }
3183
3184 sub GenerateConstructorDeclaration
3185 {
3186     my $outputArray = shift;
3187     my $className = shift;
3188     my $dataNode = shift;
3189
3190     my $constructorClassName = "${className}Constructor";
3191     my $canConstruct = $dataNode->extendedAttributes->{"CanBeConstructed"} || $dataNode->extendedAttributes->{"Constructor"} || $dataNode->extendedAttributes->{"JSCustomConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"};
3192     my $callWith = $dataNode->extendedAttributes->{"CallWith"};
3193
3194     push(@$outputArray, "class ${constructorClassName} : public DOMConstructorObject {\n");
3195     push(@$outputArray, "private:\n");
3196     push(@$outputArray, "    ${constructorClassName}(JSC::Structure*, JSDOMGlobalObject*);\n");
3197     push(@$outputArray, "    void finishCreation(JSC::ExecState*, JSDOMGlobalObject*);\n\n");
3198
3199     push(@$outputArray, "public:\n");
3200     push(@$outputArray, "    typedef DOMConstructorObject Base;\n");
3201     push(@$outputArray, "    static $constructorClassName* create(JSC::ExecState* exec, JSC::Structure* structure, JSDOMGlobalObject* globalObject)\n");
3202     push(@$outputArray, "    {\n");
3203     push(@$outputArray, "        $constructorClassName* ptr = new (JSC::allocateCell<$constructorClassName>(*exec->heap())) $constructorClassName(structure, globalObject);\n");
3204     push(@$outputArray, "        ptr->finishCreation(exec, globalObject);\n");
3205     push(@$outputArray, "        return ptr;\n");
3206     push(@$outputArray, "    }\n\n");
3207
3208     push(@$outputArray, "    static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n");
3209     push(@$outputArray, "    virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n");
3210     push(@$outputArray, "    static const JSC::ClassInfo s_info;\n");
3211
3212     push(@$outputArray, "    static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)\n");
3213     push(@$outputArray, "    {\n");
3214     push(@$outputArray, "        return JSC::Structure::create(globalData, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), &s_info);\n");
3215     push(@$outputArray, "    }\n");
3216
3217     push(@$outputArray, "protected:\n");
3218     push(@$outputArray, "    static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::ImplementsHasInstance | DOMConstructorObject::StructureFlags;\n");
3219
3220     if ($canConstruct) {
3221         push(@$outputArray, "    static JSC::EncodedJSValue JSC_HOST_CALL construct${className}(JSC::ExecState*);\n");
3222         push(@$outputArray, "    static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&);\n");
3223     }
3224     push(@$outputArray, "};\n\n");
3225 }
3226
3227 sub GenerateConstructorDefinition
3228 {
3229     my $outputArray = shift;
3230
3231     my $className = shift;
3232     my $protoClassName = shift;
3233     my $interfaceName = shift;
3234     my $visibleClassName = shift;
3235     my $dataNode = shift;
3236
3237     my $constructorClassName = "${className}Constructor";
3238     my $numberOfconstructParameters = $dataNode->extendedAttributes->{"ConstructorParameters"};
3239
3240     push(@$outputArray, "const ClassInfo ${constructorClassName}::s_info = { \"${visibleClassName}Constructor\", &DOMConstructorObject::s_info, &${constructorClassName}Table, 0, CREATE_METHOD_TABLE($constructorClassName) };\n\n");
3241
3242     push(@$outputArray, "${constructorClassName}::${constructorClassName}(Structure* structure, JSDOMGlobalObject* globalObject)\n");
3243     push(@$outputArray, "    : DOMConstructorObject(structure, globalObject)\n");
3244     push(@$outputArray, "{\n");
3245     push(@$outputArray, "}\n\n");
3246
3247     push(@$outputArray, "void ${constructorClassName}::finishCreation(ExecState* exec, JSDOMGlobalObject* globalObject)\n");
3248     push(@$outputArray, "{\n");
3249     push(@$outputArray, "    Base::finishCreation(exec->globalData());\n");
3250     push(@$outputArray, "    ASSERT(inherits(&s_info));\n");
3251     if ($interfaceName eq "DOMWindow") {
3252         push(@$outputArray, "    putDirect(exec->globalData(), exec->propertyNames().prototype, globalObject->prototype(), DontDelete | ReadOnly);\n");
3253     } else {
3254         push(@$outputArray, "    putDirect(exec->globalData(), exec->propertyNames().prototype, ${protoClassName}::self(exec, globalObject), DontDelete | ReadOnly);\n");
3255     }
3256     push(@$outputArray, "    putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(${numberOfconstructParameters}), ReadOnly | DontDelete | DontEnum);\n") if $numberOfconstructParameters;
3257     push(@$outputArray, "}\n\n");
3258
3259     push(@$outputArray, "bool ${constructorClassName}::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n");
3260     push(@$outputArray, "{\n");
3261     push(@$outputArray, "    return getStaticValueSlot<${constructorClassName}, JSDOMWrapper>(exec, &${constructorClassName}Table, static_cast<${constructorClassName}*>(cell), propertyName, slot);\n");
3262     push(@$outputArray, "}\n\n");
3263
3264     push(@$outputArray, "bool ${constructorClassName}::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\n");
3265     push(@$outputArray, "{\n");
3266     push(@$outputArray, "    return getStaticValueDescriptor<${constructorClassName}, JSDOMWrapper>(exec, &${constructorClassName}Table, this, propertyName, descriptor);\n");
3267     push(@$outputArray, "}\n\n");
3268
3269     if ($dataNode->extendedAttributes->{"CanBeConstructed"} || $dataNode->extendedAttributes->{"Constructor"} || $dataNode->extendedAttributes->{"JSCustomConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"}) {
3270         if (!($dataNode->extendedAttributes->{"JSCustomConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
3271             push(@$outputArray, "EncodedJSValue JSC_HOST_CALL ${constructorClassName}::construct${className}(ExecState* exec)\n");
3272             push(@$outputArray, "{\n");
3273
3274             push(@$outputArray, "    ${constructorClassName}* jsConstructor = static_cast<${constructorClassName}*>(exec->callee());\n");
3275
3276             if ($dataNode->extendedAttributes->{"Constructor"}) {
3277                 my $function = $dataNode->constructor;
3278                 my @constructorArgList;
3279
3280                 $implIncludes{"<runtime/Error.h>"} = 1;
3281
3282                 GenerateArgumentsCountCheck($outputArray, $function, $dataNode);
3283
3284                 if (@{$function->raisesExceptions} || $dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
3285                     $implIncludes{"ExceptionCode.h"} = 1;
3286                     push(@$outputArray, "    ExceptionCode ec = 0;\n");
3287                 }
3288
3289                 # For now, we do not support SVG constructors.
3290                 # We do not also support a constructor [Optional] argument without CallWithDefaultValue
3291                 # nor CallWithNullValue.
3292                 my $numParameters = @{$function->parameters};
3293                 my ($dummy, $paramIndex) = GenerateParametersCheck($outputArray, $function, $dataNode, $numParameters, $interfaceName, "constructorCallback", undef, undef, undef);
3294
3295                 if ($dataNode->extendedAttributes->{"CallWith"} && $dataNode->extendedAttributes->{"CallWith"} eq "ScriptExecutionContext") {
3296                     push(@constructorArgList, "context");
3297                     push(@$outputArray, "    ScriptExecutionContext* context = jsConstructor->scriptExecutionContext();\n");
3298                     push(@$outputArray, "    if (!context)\n");
3299                     push(@$outputArray, "        return throwVMError(exec, createReferenceError(exec, \"${interfaceName} constructor associated document is unavailable\"));\n");
3300                 }
3301
3302                 my $index = 0;
3303                 foreach my $parameter (@{$function->parameters}) {
3304                     last if $index eq $paramIndex;
3305                     push(@constructorArgList, $parameter->name);
3306                     $index++;
3307                 }
3308
3309                 if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
3310                     push(@constructorArgList, "ec");
3311                 }
3312                 my $constructorArg = join(", ", @constructorArgList);
3313                 push(@$outputArray, "    RefPtr<${interfaceName}> object = ${interfaceName}::create(${constructorArg});\n");
3314                 if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
3315                     push(@$outputArray, "    if (ec) {\n");
3316                     push(@$outputArray, "        setDOMException(exec, ec);\n");
3317                     push(@$outputArray, "        return JSValue::encode(JSValue());\n");
3318                     push(@$outputArray, "    }\n");
3319                 }
3320             } else {
3321                 my $constructorArg = "";
3322                 if ($dataNode->extendedAttributes->{"CallWith"} and $dataNode->extendedAttributes->{"CallWith"} eq "ScriptExecutionContext") {
3323                     $constructorArg = "context";
3324                     push(@$outputArray, "    ScriptExecutionContext* context = static_cast<${constructorClassName}*>(exec->callee())->scriptExecutionContext();\n");
3325                     push(@$outputArray, "    if (!context)\n");
3326                     push(@$outputArray, "        return throwVMError(exec, createReferenceError(exec, \"${interfaceName} constructor associated document is unavailable\"));\n");
3327                 }
3328                 push(@$outputArray, "    RefPtr<${interfaceName}> object = ${interfaceName}::create(${constructorArg});\n");
3329             }
3330
3331             push(@$outputArray, "    return JSValue::encode(asObject(toJS(exec, jsConstructor->globalObject(), object.get())));\n");
3332             push(@$outputArray, "}\n\n");
3333         }
3334
3335         push(@$outputArray, "ConstructType ${constructorClassName}::getConstructData(JSCell*, ConstructData& constructData)\n");
3336         push(@$outputArray, "{\n");
3337         push(@$outputArray, "    constructData.native.function = construct${className};\n");
3338         push(@$outputArray, "    return ConstructTypeHost;\n");
3339         push(@$outputArray, "}\n\n");
3340     }
3341 }
3342
3343 1;