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