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