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