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