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