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