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