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