24d5c42299133938a30dcbe175c7443216647bea
[WebKit.git] / Source / WebCore / bindings / scripts / CodeGeneratorJS.pm
1 #
2 # Copyright (C) 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3 # Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
4 # Copyright (C) 2006, 2007 Samuel Weinig <sam@webkit.org>
5 # Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
6 # Copyright (C) 2006, 2007, 2008, 2009, 2010 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" if (@{$interface->parents} eq 0);
171     return "JS" . $interface->parents(0);
172 }
173
174 sub GetCallbackClassName
175 {
176     my $className = shift;
177
178     return "JS$className";
179 }
180
181 sub IndexGetterReturnsStrings
182 {
183     my $type = shift;
184
185     return 1 if $type eq "CSSStyleDeclaration" or $type eq "MediaList" or $type eq "DOMStringList" or $type eq "DOMTokenList" or $type eq "DOMSettableTokenList";
186     return 0;
187 }
188
189 sub AddIncludesForTypeInImpl
190 {
191     my $type = shift;
192     my $isCallback = @_ ? shift : 0;
193     
194     AddIncludesForType($type, $isCallback, \%implIncludes);
195 }
196
197 sub AddIncludesForTypeInHeader
198 {
199     my $type = shift;
200     my $isCallback = @_ ? shift : 0;
201     
202     AddIncludesForType($type, $isCallback, \%headerIncludes);
203 }
204
205 sub AddIncludesForType
206 {
207     my $type = shift;
208     my $isCallback = shift;
209     my $includesRef = shift;
210
211     # When we're finished with the one-file-per-class
212     # reorganization, we won't need these special cases.
213     if ($codeGenerator->IsPrimitiveType($type) or $codeGenerator->SkipIncludeHeader($type)
214         or $type eq "DOMString" or $type eq "any" or $type eq "Array" or $type eq "DOMTimeStamp") {
215     } elsif ($type =~ /SVGPathSeg/) {
216         my $joinedName = $type;
217         $joinedName =~ s/Abs|Rel//;
218         $includesRef->{"${joinedName}.h"} = 1;
219     } elsif ($type eq "XPathNSResolver") {
220         $includesRef->{"JSXPathNSResolver.h"} = 1;
221         $includesRef->{"JSCustomXPathNSResolver.h"} = 1;
222     } elsif ($type eq "SerializedScriptValue") {
223         $includesRef->{"SerializedScriptValue.h"} = 1;
224     } elsif ($isCallback) {
225         $includesRef->{"JS${type}.h"} = 1;
226     } elsif ($codeGenerator->IsTypedArrayType($type)) {
227         $includesRef->{"<wtf/${type}.h>"} = 1;
228     } elsif ($codeGenerator->GetSequenceType($type)) {
229     } elsif ($codeGenerator->GetArrayType($type)) {
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 HashValueForClassAndName
294 {
295     my $class = shift;
296     my $name = shift;
297
298     # SVG Filter enums live in WebCore namespace (platform/graphics/)
299     if ($class =~ /^SVGFE*/ or $class =~ /^SVGComponentTransferFunctionElement$/) {
300         return "WebCore::$name";
301     }
302
303     return "${class}::$name";
304 }
305
306 sub hashTableAccessor
307 {
308     my $noStaticTables = shift;
309     my $className = shift;
310     if ($noStaticTables) {
311         return "get${className}Table(exec)";
312     } else {
313         return "&${className}Table";
314     }
315 }
316
317 sub prototypeHashTableAccessor
318 {
319     my $noStaticTables = shift;
320     my $className = shift;
321     if ($noStaticTables) {
322         return "get${className}PrototypeTable(exec)";
323     } else {
324         return "&${className}PrototypeTable";
325     }
326 }
327
328 sub constructorHashTableAccessor
329 {
330     my $noStaticTables = shift;
331     my $constructorClassName = shift;
332     if ($noStaticTables) {
333         return "get${constructorClassName}Table(exec)";
334     } else {
335         return "&${constructorClassName}Table";
336     }
337 }
338
339 sub GetGenerateIsReachable
340 {
341     my $interface = shift;
342     return $interface->extendedAttributes->{"GenerateIsReachable"};
343 }
344
345 sub GetCustomIsReachable
346 {
347     my $interface = shift;
348     return $interface->extendedAttributes->{"CustomIsReachable"};
349 }
350
351 sub GenerateGetOwnPropertySlotBody
352 {
353     my ($interface, $interfaceName, $className, $hasAttributes, $inlined) = @_;
354
355     my $namespaceMaybe = ($inlined ? "JSC::" : "");
356
357     my @getOwnPropertySlotImpl = ();
358
359     if ($interfaceName eq "NamedNodeMap" or $interfaceName =~ /^HTML\w*Collection$/) {
360         push(@getOwnPropertySlotImpl, "    ${namespaceMaybe}JSValue proto = thisObject->prototype();\n");
361         push(@getOwnPropertySlotImpl, "    if (proto.isObject() && jsCast<${namespaceMaybe}JSObject*>(asObject(proto))->hasProperty(exec, propertyName))\n");
362         push(@getOwnPropertySlotImpl, "        return false;\n\n");
363     }
364
365     my $manualLookupGetterGeneration = sub {
366         my $requiresManualLookup = $interface->extendedAttributes->{"IndexedGetter"} || $interface->extendedAttributes->{"NamedGetter"};
367         if ($requiresManualLookup) {
368             push(@getOwnPropertySlotImpl, "    const ${namespaceMaybe}HashEntry* entry = getStaticValueSlotEntryWithoutCaching<$className>(exec, propertyName);\n");
369             push(@getOwnPropertySlotImpl, "    if (entry) {\n");
370             push(@getOwnPropertySlotImpl, "        slot.setCustom(thisObject, entry->propertyGetter());\n");
371             push(@getOwnPropertySlotImpl, "        return true;\n");
372             push(@getOwnPropertySlotImpl, "    }\n");
373         }
374     };
375
376     if (!$interface->extendedAttributes->{"CustomNamedGetter"}) {
377         &$manualLookupGetterGeneration();
378     }
379
380     if ($interface->extendedAttributes->{"IndexedGetter"} || $interface->extendedAttributes->{"NumericIndexedGetter"}) {
381         push(@getOwnPropertySlotImpl, "    unsigned index = propertyName.asIndex();\n");
382
383         # If the item function returns a string then we let the TreatReturnedNullStringAs handle the cases
384         # where the index is out of range.
385         if (IndexGetterReturnsStrings($interfaceName)) {
386             push(@getOwnPropertySlotImpl, "    if (index != PropertyName::NotAnIndex) {\n");
387         } else {
388             push(@getOwnPropertySlotImpl, "    if (index != PropertyName::NotAnIndex && index < static_cast<$interfaceName*>(thisObject->impl())->length()) {\n");
389         }
390         if ($interface->extendedAttributes->{"NumericIndexedGetter"}) {
391             push(@getOwnPropertySlotImpl, "        slot.setValue(thisObject->getByIndex(exec, index));\n");
392         } else {
393             push(@getOwnPropertySlotImpl, "        slot.setCustomIndex(thisObject, index, indexGetter);\n");
394         }
395         push(@getOwnPropertySlotImpl, "        return true;\n");
396         push(@getOwnPropertySlotImpl, "    }\n");
397     }
398
399     if ($interface->extendedAttributes->{"NamedGetter"} || $interface->extendedAttributes->{"CustomNamedGetter"}) {
400         push(@getOwnPropertySlotImpl, "    if (canGetItemsForName(exec, static_cast<$interfaceName*>(thisObject->impl()), propertyName)) {\n");
401         push(@getOwnPropertySlotImpl, "        slot.setCustom(thisObject, thisObject->nameGetter);\n");
402         push(@getOwnPropertySlotImpl, "        return true;\n");
403         push(@getOwnPropertySlotImpl, "    }\n");
404         if ($inlined) {
405             $headerIncludes{"wtf/text/AtomicString.h"} = 1;
406         } else {
407             $implIncludes{"wtf/text/AtomicString.h"} = 1;
408         }
409     }
410
411     if ($interface->extendedAttributes->{"CustomNamedGetter"}) {
412         &$manualLookupGetterGeneration();
413     }
414
415     if ($interface->extendedAttributes->{"JSCustomGetOwnPropertySlotAndDescriptor"}) {
416         push(@getOwnPropertySlotImpl, "    if (thisObject->getOwnPropertySlotDelegate(exec, propertyName, slot))\n");
417         push(@getOwnPropertySlotImpl, "        return true;\n");
418     }
419
420     if ($hasAttributes) {
421         if ($inlined) {
422             die "Cannot inline if NoStaticTables is set." if ($interface->extendedAttributes->{"JSNoStaticTables"});
423             push(@getOwnPropertySlotImpl, "    return ${namespaceMaybe}getStaticValueSlot<$className, Base>(exec, s_info.staticPropHashTable, thisObject, propertyName, slot);\n");
424         } else {
425             push(@getOwnPropertySlotImpl, "    return ${namespaceMaybe}getStaticValueSlot<$className, Base>(exec, " . hashTableAccessor($interface->extendedAttributes->{"JSNoStaticTables"}, $className) . ", thisObject, propertyName, slot);\n");
426         }
427     } else {
428         push(@getOwnPropertySlotImpl, "    return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);\n");
429     }
430
431     return @getOwnPropertySlotImpl;
432 }
433
434 sub GenerateGetOwnPropertyDescriptorBody
435 {
436     my ($interface, $interfaceName, $className, $hasAttributes, $inlined) = @_;
437     
438     my $namespaceMaybe = ($inlined ? "JSC::" : "");
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 = $interface->extendedAttributes->{"IndexedGetter"} || $interface->extendedAttributes->{"NamedGetter"};
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;\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 ($interface->extendedAttributes->{"IndexedGetter"} || $interface->extendedAttributes->{"NumericIndexedGetter"}) {
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 ($interface->extendedAttributes->{"NumericIndexedGetter"}) {
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;\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 ($interface->extendedAttributes->{"NamedGetter"} || $interface->extendedAttributes->{"CustomNamedGetter"}) {
499         push(@getOwnPropertyDescriptorImpl, "    if (canGetItemsForName(exec, static_cast<$interfaceName*>(thisObject->impl()), propertyName)) {\n");
500         push(@getOwnPropertyDescriptorImpl, "        ${namespaceMaybe}PropertySlot slot;\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, s_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 GenerateHeader
616 {
617     my $object = shift;
618     my $interface = shift;
619
620     my $interfaceName = $interface->name;
621     my $className = "JS$interfaceName";
622     my @ancestorInterfaceNames = ();
623     my %structureFlags = ();
624
625     # We only support multiple parents with SVG (for now).
626     if (@{$interface->parents} > 1) {
627         die "A class can't have more than one parent" unless $interfaceName =~ /SVG/;
628         $codeGenerator->AddMethodsConstantsAndAttributesFromParentInterfaces($interface, \@ancestorInterfaceNames);
629     }
630
631     my $hasLegacyParent = $interface->extendedAttributes->{"JSLegacyParent"};
632     my $hasRealParent = @{$interface->parents} > 0;
633     my $hasParent = $hasLegacyParent || $hasRealParent;
634     my $parentClassName = GetParentClassName($interface);
635     my $needsMarkChildren = $interface->extendedAttributes->{"JSCustomMarkFunction"} || $interface->extendedAttributes->{"EventTarget"} || $interface->name eq "EventTarget";
636
637     # - Add default header template and header protection
638     push(@headerContentHeader, GenerateHeaderContentHeader($interface));
639
640     if ($hasParent) {
641         $headerIncludes{"$parentClassName.h"} = 1;
642     } else {
643         $headerIncludes{"JSDOMBinding.h"} = 1;
644         $headerIncludes{"<runtime/JSGlobalObject.h>"} = 1;
645         if ($interface->isException) {
646             $headerIncludes{"<runtime/ErrorPrototype.h>"} = 1;
647         } else {
648             $headerIncludes{"<runtime/ObjectPrototype.h>"} = 1;
649         }
650     }
651
652     if ($interface->extendedAttributes->{"CustomCall"}) {
653         $headerIncludes{"<runtime/CallData.h>"} = 1;
654     }
655
656     if ($interface->extendedAttributes->{"JSInlineGetOwnPropertySlot"}) {
657         $headerIncludes{"<runtime/Lookup.h>"} = 1;
658     }
659
660     if ($hasParent && $interface->extendedAttributes->{"JSGenerateToNativeObject"}) {
661         if ($codeGenerator->IsTypedArrayType($interfaceName)) {
662             $headerIncludes{"<wtf/$interfaceName.h>"} = 1;
663         } else {
664             $headerIncludes{"$interfaceName.h"} = 1;
665         }
666     }
667     
668     $headerIncludes{"<runtime/JSObject.h>"} = 1;
669     $headerIncludes{"SVGElement.h"} = 1 if $className =~ /^JSSVG/;
670
671     my $implType = $interfaceName;
672     my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implType);
673     $implType = $svgNativeType if $svgNativeType;
674
675     my $svgPropertyOrListPropertyType;
676     $svgPropertyOrListPropertyType = $svgPropertyType if $svgPropertyType;
677     $svgPropertyOrListPropertyType = $svgListPropertyType if $svgListPropertyType;
678
679     my $numConstants = @{$interface->constants};
680     my $numAttributes = @{$interface->attributes};
681     my $numFunctions = @{$interface->functions};
682
683     push(@headerContent, "\nnamespace WebCore {\n\n");
684
685     if ($codeGenerator->IsSVGAnimatedType($interfaceName)) {
686         $headerIncludes{"$interfaceName.h"} = 1;
687     } else {
688         # Implementation class forward declaration
689         if ($interfaceName eq "DOMWindow" || $interface->extendedAttributes->{"IsWorkerContext"}) {
690             AddClassForwardIfNeeded($interfaceName) unless $svgPropertyOrListPropertyType;
691         }
692     }
693
694     AddClassForwardIfNeeded("JSDOMWindowShell") if $interfaceName eq "DOMWindow";
695     AddClassForwardIfNeeded("JSDictionary") if $codeGenerator->IsConstructorTemplate($interface, "Event");
696
697     # Class declaration
698     push(@headerContent, "class $className : public $parentClassName {\n");
699
700     # Static create methods
701     push(@headerContent, "public:\n");
702     push(@headerContent, "    typedef $parentClassName Base;\n");
703     if ($interfaceName eq "DOMWindow") {
704         push(@headerContent, "    static $className* create(JSC::VM& vm, JSC::Structure* structure, PassRefPtr<$implType> impl, JSDOMWindowShell* windowShell)\n");
705         push(@headerContent, "    {\n");
706         push(@headerContent, "        $className* ptr = new (NotNull, JSC::allocateCell<$className>(vm.heap)) ${className}(vm, structure, impl, windowShell);\n");
707         push(@headerContent, "        ptr->finishCreation(vm, windowShell);\n");
708         push(@headerContent, "        vm.heap.addFinalizer(ptr, destroy);\n");
709         push(@headerContent, "        return ptr;\n");
710         push(@headerContent, "    }\n\n");
711     } elsif ($interface->extendedAttributes->{"IsWorkerContext"}) {
712         push(@headerContent, "    static $className* create(JSC::VM& vm, JSC::Structure* structure, PassRefPtr<$implType> impl)\n");
713         push(@headerContent, "    {\n");
714         push(@headerContent, "        $className* ptr = new (NotNull, JSC::allocateCell<$className>(vm.heap)) ${className}(vm, structure, impl);\n");
715         push(@headerContent, "        ptr->finishCreation(vm);\n");
716         push(@headerContent, "        vm.heap.addFinalizer(ptr, destroy);\n");
717         push(@headerContent, "        return ptr;\n");
718         push(@headerContent, "    }\n\n");
719     } elsif ($interface->extendedAttributes->{"MasqueradesAsUndefined"}) {
720         AddIncludesForTypeInHeader($implType) unless $svgPropertyOrListPropertyType;
721         push(@headerContent, "    static $className* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl)\n");
722         push(@headerContent, "    {\n");
723         push(@headerContent, "        globalObject->masqueradesAsUndefinedWatchpoint()->notifyWrite();\n");
724         push(@headerContent, "        $className* ptr = new (NotNull, JSC::allocateCell<$className>(globalObject->vm().heap)) $className(structure, globalObject, impl);\n");
725         push(@headerContent, "        ptr->finishCreation(globalObject->vm());\n");
726         push(@headerContent, "        return ptr;\n");
727         push(@headerContent, "    }\n\n");
728     } else {
729         AddIncludesForTypeInHeader($implType) unless $svgPropertyOrListPropertyType;
730         push(@headerContent, "    static $className* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl)\n");
731         push(@headerContent, "    {\n");
732         push(@headerContent, "        $className* ptr = new (NotNull, JSC::allocateCell<$className>(globalObject->vm().heap)) $className(structure, globalObject, impl);\n");
733         push(@headerContent, "        ptr->finishCreation(globalObject->vm());\n");
734         push(@headerContent, "        return ptr;\n");
735         push(@headerContent, "    }\n\n");
736     }
737
738     if ($interfaceName eq "DOMWindow" || $interface->extendedAttributes->{"IsWorkerContext"}) {
739         push(@headerContent, "    static const bool needsDestruction = false;\n\n");
740     }
741
742     # Prototype
743     push(@headerContent, "    static JSC::JSObject* createPrototype(JSC::ExecState*, JSC::JSGlobalObject*);\n") unless ($interface->extendedAttributes->{"ExtendsDOMGlobalObject"});
744
745     $headerTrailingIncludes{"${className}Custom.h"} = 1 if $interface->extendedAttributes->{"JSCustomHeader"};
746
747     $implIncludes{"${className}Custom.h"} = 1 if !$interface->extendedAttributes->{"JSCustomHeader"} && ($interface->extendedAttributes->{"CustomPutFunction"} || $interface->extendedAttributes->{"CustomNamedSetter"});
748
749     my $hasImpureNamedGetter =
750         $interface->extendedAttributes->{"NamedGetter"}
751         || $interface->extendedAttributes->{"CustomNamedGetter"}
752         || $interface->extendedAttributes->{"CustomGetOwnPropertySlot"};
753
754     my $hasComplexGetter =
755         $interface->extendedAttributes->{"IndexedGetter"}
756         || $interface->extendedAttributes->{"NumericIndexedGetter"}
757         || $interface->extendedAttributes->{"JSCustomGetOwnPropertySlotAndDescriptor"}
758         || $hasImpureNamedGetter;
759     
760     my $hasGetter = $numAttributes > 0 || !$interface->extendedAttributes->{"OmitConstructor"} || $hasComplexGetter;
761
762     if ($hasImpureNamedGetter) {
763         $structureFlags{"JSC::HasImpureGetOwnPropertySlot"} = 1;
764     }
765
766     # Getters
767     if ($hasGetter) {
768         push(@headerContent, "    static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&);\n");
769         push(@headerContent, "    static bool getOwnPropertyDescriptor(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName, JSC::PropertyDescriptor&);\n");
770         push(@headerContent, "    static bool getOwnPropertySlotByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);\n") if ($hasComplexGetter);
771         push(@headerContent, "    bool getOwnPropertySlotDelegate(JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&);\n") if $interface->extendedAttributes->{"JSCustomGetOwnPropertySlotAndDescriptor"};
772         push(@headerContent, "    bool getOwnPropertyDescriptorDelegate(JSC::ExecState*, JSC::PropertyName, JSC::PropertyDescriptor&);\n") if $interface->extendedAttributes->{"JSCustomGetOwnPropertySlotAndDescriptor"};
773         $structureFlags{"JSC::OverridesGetOwnPropertySlot"} = 1;
774         $structureFlags{"JSC::InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero"} = 1;
775     }
776
777     # Check if we have any writable properties
778     my $hasReadWriteProperties = 0;
779     foreach (@{$interface->attributes}) {
780         if (!IsReadonly($_) && !$_->isStatic) {
781             $hasReadWriteProperties = 1;
782         }
783     }
784
785     my $hasComplexSetter =
786         $interface->extendedAttributes->{"CustomPutFunction"}
787         || $interface->extendedAttributes->{"CustomNamedSetter"}
788         || $interface->extendedAttributes->{"CustomIndexedSetter"};
789         
790     my $hasSetter = $hasReadWriteProperties || $hasComplexSetter;
791
792     # Getters
793     if ($hasSetter) {
794         push(@headerContent, "    static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName, JSC::JSValue, JSC::PutPropertySlot&);\n");
795         push(@headerContent, "    static void putByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::JSValue, bool shouldThrow);\n") if ($hasComplexSetter);
796         push(@headerContent, "    bool putDelegate(JSC::ExecState*, JSC::PropertyName, JSC::JSValue, JSC::PutPropertySlot&);\n") if $interface->extendedAttributes->{"CustomNamedSetter"};
797     }
798
799     if (!$hasParent) {
800         push(@headerContent, "    static void destroy(JSC::JSCell*);\n");
801         push(@headerContent, "    ~${className}();\n");
802     }
803
804     # Class info
805     if ($interfaceName eq "Node") {
806         push(@headerContent, "    static WEBKIT_EXPORTDATA const JSC::ClassInfo s_info;\n\n");
807     } else {
808         push(@headerContent, "    static const JSC::ClassInfo s_info;\n\n");
809     }
810     # Structure ID
811     if ($interfaceName eq "DOMWindow") {
812         $structureFlags{"JSC::ImplementsHasInstance"} = 1;
813     }
814     push(@headerContent, "    static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)\n");
815     push(@headerContent, "    {\n");
816     if ($interfaceName eq "DOMWindow" || $interface->extendedAttributes->{"IsWorkerContext"}) {
817         push(@headerContent, "        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::GlobalObjectType, StructureFlags), &s_info);\n");
818     } else {
819         push(@headerContent, "        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), &s_info);\n");
820     }
821     push(@headerContent, "    }\n\n");
822
823     # Custom pushEventHandlerScope function
824     push(@headerContent, "    JSC::JSScope* pushEventHandlerScope(JSC::ExecState*, JSC::JSScope*) const;\n\n") if $interface->extendedAttributes->{"JSCustomPushEventHandlerScope"};
825
826     # Custom call functions
827     push(@headerContent, "    static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&);\n\n") if $interface->extendedAttributes->{"CustomCall"};
828
829     # Custom deleteProperty function
830     push(@headerContent, "    static bool deleteProperty(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName);\n") if $interface->extendedAttributes->{"CustomDeleteProperty"};
831     push(@headerContent, "    static bool deletePropertyByIndex(JSC::JSCell*, JSC::ExecState*, unsigned);\n") if $interface->extendedAttributes->{"CustomDeleteProperty"};
832
833     # Custom getPropertyNames function exists on DOMWindow
834     if ($interfaceName eq "DOMWindow") {
835         push(@headerContent, "    static void getPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n");
836         $structureFlags{"JSC::OverridesGetPropertyNames"} = 1;
837     }
838
839     # Custom getOwnPropertyNames function
840     if ($interface->extendedAttributes->{"CustomEnumerateProperty"} || $interface->extendedAttributes->{"IndexedGetter"} || $interface->extendedAttributes->{"NumericIndexedGetter"}) {
841         push(@headerContent, "    static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n");
842         $structureFlags{"JSC::OverridesGetPropertyNames"} = 1;       
843     }
844
845     # Custom defineOwnProperty function
846     push(@headerContent, "    static bool defineOwnProperty(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName, JSC::PropertyDescriptor&, bool shouldThrow);\n") if $interface->extendedAttributes->{"JSCustomDefineOwnProperty"};
847
848     # Override toBoolean to return false for objects that want to 'MasqueradesAsUndefined'.
849     if ($interface->extendedAttributes->{"MasqueradesAsUndefined"}) {
850         $structureFlags{"JSC::MasqueradesAsUndefined"} = 1;
851     }
852
853     # Constructor object getter
854     push(@headerContent, "    static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*);\n") if !$interface->extendedAttributes->{"OmitConstructor"};
855
856     my $numCustomFunctions = 0;
857     my $numCustomAttributes = 0;
858
859     # Attribute and function enums
860     if ($numAttributes > 0) {
861         foreach (@{$interface->attributes}) {
862             my $attribute = $_;
863             $numCustomAttributes++ if HasCustomGetter($attribute->signature->extendedAttributes);
864             $numCustomAttributes++ if HasCustomSetter($attribute->signature->extendedAttributes);
865             if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) {
866                 my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
867                 push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
868                 push(@headerContent, "    JSC::WriteBarrier<JSC::Unknown> m_" . $attribute->signature->name . ";\n");
869                 $numCachedAttributes++;
870                 $needsMarkChildren = 1;
871                 push(@headerContent, "#endif\n") if $conditionalString;
872             }
873         }
874     }
875
876     # visit function
877     if ($needsMarkChildren) {
878         push(@headerContent, "    static void visitChildren(JSCell*, JSC::SlotVisitor&);\n\n");
879         $structureFlags{"JSC::OverridesVisitChildren"} = 1;
880     }
881
882     if ($numCustomAttributes > 0) {
883         push(@headerContent, "\n    // Custom attributes\n");
884
885         foreach my $attribute (@{$interface->attributes}) {
886             my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
887             if (HasCustomGetter($attribute->signature->extendedAttributes)) {
888                 push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
889                 my $methodName = $codeGenerator->WK_lcfirst($attribute->signature->name);
890                 push(@headerContent, "    JSC::JSValue " . $methodName . "(JSC::ExecState*) const;\n");
891                 push(@headerContent, "#endif\n") if $conditionalString;
892             }
893             if (HasCustomSetter($attribute->signature->extendedAttributes) && !IsReadonly($attribute)) {
894                 push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
895                 push(@headerContent, "    void set" . $codeGenerator->WK_ucfirst($attribute->signature->name) . "(JSC::ExecState*, JSC::JSValue);\n");
896                 push(@headerContent, "#endif\n") if $conditionalString;
897             }
898         }
899     }
900
901     foreach my $function (@{$interface->functions}) {
902         $numCustomFunctions++ if HasCustomMethod($function->signature->extendedAttributes);
903     }
904
905     if ($numCustomFunctions > 0) {
906         push(@headerContent, "\n    // Custom functions\n");
907         foreach my $function (@{$interface->functions}) {
908             next unless HasCustomMethod($function->signature->extendedAttributes);
909             next if $function->{overloads} && $function->{overloadIndex} != 1;
910             my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
911             push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
912             my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementedAs"} || $codeGenerator->WK_lcfirst($function->signature->name);
913             push(@headerContent, "    " . ($function->isStatic ? "static " : "") . "JSC::JSValue " . $functionImplementationName . "(JSC::ExecState*);\n");
914             push(@headerContent, "#endif\n") if $conditionalString;
915         }
916     }
917
918     if (!$hasParent) {
919         push(@headerContent, "    $implType* impl() const { return m_impl; }\n");
920         push(@headerContent, "    void releaseImpl() { m_impl->deref(); m_impl = 0; }\n\n");
921         push(@headerContent, "    void releaseImplIfNotNull() { if (m_impl) { m_impl->deref(); m_impl = 0; } }\n\n");
922         push(@headerContent, "private:\n");
923         push(@headerContent, "    $implType* m_impl;\n");
924     } elsif ($interface->extendedAttributes->{"JSGenerateToNativeObject"}) {
925         push(@headerContent, "    $interfaceName* impl() const\n");
926         push(@headerContent, "    {\n");
927         push(@headerContent, "        return static_cast<$interfaceName*>(Base::impl());\n");
928         push(@headerContent, "    }\n");
929     }
930
931     if ($codeGenerator->IsTypedArrayType($implType) and ($implType ne "ArrayBufferView") and ($implType ne "ArrayBuffer")) {
932         push(@headerContent, "    static const JSC::TypedArrayType TypedArrayStorageType = JSC::");
933         push(@headerContent, "TypedArrayInt8") if $implType eq "Int8Array";
934         push(@headerContent, "TypedArrayInt16") if $implType eq "Int16Array";
935         push(@headerContent, "TypedArrayInt32") if $implType eq "Int32Array";
936         push(@headerContent, "TypedArrayUint8") if $implType eq "Uint8Array";
937         push(@headerContent, "TypedArrayUint8Clamped") if $implType eq "Uint8ClampedArray";
938         push(@headerContent, "TypedArrayUint16") if $implType eq "Uint16Array";
939         push(@headerContent, "TypedArrayUint32") if $implType eq "Uint32Array";
940         push(@headerContent, "TypedArrayFloat32") if $implType eq "Float32Array";
941         push(@headerContent, "TypedArrayFloat64") if $implType eq "Float64Array";
942         push(@headerContent, ";\n");
943         push(@headerContent, "    intptr_t m_storageLength;\n");
944         push(@headerContent, "    void* m_storage;\n");
945     }
946
947     push(@headerContent, "protected:\n");
948     # Constructor
949     if ($interfaceName eq "DOMWindow") {
950         push(@headerContent, "    $className(JSC::VM&, JSC::Structure*, PassRefPtr<$implType>, JSDOMWindowShell*);\n");
951     } elsif ($interface->extendedAttributes->{"IsWorkerContext"}) {
952         push(@headerContent, "    $className(JSC::VM&, JSC::Structure*, PassRefPtr<$implType>);\n");
953     } else {
954         push(@headerContent, "    $className(JSC::Structure*, JSDOMGlobalObject*, PassRefPtr<$implType>);\n");
955         push(@headerContent, "    void finishCreation(JSC::VM&);\n");
956     }
957
958     # structure flags
959     push(@headerContent, "    static const unsigned StructureFlags = ");
960     foreach my $structureFlag (keys %structureFlags) {
961         push(@headerContent, $structureFlag . " | ");
962     }
963     push(@headerContent, "Base::StructureFlags;\n");
964
965     # Index getter
966     if ($interface->extendedAttributes->{"IndexedGetter"}) {
967         push(@headerContent, "    static JSC::JSValue indexGetter(JSC::ExecState*, JSC::JSValue, unsigned);\n");
968     }
969     if ($interface->extendedAttributes->{"NumericIndexedGetter"}) {
970         push(@headerContent, "    JSC::JSValue getByIndex(JSC::ExecState*, unsigned index);\n");
971     }
972
973     # Index setter
974     if ($interface->extendedAttributes->{"CustomIndexedSetter"}) {
975         push(@headerContent, "    void indexSetter(JSC::ExecState*, unsigned index, JSC::JSValue);\n");
976     }
977     # Name getter
978     if ($interface->extendedAttributes->{"NamedGetter"} || $interface->extendedAttributes->{"CustomNamedGetter"}) {
979         push(@headerContent, "private:\n");
980         push(@headerContent, "    static bool canGetItemsForName(JSC::ExecState*, $interfaceName*, JSC::PropertyName);\n");
981         push(@headerContent, "    static JSC::JSValue nameGetter(JSC::ExecState*, JSC::JSValue, JSC::PropertyName);\n");
982     }
983
984     push(@headerContent, "};\n\n");
985
986     if ($interface->extendedAttributes->{"JSInlineGetOwnPropertySlot"} && !$interface->extendedAttributes->{"CustomGetOwnPropertySlot"}) {
987         push(@headerContent, "ALWAYS_INLINE bool ${className}::getOwnPropertySlot(JSC::JSCell* cell, JSC::ExecState* exec, JSC::PropertyName propertyName, JSC::PropertySlot& slot)\n");
988         push(@headerContent, "{\n");
989         push(@headerContent, "    ${className}* thisObject = JSC::jsCast<${className}*>(cell);\n");
990         push(@headerContent, "    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\n");
991         push(@headerContent, GenerateGetOwnPropertySlotBody($interface, $interfaceName, $className, $numAttributes > 0, 1));
992         push(@headerContent, "}\n\n");
993         push(@headerContent, "ALWAYS_INLINE bool ${className}::getOwnPropertyDescriptor(JSC::JSObject* object, JSC::ExecState* exec, JSC::PropertyName propertyName, JSC::PropertyDescriptor& descriptor)\n");
994         push(@headerContent, "{\n");
995         push(@headerContent, "    ${className}* thisObject = JSC::jsCast<${className}*>(object);\n");
996         push(@headerContent, "    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\n");
997         push(@headerContent, GenerateGetOwnPropertyDescriptorBody($interface, $interfaceName, $className, $numAttributes > 0, 1));
998         push(@headerContent, "}\n\n");
999     }
1000
1001     if (!$hasParent ||
1002         GetGenerateIsReachable($interface) ||
1003         GetCustomIsReachable($interface) ||
1004         $interface->extendedAttributes->{"JSCustomFinalize"} ||
1005         $codeGenerator->InheritsExtendedAttribute($interface, "ActiveDOMObject")) {
1006         if ($interfaceName ne "Node" && $codeGenerator->InheritsInterface($interface, "Node")) {
1007             $headerIncludes{"JSNode.h"} = 1;
1008             push(@headerContent, "class JS${interfaceName}Owner : public JSNodeOwner {\n");
1009         } else {
1010             push(@headerContent, "class JS${interfaceName}Owner : public JSC::WeakHandleOwner {\n");
1011         }
1012         push(@headerContent, "public:\n");
1013         push(@headerContent, "    virtual bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::SlotVisitor&);\n");
1014         push(@headerContent, "    virtual void finalize(JSC::Handle<JSC::Unknown>, void* context);\n");
1015         push(@headerContent, "};\n");
1016         push(@headerContent, "\n");
1017         push(@headerContent, "inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld*, $implType*)\n");
1018         push(@headerContent, "{\n");
1019         push(@headerContent, "    DEFINE_STATIC_LOCAL(JS${interfaceName}Owner, js${interfaceName}Owner, ());\n");
1020         push(@headerContent, "    return &js${interfaceName}Owner;\n");
1021         push(@headerContent, "}\n");
1022         push(@headerContent, "\n");
1023         push(@headerContent, "inline void* wrapperContext(DOMWrapperWorld* world, $implType*)\n");
1024         push(@headerContent, "{\n");
1025         push(@headerContent, "    return world;\n");
1026         push(@headerContent, "}\n");
1027         push(@headerContent, "\n");
1028     }
1029     if (ShouldGenerateToJSDeclaration($hasParent, $interface)) {
1030         push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType*);\n");
1031     }
1032     if (!$hasParent || $interface->extendedAttributes->{"JSGenerateToNativeObject"}) {
1033         if ($interfaceName eq "NodeFilter") {
1034             push(@headerContent, "PassRefPtr<NodeFilter> toNodeFilter(JSC::VM&, JSC::JSValue);\n");
1035         } elsif ($interfaceName eq "DOMStringList") {
1036             push(@headerContent, "PassRefPtr<DOMStringList> toDOMStringList(JSC::ExecState*, JSC::JSValue);\n");
1037         } else {
1038             push(@headerContent, "$implType* to${interfaceName}(JSC::JSValue);\n");
1039         }
1040     }
1041     if ($usesToJSNewlyCreated{$interfaceName}) {
1042         push(@headerContent, "JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject*, $interfaceName*);\n");
1043     }
1044     
1045     push(@headerContent, "\n");
1046
1047     # Add prototype declaration.
1048     %structureFlags = ();
1049     push(@headerContent, "class ${className}Prototype : public JSC::JSNonFinalObject {\n");
1050     push(@headerContent, "public:\n");
1051     push(@headerContent, "    typedef JSC::JSNonFinalObject Base;\n");
1052     if ($interfaceName ne "DOMWindow" && !$interface->extendedAttributes->{"IsWorkerContext"}) {
1053         push(@headerContent, "    static JSC::JSObject* self(JSC::ExecState*, JSC::JSGlobalObject*);\n");
1054     }
1055
1056     push(@headerContent, "    static ${className}Prototype* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure)\n");
1057     push(@headerContent, "    {\n");
1058     push(@headerContent, "        ${className}Prototype* ptr = new (NotNull, JSC::allocateCell<${className}Prototype>(vm.heap)) ${className}Prototype(vm, globalObject, structure);\n");
1059     push(@headerContent, "        ptr->finishCreation(vm);\n");
1060     push(@headerContent, "        return ptr;\n");
1061     push(@headerContent, "    }\n\n");
1062
1063     push(@headerContent, "    static const JSC::ClassInfo s_info;\n");
1064     if ($numFunctions > 0 || $numConstants > 0) {
1065         push(@headerContent, "    static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&);\n");
1066         push(@headerContent, "    static bool getOwnPropertyDescriptor(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName, JSC::PropertyDescriptor&);\n");
1067         $structureFlags{"JSC::OverridesGetOwnPropertySlot"} = 1;
1068     }
1069     if ($interface->extendedAttributes->{"JSCustomMarkFunction"} or $needsMarkChildren) {
1070         $structureFlags{"JSC::OverridesVisitChildren"} = 1;
1071     }
1072     push(@headerContent,
1073         "    static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)\n" .
1074         "    {\n" .
1075         "        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), &s_info);\n" .
1076         "    }\n");
1077     if ($interface->extendedAttributes->{"JSCustomNamedGetterOnPrototype"}) {
1078         push(@headerContent, "    static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName, JSC::JSValue, JSC::PutPropertySlot&);\n");
1079         push(@headerContent, "    bool putDelegate(JSC::ExecState*, JSC::PropertyName, JSC::JSValue, JSC::PutPropertySlot&);\n");
1080     }
1081
1082     # Custom defineOwnProperty function
1083     push(@headerContent, "    static bool defineOwnProperty(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName, JSC::PropertyDescriptor&, bool shouldThrow);\n") if $interface->extendedAttributes->{"JSCustomDefineOwnPropertyOnPrototype"};
1084
1085     push(@headerContent, "\nprivate:\n");
1086     push(@headerContent, "    ${className}Prototype(JSC::VM& vm, JSC::JSGlobalObject*, JSC::Structure* structure) : JSC::JSNonFinalObject(vm, structure) { }\n");
1087
1088     # structure flags
1089     push(@headerContent, "protected:\n");
1090     push(@headerContent, "    static const unsigned StructureFlags = ");
1091     foreach my $structureFlag (keys %structureFlags) {
1092         push(@headerContent, $structureFlag . " | ");
1093     }
1094     push(@headerContent, "Base::StructureFlags;\n");
1095
1096     push(@headerContent, "};\n\n");
1097
1098     if (!$interface->extendedAttributes->{"OmitConstructor"}) {
1099         $headerIncludes{"JSDOMBinding.h"} = 1;
1100         GenerateConstructorDeclaration(\@headerContent, $className, $interface, $interfaceName);
1101     }
1102
1103     if ($numFunctions > 0) {
1104         push(@headerContent,"// Functions\n\n");
1105         foreach my $function (@{$interface->functions}) {
1106             next if $function->{overloadIndex} && $function->{overloadIndex} > 1;
1107             my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
1108             push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
1109             my $functionName = GetFunctionName($className, $function);
1110             push(@headerContent, "JSC::EncodedJSValue JSC_HOST_CALL ${functionName}(JSC::ExecState*);\n");
1111             push(@headerContent, "#endif\n") if $conditionalString;
1112         }
1113     }
1114
1115     if ($numAttributes > 0 || !$interface->extendedAttributes->{"OmitConstructor"}) {
1116         push(@headerContent,"// Attributes\n\n");
1117         foreach my $attribute (@{$interface->attributes}) {
1118             my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
1119             push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
1120             my $getter = GetAttributeGetterName($interfaceName, $className, $attribute);
1121             push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, JSC::JSValue, JSC::PropertyName);\n");
1122             if (!IsReadonly($attribute)) {
1123                 my $setter = GetAttributeSetterName($interfaceName, $className, $attribute);
1124                 push(@headerContent, "void ${setter}(JSC::ExecState*, JSC::JSObject*, JSC::JSValue);\n");
1125             }
1126             push(@headerContent, "#endif\n") if $conditionalString;
1127         }
1128         
1129         if (!$interface->extendedAttributes->{"OmitConstructor"}) {
1130             my $getter = "js" . $interfaceName . "Constructor";
1131             push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, JSC::JSValue, JSC::PropertyName);\n");
1132         }
1133
1134         if ($interface->extendedAttributes->{"ReplaceableConstructor"}) {
1135             my $constructorFunctionName = "setJS" . $interfaceName . "Constructor";
1136             push(@headerContent, "void ${constructorFunctionName}(JSC::ExecState*, JSC::JSObject*, JSC::JSValue);\n");
1137         }
1138     }
1139
1140     if ($numConstants > 0) {
1141         push(@headerContent,"// Constants\n\n");
1142         foreach my $constant (@{$interface->constants}) {
1143             my $conditionalString = $codeGenerator->GenerateConditionalString($constant);
1144             push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
1145             my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);
1146             push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, JSC::JSValue, JSC::PropertyName);\n");
1147             push(@headerContent, "#endif\n") if $conditionalString;
1148         }
1149     }
1150
1151     my $conditionalString = $codeGenerator->GenerateConditionalString($interface);
1152     push(@headerContent, "\n} // namespace WebCore\n\n");
1153     push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;
1154     push(@headerContent, "#endif\n");
1155
1156     # - Generate dependencies.
1157     if ($writeDependencies && @ancestorInterfaceNames) {
1158         push(@depsContent, "$className.h : ", join(" ", map { "$_.idl" } @ancestorInterfaceNames), "\n");
1159         push(@depsContent, map { "$_.idl :\n" } @ancestorInterfaceNames); 
1160     }
1161 }
1162
1163 sub GenerateAttributesHashTable($$)
1164 {
1165     my ($object, $interface) = @_;
1166
1167     # FIXME: These should be functions on $interface.
1168     my $interfaceName = $interface->name;
1169     my $className = "JS$interfaceName";
1170     
1171     # - Add all attributes in a hashtable definition
1172     my $numAttributes = @{$interface->attributes};
1173     $numAttributes++ if !$interface->extendedAttributes->{"OmitConstructor"};
1174
1175     return 0  if !$numAttributes;
1176
1177     my $hashSize = $numAttributes;
1178     my $hashName = $className . "Table";
1179
1180     my @hashKeys = ();
1181     my @hashSpecials = ();
1182     my @hashValue1 = ();
1183     my @hashValue2 = ();
1184     my %conditionals = ();
1185
1186     my @entries = ();
1187
1188     foreach my $attribute (@{$interface->attributes}) {
1189         next if ($attribute->isStatic);
1190         my $name = $attribute->signature->name;
1191         push(@hashKeys, $name);
1192
1193         my @specials = ();
1194         # As per Web IDL specification, constructor properties on the ECMAScript global object should be
1195         # configurable and should not be enumerable.
1196         my $is_domwindow_constructor = ($interface->name eq "DOMWindow" && $attribute->signature->type =~ /Constructor$/);
1197         push(@specials, "DontDelete") unless ($attribute->signature->extendedAttributes->{"Deletable"} || $is_domwindow_constructor);
1198         push(@specials, "DontEnum") if ($attribute->signature->extendedAttributes->{"NotEnumerable"} || $is_domwindow_constructor);
1199         push(@specials, "ReadOnly") if IsReadonly($attribute);
1200         my $special = (@specials > 0) ? join(" | ", @specials) : "0";
1201         push(@hashSpecials, $special);
1202
1203         my $getter = GetAttributeGetterName($interfaceName, $className, $attribute);
1204         push(@hashValue1, $getter);
1205
1206         if (IsReadonly($attribute)) {
1207             push(@hashValue2, "0");
1208         } else {
1209             my $setter = GetAttributeSetterName($interfaceName, $className, $attribute);
1210             push(@hashValue2, $setter);
1211         }
1212
1213         my $conditional = $attribute->signature->extendedAttributes->{"Conditional"};
1214         if ($conditional) {
1215             $conditionals{$name} = $conditional;
1216         }
1217     }
1218
1219     if (!$interface->extendedAttributes->{"OmitConstructor"}) {
1220         push(@hashKeys, "constructor");
1221         my $getter = "js" . $interfaceName . "Constructor";
1222         push(@hashValue1, $getter);
1223         if ($interface->extendedAttributes->{"ReplaceableConstructor"}) {
1224             my $setter = "setJS" . $interfaceName . "Constructor";
1225             push(@hashValue2, $setter);
1226             push(@hashSpecials, "DontEnum | DontDelete");
1227         } else {            
1228             push(@hashValue2, "0");
1229             push(@hashSpecials, "DontEnum | ReadOnly");
1230         }
1231     }
1232
1233     $object->GenerateHashTable($hashName, $hashSize,
1234                                \@hashKeys, \@hashSpecials,
1235                                \@hashValue1, \@hashValue2,
1236                                \%conditionals);
1237     return $numAttributes;
1238 }
1239
1240 sub GenerateParametersCheckExpression
1241 {
1242     my $numParameters = shift;
1243     my $function = shift;
1244
1245     my @andExpression = ();
1246     push(@andExpression, "argsCount == $numParameters");
1247     my $parameterIndex = 0;
1248     my %usedArguments = ();
1249     foreach my $parameter (@{$function->parameters}) {
1250         last if $parameterIndex >= $numParameters;
1251         my $value = "arg$parameterIndex";
1252         my $type = $parameter->type;
1253
1254         # Only DOMString or wrapper types are checked.
1255         # For DOMString with StrictTypeChecking only Null, Undefined and Object
1256         # are accepted for compatibility. Otherwise, no restrictions are made to
1257         # match the non-overloaded behavior.
1258         # FIXME: Implement WebIDL overload resolution algorithm.
1259         if ($codeGenerator->IsStringType($type)) {
1260             if ($parameter->extendedAttributes->{"StrictTypeChecking"}) {
1261                 push(@andExpression, "(${value}.isUndefinedOrNull() || ${value}.isString() || ${value}.isObject())");
1262                 $usedArguments{$parameterIndex} = 1;
1263             }
1264         } elsif ($codeGenerator->IsCallbackInterface($parameter->type)) {
1265             # For Callbacks only checks if the value is null or object.
1266             push(@andExpression, "(${value}.isNull() || ${value}.isFunction())");
1267             $usedArguments{$parameterIndex} = 1;
1268         } elsif ($codeGenerator->GetArrayType($type) || $codeGenerator->GetSequenceType($type)) {
1269             # FIXME: Add proper support for T[], T[]?, sequence<T>
1270             if ($parameter->isNullable) {
1271                 push(@andExpression, "(${value}.isNull() || (${value}.isObject() && isJSArray(${value})))");
1272             } else {
1273                 push(@andExpression, "(${value}.isObject() && isJSArray(${value}))");
1274             }
1275             $usedArguments{$parameterIndex} = 1;
1276         } elsif (!IsNativeType($type)) {
1277             if ($parameter->isNullable) {
1278                 push(@andExpression, "(${value}.isNull() || (${value}.isObject() && asObject(${value})->inherits(&JS${type}::s_info)))");
1279             } else {
1280                 push(@andExpression, "(${value}.isObject() && asObject(${value})->inherits(&JS${type}::s_info))");
1281             }
1282             $usedArguments{$parameterIndex} = 1;
1283         }
1284         $parameterIndex++;
1285     }
1286     my $res = join(" && ", @andExpression);
1287     $res = "($res)" if @andExpression > 1;
1288     return ($res, keys %usedArguments);
1289 }
1290
1291 # As per Web IDL specification, the length of a function Object is
1292 # its number of mandatory parameters.
1293 sub GetFunctionLength
1294 {
1295   my $function = shift;
1296
1297   my $numMandatoryParams = 0;
1298   foreach my $parameter (@{$function->parameters}) {
1299     # Abort as soon as we find the first optional parameter as no mandatory
1300     # parameter can follow an optional one.
1301     last if $parameter->isOptional;
1302     $numMandatoryParams++;
1303   }
1304   return $numMandatoryParams;
1305 }
1306
1307 sub GenerateFunctionParametersCheck
1308 {
1309     my $function = shift;
1310
1311     my @orExpression = ();
1312     my $numParameters = 0;
1313     my @neededArguments = ();
1314     my $hasVariadic = 0;
1315     my $numMandatoryParams = @{$function->parameters};
1316
1317     foreach my $parameter (@{$function->parameters}) {
1318         if ($parameter->isOptional) {
1319             my ($expression, @usedArguments) = GenerateParametersCheckExpression($numParameters, $function);
1320             push(@orExpression, $expression);
1321             push(@neededArguments, @usedArguments);
1322             $numMandatoryParams--;
1323         }
1324         if ($parameter->isVariadic) {
1325             $hasVariadic = 1;
1326             last;
1327         }
1328         $numParameters++;
1329     }
1330     if (!$hasVariadic) {
1331         my ($expression, @usedArguments) = GenerateParametersCheckExpression($numParameters, $function);
1332         push(@orExpression, $expression);
1333         push(@neededArguments, @usedArguments);
1334     }
1335     return ($numMandatoryParams, join(" || ", @orExpression), @neededArguments);
1336 }
1337
1338 sub GenerateOverloadedFunction
1339 {
1340     my $function = shift;
1341     my $interface = shift;
1342     my $interfaceName = shift;
1343
1344     # Generate code for choosing the correct overload to call. Overloads are
1345     # chosen based on the total number of arguments passed and the type of
1346     # values passed in non-primitive argument slots. When more than a single
1347     # overload is applicable, precedence is given according to the order of
1348     # declaration in the IDL.
1349
1350     my $kind = $function->isStatic ? "Constructor" : "Prototype";
1351     my $functionName = "js${interfaceName}${kind}Function" . $codeGenerator->WK_ucfirst($function->signature->name);
1352
1353     push(@implContent, "EncodedJSValue JSC_HOST_CALL ${functionName}(ExecState* exec)\n");
1354     push(@implContent, <<END);
1355 {
1356     size_t argsCount = exec->argumentCount();
1357 END
1358
1359     my %fetchedArguments = ();
1360     my $leastNumMandatoryParams = 255;
1361
1362     foreach my $overload (@{$function->{overloads}}) {
1363         my ($numMandatoryParams, $parametersCheck, @neededArguments) = GenerateFunctionParametersCheck($overload);
1364         $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams < $leastNumMandatoryParams);
1365
1366         foreach my $parameterIndex (@neededArguments) {
1367             next if exists $fetchedArguments{$parameterIndex};
1368             push(@implContent, "    JSValue arg$parameterIndex(exec->argument($parameterIndex));\n");
1369             $fetchedArguments{$parameterIndex} = 1;
1370         }
1371
1372         push(@implContent, "    if ($parametersCheck)\n");
1373         push(@implContent, "        return ${functionName}$overload->{overloadIndex}(exec);\n");
1374     }
1375     if ($leastNumMandatoryParams >= 1) {
1376         push(@implContent, "    if (argsCount < $leastNumMandatoryParams)\n");
1377         push(@implContent, "        return throwVMError(exec, createNotEnoughArgumentsError(exec));\n");
1378     }
1379     push(@implContent, <<END);
1380     return throwVMTypeError(exec);
1381 }
1382
1383 END
1384 }
1385
1386 sub GetNativeTypeForConversions
1387 {
1388     my $interface = shift;
1389     my $interfaceName = $interface->name;
1390     $interfaceName = $codeGenerator->GetSVGTypeNeedingTearOff($interfaceName) if $codeGenerator->IsSVGTypeNeedingTearOff($interfaceName);
1391     return $interfaceName;
1392 }
1393
1394 # See http://refspecs.linux-foundation.org/cxxabi-1.83.html.
1395 sub GetGnuVTableRefForInterface
1396 {
1397     my $interface = shift;
1398     my $vtableName = GetGnuVTableNameForInterface($interface);
1399     if (!$vtableName) {
1400         return "0";
1401     }
1402     my $typename = GetNativeTypeForConversions($interface);
1403     my $offset = GetGnuVTableOffsetForType($typename);
1404     return "&" . $vtableName . "[" . $offset . "]";
1405 }
1406
1407 sub GetGnuVTableNameForInterface
1408 {
1409     my $interface = shift;
1410     my $typename = GetNativeTypeForConversions($interface);
1411     my $templatePosition = index($typename, "<");
1412     return "" if $templatePosition != -1;
1413     return "" if GetImplementationLacksVTableForInterface($interface);
1414     return "" if GetSkipVTableValidationForInterface($interface);
1415     return "_ZTV" . GetGnuMangledNameForInterface($interface);
1416 }
1417
1418 sub GetGnuMangledNameForInterface
1419 {
1420     my $interface = shift;
1421     my $typename = GetNativeTypeForConversions($interface);
1422     my $templatePosition = index($typename, "<");
1423     if ($templatePosition != -1) {
1424         return "";
1425     }
1426     my $mangledType = length($typename) . $typename;
1427     my $namespace = GetNamespaceForInterface($interface);
1428     my $mangledNamespace =  "N" . length($namespace) . $namespace;
1429     return $mangledNamespace . $mangledType . "E";
1430 }
1431
1432 sub GetGnuVTableOffsetForType
1433 {
1434     my $typename = shift;
1435     if ($typename eq "SVGAElement"
1436         || $typename eq "SVGCircleElement"
1437         || $typename eq "SVGClipPathElement"
1438         || $typename eq "SVGDefsElement"
1439         || $typename eq "SVGEllipseElement"
1440         || $typename eq "SVGForeignObjectElement"
1441         || $typename eq "SVGGElement"
1442         || $typename eq "SVGImageElement"
1443         || $typename eq "SVGLineElement"
1444         || $typename eq "SVGPathElement"
1445         || $typename eq "SVGPolyElement"
1446         || $typename eq "SVGPolygonElement"
1447         || $typename eq "SVGPolylineElement"
1448         || $typename eq "SVGRectElement"
1449         || $typename eq "SVGSVGElement"
1450         || $typename eq "SVGStyledLocatableElement"
1451         || $typename eq "SVGStyledTransformableElement"
1452         || $typename eq "SVGSwitchElement"
1453         || $typename eq "SVGTextElement"
1454         || $typename eq "SVGTransformable"
1455         || $typename eq "SVGUseElement") {
1456         return "3";
1457     }
1458     return "2";
1459 }
1460
1461 # See http://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B_Name_Mangling.
1462 sub GetWinVTableRefForInterface
1463 {
1464     my $interface = shift;
1465     my $vtableName = GetWinVTableNameForInterface($interface);
1466     return 0 if !$vtableName;
1467     return "__identifier(\"" . $vtableName . "\")";
1468 }
1469
1470 sub GetWinVTableNameForInterface
1471 {
1472     my $interface = shift;
1473     my $typename = GetNativeTypeForConversions($interface);
1474     my $templatePosition = index($typename, "<");
1475     return "" if $templatePosition != -1;
1476     return "" if GetImplementationLacksVTableForInterface($interface);
1477     return "" if GetSkipVTableValidationForInterface($interface);
1478     return "??_7" . GetWinMangledNameForInterface($interface) . "6B@";
1479 }
1480
1481 sub GetWinMangledNameForInterface
1482 {
1483     my $interface = shift;
1484     my $typename = GetNativeTypeForConversions($interface);
1485     my $namespace = GetNamespaceForInterface($interface);
1486     return $typename . "@" . $namespace . "@@";
1487 }
1488
1489 sub GetNamespaceForInterface
1490 {
1491     my $interface = shift;
1492     return $interface->extendedAttributes->{"ImplementationNamespace"} || "WebCore";
1493 }
1494
1495 sub GetImplementationLacksVTableForInterface
1496 {
1497     my $interface = shift;
1498     return $interface->extendedAttributes->{"ImplementationLacksVTable"};
1499 }
1500
1501 sub GetSkipVTableValidationForInterface
1502 {
1503     my $interface = shift;
1504     return $interface->extendedAttributes->{"SkipVTableValidation"};
1505 }
1506
1507
1508 sub GenerateImplementation
1509 {
1510     my ($object, $interface) = @_;
1511
1512     my $interfaceName = $interface->name;
1513     my $className = "JS$interfaceName";
1514
1515     my $hasLegacyParent = $interface->extendedAttributes->{"JSLegacyParent"};
1516     my $hasRealParent = @{$interface->parents} > 0;
1517     my $hasParent = $hasLegacyParent || $hasRealParent;
1518     my $parentClassName = GetParentClassName($interface);
1519     my $visibleInterfaceName = $codeGenerator->GetVisibleInterfaceName($interface);
1520     my $eventTarget = $interface->extendedAttributes->{"EventTarget"} || ($codeGenerator->InheritsInterface($interface, "EventTarget") && $interface->name ne "EventTarget");
1521     my $needsMarkChildren = $interface->extendedAttributes->{"JSCustomMarkFunction"} || $interface->extendedAttributes->{"EventTarget"} || $interface->name eq "EventTarget";
1522
1523     # - Add default header template
1524     push(@implContentHeader, GenerateImplementationContentHeader($interface));
1525
1526     $implIncludes{"<wtf/GetPtr.h>"} = 1;
1527     $implIncludes{"<runtime/PropertyNameArray.h>"} = 1 if $interface->extendedAttributes->{"IndexedGetter"} || $interface->extendedAttributes->{"NumericIndexedGetter"};
1528
1529     AddIncludesForTypeInImpl($interfaceName);
1530
1531     @implContent = ();
1532
1533     push(@implContent, "\nusing namespace JSC;\n\n");
1534     push(@implContent, "namespace WebCore {\n\n");
1535
1536     my $numAttributes = GenerateAttributesHashTable($object, $interface);
1537
1538     my $numConstants = @{$interface->constants};
1539     my $numFunctions = @{$interface->functions};
1540
1541     # - Add all constants
1542     if (!$interface->extendedAttributes->{"OmitConstructor"}) {
1543         my $hashSize = $numConstants;
1544         my $hashName = $className . "ConstructorTable";
1545
1546         my @hashKeys = ();
1547         my @hashValue1 = ();
1548         my @hashValue2 = ();
1549         my @hashSpecials = ();
1550         my %conditionals = ();
1551
1552         # FIXME: we should not need a function for every constant.
1553         foreach my $constant (@{$interface->constants}) {
1554             my $name = $constant->name;
1555             push(@hashKeys, $name);
1556             my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($name);
1557             push(@hashValue1, $getter);
1558             push(@hashValue2, "0");
1559             push(@hashSpecials, "DontDelete | ReadOnly");
1560
1561             my $implementedBy = $constant->extendedAttributes->{"ImplementedBy"};
1562             if ($implementedBy) {
1563                 $implIncludes{"${implementedBy}.h"} = 1;
1564             }
1565             my $conditional = $constant->extendedAttributes->{"Conditional"};
1566             if ($conditional) {
1567                 $conditionals{$name} = $conditional;
1568             }
1569         }
1570
1571         foreach my $attribute (@{$interface->attributes}) {
1572             next unless ($attribute->isStatic);
1573             my $name = $attribute->signature->name;
1574             push(@hashKeys, $name);
1575
1576             my @specials = ();
1577             push(@specials, "DontDelete") unless $attribute->signature->extendedAttributes->{"Deletable"};
1578             push(@specials, "ReadOnly") if IsReadonly($attribute);
1579             my $special = (@specials > 0) ? join(" | ", @specials) : "0";
1580             push(@hashSpecials, $special);
1581
1582             my $getter = GetAttributeGetterName($interfaceName, $className, $attribute);
1583             push(@hashValue1, $getter);
1584
1585             if (IsReadonly($attribute)) {
1586                 push(@hashValue2, "0");
1587             } else {
1588                 my $setter = GetAttributeSetterName($interfaceName, $className, $attribute);
1589                 push(@hashValue2, $setter);
1590             }
1591
1592             my $conditional = $attribute->signature->extendedAttributes->{"Conditional"};
1593             if ($conditional) {
1594                 $conditionals{$name} = $conditional;
1595             }
1596         }
1597
1598         foreach my $function (@{$interface->functions}) {
1599             next unless ($function->isStatic);
1600             next if $function->{overloadIndex} && $function->{overloadIndex} > 1;
1601             my $name = $function->signature->name;
1602             push(@hashKeys, $name);
1603
1604             my $functionName = GetFunctionName($className, $function);
1605             push(@hashValue1, $functionName);
1606
1607             my $functionLength = GetFunctionLength($function);
1608             push(@hashValue2, $functionLength);
1609
1610             my @specials = ();
1611             push(@specials, "DontDelete") unless $function->signature->extendedAttributes->{"Deletable"};
1612             push(@specials, "DontEnum") if $function->signature->extendedAttributes->{"NotEnumerable"};
1613             push(@specials, "JSC::Function");
1614             my $special = (@specials > 0) ? join(" | ", @specials) : "0";
1615             push(@hashSpecials, $special);
1616
1617             my $conditional = $function->signature->extendedAttributes->{"Conditional"};
1618             if ($conditional) {
1619                 $conditionals{$name} = $conditional;
1620             }
1621         }
1622
1623         $object->GenerateHashTable($hashName, $hashSize,
1624                                    \@hashKeys, \@hashSpecials,
1625                                    \@hashValue1, \@hashValue2,
1626                                    \%conditionals);
1627
1628         push(@implContent, $codeGenerator->GenerateCompileTimeCheckForEnumsIfNeeded($interface));
1629
1630         my $protoClassName = "${className}Prototype";
1631         GenerateConstructorDefinitions(\@implContent, $className, $protoClassName, $interfaceName, $visibleInterfaceName, $interface);
1632         if ($interface->extendedAttributes->{"NamedConstructor"}) {
1633             GenerateConstructorDefinitions(\@implContent, $className, $protoClassName, $interfaceName, $interface->extendedAttributes->{"NamedConstructor"}, $interface, "GeneratingNamedConstructor");
1634         }
1635     }
1636
1637     # - Add functions and constants to a hashtable definition
1638     my $hashSize = $numFunctions + $numConstants;
1639     my $hashName = $className . "PrototypeTable";
1640
1641     my @hashKeys = ();
1642     my @hashValue1 = ();
1643     my @hashValue2 = ();
1644     my @hashSpecials = ();
1645     my %conditionals = ();
1646
1647     # FIXME: we should not need a function for every constant.
1648     foreach my $constant (@{$interface->constants}) {
1649         my $name = $constant->name;
1650         push(@hashKeys, $name);
1651         my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($name);
1652         push(@hashValue1, $getter);
1653         push(@hashValue2, "0");
1654         push(@hashSpecials, "DontDelete | ReadOnly");
1655
1656         my $conditional = $constant->extendedAttributes->{"Conditional"};
1657         if ($conditional) {
1658             $conditionals{$name} = $conditional;
1659         }
1660     }
1661
1662     foreach my $function (@{$interface->functions}) {
1663         next if ($function->isStatic);
1664         next if $function->{overloadIndex} && $function->{overloadIndex} > 1;
1665         my $name = $function->signature->name;
1666         push(@hashKeys, $name);
1667
1668         my $functionName = GetFunctionName($className, $function);
1669         push(@hashValue1, $functionName);
1670
1671         my $functionLength = GetFunctionLength($function);
1672         push(@hashValue2, $functionLength);
1673
1674         my @specials = ();
1675         push(@specials, "DontDelete") unless $function->signature->extendedAttributes->{"Deletable"};
1676         push(@specials, "DontEnum") if $function->signature->extendedAttributes->{"NotEnumerable"};
1677         push(@specials, "JSC::Function");
1678         my $special = (@specials > 0) ? join(" | ", @specials) : "0";
1679         push(@hashSpecials, $special);
1680
1681         my $conditional = $function->signature->extendedAttributes->{"Conditional"};
1682         if ($conditional) {
1683             $conditionals{$name} = $conditional;
1684         }
1685     }
1686
1687     $object->GenerateHashTable($hashName, $hashSize,
1688                                \@hashKeys, \@hashSpecials,
1689                                \@hashValue1, \@hashValue2,
1690                                \%conditionals);
1691
1692     if ($interface->extendedAttributes->{"JSNoStaticTables"}) {
1693         push(@implContent, "static const HashTable* get${className}PrototypeTable(ExecState* exec)\n");
1694         push(@implContent, "{\n");
1695         push(@implContent, "    return getHashTableForGlobalData(exec->vm(), &${className}PrototypeTable);\n");
1696         push(@implContent, "}\n\n");
1697         push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleInterfaceName}Prototype\", &Base::s_info, 0, get${className}PrototypeTable, CREATE_METHOD_TABLE(${className}Prototype) };\n\n");
1698     } else {
1699         push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleInterfaceName}Prototype\", &Base::s_info, &${className}PrototypeTable, 0, CREATE_METHOD_TABLE(${className}Prototype) };\n\n");
1700     }
1701     if ($interfaceName ne "DOMWindow" && !$interface->extendedAttributes->{"IsWorkerContext"}) {
1702         push(@implContent, "JSObject* ${className}Prototype::self(ExecState* exec, JSGlobalObject* globalObject)\n");
1703         push(@implContent, "{\n");
1704         push(@implContent, "    return getDOMPrototype<${className}>(exec, globalObject);\n");
1705         push(@implContent, "}\n\n");
1706     }
1707
1708     if ($numConstants > 0 || $numFunctions > 0) {
1709         push(@implContent, "bool ${className}Prototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot& slot)\n");
1710         push(@implContent, "{\n");
1711         push(@implContent, "    ${className}Prototype* thisObject = jsCast<${className}Prototype*>(cell);\n");
1712
1713         if ($numConstants eq 0 && $numFunctions eq 0) {
1714             push(@implContent, "    return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);\n");        
1715         } elsif ($numConstants eq 0) {
1716             push(@implContent, "    return getStaticFunctionSlot<JSObject>(exec, " . prototypeHashTableAccessor($interface->extendedAttributes->{"JSNoStaticTables"}, $className) . ", thisObject, propertyName, slot);\n");
1717         } elsif ($numFunctions eq 0) {
1718             push(@implContent, "    return getStaticValueSlot<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($interface->extendedAttributes->{"JSNoStaticTables"}, $className) . ", thisObject, propertyName, slot);\n");
1719         } else {
1720             push(@implContent, "    return getStaticPropertySlot<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($interface->extendedAttributes->{"JSNoStaticTables"}, $className) . ", thisObject, propertyName, slot);\n");
1721         }
1722         push(@implContent, "}\n\n");
1723
1724         push(@implContent, "bool ${className}Prototype::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor)\n");
1725         push(@implContent, "{\n");
1726         push(@implContent, "    ${className}Prototype* thisObject = jsCast<${className}Prototype*>(object);\n");
1727
1728         if ($numConstants eq 0 && $numFunctions eq 0) {
1729             push(@implContent, "    return Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);\n");        
1730         } elsif ($numConstants eq 0) {
1731             push(@implContent, "    return getStaticFunctionDescriptor<JSObject>(exec, " . prototypeHashTableAccessor($interface->extendedAttributes->{"JSNoStaticTables"}, $className) . ", thisObject, propertyName, descriptor);\n");
1732         } elsif ($numFunctions eq 0) {
1733             push(@implContent, "    return getStaticValueDescriptor<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($interface->extendedAttributes->{"JSNoStaticTables"}, $className) . ", thisObject, propertyName, descriptor);\n");
1734         } else {
1735             push(@implContent, "    return getStaticPropertyDescriptor<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($interface->extendedAttributes->{"JSNoStaticTables"}, $className) . ", thisObject, propertyName, descriptor);\n");
1736         }
1737         push(@implContent, "}\n\n");
1738     }
1739
1740     if ($interface->extendedAttributes->{"JSCustomNamedGetterOnPrototype"}) {
1741         push(@implContent, "void ${className}Prototype::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)\n");
1742         push(@implContent, "{\n");
1743         push(@implContent, "    ${className}Prototype* thisObject = jsCast<${className}Prototype*>(cell);\n");
1744         push(@implContent, "    if (thisObject->putDelegate(exec, propertyName, value, slot))\n");
1745         push(@implContent, "        return;\n");
1746         push(@implContent, "    Base::put(thisObject, exec, propertyName, value, slot);\n");
1747         push(@implContent, "}\n\n");
1748     }
1749
1750     # - Initialize static ClassInfo object
1751     if ($numAttributes > 0 && $interface->extendedAttributes->{"JSNoStaticTables"}) {
1752         push(@implContent, "static const HashTable* get${className}Table(ExecState* exec)\n");
1753         push(@implContent, "{\n");
1754         push(@implContent, "    return getHashTableForGlobalData(exec->vm(), &${className}Table);\n");
1755         push(@implContent, "}\n\n");
1756     }
1757
1758     push(@implContent, "const ClassInfo $className" . "::s_info = { \"${visibleInterfaceName}\", &Base::s_info, ");
1759
1760     if ($numAttributes > 0 && !$interface->extendedAttributes->{"JSNoStaticTables"}) {
1761         push(@implContent, "&${className}Table");
1762     } else {
1763         push(@implContent, "0");
1764     }
1765     if ($numAttributes > 0 && $interface->extendedAttributes->{"JSNoStaticTables"}) {
1766         push(@implContent, ", get${className}Table ");
1767     } else {
1768         push(@implContent, ", 0 ");
1769     }
1770     push(@implContent, ", CREATE_METHOD_TABLE($className) };\n\n");
1771
1772     my $implType = $interfaceName;
1773     my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implType);
1774     $implType = $svgNativeType if $svgNativeType;
1775
1776     my $svgPropertyOrListPropertyType;
1777     $svgPropertyOrListPropertyType = $svgPropertyType if $svgPropertyType;
1778     $svgPropertyOrListPropertyType = $svgListPropertyType if $svgListPropertyType;
1779
1780     # Constructor
1781     if ($interfaceName eq "DOMWindow") {
1782         AddIncludesForTypeInImpl("JSDOMWindowShell");
1783         push(@implContent, "${className}::$className(VM& vm, Structure* structure, PassRefPtr<$implType> impl, JSDOMWindowShell* shell)\n");
1784         push(@implContent, "    : $parentClassName(vm, structure, impl, shell)\n");
1785         push(@implContent, "{\n");
1786         push(@implContent, "}\n\n");
1787     } elsif ($interface->extendedAttributes->{"IsWorkerContext"}) {
1788         AddIncludesForTypeInImpl($interfaceName);
1789         push(@implContent, "${className}::$className(VM& vm, Structure* structure, PassRefPtr<$implType> impl)\n");
1790         push(@implContent, "    : $parentClassName(vm, structure, impl)\n");
1791         push(@implContent, "{\n");
1792         push(@implContent, "}\n\n");
1793     } else {
1794         push(@implContent, "${className}::$className(Structure* structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl)\n");
1795         if ($hasParent) {
1796             push(@implContent, "    : $parentClassName(structure, globalObject, impl)\n");
1797         } else {
1798             push(@implContent, "    : $parentClassName(structure, globalObject)\n");
1799             push(@implContent, "    , m_impl(impl.leakRef())\n");
1800         }
1801         push(@implContent, "{\n");
1802         push(@implContent, "}\n\n");
1803
1804         push(@implContent, "void ${className}::finishCreation(VM& vm)\n");
1805         push(@implContent, "{\n");
1806         push(@implContent, "    Base::finishCreation(vm);\n");
1807         if ($codeGenerator->IsTypedArrayType($implType) and ($implType ne "ArrayBufferView") and ($implType ne "ArrayBuffer")) {
1808             push(@implContent, "    TypedArrayDescriptor descriptor(&${className}::s_info, OBJECT_OFFSETOF(${className}, m_storage), OBJECT_OFFSETOF(${className}, m_storageLength));\n");
1809             push(@implContent, "    vm.registerTypedArrayDescriptor(impl(), descriptor);\n");
1810             push(@implContent, "    m_storage = impl()->data();\n");
1811             push(@implContent, "    m_storageLength = impl()->length();\n");
1812         }
1813         push(@implContent, "    ASSERT(inherits(&s_info));\n");
1814         push(@implContent, "}\n\n");
1815     }
1816
1817     if (!$interface->extendedAttributes->{"ExtendsDOMGlobalObject"}) {
1818         push(@implContent, "JSObject* ${className}::createPrototype(ExecState* exec, JSGlobalObject* globalObject)\n");
1819         push(@implContent, "{\n");
1820         if ($hasParent && $parentClassName ne "JSC::DOMNodeFilter") {
1821             push(@implContent, "    return ${className}Prototype::create(exec->vm(), globalObject, ${className}Prototype::createStructure(exec->vm(), globalObject, ${parentClassName}Prototype::self(exec, globalObject)));\n");
1822         } else {
1823             my $prototype = $interface->isException ? "errorPrototype" : "objectPrototype";
1824             push(@implContent, "    return ${className}Prototype::create(exec->vm(), globalObject, ${className}Prototype::createStructure(globalObject->vm(), globalObject, globalObject->${prototype}()));\n");
1825         }
1826         push(@implContent, "}\n\n");
1827     }
1828
1829     if (!$hasParent) {
1830         # FIXME: This destroy function should not be necessary, as 
1831         # a finalizer should be called for each DOM object wrapper.
1832         # However, that seems not to be the case, so this has been
1833         # added back to avoid leaking while we figure out why the
1834         # finalizers are not always getting called. The work tracking
1835         # the finalizer issue is being tracked in http://webkit.org/b/75451
1836         push(@implContent, "void ${className}::destroy(JSC::JSCell* cell)\n");
1837         push(@implContent, "{\n");
1838         push(@implContent, "    ${className}* thisObject = static_cast<${className}*>(cell);\n");
1839         push(@implContent, "    thisObject->${className}::~${className}();\n");
1840         push(@implContent, "}\n\n");
1841
1842         # We also need a destructor for the allocateCell to work properly with the destructor-free part of the heap.
1843         # Otherwise, these destroy functions/destructors won't get called.
1844         push(@implContent, "${className}::~${className}()\n");
1845         push(@implContent, "{\n");
1846         push(@implContent, "    releaseImplIfNotNull();\n");
1847         push(@implContent, "}\n\n");
1848     }
1849
1850     my $hasGetter = $numAttributes > 0
1851                  || !$interface->extendedAttributes->{"OmitConstructor"} 
1852                  || $interface->extendedAttributes->{"IndexedGetter"}
1853                  || $interface->extendedAttributes->{"NumericIndexedGetter"}
1854                  || $interface->extendedAttributes->{"JSCustomGetOwnPropertySlotAndDescriptor"}
1855                  || $interface->extendedAttributes->{"CustomGetOwnPropertySlot"}
1856                  || $interface->extendedAttributes->{"NamedGetter"}
1857                  || $interface->extendedAttributes->{"CustomNamedGetter"};
1858
1859     # Attributes
1860     if ($hasGetter) {
1861         if (!$interface->extendedAttributes->{"JSInlineGetOwnPropertySlot"} && !$interface->extendedAttributes->{"CustomGetOwnPropertySlot"}) {
1862             push(@implContent, "bool ${className}::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot& slot)\n");
1863             push(@implContent, "{\n");
1864             push(@implContent, "    ${className}* thisObject = jsCast<${className}*>(cell);\n");
1865             push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\n");
1866             push(@implContent, GenerateGetOwnPropertySlotBody($interface, $interfaceName, $className, $numAttributes > 0, 0));
1867             push(@implContent, "}\n\n");
1868             push(@implContent, "bool ${className}::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor)\n");
1869             push(@implContent, "{\n");
1870             push(@implContent, "    ${className}* thisObject = jsCast<${className}*>(object);\n");
1871             push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\n");
1872             push(@implContent, GenerateGetOwnPropertyDescriptorBody($interface, $interfaceName, $className, $numAttributes > 0, 0));
1873             push(@implContent, "}\n\n");
1874         }
1875
1876         if ($interface->extendedAttributes->{"IndexedGetter"} || $interface->extendedAttributes->{"NumericIndexedGetter"}
1877                 || $interface->extendedAttributes->{"NamedGetter"} || $interface->extendedAttributes->{"CustomNamedGetter"}
1878                 || $interface->extendedAttributes->{"JSCustomGetOwnPropertySlotAndDescriptor"}) {
1879             push(@implContent, "bool ${className}::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned index, PropertySlot& slot)\n");
1880             push(@implContent, "{\n");
1881             push(@implContent, "    ${className}* thisObject = jsCast<${className}*>(cell);\n");
1882             push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\n");
1883
1884             # Sink the int-to-string conversion that happens when we create a PropertyName
1885             # to the point where we actually need it.
1886             my $generatedPropertyName = 0;
1887             my $propertyNameGeneration = sub {
1888                 if ($generatedPropertyName) {
1889                     return;
1890                 }
1891                 push(@implContent, "    PropertyName propertyName = Identifier::from(exec, index);\n");
1892                 $generatedPropertyName = 1;
1893             };
1894
1895             if ($interface->extendedAttributes->{"IndexedGetter"} || $interface->extendedAttributes->{"NumericIndexedGetter"}) {
1896                 if (IndexGetterReturnsStrings($interfaceName)) {
1897                     push(@implContent, "    if (index <= MAX_ARRAY_INDEX) {\n");
1898                 } else {
1899                     push(@implContent, "    if (index < static_cast<$interfaceName*>(thisObject->impl())->length()) {\n");
1900                 }
1901                 if ($interface->extendedAttributes->{"NumericIndexedGetter"}) {
1902                     push(@implContent, "        slot.setValue(thisObject->getByIndex(exec, index));\n");
1903                 } else {
1904                     push(@implContent, "        slot.setCustomIndex(thisObject, index, thisObject->indexGetter);\n");
1905                 }
1906                 push(@implContent, "        return true;\n");
1907                 push(@implContent, "    }\n");
1908             }
1909
1910             if ($interface->extendedAttributes->{"NamedGetter"} || $interface->extendedAttributes->{"CustomNamedGetter"}) {
1911                 &$propertyNameGeneration();
1912                 push(@implContent, "    if (canGetItemsForName(exec, static_cast<$interfaceName*>(thisObject->impl()), propertyName)) {\n");
1913                 push(@implContent, "        slot.setCustom(thisObject, thisObject->nameGetter);\n");
1914                 push(@implContent, "        return true;\n");
1915                 push(@implContent, "    }\n");
1916                 $implIncludes{"wtf/text/AtomicString.h"} = 1;
1917             }
1918
1919             if ($interface->extendedAttributes->{"JSCustomGetOwnPropertySlotAndDescriptor"}) {
1920                 &$propertyNameGeneration();
1921                 push(@implContent, "    if (thisObject->getOwnPropertySlotDelegate(exec, propertyName, slot))\n");
1922                 push(@implContent, "        return true;\n");
1923             }
1924
1925             push(@implContent, "    return Base::getOwnPropertySlotByIndex(thisObject, exec, index, slot);\n");
1926             push(@implContent, "}\n\n");
1927         }
1928
1929         if ($numAttributes > 0) {
1930             foreach my $attribute (@{$interface->attributes}) {
1931                 my $name = $attribute->signature->name;
1932                 my $type = $attribute->signature->type;
1933                 my $isNullable = $attribute->signature->isNullable;
1934                 $codeGenerator->AssertNotSequenceType($type);
1935                 my $getFunctionName = GetAttributeGetterName($interfaceName, $className, $attribute);
1936                 my $implGetterFunctionName = $codeGenerator->WK_lcfirst($name);
1937
1938                 my $attributeConditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
1939                 push(@implContent, "#if ${attributeConditionalString}\n") if $attributeConditionalString;
1940
1941                 push(@implContent, "JSValue ${getFunctionName}(ExecState* exec, JSValue slotBase, PropertyName)\n");
1942                 push(@implContent, "{\n");
1943
1944                 if (!$attribute->isStatic || $attribute->signature->type =~ /Constructor$/) {
1945                     push(@implContent, "    ${className}* castedThis = jsCast<$className*>(asObject(slotBase));\n");
1946                 } else {
1947                     push(@implContent, "    UNUSED_PARAM(slotBase);\n");
1948                 }
1949
1950                 if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) {
1951                     $needsMarkChildren = 1;
1952                 }
1953
1954                 if ($interface->extendedAttributes->{"CheckSecurity"} &&
1955                     !$attribute->signature->extendedAttributes->{"DoNotCheckSecurity"} &&
1956                     !$attribute->signature->extendedAttributes->{"DoNotCheckSecurityOnGetter"}) {
1957                     $implIncludes{"BindingSecurity.h"} = 1;
1958                     push(@implContent, "    if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, castedThis->impl()))\n");
1959                     push(@implContent, "        return jsUndefined();\n");
1960                 }
1961
1962                 if (HasCustomGetter($attribute->signature->extendedAttributes)) {
1963                     push(@implContent, "    return castedThis->$implGetterFunctionName(exec);\n");
1964                 } elsif ($attribute->signature->extendedAttributes->{"CheckSecurityForNode"}) {
1965                     $implIncludes{"JSDOMBinding.h"} = 1;
1966                     push(@implContent, "    $interfaceName* impl = static_cast<$interfaceName*>(castedThis->impl());\n");
1967                     push(@implContent, "    return shouldAllowAccessToNode(exec, impl->" . $attribute->signature->name . "()) ? " . NativeToJSValue($attribute->signature, 0, $interfaceName, "impl->$implGetterFunctionName()", "castedThis") . " : jsNull();\n");
1968                 } elsif ($type eq "EventListener") {
1969                     $implIncludes{"EventListener.h"} = 1;
1970                     push(@implContent, "    UNUSED_PARAM(exec);\n");
1971                     push(@implContent, "    $interfaceName* impl = static_cast<$interfaceName*>(castedThis->impl());\n");
1972                     push(@implContent, "    if (EventListener* listener = impl->$implGetterFunctionName()) {\n");
1973                     push(@implContent, "        if (const JSEventListener* jsListener = JSEventListener::cast(listener)) {\n");
1974                     if ($interfaceName eq "Document" || $interfaceName eq "WorkerContext" || $interfaceName eq "SharedWorkerContext" || $interfaceName eq "DedicatedWorkerContext") {
1975                         push(@implContent, "            if (JSObject* jsFunction = jsListener->jsFunction(impl))\n");
1976                     } else {
1977                         push(@implContent, "            if (JSObject* jsFunction = jsListener->jsFunction(impl->scriptExecutionContext()))\n");
1978                     }
1979                     push(@implContent, "                return jsFunction;\n");
1980                     push(@implContent, "        }\n");
1981                     push(@implContent, "    }\n");
1982                     push(@implContent, "    return jsNull();\n");
1983                 } elsif ($attribute->signature->type =~ /Constructor$/) {
1984                     my $constructorType = $attribute->signature->type;
1985                     $constructorType =~ s/Constructor$//;
1986                     # When Constructor attribute is used by DOMWindow.idl, it's correct to pass castedThis as the global object
1987                     # When JSDOMWrappers have a back-pointer to the globalObject we can pass castedThis->globalObject()
1988                     if ($interfaceName eq "DOMWindow") {
1989                         push(@implContent, "    return JS" . $constructorType . "::getConstructor(exec, castedThis);\n");
1990                     } else {
1991                        AddToImplIncludes("JS" . $constructorType . ".h", $attribute->signature->extendedAttributes->{"Conditional"});
1992                        push(@implContent, "    return JS" . $constructorType . "::getConstructor(exec, castedThis->globalObject());\n");
1993                     }
1994                 } elsif (!@{$attribute->getterExceptions}) {
1995                     push(@implContent, "    UNUSED_PARAM(exec);\n") if !$attribute->signature->extendedAttributes->{"CallWith"};
1996                     push(@implContent, "    bool isNull = false;\n") if $isNullable;
1997
1998                     my $cacheIndex = 0;
1999                     if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) {
2000                         $cacheIndex = $currentCachedAttribute;
2001                         $currentCachedAttribute++;
2002                         push(@implContent, "    if (JSValue cachedValue = castedThis->m_" . $attribute->signature->name . ".get())\n");
2003                         push(@implContent, "        return cachedValue;\n");
2004                     }
2005
2006                     my @callWithArgs = GenerateCallWith($attribute->signature->extendedAttributes->{"CallWith"}, \@implContent, "jsUndefined()");
2007
2008                     if ($svgListPropertyType) {
2009                         push(@implContent, "    JSValue result =  " . NativeToJSValue($attribute->signature, 0, $interfaceName, "castedThis->impl()->$implGetterFunctionName(" . (join ", ", @callWithArgs) . ")", "castedThis") . ";\n");
2010                     } elsif ($svgPropertyOrListPropertyType) {
2011                         push(@implContent, "    $svgPropertyOrListPropertyType& impl = castedThis->impl()->propertyReference();\n");
2012                         if ($svgPropertyOrListPropertyType eq "float") { # Special case for JSSVGNumber
2013                             push(@implContent, "    JSValue result =  " . NativeToJSValue($attribute->signature, 0, $interfaceName, "impl", "castedThis") . ";\n");
2014                         } else {
2015                             push(@implContent, "    JSValue result =  " . NativeToJSValue($attribute->signature, 0, $interfaceName, "impl.$implGetterFunctionName(" . (join ", ", @callWithArgs) . ")", "castedThis") . ";\n");
2016
2017                         }
2018                     } else {
2019                         my ($functionName, @arguments) = $codeGenerator->GetterExpression(\%implIncludes, $interfaceName, $attribute);
2020                         push(@arguments, "isNull") if $isNullable;
2021                         if ($attribute->signature->extendedAttributes->{"ImplementedBy"}) {
2022                             my $implementedBy = $attribute->signature->extendedAttributes->{"ImplementedBy"};
2023                             $implIncludes{"${implementedBy}.h"} = 1;
2024                             $functionName = "${implementedBy}::${functionName}";
2025                             unshift(@arguments, "impl") if !$attribute->isStatic;
2026                         } elsif ($attribute->isStatic) {
2027                             $functionName = "${interfaceName}::${functionName}";
2028                         } else {
2029                             $functionName = "impl->${functionName}";
2030                         }
2031
2032                         unshift(@arguments, @callWithArgs);
2033                         my $jsType = NativeToJSValue($attribute->signature, 0, $interfaceName, "${functionName}(" . join(", ", @arguments) . ")", "castedThis");
2034                         push(@implContent, "    $interfaceName* impl = static_cast<$interfaceName*>(castedThis->impl());\n") if !$attribute->isStatic;
2035                         if ($codeGenerator->IsSVGAnimatedType($type)) {
2036                             push(@implContent, "    RefPtr<$type> obj = $jsType;\n");
2037                             push(@implContent, "    JSValue result =  toJS(exec, castedThis->globalObject(), obj.get());\n");
2038                         } else {
2039                             push(@implContent, "    JSValue result = $jsType;\n");
2040                         }
2041
2042                         if ($isNullable) {
2043                             push(@implContent, "    if (isNull)\n");
2044                             push(@implContent, "        return jsNull();\n");
2045                         }
2046                     }
2047
2048                     push(@implContent, "    castedThis->m_" . $attribute->signature->name . ".set(exec->vm(), castedThis, result);\n") if ($attribute->signature->extendedAttributes->{"CachedAttribute"});
2049                     push(@implContent, "    return result;\n");
2050
2051                 } else {
2052                     my @arguments = ("ec");
2053                     push(@implContent, "    ExceptionCode ec = 0;\n");
2054
2055                     if ($isNullable) {
2056                         push(@implContent, "    bool isNull = false;\n");
2057                         unshift(@arguments, "isNull");
2058                     }
2059
2060                     unshift(@arguments, GenerateCallWith($attribute->signature->extendedAttributes->{"CallWith"}, \@implContent, "jsUndefined()"));
2061
2062                     if ($svgPropertyOrListPropertyType) {
2063                         push(@implContent, "    $svgPropertyOrListPropertyType impl(*castedThis->impl());\n");
2064                         push(@implContent, "    JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $interfaceName, "impl.$implGetterFunctionName(" . join(", ", @arguments) . ")", "castedThis") . ";\n");
2065                     } else {
2066                         push(@implContent, "    $interfaceName* impl = static_cast<$interfaceName*>(castedThis->impl());\n");
2067                         push(@implContent, "    JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $interfaceName, "impl->$implGetterFunctionName(" . join(", ", @arguments) . ")", "castedThis") . ";\n");
2068                     }
2069
2070                     if ($isNullable) {
2071                         push(@implContent, "    if (isNull)\n");
2072                         push(@implContent, "        return jsNull();\n");
2073                     }
2074
2075                     push(@implContent, "    setDOMException(exec, ec);\n");
2076                     push(@implContent, "    return result;\n");
2077                 }
2078
2079                 push(@implContent, "}\n\n");
2080
2081                 push(@implContent, "#endif\n") if $attributeConditionalString;
2082
2083                 push(@implContent, "\n");
2084             }
2085
2086             if (!$interface->extendedAttributes->{"OmitConstructor"}) {
2087                 my $constructorFunctionName = "js" . $interfaceName . "Constructor";
2088
2089                 push(@implContent, "JSValue ${constructorFunctionName}(ExecState* exec, JSValue slotBase, PropertyName)\n");
2090                 push(@implContent, "{\n");
2091                 push(@implContent, "    ${className}* domObject = jsCast<$className*>(asObject(slotBase));\n");
2092
2093                 if ($interface->extendedAttributes->{"CheckSecurity"}) {
2094                     $implIncludes{"BindingSecurity.h"} = 1;
2095                     push(@implContent, "    if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, domObject->impl()))\n");
2096                     push(@implContent, "        return jsUndefined();\n");
2097                 }
2098
2099                 push(@implContent, "    return ${className}::getConstructor(exec, domObject->globalObject());\n");
2100                 push(@implContent, "}\n\n");
2101             }
2102         }
2103
2104         # Check if we have any writable attributes
2105         my $hasReadWriteProperties = 0;
2106         foreach my $attribute (@{$interface->attributes}) {
2107             $hasReadWriteProperties = 1 if !IsReadonly($attribute) && !$attribute->isStatic;
2108         }
2109
2110         my $hasSetter = $hasReadWriteProperties
2111                      || $interface->extendedAttributes->{"CustomNamedSetter"}
2112                      || $interface->extendedAttributes->{"CustomIndexedSetter"};
2113
2114         if ($hasSetter) {
2115             if (!$interface->extendedAttributes->{"CustomPutFunction"}) {
2116                 push(@implContent, "void ${className}::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)\n");
2117                 push(@implContent, "{\n");
2118                 push(@implContent, "    ${className}* thisObject = jsCast<${className}*>(cell);\n");
2119                 push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\n");
2120                 if ($interface->extendedAttributes->{"CustomIndexedSetter"}) {
2121                     push(@implContent, "    unsigned index = propertyName.asIndex();\n");
2122                     push(@implContent, "    if (index != PropertyName::NotAnIndex) {\n");
2123                     push(@implContent, "        thisObject->indexSetter(exec, index, value);\n");
2124                     push(@implContent, "        return;\n");
2125                     push(@implContent, "    }\n");
2126                 }
2127                 if ($interface->extendedAttributes->{"CustomNamedSetter"}) {
2128                     push(@implContent, "    if (thisObject->putDelegate(exec, propertyName, value, slot))\n");
2129                     push(@implContent, "        return;\n");
2130                 }
2131
2132                 if ($hasReadWriteProperties) {
2133                     push(@implContent, "    lookupPut<$className, Base>(exec, propertyName, value, " . hashTableAccessor($interface->extendedAttributes->{"JSNoStaticTables"}, $className) . ", thisObject, slot);\n");
2134                 } else {
2135                     push(@implContent, "    Base::put(thisObject, exec, propertyName, value, slot);\n");
2136                 }
2137                 push(@implContent, "}\n\n");
2138                 
2139                 if ($interface->extendedAttributes->{"CustomIndexedSetter"} || $interface->extendedAttributes->{"CustomNamedSetter"}) {
2140                     push(@implContent, "void ${className}::putByIndex(JSCell* cell, ExecState* exec, unsigned index, JSValue value, bool shouldThrow)\n");
2141                     push(@implContent, "{\n");
2142                     push(@implContent, "    ${className}* thisObject = jsCast<${className}*>(cell);\n");
2143                     push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\n");
2144                     if ($interface->extendedAttributes->{"CustomIndexedSetter"}) {
2145                         push(@implContent, "    if (index <= MAX_ARRAY_INDEX) {\n");
2146                         push(@implContent, "        UNUSED_PARAM(shouldThrow);\n");
2147                         push(@implContent, "        thisObject->indexSetter(exec, index, value);\n");
2148                         push(@implContent, "        return;\n");
2149                         push(@implContent, "    }\n");
2150                     }
2151                     
2152                     if ($interface->extendedAttributes->{"CustomNamedSetter"}) {
2153                         push(@implContent, "    PropertyName propertyName = Identifier::from(exec, index);\n");
2154                         push(@implContent, "    PutPropertySlot slot(shouldThrow);\n");
2155                         push(@implContent, "    if (thisObject->putDelegate(exec, propertyName, value, slot))\n");
2156                         push(@implContent, "        return;\n");
2157                     }
2158     
2159                     push(@implContent, "    Base::putByIndex(cell, exec, index, value, shouldThrow);\n");
2160                     push(@implContent, "}\n\n");
2161                 }
2162             }
2163
2164             if ($hasReadWriteProperties) {
2165                 foreach my $attribute (@{$interface->attributes}) {
2166                     if (!IsReadonly($attribute)) {
2167                         my $name = $attribute->signature->name;
2168                         my $type = $attribute->signature->type;
2169                         my $putFunctionName = GetAttributeSetterName($interfaceName, $className, $attribute);
2170                         my $implSetterFunctionName = $codeGenerator->WK_ucfirst($name);
2171
2172                         my $attributeConditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
2173                         push(@implContent, "#if ${attributeConditionalString}\n") if $attributeConditionalString;
2174
2175                         push(@implContent, "void ${putFunctionName}(ExecState* exec, JSObject*");
2176                         push(@implContent, " thisObject") if !$attribute->isStatic;
2177                         push(@implContent, ", JSValue value)\n");
2178                         push(@implContent, "{\n");
2179
2180                             push(@implContent, "    UNUSED_PARAM(exec);\n");
2181
2182                             if ($interface->extendedAttributes->{"CheckSecurity"} && !$attribute->signature->extendedAttributes->{"DoNotCheckSecurity"}) {
2183                                 if ($interfaceName eq "DOMWindow") {
2184                                     $implIncludes{"BindingSecurity.h"} = 1;
2185                                     push(@implContent, "    if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, jsCast<$className*>(thisObject)->impl()))\n");
2186                                 } else {
2187                                     push(@implContent, "    if (!shouldAllowAccessToFrame(exec, jsCast<$className*>(thisObject)->impl()->frame()))\n");
2188                                 }
2189                                 push(@implContent, "        return;\n");
2190                             }
2191
2192                             if (HasCustomSetter($attribute->signature->extendedAttributes)) {
2193                                 push(@implContent, "    jsCast<$className*>(thisObject)->set$implSetterFunctionName(exec, value);\n");
2194                             } elsif ($type eq "EventListener") {
2195                                 $implIncludes{"JSEventListener.h"} = 1;
2196                                 push(@implContent, "    UNUSED_PARAM(exec);\n");
2197                                 push(@implContent, "    ${className}* castedThis = jsCast<${className}*>(thisObject);\n");
2198                                 my $windowEventListener = $attribute->signature->extendedAttributes->{"JSWindowEventListener"};
2199                                 if ($windowEventListener) {
2200                                     push(@implContent, "    JSDOMGlobalObject* globalObject = castedThis->globalObject();\n");
2201                                 }
2202                                 push(@implContent, "    $interfaceName* impl = static_cast<$interfaceName*>(castedThis->impl());\n");
2203                                 if ((($interfaceName eq "DOMWindow") or ($interfaceName eq "WorkerContext")) and $name eq "onerror") {
2204                                     $implIncludes{"JSErrorHandler.h"} = 1;
2205                                     push(@implContent, "    impl->set$implSetterFunctionName(createJSErrorHandler(exec, value, thisObject));\n");
2206                                 } else {
2207                                     push(@implContent, GenerateAttributeEventListenerCall($className, $implSetterFunctionName, $windowEventListener));
2208                                 }
2209                             } elsif ($attribute->signature->type =~ /Constructor$/) {
2210                                 my $constructorType = $attribute->signature->type;
2211                                 $constructorType =~ s/Constructor$//;
2212                                 # $constructorType ~= /Constructor$/ indicates that it is NamedConstructor.
2213                                 # We do not generate the header file for NamedConstructor of class XXXX,
2214                                 # since we generate the NamedConstructor declaration into the header file of class XXXX.
2215                                 if ($constructorType ne "any" and $constructorType !~ /Constructor$/) {
2216                                     AddToImplIncludes("JS" . $constructorType . ".h", $attribute->signature->extendedAttributes->{"Conditional"});
2217                                 }
2218                                 push(@implContent, "    // Shadowing a built-in constructor\n");
2219                                 if ($interfaceName eq "DOMWindow" && $className eq "JSblah") {
2220                                     # FIXME: This branch never executes and should be removed.
2221                                     push(@implContent, "    jsCast<$className*>(thisObject)->putDirect(exec->vm(), exec->propertyNames().constructor, value);\n");
2222                                 } else {
2223                                     push(@implContent, "    jsCast<$className*>(thisObject)->putDirect(exec->vm(), Identifier(exec, \"$name\"), value);\n");
2224                                 }
2225                             } elsif ($attribute->signature->extendedAttributes->{"Replaceable"}) {
2226                                 push(@implContent, "    // Shadowing a built-in object\n");
2227                                 push(@implContent, "    jsCast<$className*>(thisObject)->putDirect(exec->vm(), Identifier(exec, \"$name\"), value);\n");
2228                             } else {
2229                                 if (!$attribute->isStatic) {
2230                                     push(@implContent, "    $className* castedThis = jsCast<$className*>(thisObject);\n");
2231                                     push(@implContent, "    $implType* impl = static_cast<$implType*>(castedThis->impl());\n");
2232                                 }
2233                                 push(@implContent, "    ExceptionCode ec = 0;\n") if @{$attribute->setterExceptions};
2234
2235                                 # If the "StrictTypeChecking" extended attribute is present, and the attribute's type is an
2236                                 # interface type, then if the incoming value does not implement that interface, a TypeError
2237                                 # is thrown rather than silently passing NULL to the C++ code.
2238                                 # Per the Web IDL and ECMAScript specifications, incoming values can always be converted to
2239                                 # both strings and numbers, so do not throw TypeError if the attribute is of these types.
2240                                 if ($attribute->signature->extendedAttributes->{"StrictTypeChecking"}) {
2241                                     $implIncludes{"<runtime/Error.h>"} = 1;
2242
2243                                     my $argType = $attribute->signature->type;
2244                                     if (!IsNativeType($argType)) {
2245                                         push(@implContent, "    if (!value.isUndefinedOrNull() && !value.inherits(&JS${argType}::s_info)) {\n");
2246                                         push(@implContent, "        throwVMTypeError(exec);\n");
2247                                         push(@implContent, "        return;\n");
2248                                         push(@implContent, "    };\n");
2249                                     }
2250                                 }
2251
2252                                 push(@implContent, "    " . GetNativeTypeFromSignature($attribute->signature) . " nativeValue(" . JSValueToNative($attribute->signature, "value") . ");\n");
2253                                 push(@implContent, "    if (exec->hadException())\n");
2254                                 push(@implContent, "        return;\n");
2255
2256                                 if ($codeGenerator->IsEnumType($type)) {
2257                                     my @enumValues = $codeGenerator->ValidEnumValues($type);
2258                                     my @enumChecks = ();
2259                                     foreach my $enumValue (@enumValues) {
2260                                         push(@enumChecks, "nativeValue != \"$enumValue\"");
2261                                     }
2262                                     push (@implContent, "    if (" . join(" && ", @enumChecks) . ")\n");
2263                                     push (@implContent, "        return;\n");
2264                                 }
2265
2266                                 if ($svgPropertyOrListPropertyType) {
2267                                     if ($svgPropertyType) {
2268                                         push(@implContent, "    if (impl->isReadOnly()) {\n");
2269                                         push(@implContent, "        setDOMException(exec, NO_MODIFICATION_ALLOWED_ERR);\n");
2270                                         push(@implContent, "        return;\n");
2271                                         push(@implContent, "    }\n");
2272                                         $implIncludes{"ExceptionCode.h"} = 1;
2273                                     }
2274                                     push(@implContent, "    $svgPropertyOrListPropertyType& podImpl = impl->propertyReference();\n");
2275                                     if ($svgPropertyOrListPropertyType eq "float") { # Special case for JSSVGNumber
2276                                         push(@implContent, "    podImpl = nativeValue;\n");
2277                                     } else {
2278                                         push(@implContent, "    podImpl.set$implSetterFunctionName(nativeValue");
2279                                         push(@implContent, ", ec") if @{$attribute->setterExceptions};
2280                                         push(@implContent, ");\n");
2281                                         push(@implContent, "    setDOMException(exec, ec);\n") if @{$attribute->setterExceptions};
2282                                     }
2283                                     if ($svgPropertyType) {
2284                                         if (@{$attribute->setterExceptions}) {
2285                                             push(@implContent, "    if (!ec)\n");
2286                                             push(@implContent, "        impl->commitChange();\n");
2287                                         } else {
2288                                             push(@implContent, "    impl->commitChange();\n");
2289                                         }
2290                                     }
2291                                 } else {
2292                                     my ($functionName, @arguments) = $codeGenerator->SetterExpression(\%implIncludes, $interfaceName, $attribute);
2293                                     push(@arguments, "nativeValue");
2294                                     if ($attribute->signature->extendedAttributes->{"ImplementedBy"}) {
2295                                         my $implementedBy = $attribute->signature->extendedAttributes->{"ImplementedBy"};
2296                                         $implIncludes{"${implementedBy}.h"} = 1;
2297                                         unshift(@arguments, "impl") if !$attribute->isStatic;
2298                                         $functionName = "${implementedBy}::${functionName}";
2299                                     } elsif ($attribute->isStatic) {
2300                                         $functionName = "${interfaceName}::${functionName}";
2301                                     } else {
2302                                         $functionName = "impl->${functionName}";
2303                                     }
2304
2305                                     unshift(@arguments, GenerateCallWith($attribute->signature->extendedAttributes->{"CallWith"}, \@implContent, ""));
2306
2307                                     push(@arguments, "ec") if @{$attribute->setterExceptions};
2308                                     push(@implContent, "    ${functionName}(" . join(", ", @arguments) . ");\n");
2309                                     push(@implContent, "    setDOMException(exec, ec);\n") if @{$attribute->setterExceptions};
2310                                 }
2311                             }
2312
2313                         push(@implContent, "}\n\n");
2314                         push(@implContent, "#endif\n") if $attributeConditionalString;
2315                         push(@implContent, "\n");
2316                     }
2317                 }
2318             }
2319
2320             if ($interface->extendedAttributes->{"ReplaceableConstructor"}) {
2321                 my $constructorFunctionName = "setJS" . $interfaceName . "Constructor";
2322
2323                 push(@implContent, "void ${constructorFunctionName}(ExecState* exec, JSObject* thisObject, JSValue value)\n");
2324                 push(@implContent, "{\n");
2325                 if ($interface->extendedAttributes->{"CheckSecurity"}) {
2326                     if ($interfaceName eq "DOMWindow") {
2327                         $implIncludes{"BindingSecurity.h"} = 1;
2328                         push(@implContent, "    if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, jsCast<$className*>(thisObject)->impl()))\n");
2329                     } else {
2330                         push(@implContent, "    if (!shouldAllowAccessToFrame(exec, jsCast<$className*>(thisObject)->impl()->frame()))\n");
2331                     }
2332                     push(@implContent, "        return;\n");
2333                 }
2334
2335                 push(@implContent, "    // Shadowing a built-in constructor\n");
2336
2337                 if ($interfaceName eq "DOMWindow") {
2338                     push(@implContent, "    jsCast<$className*>(thisObject)->putDirect(exec->vm(), exec->propertyNames().constructor, value);\n");
2339                 } else {
2340                     die "No way to handle interface with ReplaceableConstructor extended attribute: $interfaceName";
2341                 }
2342                 push(@implContent, "}\n\n");
2343             }        
2344         }
2345     }
2346
2347     if (($interface->extendedAttributes->{"IndexedGetter"} || $interface->extendedAttributes->{"NumericIndexedGetter"}) && !$interface->extendedAttributes->{"CustomEnumerateProperty"}) {
2348         push(@implContent, "void ${className}::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)\n");
2349         push(@implContent, "{\n");
2350         push(@implContent, "    ${className}* thisObject = jsCast<${className}*>(object);\n");
2351         push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\n");
2352         if ($interface->extendedAttributes->{"IndexedGetter"} || $interface->extendedAttributes->{"NumericIndexedGetter"}) {
2353             push(@implContent, "    for (unsigned i = 0; i < static_cast<${interfaceName}*>(thisObject->impl())->length(); ++i)\n");
2354             push(@implContent, "        propertyNames.add(Identifier::from(exec, i));\n");
2355         }
2356         push(@implContent, "     Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode);\n");
2357         push(@implContent, "}\n\n");
2358     }
2359
2360     if (!$interface->extendedAttributes->{"OmitConstructor"}) {
2361         push(@implContent, "JSValue ${className}::getConstructor(ExecState* exec, JSGlobalObject* globalObject)\n{\n");
2362         push(@implContent, "    return getDOMConstructor<${className}Constructor>(exec, jsCast<JSDOMGlobalObject*>(globalObject));\n");
2363         push(@implContent, "}\n\n");
2364     }
2365
2366     # Functions
2367     if ($numFunctions > 0) {
2368         foreach my $function (@{$interface->functions}) {
2369             AddIncludesForTypeInImpl($function->signature->type);
2370
2371             my $isCustom = HasCustomMethod($function->signature->extendedAttributes);
2372             my $isOverloaded = $function->{overloads} && @{$function->{overloads}} > 1;
2373
2374             next if $isCustom && $isOverloaded && $function->{overloadIndex} > 1;
2375
2376             my $functionName = GetFunctionName($className, $function);
2377
2378             my $conditional = $function->signature->extendedAttributes->{"Conditional"};
2379             if ($conditional) {
2380                 my $conditionalString = $codeGenerator->GenerateConditionalStringFromAttributeValue($conditional);
2381                 push(@implContent, "#if ${conditionalString}\n");
2382             }
2383
2384
2385             if (!$isCustom && $isOverloaded) {
2386                 # Append a number to an overloaded method's name to make it unique:
2387                 $functionName = $functionName . $function->{overloadIndex};
2388                 # Make this function static to avoid compiler warnings, since we
2389                 # don't generate a prototype for it in the header.
2390                 push(@implContent, "static ");
2391             }
2392
2393             my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementedAs"} || $codeGenerator->WK_lcfirst($function->signature->name);
2394
2395             push(@implContent, "EncodedJSValue JSC_HOST_CALL ${functionName}(ExecState* exec)\n");
2396             push(@implContent, "{\n");
2397
2398             $implIncludes{"<runtime/Error.h>"} = 1;
2399
2400             if ($function->isStatic) {
2401                 if ($isCustom) {
2402                     GenerateArgumentsCountCheck(\@implContent, $function, $interface);
2403                     push(@implContent, "    return JSValue::encode(${className}::" . $functionImplementationName . "(exec));\n");
2404                 } else {
2405                     GenerateArgumentsCountCheck(\@implContent, $function, $interface);
2406
2407                     if (@{$function->raisesExceptions}) {
2408                         push(@implContent, "    ExceptionCode ec = 0;\n");
2409                     }
2410
2411                     my $numParameters = @{$function->parameters};
2412                     my ($functionString, $dummy) = GenerateParametersCheck(\@implContent, $function, $interface, $numParameters, $interfaceName, $functionImplementationName, $svgPropertyType, $svgPropertyOrListPropertyType, $svgListPropertyType);
2413                     GenerateImplementationFunctionCall($function, $functionString, "    ", $svgPropertyType, $interfaceName);
2414                 }
2415             } else {
2416                 if ($interfaceName eq "DOMWindow") {
2417                     push(@implContent, "    $className* castedThis = toJSDOMWindow(exec->hostThisValue().toThisObject(exec));\n");
2418                     push(@implContent, "    if (!castedThis)\n");
2419                     push(@implContent, "        return throwVMTypeError(exec);\n");
2420                 } elsif ($interface->extendedAttributes->{"IsWorkerContext"}) {
2421                     push(@implContent, "    $className* castedThis = to${className}(exec->hostThisValue().toThisObject(exec));\n");
2422                     push(@implContent, "    if (!castedThis)\n");
2423                     push(@implContent, "        return throwVMTypeError(exec);\n");
2424                 } else {
2425                     push(@implContent, "    JSValue thisValue = exec->hostThisValue();\n");
2426                     push(@implContent, "    if (!thisValue.inherits(&${className}::s_info))\n");
2427                     push(@implContent, "        return throwVMTypeError(exec);\n");
2428                     push(@implContent, "    $className* castedThis = jsCast<$className*>(asObject(thisValue));\n");
2429                 }
2430
2431                 push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(castedThis, &${className}::s_info);\n");
2432
2433                 if ($interface->extendedAttributes->{"CheckSecurity"} and
2434                     !$function->signature->extendedAttributes->{"DoNotCheckSecurity"}) {
2435                     $implIncludes{"BindingSecurity.h"} = 1;
2436                     push(@implContent, "    if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, castedThis->impl()))\n");
2437                     push(@implContent, "        return JSValue::encode(jsUndefined());\n");
2438                 }
2439
2440                 if ($isCustom) {
2441                     push(@implContent, "    return JSValue::encode(castedThis->" . $functionImplementationName . "(exec));\n");
2442                 } else {
2443                     if ($function->signature->name eq "set" and $interface->extendedAttributes->{"TypedArray"}) {
2444                         my $viewType = $interface->extendedAttributes->{"TypedArray"};
2445                         push(@implContent, "    return JSValue::encode(setWebGLArrayHelper<$implType, $viewType>(exec, castedThis->impl()));\n");
2446                         push(@implContent, "}\n\n");
2447                         next;
2448                     }
2449
2450                     push(@implContent, "    $implType* impl = static_cast<$implType*>(castedThis->impl());\n");
2451                     if ($svgPropertyType) {
2452                         push(@implContent, "    if (impl->isReadOnly()) {\n");
2453                         push(@implContent, "        setDOMException(exec, NO_MODIFICATION_ALLOWED_ERR);\n");
2454                         push(@implContent, "        return JSValue::encode(jsUndefined());\n");
2455                         push(@implContent, "    }\n");
2456                         push(@implContent, "    $svgPropertyType& podImpl = impl->propertyReference();\n");
2457                         $implIncludes{"ExceptionCode.h"} = 1;
2458                     }
2459
2460                     # For compatibility with legacy content, the EventListener calls are generated without GenerateArgumentsCountCheck.
2461                     if ($function->signature->name eq "addEventListener") {
2462                         push(@implContent, GenerateEventListenerCall($className, "add"));
2463                     } elsif ($function->signature->name eq "removeEventListener") {
2464                         push(@implContent, GenerateEventListenerCall($className, "remove"));
2465                     } else {
2466                         GenerateArgumentsCountCheck(\@implContent, $function, $interface);
2467
2468                         if (@{$function->raisesExceptions}) {
2469                             push(@implContent, "    ExceptionCode ec = 0;\n");
2470                         }
2471
2472                         if ($function->signature->extendedAttributes->{"CheckSecurityForNode"}) {
2473                             push(@implContent, "    if (!shouldAllowAccessToNode(exec, impl->" . $function->signature->name . "(" . (@{$function->raisesExceptions} ? "ec" : "") .")))\n");
2474                             push(@implContent, "        return JSValue::encode(jsNull());\n");
2475                             $implIncludes{"JSDOMBinding.h"} = 1;
2476                         }
2477
2478                         my $numParameters = @{$function->parameters};
2479                         my ($functionString, $dummy) = GenerateParametersCheck(\@implContent, $function, $interface, $numParameters, $interfaceName, $functionImplementationName, $svgPropertyType, $svgPropertyOrListPropertyType, $svgListPropertyType);
2480                         GenerateImplementationFunctionCall($function, $functionString, "    ", $svgPropertyType, $interfaceName);
2481                     }
2482                 }
2483             }
2484
2485             push(@implContent, "}\n\n");
2486
2487             if (!$isCustom && $isOverloaded && $function->{overloadIndex} == @{$function->{overloads}}) {
2488                 # Generate a function dispatching call to the rest of the overloads.
2489                 GenerateOverloadedFunction($function, $interface, $interfaceName);
2490             }
2491
2492             push(@implContent, "#endif\n\n") if $conditional;
2493         }
2494     }
2495
2496     if ($needsMarkChildren && !$interface->extendedAttributes->{"JSCustomMarkFunction"}) {
2497         push(@implContent, "void ${className}::visitChildren(JSCell* cell, SlotVisitor& visitor)\n");
2498         push(@implContent, "{\n");
2499         push(@implContent, "    ${className}* thisObject = jsCast<${className}*>(cell);\n");
2500         push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\n");
2501         push(@implContent, "    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);\n");
2502         push(@implContent, "    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());\n");
2503         push(@implContent, "    Base::visitChildren(thisObject, visitor);\n");
2504         if ($interface->extendedAttributes->{"EventTarget"} || $interface->name eq "EventTarget") {
2505             push(@implContent, "    thisObject->impl()->visitJSEventListeners(visitor);\n");
2506         }
2507         if ($numCachedAttributes > 0) {
2508             foreach (@{$interface->attributes}) {
2509                 my $attribute = $_;
2510                 if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) {
2511                     push(@implContent, "    visitor.append(&thisObject->m_" . $attribute->signature->name . ");\n");
2512                 }
2513             }
2514         }
2515         push(@implContent, "}\n\n");
2516     }
2517
2518     # Cached attributes are indeed allowed when there is a custom mark/visitChildren function.
2519     # The custom function must make sure to account for the cached attribute.
2520     # Uncomment the below line to temporarily enforce generated mark functions when cached attributes are present.
2521     # die "Can't generate binding for class with cached attribute and custom mark." if (($numCachedAttributes > 0) and ($interface->extendedAttributes->{"JSCustomMarkFunction"}));
2522
2523     if ($numConstants > 0) {
2524         push(@implContent, "// Constant getters\n\n");
2525
2526         foreach my $constant (@{$interface->constants}) {
2527             my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);
2528             my $conditional = $constant->extendedAttributes->{"Conditional"};
2529
2530             if ($conditional) {
2531                 my $conditionalString = $codeGenerator->GenerateConditionalStringFromAttributeValue($conditional);
2532                 push(@implContent, "#if ${conditionalString}\n");
2533             }
2534
2535             # FIXME: this casts into int to match our previous behavior which turned 0xFFFFFFFF in -1 for NodeFilter.SHOW_ALL
2536             push(@implContent, "JSValue ${getter}(ExecState* exec, JSValue, PropertyName)\n");
2537             push(@implContent, "{\n");
2538             if ($constant->type eq "DOMString") {
2539                 push(@implContent, "    return jsStringOrNull(exec, String(" . $constant->value . "));\n");
2540             } else {
2541                 push(@implContent, "    UNUSED_PARAM(exec);\n");
2542                 push(@implContent, "    return jsNumber(static_cast<int>(" . $constant->value . "));\n");
2543             }
2544             push(@implContent, "}\n\n");
2545             push(@implContent, "#endif\n") if $conditional;
2546         }
2547     }
2548
2549     if ($interface->extendedAttributes->{"IndexedGetter"}) {
2550         push(@implContent, "\nJSValue ${className}::indexGetter(ExecState* exec, JSValue slotBase, unsigned index)\n");
2551         push(@implContent, "{\n");
2552         push(@implContent, "    ${className}* thisObj = jsCast<$className*>(asObject(slotBase));\n");
2553         push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(thisObj, &s_info);\n");
2554         if (IndexGetterReturnsStrings($interfaceName)) {
2555             $implIncludes{"KURL.h"} = 1;
2556             push(@implContent, "    return jsStringOrUndefined(exec, thisObj->impl()->item(index));\n");
2557         } else {
2558             push(@implContent, "    return toJS(exec, thisObj->globalObject(), static_cast<$interfaceName*>(thisObj->impl())->item(index));\n");
2559         }
2560         push(@implContent, "}\n\n");
2561         if ($interfaceName =~ /^HTML\w*Collection$/ or $interfaceName eq "RadioNodeList") {
2562             $implIncludes{"JSNode.h"} = 1;
2563             $implIncludes{"Node.h"} = 1;
2564         }
2565     }
2566
2567     if ($interface->extendedAttributes->{"NumericIndexedGetter"}) {
2568         push(@implContent, "\nJSValue ${className}::getByIndex(ExecState*, unsigned index)\n");
2569         push(@implContent, "{\n");
2570         push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(this, &s_info);\n");
2571         push(@implContent, "    double result = static_cast<$interfaceName*>(impl())->item(index);\n");
2572         # jsNumber conversion doesn't suppress signalling NaNs, so enforce that here.
2573         push(@implContent, "    if (std::isnan(result))\n");
2574         push(@implContent, "        return jsNaN();\n");
2575         push(@implContent, "    return JSValue(result);\n");
2576         push(@implContent, "}\n\n");
2577         if ($interfaceName =~ /^HTML\w*Collection$/) {
2578             $implIncludes{"JSNode.h"} = 1;
2579             $implIncludes{"Node.h"} = 1;
2580         }
2581     }
2582
2583     if ($interfaceName eq "HTMLPropertiesCollection" or $interfaceName eq "DOMNamedFlowCollection") {
2584         if ($interface->extendedAttributes->{"NamedGetter"}) {
2585             push(@implContent, "bool ${className}::canGetItemsForName(ExecState*, $interfaceName* collection, PropertyName propertyName)\n");
2586             push(@implContent, "{\n");
2587             push(@implContent, "    return collection->hasNamedItem(propertyNameToAtomicString(propertyName));\n");
2588             push(@implContent, "}\n\n");
2589             push(@implContent, "JSValue ${className}::nameGetter(ExecState* exec, JSValue slotBase, PropertyName propertyName)\n");
2590             push(@implContent, "{\n");
2591             push(@implContent, "    ${className}* thisObj = jsCast<$className*>(asObject(slotBase));\n");
2592             if ($interfaceName eq "HTMLPropertiesCollection") {
2593                 push(@implContent, "    return toJS(exec, thisObj->globalObject(), WTF::getPtr(static_cast<$interfaceName*>(thisObj->impl())->propertyNodeList(propertyNameToAtomicString(propertyName))));\n");
2594             } else {
2595                 push(@implContent, "    return toJS(exec, thisObj->globalObject(), static_cast<$interfaceName*>(thisObj->impl())->namedItem(propertyNameToAtomicString(propertyName)));\n");
2596             }
2597             push(@implContent, "}\n\n");
2598         }
2599     }
2600
2601     if ((!$hasParent && !GetCustomIsReachable($interface))|| GetGenerateIsReachable($interface) || $codeGenerator->InheritsExtendedAttribute($interface, "ActiveDOMObject")) {
2602         push(@implContent, "static inline bool isObservable(JS${interfaceName}* js${interfaceName})\n");
2603         push(@implContent, "{\n");
2604         push(@implContent, "    if (js${interfaceName}->hasCustomProperties())\n");
2605         push(@implContent, "        return true;\n");
2606         if ($eventTarget) {
2607             push(@implContent, "    if (js${interfaceName}->impl()->hasEventListeners())\n");
2608             push(@implContent, "        return true;\n");
2609         }
2610         push(@implContent, "    return false;\n");
2611         push(@implContent, "}\n\n");
2612
2613         push(@implContent, "bool JS${interfaceName}Owner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)\n");
2614         push(@implContent, "{\n");
2615         push(@implContent, "    JS${interfaceName}* js${interfaceName} = jsCast<JS${interfaceName}*>(handle.get().asCell());\n");
2616         # All ActiveDOMObjects implement hasPendingActivity(), but not all of them
2617         # increment their C++ reference counts when hasPendingActivity() becomes
2618         # true. As a result, ActiveDOMObjects can be prematurely destroyed before
2619         # their pending activities complete. To wallpaper over this bug, JavaScript
2620         # wrappers unconditionally keep ActiveDOMObjects with pending activity alive.
2621         # FIXME: Fix this lifetime issue in the DOM, and move this hasPendingActivity
2622         # check below the isObservable check.
2623         if ($codeGenerator->InheritsExtendedAttribute($interface, "ActiveDOMObject")) {
2624             push(@implContent, "    if (js${interfaceName}->impl()->hasPendingActivity())\n");
2625             push(@implContent, "        return true;\n");
2626         }
2627         if ($codeGenerator->InheritsExtendedAttribute($interface, "EventTarget")) {
2628             push(@implContent, "    if (js${interfaceName}->impl()->isFiringEventListeners())\n");
2629             push(@implContent, "        return true;\n");
2630         }
2631         if ($codeGenerator->InheritsInterface($interface, "Node")) {
2632             push(@implContent, "    if (JSNodeOwner::isReachableFromOpaqueRoots(handle, 0, visitor))\n");
2633             push(@implContent, "        return true;\n");
2634         }
2635         push(@implContent, "    if (!isObservable(js${interfaceName}))\n");
2636         push(@implContent, "        return false;\n");
2637         if (GetGenerateIsReachable($interface)) {
2638             my $rootString;
2639             if (GetGenerateIsReachable($interface) eq "Impl") {
2640                 $rootString  = "    ${implType}* root = js${interfaceName}->impl();\n";
2641             } elsif (GetGenerateIsReachable($interface) eq "ImplContext") {
2642                 $rootString  = "    WebGLRenderingContext* root = js${interfaceName}->impl()->context();\n";
2643             } elsif (GetGenerateIsReachable($interface) eq "ImplFrame") {
2644                 $rootString  = "    Frame* root = js${interfaceName}->impl()->frame();\n";
2645                 $rootString .= "    if (!root)\n";
2646                 $rootString .= "        return false;\n";
2647             } elsif (GetGenerateIsReachable($interface) eq "ImplDocument") {
2648                 $rootString  = "    Document* root = js${interfaceName}->impl()->document();\n";
2649                 $rootString .= "    if (!root)\n";
2650                 $rootString .= "        return false;\n";
2651             } elsif (GetGenerateIsReachable($interface) eq "ImplElementRoot") {
2652                 $implIncludes{"Element.h"} = 1;
2653                 $implIncludes{"JSNodeCustom.h"} = 1;
2654                 $rootString  = "    Element* element = js${interfaceName}->impl()->element();\n";
2655                 $rootString .= "    if (!element)\n";
2656                 $rootString .= "        return false;\n";
2657                 $rootString .= "    void* root = WebCore::root(element);\n";
2658             } elsif ($interfaceName eq "CanvasRenderingContext") {
2659                 $rootString  = "    void* root = WebCore::root(js${interfaceName}->impl()->canvas());\n";
2660             } elsif (GetGenerateIsReachable($interface) eq "ImplOwnerNodeRoot") {
2661                 $implIncludes{"Element.h"} = 1;
2662                 $implIncludes{"JSNodeCustom.h"} = 1;
2663                 $rootString  = "    void* root = WebCore::root(js${interfaceName}->impl()->ownerNode());\n";
2664             } else {
2665                 $rootString  = "    void* root = WebCore::root(js${interfaceName}->impl());\n";
2666             }
2667
2668             push(@implContent, $rootString);
2669             push(@implContent, "    return visitor.containsOpaqueRoot(root);\n");
2670         } else {
2671             push(@implContent, "    UNUSED_PARAM(visitor);\n");
2672             push(@implContent, "    return false;\n");
2673         }
2674         push(@implContent, "}\n\n");
2675     }
2676
2677     if (!$interface->extendedAttributes->{"JSCustomFinalize"} &&
2678         (!$hasParent ||
2679          GetGenerateIsReachable($interface) ||
2680          GetCustomIsReachable($interface) ||
2681          $codeGenerator->InheritsExtendedAttribute($interface, "ActiveDOMObject"))) {
2682         push(@implContent, "void JS${interfaceName}Owner::finalize(JSC::Handle<JSC::Unknown> handle, void* context)\n");
2683         push(@implContent, "{\n");
2684         push(@implContent, "    JS${interfaceName}* js${interfaceName} = jsCast<JS${interfaceName}*>(handle.get().asCell());\n");
2685         push(@implContent, "    DOMWrapperWorld* world = static_cast<DOMWrapperWorld*>(context);\n");
2686         push(@implContent, "    uncacheWrapper(world, js${interfaceName}->impl(), js${interfaceName});\n");
2687         push(@implContent, "    js${interfaceName}->releaseImpl();\n");
2688         push(@implContent, "}\n\n");
2689     }
2690
2691     if (ShouldGenerateToJSImplementation($hasParent, $interface)) {
2692         my $vtableNameGnu = GetGnuVTableNameForInterface($interface);
2693         my $vtableRefGnu = GetGnuVTableRefForInterface($interface);
2694         my $vtableRefWin = GetWinVTableRefForInterface($interface);
2695
2696         push(@implContent, <<END) if $vtableNameGnu;
2697 #if ENABLE(BINDING_INTEGRITY)
2698 #if PLATFORM(WIN)
2699 #pragma warning(disable: 4483)
2700 extern "C" { extern void (*const ${vtableRefWin}[])(); }
2701 #else
2702 extern "C" { extern void* ${vtableNameGnu}[]; }
2703 #endif
2704 #endif
2705 END
2706
2707         push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* impl)\n");
2708         push(@implContent, "{\n");
2709         push(@implContent, <<END);
2710     if (!impl)
2711         return jsNull();
2712 END
2713
2714         if ($svgPropertyType) {
2715             push(@implContent, "    if (JSValue result = getExistingWrapper<$className, $implType>(exec, impl)) return result;\n");
2716         } else {
2717             push(@implContent, "    if (JSValue result = getExistingWrapper<$className>(exec, impl)) return result;\n");
2718         }
2719         push(@implContent, <<END) if $vtableNameGnu;
2720
2721 #if ENABLE(BINDING_INTEGRITY)
2722     void* actualVTablePointer = *(reinterpret_cast<void**>(impl));
2723 #if PLATFORM(WIN)
2724     void* expectedVTablePointer = reinterpret_cast<void*>(${vtableRefWin});
2725 #else
2726     void* expectedVTablePointer = ${vtableRefGnu};
2727 #if COMPILER(CLANG)
2728     // If this fails $implType does not have a vtable, so you need to add the
2729     // ImplementationLacksVTable attribute to the interface definition
2730     COMPILE_ASSERT(__is_polymorphic($implType), ${implType}_is_not_polymorphic);
2731 #endif
2732 #endif
2733     // If you hit this assertion you either have a use after free bug, or
2734     // $implType has subclasses. If $implType has subclasses that get passed
2735     // to toJS() we currently require $interfaceName you to opt out of binding hardening
2736     // by adding the SkipVTableValidation attribute to the interface IDL definition
2737     RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer);
2738 #endif
2739 END
2740         push(@implContent, <<END) if $interface->extendedAttributes->{"ImplementationLacksVTable"};
2741 #if COMPILER(CLANG)
2742     // If you hit this failure the interface definition has the ImplementationLacksVTable
2743     // attribute. You should remove that attribute. If the class has subclasses
2744     // that may be passed through this toJS() function you should use the SkipVTableValidation
2745     // attribute to $interfaceName.
2746     COMPILE_ASSERT(!__is_polymorphic($implType), ${implType}_is_polymorphic_but_idl_claims_not_to_be);
2747 #endif
2748 END
2749         push(@implContent, <<END);
2750     ReportMemoryCost<$implType>::reportMemoryCost(exec, impl);
2751 END
2752
2753         if ($svgPropertyType) {
2754             push(@implContent, "    return createNewWrapper<$className, $implType>(exec, globalObject, impl);\n");
2755         } else {
2756             push(@implContent, "    return createNewWrapper<$className>(exec, globalObject, impl);\n");
2757         }
2758
2759         push(@implContent, "}\n\n");
2760     }
2761
2762     if ((!$hasParent or $interface->extendedAttributes->{"JSGenerateToNativeObject"}) and !$interface->extendedAttributes->{"JSCustomToNativeObject"}) {
2763         push(@implContent, "$implType* to${interfaceName}(JSC::JSValue value)\n");
2764         push(@implContent, "{\n");
2765         push(@implContent, "    return value.inherits(&${className}::s_info) ? jsCast<$className*>(asObject(value))->impl() : 0");
2766         push(@implContent, ";\n}\n");
2767     }
2768
2769     push(@implContent, "\n}\n");
2770
2771     my $conditionalString = $codeGenerator->GenerateConditionalString($interface);
2772     push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
2773 }
2774
2775 sub GenerateCallWith
2776 {
2777     my $callWith = shift;
2778     return () unless $callWith;
2779     my $outputArray = shift;
2780     my $returnValue = shift;
2781     my $function = shift;
2782
2783     my @callWithArgs;
2784     if ($codeGenerator->ExtendedAttributeContains($callWith, "ScriptState")) {
2785         push(@callWithArgs, "exec");
2786     }
2787     if ($codeGenerator->ExtendedAttributeContains($callWith, "ScriptExecutionContext")) {
2788         push(@$outputArray, "    ScriptExecutionContext* scriptContext = jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext();\n");
2789         push(@$outputArray, "    if (!scriptContext)\n");
2790         push(@$outputArray, "        return" . ($returnValue ? " " . $returnValue : "") . ";\n");
2791         push(@callWithArgs, "scriptContext");
2792     }
2793     if ($function and $codeGenerator->ExtendedAttributeContains($callWith, "ScriptArguments")) {
2794         push(@$outputArray, "    RefPtr<ScriptArguments> scriptArguments(createScriptArguments(exec, " . @{$function->parameters} . "));\n");
2795         $implIncludes{"ScriptArguments.h"} = 1;
2796         $implIncludes{"ScriptCallStackFactory.h"} = 1;
2797         push(@callWithArgs, "scriptArguments.release()");
2798     }
2799     return @callWithArgs;
2800 }
2801
2802 sub GenerateArgumentsCountCheck
2803 {
2804     my $outputArray = shift;
2805     my $function = shift;
2806     my $interface = shift;
2807
2808     my $numMandatoryParams = @{$function->parameters};
2809     foreach my $param (reverse(@{$function->parameters})) {
2810         if ($param->isOptional or $param->isVariadic) {
2811             $numMandatoryParams--;
2812         } else {
2813             last;
2814         }
2815     }
2816     if ($numMandatoryParams >= 1)
2817     {
2818         push(@$outputArray, "    if (exec->argumentCount() < $numMandatoryParams)\n");
2819         push(@$outputArray, "        return throwVMError(exec, createNotEnoughArgumentsError(exec));\n");
2820     }
2821 }
2822
2823 sub GenerateParametersCheck
2824 {
2825     my $outputArray = shift;
2826     my $function = shift;
2827     my $interface = shift;
2828     my $numParameters = shift;
2829     my $interfaceName = shift;
2830     my $functionImplementationName = shift;
2831     my $svgPropertyType = shift;
2832     my $svgPropertyOrListPropertyType = shift;
2833     my $svgListPropertyType = shift;
2834
2835     my $argsIndex = 0;
2836     my $hasOptionalArguments = 0;
2837
2838     my @arguments;
2839     my $functionName;
2840     my $implementedBy = $function->signature->extendedAttributes->{"ImplementedBy"};
2841     if ($implementedBy) {
2842         AddToImplIncludes("${implementedBy}.h");
2843         unshift(@arguments, "impl") if !$function->isStatic;
2844         $functionName = "${implementedBy}::${functionImplementationName}";
2845     } elsif ($function->isStatic) {
2846         $functionName = "${interfaceName}::${functionImplementationName}";
2847     } elsif ($svgPropertyOrListPropertyType and !$svgListPropertyType) {
2848         $functionName = "podImpl.${functionImplementationName}";
2849     } else {
2850         $functionName = "impl->${functionImplementationName}";
2851     }
2852
2853     if (!$function->signature->extendedAttributes->{"Constructor"}) {
2854         push(@arguments, GenerateCallWith($function->signature->extendedAttributes->{"CallWith"}, \@$outputArray, "JSValue::encode(jsUndefined())", $function));
2855     }
2856
2857     $implIncludes{"ExceptionCode.h"} = 1;
2858     $implIncludes{"JSDOMBinding.h"} = 1;
2859
2860     foreach my $parameter (@{$function->parameters}) {
2861         my $argType = $parameter->type;
2862
2863         # Optional arguments with [Optional] should generate an early call with fewer arguments.
2864         # Optional arguments with [Optional=...] should not generate the early call.
2865         # Optional Dictionary arguments always considered to have default of empty dictionary.
2866         my $optional = $parameter->isOptional;
2867         my $defaultAttribute = $parameter->extendedAttributes->{"Default"};
2868         if ($optional && !$defaultAttribute && $argType ne "Dictionary" && !$codeGenerator->IsCallbackInterface($parameter->type)) {
2869             # Generate early call if there are enough parameters.
2870             if (!$hasOptionalArguments) {
2871                 push(@$outputArray, "\n    size_t argsCount = exec->argumentCount();\n");
2872                 $hasOptionalArguments = 1;
2873             }
2874             push(@$outputArray, "    if (argsCount <= $argsIndex) {\n");
2875
2876             my @optionalCallbackArguments = @arguments;
2877             if (@{$function->raisesExceptions}) {
2878                 push @optionalCallbackArguments, "ec";
2879             }
2880             my $functionString = "$functionName(" . join(", ", @optionalCallbackArguments) . ")";
2881             GenerateImplementationFunctionCall($function, $functionString, "    " x 2, $svgPropertyType, $interfaceName);
2882             push(@$outputArray, "    }\n\n");
2883         }
2884
2885         my $name = $parameter->name;
2886
2887         if ($argType eq "XPathNSResolver") {
2888             push(@$outputArray, "    RefPtr<XPathNSResolver> customResolver;\n");
2889             push(@$outputArray, "    XPathNSResolver* resolver = toXPathNSResolver(exec->argument($argsIndex));\n");
2890             push(@$outputArray, "    if (!resolver) {\n");
2891             push(@$outputArray, "        customResolver = JSCustomXPathNSResolver::create(exec, exec->argument($argsIndex));\n");
2892             push(@$outputArray, "        if (exec->hadException())\n");
2893             push(@$outputArray, "            return JSValue::encode(jsUndefined());\n");
2894             push(@$outputArray, "        resolver = customResolver.get();\n");
2895             push(@$outputArray, "    }\n");
2896         } elsif ($codeGenerator->IsCallbackInterface($parameter->type)) {
2897             my $callbackClassName = GetCallbackClassName($argType);
2898             $implIncludes{"$callbackClassName.h"} = 1;
2899             if ($optional) {
2900                 push(@$outputArray, "    RefPtr<$argType> $name;\n");
2901                 push(@$outputArray, "    if (exec->argumentCount() > $argsIndex && !exec->argument($argsIndex).isUndefinedOrNull()) {\n");
2902                 push(@$outputArray, "        if (!exec->argument($argsIndex).isFunction())\n");
2903                 push(@$outputArray, "            return throwVMTypeError(exec);\n");
2904                 if ($function->isStatic) {
2905                     AddToImplIncludes("CallbackFunction.h");
2906                     push(@$outputArray, "        $name = createFunctionOnlyCallback<${callbackClassName}>(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), exec->argument($argsIndex));\n");
2907                 } else {
2908                     push(@$outputArray, "        $name = ${callbackClassName}::create(asObject(exec->argument($argsIndex)), castedThis->globalObject());\n");
2909                 }
2910                 push(@$outputArray, "    }\n");
2911             } else {
2912                 push(@$outputArray, "    if (exec->argumentCount() <= $argsIndex || !exec->argument($argsIndex).isFunction())\n");
2913                 push(@$outputArray, "        return throwVMTypeError(exec);\n");
2914                 if ($function->isStatic) {
2915                     AddToImplIncludes("CallbackFunction.h");
2916                     push(@$outputArray, "    RefPtr<$argType> $name = createFunctionOnlyCallback<${callbackClassName}>(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), exec->argument($argsIndex));\n");
2917                 } else {
2918                     push(@$outputArray, "    RefPtr<$argType> $name = ${callbackClassName}::create(asObject(exec->argument($argsIndex)), castedThis->globalObject());\n");
2919                 }
2920             }
2921         } elsif ($parameter->extendedAttributes->{"Clamp"}) {
2922             my $nativeValue = "${name}NativeValue";
2923             push(@$outputArray, "    $argType $name = 0;\n");
2924             push(@$outputArray, "    double $nativeValue = exec->argument($argsIndex).toNumber(exec);\n");
2925             push(@$outputArray, "    if (exec->hadException())\n");
2926             push(@$outputArray, "        return JSValue::encode(jsUndefined());\n\n");
2927             push(@$outputArray, "    if (!std::isnan($nativeValue))\n");
2928             push(@$outputArray, "        $name = clampTo<$argType>($nativeValue);\n\n");
2929         } elsif ($parameter->isVariadic) {
2930             my $nativeElementType;
2931             if ($argType eq "DOMString") {
2932                 $nativeElementType = "String";
2933             } else {
2934                 $nativeElementType = GetNativeType($argType);
2935                 if ($nativeElementType =~ />$/) {
2936                     $nativeElementType .= " ";
2937                 }
2938             }
2939
2940             if (!IsNativeType($argType)) {
2941                 push(@$outputArray, "    Vector<$nativeElementType> $name;\n");
2942                 push(@$outputArray, "    for (unsigned i = $argsIndex; i < exec->argumentCount(); ++i) {\n");
2943                 push(@$outputArray, "        if (!exec->argument(i).inherits(&JS${argType}::s_info))\n");
2944                 push(@$outputArray, "            return throwVMTypeError(exec);\n");
2945                 push(@$outputArray, "        $name.append(to$argType(exec->argument(i)));\n");
2946                 push(@$outputArray, "    }\n")
2947             } else {
2948                 push(@$outputArray, "    Vector<$nativeElementType> $name = toNativeArguments<$nativeElementType>(exec, $argsIndex);\n");
2949                 # Check if the type conversion succeeded.
2950                 push(@$outputArray, "    if (exec->hadException())\n");
2951                 push(@$outputArray, "        return JSValue::encode(jsUndefined());\n");
2952             }
2953
2954         } elsif ($codeGenerator->IsEnumType($argType)) {
2955             $implIncludes{"<runtime/Error.h>"} = 1;
2956
2957             my $argValue = "exec->argument($argsIndex)";
2958             push(@$outputArray, "    const String ${name}(${argValue}.isEmpty() ? String() : ${argValue}.toString(exec)->value(exec));\n");
2959             push(@$outputArray, "    if (exec->hadException())\n");
2960             push(@$outputArray, "        return JSValue::encode(jsUndefined());\n");
2961
2962             my @enumValues = $codeGenerator->ValidEnumValues($argType);
2963             my @enumChecks = ();
2964             foreach my $enumValue (@enumValues) {
2965                 push(@enumChecks, "${name} != \"$enumValue\"");
2966             }
2967             push (@$outputArray, "    if (" . join(" && ", @enumChecks) . ")\n");
2968             push (@$outputArray, "        return throwVMTypeError(exec);\n");
2969         } else {
2970             # If the "StrictTypeChecking" extended attribute is present, and the argument's type is an
2971             # interface type, then if the incoming value does not implement that interface, a TypeError
2972             # is thrown rather than silently passing NULL to the C++ code.
2973             # Per the Web IDL and ECMAScript semantics, incoming values can always be converted to both
2974             # strings and numbers, so do not throw TypeError if the argument is of these types.
2975             if ($function->signature->extendedAttributes->{"StrictTypeChecking"}) {
2976                 $implIncludes{"<runtime/Error.h>"} = 1;
2977
2978                 my $argValue = "exec->argument($argsIndex)";
2979                 if (!IsNativeType($argType)) {
2980                     push(@$outputArray, "    if (exec->argumentCount() > $argsIndex && !${argValue}.isUndefinedOrNull() && !${argValue}.inherits(&JS${argType}::s_info))\n");
2981                     push(@$outputArray, "        return throwVMTypeError(exec);\n");
2982                 }
2983             }
2984
2985             push(@$outputArray, "    " . GetNativeTypeFromSignature($parameter) . " $name(" . JSValueToNative($parameter, $optional && $defaultAttribute && $defaultAttribute eq "NullString" ? "argumentOrNull(exec, $argsIndex)" : "exec->argument($argsIndex)") . ");\n");
2986
2987             # If a parameter is "an index" and it's negative it should throw an INDEX_SIZE_ERR exception.
2988             # But this needs to be done in the bindings, because the type is unsigned and the fact that it
2989             # was negative will be lost by the time we're inside the DOM.
2990             if ($parameter->extendedAttributes->{"IsIndex"}) {
2991                 push(@$outputArray, "    if ($name < 0) {\n");
2992                 push(@$outputArray, "        setDOMException(exec, INDEX_SIZE_ERR);\n");
2993                 push(@$outputArray, "        return JSValue::encode(jsUndefined());\n");
2994                 push(@$outputArray, "    }\n");
2995             }
2996
2997             # Check if the type conversion succeeded.
2998             push(@$outputArray, "    if (exec->hadException())\n");
2999             push(@$outputArray, "        return JSValue::encode(jsUndefined());\n");
3000
3001             if ($codeGenerator->IsSVGTypeNeedingTearOff($argType) and not $interfaceName =~ /List$/) {
3002                 push(@$outputArray, "    if (!$name) {\n");
3003                 push(@$outputArray, "        setDOMException(exec, TYPE_MISMATCH_ERR);\n");
3004                 push(@$outputArray, "        return JSValue::encode(jsUndefined());\n");
3005                 push(@$outputArray, "    }\n");
3006             }
3007         }
3008
3009         if ($argType eq "NodeFilter") {
3010             push @arguments, "$name.get()";
3011         } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($argType) and not $interfaceName =~ /List$/) {
3012             push @arguments, "$name->propertyReference()";
3013         } else {
3014             push @arguments, $name;
3015         }
3016         $argsIndex++;
3017     }
3018
3019     if (@{$function->raisesExceptions}) {
3020         push @arguments, "ec";
3021     }
3022     return ("$functionName(" . join(", ", @arguments) . ")", scalar @arguments);
3023 }
3024
3025 sub GenerateCallbackHeader
3026 {
3027     my $object = shift;
3028     my $interface = shift;
3029
3030     my $interfaceName = $interface->name;
3031     my $className = "JS$interfaceName";
3032
3033     # - Add default header template and header protection
3034     push(@headerContentHeader, GenerateHeaderContentHeader($interface));
3035
3036     $headerIncludes{"ActiveDOMCallback.h"} = 1;
3037     $headerIncludes{"$interfaceName.h"} = 1;
3038     $headerIncludes{"JSCallbackData.h"} = 1;
3039     $headerIncludes{"<wtf/Forward.h>"} = 1;
3040
3041     push(@headerContent, "\nnamespace WebCore {\n\n");
3042     push(@headerContent, "class $className : public $interfaceName, public ActiveDOMCallback {\n");
3043     push(@headerContent, "public:\n");
3044
3045     # The static create() method.
3046     push(@headerContent, "    static PassRefPtr<$className> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject)\n");
3047     push(@headerContent, "    {\n");
3048     push(@headerContent, "        return adoptRef(new $className(callback, globalObject));\n");
3049     push(@headerContent, "    }\n\n");
3050
3051     # ScriptExecutionContext
3052     push(@headerContent, "    virtual ScriptExecutionContext* scriptExecutionContext() const { return ContextDestructionObserver::scriptExecutionContext(); }\n\n");
3053
3054     # Destructor
3055     push(@headerContent, "    virtual ~$className();\n");
3056
3057     # Functions
3058     my $numFunctions = @{$interface->functions};
3059     if ($numFunctions > 0) {
3060         push(@headerContent, "\n    // Functions\n");
3061         foreach my $function (@{$interface->functions}) {
3062             my @params = @{$function->parameters};
3063             if (!$function->signature->extendedAttributes->{"Custom"} &&
3064                 !(GetNativeType($function->signature->type) eq "bool")) {
3065                 push(@headerContent, "    COMPILE_ASSERT(false)");
3066             }
3067
3068             push(@headerContent, "    virtual " . GetNativeTypeForCallbacks($function->signature->type) . " " . $function->signature->name . "(");
3069
3070             my @args = ();
3071             foreach my $param (@params) {
3072                 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $param->name);
3073             }
3074             push(@headerContent, join(", ", @args));
3075
3076             push(@headerContent, ");\n");
3077         }
3078     }
3079
3080     push(@headerContent, "\nprivate:\n");
3081
3082     # Constructor
3083     push(@headerContent, "    $className(JSC::JSObject* callback, JSDOMGlobalObject*);\n\n");
3084
3085     # Private members
3086     push(@headerContent, "    JSCallbackData* m_data;\n");
3087     push(@headerContent, "};\n\n");
3088
3089     push(@headerContent, "} // namespace WebCore\n\n");
3090     my $conditionalString = $codeGenerator->GenerateConditionalString($interface);
3091     push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;
3092     push(@headerContent, "#endif\n");
3093 }
3094
3095 sub GenerateCallbackImplementation
3096 {
3097     my ($object, $interface) = @_;
3098
3099     my $interfaceName = $interface->name;
3100     my $className = "JS$interfaceName";
3101
3102     # - Add default header template
3103     push(@implContentHeader, GenerateImplementationContentHeader($interface));
3104
3105     $implIncludes{"ScriptExecutionContext.h"} = 1;
3106     $implIncludes{"<runtime/JSLock.h>"} = 1;
3107
3108     @implContent = ();
3109
3110     push(@implContent, "\nusing namespace JSC;\n\n");
3111     push(@implContent, "namespace WebCore {\n\n");
3112
3113     # Constructor
3114     push(@implContent, "${className}::${className}(JSObject* callback, JSDOMGlobalObject* globalObject)\n");
3115     push(@implContent, "    : ActiveDOMCallback(globalObject->scriptExecutionContext())\n");
3116     push(@implContent, "    , m_data(new JSCallbackData(callback, globalObject))\n");
3117     push(@implContent, "{\n");
3118     push(@implContent, "}\n\n");
3119
3120     # Destructor
3121     push(@implContent, "${className}::~${className}()\n");
3122     push(@implContent, "{\n");
3123     push(@implContent, "    ScriptExecutionContext* context = scriptExecutionContext();\n");
3124     push(@implContent, "    // When the context is destroyed, all tasks with a reference to a callback\n");
3125     push(@implContent, "    // should be deleted. So if the context is 0, we are on the context thread.\n");
3126     push(@implContent, "    if (!context || context->isContextThread())\n");
3127     push(@implContent, "        delete m_data;\n");
3128     push(@implContent, "    else\n");
3129     push(@implContent, "        context->postTask(DeleteCallbackDataTask::create(m_data));\n");
3130     push(@implContent, "#ifndef NDEBUG\n");
3131     push(@implContent, "    m_data = 0;\n");
3132     push(@implContent, "#endif\n");
3133     push(@implContent, "}\n");
3134
3135     # Functions
3136     my $numFunctions = @{$interface->functions};
3137     if ($numFunctions > 0) {
3138         push(@implContent, "\n// Functions\n");
3139         foreach my $function (@{$interface->functions}) {
3140             my @params = @{$function->parameters};
3141             if ($function->signature->extendedAttributes->{"Custom"} ||
3142                 !(GetNativeType($function->signature->type) eq "bool")) {
3143                 next;
3144             }
3145
3146             AddIncludesForTypeInImpl($function->signature->type);
3147             push(@implContent, "\n" . GetNativeTypeForCallbacks($function->signature->type) . " ${className}::" . $function->signature->name . "(");
3148
3149             my @args = ();
3150             my @argsCheck = ();
3151             my $thisType = $function->signature->extendedAttributes->{"PassThisToCallback"};
3152             foreach my $param (@params) {
3153                 my $paramName = $param->name;
3154                 AddIncludesForTypeInImpl($param->type, 1);
3155                 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $paramName);
3156                 if ($thisType and $thisType eq $param->type) {
3157                     push(@argsCheck, <<END);
3158     ASSERT(${paramName});
3159
3160 END
3161                 }
3162             }
3163             push(@implContent, join(", ", @args));
3164             push(@implContent, ")\n");
3165
3166             push(@implContent, "{\n");
3167             push(@implContent, @argsCheck) if @argsCheck;
3168             push(@implContent, "    if (!canInvokeCallback())\n");
3169             push(@implContent, "        return true;\n\n");
3170             push(@implContent, "    RefPtr<$className> protect(this);\n\n");
3171             push(@implContent, "    JSLockHolder lock(m_data->globalObject()->vm());\n\n");
3172             if (@params) {
3173                 push(@implContent, "    ExecState* exec = m_data->globalObject()->globalExec();\n");
3174             }
3175             push(@implContent, "    MarkedArgumentBuffer args;\n");
3176
3177             foreach my $param (@params) {
3178                 my $paramName = $param->name;
3179                 if ($param->type eq "DOMString") {
3180                     push(@implContent, "    args.append(jsStringWithCache(exec, ${paramName}));\n");
3181                 } elsif ($param->type eq "boolean") {
3182                     push(@implContent, "    args.append(jsBoolean(${paramName}));\n");
3183                 } elsif ($param->type eq "SerializedScriptValue") {
3184                     push(@implContent, "    args.append($paramName ? $paramName->deserialize(exec, m_data->globalObject(), 0) : jsNull());\n");
3185                 } else {
3186                     push(@implContent, "    args.append(toJS(exec, m_data->globalObject(), ${paramName}));\n");
3187                 }
3188             }
3189
3190             push(@implContent, "\n    bool raisedException = false;\n");
3191             if ($thisType) {
3192                 foreach my $param (@params) {
3193                     next if $param->type ne $thisType;
3194                     my $paramName = $param->name;
3195                     push(@implContent, <<END);
3196     JSValue js${paramName} = toJS(exec, m_data->globalObject(), ${paramName});
3197     m_data->invokeCallback(js${paramName}, args, &raisedException);
3198
3199 END
3200                     last;
3201                 }
3202             } else {
3203                 push(@implContent, "    m_data->invokeCallback(args, &raisedException);\n");
3204             }
3205             push(@implContent, "    return !raisedException;\n");
3206             push(@implContent, "}\n");
3207         }
3208     }
3209
3210     push(@implContent, "\n}\n");
3211     my $conditionalString = $codeGenerator->GenerateConditionalString($interface);
3212     push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
3213 }
3214
3215 sub GenerateImplementationFunctionCall()
3216 {
3217     my $function = shift;
3218     my $functionString = shift;
3219     my $indent = shift;
3220     my $svgPropertyType = shift;
3221     my $interfaceName = shift;
3222
3223     if ($function->signature->type eq "void") {
3224         push(@implContent, $indent . "$functionString;\n");
3225         push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions};
3226
3227         if ($svgPropertyType and !$function->isStatic) {
3228             if (@{$function->raisesExceptions}) {
3229                 push(@implContent, $indent . "if (!ec)\n"); 
3230                 push(@implContent, $indent . "    impl->commitChange();\n");
3231             } else {
3232                 push(@implContent, $indent . "impl->commitChange();\n");
3233             }
3234         }
3235
3236         push(@implContent, $indent . "return JSValue::encode(jsUndefined());\n");
3237     } else {
3238         my $thisObject = $function->isStatic ? 0 : "castedThis";
3239         push(@implContent, "\n" . $indent . "JSC::JSValue result = " . NativeToJSValue($function->signature, 1, $interfaceName, $functionString, $thisObject) . ";\n");
3240         push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions};
3241
3242         if ($codeGenerator->ExtendedAttributeContains($function->signature->extendedAttributes->{"CallWith"}, "ScriptState")) {
3243             push(@implContent, $indent . "if (exec->hadException())\n");
3244             push(@implContent, $indent . "    return JSValue::encode(jsUndefined());\n");
3245         }
3246
3247         push(@implContent, $indent . "return JSValue::encode(result);\n");
3248     }
3249 }
3250
3251 sub GetNativeTypeFromSignature
3252 {
3253     my $signature = shift;
3254     my $type = $signature->type;
3255
3256     if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) {
3257         # Special-case index arguments because we need to check that they aren't < 0.
3258         return "int";
3259     }
3260
3261     return GetNativeType($type);
3262 }
3263
3264 my %nativeType = (
3265     "CompareHow" => "Range::CompareHow",
3266     "DOMString" => "const String&",
3267     "NodeFilter" => "RefPtr<NodeFilter>",
3268     "SerializedScriptValue" => "RefPtr<SerializedScriptValue>",
3269     "Date" => "double",
3270     "Dictionary" => "Dictionary",
3271     "any" => "ScriptValue",
3272     "boolean" => "bool",
3273     "double" => "double",
3274     "float" => "float",
3275     "short" => "short",
3276     "long" => "int",
3277     "unsigned long" => "unsigned",
3278     "unsigned short" => "unsigned short",
3279     "long long" => "long long",
3280     "unsigned long long" => "unsigned long long",
3281     "MediaQueryListListener" => "RefPtr<MediaQueryListListener>",
3282     "DOMTimeStamp" => "DOMTimeStamp",    
3283 );
3284
3285 sub GetNativeType
3286 {
3287     my $type = shift;
3288
3289     my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($type);
3290     return "${svgNativeType}*" if $svgNativeType;
3291     return "RefPtr<DOMStringList>" if $type eq "DOMStringList";
3292     return $nativeType{$type} if exists $nativeType{$type};
3293
3294     my $arrayType = $codeGenerator->GetArrayType($type);
3295     my $sequenceType = $codeGenerator->GetSequenceType($type);
3296     my $arrayOrSequenceType = $arrayType || $sequenceType;
3297
3298     return "Vector<" . GetNativeVectorInnerType($arrayOrSequenceType) . ">" if $arrayOrSequenceType;
3299
3300     if ($codeGenerator->IsEnumType($type)) {
3301         return "const String";
3302     }
3303
3304     # For all other types, the native type is a pointer with same type name as the IDL type.
3305     return "${type}*";
3306 }
3307
3308 sub GetNativeVectorInnerType
3309 {
3310     my $arrayOrSequenceType = shift;
3311
3312     return "String" if $arrayOrSequenceType eq "DOMString";
3313     return $nativeType{$arrayOrSequenceType} if exists $nativeType{$arrayOrSequenceType};
3314     return "RefPtr<${arrayOrSequenceType}> ";
3315 }
3316
3317 sub GetNativeTypeForCallbacks
3318 {
3319     my $type = shift;
3320     return "PassRefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValue";
3321     return "PassRefPtr<DOMStringList>" if $type eq "DOMStringList";
3322
3323     return GetNativeType($type);
3324 }
3325
3326 sub GetSVGPropertyTypes
3327 {
3328     my $implType = shift;
3329
3330     my $svgPropertyType;
3331     my $svgListPropertyType;
3332     my $svgNativeType;
3333
3334     return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $implType =~ /SVG/;
3335     
3336     $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implType);
3337     return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $svgNativeType;
3338
3339     # Append space to avoid compilation errors when using  PassRefPtr<$svgNativeType>
3340     $svgNativeType = "$svgNativeType ";
3341
3342     my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implType);
3343     if ($svgNativeType =~ /SVGPropertyTearOff/) {
3344         $svgPropertyType = $svgWrappedNativeType;
3345         $headerIncludes{"$svgWrappedNativeType.h"} = 1;
3346         $headerIncludes{"SVGAnimatedPropertyTearOff.h"} = 1;
3347     } elsif ($svgNativeType =~ /SVGListPropertyTearOff/ or $svgNativeType =~ /SVGStaticListPropertyTearOff/) {
3348         $svgListPropertyType = $svgWrappedNativeType;
3349         $headerIncludes{"$svgWrappedNativeType.h"} = 1;
3350         $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;
3351     } elsif ($svgNativeType =~ /SVGTransformListPropertyTearOff/) {
3352         $svgListPropertyType = $svgWrappedNativeType;
3353         $headerIncludes{"$svgWrappedNativeType.h"} = 1;
3354         $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;
3355         $headerIncludes{"SVGTransformListPropertyTearOff.h"} = 1;
3356     } elsif ($svgNativeType =~ /SVGPathSegListPropertyTearOff/) {
3357         $svgListPropertyType = $svgWrappedNativeType;
3358         $headerIncludes{"$svgWrappedNativeType.h"} = 1;
3359         $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;
3360         $headerIncludes{"SVGPathSegListPropertyTearOff.h"} = 1;
3361     }
3362
3363     return ($svgPropertyType, $svgListPropertyType, $svgNativeType);
3364 }
3365
3366 sub IsNativeType
3367 {
3368     my $type = shift;
3369     return exists $nativeType{$type};
3370 }
3371
3372 sub JSValueToNative
3373 {
3374     my $signature = shift;
3375     my $value = shift;
3376
3377     my $conditional = $signature->extendedAttributes->{"Conditional"};
3378     my $type = $signature->type;
3379
3380     return "$value.toBoolean(exec)" if $type eq "boolean";
3381     return "$value.toNumber(exec)" if $type eq "double";
3382     return "$value.toFloat(exec)" if $type eq "float";
3383
3384     my $intConversion = $signature->extendedAttributes->{"EnforceRange"} ? "EnforceRange" : "NormalConversion";
3385     return "toInt32(exec, $value, $intConversion)" if $type eq "long" or $type eq "short";
3386     return "toUInt32(exec, $value, $intConversion)" if $type eq "unsigned long" or $type eq "unsigned short";
3387     return "toInt64(exec, $value, $intConversion)" if $type eq "long long";
3388     return "toUInt64(exec, $value, $intConversion)" if $type eq "unsigned long long";
3389
3390     return "valueToDate(exec, $value)" if $type eq "Date";
3391     return "static_cast<Range::CompareHow>($value.toInt32