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