[V8] Add an optional Isolate parameter to GetTemplate() and GetRawTemplate()
[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(v8::Isolate*);
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(v8::Isolate* = 0);
359     static v8::Persistent<v8::FunctionTemplate> GetTemplate(v8::Isolate* = 0);
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(v8::Isolate* isolate)
2172 {
2173     if (!isolate)
2174         isolate = v8::Isolate::GetCurrent();
2175     static v8::Persistent<v8::FunctionTemplate> cachedTemplate;
2176     if (!cachedTemplate.IsEmpty())
2177         return cachedTemplate;
2178
2179     v8::HandleScope scope;
2180     v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(${v8InterfaceName}ConstructorCallback);
2181
2182     v8::Local<v8::ObjectTemplate> instance = result->InstanceTemplate();
2183     instance->SetInternalFieldCount(${v8InterfaceName}::internalFieldCount);
2184     result->SetClassName(v8::String::NewSymbol("${interfaceName}"));
2185     result->Inherit(${v8InterfaceName}::GetTemplate());
2186
2187     cachedTemplate = v8::Persistent<v8::FunctionTemplate>::New(result);
2188     return cachedTemplate;
2189 }
2190
2191 END
2192 }
2193
2194 sub GenerateConstructorHeader
2195 {
2196     my $content = <<END;
2197     if (!args.IsConstructCall())
2198         return throwTypeError("DOM object constructor cannot be called as a function.", args.GetIsolate());
2199
2200     if (ConstructorMode::current() == ConstructorMode::WrapExistingObject)
2201         return args.Holder();
2202 END
2203     return $content;
2204 }
2205
2206 sub GenerateBatchedAttributeData
2207 {
2208     my $interface = shift;
2209     my $attributes = shift;
2210     my $interfaceName = $interface->name;
2211
2212     foreach my $attribute (@$attributes) {
2213         my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
2214         push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
2215         GenerateSingleBatchedAttribute($interfaceName, $attribute, ",", "");
2216         push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
2217     }
2218 }
2219
2220 sub GenerateSingleBatchedAttribute
2221 {
2222     my $interfaceName = shift;
2223     my $attribute = shift;
2224     my $delimiter = shift;
2225     my $indent = shift;
2226     my $attrName = $attribute->signature->name;
2227     my $attrExt = $attribute->signature->extendedAttributes;
2228
2229     my $accessControl = "v8::DEFAULT";
2230     if ($attrExt->{"DoNotCheckSecurityOnGetter"}) {
2231         $accessControl = "v8::ALL_CAN_READ";
2232     } elsif ($attrExt->{"DoNotCheckSecurityOnSetter"}) {
2233         $accessControl = "v8::ALL_CAN_WRITE";
2234     } elsif ($attrExt->{"DoNotCheckSecurity"}) {
2235         $accessControl = "v8::ALL_CAN_READ";
2236         if (!IsReadonly($attribute)) {
2237             $accessControl .= " | v8::ALL_CAN_WRITE";
2238         }
2239     }
2240     if ($attrExt->{"V8Unforgeable"}) {
2241         $accessControl .= " | v8::PROHIBITS_OVERWRITING";
2242     }
2243     $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")";
2244
2245     my $customAccessor =
2246         $attrExt->{"Custom"} ||
2247         $attrExt->{"CustomSetter"} ||
2248         $attrExt->{"CustomGetter"} ||
2249         $attrExt->{"V8Custom"} ||
2250         $attrExt->{"V8CustomSetter"} ||
2251         $attrExt->{"V8CustomGetter"} ||
2252         "";
2253     if ($customAccessor eq "VALUE_IS_MISSING") {
2254         # use the naming convension, interface + (capitalize) attr name
2255         $customAccessor = $interfaceName . "::" . $attrName;
2256     }
2257
2258     my $getter;
2259     my $setter;
2260     my $propAttr = "v8::None";
2261
2262     # Check attributes.
2263     if ($attrExt->{"NotEnumerable"}) {
2264         $propAttr .= " | v8::DontEnum";
2265     }
2266     if ($attrExt->{"V8Unforgeable"}) {
2267         $propAttr .= " | v8::DontDelete";
2268     }
2269
2270     my $on_proto = "0 /* on instance */";
2271     my $data = "0 /* no data */";
2272
2273     # Constructor
2274     if ($attribute->signature->type =~ /Constructor$/) {
2275         my $constructorType = $attribute->signature->type;
2276         $constructorType =~ s/Constructor$//;
2277         # $constructorType ~= /Constructor$/ indicates that it is NamedConstructor.
2278         # We do not generate the header file for NamedConstructor of class XXXX,
2279         # since we generate the NamedConstructor declaration into the header file of class XXXX.
2280         if ($constructorType !~ /Constructor$/ || $attribute->signature->extendedAttributes->{"V8CustomConstructor"} || $attribute->signature->extendedAttributes->{"CustomConstructor"}) {
2281             AddToImplIncludes("V8${constructorType}.h", $attribute->signature->extendedAttributes->{"Conditional"});
2282         }
2283         if ($customAccessor) {
2284             $getter = "V8${customAccessor}AccessorGetter";
2285         } else {
2286             $data = "&V8${constructorType}::info";
2287             $getter = "${interfaceName}V8Internal::${interfaceName}ConstructorGetter";
2288         }
2289         $setter = "${interfaceName}V8Internal::${interfaceName}ReplaceableAttrSetter";
2290     } else {
2291         # Default Getter and Setter
2292         $getter = "${interfaceName}V8Internal::${attrName}AttrGetter";
2293         $setter = "${interfaceName}V8Internal::${attrName}AttrSetter";
2294
2295         if ($attrExt->{"Replaceable"}) {
2296             $setter = "${interfaceName}V8Internal::${interfaceName}ReplaceableAttrSetter";
2297         }
2298
2299         # Custom Setter
2300         if ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
2301             $setter = "V8${customAccessor}AccessorSetter";
2302         }
2303
2304         # Custom Getter
2305         if ($attrExt->{"CustomGetter"} || $attrExt->{"V8CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
2306             $getter = "V8${customAccessor}AccessorGetter";
2307         }
2308     }
2309
2310     # Read only attributes
2311     if (IsReadonly($attribute)) {
2312         $setter = "0";
2313     }
2314
2315     # An accessor can be installed on the proto
2316     if ($attrExt->{"V8OnProto"}) {
2317         $on_proto = "1 /* on proto */";
2318     }
2319
2320     my $commentInfo = "Attribute '$attrName' (Type: '" . $attribute->type .
2321                       "' ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
2322
2323     push(@implContent, $indent . "    \/\/ $commentInfo\n");
2324     push(@implContent, $indent . "    {\"$attrName\", $getter, $setter, $data, $accessControl, static_cast<v8::PropertyAttribute>($propAttr), $on_proto}" . $delimiter . "\n");
2325 }
2326
2327 sub IsStandardFunction
2328 {
2329     my $interface = shift;
2330     my $function = shift;
2331
2332     my $interfaceName = $interface->name;
2333     my $attrExt = $function->signature->extendedAttributes;
2334     return 0 if $attrExt->{"V8Unforgeable"};
2335     return 0 if $function->isStatic;
2336     return 0 if $attrExt->{"V8EnabledAtRuntime"};
2337     return 0 if $attrExt->{"V8EnabledPerContext"};
2338     return 0 if RequiresCustomSignature($function);
2339     return 0 if $attrExt->{"V8DoNotCheckSignature"};
2340     return 0 if ($attrExt->{"DoNotCheckSecurity"} && ($interface->extendedAttributes->{"CheckSecurity"} || $interfaceName eq "DOMWindow"));
2341     return 0 if $attrExt->{"NotEnumerable"};
2342     return 0 if $attrExt->{"V8ReadOnly"};
2343     return 1;
2344 }
2345
2346 sub GenerateNonStandardFunction
2347 {
2348     my $interface = shift;
2349     my $function = shift;
2350
2351     my $interfaceName = $interface->name;
2352     my $attrExt = $function->signature->extendedAttributes;
2353     my $name = $function->signature->name;
2354
2355     my $property_attributes = "v8::DontDelete";
2356     if ($attrExt->{"NotEnumerable"}) {
2357         $property_attributes .= " | v8::DontEnum";
2358     }
2359     if ($attrExt->{"V8ReadOnly"}) {
2360         $property_attributes .= " | v8::ReadOnly";
2361     }
2362
2363     my $commentInfo = "Function '$name' (ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
2364
2365     my $template = "proto";
2366     if ($attrExt->{"V8Unforgeable"}) {
2367         $template = "instance";
2368     }
2369     if ($function->isStatic) {
2370         $template = "desc";
2371     }
2372
2373     my $conditional = "";
2374     if ($attrExt->{"V8EnabledAtRuntime"}) {
2375         # Only call Set()/SetAccessor() if this method should be enabled
2376         my $enable_function = GetRuntimeEnableFunctionName($function->signature);
2377         $conditional = "if (${enable_function}())\n        ";
2378     }
2379     if ($attrExt->{"V8EnabledPerContext"}) {
2380         # Only call Set()/SetAccessor() if this method should be enabled
2381         my $enable_function = GetContextEnableFunction($function->signature);
2382         $conditional = "if (${enable_function}(impl->document()))\n        ";
2383     }
2384
2385     if ($attrExt->{"DoNotCheckSecurity"} &&
2386         ($interface->extendedAttributes->{"CheckSecurity"} || $interfaceName eq "DOMWindow")) {
2387         # Functions that are marked DoNotCheckSecurity are always readable but if they are changed
2388         # and then accessed on a different domain we do not return the underlying value but instead
2389         # return a new copy of the original function. This is achieved by storing the changed value
2390         # as hidden property.
2391         push(@implContent, <<END);
2392
2393     // $commentInfo
2394     ${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));
2395 END
2396         return;
2397     }
2398
2399     my $signature = "defaultSignature";
2400     if ($attrExt->{"V8DoNotCheckSignature"} || $function->isStatic) {
2401        $signature = "v8::Local<v8::Signature>()";
2402     }
2403
2404     if (RequiresCustomSignature($function)) {
2405         $signature = "${name}Signature";
2406         push(@implContent, "\n    // Custom Signature '$name'\n", CreateCustomSignature($function));
2407     }
2408
2409     # Normal function call is a template
2410     my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
2411
2412     if ($property_attributes eq "v8::DontDelete") {
2413         $property_attributes = "";
2414     } else {
2415         $property_attributes = ", static_cast<v8::PropertyAttribute>($property_attributes)";
2416     }
2417
2418     if ($template eq "proto" && $conditional eq "" && $signature eq "defaultSignature" && $property_attributes eq "") {
2419         die "This shouldn't happen: Intraface '$interfaceName' $commentInfo\n";
2420     }
2421
2422     my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
2423     push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
2424
2425     push(@implContent, "    ${conditional}$template->Set(v8::String::NewSymbol(\"$name\"), v8::FunctionTemplate::New($callback, v8Undefined(), ${signature})$property_attributes);\n");
2426
2427     push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
2428 }
2429
2430 sub GenerateImplementationIndexer
2431 {
2432     my $interface = shift;
2433     my $indexer = shift;
2434     my $interfaceName = $interface->name;
2435     my $v8InterfaceName = "V8$interfaceName";
2436
2437     # FIXME: Figure out what NumericIndexedGetter is really supposed to do. Right now, it's only set on WebGL-related files.
2438     my $hasCustomSetter = $interface->extendedAttributes->{"CustomIndexedSetter"} && !$interface->extendedAttributes->{"NumericIndexedGetter"};
2439     my $hasGetter = $interface->extendedAttributes->{"IndexedGetter"} || $interface->extendedAttributes->{"CustomGetOwnPropertySlot"};
2440
2441     # FIXME: Investigate and remove this nastinesss. In V8, named property handling and indexer handling are apparently decoupled,
2442     # which means that object[X] where X is a number doesn't reach named property indexer. So we need to provide
2443     # simplistic, mirrored indexer handling in addition to named property handling.
2444     my $isSpecialCase = exists $indexerSpecialCases{$interfaceName};
2445     if ($isSpecialCase) {
2446         $hasGetter = 1;
2447         if ($interface->extendedAttributes->{"CustomNamedSetter"}) {
2448             $hasCustomSetter = 1;
2449         }
2450     }
2451
2452     my $hasEnumerator = !$isSpecialCase && $codeGenerator->IsSubType($interface, "Node");
2453
2454     # FIXME: Find a way to not have to special-case HTMLOptionsCollection.
2455     if ($interfaceName eq "HTMLOptionsCollection") {
2456         $hasEnumerator = 1;
2457         $hasGetter = 1;
2458     }
2459
2460     if (!$hasGetter) {
2461         return;
2462     }
2463
2464     AddToImplIncludes("V8Collection.h");
2465
2466     if (!$indexer) {
2467         $indexer = $codeGenerator->FindSuperMethod($interface, "item");
2468     }
2469
2470     my $indexerType = $indexer ? $indexer->type : 0;
2471
2472     # FIXME: Remove this once toV8 helper methods are implemented (see https://bugs.webkit.org/show_bug.cgi?id=32563).
2473     if ($interfaceName eq "WebKitCSSKeyframesRule") {
2474         $indexerType = "WebKitCSSKeyframeRule";
2475     }
2476
2477     if ($indexerType && !$hasCustomSetter) {
2478         if ($indexerType eq "DOMString") {
2479             my $conversion = $indexer->extendedAttributes->{"TreatReturnedNullStringAs"};
2480             if ($conversion && $conversion eq "Null") {
2481                 push(@implContent, <<END);
2482     setCollectionStringOrUndefinedIndexedGetter<${interfaceName}>(desc);
2483 END
2484             } else {
2485                 push(@implContent, <<END);
2486     setCollectionStringIndexedGetter<${interfaceName}>(desc);
2487 END
2488             }
2489         } else {
2490             push(@implContent, <<END);
2491     setCollectionIndexedGetter<${interfaceName}, ${indexerType}>(desc);
2492 END
2493             # Include the header for this indexer type, because setCollectionIndexedGetter() requires toV8() for this type.
2494             AddToImplIncludes("V8${indexerType}.h");
2495         }
2496
2497         return;
2498     }
2499
2500     my $hasDeleter = $interface->extendedAttributes->{"CustomDeleteProperty"};
2501     my $setOn = "Instance";
2502
2503     # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
2504     # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
2505     # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
2506     # on the object.
2507     if ($interfaceName eq "DOMWindow") {
2508         $setOn = "Prototype";
2509         $hasDeleter = 0;
2510     }
2511
2512     push(@implContent, "    desc->${setOn}Template()->SetIndexedPropertyHandler(${v8InterfaceName}::indexedPropertyGetter");
2513     push(@implContent, $hasCustomSetter ? ", ${v8InterfaceName}::indexedPropertySetter" : ", 0");
2514     push(@implContent, ", 0"); # IndexedPropertyQuery -- not being used at the moment.
2515     push(@implContent, $hasDeleter ? ", ${v8InterfaceName}::indexedPropertyDeleter" : ", 0");
2516     push(@implContent, ", nodeCollectionIndexedPropertyEnumerator<${interfaceName}>") if $hasEnumerator;
2517     push(@implContent, ");\n");
2518 }
2519
2520 sub GenerateImplementationNamedPropertyGetter
2521 {
2522     my $interface = shift;
2523     my $namedPropertyGetter = shift;
2524     my $interfaceName = $interface->name;
2525     my $v8InterfaceName = "V8$interfaceName";
2526     my $hasCustomNamedGetter = $interface->extendedAttributes->{"CustomNamedGetter"} || $interface->extendedAttributes->{"CustomGetOwnPropertySlot"};
2527
2528     if ($interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") {
2529         $hasCustomNamedGetter = 1;
2530     }
2531
2532     if ($interfaceName eq "HTMLDocument") {
2533         $hasCustomNamedGetter = 0;
2534     }
2535
2536     my $hasGetter = $interface->extendedAttributes->{"NamedGetter"} || $hasCustomNamedGetter;
2537     if (!$hasGetter) {
2538         return;
2539     }
2540
2541     if (!$namedPropertyGetter) {
2542         $namedPropertyGetter = $codeGenerator->FindSuperMethod($interface, "namedItem");
2543     }
2544
2545     if ($namedPropertyGetter && $namedPropertyGetter->type ne "Node" && !$namedPropertyGetter->extendedAttributes->{"Custom"} && !$hasCustomNamedGetter) {
2546         AddToImplIncludes("V8Collection.h");
2547         my $type = $namedPropertyGetter->type;
2548         push(@implContent, <<END);
2549     setCollectionNamedGetter<${interfaceName}, ${type}>(desc);
2550 END
2551         return;
2552     }
2553
2554     my $hasCustomNamedSetter = $interface->extendedAttributes->{"CustomNamedSetter"};
2555     my $hasDeleter = $interface->extendedAttributes->{"CustomDeleteProperty"};
2556     my $hasEnumerator = $interface->extendedAttributes->{"CustomEnumerateProperty"};
2557     my $setOn = "Instance";
2558
2559     # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
2560     # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
2561     # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
2562     # on the object.
2563     if ($interfaceName eq "DOMWindow") {
2564         $setOn = "Prototype";
2565         $hasDeleter = 0;
2566         $hasEnumerator = 0;
2567     }
2568
2569     if ($interfaceName eq "HTMLPropertiesCollection") {
2570         push(@implContent, "    desc->${setOn}Template()->SetNamedPropertyHandler(V8HTMLCollection::namedPropertyGetter, ");
2571     } else {
2572         push(@implContent, "    desc->${setOn}Template()->SetNamedPropertyHandler(${v8InterfaceName}::namedPropertyGetter, ");
2573     }
2574     push(@implContent, $hasCustomNamedSetter ? "${v8InterfaceName}::namedPropertySetter, " : "0, ");
2575     # If there is a custom enumerator, there MUST be custom query to properly communicate property attributes.
2576     push(@implContent, $hasEnumerator ? "${v8InterfaceName}::namedPropertyQuery, " : "0, ");
2577     push(@implContent, $hasDeleter ? "${v8InterfaceName}::namedPropertyDeleter, " : "0, ");
2578     push(@implContent, $hasEnumerator ? "${v8InterfaceName}::namedPropertyEnumerator" : "0");
2579     push(@implContent, ");\n");
2580 }
2581
2582 sub GenerateImplementationCustomCall
2583 {
2584     my $interface = shift;
2585     my $interfaceName = $interface->name;
2586
2587     if ($interface->extendedAttributes->{"CustomCall"}) {
2588         push(@implContent, "    desc->InstanceTemplate()->SetCallAsFunctionHandler(V8${interfaceName}::callAsFunctionCallback);\n");
2589     }
2590 }
2591
2592 sub GenerateImplementationMasqueradesAsUndefined
2593 {
2594     my $interface = shift;
2595     if ($interface->extendedAttributes->{"MasqueradesAsUndefined"})
2596     {
2597         push(@implContent, "    desc->InstanceTemplate()->MarkAsUndetectable();\n");
2598     }
2599 }
2600
2601 sub GenerateImplementation
2602 {
2603     my $object = shift;
2604     my $interface = shift;
2605     my $interfaceName = $interface->name;
2606     my $visibleInterfaceName = $codeGenerator->GetVisibleInterfaceName($interface);
2607     my $v8InterfaceName = "V8$interfaceName";
2608     my $nativeType = GetNativeTypeForConversions($interface);
2609
2610     # - Add default header template
2611     push(@implContentHeader, GenerateImplementationContentHeader($interface));
2612
2613     AddToImplIncludes("BindingState.h");
2614     AddToImplIncludes("ContextFeatures.h");
2615     AddToImplIncludes("RuntimeEnabledFeatures.h");
2616     AddToImplIncludes("V8Binding.h");
2617     AddToImplIncludes("V8DOMWrapper.h");
2618
2619     AddIncludesForType($interfaceName);
2620
2621     my $toActive = $interface->extendedAttributes->{"ActiveDOMObject"} ? "${v8InterfaceName}::toActiveDOMObject" : "0";
2622     my $rootForGC = NeedsCustomOpaqueRootForGC($interface) ? "${v8InterfaceName}::opaqueRootForGC" : "0";
2623
2624     # Find the super descriptor.
2625     my $parentClass = "";
2626     my $parentClassTemplate = "";
2627     foreach (@{$interface->parents}) {
2628         my $parent = $_;
2629         AddToImplIncludes("V8${parent}.h");
2630         $parentClass = "V8" . $parent;
2631         $parentClassTemplate = $parentClass . "::GetTemplate()";
2632         last;
2633     }
2634     push(@implContentDecls, "namespace WebCore {\n\n");
2635     my $parentClassInfo = $parentClass ? "&${parentClass}::info" : "0";
2636
2637     my $WrapperTypePrototype = $interface->isException ? "WrapperTypeErrorPrototype" : "WrapperTypeObjectPrototype";
2638
2639     push(@implContentDecls, "WrapperTypeInfo ${v8InterfaceName}::info = { ${v8InterfaceName}::GetTemplate, ${v8InterfaceName}::derefObject, $toActive, $rootForGC, ${v8InterfaceName}::installPerContextPrototypeProperties, $parentClassInfo, $WrapperTypePrototype };\n\n");
2640     push(@implContentDecls, "namespace ${interfaceName}V8Internal {\n\n");
2641
2642     push(@implContentDecls, "template <typename T> void V8_USE(T) { }\n\n");
2643
2644     my $hasConstructors = 0;
2645     my $hasReplaceable = 0;
2646
2647     # Generate property accessors for attributes.
2648     for (my $index = 0; $index < @{$interface->attributes}; $index++) {
2649         my $attribute = @{$interface->attributes}[$index];
2650         my $attrType = $attribute->signature->type;
2651
2652         # Generate special code for the constructor attributes.
2653         if ($attrType =~ /Constructor$/) {
2654             if (!($attribute->signature->extendedAttributes->{"CustomGetter"} ||
2655                 $attribute->signature->extendedAttributes->{"V8CustomGetter"})) {
2656                 $hasConstructors = 1;
2657             }
2658             next;
2659         }
2660
2661         if ($attrType eq "EventListener" && $interfaceName eq "DOMWindow") {
2662             $attribute->signature->extendedAttributes->{"V8OnProto"} = 1;
2663         }
2664
2665         if ($attrType eq "SerializedScriptValue") {
2666             AddToImplIncludes("SerializedScriptValue.h");
2667         }
2668
2669         # Do not generate accessor if this is a custom attribute.  The
2670         # call will be forwarded to a hand-written accessor
2671         # implementation.
2672         if ($attribute->signature->extendedAttributes->{"Custom"} ||
2673             $attribute->signature->extendedAttributes->{"V8Custom"}) {
2674             next;
2675         }
2676
2677         # Generate the accessor.
2678         if (!($attribute->signature->extendedAttributes->{"CustomGetter"} ||
2679             $attribute->signature->extendedAttributes->{"V8CustomGetter"})) {
2680             GenerateNormalAttrGetter($attribute, $interface);
2681         }
2682
2683         if ($attribute->signature->extendedAttributes->{"Replaceable"}) {
2684             $hasReplaceable = 1;
2685         } elsif (!$attribute->signature->extendedAttributes->{"CustomSetter"} &&
2686             !$attribute->signature->extendedAttributes->{"V8CustomSetter"} &&
2687             !IsReadonly($attribute)) {
2688             GenerateNormalAttrSetter($attribute, $interface);
2689         }
2690     }
2691
2692     if ($hasConstructors) {
2693         GenerateConstructorGetter($interface);
2694     }
2695
2696     if ($hasConstructors || $hasReplaceable) {
2697         GenerateReplaceableAttrSetter($interface);
2698     }
2699
2700     if (NeedsCustomOpaqueRootForGC($interface)) {
2701         GenerateOpaqueRootForGC($interface);
2702     }
2703
2704     if ($interface->extendedAttributes->{"TypedArray"}) {
2705         my $viewType = GetTypeNameOfExternalTypedArray($interface);
2706         push(@implContent, <<END);
2707 v8::Handle<v8::Object> wrap($interfaceName* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
2708 {
2709     ASSERT(impl);
2710     v8::Handle<v8::Object> wrapper = ${v8InterfaceName}::createWrapper(impl, creationContext, isolate);
2711     if (!wrapper.IsEmpty())
2712         wrapper->SetIndexedPropertiesToExternalArrayData(impl->baseAddress(), $viewType, impl->length());
2713     return wrapper;
2714 }
2715
2716 END
2717     }
2718
2719     my $indexer;
2720     my $namedPropertyGetter;
2721     my @enabledPerContextFunctions;
2722     my @normalFunctions;
2723     my $needsDomainSafeFunctionSetter = 0;
2724     # Generate methods for functions.
2725     foreach my $function (@{$interface->functions}) {
2726         my $isCustom = $function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"V8Custom"};
2727         if (!$isCustom) {
2728             GenerateFunctionCallback($function, $interface);
2729             if ($function->{overloadIndex} > 1 && $function->{overloadIndex} == @{$function->{overloads}}) {
2730                 GenerateOverloadedFunctionCallback($function, $interface);
2731             }
2732         }
2733
2734         if ($function->signature->name eq "item") {
2735             $indexer = $function->signature;
2736         }
2737
2738         if ($interfaceName eq "HTMLPropertiesCollection") {
2739             if ($function->signature->name eq "propertyNodeList") {
2740                 $namedPropertyGetter = $function->signature;
2741             }
2742         } elsif ($function->signature->name eq "namedItem") {
2743             $namedPropertyGetter = $function->signature;
2744         }
2745
2746         # If the function does not need domain security check, we need to
2747         # generate an access getter that returns different function objects
2748         # for different calling context.
2749         if (($interface->extendedAttributes->{"CheckSecurity"} || ($interfaceName eq "DOMWindow")) && $function->signature->extendedAttributes->{"DoNotCheckSecurity"}) {
2750             if (!$isCustom || $function->{overloadIndex} == 1) {
2751                 GenerateDomainSafeFunctionGetter($function, $interfaceName);
2752                 $needsDomainSafeFunctionSetter = 1;
2753             }
2754         }
2755
2756         # Separate out functions that are enabled per context so we can process them specially.
2757         if ($function->signature->extendedAttributes->{"V8EnabledPerContext"}) {
2758             push(@enabledPerContextFunctions, $function);
2759         } else {
2760             push(@normalFunctions, $function);
2761         }
2762     }
2763
2764     if ($needsDomainSafeFunctionSetter) {
2765         GenerateDomainSafeFunctionSetter($interfaceName);
2766     }
2767
2768     # Attributes
2769     my $attributes = $interface->attributes;
2770
2771     # For the DOMWindow interface we partition the attributes into the
2772     # ones that disallows shadowing and the rest.
2773     my @disallowsShadowing;
2774     # Also separate out attributes that are enabled at runtime so we can process them specially.
2775     my @enabledAtRuntimeAttributes;
2776     my @enabledPerContextAttributes;
2777     my @normalAttributes;
2778     foreach my $attribute (@$attributes) {
2779
2780         if ($interfaceName eq "DOMWindow" && $attribute->signature->extendedAttributes->{"V8Unforgeable"}) {
2781             push(@disallowsShadowing, $attribute);
2782         } elsif ($attribute->signature->extendedAttributes->{"V8EnabledAtRuntime"}) {
2783             push(@enabledAtRuntimeAttributes, $attribute);
2784         } elsif ($attribute->signature->extendedAttributes->{"V8EnabledPerContext"}) {
2785             push(@enabledPerContextAttributes, $attribute);
2786         } else {
2787             push(@normalAttributes, $attribute);
2788         }
2789     }
2790     $attributes = \@normalAttributes;
2791     # Put the attributes that disallow shadowing on the shadow object.
2792     if (@disallowsShadowing) {
2793         push(@implContent, "static const V8DOMConfiguration::BatchedAttribute shadowAttrs[] = {\n");
2794         GenerateBatchedAttributeData($interface, \@disallowsShadowing);
2795         push(@implContent, "};\n\n");
2796     }
2797
2798     my $has_attributes = 0;
2799     if (@$attributes) {
2800         $has_attributes = 1;
2801         push(@implContent, "static const V8DOMConfiguration::BatchedAttribute ${v8InterfaceName}Attrs[] = {\n");
2802         GenerateBatchedAttributeData($interface, $attributes);
2803         push(@implContent, "};\n\n");
2804     }
2805
2806     # Setup table of standard callback functions
2807     my $num_callbacks = 0;
2808     my $has_callbacks = 0;
2809     foreach my $function (@normalFunctions) {
2810         # Only one table entry is needed for overloaded methods:
2811         next if $function->{overloadIndex} > 1;
2812         # Don't put any nonstandard functions into this table:
2813         next if !IsStandardFunction($interface, $function);
2814         if (!$has_callbacks) {
2815             $has_callbacks = 1;
2816             push(@implContent, "static const V8DOMConfiguration::BatchedCallback ${v8InterfaceName}Callbacks[] = {\n");
2817         }
2818         my $name = $function->signature->name;
2819         my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
2820         my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
2821         push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
2822         push(@implContent, <<END);
2823     {"$name", $callback},
2824 END
2825         push(@implContent, "#endif\n") if $conditionalString;
2826         $num_callbacks++;
2827     }
2828     push(@implContent, "};\n\n")  if $has_callbacks;
2829
2830     # Setup constants
2831     my $has_constants = 0;
2832     my @constantsEnabledAtRuntime;
2833     if (@{$interface->constants}) {
2834         $has_constants = 1;
2835         push(@implContent, "static const V8DOMConfiguration::BatchedConstant ${v8InterfaceName}Consts[] = {\n");
2836     }
2837     foreach my $constant (@{$interface->constants}) {
2838         my $name = $constant->name;
2839         my $value = $constant->value;
2840         my $attrExt = $constant->extendedAttributes;
2841         my $conditional = $attrExt->{"Conditional"};
2842         my $implementedBy = $attrExt->{"ImplementedBy"};
2843         if ($implementedBy) {
2844             AddToImplIncludes("${implementedBy}.h");
2845         }
2846         if ($attrExt->{"V8EnabledAtRuntime"}) {
2847             push(@constantsEnabledAtRuntime, $constant);
2848         } else {
2849             # FIXME: we need the static_cast here only because of one constant, NodeFilter.idl
2850             # defines "const unsigned long SHOW_ALL = 0xFFFFFFFF".  It would be better if we
2851             # handled this here, and converted it to a -1 constant in the c++ output.
2852             if ($conditional) {
2853                 my $conditionalString = $codeGenerator->GenerateConditionalStringFromAttributeValue($conditional);
2854                 push(@implContent, "#if ${conditionalString}\n");
2855             }
2856             push(@implContent, <<END);
2857     {"${name}", static_cast<signed int>($value)},
2858 END
2859             push(@implContent, "#endif\n") if $conditional;
2860         }
2861     }
2862     if ($has_constants) {
2863         push(@implContent, "};\n\n");
2864         push(@implContent, $codeGenerator->GenerateCompileTimeCheckForEnumsIfNeeded($interface));
2865     }
2866
2867     push(@implContentDecls, "} // namespace ${interfaceName}V8Internal\n\n");
2868
2869     if (HasCustomConstructor($interface)) {
2870         GenerateCustomConstructorCallback($interface);
2871     } elsif ($interface->extendedAttributes->{"NamedConstructor"}) {
2872         GenerateNamedConstructorCallback(@{$interface->constructors}[0], $interface);
2873     } elsif ($interface->extendedAttributes->{"Constructor"}) {
2874         GenerateConstructorCallback($interface);
2875     } elsif ($codeGenerator->IsConstructorTemplate($interface, "Event")) {
2876         GenerateEventConstructorCallback($interface);
2877     } elsif ($codeGenerator->IsConstructorTemplate($interface, "TypedArray")) {
2878         GenerateTypedArrayConstructorCallback($interface);
2879     }
2880
2881     my $access_check = "";
2882     if ($interface->extendedAttributes->{"CheckSecurity"} && !($interfaceName eq "DOMWindow")) {
2883         $access_check = "instance->SetAccessCheckCallbacks(${v8InterfaceName}::namedSecurityCheck, ${v8InterfaceName}::indexedSecurityCheck, v8::External::New(&${v8InterfaceName}::info));";
2884     }
2885
2886     # For the DOMWindow interface, generate the shadow object template
2887     # configuration method.
2888     if ($interfaceName eq "DOMWindow") {
2889         push(@implContent, <<END);
2890 static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Persistent<v8::ObjectTemplate> templ)
2891 {
2892     V8DOMConfiguration::batchConfigureAttributes(templ, v8::Handle<v8::ObjectTemplate>(), shadowAttrs, WTF_ARRAY_LENGTH(shadowAttrs));
2893
2894     // Install a security handler with V8.
2895     templ->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::External::New(&V8DOMWindow::info));
2896     templ->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
2897     return templ;
2898 }
2899 END
2900     }
2901
2902     if (!$parentClassTemplate) {
2903         $parentClassTemplate = "v8::Persistent<v8::FunctionTemplate>()";
2904     }
2905
2906     # Generate the template configuration method
2907     push(@implContent,  <<END);
2908 static v8::Persistent<v8::FunctionTemplate> Configure${v8InterfaceName}Template(v8::Persistent<v8::FunctionTemplate> desc)
2909 {
2910     desc->ReadOnlyPrototype();
2911
2912     v8::Local<v8::Signature> defaultSignature;
2913 END
2914     if ($interface->extendedAttributes->{"V8EnabledAtRuntime"}) {
2915         my $enable_function = GetRuntimeEnableFunctionName($interface);
2916         push(@implContent, <<END);
2917     if (!${enable_function}())
2918         defaultSignature = V8DOMConfiguration::configureTemplate(desc, \"\", $parentClassTemplate, ${v8InterfaceName}::internalFieldCount, 0, 0, 0, 0);
2919     else
2920 END
2921     }
2922     push(@implContent,  <<END);
2923     defaultSignature = V8DOMConfiguration::configureTemplate(desc, \"${visibleInterfaceName}\", $parentClassTemplate, ${v8InterfaceName}::internalFieldCount,
2924 END
2925     # Set up our attributes if we have them
2926     if ($has_attributes) {
2927         push(@implContent, <<END);
2928         ${v8InterfaceName}Attrs, WTF_ARRAY_LENGTH(${v8InterfaceName}Attrs),
2929 END
2930     } else {
2931         push(@implContent, <<END);
2932         0, 0,
2933 END
2934     }
2935
2936     if ($has_callbacks) {
2937         push(@implContent, <<END);
2938         ${v8InterfaceName}Callbacks, WTF_ARRAY_LENGTH(${v8InterfaceName}Callbacks));
2939 END
2940     } else {
2941         push(@implContent, <<END);
2942         0, 0);
2943 END
2944     }
2945     
2946     AddToImplIncludes("wtf/UnusedParam.h");
2947     push(@implContent, <<END);
2948     UNUSED_PARAM(defaultSignature); // In some cases, it will not be used.
2949 END
2950
2951     if (IsConstructable($interface)) {
2952         my $conditionalString = $codeGenerator->GenerateConstructorConditionalString($interface);
2953         push(@implContent, "#if $conditionalString\n") if $conditionalString;
2954         push(@implContent, "    desc->SetCallHandler(${v8InterfaceName}::constructorCallback);\n");
2955         push(@implContent, "#endif // $conditionalString\n") if $conditionalString;
2956     }
2957
2958     if ($access_check or @enabledAtRuntimeAttributes or @normalFunctions or $has_constants) {
2959         push(@implContent,  <<END);
2960     v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate();
2961     v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate();
2962     UNUSED_PARAM(instance); // In some cases, it will not be used.
2963     UNUSED_PARAM(proto); // In some cases, it will not be used.
2964 END
2965     }
2966
2967     push(@implContent,  "    $access_check\n");
2968
2969     # Setup the enable-at-runtime attrs if we have them
2970     foreach my $runtime_attr (@enabledAtRuntimeAttributes) {
2971         my $enable_function = GetRuntimeEnableFunctionName($runtime_attr->signature);
2972         my $conditionalString = $codeGenerator->GenerateConditionalString($runtime_attr->signature);
2973         push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
2974         push(@implContent, "    if (${enable_function}()) {\n");
2975         push(@implContent, "        static const V8DOMConfiguration::BatchedAttribute attrData =\\\n");
2976         GenerateSingleBatchedAttribute($interfaceName, $runtime_attr, ";", "    ");
2977         push(@implContent, <<END);
2978         V8DOMConfiguration::configureAttribute(instance, proto, attrData);
2979     }
2980 END
2981         push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
2982     }
2983
2984     # Setup the enable-at-runtime constants if we have them
2985     foreach my $runtime_const (@constantsEnabledAtRuntime) {
2986         my $enable_function = GetRuntimeEnableFunctionName($runtime_const);
2987         my $conditionalString = $codeGenerator->GenerateConditionalString($runtime_const);
2988         my $name = $runtime_const->name;
2989         my $value = $runtime_const->value;
2990         push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
2991         push(@implContent, "    if (${enable_function}()) {\n");
2992         push(@implContent, <<END);
2993         static const V8DOMConfiguration::BatchedConstant constData = {"${name}", static_cast<signed int>(${value})};
2994         V8DOMConfiguration::batchConfigureConstants(desc, proto, &constData, 1);
2995 END
2996         push(@implContent, "    }\n");
2997         push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
2998     }
2999
3000     GenerateImplementationIndexer($interface, $indexer);
3001     GenerateImplementationNamedPropertyGetter($interface, $namedPropertyGetter);
3002     GenerateImplementationCustomCall($interface);
3003     GenerateImplementationMasqueradesAsUndefined($interface);
3004
3005     # Define our functions with Set() or SetAccessor()
3006     my $total_functions = 0;
3007     foreach my $function (@normalFunctions) {
3008         # Only one accessor is needed for overloaded methods:
3009         next if $function->{overloadIndex} > 1;
3010
3011         $total_functions++;
3012         next if IsStandardFunction($interface, $function);
3013         GenerateNonStandardFunction($interface, $function);
3014         $num_callbacks++;
3015     }
3016
3017     die "Wrong number of callbacks generated for $interfaceName ($num_callbacks, should be $total_functions)" if $num_callbacks != $total_functions;
3018
3019     if ($has_constants) {
3020         push(@implContent, <<END);
3021     V8DOMConfiguration::batchConfigureConstants(desc, proto, ${v8InterfaceName}Consts, WTF_ARRAY_LENGTH(${v8InterfaceName}Consts));
3022 END
3023     }
3024
3025     # Special cases
3026     if ($interfaceName eq "DOMWindow") {
3027         push(@implContent, <<END);
3028
3029     proto->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
3030     desc->SetHiddenPrototype(true);
3031     instance->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
3032     // Set access check callbacks, but turned off initially.
3033     // When a context is detached from a frame, turn on the access check.
3034     // Turning on checks also invalidates inline caches of the object.
3035     instance->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::External::New(&V8DOMWindow::info), false);
3036 END
3037     }
3038     if ($interfaceName eq "HTMLDocument" or $interfaceName eq "DedicatedWorkerContext" or $interfaceName eq "SharedWorkerContext") {
3039         push(@implContent, <<END);
3040     desc->SetHiddenPrototype(true);
3041 END
3042     }
3043     if ($interfaceName eq "Location") {
3044         push(@implContent, <<END);
3045
3046     // For security reasons, these functions are on the instance instead
3047     // of on the prototype object to ensure that they cannot be overwritten.
3048     instance->SetAccessor(v8::String::NewSymbol("reload"), V8Location::reloadAccessorGetter, 0, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
3049     instance->SetAccessor(v8::String::NewSymbol("replace"), V8Location::replaceAccessorGetter, 0, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
3050     instance->SetAccessor(v8::String::NewSymbol("assign"), V8Location::assignAccessorGetter, 0, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
3051 END
3052     }
3053
3054     push(@implContent, <<END);
3055
3056     // Custom toString template
3057     desc->Set(v8::String::NewSymbol("toString"), V8PerIsolateData::current()->toStringTemplate());
3058     return desc;
3059 }
3060
3061 v8::Persistent<v8::FunctionTemplate> ${v8InterfaceName}::GetRawTemplate(v8::Isolate* isolate)
3062 {
3063     if (!isolate)
3064         isolate = v8::Isolate::GetCurrent();
3065     V8PerIsolateData* data = V8PerIsolateData::from(isolate);
3066     V8PerIsolateData::TemplateMap::iterator result = data->rawTemplateMap().find(&info);
3067     if (result != data->rawTemplateMap().end())
3068         return result->value;
3069
3070     v8::HandleScope handleScope;
3071     v8::Persistent<v8::FunctionTemplate> templ = createRawTemplate();
3072     data->rawTemplateMap().add(&info, templ);
3073     return templ;
3074 }
3075
3076 v8::Persistent<v8::FunctionTemplate> ${v8InterfaceName}::GetTemplate(v8::Isolate* isolate)
3077 {
3078     if (!isolate)
3079         isolate = v8::Isolate::GetCurrent();
3080     V8PerIsolateData* data = V8PerIsolateData::from(isolate);
3081     V8PerIsolateData::TemplateMap::iterator result = data->templateMap().find(&info);
3082     if (result != data->templateMap().end())
3083         return result->value;
3084
3085     v8::HandleScope handleScope;
3086     v8::Persistent<v8::FunctionTemplate> templ =
3087         Configure${v8InterfaceName}Template(GetRawTemplate());
3088     data->templateMap().add(&info, templ);
3089     return templ;
3090 }
3091
3092 bool ${v8InterfaceName}::HasInstance(v8::Handle<v8::Value> value)
3093 {
3094     return GetRawTemplate()->HasInstance(value);
3095 }
3096
3097 END
3098
3099     if (@enabledPerContextAttributes) {
3100         push(@implContent, <<END);
3101 void ${v8InterfaceName}::installPerContextProperties(v8::Handle<v8::Object> instance, ${nativeType}* impl)
3102 {
3103     v8::Local<v8::Object> proto = v8::Local<v8::Object>::Cast(instance->GetPrototype());
3104     // When building QtWebkit with V8 this variable is unused when none of the features are enabled.
3105     UNUSED_PARAM(proto);
3106 END
3107
3108         # Setup the enable-by-settings attrs if we have them
3109         foreach my $runtimeAttr (@enabledPerContextAttributes) {
3110             my $enableFunction = GetContextEnableFunction($runtimeAttr->signature);
3111             my $conditionalString = $codeGenerator->GenerateConditionalString($runtimeAttr->signature);
3112             push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
3113             push(@implContent, "    if (${enableFunction}(impl->document())) {\n");
3114             push(@implContent, "        static const V8DOMConfiguration::BatchedAttribute attrData =\\\n");
3115             GenerateSingleBatchedAttribute($interfaceName, $runtimeAttr, ";", "    ");
3116             push(@implContent, <<END);
3117         V8DOMConfiguration::configureAttribute(instance, proto, attrData);
3118 END
3119             push(@implContent, "    }\n");
3120             push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
3121         }
3122         push(@implContent, <<END);
3123 }
3124 END
3125     }
3126
3127     if (@enabledPerContextFunctions) {
3128         push(@implContent, <<END);
3129 void ${v8InterfaceName}::installPerContextPrototypeProperties(v8::Handle<v8::Object> proto)
3130 {
3131     UNUSED_PARAM(proto);
3132 END
3133         # Setup the enable-by-settings functions if we have them
3134         push(@implContent,  <<END);
3135     v8::Local<v8::Signature> defaultSignature = v8::Signature::New(GetTemplate());
3136     UNUSED_PARAM(defaultSignature); // In some cases, it will not be used.
3137
3138     ScriptExecutionContext* context = toScriptExecutionContext(proto->CreationContext());
3139 END
3140
3141         foreach my $runtimeFunc (@enabledPerContextFunctions) {
3142             my $enableFunction = GetContextEnableFunction($runtimeFunc->signature);
3143             my $conditionalString = $codeGenerator->GenerateConditionalString($runtimeFunc->signature);
3144             push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
3145             push(@implContent, "    if (context && context->isDocument() && ${enableFunction}(static_cast<Document*>(context))) {\n");
3146             my $name = $runtimeFunc->signature->name;
3147             my $callback = GetFunctionTemplateCallbackName($runtimeFunc, $interfaceName);
3148             push(@implContent, <<END);
3149         proto->Set(v8::String::NewSymbol("${name}"), v8::FunctionTemplate::New(${callback}, v8Undefined(), defaultSignature)->GetFunction());
3150 END
3151             push(@implContent, "    }\n");
3152             push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
3153         }
3154
3155         push(@implContent, <<END);
3156 }
3157 END
3158     }
3159
3160     if ($interface->extendedAttributes->{"ActiveDOMObject"}) {
3161         # MessagePort is handled like an active dom object even though it doesn't inherit
3162         # from ActiveDOMObject, so don't try to cast it to ActiveDOMObject.
3163         my $returnValue = $interfaceName eq "MessagePort" ? "0" : "toNative(object)";
3164         push(@implContent, <<END);
3165 ActiveDOMObject* ${v8InterfaceName}::toActiveDOMObject(v8::Handle<v8::Object> object)
3166 {
3167     return ${returnValue};
3168 }      
3169 END
3170     }
3171
3172     if ($interfaceName eq "DOMWindow") {
3173         push(@implContent, <<END);
3174 v8::Persistent<v8::ObjectTemplate> V8DOMWindow::GetShadowObjectTemplate()
3175 {
3176     static v8::Persistent<v8::ObjectTemplate> V8DOMWindowShadowObjectCache;
3177     if (V8DOMWindowShadowObjectCache.IsEmpty()) {
3178         V8DOMWindowShadowObjectCache = v8::Persistent<v8::ObjectTemplate>::New(v8::ObjectTemplate::New());
3179         ConfigureShadowObjectTemplate(V8DOMWindowShadowObjectCache);
3180     }
3181     return V8DOMWindowShadowObjectCache;
3182 }
3183 END
3184     }
3185
3186     GenerateToV8Converters($interface, $v8InterfaceName, $nativeType);
3187
3188     push(@implContent, <<END);
3189
3190 void ${v8InterfaceName}::derefObject(void* object)
3191 {
3192     static_cast<${nativeType}*>(object)->deref();
3193 }
3194
3195 } // namespace WebCore
3196 END
3197