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