a85a370033ff484b235e5596738d230d4ef34f69
[WebKit-https.git] / Source / WebCore / bindings / scripts / CodeGeneratorV8.pm
1 # Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
2 # Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
3 # Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
4 # Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
5 # Copyright (C) 2006 Apple Computer, Inc.
6 # Copyright (C) 2007, 2008, 2009, 2012 Google Inc.
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 #
11 # This library is free software; you can redistribute it and/or
12 # modify it under the terms of the GNU Library General Public
13 # License as published by the Free Software Foundation; either
14 # version 2 of the License, or (at your option) any later version.
15 #
16 # This library is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 # Library General Public License for more details.
20 #
21 # You should have received a copy of the GNU Library General Public License
22 # along with this library; see the file COPYING.LIB.  If not, write to
23 # the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 # Boston, MA 02111-1307, USA.
25 #
26
27 package CodeGeneratorV8;
28
29 use strict;
30
31 use Digest::MD5;
32
33 use constant FileNamePrefix => "V8";
34
35 my $codeGenerator;
36
37 my $module = "";
38 my $outputDir = "";
39 my $outputHeadersDir = "";
40
41 my @headerContent = ();
42 my @implContentHeader = ();
43 my @implFixedHeader = ();
44 my @implContent = ();
45 my @implContentDecls = ();
46 my %implIncludes = ();
47 my %headerIncludes = ();
48
49 my @allParents = ();
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., 59 Temple Place - Suite 330,
70     Boston, MA 02111-1307, USA.
71 */
72 EOF
73
74 # Default constructor
75 sub new
76 {
77     my $object = shift;
78     my $reference = { };
79
80     $codeGenerator = shift;
81     $outputDir = shift;
82     $outputHeadersDir = shift;
83
84     bless($reference, $object);
85     return $reference;
86 }
87
88 # Params: 'domClass' struct
89 sub GenerateInterface
90 {
91     my $object = shift;
92     my $dataNode = shift;
93     my $defines = shift;
94
95     # Start actual generation
96     if ($dataNode->extendedAttributes->{"Callback"}) {
97         $object->GenerateCallbackHeader($dataNode);
98         $object->GenerateCallbackImplementation($dataNode);
99     } else {
100         $object->GenerateHeader($dataNode);
101         $object->GenerateImplementation($dataNode);
102     }
103
104     $object->WriteData($dataNode);
105 }
106
107 # Params: 'idlDocument' struct
108 sub GenerateModule
109 {
110     my $object = shift;
111     my $dataNode = shift;
112
113     $module = $dataNode->module;
114 }
115
116 sub AddToImplIncludes
117 {
118     my $header = shift;
119     my $conditional = shift;
120
121     if (not $conditional) {
122         $implIncludes{$header} = 1;
123     } elsif (not exists($implIncludes{$header})) {
124         $implIncludes{$header} = $conditional;
125     } else {
126         my $oldValue = $implIncludes{$header};
127         if ($oldValue ne 1) {
128             my %newValue = ();
129             $newValue{$conditional} = 1;
130             foreach my $condition (split(/\|/, $oldValue)) {
131                 $newValue{$condition} = 1;
132             }
133             $implIncludes{$header} = join("|", sort keys %newValue);
134         }
135     }
136 }
137
138 sub AddIncludesForType
139 {
140     my $type = $codeGenerator->StripModule(shift);
141
142     # When we're finished with the one-file-per-class
143     # reorganization, we won't need these special cases.
144     if ($codeGenerator->IsTypedArrayType($type)) {
145         AddToImplIncludes("wtf/${type}.h");
146     }
147     if (!$codeGenerator->IsPrimitiveType($type) and !$codeGenerator->IsStringType($type) and !$codeGenerator->SkipIncludeHeader($type) and $type ne "Date") {
148         # default, include the same named file
149         AddToImplIncludes(GetV8HeaderName(${type}));
150
151         if ($type =~ /SVGPathSeg/) {
152             my $joinedName = $type;
153             $joinedName =~ s/Abs|Rel//;
154             AddToImplIncludes("${joinedName}.h");
155         }
156     }
157
158     # additional includes (things needed to compile the bindings but not the header)
159
160     if ($type eq "CanvasRenderingContext2D") {
161         AddToImplIncludes("CanvasGradient.h");
162         AddToImplIncludes("CanvasPattern.h");
163         AddToImplIncludes("CanvasStyle.h");
164     }
165
166     if ($type eq "CanvasGradient" or $type eq "XPathNSResolver") {
167         AddToImplIncludes("wtf/text/WTFString.h");
168     }
169
170     if ($type eq "CSSStyleSheet" or $type eq "StyleSheet") {
171         AddToImplIncludes("CSSImportRule.h");
172     }
173
174     if ($type eq "CSSStyleDeclaration") {
175         AddToImplIncludes("StylePropertySet.h");
176     }
177
178     if ($type eq "Plugin" or $type eq "PluginArray" or $type eq "MimeTypeArray") {
179         # So we can get String -> AtomicString conversion for namedItem().
180         AddToImplIncludes("wtf/text/AtomicString.h");
181     }
182 }
183
184 sub NeedsCustomOpaqueRootForGC
185 {
186     my $dataNode = shift;
187     return GetGenerateIsReachable($dataNode) || GetCustomIsReachable($dataNode);
188 }
189
190 sub GetGenerateIsReachable
191 {
192     my $dataNode = shift;
193     return $dataNode->extendedAttributes->{"GenerateIsReachable"} || $dataNode->extendedAttributes->{"V8GenerateIsReachable"} || ""
194 }
195
196 sub GetCustomIsReachable
197 {
198     my $dataNode = shift;
199     return $dataNode->extendedAttributes->{"CustomIsReachable"} || $dataNode->extendedAttributes->{"V8CustomIsReachable"};
200 }
201
202 sub GenerateOpaqueRootForGC
203 {
204     my $dataNode = shift;
205     my $interfaceName = $dataNode->name;
206
207     if (GetCustomIsReachable($dataNode)) {
208         return;
209     }
210
211     push(@implContent, <<END);
212 void* V8${interfaceName}::opaqueRootForGC(void* object, v8::Persistent<v8::Object> wrapper)
213 {
214     ASSERT(!wrapper.IsIndependent());
215     ${interfaceName}* impl = static_cast<${interfaceName}*>(object);
216 END
217     if (GetGenerateIsReachable($dataNode) eq  "ImplDocument" ||
218         GetGenerateIsReachable($dataNode) eq  "ImplElementRoot" ||
219         GetGenerateIsReachable($dataNode) eq  "ImplOwnerRoot" ||
220         GetGenerateIsReachable($dataNode) eq  "ImplOwnerNodeRoot" ||
221         GetGenerateIsReachable($dataNode) eq  "ImplBaseRoot") {
222
223         $implIncludes{"V8GCController.h"} = 1;
224
225         my $methodName;
226         $methodName = "document" if (GetGenerateIsReachable($dataNode) eq "ImplDocument");
227         $methodName = "element" if (GetGenerateIsReachable($dataNode) eq "ImplElementRoot");
228         $methodName = "owner" if (GetGenerateIsReachable($dataNode) eq "ImplOwnerRoot");
229         $methodName = "ownerNode" if (GetGenerateIsReachable($dataNode) eq "ImplOwnerNodeRoot");
230         $methodName = "base" if (GetGenerateIsReachable($dataNode) eq "ImplBaseRoot");
231
232         push(@implContent, <<END);
233     if (Node* owner = impl->${methodName}())
234         return V8GCController::opaqueRootForGC(owner);
235 END
236     }
237
238     push(@implContent, <<END);
239     return object;
240 }
241
242 END
243 }
244
245 sub GetSVGPropertyTypes
246 {
247     my $implType = shift;
248
249     my $svgPropertyType;
250     my $svgListPropertyType;
251     my $svgNativeType;
252
253     return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $implType =~ /SVG/;
254
255     $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implType);
256     return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $svgNativeType;
257
258     # Append space to avoid compilation errors when using  PassRefPtr<$svgNativeType>
259     $svgNativeType = "$svgNativeType ";
260
261     my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implType);
262     if ($svgNativeType =~ /SVGPropertyTearOff/) {
263         $svgPropertyType = $svgWrappedNativeType;
264         AddToImplIncludes("SVGAnimatedPropertyTearOff.h");
265     } elsif ($svgNativeType =~ /SVGListPropertyTearOff/ or $svgNativeType =~ /SVGStaticListPropertyTearOff/) {
266         $svgListPropertyType = $svgWrappedNativeType;
267         $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;
268         $headerIncludes{"SVGStaticListPropertyTearOff.h"} = 1;
269     } elsif ($svgNativeType =~ /SVGTransformListPropertyTearOff/) {
270         $svgListPropertyType = $svgWrappedNativeType;
271         $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;
272         $headerIncludes{"SVGTransformListPropertyTearOff.h"} = 1;
273     } elsif ($svgNativeType =~ /SVGPathSegListPropertyTearOff/) {
274         $svgListPropertyType = $svgWrappedNativeType;
275         $headerIncludes{"SVGPathSegListPropertyTearOff.h"} = 1;
276     }
277
278     if ($svgPropertyType) {
279         $svgPropertyType = "SVGPoint" if $svgPropertyType eq "FloatPoint";
280     }
281
282     return ($svgPropertyType, $svgListPropertyType, $svgNativeType);
283 }
284
285 sub GenerateHeader
286 {
287     my $object = shift;
288     my $dataNode = shift;
289
290     my $interfaceName = $dataNode->name;
291     my $className = "V8$interfaceName";
292
293     # Copy contents of parent classes except the first parent.
294     $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@allParents, 1);
295     $codeGenerator->LinkOverloadedFunctions($dataNode);
296
297     # Ensure the IsDOMNodeType function is in sync.
298     die("IsDOMNodeType is out of date with respect to $interfaceName") if IsDOMNodeType($interfaceName) != IsNodeSubType($dataNode);
299
300     my $hasDependentLifetime = $dataNode->extendedAttributes->{"V8DependentLifetime"} || $dataNode->extendedAttributes->{"ActiveDOMObject"}
301          || GetGenerateIsReachable($dataNode) || $className =~ /SVG/;
302     if (!$hasDependentLifetime) {
303         foreach (@{$dataNode->parents}) {
304             my $parent = $codeGenerator->StripModule($_);
305             $headerIncludes{"V8${parent}.h"} = 1;
306         }
307     }
308
309     # - Add default header template
310     push(@headerContent, GenerateHeaderContentHeader($dataNode));
311
312     $headerIncludes{"wtf/text/StringHash.h"} = 1;
313     $headerIncludes{"WrapperTypeInfo.h"} = 1;
314     $headerIncludes{"V8Binding.h"} = 1;
315     $headerIncludes{"V8DOMWrapper.h"} = 1;
316     $headerIncludes{"wtf/HashMap.h"} = 1;
317     $headerIncludes{"v8.h"} = 1;
318
319     my $headerClassInclude = GetHeaderClassInclude($interfaceName);
320     $headerIncludes{$headerClassInclude} = 1 if $headerClassInclude ne "";
321
322     my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($interfaceName);
323
324     foreach my $headerInclude (sort keys(%headerIncludes)) {
325         if ($headerInclude =~ /wtf|v8\.h/) {
326             push(@headerContent, "#include \<${headerInclude}\>\n");
327         } else {
328             push(@headerContent, "#include \"${headerInclude}\"\n");
329         }
330     }
331
332     push(@headerContent, "\nnamespace WebCore {\n");
333     push(@headerContent, "\ntemplate<typename PropertyType> class SVGPropertyTearOff;\n") if $svgPropertyType;
334     if ($svgNativeType) {
335         if ($svgNativeType =~ /SVGStaticListPropertyTearOff/) {
336             push(@headerContent, "\ntemplate<typename PropertyType> class SVGStaticListPropertyTearOff;\n");
337         } else {
338             push(@headerContent, "\ntemplate<typename PropertyType> class SVGListPropertyTearOff;\n");
339         }
340     }
341
342     push(@headerContent, "\n");
343     push(@headerContent, "class FloatRect;\n") if $svgPropertyType && $svgPropertyType eq "FloatRect";
344     push(@headerContent, "class Dictionary;\n") if $codeGenerator->IsConstructorTemplate($dataNode, "Event");
345
346     my $nativeType = GetNativeTypeForConversions($dataNode);
347     if ($dataNode->extendedAttributes->{"NamedConstructor"}) {
348         push(@headerContent, <<END);
349 class V8${nativeType}Constructor {
350 public:
351     static v8::Persistent<v8::FunctionTemplate> GetTemplate();
352     static WrapperTypeInfo info;
353 };
354
355 END
356     }
357
358     push(@headerContent, "class $className {\n");
359     push(@headerContent, "public:\n");
360
361     push(@headerContent, "    static const bool hasDependentLifetime = ");
362     if ($hasDependentLifetime) {
363         push(@headerContent, "true;\n");
364     } elsif (@{$dataNode->parents}) {
365         # Even if this type doesn't have the V8DependentLifetime attribute its parents may.
366         # Let the compiler statically determine this for us.
367         my $separator = "";
368         foreach (@{$dataNode->parents}) {
369             my $parent = $codeGenerator->StripModule($_);
370             $headerIncludes{"V8${parent}.h"} = 1;
371             push(@headerContent, "${separator}V8${parent}::hasDependentLifetime");
372             $separator = " || ";
373         }
374         push(@headerContent, ";\n");
375     } else {
376         push(@headerContent, "false;\n");
377     }
378
379     push(@headerContent, <<END);
380     static bool HasInstance(v8::Handle<v8::Value>);
381     static v8::Persistent<v8::FunctionTemplate> GetRawTemplate();
382     static v8::Persistent<v8::FunctionTemplate> GetTemplate();
383     static ${nativeType}* toNative(v8::Handle<v8::Object> object)
384     {
385         return reinterpret_cast<${nativeType}*>(object->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex));
386     }
387     static void derefObject(void*);
388     static WrapperTypeInfo info;
389 END
390
391     if (NeedsCustomOpaqueRootForGC($dataNode)) {
392         push(@headerContent, "    static void* opaqueRootForGC(void*, v8::Persistent<v8::Object>);\n");
393     }
394
395     if ($dataNode->extendedAttributes->{"ActiveDOMObject"}) {
396         push(@headerContent, "    static ActiveDOMObject* toActiveDOMObject(v8::Handle<v8::Object>);\n");
397     }
398
399     if ($interfaceName eq "DOMWindow") {
400         push(@headerContent, <<END);
401     static v8::Persistent<v8::ObjectTemplate> GetShadowObjectTemplate();
402 END
403     }
404
405     if ($interfaceName eq "HTMLDocument") {
406       push(@headerContent, <<END);
407     static v8::Local<v8::Object> wrapInShadowObject(v8::Local<v8::Object> wrapper, Node* impl);
408     static v8::Handle<v8::Value> getNamedProperty(HTMLDocument* htmlDocument, const AtomicString& key, v8::Handle<v8::Object> creationContext, v8::Isolate*);
409 END
410     }
411
412     my @enabledPerContextFunctions;
413     foreach my $function (@{$dataNode->functions}) {
414         my $name = $function->signature->name;
415         my $attrExt = $function->signature->extendedAttributes;
416
417         if (($attrExt->{"Custom"} || $attrExt->{"V8Custom"}) && !$attrExt->{"ImplementedBy"} && $function->{overloadIndex} == 1) {
418             my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
419             push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
420             push(@headerContent, <<END);
421     static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments&);
422 END
423             push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString;
424         }
425         if ($attrExt->{"V8EnabledPerContext"}) {
426             push(@enabledPerContextFunctions, $function);
427         }
428     }
429
430     if (IsConstructable($dataNode)) {
431         push(@headerContent, <<END);
432     static v8::Handle<v8::Value> constructorCallback(const v8::Arguments&);
433 END
434     }
435
436     my @enabledPerContextAttributes;
437     foreach my $attribute (@{$dataNode->attributes}) {
438         my $name = $attribute->signature->name;
439         my $attrExt = $attribute->signature->extendedAttributes;
440         my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
441         if (($attrExt->{"V8CustomGetter"} || $attrExt->{"CustomGetter"} ||
442              $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) &&
443             !$attrExt->{"ImplementedBy"}) {
444             push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
445             push(@headerContent, <<END);
446     static v8::Handle<v8::Value> ${name}AccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo&);
447 END
448             push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString;
449         }
450         if (($attrExt->{"V8CustomSetter"} || $attrExt->{"CustomSetter"} ||
451              $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) &&
452             !$attrExt->{"ImplementedBy"}) {
453             push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
454             push(@headerContent, <<END);
455     static void ${name}AccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value>, const v8::AccessorInfo&);
456 END
457             push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString;
458         }
459         if ($attrExt->{"V8EnabledPerContext"}) {
460             push(@enabledPerContextAttributes, $attribute);
461         }
462     }
463
464     GenerateHeaderNamedAndIndexedPropertyAccessors($dataNode);
465     GenerateHeaderCustomCall($dataNode);
466     GenerateHeaderCustomInternalFieldIndices($dataNode);
467
468     if ($dataNode->extendedAttributes->{"CheckSecurity"}) {
469         push(@headerContent, <<END);
470     static bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType, v8::Local<v8::Value> data);
471     static bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType, v8::Local<v8::Value> data);
472 END
473     }
474
475     if (@enabledPerContextAttributes) {
476         push(@headerContent, <<END);
477     static void installPerContextProperties(v8::Handle<v8::Object>, ${nativeType}*);
478 END
479     } else {
480         push(@headerContent, <<END);
481     static void installPerContextProperties(v8::Handle<v8::Object>, ${nativeType}*) { }
482 END
483     }
484
485     if (@enabledPerContextFunctions) {
486         push(@headerContent, <<END);
487     static void installPerContextPrototypeProperties(v8::Handle<v8::Object>);
488 END
489     } else {
490         push(@headerContent, <<END);
491     static void installPerContextPrototypeProperties(v8::Handle<v8::Object>) { }
492 END
493     }
494
495     if ($interfaceName eq "HTMLElement") {
496         push(@headerContent, <<END);
497     friend v8::Handle<v8::Object> createV8HTMLWrapper(HTMLElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
498 END
499     } elsif ($interfaceName eq "SVGElement") {
500         push(@headerContent, <<END);
501     friend v8::Handle<v8::Object> createV8SVGWrapper(SVGElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
502 END
503     } elsif ($interfaceName eq "Element") {
504         push(@headerContent, <<END);
505     // This is a performance optimization hack. See V8Element::wrap.
506     friend v8::Handle<v8::Object> wrap(Node*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
507 END
508     }
509
510         push(@headerContent, <<END);
511 private:
512 END
513
514     if (IsConstructable($dataNode) && @{$dataNode->constructors} > 1) {
515         for (my $i = 1; $i <= @{$dataNode->constructors}; $i++) {
516            push(@headerContent, <<END);
517     static v8::Handle<v8::Value> constructor${i}Callback(const v8::Arguments&);
518 END
519         }
520     }
521
522     my $noToV8 = $dataNode->extendedAttributes->{"SuppressToJSObject"};
523     my $noWrap = $dataNode->extendedAttributes->{"V8NoWrapperCache"} || $noToV8;
524     my $createWrapperArgumentType = GetPassRefPtrType($nativeType);
525     if (!$noWrap) {
526         my $createWrapperArgumentType = GetPassRefPtrType($nativeType);
527         push(@headerContent, <<END);
528     friend v8::Handle<v8::Object> wrap(${nativeType}*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
529     static v8::Handle<v8::Object> createWrapper(${createWrapperArgumentType}, v8::Handle<v8::Object> creationContext, v8::Isolate*);
530 END
531     }
532
533     push(@headerContent, <<END);
534 };
535
536 END
537
538     my $customWrap = !!($dataNode->extendedAttributes->{"CustomToJSObject"} or $dataNode->extendedAttributes->{"V8CustomToJSObject"});
539     if ($noToV8) {
540         die "Can't suppress toV8 for subclass\n" if @allParents;
541     } elsif ($noWrap) {
542         die "Must have custom toV8\n" if !$customWrap;
543         push(@headerContent, <<END);
544 class ${nativeType};
545 v8::Handle<v8::Value> toV8(${nativeType}*, v8::Handle<v8::Object> creationContext = v8::Handle<v8::Object>(), v8::Isolate* = 0);
546
547 inline v8::Handle<v8::Value> toV8Fast(${nativeType}* impl, const v8::AccessorInfo& info, Node*)
548 {
549     return toV8(impl, info.Holder(), info.GetIsolate());
550 }
551 END
552     } else {
553
554         my $getCachedWrapper = IsNodeSubType($dataNode) ? "V8DOMWrapper::getCachedWrapper(impl)" : "DOMDataStore::current(isolate)->get(impl)";
555         my $createWrapperCall = $customWrap ? "${className}::wrap" : "${className}::createWrapper";
556
557         if ($customWrap) {
558             push(@headerContent, <<END);
559
560 v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* = 0);
561 END
562         } else {
563             push(@headerContent, <<END);
564
565 inline v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate = 0)
566 {
567     ASSERT(impl);
568     ASSERT($getCachedWrapper.IsEmpty());
569     return $createWrapperCall(impl, creationContext, isolate);
570 }
571 END
572         }
573
574         push(@headerContent, <<END);
575
576 inline v8::Handle<v8::Object> toV8Object(${nativeType}* impl, v8::Handle<v8::Object> creationContext = v8::Handle<v8::Object>(), v8::Isolate* isolate = 0)
577 {
578     if (UNLIKELY(!impl))
579         return v8::Handle<v8::Object>();
580     v8::Handle<v8::Object> wrapper = $getCachedWrapper;
581     if (!wrapper.IsEmpty())
582         return wrapper;
583     return wrap(impl, creationContext, isolate);
584 }
585
586 inline v8::Handle<v8::Value> toV8(${nativeType}* impl, v8::Handle<v8::Object> creationContext = v8::Handle<v8::Object>(), v8::Isolate* isolate = 0)
587 {
588     if (UNLIKELY(!impl))
589         return v8NullWithCheck(isolate);
590     v8::Handle<v8::Value> wrapper = $getCachedWrapper;
591     if (!wrapper.IsEmpty())
592         return wrapper;
593     return wrap(impl, creationContext, isolate);
594 }
595 END
596         if (IsNodeSubType($dataNode)) {
597             push(@headerContent, <<END);
598
599 inline v8::Handle<v8::Value> toV8Fast(${nativeType}* impl, const v8::AccessorInfo& info, Node* holder)
600 {
601     if (UNLIKELY(!impl))
602         return v8::Null(info.GetIsolate());
603     // What we'd really like to check here is whether we're in the main world or
604     // in an isolated world. The fastest way we know how to do that is to check
605     // whether the holder's inline wrapper is the same wrapper we see in the
606     // v8::AccessorInfo.
607     v8::Handle<v8::Object> wrapper = (holder->wrapper() == info.Holder()) ? impl->wrapper() : V8DOMWrapper::getCachedWrapper(impl);
608     if (!wrapper.IsEmpty())
609         return wrapper;
610     return wrap(impl, info.Holder(), info.GetIsolate());
611 }
612 END
613         }
614     }
615
616     push(@headerContent, <<END);
617
618 inline v8::Handle<v8::Value> toV8(PassRefPtr< ${nativeType} > impl, v8::Handle<v8::Object> creationContext = v8::Handle<v8::Object>(), v8::Isolate* isolate = 0)
619 {
620     return toV8(impl.get(), creationContext, isolate);
621 }
622 END
623
624     if ($codeGenerator->IsConstructorTemplate($dataNode, "Event")) {
625         push(@headerContent, "\nbool fill${interfaceName}Init(${interfaceName}Init&, const Dictionary&);\n");
626     }
627
628     push(@headerContent, "\n}\n\n");
629     push(@headerContent, "#endif // $className" . "_h\n");
630
631     my $conditionalString = $codeGenerator->GenerateConditionalString($dataNode);
632     push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;
633 }
634
635 sub GetInternalFields
636 {
637     my $dataNode = shift;
638     my $name = $dataNode->name;
639
640     my @customInternalFields = ();
641     # We can't ask whether a parent type has a given extendedAttribute,
642     # so special-case AbstractWorker and WorkerContext to include all sub-types.
643     # Event listeners on DOM nodes are explicitly supported in the GC controller.
644     # FIXME: Simplify this when all EventTargets are subtypes of EventTarget.
645     if (!IsNodeSubType($dataNode)
646         && ($dataNode->extendedAttributes->{"EventTarget"}
647             || $dataNode->extendedAttributes->{"IsWorkerContext"}
648             || IsSubType($dataNode, "AbstractWorker")
649             || IsSubType($dataNode, "EventTarget"))) {
650         push(@customInternalFields, "eventListenerCacheIndex");
651     }
652
653     return @customInternalFields;
654 }
655
656 sub GetHeaderClassInclude
657 {
658     my $className = shift;
659     if ($className =~ /SVGPathSeg/) {
660         $className =~ s/Abs|Rel//;
661     }
662     return "wtf/${className}.h" if $codeGenerator->IsTypedArrayType($className);
663     return "" if ($codeGenerator->SkipIncludeHeader($className));
664     return "${className}.h";
665 }
666
667 sub GenerateHeaderCustomInternalFieldIndices
668 {
669     my $dataNode = shift;
670     my @customInternalFields = GetInternalFields($dataNode);
671     my $customFieldCounter = 0;
672     foreach my $customInternalField (@customInternalFields) {
673         push(@headerContent, <<END);
674     static const int ${customInternalField} = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
675 END
676         $customFieldCounter++;
677     }
678     push(@headerContent, <<END);
679     static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
680 END
681 }
682
683 my %indexerSpecialCases = (
684     "Storage" => 1,
685     "HTMLAppletElement" => 1,
686     "HTMLEmbedElement" => 1,
687     "HTMLObjectElement" => 1
688 );
689
690 sub GenerateHeaderNamedAndIndexedPropertyAccessors
691 {
692     my $dataNode = shift;
693     my $interfaceName = $dataNode->name;
694     my $hasCustomIndexedGetter = $dataNode->extendedAttributes->{"IndexedGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
695     my $hasCustomIndexedSetter = $dataNode->extendedAttributes->{"CustomIndexedSetter"} && !$dataNode->extendedAttributes->{"NumericIndexedGetter"};
696     my $hasCustomNamedGetter = $dataNode->extendedAttributes->{"NamedGetter"} || $dataNode->extendedAttributes->{"CustomNamedGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
697     my $hasCustomNamedSetter = $dataNode->extendedAttributes->{"CustomNamedSetter"};
698     my $hasCustomDeleters = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
699     my $hasCustomEnumerator = $dataNode->extendedAttributes->{"CustomEnumerateProperty"};
700     if ($interfaceName eq "HTMLOptionsCollection") {
701         $interfaceName = "HTMLCollection";
702         $hasCustomIndexedGetter = 1;
703         $hasCustomNamedGetter = 1;
704     }
705     if ($interfaceName eq "DOMWindow") {
706         $hasCustomDeleters = 0;
707         $hasCustomEnumerator = 0;
708     }
709     if ($interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") {
710         $hasCustomNamedGetter = 1;
711     }
712     if ($interfaceName eq "HTMLDocument") {
713         $hasCustomNamedGetter = 0;
714         $hasCustomIndexedGetter = 0;
715     }
716     my $isIndexerSpecialCase = exists $indexerSpecialCases{$interfaceName};
717
718     if ($hasCustomIndexedGetter || $isIndexerSpecialCase) {
719         push(@headerContent, <<END);
720     static v8::Handle<v8::Value> indexedPropertyGetter(uint32_t, const v8::AccessorInfo&);
721 END
722     }
723
724     if ($isIndexerSpecialCase || $hasCustomIndexedSetter) {
725         push(@headerContent, <<END);
726     static v8::Handle<v8::Value> indexedPropertySetter(uint32_t, v8::Local<v8::Value>, const v8::AccessorInfo&);
727 END
728     }
729     if ($hasCustomDeleters) {
730         push(@headerContent, <<END);
731     static v8::Handle<v8::Boolean> indexedPropertyDeleter(uint32_t, const v8::AccessorInfo&);
732 END
733     }
734     if ($hasCustomNamedGetter) {
735         push(@headerContent, <<END);
736     static v8::Handle<v8::Value> namedPropertyGetter(v8::Local<v8::String>, const v8::AccessorInfo&);
737 END
738     }
739     if ($hasCustomNamedSetter) {
740         push(@headerContent, <<END);
741     static v8::Handle<v8::Value> namedPropertySetter(v8::Local<v8::String>, v8::Local<v8::Value>, const v8::AccessorInfo&);
742 END
743     }
744     if ($hasCustomDeleters) {
745         push(@headerContent, <<END);
746     static v8::Handle<v8::Boolean> namedPropertyDeleter(v8::Local<v8::String>, const v8::AccessorInfo&);
747 END
748     }
749     if ($hasCustomEnumerator) {
750         push(@headerContent, <<END);
751     static v8::Handle<v8::Array> namedPropertyEnumerator(const v8::AccessorInfo&);
752     static v8::Handle<v8::Integer> namedPropertyQuery(v8::Local<v8::String>, const v8::AccessorInfo&);
753 END
754     }
755 }
756
757 sub GenerateHeaderCustomCall
758 {
759     my $dataNode = shift;
760
761     if ($dataNode->extendedAttributes->{"CustomCall"}) {
762         push(@headerContent, "    static v8::Handle<v8::Value> callAsFunctionCallback(const v8::Arguments&);\n");
763     }
764     if ($dataNode->name eq "Event") {
765         push(@headerContent, "    static v8::Handle<v8::Value> dataTransferAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo&);\n");
766         push(@headerContent, "    static void valueAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value>, const v8::AccessorInfo&);\n");
767     }
768     if ($dataNode->name eq "Location") {
769         push(@headerContent, "    static v8::Handle<v8::Value> assignAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo&);\n");
770         push(@headerContent, "    static v8::Handle<v8::Value> reloadAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo&);\n");
771         push(@headerContent, "    static v8::Handle<v8::Value> replaceAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo&);\n");
772     }
773 }
774
775 sub IsSubType
776 {
777     my $dataNode = shift;
778     my $parentType = shift;
779     return 1 if ($dataNode->name eq $parentType);
780     foreach (@allParents) {
781         my $parent = $codeGenerator->StripModule($_);
782         return 1 if $parent eq $parentType;
783     }
784     return 0;
785 }
786
787 sub IsNodeSubType
788 {
789     my $dataNode = shift;
790     return IsSubType($dataNode, "Node");
791 }
792
793 sub IsVisibleAcrossOrigins
794 {
795     my $dataNode = shift;
796     return $dataNode->extendedAttributes->{"CheckSecurity"} && !($dataNode->name eq "DOMWindow");
797 }
798
799 sub IsConstructable
800 {
801     my $dataNode = shift;
802
803     return $dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"V8CustomConstructor"} || $dataNode->extendedAttributes->{"Constructor"} || $dataNode->extendedAttributes->{"ConstructorTemplate"};
804 }
805
806 sub IsReadonly
807 {
808     my $attribute = shift;
809     my $attrExt = $attribute->signature->extendedAttributes;
810     return ($attribute->type =~ /readonly/ || $attrExt->{"V8ReadOnly"}) && !$attrExt->{"Replaceable"};
811 }
812
813 sub GenerateDomainSafeFunctionGetter
814 {
815     my $function = shift;
816     my $interfaceName = shift;
817
818     my $className = "V8" . $interfaceName;
819     my $funcName = $function->signature->name;
820
821     my $signature = "v8::Signature::New(" . $className . "::GetRawTemplate())";
822     if ($function->signature->extendedAttributes->{"V8DoNotCheckSignature"}) {
823         $signature = "v8::Local<v8::Signature>()";
824     }
825
826     my $newTemplateString = GenerateNewFunctionTemplate($function, $interfaceName, $signature);
827
828     AddToImplIncludes("Frame.h");
829     push(@implContentDecls, <<END);
830 static v8::Handle<v8::Value> ${funcName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
831 {
832     INC_STATS(\"DOM.$interfaceName.$funcName._get\");
833     static v8::Persistent<v8::FunctionTemplate> privateTemplate = v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
834     v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(${className}::GetTemplate(), info.This());
835     if (holder.IsEmpty()) {
836         // can only reach here by 'object.__proto__.func', and it should passed
837         // domain security check already
838         return privateTemplate->GetFunction();
839     }
840     ${interfaceName}* imp = ${className}::toNative(holder);
841     if (!BindingSecurity::shouldAllowAccessToFrame(BindingState::instance(), imp->frame(), DoNotReportSecurityError)) {
842         static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
843         return sharedTemplate->GetFunction();
844     }
845
846     v8::Local<v8::Value> hiddenValue = info.This()->GetHiddenValue(name);
847     if (!hiddenValue.IsEmpty())
848         return hiddenValue;
849
850     return privateTemplate->GetFunction();
851 }
852
853 END
854 }
855
856 sub GenerateDomainSafeFunctionSetter
857 {
858     my $interfaceName = shift;
859     my $className = "V8" . $interfaceName;
860
861     push(@implContentDecls, <<END);
862 static void ${interfaceName}DomainSafeFunctionSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
863 {
864     INC_STATS("DOM.$interfaceName._set");
865     v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(${className}::GetTemplate(), info.This());
866     if (holder.IsEmpty())
867         return;
868     ${interfaceName}* imp = ${className}::toNative(holder);
869     if (!BindingSecurity::shouldAllowAccessToFrame(BindingState::instance(), imp->frame()))
870         return;
871
872     info.This()->SetHiddenValue(name, value);
873 }
874
875 END
876 }
877
878 sub GenerateConstructorGetter
879 {
880     my $dataNode = shift;
881     my $interfaceName = $dataNode->name;
882
883     push(@implContentDecls, <<END);
884 static v8::Handle<v8::Value> ${interfaceName}ConstructorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
885 {
886     INC_STATS(\"DOM.$interfaceName.constructors._get\");
887     v8::Handle<v8::Value> data = info.Data();
888     ASSERT(data->IsExternal());
889     V8PerContextData* perContextData = V8PerContextData::from(info.Holder()->CreationContext());
890     if (!perContextData)
891         return v8Undefined();
892     return perContextData->constructorForType(WrapperTypeInfo::unwrap(data));
893 }
894 END
895 }
896
897 sub GenerateFeatureObservation
898 {
899     my $measureAs = shift;
900
901     if ($measureAs) {
902         AddToImplIncludes("FeatureObserver.h");
903         return "    FeatureObserver::observe(activeDOMWindow(BindingState::instance()), FeatureObserver::${measureAs});\n";
904     }
905
906     return "";
907 }
908
909 sub GenerateNormalAttrGetter
910 {
911     my $attribute = shift;
912     my $dataNode = shift;
913
914     my $interfaceName = $dataNode->name;
915     my $attrExt = $attribute->signature->extendedAttributes;
916     my $attrName = $attribute->signature->name;
917     my $attrType = GetTypeFromSignature($attribute->signature);
918     $codeGenerator->AssertNotSequenceType($attrType);
919     my $nativeType = GetNativeTypeFromSignature($attribute->signature, -1);
920
921     my $getterStringUsesImp = $interfaceName ne "SVGNumber";
922     my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($interfaceName);
923
924     # Getter
925     my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
926     push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
927
928     push(@implContentDecls, <<END);
929 static v8::Handle<v8::Value> ${attrName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
930 {
931     INC_STATS("DOM.$interfaceName.$attrName._get");
932 END
933     push(@implContentDecls, GenerateFeatureObservation($attrExt->{"V8MeasureAs"}));
934
935     if ($svgNativeType) {
936         my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($interfaceName);
937         if ($svgWrappedNativeType =~ /List/) {
938             push(@implContentDecls, <<END);
939     $svgNativeType* imp = V8${interfaceName}::toNative(info.Holder());
940 END
941         } else {
942             push(@implContentDecls, <<END);
943     $svgNativeType* wrapper = V8${interfaceName}::toNative(info.Holder());
944     $svgWrappedNativeType& impInstance = wrapper->propertyReference();
945 END
946             if ($getterStringUsesImp) {
947                 push(@implContentDecls, <<END);
948     $svgWrappedNativeType* imp = &impInstance;
949 END
950             }
951         }
952     } elsif ($attrExt->{"V8OnProto"} || $attrExt->{"V8Unforgeable"}) {
953         if ($interfaceName eq "DOMWindow") {
954             push(@implContentDecls, <<END);
955     v8::Handle<v8::Object> holder = info.Holder();
956 END
957         } else {
958             # perform lookup first
959             push(@implContentDecls, <<END);
960     v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8${interfaceName}::GetTemplate(), info.This());
961     if (holder.IsEmpty())
962         return v8Undefined();
963 END
964         }
965         push(@implContentDecls, <<END);
966     ${interfaceName}* imp = V8${interfaceName}::toNative(holder);
967 END
968     } else {
969         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
970         my $url = $attribute->signature->extendedAttributes->{"URL"};
971         if ($getterStringUsesImp && $reflect && !$url && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
972             # Generate super-compact call for regular attribute getter:
973             my $contentAttributeName = $reflect eq "VALUE_IS_MISSING" ? lc $attrName : $reflect;
974             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
975             AddToImplIncludes("${namespace}.h");
976             push(@implContentDecls, "    Element* imp = V8Element::toNative(info.Holder());\n");
977             push(@implContentDecls, "    return v8ExternalString(imp->getAttribute(${namespace}::${contentAttributeName}Attr), info.GetIsolate());\n");
978             push(@implContentDecls, "}\n\n");
979             push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
980             return;
981             # Skip the rest of the function!
982         }
983         if ($attribute->signature->type eq "SerializedScriptValue" && $attrExt->{"CachedAttribute"}) {
984             push(@implContentDecls, <<END);
985     v8::Handle<v8::String> propertyName = v8::String::NewSymbol("${attrName}");
986     v8::Handle<v8::Value> value = info.Holder()->GetHiddenValue(propertyName);
987     if (!value.IsEmpty())
988         return value;
989 END
990         }
991         if (!$attribute->isStatic) {
992             push(@implContentDecls, <<END);
993     ${interfaceName}* imp = V8${interfaceName}::toNative(info.Holder());
994 END
995         }
996     }
997
998     # Generate security checks if necessary
999     if ($attribute->signature->extendedAttributes->{"CheckSecurityForNode"}) {
1000         push(@implContentDecls, "    if (!BindingSecurity::shouldAllowAccessToNode(BindingState::instance(), imp->" . $attribute->signature->name . "()))\n        return v8::Handle<v8::Value>(v8::Null(info.GetIsolate()));\n\n");
1001     }
1002
1003     my $useExceptions = 1 if @{$attribute->getterExceptions};
1004     if ($useExceptions) {
1005         AddToImplIncludes("ExceptionCode.h");
1006         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
1007     }
1008
1009     my $returnType = GetTypeFromSignature($attribute->signature);
1010     my $getterString;
1011
1012     if ($getterStringUsesImp) {
1013         my ($functionName, @arguments) = $codeGenerator->GetterExpression(\%implIncludes, $interfaceName, $attribute);
1014         push(@arguments, "ec") if $useExceptions;
1015         if ($attribute->signature->extendedAttributes->{"ImplementedBy"}) {
1016             my $implementedBy = $attribute->signature->extendedAttributes->{"ImplementedBy"};
1017             AddToImplIncludes("${implementedBy}.h");
1018             unshift(@arguments, "imp") if !$attribute->isStatic;
1019             $functionName = "${implementedBy}::${functionName}";
1020         } elsif ($attribute->isStatic) {
1021             $functionName = "${interfaceName}::${functionName}";
1022         } else {
1023             $functionName = "imp->${functionName}";
1024         }
1025         unshift(@arguments, GenerateCallWith($attribute->signature->extendedAttributes->{"CallWith"}, \@implContentDecls, "    ", 0, 0));
1026         $getterString = "${functionName}(" . join(", ", @arguments) . ")";
1027     } else {
1028         $getterString = "impInstance";
1029     }
1030
1031     my $result;
1032     my $wrapper;
1033
1034     if ($attribute->signature->type eq "EventListener" && $dataNode->name eq "DOMWindow") {
1035         push(@implContentDecls, "    if (!imp->document())\n");
1036         push(@implContentDecls, "        return v8Undefined();\n");
1037     }
1038
1039     if ($useExceptions) {
1040         if ($nativeType =~ /^V8Parameter/) {
1041             push(@implContentDecls, "    " . ConvertToV8Parameter($attribute->signature, $nativeType, "v", $getterString) . ";\n");
1042         } else {
1043             push(@implContentDecls, "    $nativeType v = $getterString;\n");
1044         }
1045         push(@implContentDecls, "    if (UNLIKELY(ec))\n");
1046         push(@implContentDecls, "        return setDOMException(ec, info.GetIsolate());\n");
1047
1048         if ($codeGenerator->ExtendedAttributeContains($attribute->signature->extendedAttributes->{"CallWith"}, "ScriptState")) {
1049             push(@implContentDecls, "    if (state.hadException())\n");
1050             push(@implContentDecls, "        return throwError(state.exception(), info.GetIsolate());\n");
1051         }
1052
1053         $result = "v";
1054         $result .= ".release()" if (IsRefPtrType($returnType));
1055     } else {
1056         # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
1057         $result = $getterString;
1058         # Fix amigious conversion problem, by casting to the base type first ($getterString returns a type that inherits from SVGAnimatedEnumeration, not the base class directly).
1059         $result = "static_pointer_cast<SVGAnimatedEnumeration>($result)" if $returnType eq "SVGAnimatedEnumeration";
1060     }
1061  
1062     # Special case for readonly or Replaceable attributes (with a few exceptions). This attempts to ensure that JS wrappers don't get
1063     # garbage-collected prematurely when their lifetime is strongly tied to their owner. We accomplish this by inserting a reference to
1064     # the newly created wrapper into an internal field of the holder object.
1065     if (!IsNodeSubType($dataNode) && $attrName ne "self" && IsWrapperType($returnType) && (IsReadonly($attribute) || $attribute->signature->extendedAttributes->{"Replaceable"} || $attrName eq "location")
1066         && $returnType ne "EventTarget" && $returnType ne "SerializedScriptValue" && $returnType ne "DOMWindow" 
1067         && $returnType ne "MessagePortArray"
1068         && $returnType !~ /SVG/ && $returnType !~ /HTML/ && !IsDOMNodeType($returnType)) {
1069
1070         my $arrayType = $codeGenerator->GetArrayType($returnType);
1071         if ($arrayType) {
1072             if (!$codeGenerator->SkipIncludeHeader($arrayType)) {
1073                 AddToImplIncludes("V8$arrayType.h");
1074                 AddToImplIncludes("$arrayType.h");
1075             }
1076             push(@implContentDecls, "    return v8Array(${getterString}, info.GetIsolate());\n");
1077             push(@implContentDecls, "}\n\n");
1078             return;
1079         }
1080
1081         AddIncludesForType($returnType);
1082         # Check for a wrapper in the wrapper cache. If there is one, we know that a hidden reference has already
1083         # been created. If we don't find a wrapper, we create both a wrapper and a hidden reference.
1084         push(@implContentDecls, "    RefPtr<$returnType> result = ${getterString};\n");
1085         push(@implContentDecls, "    v8::Handle<v8::Value> wrapper = result.get() ? v8::Handle<v8::Value>(DOMDataStore::current(info.GetIsolate())->get(result.get())) : v8Undefined();\n");
1086         push(@implContentDecls, "    if (wrapper.IsEmpty()) {\n");
1087         push(@implContentDecls, "        wrapper = toV8(result.get(), info.Holder(), info.GetIsolate());\n"); # FIXME: Could use wrap here since the wrapper is empty.
1088         push(@implContentDecls, "        if (!wrapper.IsEmpty())\n");
1089         push(@implContentDecls, "            V8DOMWrapper::setNamedHiddenReference(info.Holder(), \"${attrName}\", wrapper);\n");
1090         push(@implContentDecls, "    }\n");
1091         push(@implContentDecls, "    return wrapper;\n");
1092         push(@implContentDecls, "}\n\n");
1093         push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1094         return;
1095     }
1096
1097     if (($codeGenerator->IsSVGAnimatedType($interfaceName) or $interfaceName eq "SVGViewSpec") and $codeGenerator->IsSVGTypeNeedingTearOff($attrType)) {
1098         AddToImplIncludes("V8$attrType.h");
1099         my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($attrType);
1100         # Convert from abstract SVGProperty to real type, so the right toJS() method can be invoked.
1101         push(@implContentDecls, "    return toV8(static_cast<$svgNativeType*>($result), info.Holder(), info.GetIsolate());\n");
1102     } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($attrType) and not $interfaceName =~ /List$/) {
1103         AddToImplIncludes("V8$attrType.h");
1104         AddToImplIncludes("SVGPropertyTearOff.h");
1105         my $tearOffType = $codeGenerator->GetSVGTypeNeedingTearOff($attrType);
1106         if ($codeGenerator->IsSVGTypeWithWritablePropertiesNeedingTearOff($attrType) and not defined $attribute->signature->extendedAttributes->{"Immutable"}) {
1107             my $getter = $result;
1108             $getter =~ s/imp->//;
1109             $getter =~ s/\(\)//;
1110
1111             my $updateMethod = "&${interfaceName}::update" . $codeGenerator->WK_ucfirst($getter);
1112
1113             my $selfIsTearOffType = $codeGenerator->IsSVGTypeNeedingTearOff($interfaceName);
1114             if ($selfIsTearOffType) {
1115                 AddToImplIncludes("SVGStaticPropertyWithParentTearOff.h");
1116                 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyWithParentTearOff<$interfaceName, /;
1117
1118                 if ($result =~ /matrix/ and $interfaceName eq "SVGTransform") {
1119                     # SVGTransform offers a matrix() method for internal usage that returns an AffineTransform
1120                     # and a svgMatrix() method returning a SVGMatrix, used for the bindings.
1121                     $result =~ s/matrix/svgMatrix/;
1122                 }
1123
1124                 push(@implContentDecls, "    return toV8(WTF::getPtr(${tearOffType}::create(wrapper, $result, $updateMethod)), info.Holder(), info.GetIsolate());\n");
1125             } else {
1126                 AddToImplIncludes("SVGStaticPropertyTearOff.h");
1127                 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyTearOff<$interfaceName, /;
1128
1129                 push(@implContentDecls, "    return toV8(WTF::getPtr(${tearOffType}::create(imp, $result, $updateMethod)), info.Holder(), info.GetIsolate());\n");
1130             }
1131         } elsif ($tearOffType =~ /SVGStaticListPropertyTearOff/) {
1132             push(@implContentDecls, "    return toV8(WTF::getPtr(${tearOffType}::create(imp, $result)), info.Holder(), info.GetIsolate());\n");
1133         } elsif ($tearOffType =~ /SVG(Point|PathSeg)List/) {
1134             push(@implContentDecls, "    return toV8(WTF::getPtr($result), info.Holder(), info.GetIsolate());\n");
1135         } else {
1136             push(@implContentDecls, "    return toV8(WTF::getPtr(${tearOffType}::create($result)), info.Holder(), info.GetIsolate());\n");
1137         }
1138     } elsif ($attribute->signature->type eq "MessagePortArray") {
1139         AddToImplIncludes("MessagePort.h");
1140         AddToImplIncludes("V8MessagePort.h");
1141         my $getterFunc = $codeGenerator->WK_lcfirst($attribute->signature->name);
1142         push(@implContentDecls, <<END);
1143     MessagePortArray* ports = imp->${getterFunc}();
1144     if (!ports)
1145         return v8::Array::New(0);
1146     MessagePortArray portsCopy(*ports);
1147     v8::Local<v8::Array> portArray = v8::Array::New(portsCopy.size());
1148     for (size_t i = 0; i < portsCopy.size(); ++i)
1149         portArray->Set(v8Integer(i, info.GetIsolate()), toV8(portsCopy[i].get(), info.Holder(), info.GetIsolate()));
1150     return portArray;
1151 END
1152     } elsif ($attribute->signature->type eq "SerializedScriptValue" && $attrExt->{"CachedAttribute"}) {
1153         my $getterFunc = $codeGenerator->WK_lcfirst($attribute->signature->name);
1154         push(@implContentDecls, <<END);
1155     SerializedScriptValue* serialized = imp->${getterFunc}();
1156     value = serialized ? serialized->deserialize() : v8::Handle<v8::Value>(v8::Null(info.GetIsolate()));
1157     info.Holder()->SetHiddenValue(propertyName, value);
1158     return value;
1159 END
1160     } elsif (IsDOMNodeType($interfaceName) && IsDOMNodeType($attrType)) {
1161         AddToImplIncludes($attrType.".h");
1162         push(@implContentDecls, "    return toV8Fast($result, info, imp);\n");
1163     } else {
1164         push(@implContentDecls, "    " . ReturnNativeToJSValue($attribute->signature, $result, "info.Holder()", "info.GetIsolate()").";\n");
1165     }
1166
1167     push(@implContentDecls, "}\n\n");  # end of getter
1168     push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1169 }
1170
1171 sub GenerateReplaceableAttrSetter
1172 {
1173     my $dataNode = shift;
1174     my $interfaceName = $dataNode->name;
1175
1176     push(@implContentDecls, <<END);
1177 static void ${interfaceName}ReplaceableAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
1178 {
1179     INC_STATS("DOM.$interfaceName.replaceable._set");
1180 END
1181     push(@implContentDecls, GenerateFeatureObservation($dataNode->extendedAttributes->{"V8MeasureAs"}));
1182
1183     if ($interfaceName eq "DOMWindow" || $dataNode->extendedAttributes->{"CheckSecurity"}) {
1184         AddToImplIncludes("Frame.h");
1185         push(@implContentDecls, <<END);
1186     ${interfaceName}* imp = V8${interfaceName}::toNative(info.Holder());
1187     if (!BindingSecurity::shouldAllowAccessToFrame(BindingState::instance(), imp->frame()))
1188         return;
1189 END
1190     }
1191
1192     push(@implContentDecls, <<END);
1193     info.This()->ForceSet(name, value);
1194 }
1195
1196 END
1197 }
1198
1199 sub GenerateNormalAttrSetter
1200 {
1201     my $attribute = shift;
1202     my $dataNode = shift;
1203
1204     my $interfaceName = $dataNode->name;
1205     my $attrName = $attribute->signature->name;
1206     my $attrExt = $attribute->signature->extendedAttributes;
1207
1208     my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
1209     push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
1210
1211     push(@implContentDecls, "static void ${attrName}AttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)\n{\n");
1212     push(@implContentDecls, "    INC_STATS(\"DOM.$interfaceName.$attrName._set\");\n");
1213     push(@implContentDecls, GenerateFeatureObservation($attribute->signature->extendedAttributes->{"V8MeasureAs"}));
1214
1215     # If the "StrictTypeChecking" extended attribute is present, and the attribute's type is an
1216     # interface type, then if the incoming value does not implement that interface, a TypeError is
1217     # thrown rather than silently passing NULL to the C++ code.
1218     # Per the Web IDL and ECMAScript specifications, incoming values can always be converted to both
1219     # strings and numbers, so do not throw TypeError if the attribute is of these types.
1220     if ($attribute->signature->extendedAttributes->{"StrictTypeChecking"}) {
1221         my $argType = GetTypeFromSignature($attribute->signature);
1222         if (IsWrapperType($argType)) {
1223             push(@implContentDecls, "    if (!isUndefinedOrNull(value) && !V8${argType}::HasInstance(value)) {\n");
1224             push(@implContentDecls, "        throwTypeError(0, info.GetIsolate());\n");
1225             push(@implContentDecls, "        return;\n");
1226             push(@implContentDecls, "    }\n");
1227         }
1228     }
1229
1230     my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($interfaceName);
1231     if ($svgNativeType) {
1232         my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($interfaceName);
1233         if ($svgWrappedNativeType =~ /List$/) {
1234             push(@implContentDecls, <<END);
1235     $svgNativeType* imp = V8${interfaceName}::toNative(info.Holder());
1236 END
1237         } else {
1238             AddToImplIncludes("ExceptionCode.h");
1239             push(@implContentDecls, "    $svgNativeType* wrapper = V8${interfaceName}::toNative(info.Holder());\n");
1240             push(@implContentDecls, "    if (wrapper->isReadOnly()) {\n");
1241             push(@implContentDecls, "        setDOMException(NO_MODIFICATION_ALLOWED_ERR, info.GetIsolate());\n");
1242             push(@implContentDecls, "        return;\n");
1243             push(@implContentDecls, "    }\n");
1244             push(@implContentDecls, "    $svgWrappedNativeType& impInstance = wrapper->propertyReference();\n");
1245             push(@implContentDecls, "    $svgWrappedNativeType* imp = &impInstance;\n");
1246         }
1247     } elsif ($attrExt->{"V8OnProto"}) {
1248         push(@implContentDecls, <<END);
1249     ${interfaceName}* imp = V8${interfaceName}::toNative(info.Holder());
1250 END
1251     } else {
1252         my $attrType = GetTypeFromSignature($attribute->signature);
1253         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
1254         if ($reflect && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
1255             # Generate super-compact call for regular attribute setter:
1256             my $contentAttributeName = $reflect eq "VALUE_IS_MISSING" ? lc $attrName : $reflect;
1257             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
1258             AddToImplIncludes("${namespace}.h");
1259             push(@implContentDecls, "    Element* imp = V8Element::toNative(info.Holder());\n");
1260             push(@implContentDecls, "    AtomicString v = toWebCoreAtomicStringWithNullCheck(value);\n");
1261             push(@implContentDecls, "    imp->setAttribute(${namespace}::${contentAttributeName}Attr, v);\n");
1262             push(@implContentDecls, "}\n\n");
1263             push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1264             return;
1265             # Skip the rest of the function!
1266         }
1267
1268         if (!$attribute->isStatic) {
1269             push(@implContentDecls, <<END);
1270     ${interfaceName}* imp = V8${interfaceName}::toNative(info.Holder());
1271 END
1272         }
1273     }
1274
1275     my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0);
1276     if ($attribute->signature->type eq "EventListener") {
1277         if ($dataNode->name eq "DOMWindow") {
1278             push(@implContentDecls, "    if (!imp->document())\n");
1279             push(@implContentDecls, "        return;\n");
1280         }
1281     } else {
1282         my $value = JSValueToNative($attribute->signature, "value", "info.GetIsolate()");
1283         my $arrayType = $codeGenerator->GetArrayType($nativeType);
1284
1285         if ($nativeType =~ /^V8Parameter/) {
1286             push(@implContentDecls, "    " . ConvertToV8Parameter($attribute->signature, $nativeType, "v", $value, "VOID") . "\n");
1287         } elsif ($arrayType) {
1288             push(@implContentDecls, "    Vector<$arrayType> v = $value;\n");
1289         } else {
1290             push(@implContentDecls, "    $nativeType v = $value;\n");
1291         }
1292     }
1293
1294     my $result = "v";
1295     my $returnType = GetTypeFromSignature($attribute->signature);
1296     if (IsRefPtrType($returnType) && !$codeGenerator->GetArrayType($returnType)) {
1297         $result = "WTF::getPtr(" . $result . ")";
1298     }
1299
1300     my $useExceptions = 1 if @{$attribute->setterExceptions};
1301
1302     if ($useExceptions) {
1303         AddToImplIncludes("ExceptionCode.h");
1304         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
1305     }
1306
1307     if ($interfaceName eq "SVGNumber") {
1308         push(@implContentDecls, "    *imp = $result;\n");
1309     } else {
1310         if ($attribute->signature->type eq "EventListener") {
1311             my $implSetterFunctionName = $codeGenerator->WK_ucfirst($attrName);
1312             AddToImplIncludes("V8AbstractEventListener.h");
1313             if (!IsNodeSubType($dataNode)) {
1314                 push(@implContentDecls, "    transferHiddenDependency(info.Holder(), imp->$attrName(), value, V8${interfaceName}::eventListenerCacheIndex);\n");
1315             }
1316             if ($interfaceName eq "WorkerContext" and $attribute->signature->name eq "onerror") {
1317                 AddToImplIncludes("V8EventListenerList.h");
1318                 AddToImplIncludes("V8WorkerContextErrorHandler.h");
1319                 push(@implContentDecls, "    imp->set$implSetterFunctionName(V8EventListenerList::findOrCreateWrapper<V8WorkerContextErrorHandler>(value, true)");
1320             } elsif ($interfaceName eq "DOMWindow" and $attribute->signature->name eq "onerror") {
1321                 AddToImplIncludes("V8EventListenerList.h");
1322                 AddToImplIncludes("V8WindowErrorHandler.h");
1323                 push(@implContentDecls, "    imp->set$implSetterFunctionName(V8EventListenerList::findOrCreateWrapper<V8WindowErrorHandler>(value, true)");
1324             } else {
1325                 push(@implContentDecls, "    imp->set$implSetterFunctionName(V8DOMWrapper::getEventListener(value, true, ListenerFindOrCreate)");
1326             }
1327             push(@implContentDecls, ", ec") if $useExceptions;
1328             push(@implContentDecls, ");\n");
1329         } else {
1330             my ($functionName, @arguments) = $codeGenerator->SetterExpression(\%implIncludes, $interfaceName, $attribute);
1331             push(@arguments, $result);
1332             push(@arguments, "ec") if $useExceptions;
1333             if ($attribute->signature->extendedAttributes->{"ImplementedBy"}) {
1334                 my $implementedBy = $attribute->signature->extendedAttributes->{"ImplementedBy"};
1335                 AddToImplIncludes("${implementedBy}.h");
1336                 unshift(@arguments, "imp") if !$attribute->isStatic;
1337                 $functionName = "${implementedBy}::${functionName}";
1338             } elsif ($attribute->isStatic) {
1339                 $functionName = "${interfaceName}::${functionName}";
1340             } else {
1341                 $functionName = "imp->${functionName}";
1342             }
1343             unshift(@arguments, GenerateCallWith($attribute->signature->extendedAttributes->{"CallWith"}, \@implContentDecls, "    ", 1, 0));
1344             push(@implContentDecls, "    ${functionName}(" . join(", ", @arguments) . ");\n");
1345         }
1346     }
1347
1348     if ($useExceptions) {
1349         push(@implContentDecls, "    if (UNLIKELY(ec))\n");
1350         push(@implContentDecls, "        setDOMException(ec, info.GetIsolate());\n");
1351     }
1352
1353     if ($codeGenerator->ExtendedAttributeContains($attribute->signature->extendedAttributes->{"CallWith"}, "ScriptState")) {
1354         push(@implContentDecls, "    if (state.hadException())\n");
1355         push(@implContentDecls, "        throwError(state.exception(), info.GetIsolate());\n");
1356     }
1357
1358     if ($svgNativeType) {
1359         if ($useExceptions) {
1360             push(@implContentDecls, "    if (!ec)\n");
1361             push(@implContentDecls, "        wrapper->commitChange();\n");
1362         } else {
1363             push(@implContentDecls, "    wrapper->commitChange();\n");
1364         }
1365     }
1366
1367     if ($attribute->signature->type eq "SerializedScriptValue" && $attribute->signature->extendedAttributes->{"CachedAttribute"}) {
1368         push(@implContentDecls, <<END);
1369     info.Holder()->DeleteHiddenValue(v8::String::NewSymbol("${attrName}")); // Invalidate the cached value.
1370 END
1371     }
1372
1373     push(@implContentDecls, "    return;\n");
1374     push(@implContentDecls, "}\n\n");  # end of setter
1375     push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1376 }
1377
1378 sub GetFunctionTemplateCallbackName
1379 {
1380     my $function = shift;
1381     my $interfaceName = shift;
1382
1383     my $name = $function->signature->name;
1384
1385     if ($function->signature->extendedAttributes->{"Custom"} ||
1386         $function->signature->extendedAttributes->{"V8Custom"}) {
1387         if ($function->signature->extendedAttributes->{"Custom"} &&
1388             $function->signature->extendedAttributes->{"V8Custom"}) {
1389             die "Custom and V8Custom should be mutually exclusive!"
1390         }
1391         return "V8${interfaceName}::${name}Callback";
1392     } else {
1393         return "${interfaceName}V8Internal::${name}Callback";
1394     }
1395 }
1396
1397 sub GenerateNewFunctionTemplate
1398 {
1399     my $function = shift;
1400     my $interfaceName = shift;
1401     my $signature = shift;
1402
1403     my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
1404     return "v8::FunctionTemplate::New($callback, v8Undefined(), $signature)";
1405 }
1406
1407 sub GenerateEventListenerCallback
1408 {
1409     my $interfaceName = shift;
1410     my $requiresHiddenDependency = shift;
1411     my $functionName = shift;
1412     my $lookupType = ($functionName eq "add") ? "OrCreate" : "Only";
1413     my $passRefPtrHandling = ($functionName eq "add") ? "" : ".get()";
1414     my $hiddenDependencyAction = ($functionName eq "add") ? "create" : "remove";
1415  
1416     push(@implContentDecls, <<END);
1417 static v8::Handle<v8::Value> ${functionName}EventListenerCallback(const v8::Arguments& args)
1418 {
1419     INC_STATS("DOM.${interfaceName}.${functionName}EventListener()");
1420     RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(args[1], false, ListenerFind${lookupType});
1421     if (listener) {
1422         V8${interfaceName}::toNative(args.Holder())->${functionName}EventListener(toWebCoreAtomicString(args[0]), listener${passRefPtrHandling}, args[2]->BooleanValue());
1423 END
1424     if ($requiresHiddenDependency) {
1425         push(@implContentDecls, <<END);
1426         ${hiddenDependencyAction}HiddenDependency(args.Holder(), args[1], V8${interfaceName}::eventListenerCacheIndex);
1427 END
1428     }
1429     push(@implContentDecls, <<END);
1430     }
1431     return v8Undefined();
1432 }
1433
1434 END
1435 }
1436
1437 sub GenerateParametersCheckExpression
1438 {
1439     my $numParameters = shift;
1440     my $function = shift;
1441
1442     my @andExpression = ();
1443     push(@andExpression, "args.Length() == $numParameters");
1444     my $parameterIndex = 0;
1445     foreach my $parameter (@{$function->parameters}) {
1446         last if $parameterIndex >= $numParameters;
1447         my $value = "args[$parameterIndex]";
1448         my $type = GetTypeFromSignature($parameter);
1449
1450         # Only DOMString or wrapper types are checked.
1451         # For DOMString with StrictTypeChecking only Null, Undefined and Object
1452         # are accepted for compatibility. Otherwise, no restrictions are made to
1453         # match the non-overloaded behavior.
1454         # FIXME: Implement WebIDL overload resolution algorithm.
1455         if ($codeGenerator->IsStringType($type)) {
1456             if ($parameter->extendedAttributes->{"StrictTypeChecking"}) {
1457                 push(@andExpression, "(${value}->IsNull() || ${value}->IsUndefined() || ${value}->IsString() || ${value}->IsObject())");
1458             }
1459         } elsif ($parameter->extendedAttributes->{"Callback"}) {
1460             # For Callbacks only checks if the value is null or object.
1461             push(@andExpression, "(${value}->IsNull() || ${value}->IsFunction())");
1462         } elsif ($codeGenerator->IsArrayType($type) || $codeGenerator->GetSequenceType($type)) {
1463             # FIXME: Add proper support for T[], T[]?, sequence<T>.
1464             if ($parameter->isNullable) {
1465                 push(@andExpression, "(${value}->IsNull() || ${value}->IsArray())");
1466             } else {
1467                 push(@andExpression, "(${value}->IsArray())");
1468             }
1469         } elsif (IsWrapperType($type)) {
1470             if ($parameter->isNullable) {
1471                 push(@andExpression, "(${value}->IsNull() || V8${type}::HasInstance($value))");
1472             } else {
1473                 push(@andExpression, "(V8${type}::HasInstance($value))");
1474             }
1475         }
1476
1477         $parameterIndex++;
1478     }
1479     my $res = join(" && ", @andExpression);
1480     $res = "($res)" if @andExpression > 1;
1481     return $res;
1482 }
1483
1484 sub GenerateFunctionParametersCheck
1485 {
1486     my $function = shift;
1487
1488     my @orExpression = ();
1489     my $numParameters = 0;
1490     my $hasVariadic = 0;
1491     my $numMandatoryParams = @{$function->parameters};
1492     foreach my $parameter (@{$function->parameters}) {
1493         if ($parameter->extendedAttributes->{"Optional"}) {
1494             push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
1495             $numMandatoryParams--;
1496         }
1497         if ($parameter->isVariadic) {
1498             $hasVariadic = 1;
1499             last;
1500         }
1501         $numParameters++;
1502     }
1503     if (!$hasVariadic) {
1504         push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
1505     }
1506     return ($numMandatoryParams, join(" || ", @orExpression));
1507 }
1508
1509 sub GenerateOverloadedFunctionCallback
1510 {
1511     my $function = shift;
1512     my $dataNode = shift;
1513     my $interfaceName = $dataNode->name;
1514
1515     # Generate code for choosing the correct overload to call. Overloads are
1516     # chosen based on the total number of arguments passed and the type of
1517     # values passed in non-primitive argument slots. When more than a single
1518     # overload is applicable, precedence is given according to the order of
1519     # declaration in the IDL.
1520
1521     my $name = $function->signature->name;
1522     my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
1523     my $leastNumMandatoryParams = 255;
1524     push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
1525     push(@implContentDecls, <<END);
1526 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args)
1527 {
1528     INC_STATS(\"DOM.$interfaceName.$name\");
1529 END
1530     push(@implContentDecls, GenerateFeatureObservation($function->signature->extendedAttributes->{"V8MeasureAs"}));
1531
1532     foreach my $overload (@{$function->{overloads}}) {
1533         my ($numMandatoryParams, $parametersCheck) = GenerateFunctionParametersCheck($overload);
1534         $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams < $leastNumMandatoryParams);
1535         push(@implContentDecls, "    if ($parametersCheck)\n");
1536         push(@implContentDecls, "        return ${name}$overload->{overloadIndex}Callback(args);\n");
1537     }
1538     if ($leastNumMandatoryParams >= 1) {
1539         push(@implContentDecls, "    if (args.Length() < $leastNumMandatoryParams)\n");
1540         push(@implContentDecls, "        return throwNotEnoughArgumentsError(args.GetIsolate());\n");
1541     }
1542     push(@implContentDecls, <<END);
1543     return throwTypeError(0, args.GetIsolate());
1544 END
1545     push(@implContentDecls, "}\n\n");
1546     push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1547 }
1548
1549 sub GenerateFunctionCallback
1550 {
1551     my $function = shift;
1552     my $dataNode = shift;
1553
1554     my $interfaceName = $dataNode->name;
1555     my $name = $function->signature->name;
1556
1557     if (@{$function->{overloads}} > 1) {
1558         # Append a number to an overloaded method's name to make it unique:
1559         $name = $name . $function->{overloadIndex};
1560     }
1561
1562     # Adding and removing event listeners are not standard callback behavior,
1563     # but they are extremely consistent across the various classes that take event listeners,
1564     # so we can generate them as a "special case".
1565     if ($name eq "addEventListener") {
1566         GenerateEventListenerCallback($interfaceName, !IsNodeSubType($dataNode), "add");
1567         return;
1568     } elsif ($name eq "removeEventListener") {
1569         GenerateEventListenerCallback($interfaceName, !IsNodeSubType($dataNode), "remove");
1570         return;
1571     }
1572
1573     my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
1574     push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
1575     push(@implContentDecls, <<END);
1576 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args)
1577 {
1578     INC_STATS(\"DOM.$interfaceName.$name\");
1579 END
1580     push(@implContentDecls, GenerateFeatureObservation($function->signature->extendedAttributes->{"V8MeasureAs"}));
1581
1582     push(@implContentDecls, GenerateArgumentsCountCheck($function, $dataNode));
1583
1584     if ($name eq "set" and $dataNode->extendedAttributes->{"TypedArray"}) {
1585         AddToImplIncludes("V8ArrayBufferViewCustom.h");
1586         push(@implContentDecls, <<END);
1587     return setWebGLArrayHelper<$interfaceName, V8${interfaceName}>(args);
1588 }
1589
1590 END
1591         return;
1592     }
1593
1594     my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($interfaceName);
1595
1596     if ($svgNativeType) {
1597         my $nativeClassName = GetNativeType($interfaceName); 
1598         if ($interfaceName =~ /List$/) {
1599             push(@implContentDecls, "    $nativeClassName imp = V8${interfaceName}::toNative(args.Holder());\n");
1600         } else {
1601             AddToImplIncludes("ExceptionCode.h");
1602             push(@implContentDecls, "    $nativeClassName wrapper = V8${interfaceName}::toNative(args.Holder());\n");
1603             push(@implContentDecls, "    if (wrapper->isReadOnly())\n");
1604             push(@implContentDecls, "        return setDOMException(NO_MODIFICATION_ALLOWED_ERR, args.GetIsolate());\n");
1605             my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($interfaceName);
1606             push(@implContentDecls, "    $svgWrappedNativeType& impInstance = wrapper->propertyReference();\n");
1607             push(@implContentDecls, "    $svgWrappedNativeType* imp = &impInstance;\n");
1608         }
1609     } elsif (!$function->isStatic) {
1610         push(@implContentDecls, <<END);
1611     ${interfaceName}* imp = V8${interfaceName}::toNative(args.Holder());
1612 END
1613     }
1614
1615     # Check domain security if needed
1616     if (($dataNode->extendedAttributes->{"CheckSecurity"}
1617         || $interfaceName eq "DOMWindow")
1618         && !$function->signature->extendedAttributes->{"DoNotCheckSecurity"}) {
1619         # We have not find real use cases yet.
1620         AddToImplIncludes("Frame.h");
1621         push(@implContentDecls, <<END);
1622     if (!BindingSecurity::shouldAllowAccessToFrame(BindingState::instance(), imp->frame()))
1623         return v8Undefined();
1624 END
1625     }
1626
1627     my $raisesExceptions = @{$function->raisesExceptions};
1628     if (!$raisesExceptions) {
1629         foreach my $parameter (@{$function->parameters}) {
1630             if ((!$parameter->extendedAttributes->{"Callback"} and TypeCanFailConversion($parameter)) or $parameter->extendedAttributes->{"IsIndex"}) {
1631                 $raisesExceptions = 1;
1632             }
1633         }
1634     }
1635
1636     if ($raisesExceptions) {
1637         AddToImplIncludes("ExceptionCode.h");
1638         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
1639         push(@implContentDecls, "    {\n");
1640         # The brace here is needed to prevent the ensuing 'goto fail's from jumping past constructors
1641         # of objects (like Strings) declared later, causing compile errors. The block scope ends
1642         # right before the label 'fail:'.
1643     }
1644
1645     if ($function->signature->extendedAttributes->{"CheckSecurityForNode"}) {
1646         push(@implContentDecls, "    if (!BindingSecurity::shouldAllowAccessToNode(BindingState::instance(), imp->" . $function->signature->name . "(ec)))\n");
1647         push(@implContentDecls, "        return v8::Handle<v8::Value>(v8::Null(args.GetIsolate()));\n");
1648 END
1649     }
1650
1651     my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersCheck($function, $interfaceName);
1652     push(@implContentDecls, $parameterCheckString);
1653
1654     # Build the function call string.
1655     push(@implContentDecls, GenerateFunctionCallString($function, $paramIndex, "    ", $interfaceName, %replacements));
1656
1657     if ($raisesExceptions) {
1658         push(@implContentDecls, "    }\n");
1659         push(@implContentDecls, "    fail:\n");
1660         push(@implContentDecls, "    return setDOMException(ec, args.GetIsolate());\n");
1661     }
1662
1663     push(@implContentDecls, "}\n\n");
1664     push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1665 }
1666
1667 sub GenerateCallWith
1668 {
1669     my $callWith = shift;
1670     return () unless $callWith;
1671     my $outputArray = shift;
1672     my $indent = shift;
1673     my $returnVoid = shift;
1674     my $emptyContext = shift;
1675     my $function = shift;
1676
1677     my @callWithArgs;
1678     if ($codeGenerator->ExtendedAttributeContains($callWith, "ScriptState")) {
1679         if ($emptyContext) {
1680             push(@$outputArray, $indent . "EmptyScriptState state;\n");
1681             push(@callWithArgs, "&state");
1682         } else {
1683             push(@$outputArray, $indent . "ScriptState* state = ScriptState::current();\n");
1684             push(@$outputArray, $indent . "if (!state)\n");
1685             push(@$outputArray, $indent . "    return" . ($returnVoid ? "" : " v8Undefined()") . ";\n");
1686             push(@callWithArgs, "state");
1687         }
1688     }
1689     if ($codeGenerator->ExtendedAttributeContains($callWith, "ScriptExecutionContext")) {
1690         push(@$outputArray, $indent . "ScriptExecutionContext* scriptContext = getScriptExecutionContext();\n");
1691         push(@callWithArgs, "scriptContext");
1692     }
1693     if ($function and $codeGenerator->ExtendedAttributeContains($callWith, "ScriptArguments")) {
1694         push(@$outputArray, $indent . "RefPtr<ScriptArguments> scriptArguments(createScriptArguments(args, " . @{$function->parameters} . "));\n");
1695         push(@callWithArgs, "scriptArguments");
1696         AddToImplIncludes("ScriptArguments.h");
1697     }
1698     if ($codeGenerator->ExtendedAttributeContains($callWith, "CallStack")) {
1699         push(@$outputArray, $indent . "RefPtr<ScriptCallStack> callStack(createScriptCallStackForConsole());\n");
1700         push(@$outputArray, $indent . "if (!callStack)\n");
1701         push(@$outputArray, $indent . "    return v8Undefined();\n");
1702         push(@callWithArgs, "callStack");
1703         AddToImplIncludes("ScriptCallStack.h");
1704         AddToImplIncludes("ScriptCallStackFactory.h");
1705     }
1706     return @callWithArgs;
1707 }
1708
1709 sub GenerateArgumentsCountCheck
1710 {
1711     my $function = shift;
1712     my $dataNode = shift;
1713
1714     my $numMandatoryParams = 0;
1715     my $allowNonOptional = 1;
1716     foreach my $param (@{$function->parameters}) {
1717         if ($param->extendedAttributes->{"Optional"} or $param->isVariadic) {
1718             $allowNonOptional = 0;
1719         } else {
1720             die "An argument must not be declared to be optional unless all subsequent arguments to the operation are also optional." if !$allowNonOptional;
1721             $numMandatoryParams++;
1722         }
1723     }
1724
1725     my $argumentsCountCheckString = "";
1726     if ($numMandatoryParams >= 1) {
1727         $argumentsCountCheckString .= "    if (args.Length() < $numMandatoryParams)\n";
1728         $argumentsCountCheckString .= "        return throwNotEnoughArgumentsError(args.GetIsolate());\n";
1729     }
1730     return $argumentsCountCheckString;
1731 }
1732
1733 sub GetIndexOf
1734 {
1735     my $paramName = shift;
1736     my @paramList = @_;
1737     my $index = 0;
1738     foreach my $param (@paramList) {
1739         if ($paramName eq $param) {
1740             return $index;
1741         }
1742         $index++;
1743     }
1744     return -1;
1745 }
1746
1747 sub GenerateParametersCheck
1748 {
1749     my $function = shift;
1750     my $interfaceName = shift;
1751
1752     my $parameterCheckString = "";
1753     my $paramIndex = 0;
1754     my @paramTransferListNames = ();
1755     my %replacements = ();
1756
1757     foreach my $parameter (@{$function->parameters}) {
1758         TranslateParameter($parameter);
1759         my $nativeType = GetNativeTypeFromSignature($parameter, $paramIndex);
1760
1761         # Optional arguments with [Optional] should generate an early call with fewer arguments.
1762         # Optional arguments with [Optional=...] should not generate the early call.
1763         # Optional Dictionary arguments always considered to have default of empty dictionary.
1764         my $optional = $parameter->extendedAttributes->{"Optional"};
1765         if ($optional && $optional ne "DefaultIsUndefined" && $optional ne "DefaultIsNullString" && $nativeType ne "Dictionary" && !$parameter->extendedAttributes->{"Callback"}) {
1766             $parameterCheckString .= "    if (args.Length() <= $paramIndex) {\n";
1767             my $functionCall = GenerateFunctionCallString($function, $paramIndex, "    " x 2, $interfaceName, %replacements);
1768             $parameterCheckString .= $functionCall;
1769             $parameterCheckString .= "    }\n";
1770         }
1771
1772         my $parameterDefaultPolicy = "DefaultIsUndefined";
1773         if ($optional and $optional eq "DefaultIsNullString") {
1774             $parameterDefaultPolicy = "DefaultIsNullString";
1775         }
1776
1777         my $parameterName = $parameter->name;
1778         if (GetIndexOf($parameterName, @paramTransferListNames) != -1) {
1779             $replacements{$parameterName} = "messagePortArray" . ucfirst($parameterName);
1780             $paramIndex++;
1781             next;
1782         }
1783
1784         AddToImplIncludes("ExceptionCode.h");
1785         if ($parameter->extendedAttributes->{"Callback"}) {
1786             my $className = GetCallbackClassName($parameter->type);
1787             AddToImplIncludes("$className.h");
1788             if ($optional) {
1789                 $parameterCheckString .= "    RefPtr<" . $parameter->type . "> $parameterName;\n";
1790                 $parameterCheckString .= "    if (args.Length() > $paramIndex && !args[$paramIndex]->IsNull() && !args[$paramIndex]->IsUndefined()) {\n";
1791                 $parameterCheckString .= "        if (!args[$paramIndex]->IsFunction())\n";
1792                 $parameterCheckString .= "            return throwTypeError(0, args.GetIsolate());\n";
1793                 $parameterCheckString .= "        $parameterName = ${className}::create(args[$paramIndex], getScriptExecutionContext());\n";
1794                 $parameterCheckString .= "    }\n";
1795             } else {
1796                 $parameterCheckString .= "    if (args.Length() <= $paramIndex || !args[$paramIndex]->IsFunction())\n";
1797                 $parameterCheckString .= "        return throwTypeError(0, args.GetIsolate());\n";
1798                 $parameterCheckString .= "    RefPtr<" . $parameter->type . "> $parameterName = ${className}::create(args[$paramIndex], getScriptExecutionContext());\n";
1799             }
1800         } elsif ($parameter->extendedAttributes->{"Clamp"}) {
1801                 my $nativeValue = "${parameterName}NativeValue";
1802                 my $paramType = $parameter->type;
1803                 $parameterCheckString .= "    $paramType $parameterName = 0;\n";
1804                 $parameterCheckString .= "    EXCEPTION_BLOCK(double, $nativeValue, args[$paramIndex]->NumberValue());\n";
1805                 $parameterCheckString .= "    if (!isnan($nativeValue))\n";
1806                 $parameterCheckString .= "        $parameterName = clampTo<$paramType>($nativeValue);\n";
1807         } elsif ($parameter->type eq "SerializedScriptValue") {
1808             AddToImplIncludes("SerializedScriptValue.h");
1809             my $useTransferList = 0;
1810             my $transferListName = "";
1811             my $TransferListName = "";
1812             if ($parameter->extendedAttributes->{"TransferList"}) {
1813                 $transferListName = $parameter->extendedAttributes->{"TransferList"};
1814                 push(@paramTransferListNames, $transferListName);
1815
1816                 my @allParameterNames = ();
1817                 foreach my $parameter (@{$function->parameters}) {
1818                     push(@allParameterNames, $parameter->name);
1819                 }
1820                 my $transferListIndex = GetIndexOf($transferListName, @allParameterNames);
1821                 if ($transferListIndex == -1) {
1822                     die "IDL error: TransferList refers to a nonexistent argument";
1823                 }
1824
1825                 AddToImplIncludes("wtf/ArrayBuffer.h");
1826                 AddToImplIncludes("MessagePort.h");
1827                 $TransferListName = ucfirst($transferListName);
1828                 $parameterCheckString .= "    MessagePortArray messagePortArray$TransferListName;\n";
1829                 $parameterCheckString .= "    ArrayBufferArray arrayBufferArray$TransferListName;\n";
1830                 $parameterCheckString .= "    if (args.Length() > $transferListIndex) {\n";
1831                 $parameterCheckString .= "        if (!extractTransferables(args[$transferListIndex], messagePortArray$TransferListName, arrayBufferArray$TransferListName, args.GetIsolate()))\n";
1832                 $parameterCheckString .= "            return throwTypeError(\"Could not extract transferables\");\n";
1833                 $parameterCheckString .= "    }\n";
1834                 $useTransferList = 1;
1835             }
1836             $parameterCheckString .= "    bool ${parameterName}DidThrow = false;\n";
1837             if (!$useTransferList) {
1838                     $parameterCheckString .= "    $nativeType $parameterName = SerializedScriptValue::create(args[$paramIndex], 0, 0, ${parameterName}DidThrow, args.GetIsolate());\n";
1839             } else {
1840                     $parameterCheckString .= "    $nativeType $parameterName = SerializedScriptValue::create(args[$paramIndex], &messagePortArray$TransferListName, &arrayBufferArray$TransferListName, ${parameterName}DidThrow, args.GetIsolate());\n";
1841             }
1842             $parameterCheckString .= "    if (${parameterName}DidThrow)\n";
1843             $parameterCheckString .= "        return v8Undefined();\n";
1844         } elsif (TypeCanFailConversion($parameter)) {
1845             $parameterCheckString .= "    $nativeType $parameterName = " .
1846                  JSValueToNative($parameter, "args[$paramIndex]", "args.GetIsolate()") . ";\n";
1847             $parameterCheckString .= "    if (UNLIKELY(!$parameterName)) {\n";
1848             $parameterCheckString .= "        ec = TYPE_MISMATCH_ERR;\n";
1849             $parameterCheckString .= "        goto fail;\n";
1850             $parameterCheckString .= "    }\n";
1851         } elsif ($parameter->isVariadic) {
1852             my $nativeElementType = GetNativeType($parameter->type);
1853             if ($nativeElementType =~ />$/) {
1854                 $nativeElementType .= " ";
1855             }
1856
1857             my $argType = GetTypeFromSignature($parameter);
1858             if (IsWrapperType($argType)) {
1859                 $parameterCheckString .= "    Vector<$nativeElementType> $parameterName;\n";
1860                 $parameterCheckString .= "    for (int i = $paramIndex; i < args.Length(); ++i) {\n";
1861                 $parameterCheckString .= "        if (!V8${argType}::HasInstance(args[i]))\n";
1862                 $parameterCheckString .= "            return throwTypeError(0, args.GetIsolate());\n";
1863                 $parameterCheckString .= "        $parameterName.append(V8${argType}::toNative(v8::Handle<v8::Object>::Cast(args[i])));\n";
1864                 $parameterCheckString .= "    }\n";
1865             } else {
1866                 $parameterCheckString .= "    EXCEPTION_BLOCK(Vector<$nativeElementType>, $parameterName, toNativeArguments<$nativeElementType>(args, $paramIndex));\n";
1867             }
1868         } elsif ($nativeType =~ /^V8Parameter/) {
1869             my $value = JSValueToNative($parameter, "MAYBE_MISSING_PARAMETER(args, $paramIndex, $parameterDefaultPolicy)", "args.GetIsolate()");
1870             $parameterCheckString .= "    " . ConvertToV8Parameter($parameter, $nativeType, $parameterName, $value) . "\n";
1871         } else {
1872             # If the "StrictTypeChecking" extended attribute is present, and the argument's type is an
1873             # interface type, then if the incoming value does not implement that interface, a TypeError
1874             # is thrown rather than silently passing NULL to the C++ code.
1875             # Per the Web IDL and ECMAScript specifications, incoming values can always be converted
1876             # to both strings and numbers, so do not throw TypeError if the argument is of these
1877             # types.
1878             if ($function->signature->extendedAttributes->{"StrictTypeChecking"}) {
1879                 my $argValue = "args[$paramIndex]";
1880                 my $argType = GetTypeFromSignature($parameter);
1881                 if (IsWrapperType($argType)) {
1882                     $parameterCheckString .= "    if (args.Length() > $paramIndex && !isUndefinedOrNull($argValue) && !V8${argType}::HasInstance($argValue))\n";
1883                     $parameterCheckString .= "        return throwTypeError(0, args.GetIsolate());\n";
1884                 }
1885             }
1886             $parameterCheckString .= "    EXCEPTION_BLOCK($nativeType, $parameterName, " .
1887                  JSValueToNative($parameter, "MAYBE_MISSING_PARAMETER(args, $paramIndex, $parameterDefaultPolicy)", "args.GetIsolate()") . ");\n";
1888             if ($nativeType eq 'Dictionary') {
1889                $parameterCheckString .= "    if (!$parameterName.isUndefinedOrNull() && !$parameterName.isObject())\n";
1890                $parameterCheckString .= "        return throwTypeError(\"Not an object.\", args.GetIsolate());\n";
1891             }
1892         }
1893
1894         if ($parameter->extendedAttributes->{"IsIndex"}) {
1895             $parameterCheckString .= "    if (UNLIKELY($parameterName < 0)) {\n";
1896             $parameterCheckString .= "        ec = INDEX_SIZE_ERR;\n";
1897             $parameterCheckString .= "        goto fail;\n";
1898             $parameterCheckString .= "    }\n";
1899         }
1900
1901         $paramIndex++;
1902     }
1903     return ($parameterCheckString, $paramIndex, %replacements);
1904 }
1905
1906 sub GenerateOverloadedConstructorCallback
1907 {
1908     my $dataNode = shift;
1909     my $interfaceName = $dataNode->name;
1910
1911     push(@implContent, <<END);
1912 v8::Handle<v8::Value> V8${interfaceName}::constructorCallback(const v8::Arguments& args)
1913 {
1914     INC_STATS("DOM.${interfaceName}.Constructor");
1915     if (!args.IsConstructCall())
1916         return throwTypeError("DOM object constructor cannot be called as a function.");
1917
1918     if (ConstructorMode::current() == ConstructorMode::WrapExistingObject)
1919         return args.Holder();
1920
1921 END
1922
1923     my $leastNumMandatoryParams = 255;
1924     foreach my $constructor (@{$dataNode->constructors}) {
1925         my $name = "constructor" . $constructor->{overloadedIndex} . "Callback";
1926         my ($numMandatoryParams, $parametersCheck) = GenerateFunctionParametersCheck($constructor);
1927         $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams < $leastNumMandatoryParams);
1928         push(@implContent, "    if ($parametersCheck)\n");
1929         push(@implContent, "        return $name(args);\n");
1930     }
1931     if ($leastNumMandatoryParams >= 1) {
1932         push(@implContent, "    if (args.Length() < $leastNumMandatoryParams)\n");
1933         push(@implContent, "        return throwNotEnoughArgumentsError(args.GetIsolate());\n");
1934     }
1935     push(@implContent, <<END);
1936     return throwTypeError(0, args.GetIsolate());
1937 END
1938     push(@implContent, "}\n\n");
1939 }
1940
1941 sub GenerateSingleConstructorCallback
1942 {
1943     my $dataNode = shift;
1944     my $function = shift;
1945
1946     my $interfaceName = $dataNode->name;
1947     my $overloadedIndexString = "";
1948     if ($function->{overloadedIndex} > 0) {
1949         $overloadedIndexString .= $function->{overloadedIndex};
1950     }
1951
1952     my $raisesExceptions = @{$function->raisesExceptions};
1953     if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
1954         $raisesExceptions = 1;
1955     }
1956     if (!$raisesExceptions) {
1957         foreach my $parameter (@{$function->parameters}) {
1958             if ((!$parameter->extendedAttributes->{"Callback"} and TypeCanFailConversion($parameter)) or $parameter->extendedAttributes->{"IsIndex"}) {
1959                 $raisesExceptions = 1;
1960             }
1961         }
1962     }
1963
1964     my $maybeObserveFeature = GenerateFeatureObservation($function->signature->extendedAttributes->{"V8MeasureAs"});
1965
1966     my @beforeArgumentList;
1967     my @afterArgumentList;
1968     push(@implContent, <<END);
1969 v8::Handle<v8::Value> V8${interfaceName}::constructor${overloadedIndexString}Callback(const v8::Arguments& args)
1970 {
1971     INC_STATS("DOM.${interfaceName}.Constructor${overloadedIndexString}");
1972     ${maybeObserveFeature}
1973 END
1974
1975     if ($function->{overloadedIndex} == 0) {
1976        push(@implContent, <<END);
1977     if (!args.IsConstructCall())
1978         return throwTypeError("DOM object constructor cannot be called as a function.");
1979
1980     if (ConstructorMode::current() == ConstructorMode::WrapExistingObject)
1981         return args.Holder();
1982 END
1983         push(@implContent, GenerateArgumentsCountCheck($function, $dataNode));
1984     }
1985
1986     if ($raisesExceptions) {
1987         AddToImplIncludes("ExceptionCode.h");
1988         push(@implContent, "\n");
1989         push(@implContent, "    ExceptionCode ec = 0;\n");
1990     }
1991
1992     # FIXME: Currently [Constructor(...)] does not yet support [Optional] arguments.
1993     # It just supports [Optional=DefaultIsUndefined] or [Optional=DefaultIsNullString].
1994     my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersCheck($function, $interfaceName);
1995     push(@implContent, $parameterCheckString);
1996
1997     if ($dataNode->extendedAttributes->{"CallWith"} && $dataNode->extendedAttributes->{"CallWith"} eq "ScriptExecutionContext") {
1998         push(@beforeArgumentList, "context");
1999         push(@implContent, <<END);
2000
2001     ScriptExecutionContext* context = getScriptExecutionContext();
2002 END
2003     }
2004
2005     if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
2006         push(@afterArgumentList, "ec");
2007     }
2008
2009     my @argumentList;
2010     my $index = 0;
2011     foreach my $parameter (@{$function->parameters}) {
2012         last if $index eq $paramIndex;
2013         if ($replacements{$parameter->name}) {
2014             push(@argumentList, $replacements{$parameter->name});
2015         } else {
2016             push(@argumentList, $parameter->name);
2017         }
2018         $index++;
2019     }
2020
2021     my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterArgumentList);
2022     push(@implContent, "\n");
2023     push(@implContent, "    RefPtr<${interfaceName}> impl = ${interfaceName}::create(${argumentString});\n");
2024     push(@implContent, "    v8::Handle<v8::Object> wrapper = args.Holder();\n");
2025
2026     if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
2027         push(@implContent, "    if (ec)\n");
2028         push(@implContent, "        goto fail;\n");
2029     }
2030
2031     push(@implContent, <<END);
2032
2033     V8DOMWrapper::createDOMWrapper(impl.release(), &info, wrapper, args.GetIsolate());
2034     return wrapper;
2035 END
2036
2037     if ($raisesExceptions) {
2038         push(@implContent, "  fail:\n");
2039         push(@implContent, "    return setDOMException(ec, args.GetIsolate());\n");
2040     }
2041
2042     push(@implContent, "}\n");
2043     push(@implContent, "\n");
2044 }
2045
2046 sub GenerateConstructorCallback
2047 {
2048     my $dataNode = shift;
2049     my $interfaceName = $dataNode->name;
2050
2051     if (@{$dataNode->constructors} == 1) {
2052         GenerateSingleConstructorCallback($dataNode, @{$dataNode->constructors}[0]);
2053     } else {
2054         foreach my $constructor (@{$dataNode->constructors}) {
2055             GenerateSingleConstructorCallback($dataNode, $constructor);
2056         }
2057         GenerateOverloadedConstructorCallback($dataNode);
2058     }
2059 }
2060
2061 sub GenerateEventConstructorCallback
2062 {
2063     my $dataNode = shift;
2064     my $interfaceName = $dataNode->name;
2065
2066     AddToImplIncludes("Dictionary.h");
2067     push(@implContent, <<END);
2068 v8::Handle<v8::Value> V8${interfaceName}::constructorCallback(const v8::Arguments& args)
2069 {
2070     INC_STATS("DOM.${interfaceName}.Constructor");
2071
2072     if (!args.IsConstructCall())
2073         return throwTypeError("DOM object constructor cannot be called as a function.");
2074
2075     if (ConstructorMode::current() == ConstructorMode::WrapExistingObject)
2076         return args.Holder();
2077
2078     if (args.Length() < 1)
2079         return throwNotEnoughArgumentsError(args.GetIsolate());
2080
2081     STRING_TO_V8PARAMETER_EXCEPTION_BLOCK(V8Parameter<>, type, args[0]);
2082     ${interfaceName}Init eventInit;
2083     if (args.Length() >= 2) {
2084         EXCEPTION_BLOCK(Dictionary, options, Dictionary(args[1], args.GetIsolate()));
2085         if (!fill${interfaceName}Init(eventInit, options))
2086             return v8Undefined();
2087     }
2088
2089     RefPtr<${interfaceName}> event = ${interfaceName}::create(type, eventInit);
2090
2091     v8::Handle<v8::Object> wrapper = args.Holder();
2092     V8DOMWrapper::createDOMWrapper(event.release(), &info, wrapper, args.GetIsolate());
2093     return wrapper;
2094 }
2095
2096 bool fill${interfaceName}Init(${interfaceName}Init& eventInit, const Dictionary& options)
2097 {
2098 END
2099
2100     foreach my $interfaceBase (@{$dataNode->parents}) {
2101         push(@implContent, <<END);
2102     if (!fill${interfaceBase}Init(eventInit, options))
2103         return false;
2104
2105 END
2106     }
2107
2108     for (my $index = 0; $index < @{$dataNode->attributes}; $index++) {
2109         my $attribute = @{$dataNode->attributes}[$index];
2110         if ($attribute->signature->extendedAttributes->{"InitializedByEventConstructor"}) {
2111             my $attributeName = $attribute->signature->name;
2112             push(@implContent, "    options.get(\"$attributeName\", eventInit.$attributeName);\n");
2113         }
2114     }
2115
2116     push(@implContent, <<END);
2117     return true;
2118 }
2119
2120 END
2121 }
2122
2123 sub GenerateTypedArrayConstructorCallback
2124 {
2125     my $dataNode = shift;
2126     my $interfaceName = $dataNode->name;
2127     my $viewType = GetTypeNameOfExternalTypedArray($dataNode);
2128     my $type = $dataNode->extendedAttributes->{"TypedArray"};
2129     AddToImplIncludes("V8ArrayBufferViewCustom.h");
2130
2131     push(@implContent, <<END);
2132 v8::Handle<v8::Value> V8${interfaceName}::constructorCallback(const v8::Arguments& args)
2133 {
2134     INC_STATS("DOM.${interfaceName}.Contructor");
2135     return constructWebGLArray<$interfaceName, V8${interfaceName}, $type>(args, &info, $viewType);
2136 }
2137
2138 END
2139 }
2140
2141 sub GenerateNamedConstructorCallback
2142 {
2143     my $function = shift;
2144     my $dataNode = shift;
2145
2146     my $interfaceName = $dataNode->name;
2147     my $raisesExceptions = @{$function->raisesExceptions};
2148     if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
2149         $raisesExceptions = 1;
2150     }
2151     if (!$raisesExceptions) {
2152         foreach my $parameter (@{$function->parameters}) {
2153             if ((!$parameter->extendedAttributes->{"Callback"} and TypeCanFailConversion($parameter)) or $parameter->extendedAttributes->{"IsIndex"}) {
2154                 $raisesExceptions = 1;
2155             }
2156         }
2157     }
2158
2159     my $maybeObserveFeature = GenerateFeatureObservation($function->signature->extendedAttributes->{"V8MeasureAs"});
2160
2161     my @beforeArgumentList;
2162     my @afterArgumentList;
2163
2164     my $toActiveDOMObject = "0";
2165     if ($dataNode->extendedAttributes->{"ActiveDOMObject"}) {
2166         $toActiveDOMObject = "V8${interfaceName}::toActiveDOMObject";
2167     }
2168     AddToImplIncludes("Frame.h");
2169
2170     push(@implContent, <<END);
2171 WrapperTypeInfo V8${interfaceName}Constructor::info = { V8${interfaceName}Constructor::GetTemplate, V8${interfaceName}::derefObject, ${toActiveDOMObject}, 0, V8${interfaceName}::installPerContextPrototypeProperties, 0, WrapperTypeObjectPrototype };
2172
2173 static v8::Handle<v8::Value> V8${interfaceName}ConstructorCallback(const v8::Arguments& args)
2174 {
2175     INC_STATS("DOM.${interfaceName}.Constructor");
2176     ${maybeObserveFeature}
2177     if (!args.IsConstructCall())
2178         return throwTypeError("DOM object constructor cannot be called as a function.");
2179
2180     if (ConstructorMode::current() == ConstructorMode::WrapExistingObject)
2181         return args.Holder();
2182
2183     Document* document = currentDocument(BindingState::instance());
2184
2185     // Make sure the document is added to the DOM Node map. Otherwise, the ${interfaceName} instance
2186     // may end up being the only node in the map and get garbage-collected prematurely.
2187     toV8(document, args.Holder(), args.GetIsolate());
2188
2189 END
2190
2191     push(@implContent, GenerateArgumentsCountCheck($function, $dataNode));
2192
2193     if ($raisesExceptions) {
2194         AddToImplIncludes("ExceptionCode.h");
2195         push(@implContent, "\n");
2196         push(@implContent, "    ExceptionCode ec = 0;\n");
2197     }
2198
2199     my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersCheck($function, $interfaceName);
2200     push(@implContent, $parameterCheckString);
2201
2202     push(@beforeArgumentList, "document");
2203
2204     if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
2205         push(@afterArgumentList, "ec");
2206     }
2207
2208     my @argumentList;
2209     my $index = 0;
2210     foreach my $parameter (@{$function->parameters}) {
2211         last if $index eq $paramIndex;
2212         if ($replacements{$parameter->name}) {
2213             push(@argumentList, $replacements{$parameter->name});
2214         } else {
2215             push(@argumentList, $parameter->name);
2216         }
2217         $index++;
2218     }
2219
2220     my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterArgumentList);
2221     push(@implContent, "\n");
2222     push(@implContent, "    RefPtr<${interfaceName}> impl = ${interfaceName}::createForJSConstructor(${argumentString});\n");
2223     push(@implContent, "    v8::Handle<v8::Object> wrapper = args.Holder();\n");
2224
2225     if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
2226         push(@implContent, "    if (ec)\n");
2227         push(@implContent, "        goto fail;\n");
2228     }
2229
2230     push(@implContent, <<END);
2231
2232     V8DOMWrapper::createDOMWrapper(impl.release(), &V8${interfaceName}Constructor::info, wrapper, args.GetIsolate());
2233     return wrapper;
2234 END
2235
2236     if ($raisesExceptions) {
2237         push(@implContent, "  fail:\n");
2238         push(@implContent, "    return setDOMException(ec, args.GetIsolate());\n");
2239     }
2240
2241     push(@implContent, "}\n");
2242
2243     push(@implContent, <<END);
2244
2245 v8::Persistent<v8::FunctionTemplate> V8${interfaceName}Constructor::GetTemplate()
2246 {
2247     static v8::Persistent<v8::FunctionTemplate> cachedTemplate;
2248     if (!cachedTemplate.IsEmpty())
2249         return cachedTemplate;
2250
2251     v8::HandleScope scope;
2252     v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(V8${interfaceName}ConstructorCallback);
2253
2254     v8::Local<v8::ObjectTemplate> instance = result->InstanceTemplate();
2255     instance->SetInternalFieldCount(V8${interfaceName}::internalFieldCount);
2256     result->SetClassName(v8::String::NewSymbol("${interfaceName}"));
2257     result->Inherit(V8${interfaceName}::GetTemplate());
2258
2259     cachedTemplate = v8::Persistent<v8::FunctionTemplate>::New(result);
2260     return cachedTemplate;
2261 }
2262
2263 END
2264 }
2265
2266 sub GenerateBatchedAttributeData
2267 {
2268     my $dataNode = shift;
2269     my $attributes = shift;
2270     my $interfaceName = $dataNode->name;
2271
2272     foreach my $attribute (@$attributes) {
2273         my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
2274         push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
2275         GenerateSingleBatchedAttribute($interfaceName, $attribute, ",", "");
2276         push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
2277     }
2278 }
2279
2280 sub GenerateSingleBatchedAttribute
2281 {
2282     my $interfaceName = shift;
2283     my $attribute = shift;
2284     my $delimiter = shift;
2285     my $indent = shift;
2286     my $attrName = $attribute->signature->name;
2287     my $attrExt = $attribute->signature->extendedAttributes;
2288
2289     my $accessControl = "v8::DEFAULT";
2290     if ($attrExt->{"DoNotCheckSecurityOnGetter"}) {
2291         $accessControl = "v8::ALL_CAN_READ";
2292     } elsif ($attrExt->{"DoNotCheckSecurityOnSetter"}) {
2293         $accessControl = "v8::ALL_CAN_WRITE";
2294     } elsif ($attrExt->{"DoNotCheckSecurity"}) {
2295         $accessControl = "v8::ALL_CAN_READ";
2296         if (!IsReadonly($attribute)) {
2297             $accessControl .= " | v8::ALL_CAN_WRITE";
2298         }
2299     }
2300     if ($attrExt->{"V8Unforgeable"}) {
2301         $accessControl .= " | v8::PROHIBITS_OVERWRITING";
2302     }
2303     $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")";
2304
2305     my $customAccessor =
2306         $attrExt->{"Custom"} ||
2307         $attrExt->{"CustomSetter"} ||
2308         $attrExt->{"CustomGetter"} ||
2309         $attrExt->{"V8Custom"} ||
2310         $attrExt->{"V8CustomSetter"} ||
2311         $attrExt->{"V8CustomGetter"} ||
2312         "";
2313     if ($customAccessor eq "VALUE_IS_MISSING") {
2314         # use the naming convension, interface + (capitalize) attr name
2315         $customAccessor = $interfaceName . "::" . $attrName;
2316     }
2317
2318     my $getter;
2319     my $setter;
2320     my $propAttr = "v8::None";
2321     my $hasCustomSetter = 0;
2322
2323     # Check attributes.
2324     if ($attrExt->{"NotEnumerable"}) {
2325         $propAttr .= " | v8::DontEnum";
2326     }
2327     if ($attrExt->{"V8Unforgeable"}) {
2328         $propAttr .= " | v8::DontDelete";
2329     }
2330
2331     my $on_proto = "0 /* on instance */";
2332     my $data = "0 /* no data */";
2333
2334     # Constructor
2335     if ($attribute->signature->type =~ /Constructor$/) {
2336         my $constructorType = $codeGenerator->StripModule($attribute->signature->type);
2337         $constructorType =~ s/Constructor$//;
2338         # $constructorType ~= /Constructor$/ indicates that it is NamedConstructor.
2339         # We do not generate the header file for NamedConstructor of class XXXX,
2340         # since we generate the NamedConstructor declaration into the header file of class XXXX.
2341         if ($constructorType !~ /Constructor$/ || $attribute->signature->extendedAttributes->{"V8CustomConstructor"} || $attribute->signature->extendedAttributes->{"CustomConstructor"}) {
2342             AddToImplIncludes("V8${constructorType}.h", $attribute->signature->extendedAttributes->{"Conditional"});
2343         }
2344         if ($customAccessor) {
2345             $getter = "V8${customAccessor}AccessorGetter";
2346         } else {
2347             $data = "&V8${constructorType}::info";
2348             $getter = "${interfaceName}V8Internal::${interfaceName}ConstructorGetter";
2349         }
2350         $setter = "${interfaceName}V8Internal::${interfaceName}ReplaceableAttrSetter";
2351     } else {
2352         # Default Getter and Setter
2353         $getter = "${interfaceName}V8Internal::${attrName}AttrGetter";
2354         $setter = "${interfaceName}V8Internal::${attrName}AttrSetter";
2355
2356         if ($attrExt->{"Replaceable"}) {
2357             $setter = "${interfaceName}V8Internal::${interfaceName}ReplaceableAttrSetter";
2358         }
2359
2360         # Custom Setter
2361         if ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
2362             $hasCustomSetter = 1;
2363             $setter = "V8${customAccessor}AccessorSetter";
2364         }
2365
2366         # Custom Getter
2367         if ($attrExt->{"CustomGetter"} || $attrExt->{"V8CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
2368             $getter = "V8${customAccessor}AccessorGetter";
2369         }
2370     }
2371
2372     # Read only attributes
2373     if (IsReadonly($attribute)) {
2374         $setter = "0";
2375     }
2376
2377     # An accessor can be installed on the proto
2378     if ($attrExt->{"V8OnProto"}) {
2379         $on_proto = "1 /* on proto */";
2380     }
2381
2382     my $commentInfo = "Attribute '$attrName' (Type: '" . $attribute->type .
2383                       "' ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
2384
2385     push(@implContent, $indent . "    \/\/ $commentInfo\n");
2386     push(@implContent, $indent . "    {\"$attrName\", $getter, $setter, $data, $accessControl, static_cast<v8::PropertyAttribute>($propAttr), $on_proto}" . $delimiter . "\n");
2387 }
2388
2389 sub IsStandardFunction
2390 {
2391     my $dataNode = shift;
2392     my $function = shift;
2393
2394     my $interfaceName = $dataNode->name;
2395     my $attrExt = $function->signature->extendedAttributes;
2396     return 0 if $attrExt->{"V8Unforgeable"};
2397     return 0 if $function->isStatic;
2398     return 0 if $attrExt->{"V8EnabledAtRuntime"};
2399     return 0 if $attrExt->{"V8EnabledPerContext"};
2400     return 0 if RequiresCustomSignature($function);
2401     return 0 if $attrExt->{"V8DoNotCheckSignature"};
2402     return 0 if ($attrExt->{"DoNotCheckSecurity"} && ($dataNode->extendedAttributes->{"CheckSecurity"} || $interfaceName eq "DOMWindow"));
2403     return 0 if $attrExt->{"NotEnumerable"};
2404     return 0 if $attrExt->{"V8ReadOnly"};
2405     return 1;
2406 }
2407
2408 sub GenerateNonStandardFunction
2409 {
2410     my $dataNode = shift;
2411     my $function = shift;
2412
2413     my $interfaceName = $dataNode->name;
2414     my $attrExt = $function->signature->extendedAttributes;
2415     my $name = $function->signature->name;
2416
2417     my $property_attributes = "v8::DontDelete";
2418     if ($attrExt->{"NotEnumerable"}) {
2419         $property_attributes .= " | v8::DontEnum";
2420     }
2421     if ($attrExt->{"V8ReadOnly"}) {
2422         $property_attributes .= " | v8::ReadOnly";
2423     }
2424
2425     my $commentInfo = "Function '$name' (ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
2426
2427     my $template = "proto";
2428     if ($attrExt->{"V8Unforgeable"}) {
2429         $template = "instance";
2430     }
2431     if ($function->isStatic) {
2432         $template = "desc";
2433     }
2434
2435     my $conditional = "";
2436     if ($attrExt->{"V8EnabledAtRuntime"}) {
2437         # Only call Set()/SetAccessor() if this method should be enabled
2438         my $enable_function = GetRuntimeEnableFunctionName($function->signature);
2439         $conditional = "if (${enable_function}())\n        ";
2440     }
2441     if ($attrExt->{"V8EnabledPerContext"}) {
2442         # Only call Set()/SetAccessor() if this method should be enabled
2443         my $enable_function = GetContextEnableFunction($function->signature);
2444         $conditional = "if (${enable_function}(impl->document()))\n        ";
2445     }
2446
2447     if ($attrExt->{"DoNotCheckSecurity"} &&
2448         ($dataNode->extendedAttributes->{"CheckSecurity"} || $interfaceName eq "DOMWindow")) {
2449         # Functions that are marked DoNotCheckSecurity are always readable but if they are changed
2450         # and then accessed on a different domain we do not return the underlying value but instead
2451         # return a new copy of the original function. This is achieved by storing the changed value
2452         # as hidden property.
2453         push(@implContent, <<END);
2454
2455     // $commentInfo
2456     ${conditional}$template->SetAccessor(v8::String::NewSymbol("$name"), ${interfaceName}V8Internal::${name}AttrGetter, ${interfaceName}V8Internal::${interfaceName}DomainSafeFunctionSetter, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>($property_attributes));
2457 END
2458         return;
2459     }
2460
2461     my $signature = "defaultSignature";
2462     if ($attrExt->{"V8DoNotCheckSignature"} || $function->isStatic) {
2463        $signature = "v8::Local<v8::Signature>()";
2464     }
2465
2466     if (RequiresCustomSignature($function)) {
2467         $signature = "${name}Signature";
2468         push(@implContent, "\n    // Custom Signature '$name'\n", CreateCustomSignature($function));
2469     }
2470
2471     # Normal function call is a template
2472     my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
2473
2474     if ($property_attributes eq "v8::DontDelete") {
2475         $property_attributes = "";
2476     } else {
2477         $property_attributes = ", static_cast<v8::PropertyAttribute>($property_attributes)";
2478     }
2479
2480     if ($template eq "proto" && $conditional eq "" && $signature eq "defaultSignature" && $property_attributes eq "") {
2481         die "This shouldn't happen: Intraface '$interfaceName' $commentInfo\n";
2482     }
2483
2484     my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
2485     push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
2486
2487     push(@implContent, "    ${conditional}$template->Set(v8::String::NewSymbol(\"$name\"), v8::FunctionTemplate::New($callback, v8Undefined(), ${signature})$property_attributes);\n");
2488
2489     push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
2490 }
2491
2492 sub GenerateImplementationIndexer
2493 {
2494     my $dataNode = shift;
2495     my $indexer = shift;
2496     my $interfaceName = $dataNode->name;
2497
2498     # FIXME: Figure out what NumericIndexedGetter is really supposed to do. Right now, it's only set on WebGL-related files.
2499     my $hasCustomSetter = $dataNode->extendedAttributes->{"CustomIndexedSetter"} && !$dataNode->extendedAttributes->{"NumericIndexedGetter"};
2500     my $hasGetter = $dataNode->extendedAttributes->{"IndexedGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
2501
2502     # FIXME: Investigate and remove this nastinesss. In V8, named property handling and indexer handling are apparently decoupled,
2503     # which means that object[X] where X is a number doesn't reach named property indexer. So we need to provide
2504     # simplistic, mirrored indexer handling in addition to named property handling.
2505     my $isSpecialCase = exists $indexerSpecialCases{$interfaceName};
2506     if ($isSpecialCase) {
2507         $hasGetter = 1;
2508         if ($dataNode->extendedAttributes->{"CustomNamedSetter"}) {
2509             $hasCustomSetter = 1;
2510         }
2511     }
2512
2513     my $hasEnumerator = !$isSpecialCase && IsNodeSubType($dataNode);
2514
2515     # FIXME: Find a way to not have to special-case HTMLOptionsCollection.
2516     if ($interfaceName eq "HTMLOptionsCollection") {
2517         $hasEnumerator = 1;
2518         $hasGetter = 1;
2519     }
2520
2521     if (!$hasGetter) {
2522         return;
2523     }
2524
2525     AddToImplIncludes("V8Collection.h");
2526
2527     if (!$indexer) {
2528         $indexer = $codeGenerator->FindSuperMethod($dataNode, "item");
2529     }
2530
2531     my $indexerType = $indexer ? $indexer->type : 0;
2532
2533     # FIXME: Remove this once toV8 helper methods are implemented (see https://bugs.webkit.org/show_bug.cgi?id=32563).
2534     if ($interfaceName eq "WebKitCSSKeyframesRule") {
2535         $indexerType = "WebKitCSSKeyframeRule";
2536     }
2537
2538     if ($indexerType && !$hasCustomSetter) {
2539         if ($indexerType eq "DOMString") {
2540             my $conversion = $indexer->extendedAttributes->{"TreatReturnedNullStringAs"};
2541             if ($conversion && $conversion eq "Null") {
2542                 push(@implContent, <<END);
2543     setCollectionStringOrUndefinedIndexedGetter<${interfaceName}>(desc);
2544 END
2545             } else {
2546                 push(@implContent, <<END);
2547     setCollectionStringIndexedGetter<${interfaceName}>(desc);
2548 END
2549             }
2550         } else {
2551             push(@implContent, <<END);
2552     setCollectionIndexedGetter<${interfaceName}, ${indexerType}>(desc);
2553 END
2554             # Include the header for this indexer type, because setCollectionIndexedGetter() requires toV8() for this type.
2555             AddToImplIncludes("V8${indexerType}.h");
2556         }
2557
2558         return;
2559     }
2560
2561     my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
2562     my $setOn = "Instance";
2563
2564     # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
2565     # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
2566     # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
2567     # on the object.
2568     if ($interfaceName eq "DOMWindow") {
2569         $setOn = "Prototype";
2570         $hasDeleter = 0;
2571     }
2572
2573     push(@implContent, "    desc->${setOn}Template()->SetIndexedPropertyHandler(V8${interfaceName}::indexedPropertyGetter");
2574     push(@implContent, $hasCustomSetter ? ", V8${interfaceName}::indexedPropertySetter" : ", 0");
2575     push(@implContent, ", 0"); # IndexedPropertyQuery -- not being used at the moment.
2576     push(@implContent, $hasDeleter ? ", V8${interfaceName}::indexedPropertyDeleter" : ", 0");
2577     push(@implContent, ", nodeCollectionIndexedPropertyEnumerator<${interfaceName}>") if $hasEnumerator;
2578     push(@implContent, ");\n");
2579 }
2580
2581 sub GenerateImplementationNamedPropertyGetter
2582 {
2583     my $dataNode = shift;
2584     my $namedPropertyGetter = shift;
2585     my $interfaceName = $dataNode->name;
2586     my $hasCustomNamedGetter = $dataNode->extendedAttributes->{"CustomNamedGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
2587
2588     # FIXME: Remove hard-coded HTMLOptionsCollection reference by changing HTMLOptionsCollection to not inherit
2589     # from HTMLCollection per W3C spec (http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/html.html#HTMLOptionsCollection).
2590     if ($interfaceName eq "HTMLOptionsCollection") {
2591         $interfaceName = "HTMLCollection";
2592         $hasCustomNamedGetter = 1;
2593     }
2594
2595     if ($interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") {
2596         $hasCustomNamedGetter = 1;
2597     }
2598
2599     if ($interfaceName eq "HTMLDocument") {
2600         $hasCustomNamedGetter = 0;
2601     }
2602
2603     my $hasGetter = $dataNode->extendedAttributes->{"NamedGetter"} || $hasCustomNamedGetter;
2604     if (!$hasGetter) {
2605         return;
2606     }
2607
2608     if (!$namedPropertyGetter) {
2609         $namedPropertyGetter = $codeGenerator->FindSuperMethod($dataNode, "namedItem");
2610     }
2611
2612     if ($namedPropertyGetter && $namedPropertyGetter->type ne "Node" && !$namedPropertyGetter->extendedAttributes->{"Custom"} && !$hasCustomNamedGetter) {
2613         AddToImplIncludes("V8Collection.h");
2614         my $type = $namedPropertyGetter->type;
2615         push(@implContent, <<END);
2616     setCollectionNamedGetter<${interfaceName}, ${type}>(desc);
2617 END
2618         return;
2619     }
2620
2621     my $hasCustomNamedSetter = $dataNode->extendedAttributes->{"CustomNamedSetter"};
2622     my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
2623     my $hasEnumerator = $dataNode->extendedAttributes->{"CustomEnumerateProperty"};
2624     my $setOn = "Instance";
2625
2626     # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
2627     # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
2628     # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
2629     # on the object.
2630     if ($interfaceName eq "DOMWindow") {
2631         $setOn = "Prototype";
2632         $hasDeleter = 0;
2633         $hasEnumerator = 0;
2634     }
2635
2636     push(@implContent, "    desc->${setOn}Template()->SetNamedPropertyHandler(V8${interfaceName}::namedPropertyGetter, ");
2637     push(@implContent, $hasCustomNamedSetter ? "V8${interfaceName}::namedPropertySetter, " : "0, ");
2638     # If there is a custom enumerator, there MUST be custom query to properly communicate property attributes.
2639     push(@implContent, $hasEnumerator ? "V8${interfaceName}::namedPropertyQuery, " : "0, ");
2640     push(@implContent, $hasDeleter ? "V8${interfaceName}::namedPropertyDeleter, " : "0, ");
2641     push(@implContent, $hasEnumerator ? "V8${interfaceName}::namedPropertyEnumerator" : "0");
2642     push(@implContent, ");\n");
2643 }
2644
2645 sub GenerateImplementationCustomCall
2646 {
2647     my $dataNode = shift;
2648     my $interfaceName = $dataNode->name;
2649     my $hasCustomCall = $dataNode->extendedAttributes->{"CustomCall"};
2650
2651     if ($hasCustomCall) {
2652         push(@implContent, "    desc->InstanceTemplate()->SetCallAsFunctionHandler(V8${interfaceName}::callAsFunctionCallback);\n");
2653     }
2654 }
2655
2656 sub GenerateImplementationMasqueradesAsUndefined
2657 {
2658     my $dataNode = shift;
2659     if ($dataNode->extendedAttributes->{"MasqueradesAsUndefined"})
2660     {
2661         push(@implContent, "    desc->InstanceTemplate()->MarkAsUndetectable();\n");
2662     }
2663 }
2664
2665 sub GenerateImplementation
2666 {
2667     my $object = shift;
2668     my $dataNode = shift;
2669     my $interfaceName = $dataNode->name;
2670     my $visibleInterfaceName = $codeGenerator->GetVisibleInterfaceName($dataNode);
2671     my $className = "V8$interfaceName";
2672     my $nativeType = GetNativeTypeForConversions($dataNode);
2673
2674     # - Add default header template
2675     push(@implFixedHeader, GenerateImplementationContentHeader($dataNode));
2676
2677     AddToImplIncludes("BindingState.h");
2678     AddToImplIncludes("ContextFeatures.h");
2679     AddToImplIncludes("RuntimeEnabledFeatures.h");
2680     AddToImplIncludes("V8Binding.h");
2681     AddToImplIncludes("V8DOMWrapper.h");
2682
2683     AddIncludesForType($interfaceName);
2684
2685     my $toActive = $dataNode->extendedAttributes->{"ActiveDOMObject"} ? "${className}::toActiveDOMObject" : "0";
2686     my $rootForGC = NeedsCustomOpaqueRootForGC($dataNode) ? "${className}::opaqueRootForGC" : "0";
2687
2688     # Find the super descriptor.
2689     my $parentClass = "";
2690     my $parentClassTemplate = "";
2691     foreach (@{$dataNode->parents}) {
2692         my $parent = $codeGenerator->StripModule($_);
2693         AddToImplIncludes("V8${parent}.h");
2694         $parentClass = "V8" . $parent;
2695         $parentClassTemplate = $parentClass . "::GetTemplate()";
2696         last;
2697     }
2698     push(@implContentDecls, "namespace WebCore {\n\n");
2699     my $parentClassInfo = $parentClass ? "&${parentClass}::info" : "0";
2700
2701     my $WrapperTypePrototype = $dataNode->isException ? "WrapperTypeErrorPrototype" : "WrapperTypeObjectPrototype";
2702
2703     push(@implContentDecls, "WrapperTypeInfo ${className}::info = { ${className}::GetTemplate, ${className}::derefObject, $toActive, $rootForGC, ${className}::installPerContextPrototypeProperties, $parentClassInfo, $WrapperTypePrototype };\n\n");
2704     push(@implContentDecls, "namespace ${interfaceName}V8Internal {\n\n");
2705
2706     push(@implContentDecls, "template <typename T> void V8_USE(T) { }\n\n");
2707
2708     my $hasConstructors = 0;
2709     my $hasReplaceable = 0;
2710
2711     # Generate property accessors for attributes.
2712     for (my $index = 0; $index < @{$dataNode->attributes}; $index++) {
2713         my $attribute = @{$dataNode->attributes}[$index];
2714         my $attrType = $attribute->signature->type;
2715
2716         # Generate special code for the constructor attributes.
2717         if ($attrType =~ /Constructor$/) {
2718             if (!($attribute->signature->extendedAttributes->{"CustomGetter"} ||
2719                 $attribute->signature->extendedAttributes->{"V8CustomGetter"})) {
2720                 $hasConstructors = 1;
2721             }
2722             next;
2723         }
2724
2725         if ($attrType eq "EventListener" && $interfaceName eq "DOMWindow") {
2726             $attribute->signature->extendedAttributes->{"V8OnProto"} = 1;
2727         }
2728
2729         if ($attrType eq "SerializedScriptValue") {
2730             AddToImplIncludes("SerializedScriptValue.h");
2731         }
2732
2733         # Do not generate accessor if this is a custom attribute.  The
2734         # call will be forwarded to a hand-written accessor
2735         # implementation.
2736         if ($attribute->signature->extendedAttributes->{"Custom"} ||
2737             $attribute->signature->extendedAttributes->{"V8Custom"}) {
2738             next;
2739         }
2740
2741         # Generate the accessor.
2742         if (!($attribute->signature->extendedAttributes->{"CustomGetter"} ||
2743             $attribute->signature->extendedAttributes->{"V8CustomGetter"})) {
2744             GenerateNormalAttrGetter($attribute, $dataNode);
2745         }
2746
2747         if ($attribute->signature->extendedAttributes->{"Replaceable"}) {
2748             $hasReplaceable = 1;
2749         } elsif (!$attribute->signature->extendedAttributes->{"CustomSetter"} &&
2750             !$attribute->signature->extendedAttributes->{"V8CustomSetter"} &&
2751             !IsReadonly($attribute)) {
2752             GenerateNormalAttrSetter($attribute, $dataNode);
2753         }
2754     }
2755
2756     if ($hasConstructors) {
2757         GenerateConstructorGetter($dataNode);
2758     }
2759
2760     if ($hasConstructors || $hasReplaceable) {
2761         GenerateReplaceableAttrSetter($dataNode);
2762     }
2763
2764     if (NeedsCustomOpaqueRootForGC($dataNode)) {
2765         GenerateOpaqueRootForGC($dataNode);
2766     }
2767
2768     if ($dataNode->extendedAttributes->{"TypedArray"}) {
2769         my $viewType = GetTypeNameOfExternalTypedArray($dataNode);
2770         push(@implContent, <<END);
2771 v8::Handle<v8::Object> wrap($interfaceName* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
2772 {
2773     ASSERT(impl);
2774     v8::Handle<v8::Object> wrapper = V8${interfaceName}::createWrapper(impl, creationContext, isolate);
2775     if (!wrapper.IsEmpty())
2776         wrapper->SetIndexedPropertiesToExternalArrayData(impl->baseAddress(), $viewType, impl->length());
2777     return wrapper;
2778 }
2779
2780 END
2781     }
2782
2783     my $indexer;
2784     my $namedPropertyGetter;
2785     my @enabledPerContextFunctions;
2786     my @normalFunctions;
2787     my $needsDomainSafeFunctionSetter = 0;
2788     # Generate methods for functions.
2789     foreach my $function (@{$dataNode->functions}) {
2790         my $isCustom = $function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"V8Custom"};
2791         if (!$isCustom) {
2792             GenerateFunctionCallback($function, $dataNode);
2793             if ($function->{overloadIndex} > 1 && $function->{overloadIndex} == @{$function->{overloads}}) {
2794                 GenerateOverloadedFunctionCallback($function, $dataNode);
2795             }
2796         }
2797
2798         if ($function->signature->name eq "item") {
2799             $indexer = $function->signature;
2800         }
2801
2802         if ($function->signature->name eq "namedItem") {
2803             $namedPropertyGetter = $function->signature;
2804         }
2805
2806         # If the function does not need domain security check, we need to
2807         # generate an access getter that returns different function objects
2808         # for different calling context.
2809         if (($dataNode->extendedAttributes->{"CheckSecurity"} || ($interfaceName eq "DOMWindow")) && $function->signature->extendedAttributes->{"DoNotCheckSecurity"}) {
2810             if (!$isCustom || $function->{overloadIndex} == 1) {
2811                 GenerateDomainSafeFunctionGetter($function, $interfaceName);
2812                 $needsDomainSafeFunctionSetter = 1;
2813             }
2814         }
2815
2816         # Separate out functions that are enabled per context so we can process them specially.
2817         if ($function->signature->extendedAttributes->{"V8EnabledPerContext"}) {
2818             push(@enabledPerContextFunctions, $function);
2819         } else {
2820             push(@normalFunctions, $function);
2821         }
2822     }
2823
2824     if ($needsDomainSafeFunctionSetter) {
2825         GenerateDomainSafeFunctionSetter($interfaceName);
2826     }
2827
2828     # Attributes
2829     my $attributes = $dataNode->attributes;
2830
2831     # For the DOMWindow interface we partition the attributes into the
2832     # ones that disallows shadowing and the rest.
2833     my @disallowsShadowing;
2834     # Also separate out attributes that are enabled at runtime so we can process them specially.
2835     my @enabledAtRuntimeAttributes;
2836     my @enabledPerContextAttributes;
2837     my @normalAttributes;
2838     foreach my $attribute (@$attributes) {
2839
2840         if ($interfaceName eq "DOMWindow" && $attribute->signature->extendedAttributes->{"V8Unforgeable"}) {
2841             push(@disallowsShadowing, $attribute);
2842         } elsif ($attribute->signature->extendedAttributes->{"V8EnabledAtRuntime"}) {
2843             push(@enabledAtRuntimeAttributes, $attribute);
2844         } elsif ($attribute->signature->extendedAttributes->{"V8EnabledPerContext"}) {
2845             push(@enabledPerContextAttributes, $attribute);
2846         } else {
2847             push(@normalAttributes, $attribute);
2848         }
2849     }
2850     $attributes = \@normalAttributes;
2851     # Put the attributes that disallow shadowing on the shadow object.
2852     if (@disallowsShadowing) {
2853         push(@implContent, "static const V8DOMConfiguration::BatchedAttribute shadowAttrs[] = {\n");
2854         GenerateBatchedAttributeData($dataNode, \@disallowsShadowing);
2855         push(@implContent, "};\n\n");
2856     }
2857
2858     my $has_attributes = 0;
2859     if (@$attributes) {
2860         $has_attributes = 1;
2861         push(@implContent, "static const V8DOMConfiguration::BatchedAttribute V8${interfaceName}Attrs[] = {\n");
2862         GenerateBatchedAttributeData($dataNode, $attributes);
2863         push(@implContent, "};\n\n");
2864     }
2865
2866     # Setup table of standard callback functions
2867     my $num_callbacks = 0;
2868     my $has_callbacks = 0;
2869     foreach my $function (@normalFunctions) {
2870         # Only one table entry is needed for overloaded methods:
2871         next if $function->{overloadIndex} > 1;
2872         # Don't put any nonstandard functions into this table:
2873         next if !IsStandardFunction($dataNode, $function);
2874         if (!$has_callbacks) {
2875             $has_callbacks = 1;
2876             push(@implContent, "static const V8DOMConfiguration::BatchedCallback V8${interfaceName}Callbacks[] = {\n");
2877         }
2878         my $name = $function->signature->name;
2879         my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
2880         my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
2881         push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
2882         push(@implContent, <<END);
2883     {"$name", $callback},
2884 END
2885         push(@implContent, "#endif\n") if $conditionalString;
2886         $num_callbacks++;
2887     }
2888     push(@implContent, "};\n\n")  if $has_callbacks;
2889
2890     # Setup constants
2891     my $has_constants = 0;
2892     my @constantsEnabledAtRuntime;
2893     if (@{$dataNode->constants}) {
2894         $has_constants = 1;
2895         push(@implContent, "static const V8DOMConfiguration::BatchedConstant V8${interfaceName}Consts[] = {\n");
2896     }
2897     foreach my $constant (@{$dataNode->constants}) {
2898         my $name = $constant->name;
2899         my $value = $constant->value;
2900         my $attrExt = $constant->extendedAttributes;
2901         my $conditional = $attrExt->{"Conditional"};
2902         my $implementedBy = $attrExt->{"ImplementedBy"};
2903         if ($implementedBy) {
2904             AddToImplIncludes("${implementedBy}.h");
2905         }
2906         if ($attrExt->{"V8EnabledAtRuntime"}) {
2907             push(@constantsEnabledAtRuntime, $constant);
2908         } else {
2909             # FIXME: we need the static_cast here only because of one constant, NodeFilter.idl
2910             # defines "const unsigned long SHOW_ALL = 0xFFFFFFFF".  It would be better if we
2911             # handled this here, and converted it to a -1 constant in the c++ output.
2912             if ($conditional) {
2913                 my $conditionalString = $codeGenerator->GenerateConditionalStringFromAttributeValue($conditional);
2914                 push(@implContent, "#if ${conditionalString}\n");
2915             }
2916             push(@implContent, <<END);
2917     {"${name}", static_cast<signed int>($value)},
2918 END
2919             push(@implContent, "#endif\n") if $conditional;
2920         }
2921     }
2922     if ($has_constants) {
2923         push(@implContent, "};\n\n");
2924         push(@implContent, $codeGenerator->GenerateCompileTimeCheckForEnumsIfNeeded($dataNode));
2925     }
2926
2927     push(@implContentDecls, "} // namespace ${interfaceName}V8Internal\n\n");
2928
2929     if ($dataNode->extendedAttributes->{"NamedConstructor"} && !($dataNode->extendedAttributes->{"V8CustomConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
2930         GenerateNamedConstructorCallback(@{$dataNode->constructors}[0], $dataNode);
2931     } elsif ($dataNode->extendedAttributes->{"Constructor"} && !($dataNode->extendedAttributes->{"V8CustomConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
2932         GenerateConstructorCallback($dataNode);
2933     } elsif ($codeGenerator->IsConstructorTemplate($dataNode, "Event")) {
2934         GenerateEventConstructorCallback($dataNode);
2935     } elsif ($codeGenerator->IsConstructorTemplate($dataNode, "TypedArray")) {
2936         GenerateTypedArrayConstructorCallback($dataNode);
2937     }
2938
2939     my $access_check = "";
2940     if ($dataNode->extendedAttributes->{"CheckSecurity"} && !($interfaceName eq "DOMWindow")) {
2941         $access_check = "instance->SetAccessCheckCallbacks(V8${interfaceName}::namedSecurityCheck, V8${interfaceName}::indexedSecurityCheck, v8::External::New(&V8${interfaceName}::info));";
2942     }
2943
2944     # For the DOMWindow interface, generate the shadow object template
2945     # configuration method.
2946     if ($interfaceName eq "DOMWindow") {
2947         push(@implContent, <<END);
2948 static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Persistent<v8::ObjectTemplate> templ)
2949 {
2950     V8DOMConfiguration::batchConfigureAttributes(templ, v8::Handle<v8::ObjectTemplate>(), shadowAttrs, WTF_ARRAY_LENGTH(shadowAttrs));
2951
2952     // Install a security handler with V8.
2953     templ->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::External::New(&V8DOMWindow::info));
2954     templ->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
2955     return templ;
2956 }
2957 END
2958     }
2959
2960     if (!$parentClassTemplate) {
2961         $parentClassTemplate = "v8::Persistent<v8::FunctionTemplate>()";
2962     }
2963
2964     # Generate the template configuration method
2965     push(@implContent,  <<END);
2966 static v8::Persistent<v8::FunctionTemplate> Configure${className}Template(v8::Persistent<v8::FunctionTemplate> desc)
2967 {
2968     desc->ReadOnlyPrototype();
2969
2970     v8::Local<v8::Signature> defaultSignature;
2971 END
2972     if ($dataNode->extendedAttributes->{"V8EnabledAtRuntime"}) {
2973         my $enable_function = GetRuntimeEnableFunctionName($dataNode);
2974         push(@implContent, <<END);
2975     if (!${enable_function}())
2976         defaultSignature = V8DOMConfiguration::configureTemplate(desc, \"\", $parentClassTemplate, V8${interfaceName}::internalFieldCount, 0, 0, 0, 0);
2977     else
2978 END
2979     }
2980     push(@implContent,  <<END);
2981     defaultSignature = V8DOMConfiguration::configureTemplate(desc, \"${visibleInterfaceName}\", $parentClassTemplate, V8${interfaceName}::internalFieldCount,
2982 END
2983     # Set up our attributes if we have them
2984     if ($has_attributes) {
2985         push(@implContent, <<END);
2986         V8${interfaceName}Attrs, WTF_ARRAY_LENGTH(V8${interfaceName}Attrs),
2987 END
2988     } else {
2989         push(@implContent, <<END);
2990         0, 0,
2991 END
2992     }
2993
2994     if ($has_callbacks) {
2995         push(@implContent, <<END);
2996         V8${interfaceName}Callbacks, WTF_ARRAY_LENGTH(V8${interfaceName}Callbacks));
2997 END
2998     } else {
2999         push(@implContent, <<END);
3000         0, 0);
3001 END
3002     }
3003     
3004     AddToImplIncludes("wtf/UnusedParam.h");
3005     push(@implContent, <<END);
3006     UNUSED_PARAM(defaultSignature); // In some cases, it will not be used.
3007 END
3008
3009     if (IsConstructable($dataNode)) {
3010         push(@implContent, <<END);
3011     desc->SetCallHandler(V8${interfaceName}::constructorCallback);
3012 END
3013     }
3014
3015     if ($access_check or @enabledAtRuntimeAttributes or @normalFunctions or $has_constants) {
3016         push(@implContent,  <<END);
3017     v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate();
3018     v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate();
3019     UNUSED_PARAM(instance); // In some cases, it will not be used.
3020     UNUSED_PARAM(proto); // In some cases, it will not be used.
3021 END
3022     }
3023
3024     push(@implContent,  "    $access_check\n");
3025
3026     # Setup the enable-at-runtime attrs if we have them
3027     foreach my $runtime_attr (@enabledAtRuntimeAttributes) {
3028         my $enable_function = GetRuntimeEnableFunctionName($runtime_attr->signature);
3029         my $conditionalString = $codeGenerator->GenerateConditionalString($runtime_attr->signature);
3030         push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
3031         push(@implContent, "    if (${enable_function}()) {\n");
3032         push(@implContent, "        static const V8DOMConfiguration::BatchedAttribute attrData =\\\n");
3033         GenerateSingleBatchedAttribute($interfaceName, $runtime_attr, ";", "    ");
3034         push(@implContent, <<END);
3035         V8DOMConfiguration::configureAttribute(instance, proto, attrData);
3036     }
3037 END
3038         push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
3039     }
3040
3041     # Setup the enable-at-runtime constants if we have them
3042     foreach my $runtime_const (@constantsEnabledAtRuntime) {
3043         my $enable_function = GetRuntimeEnableFunctionName($runtime_const);
3044         my $conditionalString = $codeGenerator->GenerateConditionalString($runtime_const);
3045         my $name = $runtime_const->name;
3046         my $value = $runtime_const->value;
3047         push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
3048         push(@implContent, "    if (${enable_function}()) {\n");
3049         push(@implContent, <<END);
3050         static const V8DOMConfiguration::BatchedConstant constData = {"${name}", static_cast<signed int>(${value})};
3051         V8DOMConfiguration::batchConfigureConstants(desc, proto, &constData, 1);
3052 END
3053         push(@implContent, "    }\n");
3054         push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
3055     }
3056
3057     GenerateImplementationIndexer($dataNode, $indexer);
3058     GenerateImplementationNamedPropertyGetter($dataNode, $namedPropertyGetter);
3059     GenerateImplementationCustomCall($dataNode);
3060     GenerateImplementationMasqueradesAsUndefined($dataNode);
3061
3062     # Define our functions with Set() or SetAccessor()
3063     my $total_functions = 0;
3064     foreach my $function (@normalFunctions) {
3065         # Only one accessor is needed for overloaded methods:
3066         next if $function->{overloadIndex} > 1;
3067
3068         $total_functions++;
3069         next if IsStandardFunction($dataNode, $function);
3070         GenerateNonStandardFunction($dataNode, $function);
3071         $num_callbacks++;
3072     }
3073
3074     die "Wrong number of callbacks generated for $interfaceName ($num_callbacks, should be $total_functions)" if $num_callbacks != $total_functions;
3075
3076     if ($has_constants) {
3077         push(@implContent, <<END);
3078     V8DOMConfiguration::batchConfigureConstants(desc, proto, V8${interfaceName}Consts, WTF_ARRAY_LENGTH(V8${interfaceName}Consts));
3079 END
3080     }
3081
3082     # Special cases
3083     if ($interfaceName eq "DOMWindow") {
3084         push(@implContent, <<END);
3085
3086     proto->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
3087     desc->SetHiddenPrototype(true);
3088     instance->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
3089     // Set access check callbacks, but turned off initially.
3090     // When a context is detached from a frame, turn on the access check.
3091     // Turning on checks also invalidates inline caches of the object.
3092     instance->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::External::New(&V8DOMWindow::info), false);
3093 END
3094     }
3095     if ($interfaceName eq "HTMLDocument") {
3096         push(@implContent, <<END);
3097     desc->SetHiddenPrototype(true);
3098 END
3099     }
3100     if ($interfaceName eq "Location") {
3101         push(@implContent, <<END);
3102
3103     // For security reasons, these functions are on the instance instead
3104     // of on the prototype object to ensure that they cannot be overwritten.
3105     instance->SetAccessor(v8::String::NewSymbol("reload"), V8Location::reloadAccessorGetter, 0, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
3106     instance->SetAccessor(v8::String::NewSymbol("replace"), V8Location::replaceAccessorGetter, 0, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
3107     instance->SetAccessor(v8::String::NewSymbol("assign"), V8Location::assignAccessorGetter, 0, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
3108 END
3109     }
3110
3111     push(@implContent, <<END);
3112
3113     // Custom toString template
3114     desc->Set(v8::String::NewSymbol("toString"), V8PerIsolateData::current()->toStringTemplate());
3115     return desc;
3116 }
3117
3118 v8::Persistent<v8::FunctionTemplate> ${className}::GetRawTemplate()
3119 {
3120     V8PerIsolateData* data = V8PerIsolateData::current();
3121     V8PerIsolateData::TemplateMap::iterator result = data->rawTemplateMap().find(&info);
3122     if (result != data->rawTemplateMap().end())
3123         return result->value;
3124
3125     v8::HandleScope handleScope;
3126     v8::Persistent<v8::FunctionTemplate> templ = createRawTemplate();
3127     data->rawTemplateMap().add(&info, templ);
3128     return templ;
3129 }
3130
3131 v8::Persistent<v8::FunctionTemplate> ${className}::GetTemplate()
3132 {
3133     V8PerIsolateData* data = V8PerIsolateData::current();
3134     V8PerIsolateData::TemplateMap::iterator result = data->templateMap().find(&info);
3135     if (result != data->templateMap().end())
3136         return result->value;
3137
3138     v8::HandleScope handleScope;
3139     v8::Persistent<v8::FunctionTemplate> templ =
3140         Configure${className}Template(GetRawTemplate());
3141     data->templateMap().add(&info, templ);
3142     return templ;
3143 }
3144
3145 bool ${className}::HasInstance(v8::Handle<v8::Value> value)
3146 {
3147     return GetRawTemplate()->HasInstance(value);
3148 }
3149
3150 END
3151
3152     if (@enabledPerContextAttributes) {
3153         push(@implContent, <<END);
3154 void ${className}::installPerContextProperties(v8::Handle<v8::Object> instance, ${nativeType}* impl)
3155 {
3156     v8::Local<v8::Object> proto = v8::Local<v8::Object>::Cast(instance->GetPrototype());
3157     // When building QtWebkit with V8 this variable is unused when none of the features are enabled.
3158     UNUSED_PARAM(proto);
3159 END
3160
3161         # Setup the enable-by-settings attrs if we have them
3162         foreach my $runtimeAttr (@enabledPerContextAttributes) {
3163             my $enableFunction = GetContextEnableFunction($runtimeAttr->signature);
3164             my $conditionalString = $codeGenerator->GenerateConditionalString($runtimeAttr->signature);
3165             push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
3166             push(@implContent, "    if (${enableFunction}(impl->document())) {\n");
3167             push(@implContent, "        static const V8DOMConfiguration::BatchedAttribute attrData =\\\n");
3168             GenerateSingleBatchedAttribute($interfaceName, $runtimeAttr, ";", "    ");
3169             push(@implContent, <<END);
3170         V8DOMConfiguration::configureAttribute(instance, proto, attrData);
3171 END
3172             push(@implContent, "    }\n");
3173             push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
3174         }
3175         push(@implContent, <<END);
3176 }
3177 END
3178     }
3179
3180     if (@enabledPerContextFunctions) {
3181         push(@implContent, <<END);
3182 void ${className}::installPerContextPrototypeProperties(v8::Handle<v8::Object> proto)
3183 {
3184     UNUSED_PARAM(proto);
3185 END
3186         # Setup the enable-by-settings functions if we have them
3187         push(@implContent,  <<END);
3188     v8::Local<v8::Signature> defaultSignature = v8::Signature::New(GetTemplate());
3189     UNUSED_PARAM(defaultSignature); // In some cases, it will not be used.
3190
3191     ScriptExecutionContext* context = toScriptExecutionContext(proto->CreationContext());
3192 END
3193
3194         foreach my $runtimeFunc (@enabledPerContextFunctions) {
3195             my $enableFunction = GetContextEnableFunction($runtimeFunc->signature);
3196             my $conditionalString = $codeGenerator->GenerateConditionalString($runtimeFunc->signature);
3197             push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
3198             push(@implContent, "    if (context && context->isDocument() && ${enableFunction}(static_cast<Document*>(context))) {\n");
3199             my $name = $runtimeFunc->signature->name;
3200             my $callback = GetFunctionTemplateCallbackName($runtimeFunc, $interfaceName);
3201             push(@implContent, <<END);
3202         proto->Set(v8::String::NewSymbol("${name}"), v8::FunctionTemplate::New(${callback}, v8Undefined(), defaultSignature)->GetFunction());
3203 END
3204             push(@implContent, "    }\n");
3205             push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
3206         }
3207
3208         push(@implContent, <<END);
3209 }
3210 END
3211     }
3212
3213     if ($dataNode->extendedAttributes->{"ActiveDOMObject"}) {
3214         # MessagePort is handled like an active dom object even though it doesn't inherit
3215         # from ActiveDOMObject, so don't try to cast it to ActiveDOMObject.
3216         my $returnValue = $interfaceName eq "MessagePort" ? "0" : "toNative(object)";
3217         push(@implContent, <<END);
3218 ActiveDOMObject* ${className}::toActiveDOMObject(v8::Handle<v8::Object> object)
3219 {
3220     return ${returnValue};
3221 }      
3222 END
3223     }
3224
3225     if ($interfaceName eq "DOMWindow") {
3226         push(@implContent, <<END);
3227 v8::Persistent<v8::ObjectTemplate> V8DOMWindow::GetShadowObjectTemplate()
3228 {
3229     static v8::Persistent<v8::ObjectTemplate> V8DOMWindowShadowObjectCache;
3230     if (V8DOMWindowShadowObjectCache.IsEmpty()) {
3231         V8DOMWindowShadowObjectCache = v8::Persistent<v8::ObjectTemplate>::New(v8::ObjectTemplate::New());
3232         ConfigureShadowObjectTemplate(V8DOMWindowShadowObjectCache);
3233     }
3234     return V8DOMWindowShadowObjectCache;
3235 }
3236 END
3237     }
3238
3239     GenerateToV8Converters($dataNode, $className, $nativeType);
3240
3241     push(@implContent, <<END);
3242
3243 void ${className}::derefObject(void* object)
3244 {
3245     static_cast<${nativeType}*>(object)->deref();
3246 }
3247
3248 } // namespace WebCore
3249 END
3250
3251     my $conditionalString = $codeGenerator->GenerateConditionalString($dataNode);
3252     push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
3253     
3254     # We've already added the header for this file in implFixedHeader, so remove
3255     # it from implIncludes to ensure we don't #include it twice.
3256     delete $implIncludes{"${className}.h"};
3257 }
3258
3259 sub GenerateHeaderContentHeader
3260 {
3261     my $dataNode = shift;
3262     my $className = "V8" . $dataNode->name;
3263     my $conditionalString = $codeGenerator->GenerateConditionalString($dataNode);
3264
3265     my @headerContentHeader = split("\r", $headerTemplate);
3266
3267     push(@headerContentHeader, "\n#if ${conditionalString}\n") if $conditionalString;
3268     push(@headerContentHeader, "\n#ifndef ${className}" . "_h");
3269     push(@headerContentHeader, "\n#define ${className}" . "_h\n\n");
3270     return @headerContentHeader;
3271 }
3272
3273 sub GenerateImplementationContentHeader
3274 {
3275     my $dataNode = shift;
3276     my $className = "V8" . $dataNode->name;
3277     my $conditionalString = $codeGenerator->GenerateConditionalString($dataNode);
3278
3279     my @implContentHeader = split("\r", $headerTemplate);
3280
3281     push(@implContentHeader, "\n#include \"config.h\"\n");
3282     push(@implContentHeader, "#include \"${className}.h\"\n\n");
3283     push(@implContentHeader, "#if ${conditionalString}\n\n") if $conditionalString;
3284     return @implContentHeader;
3285 }
3286
3287 sub GenerateCallbackHeader
3288 {
3289     my $object = shift;
3290     my $dataNode = shift;
3291
3292     my $interfaceName = $dataNode->name;
3293     my $className = "V8$interfaceName";
3294
3295
3296     # - Add default header template
3297     push(@headerContent, GenerateHeaderContentHeader($dataNode));
3298
3299     my @unsortedIncludes = ();
3300     push(@unsortedIncludes, "#include \"ActiveDOMCallback.h\"");
3301     push(@unsortedIncludes, "#include \"$interfaceName.h\"");
3302     push(@unsortedIncludes, "#include \"WorldContextHandle.h\"");
3303     push(@unsortedIncludes, "#include <v8.h>");
3304     push(@unsortedIncludes, "#include <wtf/Forward.h>");
3305     push(@headerContent, join("\n", sort @unsortedIncludes));
3306     
3307     push(@headerContent, "\n\nnamespace WebCore {\n\n");
3308     push(@headerContent, "class ScriptExecutionContext;\n\n");
3309     push(@headerContent, "class $className : public $interfaceName, public ActiveDOMCallback {\n");
3310
3311     push(@headerContent, <<END);
3312 public:
3313     static PassRefPtr<${className}> create(v8::Local<v8::Value> value, ScriptExecutionContext* context)
3314     {
3315         ASSERT(value->IsObject());
3316         ASSERT(context);
3317         return adoptRef(new ${className}(value->ToObject(), context));
3318     }
3319
3320     virtual ~${className}();
3321
3322 END
3323
3324     # Functions
3325     my $numFunctions = @{$dataNode->functions};
3326     if ($numFunctions > 0) {
3327         push(@headerContent, "    // Functions\n");
3328         foreach my $function (@{$dataNode->functions}) {
3329             my @params = @{$function->parameters};
3330             if (!$function->signature->extendedAttributes->{"Custom"} &&
3331                 !(GetNativeType($function->signature->type) eq "bool")) {
3332                     push(@headerContent, "    COMPILE_ASSERT(false)");
3333             }
3334
3335             push(@headerContent, "    virtual " . GetNativeTypeForCallbacks($function->signature->type) . " " . $function->signature->name . "(");
3336
3337             my @args = ();
3338             foreach my $param (@params) {
3339                 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $param->name);
3340             }
3341             push(@headerContent, join(", ", @args));
3342             push(@headerContent, ");\n");
3343         }
3344     }
3345
3346     push(@headerContent, <<END);
3347
3348 private:
3349     ${className}(v8::Local<v8::Object>, ScriptExecutionContext*);
3350
3351     v8::Persistent<v8::Object> m_callback;
3352     WorldContextHandle m_worldContext;
3353 };
3354
3355 END
3356
3357     push(@headerContent, "}\n\n");
3358     push(@headerContent, "#endif // $className" . "_h\n\n");
3359
3360     my $conditionalString = $codeGenerator->GenerateConditionalString($dataNode);
3361     push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString;
3362 }
3363
3364 sub GenerateCallbackImplementation
3365 {
3366     my $object = shift;
3367     my $dataNode = shift;
3368     my $interfaceName = $dataNode->name;
3369     my $className = "V8$interfaceName";
3370
3371     # - Add default header template
3372     push(@implFixedHeader, GenerateImplementationContentHeader($dataNode));
3373
3374     AddToImplIncludes("ScriptExecutionContext.h");
3375     AddToImplIncludes("V8Binding.h");
3376     AddToImplIncludes("V8Callback.h");
3377
3378     push(@implContent, "#include <wtf/Assertions.h>\n\n");
3379     push(@implContent, "namespace WebCore {\n\n");
3380     push(@implContent, <<END);
3381 ${className}::${className}(v8::Local<v8::Object> callback, ScriptExecutionContext* context)
3382     : ActiveDOMCallback(context)
3383     , m_callback(v8::Persistent<v8::Object>::New(callback))
3384     , m_worldContext(UseCurrentWorld)
3385 {
3386 }
3387
3388 ${className}::~${className}()
3389 {
3390     m_callback.Dispose();
3391 }
3392
3393 END
3394
3395     # Functions
3396     my $numFunctions = @{$dataNode->functions};
3397     if ($numFunctions > 0) {
3398         push(@implContent, "// Functions\n");
3399         foreach my $function (@{$dataNode->functions}) {
3400             my @params = @{$function->parameters};
3401             if ($function->signature->extendedAttributes->{"Custom"} ||
3402                 !(GetNativeTypeForCallbacks($function->signature->type) eq "bool")) {
3403                 next;
3404             }
3405
3406             AddIncludesForType($function->signature->type);
3407             push(@implContent, "\n" . GetNativeTypeForCallbacks($function->signature->type) . " ${className}::" . $function->signature->name . "(");
3408
3409             my @args = ();
3410             my @argsCheck = ();
3411             my $thisType = $function->signature->extendedAttributes->{"PassThisToCallback"};
3412             foreach my $param (@params) {
3413                 my $paramName = $param->name;
3414                 AddIncludesForType($param->type);
3415                 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $paramName);
3416                 if ($thisType and $thisType eq $param->type) {
3417                     push(@argsCheck, <<END);
3418     ASSERT(${paramName});
3419
3420 END
3421                 }
3422             }
3423             push(@implContent, join(", ", @args));
3424
3425             push(@implContent, ")\n");
3426             push(@implContent, "{\n");
3427             push(@implContent, @argsCheck) if @argsCheck;
3428             push(@implContent, "    if (!canInvokeCallback())\n");
3429             push(@implContent, "        return true;\n\n");
3430             push(@implContent, "    v8::HandleScope handleScope;\n\n");
3431             push(@implContent, "    v8::Handle<v8::Context> v8Context = toV8Context(scriptExecutionContext(), m_worldContext);\n");
3432             push(@implContent, "    if (v8Context.IsEmpty())\n");
3433             push(@implContent, "        return true;\n\n");
3434             push(@implContent, "    v8::Context::Scope scope(v8Context);\n\n");
3435
3436             @args = ();
3437             foreach my $param (@params) {
3438                 my $paramName = $param->name;
3439                 push(@implContent, "    v8::Handle<v8::Value> ${paramName}Handle = " . NativeToJSValue($param, $paramName) . ";\n");
3440                 push(@implContent, "    if (${paramName}Handle.IsEmpty()) {\n");
3441                 push(@implContent, "        if (!isScriptControllerTerminating())\n");
3442                 push(@implContent, "            CRASH();\n");
3443                 push(@implContent, "        return true;\n");
3444                 push(@implContent, "    }\n");
3445                 push(@args, "        ${paramName}Handle");
3446             }
3447
3448             if (scalar(@args) > 0) {
3449                 push(@implContent, "\n    v8::Handle<v8::Value> argv[] = {\n");
3450                 push(@implContent, join(",\n", @args));
3451                 push(@implContent, "\n    };\n\n");
3452             } else {
3453                 push(@implContent, "\n    v8::Handle<v8::Value> *argv = 0;\n\n");
3454             }
3455             push(@implContent, "    bool callbackReturnValue = false;\n");
3456             if ($thisType) {
3457                 foreach my $param (@params) {
3458                     next if $param->type ne $thisType;
3459                     my $paramName = $param->name;
3460                     push(@implContent, "    return !invokeCallback(m_callback, v8::Handle<v8::Object>::Cast(${paramName}Handle), " . scalar(@params) . ", argv, callbackReturnValue, scriptExecutionContext());\n");
3461                     last;
3462                 }
3463             } else {
3464                 push(@implContent, "    return !invokeCallback(m_callback, " . scalar(@params) . ", argv, callbackReturnValue, scriptExecutionContext());\n");
3465             }
3466             push(@implContent, "}\n");
3467         }
3468     }
3469
3470     push(@implContent, "\n} // namespace WebCore\n\n");
3471
3472     my $conditionalString = $codeGenerator->GenerateConditionalString($dataNode);
3473     push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
3474 }
3475
3476 sub BaseInterfaceName
3477 {
3478     my $dataNode = shift;
3479
3480     while (@{$dataNode->parents}) {
3481         $dataNode = $codeGenerator->ParseInterface($codeGenerator->StripModule(@{$dataNode->parents}[0]), 1);
3482     }
3483
3484     return $codeGenerator->StripModule($dataNode->name);
3485 }
3486
3487 sub GenerateToV8Converters
3488 {
3489     my $dataNode = shift;
3490     my $className = shift;
3491     my $nativeType = shift;
3492     my $interfaceName = $dataNode->name;
3493
3494     if ($dataNode->extendedAttributes->{"V8NoWrapperCache"} || $dataNode->extendedAttributes->{"SuppressToJSObject"}) {
3495         return;
3496     }
3497
3498     my $createWrapperArgumentType = GetPassRefPtrType($nativeType);
3499     my $baseType = BaseInterfaceName($dataNode);
3500     my $getCachedWrapper = IsNodeSubType($dataNode) ? "V8DOMWrapper::getCachedWrapper(impl.get())" : "DOMDataStore::current(isolate)->get(impl.get())";
3501
3502     push(@implContent, <<END);
3503
3504 v8::Handle<v8::Object> ${className}::createWrapper(${createWrapperArgumentType} impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
3505 {
3506     ASSERT(impl.get());
3507     ASSERT($getCachedWrapper.IsEmpty());
3508 END
3509     if ($baseType ne $interfaceName) {
3510         push(@implContent, <<END);
3511     ASSERT(static_cast<void*>(static_cast<${baseType}*>(impl.get())) == static_cast<void*>(impl.get()));
3512 END
3513     }
3514
3515     AddToImplIncludes("Frame.h");
3516
3517     if (IsSubType($dataNode, "Document")) {
3518         push(@implContent, <<END);
3519     if (Frame* frame = impl->frame()) {
3520         if (frame->script()->initializeMainWorld()) {
3521             // initializeMainWorld may have created a wrapper for the object, retry from the start.
3522             v8::Handle<v8::Object> wrapper = V8DOMWrapper::getCachedWrapper(impl.get());
3523             if (!wrapper.IsEmpty())
3524                 return wrapper;
3525         }
3526     }
3527 END
3528     }
3529
3530     push(@implContent, <<END);
3531
3532     v8::Handle<v8::Object> wrapper = V8DOMWrapper::instantiateV8Object(creationContext, &info, impl.get());
3533     if (UNLIKELY(wrapper.IsEmpty()))
3534         return wrapper;
3535
3536     installPerContextProperties(wrapper, impl.get());
3537     v8::Persistent<v8::Object> wrapperHandle = V8DOMWrapper::createDOMWrapper(impl, &info, wrapper, isolate);
3538     if (!hasDependentLifetime)
3539         wrapperHandle.MarkIndependent();
3540     return wrapper;
3541 }
3542 END
3543 }
3544
3545 sub GetNativeTypeForConversions
3546 {
3547     my $dataNode = shift;
3548     my $interfaceName = $dataNode->name;
3549
3550     $interfaceName = $codeGenerator->GetSVGTypeNeedingTearOff($interfaceName) if $codeGenerator->IsSVGTypeNeedingTearOff($interfaceName);
3551     return $interfaceName;;
3552 }
3553
3554 sub GenerateFunctionCallString()
3555 {
3556     my $function = shift;
3557     my $numberOfParameters = shift;
3558     my $indent = shift;
3559     my $interfaceName = shift;
3560     my %replacements = @_;
3561
3562     my $name = $function->signature->name;
3563     my $returnType = GetTypeFromSignature($function->signature);
3564     my $nativeReturnType = GetNativeType($returnType, 0);
3565     my $result = "";
3566
3567     my $isSVGTearOffType = ($codeGenerator->IsSVGTypeNeedingTearOff($returnType) and not $interfaceName =~ /List$/);
3568     $nativeReturnType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($returnType) if $isSVGTearOffType;
3569
3570     if ($function->signature->extendedAttributes->{"ImplementedAs"}) {
3571         $name = $function->signature->extendedAttributes->{"ImplementedAs"};
3572     }
3573
3574     my $index = 0;
3575     my $hasScriptState = 0;
3576
3577     my @arguments;
3578     my $functionName;
3579     my $implementedBy = $function->signature->extendedAttributes->{"ImplementedBy"};
3580     if ($implementedBy) {
3581         AddToImplIncludes("${implementedBy}.h");
3582         unshift(@arguments, "imp") if !$function->isStatic;
3583         $functionName = "${implementedBy}::${name}";
3584     } elsif ($function->isStatic) {
3585         $functionName = "${interfaceName}::${name}";
3586     } else {
3587         $functionName = "imp->${name}";
3588     }
3589
3590     my $callWith = $function->signature->extendedAttributes->{"CallWith"};
3591     my @callWithOutput = ();
3592     my @callWithArgs = GenerateCallWith($callWith, \@callWithOutput, $indent, 0, 1, $function);
3593     $result .= join("", @callWithOutput);
3594     unshift(@arguments, @callWithArgs);
3595     $index += @callWithArgs;
3596     $numberOfParameters += @callWithArgs;
3597
3598     foreach my $parameter (@{$function->parameters}) {
3599         if ($index eq $numberOfParameters) {
3600             last;
3601         }
3602         my $paramName = $parameter->name;
3603         my $paramType = $parameter->type;
3604
3605         if ($replacements{$paramName}) {
3606             push @arguments, $replacements{$paramName};
3607         } elsif ($parameter->type eq "IDBKey" || $parameter->type eq "NodeFilter" || $parameter->type eq "XPathNSResolver") {
3608             push @arguments, "$paramName.get()";
3609         } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($parameter->type) and not $interfaceName =~ /List$/) {
3610             push @arguments, "$paramName->propertyReference()";
3611             $result .= $indent . "if (!$paramName)\n";
3612             $result .= $indent . "    return setDOMException(WebCore::TYPE_MISMATCH_ERR, args.GetIsolate());\n";
3613         } elsif ($parameter->type eq "SVGMatrix" and $interfaceName eq "SVGTransformList") {
3614             push @arguments, "$paramName.get()";
3615         } else {
3616             push @arguments, $paramName;
3617         }
3618         $index++;
3619     }
3620
3621     if (@{$function->raisesExceptions}) {
3622         push @arguments, "ec";
3623     }
3624
3625     my $functionString = "$functionName(" . join(", ", @arguments) . ")";
3626
3627     my $return = "result";
3628     my $returnIsRef = IsRefPtrType($returnType);
3629
3630     if ($returnType eq "void") {
3631         $result .= $indent . "$functionString;\n";
3632     } elsif ($codeGenerator->ExtendedAttributeContains($callWith, "ScriptState") or @{$function->raisesExceptions}) {
3633         $result .= $indent . $nativeReturnType . " result = $functionString;\n";
3634     } else {
3635         # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
3636         $return = $functionString;
3637         $returnIsRef = 0;
3638
3639         if ($interfaceName eq "SVGTransformList" and IsRefPtrType($returnType)) {
3640             $return = "WTF::getPtr(" . $return . ")";
3641         }
3642     }
3643
3644     if (@{$function->raisesExceptions}) {
3645         $result .= $indent . "if (UNLIKELY(ec))\n";
3646         $result .= $indent . "    goto fail;\n";
3647     }
3648
3649     if ($codeGenerator->ExtendedAttributeContains($callWith, "ScriptState")) {
3650         $result .= $indent . "if (state.hadException())\n";
3651         $result .= $indent . "    return throwError(state.exception(), args.GetIsolate());\n"
3652     }
3653
3654     if ($isSVGTearOffType) {
3655         AddToImplIncludes("V8$returnType.h");
3656         AddToImplIncludes("SVGPropertyTearOff.h");
3657         my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($returnType);
3658         $result .= $indent . "return toV8(WTF::getPtr(${svgNativeType}::create($return)), args.Holder(), args.GetIsolate());\n";
3659         return $result;
3660     }
3661
3662     # If the implementing class is a POD type, commit changes
3663     if ($codeGenerator->IsSVGTypeNeedingTearOff($interfaceName) and not $interfaceName =~ /List$/) {
3664         $result .= $indent . "wrapper->commitChange();\n";
3665     }
3666
3667     $return .= ".release()" if ($returnIsRef);
3668     $result .= $indent . ReturnNativeToJSValue($function->signature, $return, "args.Holder()", "args.GetIsolate()") . ";\n";
3669
3670     return $result;
3671 }
3672
3673
3674 sub GetTypeFromSignature
3675 {
3676     my $signature = shift;
3677
3678     return $codeGenerator->StripModule($signature->type);
3679 }
3680
3681
3682 sub GetNativeTypeFromSignature
3683 {
3684     my $signature = shift;
3685     my $parameterIndex = shift;
3686
3687     my $type = GetTypeFromSignature($signature);
3688
3689     if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) {
3690         # Special-case index arguments because we need to check that they aren't < 0.
3691         return "int";
3692     }
3693
3694     $type = GetNativeType($type, $parameterIndex >= 0 ? 1 : 0);
3695
3696     if ($parameterIndex >= 0 && $type eq "V8Parameter") {
3697         # FIXME: This implements [TreatNullAs=NullString] and [TreatUndefinedAs=NullString],
3698         # but the Web IDL spec requires [TreatNullAs=EmptyString] and [TreatUndefinedAs=EmptyString].
3699         my $mode = "";
3700         if (($signature->extendedAttributes->{"TreatNullAs"} and $signature->extendedAttributes->{"TreatNullAs"} eq "NullString") and ($signature->extendedAttributes->{"TreatUndefinedAs"} and $signature->extendedAttributes->{"TreatUndefinedAs"} eq "NullString")) {
3701             $mode = "WithUndefinedOrNullCheck";
3702         } elsif (($signature->extendedAttributes->{"TreatNullAs"} and $signature->extendedAttributes->{"TreatNullAs"} eq "NullString") or $signature->extendedAttributes->{"Reflect"}) {
3703             $mode = "WithNullCheck";
3704         }
3705         # FIXME: Add the case for 'elsif ($signature->extendedAttributes->{"TreatUndefinedAs"} and $signature->extendedAttributes->{"TreatUndefinedAs"} eq "NullString"))'.
3706         $type .= "<$mode>";
3707     }
3708
3709     return $type;
3710 }
3711