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