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