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