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