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