• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1
2# Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
3# Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
4# Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
5# Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
6# Copyright (C) 2006 Apple Computer, Inc.
7# Copyright (C) 2007, 2008, 2009 Google Inc.
8# Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
9#
10# This library is free software; you can redistribute it and/or
11# modify it under the terms of the GNU Library General Public
12# License as published by the Free Software Foundation; either
13# version 2 of the License, or (at your option) any later version.
14#
15# This library is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18# Library General Public License for more details.
19#
20# You should have received a copy of the GNU Library General Public License
21# aint with this library; see the file COPYING.LIB.  If not, write to
22# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23# Boston, MA 02111-1307, USA.
24#
25
26package CodeGeneratorV8;
27
28use File::stat;
29use Digest::MD5;
30
31my $module = "";
32my $outputDir = "";
33
34my @headerContent = ();
35my @implContentHeader = ();
36my @implFixedHeader = ();
37my @implContent = ();
38my @implContentDecls = ();
39my %implIncludes = ();
40
41my @allParents = ();
42
43# Default .h template
44my $headerTemplate = << "EOF";
45/*
46    This file is part of the WebKit open source project.
47    This file has been generated by generate-bindings.pl. DO NOT MODIFY!
48
49    This library is free software; you can redistribute it and/or
50    modify it under the terms of the GNU Library General Public
51    License as published by the Free Software Foundation; either
52    version 2 of the License, or (at your option) any later version.
53
54    This library is distributed in the hope that it will be useful,
55    but WITHOUT ANY WARRANTY; without even the implied warranty of
56    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
57    Library General Public License for more details.
58
59    You should have received a copy of the GNU Library General Public License
60    along with this library; see the file COPYING.LIB.  If not, write to
61    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
62    Boston, MA 02111-1307, USA.
63*/
64EOF
65
66# Default constructor
67sub new
68{
69    my $object = shift;
70    my $reference = { };
71
72    $codeGenerator = shift;
73    $outputDir = shift;
74
75    bless($reference, $object);
76    return $reference;
77}
78
79sub finish
80{
81    my $object = shift;
82
83    # Commit changes!
84    $object->WriteData();
85}
86
87sub leftShift($$) {
88    my ($value, $distance) = @_;
89    return (($value << $distance) & 0xFFFFFFFF);
90}
91
92# Workaround for V8 bindings difference where RGBColor is not a POD type.
93sub IsPodType
94{
95    my $type = shift;
96    return $codeGenerator->IsPodType($type);
97}
98
99# Params: 'domClass' struct
100sub GenerateInterface
101{
102    my $object = shift;
103    my $dataNode = shift;
104    my $defines = shift;
105
106    # Start actual generation
107    $object->GenerateHeader($dataNode);
108    $object->GenerateImplementation($dataNode);
109
110    my $name = $dataNode->name;
111
112    # Open files for writing
113    my $headerFileName = "$outputDir/V8$name.h";
114    my $implFileName = "$outputDir/V8$name.cpp";
115
116    open($IMPL, ">$implFileName") || die "Couldn't open file $implFileName";
117    open($HEADER, ">$headerFileName") || die "Couldn't open file $headerFileName";
118}
119
120# Params: 'idlDocument' struct
121sub GenerateModule
122{
123    my $object = shift;
124    my $dataNode = shift;
125
126    $module = $dataNode->module;
127}
128
129sub GetLegacyHeaderIncludes
130{
131    my $legacyParent = shift;
132
133    die "Don't know what headers to include for module $module";
134}
135
136sub AvoidInclusionOfType
137{
138    my $type = shift;
139
140    # Special case: SVGRect.h / SVGPoint.h / SVGNumber.h / SVGMatrix.h do not exist.
141    return 1 if $type eq "SVGRect" or $type eq "SVGPoint" or $type eq "SVGNumber" or $type eq "SVGMatrix";
142    return 0;
143}
144
145sub UsesManualToJSImplementation
146{
147    my $type = shift;
148
149    return 1 if $type eq "SVGPathSeg";
150    return 0;
151}
152
153sub AddIncludesForType
154{
155    my $type = $codeGenerator->StripModule(shift);
156
157    # When we're finished with the one-file-per-class
158    # reorganization, we won't need these special cases.
159    if (!$codeGenerator->IsPrimitiveType($type) and !AvoidInclusionOfType($type) and $type ne "Date") {
160        # default, include the same named file
161        $implIncludes{GetV8HeaderName(${type})} = 1;
162
163        if ($type =~ /SVGPathSeg/) {
164            $joinedName = $type;
165            $joinedName =~ s/Abs|Rel//;
166            $implIncludes{"${joinedName}.h"} = 1;
167        }
168    }
169
170    # additional includes (things needed to compile the bindings but not the header)
171
172    if ($type eq "CanvasRenderingContext2D") {
173        $implIncludes{"CanvasGradient.h"} = 1;
174        $implIncludes{"CanvasPattern.h"} = 1;
175        $implIncludes{"CanvasStyle.h"} = 1;
176    }
177
178    if ($type eq "CanvasGradient" or $type eq "XPathNSResolver") {
179        $implIncludes{"PlatformString.h"} = 1;
180    }
181
182    if ($type eq "CSSStyleDeclaration") {
183        $implIncludes{"CSSMutableStyleDeclaration.h"} = 1;
184    }
185
186    if ($type eq "Plugin" or $type eq "PluginArray" or $type eq "MimeTypeArray") {
187        # So we can get String -> AtomicString conversion for namedItem().
188        $implIncludes{"AtomicString.h"} = 1;
189    }
190}
191
192sub AddIncludesForSVGAnimatedType
193{
194    my $type = shift;
195    $type =~ s/SVGAnimated//;
196
197    if ($type eq "Point" or $type eq "Rect") {
198        $implIncludes{"Float$type.h"} = 1;
199    } elsif ($type eq "String") {
200        $implIncludes{"PlatformString.h"} = 1;
201    }
202
203    $implIncludes{"SVGAnimatedTemplate.h"} = 1;
204}
205
206sub AddClassForwardIfNeeded
207{
208    my $implClassName = shift;
209
210    # SVGAnimatedLength/Number/etc.. are typedefs to SVGAnimtatedTemplate, so don't use class forwards for them!
211    push(@headerContent, "class $implClassName;\n\n") unless $codeGenerator->IsSVGAnimatedType($implClassName);
212}
213
214# If the node has a [Conditional=XXX] attribute, returns an "ENABLE(XXX)" string for use in an #if.
215sub GenerateConditionalString
216{
217    my $node = shift;
218    my $conditional = $node->extendedAttributes->{"Conditional"};
219    if ($conditional) {
220        return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
221    } else {
222        return "";
223    }
224}
225
226sub GenerateHeader
227{
228    my $object = shift;
229    my $dataNode = shift;
230
231    my $interfaceName = $dataNode->name;
232    my $className = "V8$interfaceName";
233    my $implClassName = $interfaceName;
234
235    # Copy contents of parent classes except the first parent or if it is
236    # EventTarget.
237    $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@allParents, 1);
238
239    my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
240    my $conditionalString = GenerateConditionalString($dataNode);
241
242    # - Add default header template
243    @headerContent = split("\r", $headerTemplate);
244
245    push(@headerContent, "\n#if ${conditionalString}\n\n") if $conditionalString;
246    push(@headerContent, "\n#ifndef $className" . "_H");
247    push(@headerContent, "\n#define $className" . "_H\n\n");
248
249    # Get correct pass/store types respecting PODType flag
250    my $podType = $dataNode->extendedAttributes->{"PODType"};
251
252    push(@headerContent, "#include \"$podType.h\"\n") if $podType and ($podType ne "double" and $podType ne "float" and $podType ne "RGBA32");
253
254    push(@headerContent, "#include <v8.h>\n");
255    push(@headerContent, "#include <wtf/HashMap.h>\n");
256    push(@headerContent, "#include \"StringHash.h\"\n");
257    push(@headerContent, "#include \"V8Index.h\"\n");
258    push(@headerContent, GetHeaderClassInclude($implClassName));
259    push(@headerContent, "\nnamespace WebCore {\n");
260    if ($podType) {
261        push(@headerContent, "\ntemplate<typename PODType> class V8SVGPODTypeWrapper;\n");
262    }
263    push(@headerContent, "\nclass $className {\n");
264
265    my $nativeType = GetNativeTypeForConversions($interfaceName);
266    if ($podType) {
267        $nativeType = "V8SVGPODTypeWrapper<${nativeType} >";
268    }
269    my $forceNewObjectParameter = IsDOMNodeType($interfaceName) ? ", bool forceNewObject = false" : "";
270    push(@headerContent, <<END);
271
272 public:
273  static bool HasInstance(v8::Handle<v8::Value> value);
274  static v8::Persistent<v8::FunctionTemplate> GetRawTemplate();
275  static v8::Persistent<v8::FunctionTemplate> GetTemplate();
276  static ${nativeType}* toNative(v8::Handle<v8::Object>);
277  static v8::Handle<v8::Object> wrap(${nativeType}*${forceNewObjectParameter});
278END
279
280    if ($implClassName eq "DOMWindow") {
281      push(@headerContent, <<END);
282  static v8::Persistent<v8::ObjectTemplate> GetShadowObjectTemplate();
283END
284    }
285
286    my @enabledAtRuntime;
287    foreach my $function (@{$dataNode->functions}) {
288        my $name = $function->signature->name;
289        my $attrExt = $function->signature->extendedAttributes;
290
291        # FIXME: We should only be generating callback declarations for functions labeled [Custom] or [V8Custom],
292        # but we can't do that due to some mislabeled functions in the idl's (https://bugs.webkit.org/show_bug.cgi?id=33066).
293        push(@headerContent, <<END);
294  static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments&);
295END
296        if ($attrExt->{"EnabledAtRuntime"}) {
297            push(@enabledAtRuntime, $function);
298        }
299    }
300
301    if ($dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"CanBeConstructed"}) {
302        push(@headerContent, <<END);
303  static v8::Handle<v8::Value> constructorCallback(const v8::Arguments& args);
304END
305    }
306
307    foreach my $attribute (@{$dataNode->attributes}) {
308        my $name = $attribute->signature->name;
309        my $attrExt = $attribute->signature->extendedAttributes;
310        if ($attrExt->{"V8CustomGetter"} || $attrExt->{"CustomGetter"}
311            || $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) {
312            push(@headerContent, <<END);
313  static v8::Handle<v8::Value> ${name}AccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);
314END
315        }
316        if ($attrExt->{"V8CustomSetter"} || $attrExt->{"CustomSetter"}
317            || $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) {
318            push(@headerContent, <<END);
319  static void ${name}AccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info);
320END
321        }
322        if ($attrExt->{"EnabledAtRuntime"}) {
323            push(@enabledAtRuntime, $attribute);
324        }
325    }
326
327    GenerateHeaderNamedAndIndexedPropertyAccessors($dataNode);
328    GenerateHeaderCustomCall($dataNode);
329    GenerateHeaderCustomInternalFieldIndices($dataNode);
330
331    if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) {
332        push(@headerContent, <<END);
333  static bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType, v8::Local<v8::Value> data);
334  static bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType, v8::Local<v8::Value> data);
335END
336    }
337
338    push(@headerContent, <<END);
339};
340
341  v8::Handle<v8::Value> toV8(${nativeType}*${forceNewObjectParameter});
342END
343    if (IsRefPtrType($implClassName)) {
344        push(@headerContent, <<END);
345  v8::Handle<v8::Value> toV8(PassRefPtr<${nativeType} >${forceNewObjectParameter});
346END
347    }
348
349    push(@headerContent, "}\n\n");
350    push(@headerContent, "#endif // $className" . "_H\n");
351
352    push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;
353}
354
355sub GetInternalFields
356{
357    my $dataNode = shift;
358    my $name = $dataNode->name;
359
360    # FIXME: I am hideous and hard-coded.  Make me beautiful.
361    return ("cacheIndex", "implementationIndex") if ($name eq "Document") || ($name eq "SVGDocument");
362    return ("cacheIndex", "implementationIndex", "markerIndex", "shadowIndex") if $name eq "HTMLDocument";
363    return ("cacheIndex") if IsNodeSubType($dataNode);
364    return ("cacheIndex") if $name eq "EventSource";
365    return ("cacheIndex") if $name eq "XMLHttpRequest";
366    return ("cacheIndex") if $name eq "XMLHttpRequestUpload";
367    return ("cacheIndex") if $name eq "MessagePort";
368    return ("port1Index", "port2Index") if ($name eq "MessageChannel");
369    return ("cacheIndex") if $name eq "AbstractWorker";
370    return ("abstractWorkerCacheIndex", "cacheIndex") if $name eq "Worker";
371    return ("abstractWorkerCacheIndex", "cacheIndex") if $name eq "WorkerContext";
372    return ("abstractWorkerCacheIndex", "workerContextCacheIndex", "cacheIndex") if $name eq "DedicatedWorkerContext";
373    return ("abstractWorkerCacheIndex", "cacheIndex") if $name eq "SharedWorker";
374    return ("abstractWorkerCacheIndex", "workerContextCacheIndex", "cacheIndex") if $name eq "SharedWorkerContext";
375    return ("cacheIndex") if $name eq "Notification";
376    return ("cacheIndex") if $name eq "IDBRequest";
377    return ("cacheIndex") if $name eq "SVGElementInstance";
378    return ("consoleIndex", "historyIndex", "locationbarIndex", "menubarIndex", "navigatorIndex", "personalbarIndex",
379        "screenIndex", "scrollbarsIndex", "selectionIndex", "statusbarIndex", "toolbarIndex", "locationIndex",
380        "domSelectionIndex", "cacheIndex", "enteredIsolatedWorldIndex") if $name eq "DOMWindow";
381    return ("cacheIndex") if $name eq "DOMApplicationCache";
382    return ("cacheIndex") if $name eq "WebSocket";
383    return ("ownerNodeIndex") if ($name eq "StyleSheet") || ($name eq "CSSStyleSheet");
384    return ("ownerNodeIndex") if ($name eq "NamedNodeMap");
385    return ();
386}
387
388sub GetHeaderClassInclude
389{
390    my $className = shift;
391    if ($className =~ /SVGPathSeg/) {
392        $className =~ s/Abs|Rel//;
393    }
394    return "" if (AvoidInclusionOfType($className));
395    return "#include \"SVGAnimatedTemplate.h\"\n" if ($codeGenerator->IsSVGAnimatedType($className));
396    return "#include \"${className}.h\"\n";
397}
398
399sub GenerateHeaderCustomInternalFieldIndices
400{
401    my $dataNode = shift;
402    my @customInternalFields = GetInternalFields($dataNode);
403    my $customFieldCounter = 0;
404    foreach my $customInternalField (@customInternalFields) {
405        push(@headerContent, <<END);
406  static const int ${customInternalField} = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
407END
408        $customFieldCounter++;
409    }
410    push(@headerContent, <<END);
411  static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
412END
413}
414
415my %indexerSpecialCases = (
416    "Storage" => 1,
417    "HTMLAppletElement" => 1,
418    "HTMLDocument" => 1,
419    "HTMLEmbedElement" => 1,
420    "HTMLObjectElement" => 1
421);
422
423sub GenerateHeaderNamedAndIndexedPropertyAccessors
424{
425    my $dataNode = shift;
426    my $interfaceName = $dataNode->name;
427    my $hasCustomIndexedGetter = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
428    my $hasCustomIndexedSetter = $dataNode->extendedAttributes->{"HasCustomIndexSetter"} && !$dataNode->extendedAttributes->{"HasNumericIndexGetter"};
429    my $hasCustomNamedGetter = $dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
430    my $hasCustomNamedSetter = $dataNode->extendedAttributes->{"DelegatingPutFunction"};
431    my $hasCustomDeleters = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
432    my $hasCustomEnumerator = $dataNode->extendedAttributes->{"CustomGetPropertyNames"};
433    if ($interfaceName eq "HTMLOptionsCollection") {
434        $interfaceName = "HTMLCollection";
435        $hasCustomIndexedGetter = 1;
436        $hasCustomNamedGetter = 1;
437    }
438    if ($interfaceName eq "DOMWindow") {
439        $hasCustomDeleterr = 0;
440        $hasEnumerator = 0;
441    }
442    if ($interfaceName eq "HTMLSelectElement") {
443        $hasCustomNamedGetter = 1;
444    }
445    my $isIndexerSpecialCase = exists $indexerSpecialCases{$interfaceName};
446
447    if ($hasCustomIndexedGetter || $isIndexerSpecialCase) {
448        push(@headerContent, <<END);
449  static v8::Handle<v8::Value> indexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info);
450END
451    }
452
453    if ($isIndexerSpecialCase || $hasCustomIndexedSetter) {
454        push(@headerContent, <<END);
455  static v8::Handle<v8::Value> indexedPropertySetter(uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info);
456END
457    }
458    if ($hasCustomDeleters) {
459        push(@headerContent, <<END);
460  static v8::Handle<v8::Boolean> indexedPropertyDeleter(uint32_t index, const v8::AccessorInfo& info);
461END
462    }
463    if ($hasCustomNamedGetter) {
464        push(@headerContent, <<END);
465  static v8::Handle<v8::Value> namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);
466END
467    }
468    if ($hasCustomNamedSetter) {
469        push(@headerContent, <<END);
470  static v8::Handle<v8::Value> namedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info);
471END
472    }
473    if ($hasCustomDeleters || $interfaceName eq "HTMLDocument") {
474        push(@headerContent, <<END);
475  static v8::Handle<v8::Boolean> namedPropertyDeleter(v8::Local<v8::String> name, const v8::AccessorInfo& info);
476END
477    }
478    if ($hasCustomEnumerator) {
479        push(@headerContent, <<END);
480  static v8::Handle<v8::Array> namedPropertyEnumerator(const v8::AccessorInfo& info);
481END
482    }
483}
484
485sub GenerateHeaderCustomCall
486{
487    my $dataNode = shift;
488
489    if ($dataNode->extendedAttributes->{"CustomCall"}) {
490        push(@headerContent, "  static v8::Handle<v8::Value> callAsFunctionCallback(const v8::Arguments&);\n");
491    }
492    if ($dataNode->name eq "Event") {
493        push(@headerContent, "  static v8::Handle<v8::Value> dataTransferAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
494        push(@headerContent, "  static void valueAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info);\n");
495    }
496    if ($dataNode->name eq "Location") {
497        push(@headerContent, "  static v8::Handle<v8::Value> assignAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
498        push(@headerContent, "  static v8::Handle<v8::Value> reloadAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
499        push(@headerContent, "  static v8::Handle<v8::Value> replaceAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
500    }
501}
502
503sub GenerateSetDOMException
504{
505    my $indent = shift;
506    my $result = "";
507
508    $result .= $indent . "if (UNLIKELY(ec)) {\n";
509    $result .= $indent . "    V8Proxy::setDOMException(ec);\n";
510    $result .= $indent . "    return v8::Handle<v8::Value>();\n";
511    $result .= $indent . "}\n";
512
513    return $result;
514}
515
516sub IsSubType
517{
518    my $dataNode = shift;
519    my $parentType = shift;
520    return 1 if ($dataNode->name eq $parentType);
521    foreach (@allParents) {
522        my $parent = $codeGenerator->StripModule($_);
523        return 1 if $parent eq $parentType;
524    }
525    return 0;
526}
527
528sub IsNodeSubType
529{
530    my $dataNode = shift;
531    return IsSubType($dataNode, "Node");
532}
533
534sub IsEventSubType
535{
536    my $dataNode = shift;
537    return IsSubType($dataNode, "Event");
538}
539
540sub GenerateDomainSafeFunctionGetter
541{
542    my $function = shift;
543    my $dataNode = shift;
544    my $implClassName = shift;
545
546    my $className = "V8" . $dataNode->name;
547    my $funcName = $function->signature->name;
548
549    my $signature = "v8::Signature::New(" . $className . "::GetRawTemplate())";
550    if ($function->signature->extendedAttributes->{"V8DoNotCheckSignature"}) {
551        $signature = "v8::Local<v8::Signature>()";
552    }
553
554    my $newTemplateString = GenerateNewFunctionTemplate($function, $dataNode, $signature);
555
556    push(@implContentDecls, <<END);
557  static v8::Handle<v8::Value> ${funcName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) {
558    INC_STATS(\"DOM.$implClassName.$funcName._get\");
559    static v8::Persistent<v8::FunctionTemplate> private_template =
560        v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
561    v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(${className}::GetTemplate(), info.This());
562    if (holder.IsEmpty()) {
563      // can only reach here by 'object.__proto__.func', and it should passed
564      // domain security check already
565      return private_template->GetFunction();
566    }
567    ${implClassName}* imp = ${className}::toNative(holder);
568    if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false)) {
569      static v8::Persistent<v8::FunctionTemplate> shared_template =
570        v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
571      return shared_template->GetFunction();
572
573    } else {
574      return private_template->GetFunction();
575    }
576  }
577
578END
579}
580
581sub GenerateConstructorGetter
582{
583    my $implClassName = shift;
584    my $classIndex = shift;
585
586    push(@implContentDecls, <<END);
587  static v8::Handle<v8::Value> ${implClassName}ConstructorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) {
588    INC_STATS(\"DOM.$implClassName.constructors._get\");
589    v8::Handle<v8::Value> data = info.Data();
590    ASSERT(data->IsNumber());
591    V8ClassIndex::V8WrapperType type = V8ClassIndex::FromInt(data->Int32Value());
592END
593
594    if ($classIndex eq "DOMWINDOW") {
595        push(@implContentDecls, <<END);
596    // Get the proxy corresponding to the DOMWindow if possible to
597    // make sure that the constructor function is constructed in the
598    // context of the DOMWindow and not in the context of the caller.
599    return V8DOMWrapper::getConstructor(type, V8DOMWindow::toNative(info.Holder()));
600END
601    } elsif ($classIndex eq "DEDICATEDWORKERCONTEXT" or $classIndex eq "WORKERCONTEXT" or $classIndex eq "SHAREDWORKERCONTEXT") {
602        push(@implContentDecls, <<END);
603    return V8DOMWrapper::getConstructor(type, V8WorkerContext::toNative(info.Holder()));
604END
605    } else {
606        push(@implContentDecls, "    return v8::Handle<v8::Value>();");
607    }
608
609    push(@implContentDecls, <<END);
610
611    }
612
613END
614}
615
616sub GenerateNormalAttrGetter
617{
618    my $attribute = shift;
619    my $dataNode = shift;
620    my $implClassName = shift;
621    my $interfaceName = shift;
622
623    my $attrExt = $attribute->signature->extendedAttributes;
624
625    my $attrName = $attribute->signature->name;
626
627    my $attrType = GetTypeFromSignature($attribute->signature);
628    my $attrIsPodType = IsPodType($attrType);
629
630    my $nativeType = GetNativeTypeFromSignature($attribute->signature, -1);
631    my $isPodType = IsPodType($implClassName);
632    my $skipContext = 0;
633
634
635    if ($isPodType) {
636        $implClassName = GetNativeType($implClassName);
637        $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
638    }
639
640    # Special case: SVGZoomEvent's attributes are all read-only
641    if ($implClassName eq "SVGZoomEvent") {
642        $attrIsPodType = 0;
643        $skipContext = 1;
644    }
645
646    # Special case: SVGSVGEelement::viewport is read-only
647    if (($implClassName eq "SVGSVGElement") and ($attrName eq "viewport")) {
648        $attrIsPodType = 0;
649        $skipContext = 1;
650    }
651
652    # Special case for SVGColor
653    if (($implClassName eq "SVGColor") and ($attrName eq "rgbColor")) {
654        $attrIsPodType = 0;
655    }
656
657    my $getterStringUsesImp = $implClassName ne "float";
658
659  # Getter
660    push(@implContentDecls, <<END);
661  static v8::Handle<v8::Value> ${attrName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) {
662    INC_STATS(\"DOM.$implClassName.$attrName._get\");
663END
664
665    if ($isPodType) {
666        push(@implContentDecls, <<END);
667    V8SVGPODTypeWrapper<$implClassName>* imp_wrapper = V8SVGPODTypeWrapper<$implClassName>::toNative(info.Holder());
668    $implClassName imp_instance = *imp_wrapper;
669END
670        if ($getterStringUsesImp) {
671            push(@implContentDecls, <<END);
672    $implClassName* imp = &imp_instance;
673END
674        }
675
676    } elsif ($attrExt->{"v8OnProto"} || $attrExt->{"V8DisallowShadowing"}) {
677      if ($interfaceName eq "DOMWindow") {
678        push(@implContentDecls, <<END);
679    v8::Handle<v8::Object> holder = info.Holder();
680END
681      } else {
682        # perform lookup first
683        push(@implContentDecls, <<END);
684    v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8${interfaceName}::GetTemplate(), info.This());
685    if (holder.IsEmpty()) return v8::Handle<v8::Value>();
686END
687      }
688    push(@implContentDecls, <<END);
689    ${implClassName}* imp = V8${implClassName}::toNative(holder);
690END
691    } else {
692        my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
693        if ($getterStringUsesImp && $reflect && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
694            # Generate super-compact call for regular attribute getter:
695            my $contentAttributeName = $reflect eq "1" ? $attrName : $reflect;
696            my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
697            $implIncludes{"${namespace}.h"} = 1;
698            push(@implContentDecls, "    return getElementStringAttr(info, ${namespace}::${contentAttributeName}Attr);\n");
699            push(@implContentDecls, "  }\n\n");
700            return;
701            # Skip the rest of the function!
702        }
703        push(@implContentDecls, <<END);
704    ${implClassName}* imp = V8${implClassName}::toNative(info.Holder());
705END
706    }
707
708    # Generate security checks if necessary
709    if ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) {
710        push(@implContentDecls, "    if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->$attrName())) return v8::Handle<v8::Value>();\n\n");
711    } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) {
712        push(@implContentDecls, "    if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->contentDocument())) return v8::Handle<v8::Value>();\n\n");
713    }
714
715    my $useExceptions = 1 if @{$attribute->getterExceptions} and !($isPodType);
716    if ($useExceptions) {
717        $implIncludes{"ExceptionCode.h"} = 1;
718        push(@implContentDecls, "    ExceptionCode ec = 0;\n");
719    }
720
721    if ($attribute->signature->extendedAttributes->{"v8referenceattr"}) {
722        $attrName = $attribute->signature->extendedAttributes->{"v8referenceattr"};
723    }
724
725    my $getterFunc = $codeGenerator->WK_lcfirst($attrName);
726
727    if ($codeGenerator->IsSVGAnimatedType($attribute->signature->type)) {
728        # Some SVGFE*Element.idl use 'operator' as attribute name; rewrite as '_operator' to avoid clashes with C/C++
729        $getterFunc = "_" . $getterFunc if ($attrName =~ /operator/);
730        $getterFunc .= "Animated";
731    }
732
733    my $returnType = GetTypeFromSignature($attribute->signature);
734
735    my $getterString;
736    if ($getterStringUsesImp) {
737        my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
738        my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
739        if ($reflect || $reflectURL) {
740            my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL);
741            my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
742            $implIncludes{"${namespace}.h"} = 1;
743            my $getAttributeFunctionName = $reflectURL ? "getURLAttribute" : "getAttribute";
744            $getterString = "imp->$getAttributeFunctionName(${namespace}::${contentAttributeName}Attr";
745        } else {
746            $getterString = "imp->$getterFunc(";
747        }
748        $getterString .= "ec" if $useExceptions;
749        $getterString .= ")";
750        if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) {
751            $getterString .= ".toInt()";
752        }
753    } else {
754        $getterString = "imp_instance";
755    }
756
757    my $result;
758    my $wrapper;
759
760    if ($attrIsPodType) {
761        $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
762
763        my $getter = $getterString;
764        $getter =~ s/imp->//;
765        $getter =~ s/\(\)//;
766        my $setter = "set" . $codeGenerator->WK_ucfirst($getter);
767
768        my $implClassIsAnimatedType = $codeGenerator->IsSVGAnimatedType($implClassName);
769        if (not $implClassIsAnimatedType and $codeGenerator->IsPodTypeWithWriteableProperties($attrType) and not defined $attribute->signature->extendedAttributes->{"Immutable"}) {
770            if (IsPodType($implClassName)) {
771                my $wrapper = "V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($getterString, imp_wrapper)";
772                push(@implContentDecls, "    RefPtr<V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName> > wrapper = $wrapper;\n");
773            } else {
774                my $wrapper = "V8SVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName>::create(imp, &${implClassName}::$getter, &${implClassName}::$setter)";
775                push(@implContentDecls, "    RefPtr<V8SVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName> > wrapper = $wrapper;\n");
776            }
777        } else {
778            if ($implClassIsAnimatedType) {
779                # We can't hash member function pointers, so instead generate
780                # some hashing material based on the names of the methods.
781                my $hashhex = substr(Digest::MD5::md5_hex("${implClassName}::$getter ${implClassName}::$setter)"), 0, 8);
782                my $wrapper = "V8SVGDynamicPODTypeWrapperCache<$nativeType, $implClassName>::lookupOrCreateWrapper(imp, &${implClassName}::$getter, &${implClassName}::$setter, 0x$hashhex)";
783                push(@implContentDecls, "    RefPtr<V8SVGPODTypeWrapper<" . $nativeType . "> > wrapper = $wrapper;\n");
784            } else {
785                my $wrapper = GenerateSVGStaticPodTypeWrapper($returnType, $getterString);
786                push(@implContentDecls, "    RefPtr<V8SVGStaticPODTypeWrapper<" . $nativeType . "> > wrapper = $wrapper;\n");
787            }
788        }
789
790    } else {
791        if ($attribute->signature->type eq "EventListener" && $dataNode->name eq "DOMWindow") {
792            push(@implContentDecls, "    if (!imp->document())\n");
793            push(@implContentDecls, "      return v8::Handle<v8::Value>();\n");
794        }
795
796        if ($useExceptions) {
797            push(@implContentDecls, "    $nativeType v = ");
798            push(@implContentDecls, "$getterString;\n");
799            push(@implContentDecls, GenerateSetDOMException("    "));
800            $result = "v";
801            $result .= ".release()" if (IsRefPtrType($returnType));
802        } else {
803            # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
804            $result = $getterString;
805        }
806    }
807
808    if (IsSVGTypeNeedingContextParameter($attrType) && !$skipContext) {
809        if ($attrIsPodType) {
810            push(@implContentDecls, GenerateSVGContextAssignment($implClassName, "wrapper.get()", "    "));
811        } else {
812            push(@implContentDecls, GenerateSVGContextRetrieval($implClassName, "    "));
813            # The templating associated with passing withSVGContext()'s return value directly into toV8 can get compilers confused,
814            # so just manually set the return value to a PassRefPtr of the expected type.
815            push(@implContentDecls, "    PassRefPtr<$attrType> resultAsPassRefPtr = V8Proxy::withSVGContext($result, context);\n");
816            $result = "resultAsPassRefPtr";
817        }
818    }
819
820    if ($attrIsPodType) {
821        $implIncludes{"V8${attrType}.h"} = 1;
822        push(@implContentDecls, "    return toV8(wrapper.release().get());\n");
823    } else {
824        push(@implContentDecls, "    " . ReturnNativeToJSValue($attribute->signature, $result, "    ").";\n");
825    }
826
827    push(@implContentDecls, "  }\n\n");  # end of getter
828}
829
830
831sub GenerateReplaceableAttrSetter
832{
833    my $implClassName = shift;
834
835    push(@implContentDecls,
836       "  static void ${attrName}AttrSetter(v8::Local<v8::String> name," .
837       " v8::Local<v8::Value> value, const v8::AccessorInfo& info) {\n");
838
839    push(@implContentDecls, "    INC_STATS(\"DOM.$implClassName.$attrName._set\");\n");
840
841    push(@implContentDecls, "    v8::Local<v8::String> ${attrName}_string = v8::String::New(\"${attrName}\");\n");
842    push(@implContentDecls, "    info.Holder()->Delete(${attrName}_string);\n");
843    push(@implContentDecls, "    info.This()->Set(${attrName}_string, value);\n");
844    push(@implContentDecls, "  }\n\n");
845}
846
847
848sub GenerateNormalAttrSetter
849{
850    my $attribute = shift;
851    my $dataNode = shift;
852    my $implClassName = shift;
853    my $interfaceName = shift;
854
855    my $attrExt = $attribute->signature->extendedAttributes;
856
857    push(@implContentDecls,
858       "  static void ${attrName}AttrSetter(v8::Local<v8::String> name," .
859       " v8::Local<v8::Value> value, const v8::AccessorInfo& info) {\n");
860
861    push(@implContentDecls, "    INC_STATS(\"DOM.$implClassName.$attrName._set\");\n");
862
863    my $isPodType = IsPodType($implClassName);
864
865    if ($isPodType) {
866        $implClassName = GetNativeType($implClassName);
867        $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
868        push(@implContentDecls, "    V8SVGPODTypeWrapper<$implClassName>* wrapper = V8SVGPODTypeWrapper<$implClassName>::toNative(info.Holder());\n");
869        push(@implContentDecls, "    $implClassName imp_instance = *wrapper;\n");
870        push(@implContentDecls, "    $implClassName* imp = &imp_instance;\n");
871
872    } elsif ($attrExt->{"v8OnProto"}) {
873      if ($interfaceName eq "DOMWindow") {
874        push(@implContentDecls, <<END);
875    v8::Handle<v8::Object> holder = info.Holder();
876END
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()) return;
882END
883      }
884    push(@implContentDecls, <<END);
885    ${implClassName}* imp = V8${implClassName}::toNative(holder);
886END
887    } else {
888        my $attrType = GetTypeFromSignature($attribute->signature);
889        my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
890        my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
891        if (($reflect || $reflectURL) && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
892            # Generate super-compact call for regular attribute setter:
893            my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL);
894            my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
895            $implIncludes{"${namespace}.h"} = 1;
896            push(@implContentDecls, "    setElementStringAttr(info, ${namespace}::${contentAttributeName}Attr, value);\n");
897            push(@implContentDecls, "  }\n\n");
898            return;
899            # Skip the rest of the function!
900        }
901
902        push(@implContentDecls, <<END);
903    ${implClassName}* imp = V8${implClassName}::toNative(info.Holder());
904END
905    }
906
907    my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0);
908    if ($attribute->signature->type eq "EventListener") {
909        if ($dataNode->name eq "DOMWindow") {
910            push(@implContentDecls, "    if (!imp->document())\n");
911            push(@implContentDecls, "      return;\n");
912        }
913    } else {
914        push(@implContentDecls, "    $nativeType v = " . JSValueToNative($attribute->signature, "value") . ";\n");
915    }
916
917    my $result = "";
918    if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) {
919        $result .= "WebCore::String::number(";
920    }
921    $result .= "v";
922    if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) {
923        $result .= ")";
924    }
925    my $returnType = GetTypeFromSignature($attribute->signature);
926    if (IsRefPtrType($returnType)) {
927        $result = "WTF::getPtr(" . $result . ")";
928    }
929
930    my $useExceptions = 1 if @{$attribute->setterExceptions} and !($isPodType);
931
932    if ($useExceptions) {
933        $implIncludes{"ExceptionCode.h"} = 1;
934        push(@implContentDecls, "    ExceptionCode ec = 0;\n");
935    }
936
937    if ($implClassName eq "float") {
938        push(@implContentDecls, "    *imp = $result;\n");
939    } else {
940        my $implSetterFunctionName = $codeGenerator->WK_ucfirst($attrName);
941        my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
942        my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
943        if ($reflect || $reflectURL) {
944            my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL);
945            my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
946            $implIncludes{"${namespace}.h"} = 1;
947            push(@implContentDecls, "    imp->setAttribute(${namespace}::${contentAttributeName}Attr, $result");
948        } elsif ($attribute->signature->type eq "EventListener") {
949            $implIncludes{"V8AbstractEventListener.h"} = 1;
950            push(@implContentDecls, "    transferHiddenDependency(info.Holder(), imp->$attrName(), value, V8${interfaceName}::cacheIndex);\n");
951            push(@implContentDecls, "    imp->set$implSetterFunctionName(V8DOMWrapper::getEventListener(imp, value, true, ListenerFindOrCreate)");
952        } else {
953            push(@implContentDecls, "    imp->set$implSetterFunctionName($result");
954        }
955        push(@implContentDecls, ", ec") if $useExceptions;
956        push(@implContentDecls, ");\n");
957    }
958
959    if ($useExceptions) {
960        push(@implContentDecls, "    if (UNLIKELY(ec))\n");
961        push(@implContentDecls, "        V8Proxy::setDOMException(ec);\n");
962    }
963
964    if ($isPodType) {
965        push(@implContentDecls, "    wrapper->commitChange(*imp, V8Proxy::svgContext(wrapper));\n");
966    } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
967        $implIncludes{"SVGElement.h"} = 1;
968
969        my $currentObject = "imp";
970        if ($isPodType) {
971            $currentObject = "wrapper";
972        }
973
974        push(@implContentDecls, "    if (SVGElement* context = V8Proxy::svgContext($currentObject)) {\n");
975        push(@implContentDecls, "        context->svgAttributeChanged(imp->associatedAttributeName());\n");
976        push(@implContentDecls, "    }\n");
977    }
978
979    push(@implContentDecls, "    return;\n");
980    push(@implContentDecls, "  }\n\n");  # end of setter
981}
982
983sub GetFunctionTemplateCallbackName
984{
985    $function = shift;
986    $dataNode = shift;
987
988    my $interfaceName = $dataNode->name;
989    my $name = $function->signature->name;
990
991    if ($function->signature->extendedAttributes->{"Custom"} ||
992        $function->signature->extendedAttributes->{"V8Custom"}) {
993        if ($function->signature->extendedAttributes->{"Custom"} &&
994            $function->signature->extendedAttributes->{"V8Custom"}) {
995            die "Custom and V8Custom should be mutually exclusive!"
996        }
997        return "V8${interfaceName}::${name}Callback";
998    } else {
999        return "${interfaceName}Internal::${name}Callback";
1000    }
1001}
1002
1003sub GenerateNewFunctionTemplate
1004{
1005    $function = shift;
1006    $dataNode = shift;
1007    $signature = shift;
1008
1009    my $callback = GetFunctionTemplateCallbackName($function, $dataNode);
1010    return "v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), $signature)";
1011}
1012
1013sub GenerateFunctionCallback
1014{
1015    my $function = shift;
1016    my $dataNode = shift;
1017    my $classIndex = shift;
1018    my $implClassName = shift;
1019
1020    my $interfaceName = $dataNode->name;
1021    my $name = $function->signature->name;
1022
1023    push(@implContentDecls,
1024"  static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args) {\n" .
1025"    INC_STATS(\"DOM.$implClassName.$name\");\n");
1026
1027    my $numParameters = @{$function->parameters};
1028
1029    if ($function->signature->extendedAttributes->{"RequiresAllArguments"}) {
1030        push(@implContentDecls,
1031            "    if (args.Length() < $numParameters) return v8::Handle<v8::Value>();\n");
1032    }
1033
1034    if (IsPodType($implClassName)) {
1035        my $nativeClassName = GetNativeType($implClassName);
1036        push(@implContentDecls, "    V8SVGPODTypeWrapper<$nativeClassName>* imp_wrapper = V8SVGPODTypeWrapper<$nativeClassName>::toNative(args.Holder());\n");
1037        push(@implContentDecls, "    $nativeClassName imp_instance = *imp_wrapper;\n");
1038        push(@implContentDecls, "    $nativeClassName* imp = &imp_instance;\n");
1039    } else {
1040        push(@implContentDecls, <<END);
1041    ${implClassName}* imp = V8${implClassName}::toNative(args.Holder());
1042END
1043    }
1044
1045  # Check domain security if needed
1046    if (($dataNode->extendedAttributes->{"CheckDomainSecurity"}
1047       || $interfaceName eq "DOMWindow")
1048       && !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
1049    # We have not find real use cases yet.
1050    push(@implContentDecls,
1051"    if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) {\n".
1052"      return v8::Handle<v8::Value>();\n" .
1053"    }\n");
1054    }
1055
1056    my $raisesExceptions = @{$function->raisesExceptions};
1057    if (!$raisesExceptions) {
1058        foreach my $parameter (@{$function->parameters}) {
1059            if (TypeCanFailConversion($parameter) or $parameter->extendedAttributes->{"IsIndex"}) {
1060                $raisesExceptions = 1;
1061            }
1062        }
1063    }
1064
1065    if ($raisesExceptions) {
1066        $implIncludes{"ExceptionCode.h"} = 1;
1067        push(@implContentDecls, "    ExceptionCode ec = 0;\n");
1068        push(@implContentDecls, "    {\n");
1069        # The brace here is needed to prevent the ensuing 'goto fail's from jumping past constructors
1070        # of objects (like Strings) declared later, causing compile errors. The block scope ends
1071        # right before the label 'fail:'.
1072    }
1073
1074    if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
1075        push(@implContentDecls,
1076"    OwnPtr<ScriptCallStack> callStack(ScriptCallStack::create(args, $numParameters));\n".
1077"    if (!callStack)\n".
1078"        return v8::Undefined();\n");
1079        $implIncludes{"ScriptCallStack.h"} = 1;
1080    }
1081    if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) {
1082        push(@implContentDecls,
1083"    if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->getSVGDocument(ec)))\n" .
1084"      return v8::Handle<v8::Value>();\n");
1085    }
1086
1087    my $paramIndex = 0;
1088    foreach my $parameter (@{$function->parameters}) {
1089        TranslateParameter($parameter);
1090
1091        my $parameterName = $parameter->name;
1092
1093        if ($parameter->extendedAttributes->{"Optional"}) {
1094            # Generate early call if there are not enough parameters.
1095            push(@implContentDecls, "    if (args.Length() <= $paramIndex) {\n");
1096            my $functionCall = GenerateFunctionCallString($function, $paramIndex, "    " x 2, $implClassName);
1097            push(@implContentDecls, $functionCall);
1098            push(@implContentDecls, "    }\n");
1099        }
1100
1101        if (BasicTypeCanFailConversion($parameter)) {
1102            push(@implContentDecls, "    bool ${parameterName}Ok;\n");
1103        }
1104
1105        push(@implContentDecls, "    " . GetNativeTypeFromSignature($parameter, $paramIndex) . " $parameterName = ");
1106        push(@implContentDecls, JSValueToNative($parameter, "args[$paramIndex]",
1107           BasicTypeCanFailConversion($parameter) ?  "${parameterName}Ok" : undef) . ";\n");
1108
1109        if (TypeCanFailConversion($parameter)) {
1110            $implIncludes{"ExceptionCode.h"} = 1;
1111            push(@implContentDecls,
1112"    if (UNLIKELY(!$parameterName" . (BasicTypeCanFailConversion($parameter) ? "Ok" : "") . ")) {\n" .
1113"      ec = TYPE_MISMATCH_ERR;\n" .
1114"      goto fail;\n" .
1115"    }\n");
1116        }
1117
1118        if ($parameter->extendedAttributes->{"IsIndex"}) {
1119            $implIncludes{"ExceptionCode.h"} = 1;
1120            push(@implContentDecls,
1121"    if (UNLIKELY($parameterName < 0)) {\n" .
1122"      ec = INDEX_SIZE_ERR;\n" .
1123"      goto fail;\n" .
1124"    }\n");
1125        }
1126
1127        $paramIndex++;
1128    }
1129
1130    # Build the function call string.
1131    my $callString = GenerateFunctionCallString($function, $paramIndex, "    ", $implClassName);
1132    push(@implContentDecls, "$callString");
1133
1134    if ($raisesExceptions) {
1135        push(@implContentDecls, "    }\n");
1136        push(@implContentDecls, "  fail:\n");
1137        push(@implContentDecls, "    V8Proxy::setDOMException(ec);\n");
1138        push(@implContentDecls, "    return v8::Handle<v8::Value>();\n");
1139    }
1140
1141    push(@implContentDecls, "  }\n\n");
1142}
1143
1144sub GenerateBatchedAttributeData
1145{
1146    my $dataNode = shift;
1147    my $interfaceName = $dataNode->name;
1148    my $attributes = shift;
1149
1150    foreach my $attribute (@$attributes) {
1151        my $conditionalString = GenerateConditionalString($attribute->signature);
1152        push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
1153        GenerateSingleBatchedAttribute($interfaceName, $attribute, ",", "");
1154        push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
1155    }
1156}
1157
1158sub GenerateSingleBatchedAttribute
1159{
1160    my $interfaceName = shift;
1161    my $attribute = shift;
1162    my $delimiter = shift;
1163    my $indent = shift;
1164    my $attrName = $attribute->signature->name;
1165    my $attrExt = $attribute->signature->extendedAttributes;
1166
1167    my $accessControl = "v8::DEFAULT";
1168    if ($attrExt->{"DoNotCheckDomainSecurityOnGet"}) {
1169        $accessControl = "v8::ALL_CAN_READ";
1170    } elsif ($attrExt->{"DoNotCheckDomainSecurityOnSet"}) {
1171        $accessControl = "v8::ALL_CAN_WRITE";
1172    } elsif ($attrExt->{"DoNotCheckDomainSecurity"}) {
1173        $accessControl = "v8::ALL_CAN_READ";
1174        if (!($attribute->type =~ /^readonly/) && !($attrExt->{"V8ReadOnly"})) {
1175            $accessControl .= "|v8::ALL_CAN_WRITE";
1176        }
1177    }
1178    if ($attrExt->{"V8DisallowShadowing"}) {
1179        $accessControl .= "|v8::PROHIBITS_OVERWRITING";
1180    }
1181    $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")";
1182
1183    my $customAccessor =
1184        $attrExt->{"Custom"} ||
1185        $attrExt->{"CustomSetter"} ||
1186        $attrExt->{"CustomGetter"} ||
1187        $attrExt->{"V8Custom"} ||
1188        $attrExt->{"V8CustomSetter"} ||
1189        $attrExt->{"V8CustomGetter"} ||
1190        "";
1191    if ($customAccessor eq 1) {
1192        # use the naming convension, interface + (capitalize) attr name
1193        $customAccessor = $interfaceName . "::" . $attrName;
1194    }
1195
1196    my $getter;
1197    my $setter;
1198    my $propAttr = "v8::None";
1199    my $hasCustomSetter = 0;
1200
1201    # Check attributes.
1202    if ($attrExt->{"DontEnum"}) {
1203        $propAttr .= "|v8::DontEnum";
1204    }
1205    if ($attrExt->{"V8DisallowShadowing"}) {
1206        $propAttr .= "|v8::DontDelete";
1207    }
1208
1209    my $on_proto = "0 /* on instance */";
1210    my $data = "V8ClassIndex::INVALID_CLASS_INDEX /* no data */";
1211
1212    # Constructor
1213    if ($attribute->signature->type =~ /Constructor$/) {
1214        my $constructorType = $codeGenerator->StripModule($attribute->signature->type);
1215        $constructorType =~ s/Constructor$//;
1216        my $constructorIndex = uc($constructorType);
1217        if ($customAccessor) {
1218            $getter = "V8${customAccessor}AccessorGetter";
1219        } else {
1220            $data = "V8ClassIndex::${constructorIndex}";
1221            $getter = "${interfaceName}Internal::${interfaceName}ConstructorGetter";
1222        }
1223        $setter = "0";
1224        $propAttr = "v8::ReadOnly";
1225
1226    } else {
1227        # Default Getter and Setter
1228        $getter = "${interfaceName}Internal::${attrName}AttrGetter";
1229        $setter = "${interfaceName}Internal::${attrName}AttrSetter";
1230
1231        # Custom Setter
1232        if ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
1233            $hasCustomSetter = 1;
1234            $setter = "V8${customAccessor}AccessorSetter";
1235        }
1236
1237        # Custom Getter
1238        if ($attrExt->{"CustomGetter"} || $attrExt->{"V8CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
1239            $getter = "V8${customAccessor}AccessorGetter";
1240        }
1241    }
1242
1243    # Replaceable
1244    if ($attrExt->{"Replaceable"} && !$hasCustomSetter) {
1245        $setter = "0";
1246        # Handle the special case of window.top being marked as Replaceable.
1247        # FIXME: Investigate whether we could treat window.top as replaceable
1248        # and allow shadowing without it being a security hole.
1249        if (!($interfaceName eq "DOMWindow" and $attrName eq "top")) {
1250            $propAttr .= "|v8::ReadOnly";
1251        }
1252    }
1253
1254    # Read only attributes
1255    if ($attribute->type =~ /^readonly/ || $attrExt->{"V8ReadOnly"}) {
1256        $setter = "0";
1257    }
1258
1259    # An accessor can be installed on the proto
1260    if ($attrExt->{"v8OnProto"}) {
1261        $on_proto = "1 /* on proto */";
1262    }
1263
1264    my $commentInfo = "Attribute '$attrName' (Type: '" . $attribute->type .
1265                      "' ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
1266
1267    push(@implContent, $indent . "    {\n");
1268    push(@implContent, $indent . "        \/\/ $commentInfo\n");
1269    push(@implContent, $indent . "        \"$attrName\",\n");
1270    push(@implContent, $indent . "        $getter,\n");
1271    push(@implContent, $indent . "        $setter,\n");
1272    push(@implContent, $indent . "        $data,\n");
1273    push(@implContent, $indent . "        $accessControl,\n");
1274    push(@implContent, $indent . "        static_cast<v8::PropertyAttribute>($propAttr),\n");
1275    push(@implContent, $indent . "        $on_proto\n");
1276    push(@implContent, $indent . "    }" . $delimiter . "\n");
1277END
1278}
1279
1280sub GenerateImplementationIndexer
1281{
1282    my $dataNode = shift;
1283    my $indexer = shift;
1284    my $interfaceName = $dataNode->name;
1285
1286    # FIXME: Figure out what HasNumericIndexGetter is really supposed to do. Right now, it's only set on WebGL-related files.
1287    my $hasCustomSetter = $dataNode->extendedAttributes->{"HasCustomIndexSetter"} && !$dataNode->extendedAttributes->{"HasNumericIndexGetter"};
1288    my $hasGetter = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
1289
1290    # FIXME: Find a way to not have to special-case HTMLOptionsCollection.
1291    if ($interfaceName eq "HTMLOptionsCollection") {
1292        $hasGetter = 1;
1293    }
1294    # FIXME: If the parent interface of $dataNode already has
1295    # HasIndexGetter, we don't need to handle the getter here.
1296    if ($interfaceName eq "WebKitCSSTransformValue") {
1297        $hasGetter = 0;
1298    }
1299
1300    # FIXME: Investigate and remove this nastinesss. In V8, named property handling and indexer handling are apparently decoupled,
1301    # which means that object[X] where X is a number doesn't reach named property indexer. So we need to provide
1302    # simplistic, mirrored indexer handling in addition to named property handling.
1303    my $isSpecialCase = exists $indexerSpecialCases{$interfaceName};
1304    if ($isSpecialCase) {
1305        $hasGetter = 1;
1306        if ($dataNode->extendedAttributes->{"DelegatingPutFunction"}) {
1307            $hasCustomSetter = 1;
1308        }
1309    }
1310
1311    if (!$hasGetter) {
1312        return;
1313    }
1314
1315    $implIncludes{"V8Collection.h"} = 1;
1316
1317    my $indexerType = $indexer ? $indexer->type : 0;
1318
1319    # FIXME: Remove this once toV8 helper methods are implemented (see https://bugs.webkit.org/show_bug.cgi?id=32563).
1320    if ($interfaceName eq "WebKitCSSKeyframesRule") {
1321        $indexerType = "WebKitCSSKeyframeRule";
1322    }
1323
1324    if ($indexerType && !$hasCustomSetter) {
1325        if ($indexerType eq "DOMString") {
1326            my $conversion = $indexer->extendedAttributes->{"ConvertNullStringTo"};
1327            if ($conversion && $conversion eq "Null") {
1328                push(@implContent, <<END);
1329  setCollectionStringOrNullIndexedGetter<${interfaceName}>(desc);
1330END
1331            } else {
1332                push(@implContent, <<END);
1333  setCollectionStringIndexedGetter<${interfaceName}>(desc);
1334END
1335            }
1336        } else {
1337            my $indexerClassIndex = uc($indexerType);
1338            push(@implContent, <<END);
1339  setCollectionIndexedGetter<${interfaceName}, ${indexerType}>(desc, V8ClassIndex::${indexerClassIndex});
1340END
1341            # Include the header for this indexer type, because setCollectionIndexedGetter() requires toV8() for this type.
1342            $implIncludes{"V8${indexerType}.h"} = 1;
1343        }
1344
1345        return;
1346    }
1347
1348    my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
1349    my $hasEnumerator = !$isSpecialCase && IsNodeSubType($dataNode);
1350    my $setOn = "Instance";
1351
1352    # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
1353    # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
1354    # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
1355    # on the object.
1356    if ($interfaceName eq "DOMWindow") {
1357        $setOn = "Prototype";
1358        $hasDeleter = 0;
1359    }
1360
1361    push(@implContent, "  desc->${setOn}Template()->SetIndexedPropertyHandler(V8${interfaceName}::indexedPropertyGetter");
1362    push(@implContent, $hasCustomSetter ? ", V8${interfaceName}::indexedPropertySetter" : ", 0");
1363    push(@implContent, ", 0"); # IndexedPropertyQuery -- not being used at the moment.
1364    push(@implContent, $hasDeleter ? ", V8${interfaceName}::indexedPropertyDeleter" : ", 0");
1365    push(@implContent, ", nodeCollectionIndexedPropertyEnumerator<${interfaceName}>, v8::Integer::New(V8ClassIndex::NODE)") if $hasEnumerator;
1366    push(@implContent, ");\n");
1367}
1368
1369sub GenerateImplementationNamedPropertyGetter
1370{
1371    my $dataNode = shift;
1372    my $namedPropertyGetter = shift;
1373    my $interfaceName = $dataNode->name;
1374    my $hasCustomGetter = $dataNode->extendedAttributes->{"HasOverridingNameGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
1375
1376    # FIXME: Remove hard-coded HTMLOptionsCollection reference by changing HTMLOptionsCollection to not inherit
1377    # from HTMLCollection per W3C spec (http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/html.html#HTMLOptionsCollection).
1378    if ($interfaceName eq "HTMLOptionsCollection") {
1379        $interfaceName = "HTMLCollection";
1380        $hasCustomGetter = 1;
1381    }
1382
1383    my $hasGetter = $dataNode->extendedAttributes->{"HasNameGetter"} || $hasCustomGetter || $namedPropertyGetter;
1384    if (!$hasGetter) {
1385        return;
1386    }
1387
1388    if ($namedPropertyGetter && $namedPropertyGetter->type ne "Node" && !$namedPropertyGetter->extendedAttributes->{"Custom"} && !$hasCustomGetter) {
1389        $implIncludes{"V8Collection.h"} = 1;
1390        my $type = $namedPropertyGetter->type;
1391        my $classIndex = uc($type);
1392        push(@implContent, <<END);
1393  setCollectionNamedGetter<${interfaceName}, ${type}>(desc, V8ClassIndex::${classIndex});
1394END
1395        return;
1396    }
1397
1398    my $hasSetter = $dataNode->extendedAttributes->{"DelegatingPutFunction"};
1399    # FIXME: Try to remove hard-coded HTMLDocument reference by aligning handling of document.all with JSC bindings.
1400    my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"} || $interfaceName eq "HTMLDocument";
1401    my $hasEnumerator = $dataNode->extendedAttributes->{"CustomGetPropertyNames"};
1402    my $setOn = "Instance";
1403
1404    # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
1405    # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
1406    # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
1407    # on the object.
1408    if ($interfaceName eq "DOMWindow") {
1409        $setOn = "Prototype";
1410        $hasDeleter = 0;
1411        $hasEnumerator = 0;
1412    }
1413
1414    push(@implContent, "  desc->${setOn}Template()->SetNamedPropertyHandler(V8${interfaceName}::namedPropertyGetter, ");
1415    push(@implContent, $hasSetter ? "V8${interfaceName}::namedPropertySetter, " : "0, ");
1416    push(@implContent, "0, "); # NamedPropertyQuery -- not being used at the moment.
1417    push(@implContent, $hasDeleter ? "V8${interfaceName}::namedPropertyDeleter, " : "0, ");
1418    push(@implContent, $hasEnumerator ? "V8${interfaceName}::namedPropertyEnumerator" : "0");
1419    push(@implContent, ");\n");
1420}
1421
1422sub GenerateImplementationCustomCall
1423{
1424    my $dataNode = shift;
1425    my $interfaceName = $dataNode->name;
1426    my $hasCustomCall = $dataNode->extendedAttributes->{"CustomCall"};
1427
1428    # FIXME: Remove hard-coded HTMLOptionsCollection reference.
1429    if ($interfaceName eq "HTMLOptionsCollection") {
1430        $interfaceName = "HTMLCollection";
1431        $hasCustomCall = 1;
1432    }
1433
1434    if ($hasCustomCall) {
1435        push(@implContent, "  desc->InstanceTemplate()->SetCallAsFunctionHandler(V8${interfaceName}::callAsFunctionCallback);\n");
1436    }
1437}
1438
1439sub GenerateImplementationMasqueradesAsUndefined
1440{
1441    my $dataNode = shift;
1442    if ($dataNode->extendedAttributes->{"MasqueradesAsUndefined"})
1443    {
1444        push(@implContent, "  desc->InstanceTemplate()->MarkAsUndetectable();\n");
1445    }
1446}
1447
1448sub GenerateImplementation
1449{
1450    my $object = shift;
1451    my $dataNode = shift;
1452    my $interfaceName = $dataNode->name;
1453    my $className = "V8$interfaceName";
1454    my $implClassName = $interfaceName;
1455    my $classIndex = uc($codeGenerator->StripModule($interfaceName));
1456
1457    my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
1458    my $conditionalString = GenerateConditionalString($dataNode);
1459
1460    # - Add default header template
1461    @implContentHeader = split("\r", $headerTemplate);
1462
1463    push(@implFixedHeader,
1464         "#include \"config.h\"\n" .
1465         "#include \"RuntimeEnabledFeatures.h\"\n" .
1466         "#include \"V8Proxy.h\"\n" .
1467         "#include \"V8Binding.h\"\n" .
1468         "#include \"V8BindingState.h\"\n" .
1469         "#include \"V8DOMWrapper.h\"\n" .
1470         "#include \"V8IsolatedContext.h\"\n\n" .
1471         "#undef LOG\n\n");
1472
1473    push(@implFixedHeader, "\n#if ${conditionalString}\n\n") if $conditionalString;
1474
1475    if ($className =~ /^V8SVGAnimated/) {
1476        AddIncludesForSVGAnimatedType($interfaceName);
1477    }
1478
1479    $implIncludes{"${className}.h"} = 1;
1480
1481    AddIncludesForType($interfaceName);
1482
1483    push(@implContentDecls, "namespace WebCore {\n");
1484    push(@implContentDecls, "namespace ${interfaceName}Internal {\n\n");
1485    push(@implContentDecls, "template <typename T> void V8_USE(T) { }\n\n");
1486
1487    my $hasConstructors = 0;
1488    # Generate property accessors for attributes.
1489    for ($index = 0; $index < @{$dataNode->attributes}; $index++) {
1490        $attribute = @{$dataNode->attributes}[$index];
1491        $attrName = $attribute->signature->name;
1492        $attrType = $attribute->signature->type;
1493
1494        # Generate special code for the constructor attributes.
1495        if ($attrType =~ /Constructor$/) {
1496            if (!($attribute->signature->extendedAttributes->{"CustomGetter"} ||
1497                $attribute->signature->extendedAttributes->{"V8CustomGetter"})) {
1498                $hasConstructors = 1;
1499            }
1500            next;
1501        }
1502
1503        if ($attrType eq "EventListener" && $interfaceName eq "DOMWindow") {
1504            $attribute->signature->extendedAttributes->{"v8OnProto"} = 1;
1505        }
1506
1507        # Do not generate accessor if this is a custom attribute.  The
1508        # call will be forwarded to a hand-written accessor
1509        # implementation.
1510        if ($attribute->signature->extendedAttributes->{"Custom"} ||
1511            $attribute->signature->extendedAttributes->{"V8Custom"}) {
1512            next;
1513        }
1514
1515        # Generate the accessor.
1516        if (!($attribute->signature->extendedAttributes->{"CustomGetter"} ||
1517            $attribute->signature->extendedAttributes->{"V8CustomGetter"})) {
1518            GenerateNormalAttrGetter($attribute, $dataNode, $implClassName, $interfaceName);
1519        }
1520        if (!($attribute->signature->extendedAttributes->{"CustomSetter"} ||
1521            $attribute->signature->extendedAttributes->{"V8CustomSetter"})) {
1522            if ($attribute->signature->extendedAttributes->{"Replaceable"}) {
1523                $dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"} || die "Replaceable attribute can only be used in interface that defines ExtendsDOMGlobalObject attribute!";
1524                # GenerateReplaceableAttrSetter($implClassName);
1525            } elsif ($attribute->type !~ /^readonly/ && !$attribute->signature->extendedAttributes->{"V8ReadOnly"}) {
1526                GenerateNormalAttrSetter($attribute, $dataNode, $implClassName, $interfaceName);
1527            }
1528        }
1529    }
1530
1531    if ($hasConstructors) {
1532        GenerateConstructorGetter($implClassName, $classIndex);
1533    }
1534
1535    my $indexer;
1536    my $namedPropertyGetter;
1537    # Generate methods for functions.
1538    foreach my $function (@{$dataNode->functions}) {
1539        # hack for addEventListener/RemoveEventListener
1540        # FIXME: avoid naming conflict
1541        if (!($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"V8Custom"})) {
1542            GenerateFunctionCallback($function, $dataNode, $classIndex, $implClassName);
1543        }
1544
1545        if ($function->signature->name eq "item") {
1546            $indexer = $function->signature;
1547        }
1548
1549        if ($function->signature->name eq "namedItem") {
1550            $namedPropertyGetter = $function->signature;
1551        }
1552
1553        # If the function does not need domain security check, we need to
1554        # generate an access getter that returns different function objects
1555        # for different calling context.
1556        if (($dataNode->extendedAttributes->{"CheckDomainSecurity"} || ($interfaceName eq "DOMWindow")) && $function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
1557            GenerateDomainSafeFunctionGetter($function, $dataNode, $implClassName);
1558        }
1559    }
1560
1561    # Attributes
1562    my $attributes = $dataNode->attributes;
1563
1564    # For the DOMWindow interface we partition the attributes into the
1565    # ones that disallows shadowing and the rest.
1566    my @disallowsShadowing;
1567    # Also separate out attributes that are enabled at runtime so we can process them specially.
1568    my @enabledAtRuntime;
1569    my @normal;
1570    foreach my $attribute (@$attributes) {
1571
1572        if ($interfaceName eq "DOMWindow" && $attribute->signature->extendedAttributes->{"V8DisallowShadowing"}) {
1573            push(@disallowsShadowing, $attribute);
1574        } elsif ($attribute->signature->extendedAttributes->{"EnabledAtRuntime"}) {
1575            push(@enabledAtRuntime, $attribute);
1576        } else {
1577            push(@normal, $attribute);
1578        }
1579    }
1580    $attributes = \@normal;
1581    # Put the attributes that disallow shadowing on the shadow object.
1582    if (@disallowsShadowing) {
1583        push(@implContent, "static const BatchedAttribute shadow_attrs[] = {\n");
1584        GenerateBatchedAttributeData($dataNode, \@disallowsShadowing);
1585        push(@implContent, "};\n");
1586    }
1587
1588    my $has_attributes = 0;
1589    if (@$attributes) {
1590        $has_attributes = 1;
1591        push(@implContent, "static const BatchedAttribute ${interfaceName}_attrs[] = {\n");
1592        GenerateBatchedAttributeData($dataNode, $attributes);
1593        push(@implContent, "};\n");
1594    }
1595
1596    # Setup table of standard callback functions
1597    $num_callbacks = 0;
1598    $has_callbacks = 0;
1599    foreach my $function (@{$dataNode->functions}) {
1600        my $attrExt = $function->signature->extendedAttributes;
1601        # Don't put any nonstandard functions into this table:
1602        if ($attrExt->{"V8OnInstance"}) {
1603            next;
1604        }
1605        if ($attrExt->{"EnabledAtRuntime"} || RequiresCustomSignature($function) || $attrExt->{"V8DoNotCheckSignature"}) {
1606            next;
1607        }
1608        if ($attrExt->{"DoNotCheckDomainSecurity"} &&
1609            ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) {
1610            next;
1611        }
1612        if ($attrExt->{"DontEnum"} || $attrExt->{"V8ReadOnly"}) {
1613            next;
1614        }
1615        if (!$has_callbacks) {
1616            $has_callbacks = 1;
1617            push(@implContent, "static const BatchedCallback ${interfaceName}_callbacks[] = {\n");
1618        }
1619        my $name = $function->signature->name;
1620        my $callback = GetFunctionTemplateCallbackName($function, $dataNode);
1621        push(@implContent, <<END);
1622  {"$name", $callback},
1623END
1624        $num_callbacks++;
1625    }
1626    push(@implContent, "};\n")  if $has_callbacks;
1627
1628    # Setup constants
1629    my $has_constants = 0;
1630    if (@{$dataNode->constants}) {
1631        $has_constants = 1;
1632        push(@implContent, "static const BatchedConstant ${interfaceName}_consts[] = {\n");
1633    }
1634    foreach my $constant (@{$dataNode->constants}) {
1635        my $name = $constant->name;
1636        my $value = $constant->value;
1637        # FIXME: we need the static_cast here only because of one constant, NodeFilter.idl
1638        # defines "const unsigned long SHOW_ALL = 0xFFFFFFFF".  It would be better if we
1639        # handled this here, and converted it to a -1 constant in the c++ output.
1640        push(@implContent, <<END);
1641  { "${name}", static_cast<signed int>($value) },
1642END
1643    }
1644    if ($has_constants) {
1645        push(@implContent, "};\n");
1646    }
1647
1648    push(@implContentDecls, "} // namespace ${interfaceName}Internal\n\n");
1649
1650    # In namespace WebCore, add generated implementation for 'CanBeConstructed'.
1651    if ($dataNode->extendedAttributes->{"CanBeConstructed"} && !$dataNode->extendedAttributes->{"CustomConstructor"}) {
1652        push(@implContent, <<END);
1653 v8::Handle<v8::Value> ${className}::constructorCallback(const v8::Arguments& args)
1654  {
1655    INC_STATS("DOM.${interfaceName}.Contructor");
1656    return V8Proxy::constructDOMObject<V8ClassIndex::${classIndex}, $interfaceName>(args);
1657  }
1658END
1659   }
1660
1661    my $access_check = "";
1662    if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !($interfaceName eq "DOMWindow")) {
1663        $access_check = "instance->SetAccessCheckCallbacks(V8${interfaceName}::namedSecurityCheck, V8${interfaceName}::indexedSecurityCheck, v8::Integer::New(V8ClassIndex::ToInt(V8ClassIndex::${classIndex})));";
1664    }
1665
1666    # For the DOMWindow interface, generate the shadow object template
1667    # configuration method.
1668    if ($implClassName eq "DOMWindow") {
1669        push(@implContent, <<END);
1670static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Persistent<v8::ObjectTemplate> templ) {
1671  batchConfigureAttributes(templ,
1672                           v8::Handle<v8::ObjectTemplate>(),
1673                           shadow_attrs,
1674                           sizeof(shadow_attrs)/sizeof(*shadow_attrs));
1675
1676  // Install a security handler with V8.
1677  templ->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::Integer::New(V8ClassIndex::DOMWINDOW));
1678  templ->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
1679  return templ;
1680}
1681END
1682    }
1683
1684    # find the super descriptor
1685    my $parentClassTemplate = "";
1686    foreach (@{$dataNode->parents}) {
1687        my $parent = $codeGenerator->StripModule($_);
1688        if ($parent eq "EventTarget") { next; }
1689        $implIncludes{"V8${parent}.h"} = 1;
1690        $parentClassTemplate = "V8" . $parent . "::GetTemplate()";
1691        last;
1692    }
1693    if (!$parentClassTemplate) {
1694        $parentClassTemplate = "v8::Persistent<v8::FunctionTemplate>()";
1695    }
1696
1697    # Generate the template configuration method
1698    push(@implContent,  <<END);
1699static v8::Persistent<v8::FunctionTemplate> Configure${className}Template(v8::Persistent<v8::FunctionTemplate> desc) {
1700  v8::Local<v8::Signature> default_signature = configureTemplate(desc, \"${interfaceName}\",
1701      $parentClassTemplate, V8${interfaceName}::internalFieldCount,
1702END
1703    # Set up our attributes if we have them
1704    if ($has_attributes) {
1705        push(@implContent, <<END);
1706      ${interfaceName}_attrs, sizeof(${interfaceName}_attrs)/sizeof(*${interfaceName}_attrs),
1707END
1708    } else {
1709        push(@implContent, <<END);
1710      NULL, 0,
1711END
1712    }
1713
1714    if ($has_callbacks) {
1715        push(@implContent, <<END);
1716      ${interfaceName}_callbacks, sizeof(${interfaceName}_callbacks)/sizeof(*${interfaceName}_callbacks));
1717END
1718    } else {
1719        push(@implContent, <<END);
1720      NULL, 0);
1721END
1722    }
1723
1724    if ($dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"CanBeConstructed"}) {
1725        push(@implContent, <<END);
1726      desc->SetCallHandler(V8${interfaceName}::constructorCallback);
1727END
1728    }
1729
1730    if ($access_check or @enabledAtRuntime or @{$dataNode->functions} or $has_constants) {
1731        push(@implContent,  <<END);
1732  v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate();
1733  v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate();
1734END
1735    }
1736
1737    push(@implContent,  "  $access_check\n");
1738
1739    # Setup the enable-at-runtime attrs if we have them
1740    foreach my $runtime_attr (@enabledAtRuntime) {
1741        # A function named RuntimeEnabledFeatures::{methodName}Enabled() need to be written by hand.
1742        $enable_function = "RuntimeEnabledFeatures::" . $codeGenerator->WK_lcfirst($runtime_attr->signature->name) . "Enabled";
1743        my $conditionalString = GenerateConditionalString($runtime_attr->signature);
1744        push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
1745        push(@implContent, "    if (${enable_function}()) {\n");
1746        push(@implContent, "        static const BatchedAttribute attrData =\\\n");
1747        GenerateSingleBatchedAttribute($interfaceName, $runtime_attr, ";", "    ");
1748        push(@implContent, <<END);
1749        configureAttribute(instance, proto, attrData);
1750    }
1751END
1752        push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
1753    }
1754
1755    GenerateImplementationIndexer($dataNode, $indexer);
1756    GenerateImplementationNamedPropertyGetter($dataNode, $namedPropertyGetter);
1757    GenerateImplementationCustomCall($dataNode);
1758    GenerateImplementationMasqueradesAsUndefined($dataNode);
1759
1760    # Define our functions with Set() or SetAccessor()
1761    $total_functions = 0;
1762    foreach my $function (@{$dataNode->functions}) {
1763        $total_functions++;
1764        my $attrExt = $function->signature->extendedAttributes;
1765        my $name = $function->signature->name;
1766
1767        my $property_attributes = "v8::DontDelete";
1768        if ($attrExt->{"DontEnum"}) {
1769            $property_attributes .= "|v8::DontEnum";
1770        }
1771        if ($attrExt->{"V8ReadOnly"}) {
1772            $property_attributes .= "|v8::ReadOnly";
1773        }
1774
1775        my $commentInfo = "Function '$name' (ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
1776
1777        my $template = "proto";
1778        if ($attrExt->{"V8OnInstance"}) {
1779            $template = "instance";
1780        }
1781
1782        my $conditional = "";
1783        if ($attrExt->{"EnabledAtRuntime"}) {
1784            # Only call Set()/SetAccessor() if this method should be enabled
1785            $enable_function = "RuntimeEnabledFeatures::" . $codeGenerator->WK_lcfirst($function->signature->name) . "Enabled";
1786            $conditional = "if (${enable_function}())\n";
1787        }
1788
1789        if ($attrExt->{"DoNotCheckDomainSecurity"} &&
1790            ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) {
1791            # Mark the accessor as ReadOnly and set it on the proto object so
1792            # it can be shadowed. This is really a hack to make it work.
1793            # There are several sceneria to call into the accessor:
1794            #   1) from the same domain: "window.open":
1795            #      the accessor finds the DOM wrapper in the proto chain;
1796            #   2) from the same domain: "window.__proto__.open":
1797            #      the accessor will NOT find a DOM wrapper in the prototype chain
1798            #   3) from another domain: "window.open":
1799            #      the access find the DOM wrapper in the prototype chain
1800            #   "window.__proto__.open" from another domain will fail when
1801            #   accessing '__proto__'
1802            #
1803            # The solution is very hacky and fragile, it really needs to be replaced
1804            # by a better solution.
1805            $property_attributes .= "|v8::ReadOnly";
1806            push(@implContent, <<END);
1807
1808  // $commentInfo
1809  $conditional $template->SetAccessor(
1810      v8::String::New("$name"),
1811      ${interfaceName}Internal::${name}AttrGetter,
1812      0,
1813      v8::Handle<v8::Value>(),
1814      v8::ALL_CAN_READ,
1815      static_cast<v8::PropertyAttribute>($property_attributes));
1816END
1817          $num_callbacks++;
1818          next;
1819      }
1820
1821      my $signature = "default_signature";
1822      if ($attrExt->{"V8DoNotCheckSignature"}){
1823          $signature = "v8::Local<v8::Signature>()";
1824      }
1825
1826      if (RequiresCustomSignature($function)) {
1827          $signature = "${name}_signature";
1828          push(@implContent, "\n  // Custom Signature '$name'\n", CreateCustomSignature($function));
1829      }
1830
1831      # Normal function call is a template
1832      my $callback = GetFunctionTemplateCallbackName($function, $dataNode);
1833
1834      if ($property_attributes eq "v8::DontDelete") {
1835          $property_attributes = "";
1836      } else {
1837          $property_attributes = ", static_cast<v8::PropertyAttribute>($property_attributes)";
1838      }
1839
1840      if ($template eq "proto" && $conditional eq "" && $signature eq "default_signature" && $property_attributes eq "") {
1841          # Standard type of callback, already created in the batch, so skip it here.
1842          next;
1843      }
1844
1845      push(@implContent, <<END);
1846  ${conditional}$template->Set(v8::String::New("$name"), v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), ${signature})$property_attributes);
1847END
1848      $num_callbacks++;
1849    }
1850
1851    die "Wrong number of callbacks generated for $interfaceName ($num_callbacks, should be $total_functions)" if $num_callbacks != $total_functions;
1852
1853    if ($has_constants) {
1854        push(@implContent, <<END);
1855  batchConfigureConstants(desc, proto, ${interfaceName}_consts, sizeof(${interfaceName}_consts)/sizeof(*${interfaceName}_consts));
1856END
1857    }
1858
1859    # Special cases
1860    if ($interfaceName eq "DOMWindow") {
1861        push(@implContent, <<END);
1862
1863  proto->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
1864  desc->SetHiddenPrototype(true);
1865  instance->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
1866  // Set access check callbacks, but turned off initially.
1867  // When a context is detached from a frame, turn on the access check.
1868  // Turning on checks also invalidates inline caches of the object.
1869  instance->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::Integer::New(V8ClassIndex::DOMWINDOW), false);
1870END
1871    }
1872    if ($interfaceName eq "Location") {
1873        push(@implContent, <<END);
1874
1875  // For security reasons, these functions are on the instance instead
1876  // of on the prototype object to insure that they cannot be overwritten.
1877  instance->SetAccessor(v8::String::New("reload"), V8Location::reloadAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
1878  instance->SetAccessor(v8::String::New("replace"), V8Location::replaceAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
1879  instance->SetAccessor(v8::String::New("assign"), V8Location::assignAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
1880END
1881    }
1882
1883    my $nativeType = GetNativeTypeForConversions($interfaceName);
1884    if ($dataNode->extendedAttributes->{"PODType"}) {
1885        $nativeType = "V8SVGPODTypeWrapper<${nativeType}>";
1886    }
1887    push(@implContent, <<END);
1888
1889  // Custom toString template
1890  desc->Set(getToStringName(), getToStringTemplate());
1891  return desc;
1892}
1893
1894v8::Persistent<v8::FunctionTemplate> ${className}::GetRawTemplate() {
1895  static v8::Persistent<v8::FunctionTemplate> ${className}_raw_cache_ = createRawTemplate();
1896  return ${className}_raw_cache_;
1897}
1898
1899v8::Persistent<v8::FunctionTemplate> ${className}::GetTemplate() {
1900  static v8::Persistent<v8::FunctionTemplate> ${className}_cache_ = Configure${className}Template(GetRawTemplate());
1901  return ${className}_cache_;
1902}
1903
1904${nativeType}* ${className}::toNative(v8::Handle<v8::Object> object) {
1905  return reinterpret_cast<${nativeType}*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex));
1906}
1907
1908bool ${className}::HasInstance(v8::Handle<v8::Value> value) {
1909  return GetRawTemplate()->HasInstance(value);
1910}
1911
1912END
1913
1914    if ($implClassName eq "DOMWindow") {
1915        push(@implContent, <<END);
1916v8::Persistent<v8::ObjectTemplate> V8DOMWindow::GetShadowObjectTemplate() {
1917  static v8::Persistent<v8::ObjectTemplate> V8DOMWindowShadowObject_cache_;
1918  if (V8DOMWindowShadowObject_cache_.IsEmpty()) {
1919    V8DOMWindowShadowObject_cache_ = v8::Persistent<v8::ObjectTemplate>::New(v8::ObjectTemplate::New());
1920    ConfigureShadowObjectTemplate(V8DOMWindowShadowObject_cache_);
1921  }
1922  return V8DOMWindowShadowObject_cache_;
1923}
1924END
1925    }
1926
1927    GenerateToV8Converters($dataNode, $interfaceName, $className, $nativeType);
1928
1929    push(@implContent, <<END);
1930} // namespace WebCore
1931END
1932
1933    push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
1934}
1935
1936sub GenerateToV8Converters
1937{
1938    my $dataNode = shift;
1939    my $interfaceName = shift;
1940    my $className = shift;
1941    my $nativeType = shift;
1942
1943    my $wrapperType = "V8ClassIndex::" . uc($interfaceName);
1944    my $domMapFunction = GetDomMapFunction($dataNode, $interfaceName);
1945    my $forceNewObjectInput = IsDOMNodeType($interfaceName) ? ", bool forceNewObject" : "";
1946    my $forceNewObjectCall = IsDOMNodeType($interfaceName) ? ", forceNewObject" : "";
1947
1948    push(@implContent, <<END);
1949
1950v8::Handle<v8::Object> ${className}::wrap(${nativeType}* impl${forceNewObjectInput}) {
1951  v8::Handle<v8::Object> wrapper;
1952  V8Proxy* proxy = 0;
1953END
1954
1955    if (IsNodeSubType($dataNode)) {
1956        push(@implContent, <<END);
1957  if (impl->document()) {
1958    proxy = V8Proxy::retrieve(impl->document()->frame());
1959    if (proxy && static_cast<Node*>(impl->document()) == static_cast<Node*>(impl))
1960      proxy->windowShell()->initContextIfNeeded();
1961  }
1962
1963END
1964    }
1965
1966    if ($domMapFunction) {
1967        push(@implContent, "  if (!forceNewObject) {\n") if IsDOMNodeType($interfaceName);
1968        if (IsNodeSubType($dataNode)) {
1969            push(@implContent, "  wrapper = V8DOMWrapper::getWrapper(impl);\n");
1970        } else {
1971            push(@implContent, "  wrapper = ${domMapFunction}.get(impl);\n");
1972        }
1973        push(@implContent, <<END);
1974  if (!wrapper.IsEmpty())
1975    return wrapper;
1976END
1977        push(@implContent, "  }\n") if IsDOMNodeType($interfaceName);
1978    }
1979    if (IsNodeSubType($dataNode)) {
1980        push(@implContent, <<END);
1981
1982  v8::Handle<v8::Context> context;
1983  if (proxy)
1984    context = proxy->context();
1985
1986  // Enter the node's context and create the wrapper in that context.
1987  if (!context.IsEmpty())
1988    context->Enter();
1989END
1990    }
1991
1992    push(@implContent, <<END);
1993  wrapper = V8DOMWrapper::instantiateV8Object(proxy, ${wrapperType}, impl);
1994END
1995
1996    if (IsNodeSubType($dataNode)) {
1997        push(@implContent, <<END);
1998  // Exit the node's context if it was entered.
1999  if (!context.IsEmpty())
2000    context->Exit();
2001END
2002    }
2003
2004    push(@implContent, <<END);
2005  if (wrapper.IsEmpty())
2006    return wrapper;
2007END
2008    push(@implContent, "\n  impl->ref();\n") if IsRefPtrType($interfaceName);
2009
2010    if ($domMapFunction) {
2011        push(@implContent, <<END);
2012  ${domMapFunction}.set(impl, v8::Persistent<v8::Object>::New(wrapper));
2013END
2014    }
2015
2016    push(@implContent, <<END);
2017  return wrapper;
2018}
2019END
2020
2021    if (IsRefPtrType($interfaceName)) {
2022        push(@implContent, <<END);
2023
2024v8::Handle<v8::Value> toV8(PassRefPtr<${nativeType} > impl${forceNewObjectInput}) {
2025  return toV8(impl.get()${forceNewObjectCall});
2026}
2027END
2028    }
2029
2030    if (!HasCustomToV8Implementation($dataNode, $interfaceName)) {
2031        push(@implContent, <<END);
2032
2033v8::Handle<v8::Value> toV8(${nativeType}* impl${forceNewObjectInput}) {
2034  if (!impl)
2035    return v8::Null();
2036  return ${className}::wrap(impl${forceNewObjectCall});
2037}
2038END
2039    }
2040}
2041
2042sub HasCustomToV8Implementation {
2043    # FIXME: This subroutine is lame. Probably should be an .idl attribute (CustomToV8)?
2044    $dataNode = shift;
2045    $interfaceName = shift;
2046
2047    # We generate a custom converter (but JSC doesn't) for the following:
2048    return 1 if $interfaceName eq "BarInfo";
2049    return 1 if $interfaceName eq "CSSStyleSheet";
2050    return 1 if $interfaceName eq "CanvasPixelArray";
2051    return 1 if $interfaceName eq "DOMSelection";
2052    return 1 if $interfaceName eq "DOMWindow";
2053    return 1 if $interfaceName eq "Element";
2054    return 1 if $interfaceName eq "Location";
2055    return 1 if $interfaceName eq "HTMLDocument";
2056    return 1 if $interfaceName eq "HTMLElement";
2057    return 1 if $interfaceName eq "History";
2058    return 1 if $interfaceName eq "NamedNodeMap";
2059    return 1 if $interfaceName eq "Navigator";
2060    return 1 if $interfaceName eq "SVGDocument";
2061    return 1 if $interfaceName eq "SVGElement";
2062    return 1 if $interfaceName eq "Screen";
2063    return 1 if $interfaceName eq "WorkerContext";
2064    # We don't generate a custom converter (but JSC does) for the following:
2065    return 0 if $interfaceName eq "AbstractWorker";
2066    return 0 if $interfaceName eq "CanvasRenderingContext";
2067    return 0 if $interfaceName eq "ImageData";
2068    return 0 if $interfaceName eq "SVGElementInstance";
2069
2070    # For everything else, do what JSC does.
2071    return $dataNode->extendedAttributes->{"CustomToJS"};
2072}
2073
2074sub GetDomMapFunction
2075{
2076    my $dataNode = shift;
2077    my $type = shift;
2078    return "getDOMSVGElementInstanceMap()" if $type eq "SVGElementInstance";
2079    return "getDOMNodeMap()" if IsNodeSubType($dataNode);
2080    # Only use getDOMSVGObjectWithContextMap() for non-node svg objects
2081    return "getDOMSVGObjectWithContextMap()" if $type =~ /SVG/;
2082    return "" if $type eq "DOMImplementation";
2083    return "getActiveDOMObjectMap()" if IsActiveDomType($type);
2084    return "getDOMObjectMap()";
2085}
2086
2087sub IsActiveDomType
2088{
2089    # FIXME: Consider making this an .idl attribute.
2090    my $type = shift;
2091    return 1 if $type eq "MessagePort";
2092    return 1 if $type eq "XMLHttpRequest";
2093    return 1 if $type eq "WebSocket";
2094    return 1 if $type eq "Worker";
2095    return 1 if $type eq "SharedWorker";
2096    return 0;
2097}
2098
2099sub GetNativeTypeForConversions
2100{
2101    my $type = shift;
2102    return "FloatRect" if $type eq "SVGRect";
2103    return "FloatPoint" if $type eq "SVGPoint";
2104    return "AffineTransform" if $type eq "SVGMatrix";
2105    return "float" if $type eq "SVGNumber";
2106    return $type;
2107}
2108
2109sub GenerateFunctionCallString()
2110{
2111    my $function = shift;
2112    my $numberOfParameters = shift;
2113    my $indent = shift;
2114    my $implClassName = shift;
2115
2116    my $name = $function->signature->name;
2117    my $isPodType = IsPodType($implClassName);
2118    my $returnType = GetTypeFromSignature($function->signature);
2119    my $returnsPodType = IsPodType($returnType);
2120    my $nativeReturnType = GetNativeType($returnType, 0);
2121    my $result = "";
2122
2123    # Special case: SVG matrix transform methods should not mutate
2124    # the matrix but return a copy
2125    my $copyFirst = 0;
2126    if ($implClassName eq "SVGMatrix" && $function->signature->type eq "SVGMatrix") {
2127        $copyFirst = 1;
2128    }
2129
2130    if ($function->signature->extendedAttributes->{"v8implname"}) {
2131        $name = $function->signature->extendedAttributes->{"v8implname"};
2132    }
2133
2134    if ($function->signature->extendedAttributes->{"ImplementationFunction"}) {
2135        $name = $function->signature->extendedAttributes->{"ImplementationFunction"};
2136    }
2137
2138    my $functionString = "imp->${name}(";
2139
2140    if ($copyFirst) {
2141        $functionString = "result.${name}(";
2142    }
2143
2144    my $returnsListItemPodType = 0;
2145    # SVG lists functions that return POD types require special handling
2146    if (IsSVGListTypeNeedingSpecialHandling($implClassName) && IsSVGListMethod($name) && $returnsPodType) {
2147        $returnsListItemPodType = 1;
2148        $result .= $indent . "SVGList<RefPtr<SVGPODListItem<$nativeReturnType> > >* listImp = imp;\n";
2149        $functionString = "listImp->${name}(";
2150    }
2151
2152    my $first = 1;
2153    my $index = 0;
2154
2155    foreach my $parameter (@{$function->parameters}) {
2156        if ($index eq $numberOfParameters) {
2157            last;
2158        }
2159        if ($first) { $first = 0; }
2160        else { $functionString .= ", "; }
2161        my $paramName = $parameter->name;
2162        my $paramType = $parameter->type;
2163
2164        # This is a bit of a hack... we need to convert parameters to methods on SVG lists
2165        # of POD types which are items in the list to appropriate SVGList<> instances
2166        if ($returnsListItemPodType && $paramType . "List" eq $implClassName) {
2167            $paramName = "SVGPODListItem<" . GetNativeType($paramType, 1) . ">::copy($paramName)";
2168        }
2169
2170        if ($parameter->type eq "NodeFilter" || $parameter->type eq "XPathNSResolver") {
2171            $functionString .= "$paramName.get()";
2172        } else {
2173            $functionString .= $paramName;
2174        }
2175        $index++;
2176    }
2177
2178    if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
2179        $functionString .= ", " if not $first;
2180        $functionString .= "callStack.get()";
2181        if ($first) { $first = 0; }
2182    }
2183
2184    if ($function->signature->extendedAttributes->{"NeedsUserGestureCheck"}) {
2185        $functionString .= ", " if not $first;
2186        # FIXME: We need to pass DOMWrapperWorld as a parameter.
2187        # See http://trac.webkit.org/changeset/54182
2188        $functionString .= "processingUserGesture()";
2189        if ($first) { $first = 0; }
2190    }
2191
2192    if (@{$function->raisesExceptions}) {
2193        $functionString .= ", " if not $first;
2194        $functionString .= "ec";
2195    }
2196    $functionString .= ")";
2197
2198    my $return = "result";
2199    my $returnIsRef = IsRefPtrType($returnType);
2200
2201    if ($returnType eq "void") {
2202        $result .= $indent . "$functionString;\n";
2203    } elsif ($copyFirst) {
2204        $result .=
2205            $indent . GetNativeType($returnType, 0) . " result = *imp;\n" .
2206            $indent . "$functionString;\n";
2207    } elsif ($returnsListItemPodType) {
2208        $result .= $indent . "RefPtr<SVGPODListItem<$nativeReturnType> > result = $functionString;\n";
2209    } elsif (@{$function->raisesExceptions} or $returnsPodType or $isPodType or IsSVGTypeNeedingContextParameter($returnType)) {
2210        $result .= $indent . $nativeReturnType . " result = $functionString;\n";
2211    } else {
2212        # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
2213        $return = $functionString;
2214        $returnIsRef = 0;
2215    }
2216
2217    if (@{$function->raisesExceptions}) {
2218        $result .= $indent . "if (UNLIKELY(ec)) goto fail;\n";
2219    }
2220
2221    # If the return type is a POD type, separate out the wrapper generation
2222    if ($returnsListItemPodType) {
2223        $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = ";
2224        $result .= "V8SVGPODTypeWrapperCreatorForList<" . $nativeReturnType . ">::create($return, imp->associatedAttributeName());\n";
2225        $return = "wrapper";
2226    } elsif ($returnsPodType) {
2227        $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = ";
2228        $result .= GenerateSVGStaticPodTypeWrapper($returnType, $return) . ";\n";
2229        $return = "wrapper";
2230    }
2231
2232    my $generatedSVGContextRetrieval = 0;
2233    # If the return type needs an SVG context, output it
2234    if (IsSVGTypeNeedingContextParameter($returnType)) {
2235        $result .= GenerateSVGContextAssignment($implClassName, $return . ".get()", $indent);
2236        $generatedSVGContextRetrieval = 1;
2237    }
2238
2239    if (IsSVGTypeNeedingContextParameter($implClassName) && $implClassName =~ /List$/ && IsSVGListMutator($name)) {
2240        if (!$generatedSVGContextRetrieval) {
2241            $result .= GenerateSVGContextRetrieval($implClassName, $indent);
2242            $generatedSVGContextRetrieval = 1;
2243        }
2244
2245        $result .= $indent . "context->svgAttributeChanged(imp->associatedAttributeName());\n";
2246        $implIncludes{"SVGElement.h"} = 1;
2247    }
2248
2249    # If the implementing class is a POD type, commit changes
2250    if ($isPodType) {
2251        if (!$generatedSVGContextRetrieval) {
2252            $result .= GenerateSVGContextRetrieval($implClassName, $indent);
2253            $generatedSVGContextRetrieval = 1;
2254        }
2255
2256        $result .= $indent . "imp_wrapper->commitChange(imp_instance, context);\n";
2257    }
2258
2259    if ($returnsPodType) {
2260        $implIncludes{"V8${returnType}.h"} = 1;
2261        $result .= $indent . "return toV8(wrapper.release());\n";
2262    } else {
2263        $return .= ".release()" if ($returnIsRef);
2264        $result .= $indent . ReturnNativeToJSValue($function->signature, $return, $indent) . ";\n";
2265    }
2266
2267    return $result;
2268}
2269
2270
2271sub GetTypeFromSignature
2272{
2273    my $signature = shift;
2274
2275    return $codeGenerator->StripModule($signature->type);
2276}
2277
2278
2279sub GetNativeTypeFromSignature
2280{
2281    my $signature = shift;
2282    my $parameterIndex = shift;
2283
2284    my $type = GetTypeFromSignature($signature);
2285
2286    if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) {
2287        # Special-case index arguments because we need to check that they aren't < 0.
2288        return "int";
2289    }
2290
2291    $type = GetNativeType($type, $parameterIndex >= 0 ? 1 : 0);
2292
2293    if ($parameterIndex >= 0 && $type eq "V8Parameter") {
2294        my $mode = "";
2295        if ($signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"}) {
2296            $mode = "WithUndefinedOrNullCheck";
2297        } elsif ($signature->extendedAttributes->{"ConvertNullToNullString"}) {
2298            $mode = "WithNullCheck";
2299        }
2300        $type .= "<$mode>";
2301    }
2302
2303    return $type;
2304}
2305
2306sub IsRefPtrType
2307{
2308    my $type = shift;
2309
2310    return 0 if $type eq "boolean";
2311    return 0 if $type eq "float";
2312    return 0 if $type eq "int";
2313    return 0 if $type eq "Date";
2314    return 0 if $type eq "DOMString";
2315    return 0 if $type eq "double";
2316    return 0 if $type eq "short";
2317    return 0 if $type eq "long";
2318    return 0 if $type eq "unsigned";
2319    return 0 if $type eq "unsigned long";
2320    return 0 if $type eq "unsigned short";
2321    return 0 if $type eq "SVGAnimatedPoints";
2322
2323    return 1;
2324}
2325
2326sub GetNativeType
2327{
2328    my $type = shift;
2329    my $isParameter = shift;
2330
2331    if ($type eq "float" or $type eq "double") {
2332        return $type;
2333    }
2334
2335    return "V8Parameter" if ($type eq "DOMString" or $type eq "DOMUserData") and $isParameter;
2336    return "int" if $type eq "int";
2337    return "int" if $type eq "short" or $type eq "unsigned short";
2338    return "unsigned" if $type eq "unsigned long";
2339    return "int" if $type eq "long";
2340    return "long long" if $type eq "long long";
2341    return "unsigned long long" if $type eq "unsigned long long";
2342    return "bool" if $type eq "boolean";
2343    return "String" if $type eq "DOMString";
2344    return "Range::CompareHow" if $type eq "CompareHow";
2345    return "FloatRect" if $type eq "SVGRect";
2346    return "FloatPoint" if $type eq "SVGPoint";
2347    return "AffineTransform" if $type eq "SVGMatrix";
2348    return "SVGTransform" if $type eq "SVGTransform";
2349    return "SVGLength" if $type eq "SVGLength";
2350    return "SVGAngle" if $type eq "SVGAngle";
2351    return "float" if $type eq "SVGNumber";
2352    return "SVGPreserveAspectRatio" if $type eq "SVGPreserveAspectRatio";
2353    return "SVGPaint::SVGPaintType" if $type eq "SVGPaintType";
2354    return "DOMTimeStamp" if $type eq "DOMTimeStamp";
2355    return "unsigned" if $type eq "unsigned int";
2356    return "Node*" if $type eq "EventTarget" and $isParameter;
2357    return "double" if $type eq "Date";
2358
2359    return "String" if $type eq "DOMUserData";  # FIXME: Temporary hack?
2360
2361    # temporary hack
2362    return "RefPtr<NodeFilter>" if $type eq "NodeFilter";
2363
2364    # necessary as resolvers could be constructed on fly.
2365    return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver";
2366
2367    return "RefPtr<${type}>" if IsRefPtrType($type) and not $isParameter;
2368
2369    # Default, assume native type is a pointer with same type name as idl type
2370    return "${type}*";
2371}
2372
2373
2374my %typeCanFailConversion = (
2375    "Attr" => 1,
2376    "WebGLArray" => 0,
2377    "WebGLBuffer" => 0,
2378    "WebGLByteArray" => 0,
2379    "WebGLUnsignedByteArray" => 0,
2380    "WebGLContextAttributes" => 0,
2381    "WebGLFloatArray" => 0,
2382    "WebGLFramebuffer" => 0,
2383    "CanvasGradient" => 0,
2384    "WebGLIntArray" => 0,
2385    "CanvasPixelArray" => 0,
2386    "WebGLProgram" => 0,
2387    "WebGLRenderbuffer" => 0,
2388    "WebGLShader" => 0,
2389    "WebGLShortArray" => 0,
2390    "WebGLTexture" => 0,
2391    "WebGLUniformLocation" => 0,
2392    "CompareHow" => 0,
2393    "DataGridColumn" => 0,
2394    "DOMString" => 0,
2395    "DOMWindow" => 0,
2396    "DocumentType" => 0,
2397    "Element" => 0,
2398    "Event" => 0,
2399    "EventListener" => 0,
2400    "EventTarget" => 0,
2401    "HTMLCanvasElement" => 0,
2402    "HTMLElement" => 0,
2403    "HTMLImageElement" => 0,
2404    "HTMLOptionElement" => 0,
2405    "HTMLVideoElement" => 0,
2406    "Node" => 0,
2407    "NodeFilter" => 0,
2408    "MessagePort" => 0,
2409    "NSResolver" => 0,
2410    "Range" => 0,
2411    "SQLResultSet" => 0,
2412    "Storage" => 0,
2413    "SVGAngle" => 1,
2414    "SVGElement" => 0,
2415    "SVGLength" => 1,
2416    "SVGMatrix" => 1,
2417    "SVGNumber" => 0,
2418    "SVGPaintType" => 0,
2419    "SVGPathSeg" => 0,
2420    "SVGPoint" => 1,
2421    "SVGPreserveAspectRatio" => 1,
2422    "SVGRect" => 1,
2423    "SVGTransform" => 1,
2424    "TouchList" => 0,
2425    "VoidCallback" => 1,
2426    "WebKitCSSMatrix" => 0,
2427    "WebKitPoint" => 0,
2428    "XPathEvaluator" => 0,
2429    "XPathNSResolver" => 0,
2430    "XPathResult" => 0,
2431    "boolean" => 0,
2432    "double" => 0,
2433    "float" => 0,
2434    "long" => 0,
2435    "unsigned long" => 0,
2436    "unsigned short" => 0,
2437    "long long" => 0,
2438    "unsigned long long" => 0
2439);
2440
2441
2442sub TranslateParameter
2443{
2444    my $signature = shift;
2445
2446    # The IDL uses some pseudo-types which don't really exist.
2447    if ($signature->type eq "TimeoutHandler") {
2448      $signature->type("DOMString");
2449    }
2450}
2451
2452sub BasicTypeCanFailConversion
2453{
2454    my $signature = shift;
2455    my $type = GetTypeFromSignature($signature);
2456
2457    return 1 if $type eq "SVGAngle";
2458    return 1 if $type eq "SVGLength";
2459    return 1 if $type eq "SVGMatrix";
2460    return 1 if $type eq "SVGPoint";
2461    return 1 if $type eq "SVGPreserveAspectRatio";
2462    return 1 if $type eq "SVGRect";
2463    return 1 if $type eq "SVGTransform";
2464    return 0;
2465}
2466
2467sub TypeCanFailConversion
2468{
2469    my $signature = shift;
2470
2471    my $type = GetTypeFromSignature($signature);
2472
2473    $implIncludes{"ExceptionCode.h"} = 1 if $type eq "Attr";
2474
2475    return $typeCanFailConversion{$type} if exists $typeCanFailConversion{$type};
2476
2477    die "Don't know whether a JS value can fail conversion to type $type.";
2478}
2479
2480sub JSValueToNative
2481{
2482    my $signature = shift;
2483    my $value = shift;
2484    my $okParam = shift;
2485    my $maybeOkParam = $okParam ? ", ${okParam}" : "";
2486
2487    my $type = GetTypeFromSignature($signature);
2488
2489    return "$value" if $type eq "JSObject";
2490    return "$value->BooleanValue()" if $type eq "boolean";
2491    return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $type eq "double";
2492    return "$value->NumberValue()" if $type eq "SVGNumber";
2493
2494    return "toInt32($value${maybeOkParam})" if $type eq "unsigned long" or $type eq "unsigned short" or $type eq "long";
2495    return "toInt64($value)" if $type eq "unsigned long long" or $type eq "long long";
2496    return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "CompareHow";
2497    return "static_cast<SVGPaint::SVGPaintType>($value->ToInt32()->Int32Value())" if $type eq "SVGPaintType";
2498    return "toWebCoreDate($value)" if $type eq "Date";
2499
2500    if ($type eq "DOMString" or $type eq "DOMUserData") {
2501        return $value;
2502    }
2503
2504    if ($type eq "SerializedScriptValue") {
2505        $implIncludes{"SerializedScriptValue.h"} = 1;
2506        return "SerializedScriptValue::create($value)";
2507    }
2508
2509    if ($type eq "NodeFilter") {
2510        return "V8DOMWrapper::wrapNativeNodeFilter($value)";
2511    }
2512
2513    if ($type eq "SVGRect") {
2514        $implIncludes{"FloatRect.h"} = 1;
2515    }
2516
2517    if ($type eq "SVGPoint") {
2518        $implIncludes{"FloatPoint.h"} = 1;
2519    }
2520
2521    # Default, assume autogenerated type conversion routines
2522    if ($type eq "EventTarget") {
2523        $implIncludes{"V8Node.h"} = 1;
2524
2525        # EventTarget is not in DOM hierarchy, but all Nodes are EventTarget.
2526        return "V8Node::HasInstance($value) ? V8Node::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
2527    }
2528
2529    if ($type eq "XPathNSResolver") {
2530        return "V8DOMWrapper::getXPathNSResolver($value)";
2531    }
2532
2533    AddIncludesForType($type);
2534
2535    if (IsDOMNodeType($type)) {
2536        $implIncludes{"V8${type}.h"} = 1;
2537
2538        # Perform type checks on the parameter, if it is expected Node type,
2539        # return NULL.
2540        return "V8${type}::HasInstance($value) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
2541    } else {
2542        # TODO: Temporary to avoid Window name conflict.
2543        my $classIndex = uc($type);
2544        my $implClassName = ${type};
2545
2546        $implIncludes{"V8$type.h"} = 1;
2547
2548        if (IsPodType($type)) {
2549            my $nativeType = GetNativeType($type);
2550            $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
2551
2552            return "V8SVGPODTypeUtil::toSVGPODType<${nativeType}>(V8ClassIndex::${classIndex}, $value${maybeOkParam})"
2553        }
2554
2555        $implIncludes{"V8${type}.h"} = 1;
2556
2557        # Perform type checks on the parameter, if it is expected Node type,
2558        # return NULL.
2559        return "V8${type}::HasInstance($value) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
2560    }
2561}
2562
2563
2564sub GetV8HeaderName
2565{
2566    my $type = shift;
2567    return "V8Event.h" if $type eq "DOMTimeStamp";
2568    return "EventListener.h" if $type eq "EventListener";
2569    return "EventTarget.h" if $type eq "EventTarget";
2570    return "SerializedScriptValue.h" if $type eq "SerializedScriptValue";
2571    return "V8${type}.h";
2572}
2573
2574
2575sub CreateCustomSignature
2576{
2577    my $function = shift;
2578    my $count = @{$function->parameters};
2579    my $name = $function->signature->name;
2580    my $result = "  const int ${name}_argc = ${count};\n" .
2581      "  v8::Handle<v8::FunctionTemplate> ${name}_argv[${name}_argc] = { ";
2582    my $first = 1;
2583    foreach my $parameter (@{$function->parameters}) {
2584        if ($first) { $first = 0; }
2585        else { $result .= ", "; }
2586        if (IsWrapperType($parameter->type)) {
2587            if ($parameter->type eq "XPathNSResolver") {
2588                # Special case for XPathNSResolver.  All other browsers accepts a callable,
2589                # so, even though it's against IDL, accept objects here.
2590                $result .= "v8::Handle<v8::FunctionTemplate>()";
2591            } else {
2592                my $type = $parameter->type;
2593                my $header = GetV8HeaderName($type);
2594                $implIncludes{$header} = 1;
2595                $result .= "V8${type}::GetRawTemplate()";
2596            }
2597        } else {
2598            $result .= "v8::Handle<v8::FunctionTemplate>()";
2599        }
2600    }
2601    $result .= " };\n";
2602    $result .= "  v8::Handle<v8::Signature> ${name}_signature = v8::Signature::New(desc, ${name}_argc, ${name}_argv);\n";
2603    return $result;
2604}
2605
2606
2607sub RequiresCustomSignature
2608{
2609    my $function = shift;
2610    # No signature needed for Custom function
2611    if ($function->signature->extendedAttributes->{"Custom"} ||
2612        $function->signature->extendedAttributes->{"V8Custom"}) {
2613        return 0;
2614    }
2615
2616    foreach my $parameter (@{$function->parameters}) {
2617      if (IsWrapperType($parameter->type)) {
2618          return 1;
2619      }
2620    }
2621    return 0;
2622}
2623
2624
2625my %non_wrapper_types = (
2626    'float' => 1,
2627    'double' => 1,
2628    'short' => 1,
2629    'unsigned short' => 1,
2630    'long' => 1,
2631    'unsigned long' => 1,
2632    'boolean' => 1,
2633    'long long' => 1,
2634    'unsigned long long' => 1,
2635    'DOMString' => 1,
2636    'CompareHow' => 1,
2637    'SVGAngle' => 1,
2638    'SVGRect' => 1,
2639    'SVGPoint' => 1,
2640    'SVGPreserveAspectRatio' => 1,
2641    'SVGMatrix' => 1,
2642    'SVGTransform' => 1,
2643    'SVGLength' => 1,
2644    'SVGNumber' => 1,
2645    'SVGPaintType' => 1,
2646    'DOMTimeStamp' => 1,
2647    'JSObject' => 1,
2648    'EventTarget' => 1,
2649    'NodeFilter' => 1,
2650    'EventListener' => 1
2651);
2652
2653
2654sub IsWrapperType
2655{
2656    my $type = $codeGenerator->StripModule(shift);
2657    return !($non_wrapper_types{$type});
2658}
2659
2660sub IsDOMNodeType
2661{
2662    my $type = shift;
2663
2664    return 1 if $type eq 'Attr';
2665    return 1 if $type eq 'CDATASection';
2666    return 1 if $type eq 'Comment';
2667    return 1 if $type eq 'Document';
2668    return 1 if $type eq 'DocumentFragment';
2669    return 1 if $type eq 'DocumentType';
2670    return 1 if $type eq 'Element';
2671    return 1 if $type eq 'EntityReference';
2672    return 1 if $type eq 'HTMLCanvasElement';
2673    return 1 if $type eq 'HTMLDocument';
2674    return 1 if $type eq 'HTMLElement';
2675    return 1 if $type eq 'HTMLFormElement';
2676    return 1 if $type eq 'HTMLTableCaptionElement';
2677    return 1 if $type eq 'HTMLTableSectionElement';
2678    return 1 if $type eq 'Node';
2679    return 1 if $type eq 'ProcessingInstruction';
2680    return 1 if $type eq 'SVGElement';
2681    return 1 if $type eq 'SVGDocument';
2682    return 1 if $type eq 'SVGSVGElement';
2683    return 1 if $type eq 'SVGUseElement';
2684    return 1 if $type eq 'Text';
2685
2686    return 0;
2687}
2688
2689
2690sub ReturnNativeToJSValue
2691{
2692    my $signature = shift;
2693    my $value = shift;
2694    my $indent = shift;
2695    my $type = GetTypeFromSignature($signature);
2696
2697    return "return v8::Date::New(static_cast<double>($value))" if $type eq "DOMTimeStamp";
2698    return "return v8Boolean($value)" if $type eq "boolean";
2699    return "return v8::Handle<v8::Value>()" if $type eq "void";     # equivalent to v8::Undefined()
2700
2701    # For all the types where we use 'int' as the representation type,
2702    # we use Integer::New which has a fast Smi conversion check.
2703    my $nativeType = GetNativeType($type);
2704    return "return v8::Integer::New($value)" if $nativeType eq "int";
2705    return "return v8::Integer::NewFromUnsigned($value)" if $nativeType eq "unsigned";
2706
2707    return "return v8DateOrNull($value);" if $type eq "Date";
2708    return "return v8::Number::New($value)" if $codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType";
2709
2710    if ($codeGenerator->IsStringType($type)) {
2711        my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"};
2712        if (defined $conv) {
2713            return "return v8StringOrNull($value)" if $conv eq "Null";
2714            return "return v8StringOrUndefined($value)" if $conv eq "Undefined";
2715            return "return v8StringOrFalse($value)" if $conv eq "False";
2716
2717            die "Unknown value for ConvertNullStringTo extended attribute";
2718        }
2719        return "return v8String($value)";
2720    }
2721
2722    AddIncludesForType($type);
2723
2724    # special case for non-DOM node interfaces
2725    if (IsDOMNodeType($type)) {
2726        return "return toV8(${value}" . ($signature->extendedAttributes->{"ReturnsNew"} ? ", true)" : ")");
2727    }
2728
2729    if ($type eq "EventTarget") {
2730        return "return V8DOMWrapper::convertEventTargetToV8Object($value)";
2731    }
2732
2733    if ($type eq "EventListener") {
2734        $implIncludes{"V8AbstractEventListener.h"} = 1;
2735        return "return ${value} ? v8::Handle<v8::Value>(static_cast<V8AbstractEventListener*>(${value})->getListenerObject(imp->scriptExecutionContext())) : v8::Handle<v8::Value>(v8::Null())";
2736    }
2737
2738    if ($type eq "SerializedScriptValue") {
2739        $implIncludes{"$type.h"} = 1;
2740        return "return $value->deserialize()";
2741    }
2742
2743    $implIncludes{"wtf/RefCounted.h"} = 1;
2744    $implIncludes{"wtf/RefPtr.h"} = 1;
2745    $implIncludes{"wtf/GetPtr.h"} = 1;
2746
2747    if (IsPodType($type)) {
2748        $value = GenerateSVGStaticPodTypeWrapper($type, $value) . ".get()";
2749    }
2750
2751    return "return toV8($value)";
2752}
2753
2754sub GenerateSVGStaticPodTypeWrapper {
2755    my $type = shift;
2756    my $value = shift;
2757
2758    $implIncludes{"V8$type.h"}=1;
2759    $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
2760
2761    my $nativeType = GetNativeType($type);
2762    return "V8SVGStaticPODTypeWrapper<$nativeType>::create($value)";
2763}
2764
2765# Internal helper
2766sub WriteData
2767{
2768    if (defined($IMPL)) {
2769        # Write content to file.
2770        print $IMPL @implContentHeader;
2771
2772        print $IMPL @implFixedHeader;
2773
2774        foreach my $implInclude (sort keys(%implIncludes)) {
2775            my $checkType = $implInclude;
2776            $checkType =~ s/\.h//;
2777
2778            print $IMPL "#include \"$implInclude\"\n" unless $codeGenerator->IsSVGAnimatedType($checkType);
2779        }
2780
2781        print $IMPL "\n";
2782        print $IMPL @implContentDecls;
2783        print $IMPL @implContent;
2784        close($IMPL);
2785        undef($IMPL);
2786
2787        %implIncludes = ();
2788        @implFixedHeader = ();
2789        @implHeaderContent = ();
2790        @implContentDecls = ();
2791        @implContent = ();
2792    }
2793
2794    if (defined($HEADER)) {
2795        # Write content to file.
2796        print $HEADER @headerContent;
2797        close($HEADER);
2798        undef($HEADER);
2799
2800        @headerContent = ();
2801    }
2802}
2803
2804sub IsSVGTypeNeedingContextParameter
2805{
2806    my $implClassName = shift;
2807
2808    if ($implClassName =~ /SVG/ and not $implClassName =~ /Element/) {
2809        return 1 unless $implClassName =~ /SVGPaint/ or $implClassName =~ /SVGColor/ or $implClassName =~ /SVGDocument/;
2810    }
2811
2812    return 0;
2813}
2814
2815sub GenerateSVGContextAssignment
2816{
2817    my $srcType = shift;
2818    my $value = shift;
2819    my $indent = shift;
2820
2821    $result = GenerateSVGContextRetrieval($srcType, $indent);
2822    $result .= $indent . "V8Proxy::setSVGContext($value, context);\n";
2823
2824    return $result;
2825}
2826
2827sub GenerateSVGContextRetrieval
2828{
2829    my $srcType = shift;
2830    my $indent = shift;
2831
2832    my $srcIsPodType = IsPodType($srcType);
2833
2834    my $srcObject = "imp";
2835    if ($srcIsPodType) {
2836        $srcObject = "imp_wrapper";
2837    }
2838
2839    my $contextDecl;
2840
2841    if (IsSVGTypeNeedingContextParameter($srcType)) {
2842        $contextDecl = "V8Proxy::svgContext($srcObject)";
2843    } else {
2844        $contextDecl = $srcObject;
2845    }
2846
2847    return $indent . "SVGElement* context = $contextDecl;\n";
2848}
2849
2850sub IsSVGListMutator
2851{
2852    my $functionName = shift;
2853
2854    return 1 if $functionName eq "clear";
2855    return 1 if $functionName eq "initialize";
2856    return 1 if $functionName eq "insertItemBefore";
2857    return 1 if $functionName eq "replaceItem";
2858    return 1 if $functionName eq "removeItem";
2859    return 1 if $functionName eq "appendItem";
2860
2861    return 0;
2862}
2863
2864sub IsSVGListMethod
2865{
2866    my $functionName = shift;
2867
2868    return 1 if $functionName eq "getFirst";
2869    return 1 if $functionName eq "getLast";
2870    return 1 if $functionName eq "getItem";
2871
2872    return IsSVGListMutator($functionName);
2873}
2874
2875sub IsSVGListTypeNeedingSpecialHandling
2876{
2877    my $className = shift;
2878
2879    return 1 if $className eq "SVGPointList";
2880    return 1 if $className eq "SVGTransformList";
2881
2882    return 0;
2883}
2884
2885sub DebugPrint
2886{
2887    my $output = shift;
2888
2889    print $output;
2890    print "\n";
2891}
2892