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