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