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