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