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