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