Implement MouseEvent constructor
[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 ($codeGenerator->InheritsExtendedAttribute($interface, "EventTarget")) {
377         push(@headerContent, "    static EventTarget* toEventTarget(v8::Handle<v8::Object>);\n");
378     }
379
380     if ($interfaceName eq "DOMWindow") {
381         push(@headerContent, <<END);
382     static v8::Persistent<v8::ObjectTemplate> GetShadowObjectTemplate();
383 END
384     }
385
386     if ($interfaceName eq "HTMLDocument") {
387       push(@headerContent, <<END);
388     static v8::Local<v8::Object> wrapInShadowObject(v8::Local<v8::Object> wrapper, Node* impl);
389     static v8::Handle<v8::Value> getNamedProperty(HTMLDocument* htmlDocument, const AtomicString& key, v8::Handle<v8::Object> creationContext, v8::Isolate*);
390 END
391     }
392
393     my @enabledPerContextFunctions;
394     foreach my $function (@{$interface->functions}) {
395         my $name = $function->signature->name;
396         my $attrExt = $function->signature->extendedAttributes;
397
398         if (($attrExt->{"Custom"} || $attrExt->{"V8Custom"}) && !$attrExt->{"ImplementedBy"} && $function->{overloadIndex} == 1) {
399             my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
400             push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
401             push(@headerContent, <<END);
402     static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments&);
403 END
404             push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString;
405         }
406         if ($attrExt->{"V8EnabledPerContext"}) {
407             push(@enabledPerContextFunctions, $function);
408         }
409     }
410
411     if (IsConstructable($interface)) {
412         push(@headerContent, "    static v8::Handle<v8::Value> constructorCallback(const v8::Arguments&);\n");
413 END
414     }
415     if (HasCustomConstructor($interface)) {
416         push(@headerContent, <<END);
417     static v8::Handle<v8::Value> constructorCallbackCustom(const v8::Arguments&);
418 END
419     }
420
421     my @enabledPerContextAttributes;
422     foreach my $attribute (@{$interface->attributes}) {
423         my $name = $attribute->signature->name;
424         my $attrExt = $attribute->signature->extendedAttributes;
425         my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
426         if (($attrExt->{"V8CustomGetter"} || $attrExt->{"CustomGetter"} ||
427              $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) &&
428             !$attrExt->{"ImplementedBy"}) {
429             push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
430             push(@headerContent, <<END);
431     static v8::Handle<v8::Value> ${name}AccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo&);
432 END
433             push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString;
434         }
435         if (($attrExt->{"V8CustomSetter"} || $attrExt->{"CustomSetter"} ||
436              $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) &&
437             !$attrExt->{"ImplementedBy"}) {
438             push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
439             push(@headerContent, <<END);
440     static void ${name}AccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value>, const v8::AccessorInfo&);
441 END
442             push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString;
443         }
444         if ($attrExt->{"V8EnabledPerContext"}) {
445             push(@enabledPerContextAttributes, $attribute);
446         }
447     }
448
449     GenerateHeaderNamedAndIndexedPropertyAccessors($interface);
450     GenerateHeaderCustomCall($interface);
451     GenerateHeaderCustomInternalFieldIndices($interface);
452
453     if ($interface->extendedAttributes->{"CheckSecurity"}) {
454         push(@headerContent, <<END);
455     static bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType, v8::Local<v8::Value> data);
456     static bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType, v8::Local<v8::Value> data);
457 END
458     }
459
460     if (@enabledPerContextAttributes) {
461         push(@headerContent, <<END);
462     static void installPerContextProperties(v8::Handle<v8::Object>, ${nativeType}*);
463 END
464     } else {
465         push(@headerContent, <<END);
466     static void installPerContextProperties(v8::Handle<v8::Object>, ${nativeType}*) { }
467 END
468     }
469
470     if (@enabledPerContextFunctions) {
471         push(@headerContent, <<END);
472     static void installPerContextPrototypeProperties(v8::Handle<v8::Object>);
473 END
474     } else {
475         push(@headerContent, <<END);
476     static void installPerContextPrototypeProperties(v8::Handle<v8::Object>) { }
477 END
478     }
479
480     if ($interfaceName eq "HTMLElement") {
481         push(@headerContent, <<END);
482     friend v8::Handle<v8::Object> createV8HTMLWrapper(HTMLElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
483     friend v8::Handle<v8::Object> createV8HTMLDirectWrapper(HTMLElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
484 END
485     } elsif ($interfaceName eq "SVGElement") {
486         push(@headerContent, <<END);
487     friend v8::Handle<v8::Object> createV8SVGWrapper(SVGElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
488     friend v8::Handle<v8::Object> createV8SVGDirectWrapper(SVGElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
489     friend v8::Handle<v8::Object> createV8SVGFallbackWrapper(SVGElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
490 END
491     } elsif ($interfaceName eq "HTMLUnknownElement") {
492         push(@headerContent, <<END);
493     friend v8::Handle<v8::Object> createV8HTMLFallbackWrapper(HTMLUnknownElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
494 END
495     } elsif ($interfaceName eq "Element") {
496         push(@headerContent, <<END);
497     // This is a performance optimization hack. See V8Element::wrap.
498     friend v8::Handle<v8::Object> wrap(Node*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
499 END
500     }
501
502         push(@headerContent, <<END);
503 private:
504 END
505
506     if (IsConstructable($interface) && @{$interface->constructors} > 1) {
507         for (my $i = 1; $i <= @{$interface->constructors}; $i++) {
508            push(@headerContent, <<END);
509     static v8::Handle<v8::Value> constructor${i}Callback(const v8::Arguments&);
510 END
511         }
512     }
513
514     my $noToV8 = $interface->extendedAttributes->{"SuppressToJSObject"};
515     my $noWrap = $interface->extendedAttributes->{"V8NoWrapperCache"} || $noToV8;
516     if (!$noWrap) {
517         my $createWrapperArgumentType = GetPassRefPtrType($nativeType);
518         push(@headerContent, <<END);
519     friend v8::Handle<v8::Object> wrap(${nativeType}*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
520     static v8::Handle<v8::Object> createWrapper(${createWrapperArgumentType}, v8::Handle<v8::Object> creationContext, v8::Isolate*);
521 END
522     }
523
524     push(@headerContent, <<END);
525 };
526
527 END
528
529     my $customWrap = !!($interface->extendedAttributes->{"CustomToJSObject"} or $interface->extendedAttributes->{"V8CustomToJSObject"});
530     if ($noToV8) {
531         die "Can't suppress toV8 for subclass\n" if @parents;
532     } elsif ($noWrap) {
533         die "Must have custom toV8\n" if !$customWrap;
534         push(@headerContent, <<END);
535 class ${nativeType};
536 v8::Handle<v8::Value> toV8(${nativeType}*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
537
538 template<class HolderContainer, class Wrappable>
539 inline v8::Handle<v8::Value> toV8Fast(${nativeType}* impl, const HolderContainer& container, Wrappable*)
540 {
541     return toV8(impl, container.Holder(), container.GetIsolate());
542 }
543 END
544     } else {
545
546         my $createWrapperCall = $customWrap ? "${v8InterfaceName}::wrap" : "${v8InterfaceName}::createWrapper";
547
548         if ($customWrap) {
549             push(@headerContent, <<END);
550
551 v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate*);
552 END
553         } else {
554             push(@headerContent, <<END);
555
556 inline v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
557 {
558     ASSERT(impl);
559     ASSERT(DOMDataStore::getWrapper(impl, isolate).IsEmpty());
560     return $createWrapperCall(impl, creationContext, isolate);
561 }
562 END
563         }
564
565         push(@headerContent, <<END);
566
567 inline v8::Handle<v8::Value> toV8(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
568 {
569     if (UNLIKELY(!impl))
570         return v8NullWithCheck(isolate);
571     v8::Handle<v8::Value> wrapper = DOMDataStore::getWrapper(impl, isolate);
572     if (!wrapper.IsEmpty())
573         return wrapper;
574     return wrap(impl, creationContext, isolate);
575 }
576
577 template<class HolderContainer, class Wrappable>
578 inline v8::Handle<v8::Value> toV8Fast(${nativeType}* impl, const HolderContainer& container, Wrappable* wrappable)
579 {
580     if (UNLIKELY(!impl))
581         return v8Null(container.GetIsolate());
582     v8::Handle<v8::Object> wrapper = DOMDataStore::getWrapperFast(impl, container, wrappable);
583     if (!wrapper.IsEmpty())
584         return wrapper;
585     return wrap(impl, container.Holder(), container.GetIsolate());
586 }
587 END
588     }
589
590     push(@headerContent, <<END);
591
592 template<class HolderContainer, class Wrappable>
593 inline v8::Handle<v8::Value> toV8Fast(PassRefPtr< ${nativeType} > impl, const HolderContainer& container, Wrappable* wrappable)
594 {
595     return toV8Fast(impl.get(), container, wrappable);
596 }
597
598 inline v8::Handle<v8::Value> toV8(PassRefPtr< ${nativeType} > impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
599 {
600     return toV8(impl.get(), creationContext, isolate);
601 }
602 END
603
604     if ($codeGenerator->IsConstructorTemplate($interface, "Event")) {
605         push(@headerContent, "\nbool fill${interfaceName}Init(${interfaceName}Init&, const Dictionary&);\n");
606     }
607
608     push(@headerContent, "\n}\n\n");
609     push(@headerContent, "#endif // $v8InterfaceName" . "_h\n");
610
611     my $conditionalString = $codeGenerator->GenerateConditionalString($interface);
612     push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;
613 }
614
615 sub GetInternalFields
616 {
617     my $interface = shift;
618
619     my @customInternalFields = ();
620     # We can't ask whether a parent type has a given extendedAttribute,
621     # so special-case AbstractWorker and WorkerContext to include all sub-types.
622     # Event listeners on DOM nodes are explicitly supported in the GC controller.
623     # FIXME: Simplify this when all EventTargets are subtypes of EventTarget.
624     if (!$codeGenerator->IsSubType($interface, "Node")
625         && ($interface->extendedAttributes->{"EventTarget"}
626             || $interface->extendedAttributes->{"IsWorkerContext"}
627             || $codeGenerator->IsSubType($interface, "AbstractWorker")
628             || $codeGenerator->IsSubType($interface, "EventTarget"))) {
629         push(@customInternalFields, "eventListenerCacheIndex");
630     }
631
632     return @customInternalFields;
633 }
634
635 sub GetHeaderClassInclude
636 {
637     my $v8InterfaceName = shift;
638     if ($v8InterfaceName =~ /SVGPathSeg/) {
639         $v8InterfaceName =~ s/Abs|Rel//;
640     }
641     return "wtf/${v8InterfaceName}.h" if $codeGenerator->IsTypedArrayType($v8InterfaceName);
642     return "" if ($codeGenerator->SkipIncludeHeader($v8InterfaceName));
643     return "${v8InterfaceName}.h";
644 }
645
646 sub GenerateHeaderCustomInternalFieldIndices
647 {
648     my $interface = shift;
649     my @customInternalFields = GetInternalFields($interface);
650     my $customFieldCounter = 0;
651     foreach my $customInternalField (@customInternalFields) {
652         push(@headerContent, <<END);
653     static const int ${customInternalField} = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
654 END
655         $customFieldCounter++;
656     }
657     push(@headerContent, <<END);
658     static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
659 END
660 }
661
662 my %indexerSpecialCases = (
663     "Storage" => 1,
664     "HTMLAppletElement" => 1,
665     "HTMLEmbedElement" => 1,
666     "HTMLObjectElement" => 1
667 );
668
669 sub GenerateHeaderNamedAndIndexedPropertyAccessors
670 {
671     my $interface = shift;
672     my $interfaceName = $interface->name;
673     my $hasCustomIndexedGetter = $interface->extendedAttributes->{"IndexedGetter"} || $interface->extendedAttributes->{"CustomGetOwnPropertySlot"};
674     my $hasCustomIndexedSetter = $interface->extendedAttributes->{"CustomIndexedSetter"} && !$interface->extendedAttributes->{"NumericIndexedGetter"};
675     my $hasCustomNamedGetter = $interface->extendedAttributes->{"NamedGetter"} || $interface->extendedAttributes->{"CustomNamedGetter"} || $interface->extendedAttributes->{"CustomGetOwnPropertySlot"};
676     my $hasCustomNamedSetter = $interface->extendedAttributes->{"CustomNamedSetter"};
677     my $hasCustomDeleters = $interface->extendedAttributes->{"CustomDeleteProperty"};
678     my $hasCustomEnumerator = $interface->extendedAttributes->{"CustomEnumerateProperty"};
679     if ($interfaceName eq "HTMLOptionsCollection") {
680         $interfaceName = "HTMLCollection";
681         $hasCustomIndexedGetter = 1;
682         $hasCustomNamedGetter = 1;
683     }
684     if ($interfaceName eq "DOMWindow") {
685         $hasCustomDeleters = 0;
686         $hasCustomEnumerator = 0;
687     }
688     if ($interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") {
689         $hasCustomNamedGetter = 1;
690     }
691     if ($interfaceName eq "HTMLDocument") {
692         $hasCustomNamedGetter = 0;
693         $hasCustomIndexedGetter = 0;
694     }
695     my $isIndexerSpecialCase = exists $indexerSpecialCases{$interfaceName};
696
697     if ($hasCustomIndexedGetter || $isIndexerSpecialCase) {
698         push(@headerContent, <<END);
699     static v8::Handle<v8::Value> indexedPropertyGetter(uint32_t, const v8::AccessorInfo&);
700 END
701     }
702
703     if ($isIndexerSpecialCase || $hasCustomIndexedSetter) {
704         push(@headerContent, <<END);
705     static v8::Handle<v8::Value> indexedPropertySetter(uint32_t, v8::Local<v8::Value>, const v8::AccessorInfo&);
706 END
707     }
708     if ($hasCustomDeleters) {
709         push(@headerContent, <<END);
710     static v8::Handle<v8::Boolean> indexedPropertyDeleter(uint32_t, const v8::AccessorInfo&);
711 END
712     }
713     if ($hasCustomNamedGetter) {
714         push(@headerContent, <<END);
715     static v8::Handle<v8::Value> namedPropertyGetter(v8::Local<v8::String>, const v8::AccessorInfo&);
716 END
717     }
718     if ($hasCustomNamedSetter) {
719         push(@headerContent, <<END);
720     static v8::Handle<v8::Value> namedPropertySetter(v8::Local<v8::String>, v8::Local<v8::Value>, const v8::AccessorInfo&);
721 END
722     }
723     if ($hasCustomDeleters) {
724         push(@headerContent, <<END);
725     static v8::Handle<v8::Boolean> namedPropertyDeleter(v8::Local<v8::String>, const v8::AccessorInfo&);
726 END
727     }
728     if ($hasCustomEnumerator) {
729         push(@headerContent, <<END);
730     static v8::Handle<v8::Array> namedPropertyEnumerator(const v8::AccessorInfo&);
731     static v8::Handle<v8::Integer> namedPropertyQuery(v8::Local<v8::String>, const v8::AccessorInfo&);
732 END
733     }
734 }
735
736 sub GenerateHeaderCustomCall
737 {
738     my $interface = shift;
739
740     if ($interface->extendedAttributes->{"CustomCall"}) {
741         push(@headerContent, "    static v8::Handle<v8::Value> callAsFunctionCallback(const v8::Arguments&);\n");
742     }
743     if ($interface->name eq "Event") {
744         push(@headerContent, "    static v8::Handle<v8::Value> dataTransferAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo&);\n");
745         push(@headerContent, "    static void valueAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value>, const v8::AccessorInfo&);\n");
746     }
747     if ($interface->name eq "Location") {
748         push(@headerContent, "    static v8::Handle<v8::Value> assignAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo&);\n");
749         push(@headerContent, "    static v8::Handle<v8::Value> reloadAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo&);\n");
750         push(@headerContent, "    static v8::Handle<v8::Value> replaceAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo&);\n");
751     }
752 }
753
754 sub IsConstructable
755 {
756     my $interface = shift;
757
758     return $interface->extendedAttributes->{"CustomConstructor"} || $interface->extendedAttributes->{"V8CustomConstructor"} || $interface->extendedAttributes->{"Constructor"} || $interface->extendedAttributes->{"ConstructorTemplate"};
759 }
760
761 sub HasCustomConstructor
762 {
763     my $interface = shift;
764
765     return $interface->extendedAttributes->{"CustomConstructor"} || $interface->extendedAttributes->{"V8CustomConstructor"};
766 }
767
768 sub IsReadonly
769 {
770     my $attribute = shift;
771     my $attrExt = $attribute->signature->extendedAttributes;
772     return ($attribute->type =~ /readonly/ || $attrExt->{"V8ReadOnly"}) && !$attrExt->{"Replaceable"};
773 }
774
775 sub GenerateDomainSafeFunctionGetter
776 {
777     my $function = shift;
778     my $interfaceName = shift;
779
780     my $v8InterfaceName = "V8" . $interfaceName;
781     my $funcName = $function->signature->name;
782
783     my $signature = "v8::Signature::New(" . $v8InterfaceName . "::GetRawTemplate())";
784     if ($function->signature->extendedAttributes->{"V8DoNotCheckSignature"}) {
785         $signature = "v8::Local<v8::Signature>()";
786     }
787
788     my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
789     my $newTemplateString = "v8::FunctionTemplate::New($callback, v8Undefined(), $signature)";
790
791     AddToImplIncludes("Frame.h");
792     push(@implContentDecls, <<END);
793 static v8::Handle<v8::Value> ${funcName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
794 {
795     static v8::Persistent<v8::FunctionTemplate> privateTemplate = v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
796     v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(${v8InterfaceName}::GetTemplate());
797     if (holder.IsEmpty()) {
798         // can only reach here by 'object.__proto__.func', and it should passed
799         // domain security check already
800         return privateTemplate->GetFunction();
801     }
802     ${interfaceName}* imp = ${v8InterfaceName}::toNative(holder);
803     if (!BindingSecurity::shouldAllowAccessToFrame(BindingState::instance(), imp->frame(), DoNotReportSecurityError)) {
804         static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
805         return sharedTemplate->GetFunction();
806     }
807
808     v8::Local<v8::Value> hiddenValue = info.This()->GetHiddenValue(name);
809     if (!hiddenValue.IsEmpty())
810         return hiddenValue;
811
812     return privateTemplate->GetFunction();
813 }
814
815 END
816 }
817
818 sub GenerateDomainSafeFunctionSetter
819 {
820     my $interfaceName = shift;
821     my $v8InterfaceName = "V8" . $interfaceName;
822
823     push(@implContentDecls, <<END);
824 static void ${interfaceName}DomainSafeFunctionSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
825 {
826     v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(${v8InterfaceName}::GetTemplate());
827     if (holder.IsEmpty())
828         return;
829     ${interfaceName}* imp = ${v8InterfaceName}::toNative(holder);
830     if (!BindingSecurity::shouldAllowAccessToFrame(BindingState::instance(), imp->frame()))
831         return;
832
833     info.This()->SetHiddenValue(name, value);
834 }
835
836 END
837 }
838
839 sub GenerateConstructorGetter
840 {
841     my $interface = shift;
842     my $interfaceName = $interface->name;
843
844     push(@implContentDecls, <<END);
845 static v8::Handle<v8::Value> ${interfaceName}ConstructorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
846 {
847     v8::Handle<v8::Value> data = info.Data();
848     ASSERT(data->IsExternal());
849     V8PerContextData* perContextData = V8PerContextData::from(info.Holder()->CreationContext());
850     if (!perContextData)
851         return v8Undefined();
852     return perContextData->constructorForType(WrapperTypeInfo::unwrap(data));
853 }
854 END
855 }
856
857 sub GenerateFeatureObservation
858 {
859     my $measureAs = shift;
860
861     if ($measureAs) {
862         AddToImplIncludes("FeatureObserver.h");
863         return "    FeatureObserver::observe(activeDOMWindow(BindingState::instance()), FeatureObserver::${measureAs});\n";
864     }
865
866     return "";
867 }
868
869 sub GenerateNormalAttrGetter
870 {
871     my $attribute = shift;
872     my $interface = shift;
873
874     my $interfaceName = $interface->name;
875     my $v8InterfaceName = "V8$interfaceName";
876     my $attrExt = $attribute->signature->extendedAttributes;
877     my $attrName = $attribute->signature->name;
878     my $attrType = $attribute->signature->type;
879     $codeGenerator->AssertNotSequenceType($attrType);
880     my $nativeType = GetNativeTypeFromSignature($attribute->signature, -1);
881
882     my $getterStringUsesImp = $interfaceName ne "SVGNumber";
883     my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($interfaceName);
884
885     # Getter
886     my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
887     push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
888
889     push(@implContentDecls, <<END);
890 static v8::Handle<v8::Value> ${attrName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
891 {
892 END
893     push(@implContentDecls, GenerateFeatureObservation($attrExt->{"V8MeasureAs"}));
894
895     if ($svgNativeType) {
896         my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($interfaceName);
897         if ($svgWrappedNativeType =~ /List/) {
898             push(@implContentDecls, <<END);
899     $svgNativeType* imp = ${v8InterfaceName}::toNative(info.Holder());
900 END
901         } else {
902             push(@implContentDecls, <<END);
903     $svgNativeType* wrapper = ${v8InterfaceName}::toNative(info.Holder());
904     $svgWrappedNativeType& impInstance = wrapper->propertyReference();
905 END
906             if ($getterStringUsesImp) {
907                 push(@implContentDecls, <<END);
908     $svgWrappedNativeType* imp = &impInstance;
909 END
910             }
911         }
912     } elsif ($attrExt->{"V8OnProto"} || $attrExt->{"V8Unforgeable"}) {
913         if ($interfaceName eq "DOMWindow") {
914             push(@implContentDecls, <<END);
915     v8::Handle<v8::Object> holder = info.Holder();
916 END
917         } else {
918             # perform lookup first
919             push(@implContentDecls, <<END);
920     v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(${v8InterfaceName}::GetTemplate());
921     if (holder.IsEmpty())
922         return v8Undefined();
923 END
924         }
925         push(@implContentDecls, <<END);
926     ${interfaceName}* imp = ${v8InterfaceName}::toNative(holder);
927 END
928     } else {
929         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
930         my $url = $attribute->signature->extendedAttributes->{"URL"};
931         if ($getterStringUsesImp && $reflect && !$url && $codeGenerator->IsSubType($interface, "Node") && $codeGenerator->IsStringType($attrType)) {
932             # Generate super-compact call for regular attribute getter:
933             my ($functionName, @arguments) = $codeGenerator->GetterExpression(\%implIncludes, $interfaceName, $attribute);
934             push(@implContentDecls, "    Element* imp = V8Element::toNative(info.Holder());\n");
935             push(@implContentDecls, "    return v8String(imp->${functionName}(" . join(", ", @arguments) . "), info.GetIsolate(), ReturnUnsafeHandle);\n");
936             push(@implContentDecls, "}\n\n");
937             push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
938             return;
939             # Skip the rest of the function!
940         }
941         if ($attribute->signature->type eq "SerializedScriptValue" && $attrExt->{"CachedAttribute"}) {
942             push(@implContentDecls, <<END);
943     v8::Handle<v8::String> propertyName = v8::String::NewSymbol("${attrName}");
944     v8::Handle<v8::Value> value = info.Holder()->GetHiddenValue(propertyName);
945     if (!value.IsEmpty())
946         return value;
947 END
948         }
949         if (!$attribute->isStatic) {
950             push(@implContentDecls, <<END);
951     ${interfaceName}* imp = ${v8InterfaceName}::toNative(info.Holder());
952 END
953         }
954     }
955
956     # Generate security checks if necessary
957     if ($attribute->signature->extendedAttributes->{"CheckSecurityForNode"}) {
958         push(@implContentDecls, "    if (!BindingSecurity::shouldAllowAccessToNode(BindingState::instance(), imp->" . $attribute->signature->name . "()))\n        return v8::Handle<v8::Value>(v8Null(info.GetIsolate()));\n\n");
959     }
960
961     my $useExceptions = 1 if @{$attribute->getterExceptions};
962     if ($useExceptions) {
963         AddToImplIncludes("ExceptionCode.h");
964         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
965     }
966
967     my $returnType = $attribute->signature->type;
968     my $getterString;
969
970     if ($getterStringUsesImp) {
971         my ($functionName, @arguments) = $codeGenerator->GetterExpression(\%implIncludes, $interfaceName, $attribute);
972         push(@arguments, "ec") if $useExceptions;
973         if ($attribute->signature->extendedAttributes->{"ImplementedBy"}) {
974             my $implementedBy = $attribute->signature->extendedAttributes->{"ImplementedBy"};
975             AddToImplIncludes("${implementedBy}.h");
976             unshift(@arguments, "imp") if !$attribute->isStatic;
977             $functionName = "${implementedBy}::${functionName}";
978         } elsif ($attribute->isStatic) {
979             $functionName = "${interfaceName}::${functionName}";
980         } else {
981             $functionName = "imp->${functionName}";
982         }
983         unshift(@arguments, GenerateCallWith($attribute->signature->extendedAttributes->{"CallWith"}, \@implContentDecls, "    ", 0));
984         $getterString = "${functionName}(" . join(", ", @arguments) . ")";
985     } else {
986         $getterString = "impInstance";
987     }
988
989     my $result;
990     if ($attribute->signature->type eq "EventListener" && $interface->name eq "DOMWindow") {
991         push(@implContentDecls, "    if (!imp->document())\n");
992         push(@implContentDecls, "        return v8Undefined();\n");
993     }
994
995     if ($useExceptions) {
996         if ($nativeType =~ /^V8StringResource/) {
997             push(@implContentDecls, "    " . ConvertToV8StringResource($attribute->signature, $nativeType, "v", $getterString) . ";\n");
998         } else {
999             push(@implContentDecls, "    $nativeType v = $getterString;\n");
1000         }
1001         push(@implContentDecls, "    if (UNLIKELY(ec))\n");
1002         push(@implContentDecls, "        return setDOMException(ec, info.GetIsolate());\n");
1003
1004         if ($codeGenerator->ExtendedAttributeContains($attribute->signature->extendedAttributes->{"CallWith"}, "ScriptState")) {
1005             push(@implContentDecls, "    if (state.hadException())\n");
1006             push(@implContentDecls, "        return throwError(state.exception(), info.GetIsolate());\n");
1007         }
1008
1009         $result = "v";
1010         $result .= ".release()" if ($codeGenerator->IsRefPtrType($returnType));
1011     } else {
1012         # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
1013         $result = $getterString;
1014         # Fix amigious conversion problem, by casting to the base type first ($getterString returns a type that inherits from SVGAnimatedEnumeration, not the base class directly).
1015         $result = "static_pointer_cast<SVGAnimatedEnumeration>($result)" if $returnType eq "SVGAnimatedEnumeration";
1016     }
1017  
1018     # Special case for readonly or Replaceable attributes (with a few exceptions). This attempts to ensure that JS wrappers don't get
1019     # garbage-collected prematurely when their lifetime is strongly tied to their owner. We accomplish this by inserting a reference to
1020     # the newly created wrapper into an internal field of the holder object.
1021     if ((!$codeGenerator->IsSubType($interface, "Node") && $attrName ne "self" && IsWrapperType($returnType) && (IsReadonly($attribute) || $attribute->signature->extendedAttributes->{"Replaceable"} || $attrName eq "location")
1022          && $returnType ne "EventTarget" && $returnType ne "SerializedScriptValue" && $returnType ne "DOMWindow"
1023          && $returnType ne "MessagePortArray"
1024          && $returnType !~ /SVG/ && $returnType !~ /HTML/ && !IsDOMNodeType($returnType))
1025         || $attribute->signature->extendedAttributes->{"V8CacheAttributeForGC"}) {
1026
1027         my $arrayType = $codeGenerator->GetArrayType($returnType);
1028         if ($arrayType) {
1029             if (!$codeGenerator->SkipIncludeHeader($arrayType)) {
1030                 AddToImplIncludes("V8$arrayType.h");
1031                 AddToImplIncludes("$arrayType.h");
1032             }
1033             push(@implContentDecls, "    return v8Array(${getterString}, info.GetIsolate());\n");
1034             push(@implContentDecls, "}\n\n");
1035             return;
1036         }
1037
1038         AddIncludesForType($returnType);
1039         # Check for a wrapper in the wrapper cache. If there is one, we know that a hidden reference has already
1040         # been created. If we don't find a wrapper, we create both a wrapper and a hidden reference.
1041         push(@implContentDecls, "    RefPtr<$returnType> result = ${getterString};\n");
1042         push(@implContentDecls, "    v8::Handle<v8::Value> wrapper = result.get() ? v8::Handle<v8::Value>(DOMDataStore::getWrapper(result.get(), info.GetIsolate())) : v8Undefined();\n");
1043         push(@implContentDecls, "    if (wrapper.IsEmpty()) {\n");
1044         push(@implContentDecls, "        wrapper = toV8(result.get(), info.Holder(), info.GetIsolate());\n"); # FIXME: Could use wrap here since the wrapper is empty.
1045         push(@implContentDecls, "        if (!wrapper.IsEmpty())\n");
1046         push(@implContentDecls, "            V8DOMWrapper::setNamedHiddenReference(info.Holder(), \"${attrName}\", wrapper);\n");
1047         push(@implContentDecls, "    }\n");
1048         push(@implContentDecls, "    return wrapper;\n");
1049         push(@implContentDecls, "}\n\n");
1050         push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1051         return;
1052     }
1053
1054     if (($codeGenerator->IsSVGAnimatedType($interfaceName) or $interfaceName eq "SVGViewSpec") and $codeGenerator->IsSVGTypeNeedingTearOff($attrType)) {
1055         AddToImplIncludes("V8$attrType.h");
1056         my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($attrType);
1057         # Convert from abstract SVGProperty to real type, so the right toJS() method can be invoked.
1058         push(@implContentDecls, "    return toV8Fast(static_cast<$svgNativeType*>($result), info, imp);\n");
1059     } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($attrType) and not $interfaceName =~ /List$/) {
1060         AddToImplIncludes("V8$attrType.h");
1061         AddToImplIncludes("SVGPropertyTearOff.h");
1062         my $tearOffType = $codeGenerator->GetSVGTypeNeedingTearOff($attrType);
1063         my $wrappedValue;
1064         if ($codeGenerator->IsSVGTypeWithWritablePropertiesNeedingTearOff($attrType) and not defined $attribute->signature->extendedAttributes->{"Immutable"}) {
1065             my $getter = $result;
1066             $getter =~ s/imp->//;
1067             $getter =~ s/\(\)//;
1068
1069             my $updateMethod = "&${interfaceName}::update" . $codeGenerator->WK_ucfirst($getter);
1070
1071             my $selfIsTearOffType = $codeGenerator->IsSVGTypeNeedingTearOff($interfaceName);
1072             if ($selfIsTearOffType) {
1073                 AddToImplIncludes("SVGStaticPropertyWithParentTearOff.h");
1074                 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyWithParentTearOff<$interfaceName, /;
1075
1076                 if ($result =~ /matrix/ and $interfaceName eq "SVGTransform") {
1077                     # SVGTransform offers a matrix() method for internal usage that returns an AffineTransform
1078                     # and a svgMatrix() method returning a SVGMatrix, used for the bindings.
1079                     $result =~ s/matrix/svgMatrix/;
1080                 }
1081
1082                 $wrappedValue = "WTF::getPtr(${tearOffType}::create(wrapper, $result, $updateMethod))";
1083             } else {
1084                 AddToImplIncludes("SVGStaticPropertyTearOff.h");
1085                 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyTearOff<$interfaceName, /;
1086
1087                 $wrappedValue = "WTF::getPtr(${tearOffType}::create(imp, $result, $updateMethod))";
1088             }
1089         } elsif ($tearOffType =~ /SVGStaticListPropertyTearOff/) {
1090                 $wrappedValue = "WTF::getPtr(${tearOffType}::create(imp, $result))";
1091         } elsif ($tearOffType =~ /SVG(Point|PathSeg)List/) {
1092                 $wrappedValue = "WTF::getPtr($result)";
1093         } else {
1094                 $wrappedValue = "WTF::getPtr(${tearOffType}::create($result))";
1095         }
1096         push(@implContentDecls, "    return toV8Fast($wrappedValue, info, imp);\n");
1097     } elsif ($attribute->signature->type eq "MessagePortArray") {
1098         AddToImplIncludes("MessagePort.h");
1099         AddToImplIncludes("V8MessagePort.h");
1100         my $getterFunc = $codeGenerator->WK_lcfirst($attribute->signature->name);
1101         push(@implContentDecls, <<END);
1102     MessagePortArray* ports = imp->${getterFunc}();
1103     if (!ports)
1104         return v8::Array::New(0);
1105     MessagePortArray portsCopy(*ports);
1106     v8::Local<v8::Array> portArray = v8::Array::New(portsCopy.size());
1107     for (size_t i = 0; i < portsCopy.size(); ++i)
1108         portArray->Set(v8Integer(i, info.GetIsolate()), toV8Fast(portsCopy[i].get(), info, imp));
1109     return portArray;
1110 END
1111     } elsif ($attribute->signature->type eq "SerializedScriptValue" && $attrExt->{"CachedAttribute"}) {
1112         my $getterFunc = $codeGenerator->WK_lcfirst($attribute->signature->name);
1113         push(@implContentDecls, <<END);
1114     SerializedScriptValue* serialized = imp->${getterFunc}();
1115     value = serialized ? serialized->deserialize() : v8::Handle<v8::Value>(v8Null(info.GetIsolate()));
1116     info.Holder()->SetHiddenValue(propertyName, value);
1117     return value;
1118 END
1119     } else {
1120         push(@implContentDecls, "    return " . NativeToJSValue($attribute->signature, $result, "info.Holder()", "info.GetIsolate()", "info", "imp", "ReturnUnsafeHandle").";\n");
1121     }
1122
1123     push(@implContentDecls, "}\n\n");  # end of getter
1124     push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1125 }
1126
1127 sub GenerateReplaceableAttrSetter
1128 {
1129     my $interface = shift;
1130     my $interfaceName = $interface->name;
1131
1132     push(@implContentDecls, <<END);
1133 static void ${interfaceName}ReplaceableAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
1134 {
1135 END
1136     push(@implContentDecls, GenerateFeatureObservation($interface->extendedAttributes->{"V8MeasureAs"}));
1137
1138     if ($interfaceName eq "DOMWindow" || $interface->extendedAttributes->{"CheckSecurity"}) {
1139         AddToImplIncludes("Frame.h");
1140         push(@implContentDecls, <<END);
1141     ${interfaceName}* imp = V8${interfaceName}::toNative(info.Holder());
1142     if (!BindingSecurity::shouldAllowAccessToFrame(BindingState::instance(), imp->frame()))
1143         return;
1144 END
1145     }
1146
1147     push(@implContentDecls, <<END);
1148     info.This()->ForceSet(name, value);
1149 }
1150
1151 END
1152 }
1153
1154 sub GenerateNormalAttrSetter
1155 {
1156     my $attribute = shift;
1157     my $interface = shift;
1158
1159     my $interfaceName = $interface->name;
1160     my $v8InterfaceName = "V8$interfaceName";
1161     my $attrName = $attribute->signature->name;
1162     my $attrExt = $attribute->signature->extendedAttributes;
1163
1164     my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
1165     push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
1166
1167     push(@implContentDecls, "static void ${attrName}AttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)\n{\n");
1168     push(@implContentDecls, GenerateFeatureObservation($attribute->signature->extendedAttributes->{"V8MeasureAs"}));
1169
1170     # If the "StrictTypeChecking" extended attribute is present, and the attribute's type is an
1171     # interface type, then if the incoming value does not implement that interface, a TypeError is
1172     # thrown rather than silently passing NULL to the C++ code.
1173     # Per the Web IDL and ECMAScript specifications, incoming values can always be converted to both
1174     # strings and numbers, so do not throw TypeError if the attribute is of these types.
1175     if ($attribute->signature->extendedAttributes->{"StrictTypeChecking"}) {
1176         my $argType = $attribute->signature->type;
1177         if (IsWrapperType($argType)) {
1178             push(@implContentDecls, "    if (!isUndefinedOrNull(value) && !V8${argType}::HasInstance(value)) {\n");
1179             push(@implContentDecls, "        throwTypeError(0, info.GetIsolate());\n");
1180             push(@implContentDecls, "        return;\n");
1181             push(@implContentDecls, "    }\n");
1182         }
1183     }
1184
1185     my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($interfaceName);
1186     if ($svgNativeType) {
1187         my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($interfaceName);
1188         if ($svgWrappedNativeType =~ /List$/) {
1189             push(@implContentDecls, <<END);
1190     $svgNativeType* imp = ${v8InterfaceName}::toNative(info.Holder());
1191 END
1192         } else {
1193             AddToImplIncludes("ExceptionCode.h");
1194             push(@implContentDecls, "    $svgNativeType* wrapper = ${v8InterfaceName}::toNative(info.Holder());\n");
1195             push(@implContentDecls, "    if (wrapper->isReadOnly()) {\n");
1196             push(@implContentDecls, "        setDOMException(NO_MODIFICATION_ALLOWED_ERR, info.GetIsolate());\n");
1197             push(@implContentDecls, "        return;\n");
1198             push(@implContentDecls, "    }\n");
1199             push(@implContentDecls, "    $svgWrappedNativeType& impInstance = wrapper->propertyReference();\n");
1200             push(@implContentDecls, "    $svgWrappedNativeType* imp = &impInstance;\n");
1201         }
1202     } elsif ($attrExt->{"V8OnProto"}) {
1203         push(@implContentDecls, <<END);
1204     ${interfaceName}* imp = ${v8InterfaceName}::toNative(info.Holder());
1205 END
1206     } else {
1207         my $attrType = $attribute->signature->type;
1208         my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
1209         if ($reflect && $codeGenerator->IsSubType($interface, "Node") && $codeGenerator->IsStringType($attrType)) {
1210             # Generate super-compact call for regular attribute setter:
1211             my $contentAttributeName = $reflect eq "VALUE_IS_MISSING" ? lc $attrName : $reflect;
1212             my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
1213             AddToImplIncludes("${namespace}.h");
1214             push(@implContentDecls, "    Element* imp = V8Element::toNative(info.Holder());\n");
1215             push(@implContentDecls, "    V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, stringResource, value);\n");
1216             push(@implContentDecls, "    imp->setAttribute(${namespace}::${contentAttributeName}Attr, stringResource);\n");
1217             push(@implContentDecls, "}\n\n");
1218             push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1219             return;
1220             # Skip the rest of the function!
1221         }
1222
1223         if (!$attribute->isStatic) {
1224             push(@implContentDecls, <<END);
1225     ${interfaceName}* imp = ${v8InterfaceName}::toNative(info.Holder());
1226 END
1227         }
1228     }
1229
1230     my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0);
1231     if ($attribute->signature->type eq "EventListener") {
1232         if ($interface->name eq "DOMWindow") {
1233             push(@implContentDecls, "    if (!imp->document())\n");
1234             push(@implContentDecls, "        return;\n");
1235         }
1236     } else {
1237         my $value = JSValueToNative($attribute->signature, "value", "info.GetIsolate()");
1238         my $arrayType = $codeGenerator->GetArrayType($nativeType);
1239
1240         if ($nativeType =~ /^V8StringResource/) {
1241             push(@implContentDecls, "    " . ConvertToV8StringResource($attribute->signature, $nativeType, "v", $value, "VOID") . "\n");
1242         } elsif ($arrayType) {
1243             push(@implContentDecls, "    Vector<$arrayType> v = $value;\n");
1244         } else {
1245             push(@implContentDecls, "    $nativeType v = $value;\n");
1246         }
1247     }
1248
1249     my $result = "v";
1250     my $returnType = $attribute->signature->type;
1251     if ($codeGenerator->IsRefPtrType($returnType) && !$codeGenerator->GetArrayType($returnType)) {
1252         $result = "WTF::getPtr(" . $result . ")";
1253     }
1254
1255     my $useExceptions = 1 if @{$attribute->setterExceptions};
1256
1257     if ($useExceptions) {
1258         AddToImplIncludes("ExceptionCode.h");
1259         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
1260     }
1261
1262     if ($interfaceName eq "SVGNumber") {
1263         push(@implContentDecls, "    *imp = $result;\n");
1264     } else {
1265         if ($attribute->signature->type eq "EventListener") {
1266             my $implSetterFunctionName = $codeGenerator->WK_ucfirst($attrName);
1267             AddToImplIncludes("V8AbstractEventListener.h");
1268             if (!$codeGenerator->IsSubType($interface, "Node")) {
1269                 push(@implContentDecls, "    transferHiddenDependency(info.Holder(), imp->$attrName(), value, ${v8InterfaceName}::eventListenerCacheIndex);\n");
1270             }
1271             AddToImplIncludes("V8EventListenerList.h");
1272             if ($interfaceName eq "WorkerContext" and $attribute->signature->name eq "onerror") {
1273                 AddToImplIncludes("V8WorkerContextErrorHandler.h");
1274                 push(@implContentDecls, "    imp->set$implSetterFunctionName(V8EventListenerList::findOrCreateWrapper<V8WorkerContextErrorHandler>(value, true)");
1275             } elsif ($interfaceName eq "DOMWindow" and $attribute->signature->name eq "onerror") {
1276                 AddToImplIncludes("V8WindowErrorHandler.h");
1277                 push(@implContentDecls, "    imp->set$implSetterFunctionName(V8EventListenerList::findOrCreateWrapper<V8WindowErrorHandler>(value, true)");
1278             } else {
1279                 push(@implContentDecls, "    imp->set$implSetterFunctionName(V8EventListenerList::getEventListener(value, true, ListenerFindOrCreate)");
1280             }
1281             push(@implContentDecls, ", ec") if $useExceptions;
1282             push(@implContentDecls, ");\n");
1283         } else {
1284             my ($functionName, @arguments) = $codeGenerator->SetterExpression(\%implIncludes, $interfaceName, $attribute);
1285             push(@arguments, $result);
1286             push(@arguments, "ec") if $useExceptions;
1287             if ($attribute->signature->extendedAttributes->{"ImplementedBy"}) {
1288                 my $implementedBy = $attribute->signature->extendedAttributes->{"ImplementedBy"};
1289                 AddToImplIncludes("${implementedBy}.h");
1290                 unshift(@arguments, "imp") if !$attribute->isStatic;
1291                 $functionName = "${implementedBy}::${functionName}";
1292             } elsif ($attribute->isStatic) {
1293                 $functionName = "${interfaceName}::${functionName}";
1294             } else {
1295                 $functionName = "imp->${functionName}";
1296             }
1297             unshift(@arguments, GenerateCallWith($attribute->signature->extendedAttributes->{"CallWith"}, \@implContentDecls, "    ", 1));
1298             push(@implContentDecls, "    ${functionName}(" . join(", ", @arguments) . ");\n");
1299         }
1300     }
1301
1302     if ($useExceptions) {
1303         push(@implContentDecls, "    if (UNLIKELY(ec))\n");
1304         push(@implContentDecls, "        setDOMException(ec, info.GetIsolate());\n");
1305     }
1306
1307     if ($codeGenerator->ExtendedAttributeContains($attribute->signature->extendedAttributes->{"CallWith"}, "ScriptState")) {
1308         push(@implContentDecls, "    if (state.hadException())\n");
1309         push(@implContentDecls, "        throwError(state.exception(), info.GetIsolate());\n");
1310     }
1311
1312     if ($svgNativeType) {
1313         if ($useExceptions) {
1314             push(@implContentDecls, "    if (!ec)\n");
1315             push(@implContentDecls, "        wrapper->commitChange();\n");
1316         } else {
1317             push(@implContentDecls, "    wrapper->commitChange();\n");
1318         }
1319     }
1320
1321     if ($attribute->signature->type eq "SerializedScriptValue" && $attribute->signature->extendedAttributes->{"CachedAttribute"}) {
1322         push(@implContentDecls, <<END);
1323     info.Holder()->DeleteHiddenValue(v8::String::NewSymbol("${attrName}")); // Invalidate the cached value.
1324 END
1325     }
1326
1327     push(@implContentDecls, "    return;\n");
1328     push(@implContentDecls, "}\n\n");  # end of setter
1329     push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1330 }
1331
1332 sub GetFunctionTemplateCallbackName
1333 {
1334     my $function = shift;
1335     my $interfaceName = shift;
1336
1337     my $name = $function->signature->name;
1338
1339     if ($function->signature->extendedAttributes->{"Custom"} ||
1340         $function->signature->extendedAttributes->{"V8Custom"}) {
1341         if ($function->signature->extendedAttributes->{"Custom"} &&
1342             $function->signature->extendedAttributes->{"V8Custom"}) {
1343             die "Custom and V8Custom should be mutually exclusive!"
1344         }
1345         return "V8${interfaceName}::${name}Callback";
1346     } else {
1347         return "${interfaceName}V8Internal::${name}Callback";
1348     }
1349 }
1350
1351 sub GenerateEventListenerCallback
1352 {
1353     my $interfaceName = shift;
1354     my $requiresHiddenDependency = shift;
1355     my $functionName = shift;
1356     my $lookupType = ($functionName eq "add") ? "OrCreate" : "Only";
1357     my $passRefPtrHandling = ($functionName eq "add") ? "" : ".get()";
1358     my $hiddenDependencyAction = ($functionName eq "add") ? "create" : "remove";
1359
1360     AddToImplIncludes("V8EventListenerList.h");
1361     push(@implContentDecls, <<END);
1362 static v8::Handle<v8::Value> ${functionName}EventListenerCallback(const v8::Arguments& args)
1363 {
1364     RefPtr<EventListener> listener = V8EventListenerList::getEventListener(args[1], false, ListenerFind${lookupType});
1365     if (listener) {
1366         V8TRYCATCH_FOR_V8STRINGRESOURCE(V8StringResource<WithNullCheck>, stringResource, args[0]);
1367         V8${interfaceName}::toNative(args.Holder())->${functionName}EventListener(stringResource, listener${passRefPtrHandling}, args[2]->BooleanValue());
1368 END
1369     if ($requiresHiddenDependency) {
1370         push(@implContentDecls, <<END);
1371         ${hiddenDependencyAction}HiddenDependency(args.Holder(), args[1], V8${interfaceName}::eventListenerCacheIndex);
1372 END
1373     }
1374     push(@implContentDecls, <<END);
1375     }
1376     return v8Undefined();
1377 }
1378
1379 END
1380 }
1381
1382 sub GenerateParametersCheckExpression
1383 {
1384     my $numParameters = shift;
1385     my $function = shift;
1386
1387     my @andExpression = ();
1388     push(@andExpression, "args.Length() == $numParameters");
1389     my $parameterIndex = 0;
1390     foreach my $parameter (@{$function->parameters}) {
1391         last if $parameterIndex >= $numParameters;
1392         my $value = "args[$parameterIndex]";
1393         my $type = $parameter->type;
1394
1395         # Only DOMString or wrapper types are checked.
1396         # For DOMString with StrictTypeChecking only Null, Undefined and Object
1397         # are accepted for compatibility. Otherwise, no restrictions are made to
1398         # match the non-overloaded behavior.
1399         # FIXME: Implement WebIDL overload resolution algorithm.
1400         if ($codeGenerator->IsStringType($type)) {
1401             if ($parameter->extendedAttributes->{"StrictTypeChecking"}) {
1402                 push(@andExpression, "(${value}->IsNull() || ${value}->IsUndefined() || ${value}->IsString() || ${value}->IsObject())");
1403             }
1404         } elsif ($parameter->extendedAttributes->{"Callback"}) {
1405             # For Callbacks only checks if the value is null or object.
1406             push(@andExpression, "(${value}->IsNull() || ${value}->IsFunction())");
1407         } elsif ($codeGenerator->GetArrayType($type) || $codeGenerator->GetSequenceType($type)) {
1408             if ($parameter->isNullable) {
1409                 push(@andExpression, "(${value}->IsNull() || ${value}->IsArray())");
1410             } else {
1411                 push(@andExpression, "(${value}->IsArray())");
1412             }
1413         } elsif (IsWrapperType($type)) {
1414             if ($parameter->isNullable) {
1415                 push(@andExpression, "(${value}->IsNull() || V8${type}::HasInstance($value))");
1416             } else {
1417                 push(@andExpression, "(V8${type}::HasInstance($value))");
1418             }
1419         }
1420
1421         $parameterIndex++;
1422     }
1423     my $res = join(" && ", @andExpression);
1424     $res = "($res)" if @andExpression > 1;
1425     return $res;
1426 }
1427
1428 sub GenerateFunctionParametersCheck
1429 {
1430     my $function = shift;
1431
1432     my @orExpression = ();
1433     my $numParameters = 0;
1434     my $hasVariadic = 0;
1435     my $numMandatoryParams = @{$function->parameters};
1436     foreach my $parameter (@{$function->parameters}) {
1437         if ($parameter->extendedAttributes->{"Optional"}) {
1438             push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
1439             $numMandatoryParams--;
1440         }
1441         if ($parameter->isVariadic) {
1442             $hasVariadic = 1;
1443             last;
1444         }
1445         $numParameters++;
1446     }
1447     if (!$hasVariadic) {
1448         push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
1449     }
1450     return ($numMandatoryParams, join(" || ", @orExpression));
1451 }
1452
1453 sub GenerateOverloadedFunctionCallback
1454 {
1455     my $function = shift;
1456     my $interface = shift;
1457     my $interfaceName = $interface->name;
1458
1459     # Generate code for choosing the correct overload to call. Overloads are
1460     # chosen based on the total number of arguments passed and the type of
1461     # values passed in non-primitive argument slots. When more than a single
1462     # overload is applicable, precedence is given according to the order of
1463     # declaration in the IDL.
1464
1465     my $name = $function->signature->name;
1466     my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
1467     my $leastNumMandatoryParams = 255;
1468     push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
1469     push(@implContentDecls, <<END);
1470 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args)
1471 {
1472 END
1473     push(@implContentDecls, GenerateFeatureObservation($function->signature->extendedAttributes->{"V8MeasureAs"}));
1474
1475     foreach my $overload (@{$function->{overloads}}) {
1476         my ($numMandatoryParams, $parametersCheck) = GenerateFunctionParametersCheck($overload);
1477         $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams < $leastNumMandatoryParams);
1478         push(@implContentDecls, "    if ($parametersCheck)\n");
1479         push(@implContentDecls, "        return ${name}$overload->{overloadIndex}Callback(args);\n");
1480     }
1481     if ($leastNumMandatoryParams >= 1) {
1482         push(@implContentDecls, "    if (args.Length() < $leastNumMandatoryParams)\n");
1483         push(@implContentDecls, "        return throwNotEnoughArgumentsError(args.GetIsolate());\n");
1484     }
1485     push(@implContentDecls, <<END);
1486     return throwTypeError(0, args.GetIsolate());
1487 END
1488     push(@implContentDecls, "}\n\n");
1489     push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1490 }
1491
1492 sub GenerateFunctionCallback
1493 {
1494     my $function = shift;
1495     my $interface = shift;
1496
1497     my $interfaceName = $interface->name;
1498     my $v8InterfaceName = "V8$interfaceName";
1499     my $name = $function->signature->name;
1500
1501     if (@{$function->{overloads}} > 1) {
1502         # Append a number to an overloaded method's name to make it unique:
1503         $name = $name . $function->{overloadIndex};
1504     }
1505
1506     # Adding and removing event listeners are not standard callback behavior,
1507     # but they are extremely consistent across the various interfaces that take event listeners,
1508     # so we can generate them as a "special case".
1509     if ($name eq "addEventListener") {
1510         GenerateEventListenerCallback($interfaceName, !$codeGenerator->IsSubType($interface, "Node"), "add");
1511         return;
1512     } elsif ($name eq "removeEventListener") {
1513         GenerateEventListenerCallback($interfaceName, !$codeGenerator->IsSubType($interface, "Node"), "remove");
1514         return;
1515     }
1516
1517     my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
1518     push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
1519     push(@implContentDecls, <<END);
1520 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args)
1521 {
1522 END
1523     push(@implContentDecls, GenerateFeatureObservation($function->signature->extendedAttributes->{"V8MeasureAs"}));
1524
1525     push(@implContentDecls, GenerateArgumentsCountCheck($function, $interface));
1526
1527     if ($name eq "set" and $interface->extendedAttributes->{"TypedArray"}) {
1528         AddToImplIncludes("V8ArrayBufferViewCustom.h");
1529         push(@implContentDecls, <<END);
1530     return setWebGLArrayHelper<$interfaceName, ${v8InterfaceName}>(args);
1531 }
1532
1533 END
1534         return;
1535     }
1536
1537     my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($interfaceName);
1538
1539     if ($svgNativeType) {
1540         my $nativeClassName = GetNativeType($interfaceName); 
1541         if ($interfaceName =~ /List$/) {
1542             push(@implContentDecls, "    $nativeClassName imp = ${v8InterfaceName}::toNative(args.Holder());\n");
1543         } else {
1544             AddToImplIncludes("ExceptionCode.h");
1545             push(@implContentDecls, "    $nativeClassName wrapper = ${v8InterfaceName}::toNative(args.Holder());\n");
1546             push(@implContentDecls, "    if (wrapper->isReadOnly())\n");
1547             push(@implContentDecls, "        return setDOMException(NO_MODIFICATION_ALLOWED_ERR, args.GetIsolate());\n");
1548             my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($interfaceName);
1549             push(@implContentDecls, "    $svgWrappedNativeType& impInstance = wrapper->propertyReference();\n");
1550             push(@implContentDecls, "    $svgWrappedNativeType* imp = &impInstance;\n");
1551         }
1552     } elsif (!$function->isStatic) {
1553         push(@implContentDecls, <<END);
1554     ${interfaceName}* imp = ${v8InterfaceName}::toNative(args.Holder());
1555 END
1556     }
1557
1558     # Check domain security if needed
1559     if (($interface->extendedAttributes->{"CheckSecurity"}
1560         || $interfaceName eq "DOMWindow")
1561         && !$function->signature->extendedAttributes->{"DoNotCheckSecurity"}) {
1562         # We have not find real use cases yet.
1563         AddToImplIncludes("Frame.h");
1564         push(@implContentDecls, <<END);
1565     if (!BindingSecurity::shouldAllowAccessToFrame(BindingState::instance(), imp->frame()))
1566         return v8Undefined();
1567 END
1568     }
1569
1570     my $raisesExceptions = @{$function->raisesExceptions};
1571     if (!$raisesExceptions) {
1572         foreach my $parameter (@{$function->parameters}) {
1573             if ((!$parameter->extendedAttributes->{"Callback"} and TypeCanFailConversion($parameter)) or $parameter->extendedAttributes->{"IsIndex"}) {
1574                 $raisesExceptions = 1;
1575             }
1576         }
1577     }
1578
1579     if ($raisesExceptions) {
1580         AddToImplIncludes("ExceptionCode.h");
1581         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
1582         push(@implContentDecls, "    {\n");
1583         # The brace here is needed to prevent the ensuing 'goto fail's from jumping past constructors
1584         # of objects (like Strings) declared later, causing compile errors. The block scope ends
1585         # right before the label 'fail:'.
1586     }
1587
1588     if ($function->signature->extendedAttributes->{"CheckSecurityForNode"}) {
1589         push(@implContentDecls, "    if (!BindingSecurity::shouldAllowAccessToNode(BindingState::instance(), imp->" . $function->signature->name . "(ec)))\n");
1590         push(@implContentDecls, "        return v8::Handle<v8::Value>(v8Null(args.GetIsolate()));\n");
1591 END
1592     }
1593
1594     my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersCheck($function, $interfaceName);
1595     push(@implContentDecls, $parameterCheckString);
1596
1597     # Build the function call string.
1598     push(@implContentDecls, GenerateFunctionCallString($function, $paramIndex, "    ", $interfaceName, %replacements));
1599
1600     if ($raisesExceptions) {
1601         push(@implContentDecls, "    }\n");
1602         push(@implContentDecls, "    fail:\n");
1603         push(@implContentDecls, "    return setDOMException(ec, args.GetIsolate());\n");
1604     }
1605
1606     push(@implContentDecls, "}\n\n");
1607     push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1608 }
1609
1610 sub GenerateCallWith
1611 {
1612     my $callWith = shift;
1613     return () unless $callWith;
1614     my $outputArray = shift;
1615     my $indent = shift;
1616     my $returnVoid = shift;
1617     my $function = shift;
1618
1619     my @callWithArgs;
1620     if ($codeGenerator->ExtendedAttributeContains($callWith, "ScriptState")) {
1621         push(@$outputArray, $indent . "ScriptState* currentState = ScriptState::current();\n");
1622         push(@$outputArray, $indent . "if (!currentState)\n");
1623         push(@$outputArray, $indent . "    return" . ($returnVoid ? "" : " v8Undefined()") . ";\n");
1624         push(@$outputArray, $indent . "ScriptState& state = *currentState;\n");
1625         push(@callWithArgs, "&state");
1626     }
1627     if ($codeGenerator->ExtendedAttributeContains($callWith, "ScriptExecutionContext")) {
1628         push(@$outputArray, $indent . "ScriptExecutionContext* scriptContext = getScriptExecutionContext();\n");
1629         push(@callWithArgs, "scriptContext");
1630     }
1631     if ($function and $codeGenerator->ExtendedAttributeContains($callWith, "ScriptArguments")) {
1632         push(@$outputArray, $indent . "RefPtr<ScriptArguments> scriptArguments(createScriptArguments(args, " . @{$function->parameters} . "));\n");
1633         push(@callWithArgs, "scriptArguments.release()");
1634         AddToImplIncludes("ScriptArguments.h");
1635         AddToImplIncludes("ScriptCallStackFactory.h");
1636     }
1637     return @callWithArgs;
1638 }
1639
1640 sub GenerateArgumentsCountCheck
1641 {
1642     my $function = shift;
1643     my $interface = shift;
1644
1645     my $numMandatoryParams = 0;
1646     my $allowNonOptional = 1;
1647     foreach my $param (@{$function->parameters}) {
1648         if ($param->extendedAttributes->{"Optional"} or $param->isVariadic) {
1649             $allowNonOptional = 0;
1650         } else {
1651             die "An argument must not be declared to be optional unless all subsequent arguments to the operation are also optional." if !$allowNonOptional;
1652             $numMandatoryParams++;
1653         }
1654     }
1655
1656     my $argumentsCountCheckString = "";
1657     if ($numMandatoryParams >= 1) {
1658         $argumentsCountCheckString .= "    if (args.Length() < $numMandatoryParams)\n";
1659         $argumentsCountCheckString .= "        return throwNotEnoughArgumentsError(args.GetIsolate());\n";
1660     }
1661     return $argumentsCountCheckString;
1662 }
1663
1664 sub GetIndexOf
1665 {
1666     my $paramName = shift;
1667     my @paramList = @_;
1668     my $index = 0;
1669     foreach my $param (@paramList) {
1670         if ($paramName eq $param) {
1671             return $index;
1672         }
1673         $index++;
1674     }
1675     return -1;
1676 }
1677
1678 sub GenerateParametersCheck
1679 {
1680     my $function = shift;
1681     my $interfaceName = shift;
1682
1683     my $parameterCheckString = "";
1684     my $paramIndex = 0;
1685     my @paramTransferListNames = ();
1686     my %replacements = ();
1687
1688     foreach my $parameter (@{$function->parameters}) {
1689         TranslateParameter($parameter);
1690         my $nativeType = GetNativeTypeFromSignature($parameter, $paramIndex);
1691
1692         # Optional arguments with [Optional] should generate an early call with fewer arguments.
1693         # Optional arguments with [Optional=...] should not generate the early call.
1694         # Optional Dictionary arguments always considered to have default of empty dictionary.
1695         my $optional = $parameter->extendedAttributes->{"Optional"};
1696         if ($optional && $optional ne "DefaultIsUndefined" && $optional ne "DefaultIsNullString" && $nativeType ne "Dictionary" && !$parameter->extendedAttributes->{"Callback"}) {
1697             $parameterCheckString .= "    if (args.Length() <= $paramIndex) {\n";
1698             my $functionCall = GenerateFunctionCallString($function, $paramIndex, "    " x 2, $interfaceName, %replacements);
1699             $parameterCheckString .= $functionCall;
1700             $parameterCheckString .= "    }\n";
1701         }
1702
1703         my $parameterDefaultPolicy = "DefaultIsUndefined";
1704         if ($optional and $optional eq "DefaultIsNullString") {
1705             $parameterDefaultPolicy = "DefaultIsNullString";
1706         }
1707
1708         my $parameterName = $parameter->name;
1709         if (GetIndexOf($parameterName, @paramTransferListNames) != -1) {
1710             $replacements{$parameterName} = "messagePortArray" . ucfirst($parameterName);
1711             $paramIndex++;
1712             next;
1713         }
1714
1715         AddToImplIncludes("ExceptionCode.h");
1716         if ($parameter->extendedAttributes->{"Callback"}) {
1717             my $v8InterfaceName = "V8" . $parameter->type;
1718             AddToImplIncludes("$v8InterfaceName.h");
1719             if ($optional) {
1720                 $parameterCheckString .= "    RefPtr<" . $parameter->type . "> $parameterName;\n";
1721                 $parameterCheckString .= "    if (args.Length() > $paramIndex && !args[$paramIndex]->IsNull() && !args[$paramIndex]->IsUndefined()) {\n";
1722                 $parameterCheckString .= "        if (!args[$paramIndex]->IsFunction())\n";
1723                 $parameterCheckString .= "            return throwTypeError(0, args.GetIsolate());\n";
1724                 $parameterCheckString .= "        $parameterName = ${v8InterfaceName}::create(args[$paramIndex], getScriptExecutionContext());\n";
1725                 $parameterCheckString .= "    }\n";
1726             } else {
1727                 $parameterCheckString .= "    if (args.Length() <= $paramIndex || !args[$paramIndex]->IsFunction())\n";
1728                 $parameterCheckString .= "        return throwTypeError(0, args.GetIsolate());\n";
1729                 $parameterCheckString .= "    RefPtr<" . $parameter->type . "> $parameterName = ${v8InterfaceName}::create(args[$paramIndex], getScriptExecutionContext());\n";
1730             }
1731         } elsif ($parameter->extendedAttributes->{"Clamp"}) {
1732                 my $nativeValue = "${parameterName}NativeValue";
1733                 my $paramType = $parameter->type;
1734                 $parameterCheckString .= "    $paramType $parameterName = 0;\n";
1735                 $parameterCheckString .= "    V8TRYCATCH(double, $nativeValue, args[$paramIndex]->NumberValue());\n";
1736                 $parameterCheckString .= "    if (!isnan($nativeValue))\n";
1737                 $parameterCheckString .= "        $parameterName = clampTo<$paramType>($nativeValue);\n";
1738         } elsif ($parameter->type eq "SerializedScriptValue") {
1739             AddToImplIncludes("SerializedScriptValue.h");
1740             my $useTransferList = 0;
1741             my $transferListName = "";
1742             my $TransferListName = "";
1743             if ($parameter->extendedAttributes->{"TransferList"}) {
1744                 $transferListName = $parameter->extendedAttributes->{"TransferList"};
1745                 push(@paramTransferListNames, $transferListName);
1746
1747                 my @allParameterNames = ();
1748                 foreach my $parameter (@{$function->parameters}) {
1749                     push(@allParameterNames, $parameter->name);
1750                 }
1751                 my $transferListIndex = GetIndexOf($transferListName, @allParameterNames);
1752                 if ($transferListIndex == -1) {
1753                     die "IDL error: TransferList refers to a nonexistent argument";
1754                 }
1755
1756                 AddToImplIncludes("wtf/ArrayBuffer.h");
1757                 AddToImplIncludes("MessagePort.h");
1758                 $TransferListName = ucfirst($transferListName);
1759                 $parameterCheckString .= "    MessagePortArray messagePortArray$TransferListName;\n";
1760                 $parameterCheckString .= "    ArrayBufferArray arrayBufferArray$TransferListName;\n";
1761                 $parameterCheckString .= "    if (args.Length() > $transferListIndex) {\n";
1762                 $parameterCheckString .= "        if (!extractTransferables(args[$transferListIndex], messagePortArray$TransferListName, arrayBufferArray$TransferListName, args.GetIsolate()))\n";
1763                 $parameterCheckString .= "            return throwTypeError(\"Could not extract transferables\", args.GetIsolate());\n";
1764                 $parameterCheckString .= "    }\n";
1765                 $useTransferList = 1;
1766             }
1767             $parameterCheckString .= "    bool ${parameterName}DidThrow = false;\n";
1768             if (!$useTransferList) {
1769                     $parameterCheckString .= "    $nativeType $parameterName = SerializedScriptValue::create(args[$paramIndex], 0, 0, ${parameterName}DidThrow, args.GetIsolate());\n";
1770             } else {
1771                     $parameterCheckString .= "    $nativeType $parameterName = SerializedScriptValue::create(args[$paramIndex], &messagePortArray$TransferListName, &arrayBufferArray$TransferListName, ${parameterName}DidThrow, args.GetIsolate());\n";
1772             }
1773             $parameterCheckString .= "    if (${parameterName}DidThrow)\n";
1774             $parameterCheckString .= "        return v8Undefined();\n";
1775         } elsif (TypeCanFailConversion($parameter)) {
1776             $parameterCheckString .= "    $nativeType $parameterName = " .
1777                  JSValueToNative($parameter, "args[$paramIndex]", "args.GetIsolate()") . ";\n";
1778             $parameterCheckString .= "    if (UNLIKELY(!$parameterName)) {\n";
1779             $parameterCheckString .= "        ec = TYPE_MISMATCH_ERR;\n";
1780             $parameterCheckString .= "        goto fail;\n";
1781             $parameterCheckString .= "    }\n";
1782         } elsif ($parameter->isVariadic) {
1783             my $nativeElementType = GetNativeType($parameter->type);
1784             if ($nativeElementType =~ />$/) {
1785                 $nativeElementType .= " ";
1786             }
1787
1788             my $argType = $parameter->type;
1789             if (IsWrapperType($argType)) {
1790                 $parameterCheckString .= "    Vector<$nativeElementType> $parameterName;\n";
1791                 $parameterCheckString .= "    for (int i = $paramIndex; i < args.Length(); ++i) {\n";
1792                 $parameterCheckString .= "        if (!V8${argType}::HasInstance(args[i]))\n";
1793                 $parameterCheckString .= "            return throwTypeError(0, args.GetIsolate());\n";
1794                 $parameterCheckString .= "        $parameterName.append(V8${argType}::toNative(v8::Handle<v8::Object>::Cast(args[i])));\n";
1795                 $parameterCheckString .= "    }\n";
1796             } else {
1797                 $parameterCheckString .= "    V8TRYCATCH(Vector<$nativeElementType>, $parameterName, toNativeArguments<$nativeElementType>(args, $paramIndex));\n";
1798             }
1799         } elsif ($nativeType =~ /^V8StringResource/) {
1800             my $value = JSValueToNative($parameter, "MAYBE_MISSING_PARAMETER(args, $paramIndex, $parameterDefaultPolicy)", "args.GetIsolate()");
1801             $parameterCheckString .= "    " . ConvertToV8StringResource($parameter, $nativeType, $parameterName, $value) . "\n";
1802         } else {
1803             # If the "StrictTypeChecking" extended attribute is present, and the argument's type is an
1804             # interface type, then if the incoming value does not implement that interface, a TypeError
1805             # is thrown rather than silently passing NULL to the C++ code.
1806             # Per the Web IDL and ECMAScript specifications, incoming values can always be converted
1807             # to both strings and numbers, so do not throw TypeError if the argument is of these
1808             # types.
1809             if ($function->signature->extendedAttributes->{"StrictTypeChecking"}) {
1810                 my $argValue = "args[$paramIndex]";
1811                 my $argType = $parameter->type;
1812                 if (IsWrapperType($argType)) {
1813                     $parameterCheckString .= "    if (args.Length() > $paramIndex && !isUndefinedOrNull($argValue) && !V8${argType}::HasInstance($argValue))\n";
1814                     $parameterCheckString .= "        return throwTypeError(0, args.GetIsolate());\n";
1815                 }
1816             }
1817             $parameterCheckString .= "    V8TRYCATCH($nativeType, $parameterName, " .
1818                  JSValueToNative($parameter, "MAYBE_MISSING_PARAMETER(args, $paramIndex, $parameterDefaultPolicy)", "args.GetIsolate()") . ");\n";
1819             if ($nativeType eq 'Dictionary') {
1820                $parameterCheckString .= "    if (!$parameterName.isUndefinedOrNull() && !$parameterName.isObject())\n";
1821                $parameterCheckString .= "        return throwTypeError(\"Not an object.\", args.GetIsolate());\n";
1822             }
1823         }
1824
1825         if ($parameter->extendedAttributes->{"IsIndex"}) {
1826             $parameterCheckString .= "    if (UNLIKELY($parameterName < 0)) {\n";
1827             $parameterCheckString .= "        ec = INDEX_SIZE_ERR;\n";
1828             $parameterCheckString .= "        goto fail;\n";
1829             $parameterCheckString .= "    }\n";
1830         }
1831
1832         $paramIndex++;
1833     }
1834     return ($parameterCheckString, $paramIndex, %replacements);
1835 }
1836
1837 sub GenerateOverloadedConstructorCallback
1838 {
1839     my $interface = shift;
1840     my $interfaceName = $interface->name;
1841
1842     push(@implContent, <<END);
1843 v8::Handle<v8::Value> V8${interfaceName}::constructorCallback(const v8::Arguments& args)
1844 {
1845 END
1846     push(@implContent, GenerateConstructorHeader());
1847
1848     my $leastNumMandatoryParams = 255;
1849     foreach my $constructor (@{$interface->constructors}) {
1850         my $name = "constructor" . $constructor->{overloadedIndex} . "Callback";
1851         my ($numMandatoryParams, $parametersCheck) = GenerateFunctionParametersCheck($constructor);
1852         $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams < $leastNumMandatoryParams);
1853         push(@implContent, "    if ($parametersCheck)\n");
1854         push(@implContent, "        return $name(args);\n");
1855     }
1856     if ($leastNumMandatoryParams >= 1) {
1857         push(@implContent, "    if (args.Length() < $leastNumMandatoryParams)\n");
1858         push(@implContent, "        return throwNotEnoughArgumentsError(args.GetIsolate());\n");
1859     }
1860     push(@implContent, <<END);
1861     return throwTypeError(0, args.GetIsolate());
1862 END
1863     push(@implContent, "}\n\n");
1864 }
1865
1866 sub GenerateSingleConstructorCallback
1867 {
1868     my $interface = shift;
1869     my $function = shift;
1870
1871     my $interfaceName = $interface->name;
1872     my $overloadedIndexString = "";
1873     if ($function->{overloadedIndex} > 0) {
1874         $overloadedIndexString .= $function->{overloadedIndex};
1875     }
1876
1877     my $raisesExceptions = @{$function->raisesExceptions};
1878     if ($interface->extendedAttributes->{"ConstructorRaisesException"}) {
1879         $raisesExceptions = 1;
1880     }
1881     if (!$raisesExceptions) {
1882         foreach my $parameter (@{$function->parameters}) {
1883             if ((!$parameter->extendedAttributes->{"Callback"} and TypeCanFailConversion($parameter)) or $parameter->extendedAttributes->{"IsIndex"}) {
1884                 $raisesExceptions = 1;
1885             }
1886         }
1887     }
1888
1889     my $maybeObserveFeature = GenerateFeatureObservation($function->signature->extendedAttributes->{"V8MeasureAs"});
1890
1891     my @beforeArgumentList;
1892     my @afterArgumentList;
1893     push(@implContent, <<END);
1894 v8::Handle<v8::Value> V8${interfaceName}::constructor${overloadedIndexString}Callback(const v8::Arguments& args)
1895 {
1896     ${maybeObserveFeature}
1897 END
1898
1899     if ($function->{overloadedIndex} == 0) {
1900         push(@implContent, GenerateConstructorHeader());
1901         push(@implContent, GenerateArgumentsCountCheck($function, $interface));
1902     }
1903
1904     if ($raisesExceptions) {
1905         AddToImplIncludes("ExceptionCode.h");
1906         push(@implContent, "\n");
1907         push(@implContent, "    ExceptionCode ec = 0;\n");
1908     }
1909
1910     # FIXME: Currently [Constructor(...)] does not yet support [Optional] arguments.
1911     # It just supports [Optional=DefaultIsUndefined] or [Optional=DefaultIsNullString].
1912     my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersCheck($function, $interfaceName);
1913     push(@implContent, $parameterCheckString);
1914
1915     if ($interface->extendedAttributes->{"CallWith"} && $interface->extendedAttributes->{"CallWith"} eq "ScriptExecutionContext") {
1916         push(@beforeArgumentList, "context");
1917         push(@implContent, <<END);
1918
1919     ScriptExecutionContext* context = getScriptExecutionContext();
1920 END
1921     }
1922
1923     if ($interface->extendedAttributes->{"ConstructorRaisesException"}) {
1924         push(@afterArgumentList, "ec");
1925     }
1926
1927     my @argumentList;
1928     my $index = 0;
1929     foreach my $parameter (@{$function->parameters}) {
1930         last if $index eq $paramIndex;
1931         if ($replacements{$parameter->name}) {
1932             push(@argumentList, $replacements{$parameter->name});
1933         } else {
1934             push(@argumentList, $parameter->name);
1935         }
1936         $index++;
1937     }
1938
1939     my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterArgumentList);
1940     push(@implContent, "\n");
1941     push(@implContent, "    RefPtr<${interfaceName}> impl = ${interfaceName}::create(${argumentString});\n");
1942     push(@implContent, "    v8::Handle<v8::Object> wrapper = args.Holder();\n");
1943
1944     if ($interface->extendedAttributes->{"ConstructorRaisesException"}) {
1945         push(@implContent, "    if (ec)\n");
1946         push(@implContent, "        goto fail;\n");
1947     }
1948
1949     push(@implContent, <<END);
1950
1951     V8DOMWrapper::associateObjectWithWrapper(impl.release(), &info, wrapper, args.GetIsolate());
1952     return wrapper;
1953 END
1954
1955     if ($raisesExceptions) {
1956         push(@implContent, "  fail:\n");
1957         push(@implContent, "    return setDOMException(ec, args.GetIsolate());\n");
1958     }
1959
1960     push(@implContent, "}\n");
1961     push(@implContent, "\n");
1962 }
1963
1964 sub GenerateCustomConstructorCallback
1965 {
1966     my $interface = shift;
1967
1968     my $interfaceName = $interface->name;
1969     my $maybeObserveFeature = GenerateFeatureObservation($interface->extendedAttributes->{"V8MeasureAs"});
1970     push(@implContent, <<END);
1971 v8::Handle<v8::Value> V8${interfaceName}::constructorCallback(const v8::Arguments& args)
1972 {
1973     ${maybeObserveFeature}
1974 END
1975     push(@implContent, GenerateConstructorHeader());
1976     push(@implContent, <<END);
1977
1978     return V8${interfaceName}::constructorCallbackCustom(args);
1979 }
1980
1981 END
1982 }
1983
1984 sub GenerateConstructorCallback
1985 {
1986     my $interface = shift;
1987     my $interfaceName = $interface->name;
1988
1989     if (@{$interface->constructors} == 1) {
1990         GenerateSingleConstructorCallback($interface, @{$interface->constructors}[0]);
1991     } else {
1992         foreach my $constructor (@{$interface->constructors}) {
1993             GenerateSingleConstructorCallback($interface, $constructor);
1994         }
1995         GenerateOverloadedConstructorCallback($interface);
1996     }
1997 }
1998
1999 sub GenerateEventConstructorCallback
2000 {
2001     my $interface = shift;
2002     my $interfaceName = $interface->name;
2003
2004     AddToImplIncludes("Dictionary.h");
2005     push(@implContent, <<END);
2006 v8::Handle<v8::Value> V8${interfaceName}::constructorCallback(const v8::Arguments& args)
2007 {
2008 END
2009     push(@implContent, GenerateConstructorHeader());
2010
2011     push(@implContent, <<END);
2012     if (args.Length() < 1)
2013         return throwNotEnoughArgumentsError(args.GetIsolate());
2014
2015     V8TRYCATCH_FOR_V8STRINGRESOURCE(V8StringResource<>, type, args[0]);
2016     ${interfaceName}Init eventInit;
2017     if (args.Length() >= 2) {
2018         V8TRYCATCH(Dictionary, options, Dictionary(args[1], args.GetIsolate()));
2019         if (!fill${interfaceName}Init(eventInit, options))
2020             return v8Undefined();
2021     }
2022
2023     RefPtr<${interfaceName}> event = ${interfaceName}::create(type, eventInit);
2024
2025     v8::Handle<v8::Object> wrapper = args.Holder();
2026     V8DOMWrapper::associateObjectWithWrapper(event.release(), &info, wrapper, args.GetIsolate());
2027     return wrapper;
2028 }
2029
2030 bool fill${interfaceName}Init(${interfaceName}Init& eventInit, const Dictionary& options)
2031 {
2032 END
2033
2034     foreach my $interfaceBase (@{$interface->parents}) {
2035         push(@implContent, <<END);
2036     if (!fill${interfaceBase}Init(eventInit, options))
2037         return false;
2038
2039 END
2040     }
2041
2042     for (my $index = 0; $index < @{$interface->attributes}; $index++) {
2043         my $attribute = @{$interface->attributes}[$index];
2044         if ($attribute->signature->extendedAttributes->{"InitializedByEventConstructor"}) {
2045             my $attributeName = $attribute->signature->name;
2046             push(@implContent, "    options.get(\"$attributeName\", eventInit.$attributeName);\n");
2047         }
2048     }
2049
2050     push(@implContent, <<END);
2051     return true;
2052 }
2053
2054 END
2055 }
2056
2057 sub GenerateTypedArrayConstructorCallback
2058 {
2059     my $interface = shift;
2060     my $interfaceName = $interface->name;
2061     my $viewType = GetTypeNameOfExternalTypedArray($interface);
2062     my $type = $interface->extendedAttributes->{"TypedArray"};
2063     AddToImplIncludes("V8ArrayBufferViewCustom.h");
2064
2065     push(@implContent, <<END);
2066 v8::Handle<v8::Value> V8${interfaceName}::constructorCallback(const v8::Arguments& args)
2067 {
2068     return constructWebGLArray<$interfaceName, V8${interfaceName}, $type>(args, &info, $viewType);
2069 }
2070
2071 END
2072 }
2073
2074 sub GenerateNamedConstructorCallback
2075 {
2076     my $function = shift;
2077     my $interface = shift;
2078
2079     my $interfaceName = $interface->name;
2080     my $v8InterfaceName = "V8$interfaceName";
2081     my $raisesExceptions = @{$function->raisesExceptions};
2082     if ($interface->extendedAttributes->{"ConstructorRaisesException"}) {
2083         $raisesExceptions = 1;
2084     }
2085     if (!$raisesExceptions) {
2086         foreach my $parameter (@{$function->parameters}) {
2087             if ((!$parameter->extendedAttributes->{"Callback"} and TypeCanFailConversion($parameter)) or $parameter->extendedAttributes->{"IsIndex"}) {
2088                 $raisesExceptions = 1;
2089             }
2090         }
2091     }
2092
2093     my $maybeObserveFeature = GenerateFeatureObservation($function->signature->extendedAttributes->{"V8MeasureAs"});
2094
2095     my @beforeArgumentList;
2096     my @afterArgumentList;
2097
2098     my $toActiveDOMObject = "0";
2099     if ($interface->extendedAttributes->{"ActiveDOMObject"}) {
2100         $toActiveDOMObject = "${v8InterfaceName}::toActiveDOMObject";
2101     }
2102
2103     my $toEventTarget = "0";
2104     if ($codeGenerator->InheritsExtendedAttribute($interface, "EventTarget")) {
2105         $toEventTarget = "${v8InterfaceName}::toEventTarget";
2106     }
2107
2108     AddToImplIncludes("Frame.h");
2109     push(@implContent, <<END);
2110 WrapperTypeInfo ${v8InterfaceName}Constructor::info = { ${v8InterfaceName}Constructor::GetTemplate, ${v8InterfaceName}::derefObject, $toActiveDOMObject, $toEventTarget, 0, ${v8InterfaceName}::installPerContextPrototypeProperties, 0, WrapperTypeObjectPrototype };
2111
2112 static v8::Handle<v8::Value> ${v8InterfaceName}ConstructorCallback(const v8::Arguments& args)
2113 {
2114     ${maybeObserveFeature}
2115 END
2116     push(@implContent, GenerateConstructorHeader());
2117     push(@implContent, <<END);
2118     Document* document = currentDocument(BindingState::instance());
2119
2120     // Make sure the document is added to the DOM Node map. Otherwise, the ${interfaceName} instance
2121     // may end up being the only node in the map and get garbage-collected prematurely.
2122     toV8(document, args.Holder(), args.GetIsolate());
2123
2124 END
2125
2126     push(@implContent, GenerateArgumentsCountCheck($function, $interface));
2127
2128     if ($raisesExceptions) {
2129         AddToImplIncludes("ExceptionCode.h");
2130         push(@implContent, "\n");
2131         push(@implContent, "    ExceptionCode ec = 0;\n");
2132     }
2133
2134     my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersCheck($function, $interfaceName);
2135     push(@implContent, $parameterCheckString);
2136
2137     push(@beforeArgumentList, "document");
2138
2139     if ($interface->extendedAttributes->{"ConstructorRaisesException"}) {
2140         push(@afterArgumentList, "ec");
2141     }
2142
2143     my @argumentList;
2144     my $index = 0;
2145     foreach my $parameter (@{$function->parameters}) {
2146         last if $index eq $paramIndex;
2147         if ($replacements{$parameter->name}) {
2148             push(@argumentList, $replacements{$parameter->name});
2149         } else {
2150             push(@argumentList, $parameter->name);
2151         }
2152         $index++;
2153     }
2154
2155     my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterArgumentList);
2156     push(@implContent, "\n");
2157     push(@implContent, "    RefPtr<${interfaceName}> impl = ${interfaceName}::createForJSConstructor(${argumentString});\n");
2158     push(@implContent, "    v8::Handle<v8::Object> wrapper = args.Holder();\n");
2159
2160     if ($interface->extendedAttributes->{"ConstructorRaisesException"}) {
2161         push(@implContent, "    if (ec)\n");
2162         push(@implContent, "        goto fail;\n");
2163     }
2164
2165     push(@implContent, <<END);
2166
2167     V8DOMWrapper::associateObjectWithWrapper(impl.release(), &${v8InterfaceName}Constructor::info, wrapper, args.GetIsolate());
2168     return wrapper;
2169 END
2170
2171     if ($raisesExceptions) {
2172         push(@implContent, "  fail:\n");
2173         push(@implContent, "    return setDOMException(ec, args.GetIsolate());\n");
2174     }
2175
2176     push(@implContent, "}\n");
2177
2178     push(@implContent, <<END);
2179
2180 v8::Persistent<v8::FunctionTemplate> ${v8InterfaceName}Constructor::GetTemplate(v8::Isolate* isolate)
2181 {
2182     if (!isolate)
2183         isolate = v8::Isolate::GetCurrent();
2184     static v8::Persistent<v8::FunctionTemplate> cachedTemplate;
2185     if (!cachedTemplate.IsEmpty())
2186         return cachedTemplate;
2187
2188     v8::HandleScope scope;
2189     v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(${v8InterfaceName}ConstructorCallback);
2190
2191     v8::Local<v8::ObjectTemplate> instance = result->InstanceTemplate();
2192     instance->SetInternalFieldCount(${v8InterfaceName}::internalFieldCount);
2193     result->SetClassName(v8::String::NewSymbol("${interfaceName}"));
2194     result->Inherit(${v8InterfaceName}::GetTemplate());
2195
2196     cachedTemplate = v8::Persistent<v8::FunctionTemplate>::New(result);
2197     return cachedTemplate;
2198 }
2199
2200 END
2201 }
2202
2203 sub GenerateConstructorHeader
2204 {
2205     my $content = <<END;
2206     if (!args.IsConstructCall())
2207         return throwTypeError("DOM object constructor cannot be called as a function.", args.GetIsolate());
2208
2209     if (ConstructorMode::current() == ConstructorMode::WrapExistingObject)
2210         return args.Holder();
2211 END
2212     return $content;
2213 }
2214
2215 sub GenerateBatchedAttributeData
2216 {
2217     my $interface = shift;
2218     my $attributes = shift;
2219     my $interfaceName = $interface->name;
2220
2221     foreach my $attribute (@$attributes) {
2222         my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
2223         push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
2224         GenerateSingleBatchedAttribute($interfaceName, $attribute, ",", "");
2225         push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
2226     }
2227 }
2228
2229 sub GenerateSingleBatchedAttribute
2230 {
2231     my $interfaceName = shift;
2232     my $attribute = shift;
2233     my $delimiter = shift;
2234     my $indent = shift;
2235     my $attrName = $attribute->signature->name;
2236     my $attrExt = $attribute->signature->extendedAttributes;
2237
2238     my $accessControl = "v8::DEFAULT";
2239     if ($attrExt->{"DoNotCheckSecurityOnGetter"}) {
2240         $accessControl = "v8::ALL_CAN_READ";
2241     } elsif ($attrExt->{"DoNotCheckSecurityOnSetter"}) {
2242         $accessControl = "v8::ALL_CAN_WRITE";
2243     } elsif ($attrExt->{"DoNotCheckSecurity"}) {
2244         $accessControl = "v8::ALL_CAN_READ";
2245         if (!IsReadonly($attribute)) {
2246             $accessControl .= " | v8::ALL_CAN_WRITE";
2247         }
2248     }
2249     if ($attrExt->{"V8Unforgeable"}) {
2250         $accessControl .= " | v8::PROHIBITS_OVERWRITING";
2251     }
2252     $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")";
2253
2254     my $customAccessor =
2255         $attrExt->{"Custom"} ||
2256         $attrExt->{"CustomSetter"} ||
2257         $attrExt->{"CustomGetter"} ||
2258         $attrExt->{"V8Custom"} ||
2259         $attrExt->{"V8CustomSetter"} ||
2260         $attrExt->{"V8CustomGetter"} ||
2261         "";
2262     if ($customAccessor eq "VALUE_IS_MISSING") {
2263         # use the naming convension, interface + (capitalize) attr name
2264         $customAccessor = $interfaceName . "::" . $attrName;
2265     }
2266
2267     my $getter;
2268     my $setter;
2269     my $propAttr = "v8::None";
2270
2271     # Check attributes.
2272     if ($attrExt->{"NotEnumerable"}) {
2273         $propAttr .= " | v8::DontEnum";
2274     }
2275     if ($attrExt->{"V8Unforgeable"}) {
2276         $propAttr .= " | v8::DontDelete";
2277     }
2278
2279     my $on_proto = "0 /* on instance */";
2280     my $data = "0 /* no data */";
2281
2282     # Constructor
2283     if ($attribute->signature->type =~ /Constructor$/) {
2284         my $constructorType = $attribute->signature->type;
2285         $constructorType =~ s/Constructor$//;
2286         # $constructorType ~= /Constructor$/ indicates that it is NamedConstructor.
2287         # We do not generate the header file for NamedConstructor of class XXXX,
2288         # since we generate the NamedConstructor declaration into the header file of class XXXX.
2289         if ($constructorType !~ /Constructor$/ || $attribute->signature->extendedAttributes->{"V8CustomConstructor"} || $attribute->signature->extendedAttributes->{"CustomConstructor"}) {
2290             AddToImplIncludes("V8${constructorType}.h", $attribute->signature->extendedAttributes->{"Conditional"});
2291         }
2292         if ($customAccessor) {
2293             $getter = "V8${customAccessor}AccessorGetter";
2294         } else {
2295             $data = "&V8${constructorType}::info";
2296             $getter = "${interfaceName}V8Internal::${interfaceName}ConstructorGetter";
2297         }
2298         $setter = "${interfaceName}V8Internal::${interfaceName}ReplaceableAttrSetter";
2299     } else {
2300         # Default Getter and Setter
2301         $getter = "${interfaceName}V8Internal::${attrName}AttrGetter";
2302         $setter = "${interfaceName}V8Internal::${attrName}AttrSetter";
2303
2304         if ($attrExt->{"Replaceable"}) {
2305             $setter = "${interfaceName}V8Internal::${interfaceName}ReplaceableAttrSetter";
2306         }
2307
2308         # Custom Setter
2309         if ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
2310             $setter = "V8${customAccessor}AccessorSetter";
2311         }
2312
2313         # Custom Getter
2314         if ($attrExt->{"CustomGetter"} || $attrExt->{"V8CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
2315             $getter = "V8${customAccessor}AccessorGetter";
2316         }
2317     }
2318
2319     # Read only attributes
2320     if (IsReadonly($attribute)) {
2321         $setter = "0";
2322     }
2323
2324     # An accessor can be installed on the proto
2325     if ($attrExt->{"V8OnProto"}) {
2326         $on_proto = "1 /* on proto */";
2327     }
2328
2329     my $commentInfo = "Attribute '$attrName' (Type: '" . $attribute->type .
2330                       "' ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
2331
2332     push(@implContent, $indent . "    \/\/ $commentInfo\n");
2333     push(@implContent, $indent . "    {\"$attrName\", $getter, $setter, $data, $accessControl, static_cast<v8::PropertyAttribute>($propAttr), $on_proto}" . $delimiter . "\n");
2334 }
2335
2336 sub IsStandardFunction
2337 {
2338     my $interface = shift;
2339     my $function = shift;
2340
2341     my $interfaceName = $interface->name;
2342     my $attrExt = $function->signature->extendedAttributes;
2343     return 0 if $attrExt->{"V8Unforgeable"};
2344     return 0 if $function->isStatic;
2345     return 0 if $attrExt->{"V8EnabledAtRuntime"};
2346     return 0 if $attrExt->{"V8EnabledPerContext"};
2347     return 0 if RequiresCustomSignature($function);
2348     return 0 if $attrExt->{"V8DoNotCheckSignature"};
2349     return 0 if ($attrExt->{"DoNotCheckSecurity"} && ($interface->extendedAttributes->{"CheckSecurity"} || $interfaceName eq "DOMWindow"));
2350     return 0 if $attrExt->{"NotEnumerable"};
2351     return 0 if $attrExt->{"V8ReadOnly"};
2352     return 1;
2353 }
2354
2355 sub GenerateNonStandardFunction
2356 {
2357     my $interface = shift;
2358     my $function = shift;
2359
2360     my $interfaceName = $interface->name;
2361     my $attrExt = $function->signature->extendedAttributes;
2362     my $name = $function->signature->name;
2363
2364     my $property_attributes = "v8::DontDelete";
2365     if ($attrExt->{"NotEnumerable"}) {
2366         $property_attributes .= " | v8::DontEnum";
2367     }
2368     if ($attrExt->{"V8ReadOnly"}) {
2369         $property_attributes .= " | v8::ReadOnly";
2370     }
2371
2372     my $commentInfo = "Function '$name' (ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
2373
2374     my $template = "proto";
2375     if ($attrExt->{"V8Unforgeable"}) {
2376         $template = "instance";
2377     }
2378     if ($function->isStatic) {
2379         $template = "desc";
2380     }
2381
2382     my $conditional = "";
2383     if ($attrExt->{"V8EnabledAtRuntime"}) {
2384         # Only call Set()/SetAccessor() if this method should be enabled
2385         my $enable_function = GetRuntimeEnableFunctionName($function->signature);
2386         $conditional = "if (${enable_function}())\n        ";
2387     }
2388     if ($attrExt->{"V8EnabledPerContext"}) {
2389         # Only call Set()/SetAccessor() if this method should be enabled
2390         my $enable_function = GetContextEnableFunction($function->signature);
2391         $conditional = "if (${enable_function}(impl->document()))\n        ";
2392     }
2393
2394     if ($attrExt->{"DoNotCheckSecurity"} &&
2395         ($interface->extendedAttributes->{"CheckSecurity"} || $interfaceName eq "DOMWindow")) {
2396         # Functions that are marked DoNotCheckSecurity are always readable but if they are changed
2397         # and then accessed on a different domain we do not return the underlying value but instead
2398         # return a new copy of the original function. This is achieved by storing the changed value
2399         # as hidden property.
2400         push(@implContent, <<END);
2401
2402     // $commentInfo
2403     ${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));
2404 END
2405         return;
2406     }
2407
2408     my $signature = "defaultSignature";
2409     if ($attrExt->{"V8DoNotCheckSignature"} || $function->isStatic) {
2410        $signature = "v8::Local<v8::Signature>()";
2411     }
2412
2413     if (RequiresCustomSignature($function)) {
2414         $signature = "${name}Signature";
2415         push(@implContent, "\n    // Custom Signature '$name'\n", CreateCustomSignature($function));
2416     }
2417
2418     # Normal function call is a template
2419     my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
2420
2421     if ($property_attributes eq "v8::DontDelete") {
2422         $property_attributes = "";
2423     } else {
2424         $property_attributes = ", static_cast<v8::PropertyAttribute>($property_attributes)";
2425     }
2426
2427     if ($template eq "proto" && $conditional eq "" && $signature eq "defaultSignature" && $property_attributes eq "") {
2428         die "This shouldn't happen: Intraface '$interfaceName' $commentInfo\n";
2429     }
2430
2431     my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
2432     push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
2433
2434     push(@implContent, "    ${conditional}$template->Set(v8::String::NewSymbol(\"$name\"), v8::FunctionTemplate::New($callback, v8Undefined(), ${signature})$property_attributes);\n");
2435
2436     push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
2437 }
2438
2439 sub GenerateImplementationIndexer
2440 {
2441     my $interface = shift;
2442     my $indexer = shift;
2443     my $interfaceName = $interface->name;
2444     my $v8InterfaceName = "V8$interfaceName";
2445
2446     # FIXME: Figure out what NumericIndexedGetter is really supposed to do. Right now, it's only set on WebGL-related files.
2447     my $hasCustomSetter = $interface->extendedAttributes->{"CustomIndexedSetter"} && !$interface->extendedAttributes->{"NumericIndexedGetter"};
2448     my $hasGetter = $interface->extendedAttributes->{"IndexedGetter"} || $interface->extendedAttributes->{"CustomGetOwnPropertySlot"};
2449
2450     # FIXME: Investigate and remove this nastinesss. In V8, named property handling and indexer handling are apparently decoupled,
2451     # which means that object[X] where X is a number doesn't reach named property indexer. So we need to provide
2452     # simplistic, mirrored indexer handling in addition to named property handling.
2453     my $isSpecialCase = exists $indexerSpecialCases{$interfaceName};
2454     if ($isSpecialCase) {
2455         $hasGetter = 1;
2456         if ($interface->extendedAttributes->{"CustomNamedSetter"}) {
2457             $hasCustomSetter = 1;
2458         }
2459     }
2460
2461     my $hasEnumerator = !$isSpecialCase && $codeGenerator->IsSubType($interface, "Node");
2462
2463     # FIXME: Find a way to not have to special-case HTMLOptionsCollection.
2464     if ($interfaceName eq "HTMLOptionsCollection") {
2465         $hasEnumerator = 1;
2466         $hasGetter = 1;
2467     }
2468
2469     if (!$hasGetter) {
2470         return;
2471     }
2472
2473     AddToImplIncludes("V8Collection.h");
2474
2475     if (!$indexer) {
2476         $indexer = $codeGenerator->FindSuperMethod($interface, "item");
2477     }
2478
2479     my $indexerType = $indexer ? $indexer->type : 0;
2480
2481     # FIXME: Remove this once toV8 helper methods are implemented (see https://bugs.webkit.org/show_bug.cgi?id=32563).
2482     if ($interfaceName eq "WebKitCSSKeyframesRule") {
2483         $indexerType = "WebKitCSSKeyframeRule";
2484     }
2485
2486     if ($indexerType && !$hasCustomSetter) {
2487         if ($indexerType eq "DOMString") {
2488             my $conversion = $indexer->extendedAttributes->{"TreatReturnedNullStringAs"};
2489             if ($conversion && $conversion eq "Null") {
2490                 push(@implContent, <<END);
2491     setCollectionStringOrUndefinedIndexedGetter<${interfaceName}>(desc);
2492 END
2493             } else {
2494                 push(@implContent, <<END);
2495     setCollectionStringIndexedGetter<${interfaceName}>(desc);
2496 END
2497             }
2498         } else {
2499             push(@implContent, <<END);
2500     setCollectionIndexedGetter<${interfaceName}, ${indexerType}>(desc);
2501 END
2502             # Include the header for this indexer type, because setCollectionIndexedGetter() requires toV8() for this type.
2503             AddToImplIncludes("V8${indexerType}.h");
2504         }
2505
2506         return;
2507     }
2508
2509     my $hasDeleter = $interface->extendedAttributes->{"CustomDeleteProperty"};
2510     my $setOn = "Instance";
2511
2512     # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
2513     # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
2514     # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
2515     # on the object.
2516     if ($interfaceName eq "DOMWindow") {
2517         $setOn = "Prototype";
2518         $hasDeleter = 0;
2519     }
2520
2521     push(@implContent, "    desc->${setOn}Template()->SetIndexedPropertyHandler(${v8InterfaceName}::indexedPropertyGetter");
2522     push(@implContent, $hasCustomSetter ? ", ${v8InterfaceName}::indexedPropertySetter" : ", 0");
2523     push(@implContent, ", 0"); # IndexedPropertyQuery -- not being used at the moment.
2524     push(@implContent, $hasDeleter ? ", ${v8InterfaceName}::indexedPropertyDeleter" : ", 0");
2525     push(@implContent, ", nodeCollectionIndexedPropertyEnumerator<${interfaceName}>") if $hasEnumerator;
2526     push(@implContent, ");\n");
2527 }
2528
2529 sub GenerateImplementationNamedPropertyGetter
2530 {
2531     my $interface = shift;
2532     my $namedPropertyGetter = shift;
2533     my $interfaceName = $interface->name;
2534     my $v8InterfaceName = "V8$interfaceName";
2535     my $hasCustomNamedGetter = $interface->extendedAttributes->{"CustomNamedGetter"} || $interface->extendedAttributes->{"CustomGetOwnPropertySlot"};
2536
2537     if ($interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") {
2538         $hasCustomNamedGetter = 1;
2539     }
2540
2541     if ($interfaceName eq "HTMLDocument") {
2542         $hasCustomNamedGetter = 0;
2543     }
2544
2545     my $hasGetter = $interface->extendedAttributes->{"NamedGetter"} || $hasCustomNamedGetter;
2546     if (!$hasGetter) {
2547         return;
2548     }
2549
2550     if (!$namedPropertyGetter) {
2551         $namedPropertyGetter = $codeGenerator->FindSuperMethod($interface, "namedItem");
2552     }
2553
2554     if ($namedPropertyGetter && $namedPropertyGetter->type ne "Node" && !$namedPropertyGetter->extendedAttributes->{"Custom"} && !$hasCustomNamedGetter) {
2555         AddToImplIncludes("V8Collection.h");
2556         my $type = $namedPropertyGetter->type;
2557         push(@implContent, <<END);
2558     setCollectionNamedGetter<${interfaceName}, ${type}>(desc);
2559 END
2560         return;
2561     }
2562
2563     my $hasCustomNamedSetter = $interface->extendedAttributes->{"CustomNamedSetter"};
2564     my $hasDeleter = $interface->extendedAttributes->{"CustomDeleteProperty"};
2565     my $hasEnumerator = $interface->extendedAttributes->{"CustomEnumerateProperty"};
2566     my $setOn = "Instance";
2567
2568     # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
2569     # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
2570     # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
2571     # on the object.
2572     if ($interfaceName eq "DOMWindow") {
2573         $setOn = "Prototype";
2574         $hasDeleter = 0;
2575         $hasEnumerator = 0;
2576     }
2577
2578     if ($interfaceName eq "HTMLPropertiesCollection") {
2579         push(@implContent, "    desc->${setOn}Template()->SetNamedPropertyHandler(V8HTMLCollection::namedPropertyGetter, ");
2580     } else {
2581         push(@implContent, "    desc->${setOn}Template()->SetNamedPropertyHandler(${v8InterfaceName}::namedPropertyGetter, ");
2582     }
2583     push(@implContent, $hasCustomNamedSetter ? "${v8InterfaceName}::namedPropertySetter, " : "0, ");
2584     # If there is a custom enumerator, there MUST be custom query to properly communicate property attributes.
2585     push(@implContent, $hasEnumerator ? "${v8InterfaceName}::namedPropertyQuery, " : "0, ");
2586     push(@implContent, $hasDeleter ? "${v8InterfaceName}::namedPropertyDeleter, " : "0, ");
2587     push(@implContent, $hasEnumerator ? "${v8InterfaceName}::namedPropertyEnumerator" : "0");
2588     push(@implContent, ");\n");
2589 }
2590
2591 sub GenerateImplementationCustomCall
2592 {
2593     my $interface = shift;
2594     my $interfaceName = $interface->name;
2595
2596     if ($interface->extendedAttributes->{"CustomCall"}) {
2597         push(@implContent, "    desc->InstanceTemplate()->SetCallAsFunctionHandler(V8${interfaceName}::callAsFunctionCallback);\n");
2598     }
2599 }
2600
2601 sub GenerateImplementationMasqueradesAsUndefined
2602 {
2603     my $interface = shift;
2604     if ($interface->extendedAttributes->{"MasqueradesAsUndefined"})
2605     {
2606         push(@implContent, "    desc->InstanceTemplate()->MarkAsUndetectable();\n");
2607     }
2608 }
2609
2610 sub GenerateImplementation
2611 {
2612     my $object = shift;
2613     my $interface = shift;
2614     my $interfaceName = $interface->name;
2615     my $visibleInterfaceName = $codeGenerator->GetVisibleInterfaceName($interface);
2616     my $v8InterfaceName = "V8$interfaceName";
2617     my $nativeType = GetNativeTypeForConversions($interface);
2618
2619     # - Add default header template
2620     push(@implContentHeader, GenerateImplementationContentHeader($interface));
2621
2622     AddToImplIncludes("BindingState.h");
2623     AddToImplIncludes("ContextFeatures.h");
2624     AddToImplIncludes("RuntimeEnabledFeatures.h");
2625     AddToImplIncludes("V8Binding.h");
2626     AddToImplIncludes("V8DOMWrapper.h");
2627
2628     AddIncludesForType($interfaceName);
2629
2630     my $toActiveDOMObject = $interface->extendedAttributes->{"ActiveDOMObject"} ? "${v8InterfaceName}::toActiveDOMObject" : "0";
2631     my $toEventTarget = $codeGenerator->InheritsExtendedAttribute($interface, "EventTarget") ? "${v8InterfaceName}::toEventTarget" : "0";
2632     my $rootForGC = NeedsCustomOpaqueRootForGC($interface) ? "${v8InterfaceName}::opaqueRootForGC" : "0";
2633
2634     # Find the super descriptor.
2635     my $parentClass = "";
2636     my $parentClassTemplate = "";
2637     foreach (@{$interface->parents}) {
2638         my $parent = $_;
2639         AddToImplIncludes("V8${parent}.h");
2640         $parentClass = "V8" . $parent;
2641         $parentClassTemplate = $parentClass . "::GetTemplate()";
2642         last;
2643     }
2644     push(@implContentDecls, "namespace WebCore {\n\n");
2645     my $parentClassInfo = $parentClass ? "&${parentClass}::info" : "0";
2646
2647     my $WrapperTypePrototype = $interface->isException ? "WrapperTypeErrorPrototype" : "WrapperTypeObjectPrototype";
2648
2649     push(@implContentDecls, "WrapperTypeInfo ${v8InterfaceName}::info = { ${v8InterfaceName}::GetTemplate, ${v8InterfaceName}::derefObject, $toActiveDOMObject, $toEventTarget, $rootForGC, ${v8InterfaceName}::installPerContextPrototypeProperties, $parentClassInfo, $WrapperTypePrototype };\n\n");
2650     push(@implContentDecls, "namespace ${interfaceName}V8Internal {\n\n");
2651
2652     push(@implContentDecls, "template <typename T> void V8_USE(T) { }\n\n");
2653
2654     my $hasConstructors = 0;
2655     my $hasReplaceable = 0;
2656
2657     # Generate property accessors for attributes.
2658     for (my $index = 0; $index < @{$interface->attributes}; $index++) {
2659         my $attribute = @{$interface->attributes}[$index];
2660         my $attrType = $attribute->signature->type;
2661
2662         # Generate special code for the constructor attributes.
2663         if ($attrType =~ /Constructor$/) {
2664             if (!($attribute->signature->extendedAttributes->{"CustomGetter"} ||
2665                 $attribute->signature->extendedAttributes->{"V8CustomGetter"})) {
2666                 $hasConstructors = 1;
2667             }
2668             next;
2669         }
2670
2671         if ($attrType eq "EventListener" && $interfaceName eq "DOMWindow") {
2672             $attribute->signature->extendedAttributes->{"V8OnProto"} = 1;
2673         }
2674
2675         if ($attrType eq "SerializedScriptValue") {
2676             AddToImplIncludes("SerializedScriptValue.h");
2677         }
2678
2679         # Do not generate accessor if this is a custom attribute.  The
2680         # call will be forwarded to a hand-written accessor
2681         # implementation.
2682         if ($attribute->signature->extendedAttributes->{"Custom"} ||
2683             $attribute->signature->extendedAttributes->{"V8Custom"}) {
2684             next;
2685         }
2686
2687         # Generate the accessor.
2688         if (!($attribute->signature->extendedAttributes->{"CustomGetter"} ||
2689             $attribute->signature->extendedAttributes->{"V8CustomGetter"})) {
2690             GenerateNormalAttrGetter($attribute, $interface);
2691         }
2692
2693         if ($attribute->signature->extendedAttributes->{"Replaceable"}) {
2694             $hasReplaceable = 1;
2695         } elsif (!$attribute->signature->extendedAttributes->{"CustomSetter"} &&
2696             !$attribute->signature->extendedAttributes->{"V8CustomSetter"} &&
2697             !IsReadonly($attribute)) {
2698             GenerateNormalAttrSetter($attribute, $interface);
2699         }
2700     }
2701
2702     if ($hasConstructors) {
2703         GenerateConstructorGetter($interface);
2704     }
2705
2706     if ($hasConstructors || $hasReplaceable) {
2707         GenerateReplaceableAttrSetter($interface);
2708     }
2709
2710     if (NeedsCustomOpaqueRootForGC($interface)) {
2711         GenerateOpaqueRootForGC($interface);
2712     }
2713
2714     if ($interface->extendedAttributes->{"TypedArray"}) {
2715         my $viewType = GetTypeNameOfExternalTypedArray($interface);
2716         push(@implContent, <<END);
2717 v8::Handle<v8::Object> wrap($interfaceName* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
2718 {
2719     ASSERT(impl);
2720     v8::Handle<v8::Object> wrapper = ${v8InterfaceName}::createWrapper(impl, creationContext, isolate);
2721     if (!wrapper.IsEmpty())
2722         wrapper->SetIndexedPropertiesToExternalArrayData(impl->baseAddress(), $viewType, impl->length());
2723     return wrapper;
2724 }
2725
2726 END
2727     }
2728
2729     my $indexer;
2730     my $namedPropertyGetter;
2731     my @enabledPerContextFunctions;
2732     my @normalFunctions;
2733     my $needsDomainSafeFunctionSetter = 0;
2734     # Generate methods for functions.
2735     foreach my $function (@{$interface->functions}) {
2736         my $isCustom = $function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"V8Custom"};
2737         if (!$isCustom) {
2738             GenerateFunctionCallback($function, $interface);
2739             if ($function->{overloadIndex} > 1 && $function->{overloadIndex} == @{$function->{overloads}}) {
2740                 GenerateOverloadedFunctionCallback($function, $interface);
2741             }
2742         }
2743
2744         if ($function->signature->name eq "item") {
2745             $indexer = $function->signature;
2746         }
2747
2748         if ($interfaceName eq "HTMLPropertiesCollection") {
2749             if ($function->signature->name eq "propertyNodeList") {
2750                 $namedPropertyGetter = $function->signature;
2751             }
2752         } elsif ($function->signature->name eq "namedItem") {
2753             $namedPropertyGetter = $function->signature;
2754         }
2755
2756         # If the function does not need domain security check, we need to
2757         # generate an access getter that returns different function objects
2758         # for different calling context.
2759         if (($interface->extendedAttributes->{"CheckSecurity"} || ($interfaceName eq "DOMWindow")) && $function->signature->extendedAttributes->{"DoNotCheckSecurity"}) {
2760             if (!$isCustom || $function->{overloadIndex} == 1) {
2761                 GenerateDomainSafeFunctionGetter($function, $interfaceName);
2762                 $needsDomainSafeFunctionSetter = 1;
2763             }
2764         }
2765
2766         # Separate out functions that are enabled per context so we can process them specially.
2767         if ($function->signature->extendedAttributes->{"V8EnabledPerContext"}) {
2768             push(@enabledPerContextFunctions, $function);
2769         } else {
2770             push(@normalFunctions, $function);
2771         }
2772     }
2773
2774     if ($needsDomainSafeFunctionSetter) {
2775         GenerateDomainSafeFunctionSetter($interfaceName);
2776     }
2777
2778     # Attributes
2779     my $attributes = $interface->attributes;
2780
2781     # For the DOMWindow interface we partition the attributes into the
2782     # ones that disallows shadowing and the rest.
2783     my @disallowsShadowing;
2784     # Also separate out attributes that are enabled at runtime so we can process them specially.
2785     my @enabledAtRuntimeAttributes;
2786     my @enabledPerContextAttributes;
2787     my @normalAttributes;
2788     foreach my $attribute (@$attributes) {
2789
2790         if ($interfaceName eq "DOMWindow" && $attribute->signature->extendedAttributes->{"V8Unforgeable"}) {
2791             push(@disallowsShadowing, $attribute);
2792         } elsif ($attribute->signature->extendedAttributes->{"V8EnabledAtRuntime"}) {
2793             push(@enabledAtRuntimeAttributes, $attribute);
2794         } elsif ($attribute->signature->extendedAttributes->{"V8EnabledPerContext"}) {
2795             push(@enabledPerContextAttributes, $attribute);
2796         } else {
2797             push(@normalAttributes, $attribute);
2798         }
2799     }
2800     $attributes = \@normalAttributes;
2801     # Put the attributes that disallow shadowing on the shadow object.
2802     if (@disallowsShadowing) {
2803         push(@implContent, "static const V8DOMConfiguration::BatchedAttribute shadowAttrs[] = {\n");
2804         GenerateBatchedAttributeData($interface, \@disallowsShadowing);
2805         push(@implContent, "};\n\n");
2806     }
2807
2808     my $has_attributes = 0;
2809     if (@$attributes) {
2810         $has_attributes = 1;
2811         push(@implContent, "static const V8DOMConfiguration::BatchedAttribute ${v8InterfaceName}Attrs[] = {\n");
2812         GenerateBatchedAttributeData($interface, $attributes);
2813         push(@implContent, "};\n\n");
2814     }
2815
2816     # Setup table of standard callback functions
2817     my $num_callbacks = 0;
2818     my $has_callbacks = 0;
2819     foreach my $function (@normalFunctions) {
2820         # Only one table entry is needed for overloaded methods:
2821         next if $function->{overloadIndex} > 1;
2822         # Don't put any nonstandard functions into this table:
2823         next if !IsStandardFunction($interface, $function);
2824         if (!$has_callbacks) {
2825             $has_callbacks = 1;
2826             push(@implContent, "static const V8DOMConfiguration::BatchedCallback ${v8InterfaceName}Callbacks[] = {\n");
2827         }
2828         my $name = $function->signature->name;
2829         my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
2830         my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
2831         push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
2832         push(@implContent, <<END);
2833     {"$name", $callback},
2834 END
2835         push(@implContent, "#endif\n") if $conditionalString;
2836         $num_callbacks++;
2837     }
2838     push(@implContent, "};\n\n")  if $has_callbacks;
2839
2840     # Setup constants
2841     my $has_constants = 0;
2842     my @constantsEnabledAtRuntime;
2843     if (@{$interface->constants}) {
2844         $has_constants = 1;
2845         push(@implContent, "static const V8DOMConfiguration::BatchedConstant ${v8InterfaceName}Consts[] = {\n");
2846     }
2847     foreach my $constant (@{$interface->constants}) {
2848         my $name = $constant->name;
2849         my $value = $constant->value;
2850         my $attrExt = $constant->extendedAttributes;
2851         my $conditional = $attrExt->{"Conditional"};
2852         my $implementedBy = $attrExt->{"ImplementedBy"};
2853         if ($implementedBy) {
2854             AddToImplIncludes("${implementedBy}.h");
2855         }
2856         if ($attrExt->{"V8EnabledAtRuntime"}) {
2857             push(@constantsEnabledAtRuntime, $constant);
2858         } else {
2859             # FIXME: we need the static_cast here only because of one constant, NodeFilter.idl
2860             # defines "const unsigned long SHOW_ALL = 0xFFFFFFFF".  It would be better if we
2861             # handled this here, and converted it to a -1 constant in the c++ output.
2862             if ($conditional) {
2863                 my $conditionalString = $codeGenerator->GenerateConditionalStringFromAttributeValue($conditional);
2864                 push(@implContent, "#if ${conditionalString}\n");
2865             }
2866             push(@implContent, <<END);
2867     {"${name}", static_cast<signed int>($value)},
2868 END
2869             push(@implContent, "#endif\n") if $conditional;
2870         }
2871     }
2872     if ($has_constants) {
2873         push(@implContent, "};\n\n");
2874         push(@implContent, $codeGenerator->GenerateCompileTimeCheckForEnumsIfNeeded($interface));
2875     }
2876
2877     push(@implContentDecls, "} // namespace ${interfaceName}V8Internal\n\n");
2878
2879     if (HasCustomConstructor($interface)) {
2880         GenerateCustomConstructorCallback($interface);
2881     } elsif ($interface->extendedAttributes->{"NamedConstructor"}) {
2882         GenerateNamedConstructorCallback(@{$interface->constructors}[0], $interface);
2883     } elsif ($interface->extendedAttributes->{"Constructor"}) {
2884         GenerateConstructorCallback($interface);
2885     } elsif ($codeGenerator->IsConstructorTemplate($interface, "Event")) {
2886         GenerateEventConstructorCallback($interface);
2887     } elsif ($codeGenerator->IsConstructorTemplate($interface, "TypedArray")) {
2888         GenerateTypedArrayConstructorCallback($interface);
2889     }
2890
2891     my $access_check = "";
2892     if ($interface->extendedAttributes->{"CheckSecurity"} && !($interfaceName eq "DOMWindow")) {
2893         $access_check = "instance->SetAccessCheckCallbacks(${v8InterfaceName}::namedSecurityCheck, ${v8InterfaceName}::indexedSecurityCheck, v8::External::New(&${v8InterfaceName}::info));";
2894     }
2895
2896     # For the DOMWindow interface, generate the shadow object template
2897     # configuration method.
2898     if ($interfaceName eq "DOMWindow") {
2899         push(@implContent, <<END);
2900 static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Persistent<v8::ObjectTemplate> templ)
2901 {
2902     V8DOMConfiguration::batchConfigureAttributes(templ, v8::Handle<v8::ObjectTemplate>(), shadowAttrs, WTF_ARRAY_LENGTH(shadowAttrs));
2903
2904     // Install a security handler with V8.
2905     templ->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::External::New(&V8DOMWindow::info));
2906     templ->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
2907     return templ;
2908 }
2909 END
2910     }
2911
2912     if (!$parentClassTemplate) {
2913         $parentClassTemplate = "v8::Persistent<v8::FunctionTemplate>()";
2914     }
2915
2916     # Generate the template configuration method
2917     push(@implContent,  <<END);
2918 static v8::Persistent<v8::FunctionTemplate> Configure${v8InterfaceName}Template(v8::Persistent<v8::FunctionTemplate> desc)
2919 {
2920     desc->ReadOnlyPrototype();
2921
2922     v8::Local<v8::Signature> defaultSignature;
2923 END
2924     if ($interface->extendedAttributes->{"V8EnabledAtRuntime"}) {
2925         my $enable_function = GetRuntimeEnableFunctionName($interface);
2926         push(@implContent, <<END);
2927     if (!${enable_function}())
2928         defaultSignature = V8DOMConfiguration::configureTemplate(desc, \"\", $parentClassTemplate, ${v8InterfaceName}::internalFieldCount, 0, 0, 0, 0);
2929     else
2930 END
2931     }
2932     push(@implContent,  <<END);
2933     defaultSignature = V8DOMConfiguration::configureTemplate(desc, \"${visibleInterfaceName}\", $parentClassTemplate, ${v8InterfaceName}::internalFieldCount,
2934 END
2935     # Set up our attributes if we have them
2936     if ($has_attributes) {
2937         push(@implContent, <<END);
2938         ${v8InterfaceName}Attrs, WTF_ARRAY_LENGTH(${v8InterfaceName}Attrs),
2939 END
2940     } else {
2941         push(@implContent, <<END);
2942         0, 0,
2943 END
2944     }
2945
2946     if ($has_callbacks) {
2947         push(@implContent, <<END);
2948         ${v8InterfaceName}Callbacks, WTF_ARRAY_LENGTH(${v8InterfaceName}Callbacks));
2949 END
2950     } else {
2951         push(@implContent, <<END);
2952         0, 0);
2953 END
2954     }
2955     
2956     AddToImplIncludes("wtf/UnusedParam.h");
2957     push(@implContent, <<END);
2958     UNUSED_PARAM(defaultSignature); // In some cases, it will not be used.
2959 END
2960
2961     if (IsConstructable($interface)) {
2962         my $conditionalString = $codeGenerator->GenerateConstructorConditionalString($interface);
2963         push(@implContent, "#if $conditionalString\n") if $conditionalString;
2964         push(@implContent, "    desc->SetCallHandler(${v8InterfaceName}::constructorCallback);\n");
2965         push(@implContent, "#endif // $conditionalString\n") if $conditionalString;
2966     }
2967
2968     if ($access_check or @enabledAtRuntimeAttributes or @normalFunctions or $has_constants) {
2969         push(@implContent,  <<END);
2970     v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate();
2971     v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate();
2972     UNUSED_PARAM(instance); // In some cases, it will not be used.
2973     UNUSED_PARAM(proto); // In some cases, it will not be used.
2974 END
2975     }
2976
2977     push(@implContent,  "    $access_check\n");
2978
2979     # Setup the enable-at-runtime attrs if we have them
2980     foreach my $runtime_attr (@enabledAtRuntimeAttributes) {
2981         my $enable_function = GetRuntimeEnableFunctionName($runtime_attr->signature);
2982         my $conditionalString = $codeGenerator->GenerateConditionalString($runtime_attr->signature);
2983         push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
2984         push(@implContent, "    if (${enable_function}()) {\n");
2985         push(@implContent, "        static const V8DOMConfiguration::BatchedAttribute attrData =\\\n");
2986         GenerateSingleBatchedAttribute($interfaceName, $runtime_attr, ";", "    ");
2987         push(@implContent, <<END);
2988         V8DOMConfiguration::configureAttribute(instance, proto, attrData);
2989     }
2990 END
2991         push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
2992     }
2993
2994     # Setup the enable-at-runtime constants if we have them
2995     foreach my $runtime_const (@constantsEnabledAtRuntime) {
2996         my $enable_function = GetRuntimeEnableFunctionName($runtime_const);
2997         my $conditionalString = $codeGenerator->GenerateConditionalString($runtime_const);
2998         my $name = $runtime_const->name;
2999         my $value = $runtime_const->value;
3000         push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
3001         push(@implContent, "    if (${enable_function}()) {\n");
3002         push(@implContent, <<END);
3003         static const V8DOMConfiguration::BatchedConstant constData = {"${name}", static_cast<signed int>(${value})};
3004         V8DOMConfiguration::batchConfigureConstants(desc, proto, &constData, 1);
3005 END
3006         push(@implContent, "    }\n");
3007         push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
3008     }
3009
3010     GenerateImplementationIndexer($interface, $indexer);
3011     GenerateImplementationNamedPropertyGetter($interface, $namedPropertyGetter);
3012     GenerateImplementationCustomCall($interface);
3013     GenerateImplementationMasqueradesAsUndefined($interface);
3014
3015     # Define our functions with Set() or SetAccessor()
3016     my $total_functions = 0;
3017     foreach my $function (@normalFunctions) {
3018         # Only one accessor is needed for overloaded methods:
3019         next if $function->{overloadIndex} > 1;
3020
3021         $total_functions++;
3022         next if IsStandardFunction($interface, $function);
3023         GenerateNonStandardFunction($interface, $function);
3024         $num_callbacks++;
3025     }
3026
3027     die "Wrong number of callbacks generated for $interfaceName ($num_callbacks, should be $total_functions)" if $num_callbacks != $total_functions;
3028
3029     if ($has_constants) {
3030         push(@implContent, <<END);
3031     V8DOMConfiguration::batchConfigureConstants(desc, proto, ${v8InterfaceName}Consts, WTF_ARRAY_LENGTH(${v8InterfaceName}Consts));
3032 END
3033     }
3034
3035     # Special cases
3036     if ($interfaceName eq "DOMWindow") {
3037         push(@implContent, <<END);
3038
3039     proto->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
3040     desc->SetHiddenPrototype(true);
3041     instance->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
3042     // Set access check callbacks, but turned off initially.
3043     // When a context is detached from a frame, turn on the access check.
3044     // Turning on checks also invalidates inline caches of the object.
3045     instance->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::External::New(&V8DOMWindow::info), false);
3046 END
3047     }
3048     if ($interfaceName eq "HTMLDocument" or $interfaceName eq "DedicatedWorkerContext" or $interfaceName eq "SharedWorkerContext") {
3049         push(@implContent, <<END);
3050     desc->SetHiddenPrototype(true);
3051 END
3052     }
3053     if ($interfaceName eq "Location") {
3054         push(@implContent, <<END);
3055
3056     // For security reasons, these functions are on the instance instead
3057     // of on the prototype object to ensure that they cannot be overwritten.
3058     instance->SetAccessor(v8::String::NewSymbol("reload"), V8Location::reloadAccessorGetter, 0, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
3059     instance->SetAccessor(v8::String::NewSymbol("replace"), V8Location::replaceAccessorGetter, 0, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
3060     instance->SetAccessor(v8::String::NewSymbol("assign"), V8Location::assignAccessorGetter, 0, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
3061 END
3062     }
3063
3064     push(@implContent, <<END);
3065
3066     // Custom toString template
3067     desc->Set(v8::String::NewSymbol("toString"), V8PerIsolateData::current()->toStringTemplate());
3068     return desc;
3069 }
3070
3071 v8::Persistent<v8::FunctionTemplate> ${v8InterfaceName}::GetRawTemplate(v8::Isolate* isolate)
3072 {
3073     if (!isolate)
3074         isolate = v8::Isolate::GetCurrent();
3075     V8PerIsolateData* data = V8PerIsolateData::from(isolate);
3076     V8PerIsolateData::TemplateMap::iterator result = data->rawTemplateMap().find(&info);
3077     if (result != data->rawTemplateMap().end())
3078         return result->value;
3079
3080     v8::HandleScope handleScope;
3081     v8::Persistent<v8::FunctionTemplate> templ = createRawTemplate();
3082     data->rawTemplateMap().add(&info, templ);
3083     return templ;
3084 }
3085
3086 v8::Persistent<v8::FunctionTemplate> ${v8InterfaceName}::GetTemplate(v8::Isolate* isolate)
3087 {
3088     if (!isolate)
3089         isolate = v8::Isolate::GetCurrent();
3090     V8PerIsolateData* data = V8PerIsolateData::from(isolate);
3091     V8PerIsolateData::TemplateMap::iterator result = data->templateMap().find(&info);
3092     if (result != data->templateMap().end())
3093         return result->value;
3094
3095     v8::HandleScope handleScope;
3096     v8::Persistent<v8::FunctionTemplate> templ =
3097         Configure${v8InterfaceName}Template(GetRawTemplate());
3098     data->templateMap().add(&info, templ);
3099     return templ;
3100 }
3101
3102 bool ${v8InterfaceName}::HasInstance(v8::Handle<v8::Value> value)
3103 {
3104     return GetRawTemplate()->HasInstance(value);
3105 }
3106
3107 END
3108
3109     if (@enabledPerContextAttributes) {
3110         push(@implContent, <<END);
3111 void ${v8InterfaceName}::installPerContextProperties(v8::Handle<v8::Object> instance, ${nativeType}* impl)
3112 {
3113     v8::Local<v8::Object> proto = v8::Local<v8::Object>::Cast(instance->GetPrototype());
3114     // When building QtWebkit with V8 this variable is unused when none of the features are enabled.
3115     UNUSED_PARAM(proto);
3116 END
3117
3118         # Setup the enable-by-settings attrs if we have them
3119         foreach my $runtimeAttr (@enabledPerContextAttributes) {
3120             my $enableFunction = GetContextEnableFunction($runtimeAttr->signature);
3121             my $conditionalString = $codeGenerator->GenerateConditionalString($runtimeAttr->signature);
3122             push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
3123             push(@implContent, "    if (${enableFunction}(impl->document())) {\n");
3124             push(@implContent, "        static const V8DOMConfiguration::BatchedAttribute attrData =\\\n");
3125             GenerateSingleBatchedAttribute($interfaceName, $runtimeAttr, ";", "    ");
3126             push(@implContent, <<END);
3127         V8DOMConfiguration::configureAttribute(instance, proto, attrData);
3128 END
3129             push(@implContent, "    }\n");
3130             push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
3131         }
3132         push(@implContent, <<END);
3133 }
3134
3135 END
3136     }
3137
3138     if (@enabledPerContextFunctions) {
3139         push(@implContent, <<END);
3140 void ${v8InterfaceName}::installPerContextPrototypeProperties(v8::Handle<v8::Object> proto)
3141 {
3142     UNUSED_PARAM(proto);
3143 END
3144         # Setup the enable-by-settings functions if we have them
3145         push(@implContent,  <<END);
3146     v8::Local<v8::Signature> defaultSignature = v8::Signature::New(GetTemplate());
3147     UNUSED_PARAM(defaultSignature); // In some cases, it will not be used.
3148
3149     ScriptExecutionContext* context = toScriptExecutionContext(proto->CreationContext());
3150 END
3151
3152         foreach my $runtimeFunc (@enabledPerContextFunctions) {
3153             my $enableFunction = GetContextEnableFunction($runtimeFunc->signature);
3154             my $conditionalString = $codeGenerator->GenerateConditionalString($runtimeFunc->signature);
3155             push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
3156             push(@implContent, "    if (context && context->isDocument() && ${enableFunction}(static_cast<Document*>(context))) {\n");
3157             my $name = $runtimeFunc->signature->name;
3158             my $callback = GetFunctionTemplateCallbackName($runtimeFunc, $interfaceName);
3159             push(@implContent, <<END);
3160         proto->Set(v8::String::NewSymbol("${name}"), v8::FunctionTemplate::New(${callback}, v8Undefined(), defaultSignature)->GetFunction());
3161 END
3162             push(@implContent, "    }\n");
3163             push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
3164         }
3165
3166         push(@implContent, <<END);
3167 }
3168
3169 END
3170     }
3171
3172     if ($interface->extendedAttributes->{"ActiveDOMObject"}) {
3173         # MessagePort is handled like an active dom object even though it doesn't inherit
3174         # from ActiveDOMObject, so don't try to cast it to ActiveDOMObject.
3175         my $returnValue = $interfaceName eq "MessagePort" ? "0" : "toNative(object)";
3176         push(@implContent, <<END);
3177 ActiveDOMObject* ${v8InterfaceName}::toActiveDOMObject(v8::Handle<v8::Object> object)
3178 {
3179     return $returnValue;
3180 }
3181
3182 END
3183     }
3184
3185     if ($codeGenerator->InheritsExtendedAttribute($interface, "EventTarget")) {
3186         push(@implContent, <<END);
3187 EventTarget* ${v8InterfaceName}::toEventTarget(v8::Handle<v8::Object> object)
3188 {
3189     return toNative(object);
3190 }
3191
3192 END
3193     }
3194
3195     if ($interfaceName eq "DOMWindow") {
3196         push(@implContent, <<END);