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