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