1#
2# Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
3# Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
4# Copyright (C) 2006, 2007 Samuel Weinig <sam@webkit.org>
5# Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
6# Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
7# Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
8# Copyright (C) 2010 Google Inc.
9# Copyright (C) Research In Motion Limited 2010. All rights reserved.
10#
11# This library is free software; you can redistribute it and/or
12# modify it under the terms of the GNU Library General Public
13# License as published by the Free Software Foundation; either
14# version 2 of the License, or (at your option) any later version.
15#
16# This library is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19# Library General Public License for more details.
20#
21# You should have received a copy of the GNU Library General Public License
22# along with this library; see the file COPYING.LIB.  If not, write to
23# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24# Boston, MA 02110-1301, USA.
25#
26
27package CodeGeneratorObjC;
28
29# Global Variables
30my $module = "";
31my $outputDir = "";
32my $writeDependencies = 0;
33my %publicInterfaces = ();
34my $newPublicClass = 0;
35my $interfaceAvailabilityVersion = "";
36my $isProtocol = 0;
37my $noImpl = 0;
38
39my @headerContentHeader = ();
40my @headerContent = ();
41my %headerForwardDeclarations = ();
42my %headerForwardDeclarationsForProtocols = ();
43
44my @privateHeaderContentHeader = ();
45my @privateHeaderContent = ();
46my %privateHeaderForwardDeclarations = ();
47my %privateHeaderForwardDeclarationsForProtocols = ();
48
49my @internalHeaderContent = ();
50
51my @implContentHeader = ();
52my @implContent = ();
53my %implIncludes = ();
54my @depsContent = ();
55
56# Hashes
57my %protocolTypeHash = ("XPathNSResolver" => 1, "EventListener" => 1, "EventTarget" => 1, "NodeFilter" => 1,
58                        "SVGLocatable" => 1, "SVGTransformable" => 1, "SVGStylable" => 1, "SVGFilterPrimitiveStandardAttributes" => 1,
59                        "SVGTests" => 1, "SVGLangSpace" => 1, "SVGExternalResourcesRequired" => 1, "SVGURIReference" => 1,
60                        "SVGZoomAndPan" => 1, "SVGFitToViewBox" => 1, "SVGAnimatedPathData" => 1, "ElementTimeControl" => 1);
61my %nativeObjCTypeHash = ("URL" => 1, "Color" => 1);
62
63# FIXME: this should be replaced with a function that recurses up the tree
64# to find the actual base type.
65my %baseTypeHash = ("Object" => 1, "Node" => 1, "NodeList" => 1, "NamedNodeMap" => 1, "DOMImplementation" => 1,
66                    "Event" => 1, "CSSRule" => 1, "CSSValue" => 1, "StyleSheet" => 1, "MediaList" => 1,
67                    "Counter" => 1, "Rect" => 1, "RGBColor" => 1, "XPathExpression" => 1, "XPathResult" => 1,
68                    "NodeIterator" => 1, "TreeWalker" => 1, "AbstractView" => 1, "Blob" => 1,
69                    "SVGAngle" => 1, "SVGAnimatedAngle" => 1, "SVGAnimatedBoolean" => 1, "SVGAnimatedEnumeration" => 1,
70                    "SVGAnimatedInteger" => 1, "SVGAnimatedLength" => 1, "SVGAnimatedLengthList" => 1,
71                    "SVGAnimatedNumber" => 1, "SVGAnimatedNumberList" => 1,
72                    "SVGAnimatedPreserveAspectRatio" => 1, "SVGAnimatedRect" => 1, "SVGAnimatedString" => 1,
73                    "SVGAnimatedTransformList" => 1, "SVGLength" => 1, "SVGLengthList" => 1, "SVGMatrix" => 1,
74                    "SVGNumber" => 1, "SVGNumberList" => 1, "SVGPathSeg" => 1, "SVGPathSegList" => 1, "SVGPoint" => 1,
75                    "SVGPointList" => 1, "SVGPreserveAspectRatio" => 1, "SVGRect" => 1, "SVGRenderingIntent" => 1,
76                    "SVGStringList" => 1, "SVGTransform" => 1, "SVGTransformList" => 1, "SVGUnitTypes" => 1);
77
78# Constants
79my $buildingForTigerOrEarlier = 1 if $ENV{"MACOSX_DEPLOYMENT_TARGET"} and $ENV{"MACOSX_DEPLOYMENT_TARGET"} <= 10.4;
80my $buildingForLeopardOrLater = 1 if $ENV{"MACOSX_DEPLOYMENT_TARGET"} and $ENV{"MACOSX_DEPLOYMENT_TARGET"} >= 10.5;
81my $exceptionInit = "WebCore::ExceptionCode ec = 0;";
82my $jsContextSetter = "WebCore::JSMainThreadNullState state;";
83my $exceptionRaiseOnError = "WebCore::raiseOnDOMError(ec);";
84my $assertMainThread = "{ DOM_ASSERT_MAIN_THREAD(); WebCoreThreadViolationCheckRoundOne(); }";
85
86my %conflictMethod = (
87    # FIXME: Add C language keywords?
88    # FIXME: Add other predefined types like "id"?
89
90    "callWebScriptMethod:withArguments:" => "WebScriptObject",
91    "evaluateWebScript:" => "WebScriptObject",
92    "removeWebScriptKey:" => "WebScriptObject",
93    "setException:" => "WebScriptObject",
94    "setWebScriptValueAtIndex:value:" => "WebScriptObject",
95    "stringRepresentation" => "WebScriptObject",
96    "webScriptValueAtIndex:" => "WebScriptObject",
97
98    "autorelease" => "NSObject",
99    "awakeAfterUsingCoder:" => "NSObject",
100    "class" => "NSObject",
101    "classForCoder" => "NSObject",
102    "conformsToProtocol:" => "NSObject",
103    "copy" => "NSObject",
104    "copyWithZone:" => "NSObject",
105    "dealloc" => "NSObject",
106    "description" => "NSObject",
107    "doesNotRecognizeSelector:" => "NSObject",
108    "encodeWithCoder:" => "NSObject",
109    "finalize" => "NSObject",
110    "forwardInvocation:" => "NSObject",
111    "hash" => "NSObject",
112    "init" => "NSObject",
113    "initWithCoder:" => "NSObject",
114    "isEqual:" => "NSObject",
115    "isKindOfClass:" => "NSObject",
116    "isMemberOfClass:" => "NSObject",
117    "isProxy" => "NSObject",
118    "methodForSelector:" => "NSObject",
119    "methodSignatureForSelector:" => "NSObject",
120    "mutableCopy" => "NSObject",
121    "mutableCopyWithZone:" => "NSObject",
122    "performSelector:" => "NSObject",
123    "release" => "NSObject",
124    "replacementObjectForCoder:" => "NSObject",
125    "respondsToSelector:" => "NSObject",
126    "retain" => "NSObject",
127    "retainCount" => "NSObject",
128    "self" => "NSObject",
129    "superclass" => "NSObject",
130    "zone" => "NSObject",
131);
132
133my $fatalError = 0;
134
135# Default License Templates
136my $headerLicenseTemplate = << "EOF";
137/*
138 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
139 * Copyright (C) 2006 Samuel Weinig <sam.weinig\@gmail.com>
140 *
141 * Redistribution and use in source and binary forms, with or without
142 * modification, are permitted provided that the following conditions
143 * are met:
144 * 1. Redistributions of source code must retain the above copyright
145 *    notice, this list of conditions and the following disclaimer.
146 * 2. Redistributions in binary form must reproduce the above copyright
147 *    notice, this list of conditions and the following disclaimer in the
148 *    documentation and/or other materials provided with the distribution.
149 *
150 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
151 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
152 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
153 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
154 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
155 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
156 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
157 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
158 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
159 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
160 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
161 */
162EOF
163
164my $implementationLicenseTemplate = << "EOF";
165/*
166 * This file is part of the WebKit open source project.
167 * This file has been generated by generate-bindings.pl. DO NOT MODIFY!
168 *
169 * Redistribution and use in source and binary forms, with or without
170 * modification, are permitted provided that the following conditions
171 * are met:
172 * 1. Redistributions of source code must retain the above copyright
173 *    notice, this list of conditions and the following disclaimer.
174 * 2. Redistributions in binary form must reproduce the above copyright
175 *    notice, this list of conditions and the following disclaimer in the
176 *    documentation and/or other materials provided with the distribution.
177 *
178 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
179 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
180 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
181 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
182 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
183 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
184 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
185 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
186 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
187 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
188 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
189 */
190EOF
191
192# Default constructor
193sub new
194{
195    my $object = shift;
196    my $reference = { };
197
198    $codeGenerator = shift;
199    $outputDir = shift;
200    shift; # $outputHeadersDir
201    shift; # $useLayerOnTop
202    shift; # $preprocessor
203    $writeDependencies = shift;
204
205    bless($reference, $object);
206    return $reference;
207}
208
209sub finish
210{
211    my $object = shift;
212}
213
214sub ReadPublicInterfaces
215{
216    my $class = shift;
217    my $superClass = shift;
218    my $defines = shift;
219    my $isProtocol = shift;
220
221    my $found = 0;
222    my $actualSuperClass;
223    %publicInterfaces = ();
224
225    my $fileName = "WebCore/bindings/objc/PublicDOMInterfaces.h";
226    my $gccLocation = "";
227    if ($ENV{CC}) {
228        $gccLocation = $ENV{CC};
229    } elsif (($Config::Config{'osname'}) =~ /solaris/i) {
230        $gccLocation = "/usr/sfw/bin/gcc";
231    } else {
232        $gccLocation = "/usr/bin/gcc";
233    }
234    open FILE, "-|", $gccLocation, "-E", "-P", "-x", "objective-c",
235        (map { "-D$_" } split(/ +/, $defines)), "-DOBJC_CODE_GENERATION", $fileName or die "Could not open $fileName";
236    my @documentContent = <FILE>;
237    close FILE;
238
239    foreach $line (@documentContent) {
240        if (!$isProtocol && $line =~ /^\s*\@interface\s*$class\s*:\s*(\w+)\s*([A-Z0-9_]*)/) {
241            if ($superClass ne $1) {
242                warn "Public API change. Superclass for \"$class\" differs ($1 != $superClass)";
243                $fatalError = 1;
244            }
245
246            $interfaceAvailabilityVersion = $2 if defined $2;
247            $found = 1;
248            next;
249        } elsif ($isProtocol && $line =~ /^\s*\@protocol $class\s*<[^>]+>\s*([A-Z0-9_]*)/) {
250            $interfaceAvailabilityVersion = $1 if defined $1;
251            $found = 1;
252            next;
253        }
254
255        last if $found and $line =~ /^\s?\@end\s?$/;
256
257        if ($found) {
258            # trim whitspace
259            $line =~ s/^\s+//;
260            $line =~ s/\s+$//;
261
262            my $availabilityMacro = "";
263            $line =~ s/\s([A-Z0-9_]+)\s*;$/;/;
264            $availabilityMacro = $1 if defined $1;
265
266            $publicInterfaces{$line} = $availabilityMacro if length $line;
267        }
268    }
269
270    # If this class was not found in PublicDOMInterfaces.h then it should be considered as an entirely new public class.
271    $newPublicClass = !$found;
272    $interfaceAvailabilityVersion = "WEBKIT_VERSION_LATEST" if $newPublicClass;
273}
274
275sub GenerateConditionalString
276{
277    my $node = shift;
278    my $conditional = $node->extendedAttributes->{"Conditional"};
279    if ($conditional) {
280        if ($conditional =~ /&/) {
281            return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
282        } elsif ($conditional =~ /\|/) {
283            return "ENABLE(" . join(") || ENABLE(", split(/\|/, $conditional)) . ")";
284        } else {
285            return "ENABLE(" . $conditional . ")";
286        }
287    } else {
288        return "";
289    }
290}
291
292# Params: 'domClass' struct
293sub GenerateInterface
294{
295    my $object = shift;
296    my $dataNode = shift;
297    my $defines = shift;
298
299    $fatalError = 0;
300
301    my $name = $dataNode->name;
302    my $className = GetClassName($name);
303    my $parentClassName = "DOM" . GetParentImplClassName($dataNode);
304    $isProtocol = $dataNode->extendedAttributes->{ObjCProtocol};
305    $noImpl = $dataNode->extendedAttributes->{ObjCCustomImplementation} || $isProtocol;
306
307    ReadPublicInterfaces($className, $parentClassName, $defines, $isProtocol);
308
309    # Start actual generation..
310    $object->GenerateHeader($dataNode);
311    $object->GenerateImplementation($dataNode) unless $noImpl;
312
313    # Write changes.
314    $object->WriteData("DOM" . $name);
315
316    # Check for missing public API
317    if (keys %publicInterfaces > 0) {
318        my $missing = join("\n", keys %publicInterfaces);
319        warn "Public API change. There are missing public properties and/or methods from the \"$className\" class.\n$missing\n";
320        $fatalError = 1;
321    }
322
323    die if $fatalError;
324}
325
326# Params: 'idlDocument' struct
327sub GenerateModule
328{
329    my $object = shift;
330    my $dataNode = shift;
331
332    $module = $dataNode->module;
333}
334
335sub GetClassName
336{
337    my $name = $codeGenerator->StripModule(shift);
338
339    # special cases
340    return "NSString" if $codeGenerator->IsStringType($name) or $name eq "SerializedScriptValue";
341    return "NS$name" if IsNativeObjCType($name);
342    return "BOOL" if $name eq "boolean";
343    return "unsigned" if $name eq "unsigned long";
344    return "int" if $name eq "long";
345    return "NSTimeInterval" if $name eq "Date";
346    return "DOMAbstractView" if $name eq "DOMWindow";
347    return $name if $codeGenerator->IsPrimitiveType($name) or $name eq "DOMImplementation" or $name eq "DOMTimeStamp";
348
349    # Default, assume Objective-C type has the same type name as
350    # idl type prefixed with "DOM".
351    return "DOM$name";
352}
353
354sub GetClassHeaderName
355{
356    my $name = shift;
357
358    return "DOMDOMImplementation" if $name eq "DOMImplementation";
359    return $name;
360}
361
362sub GetImplClassName
363{
364    my $name = $codeGenerator->StripModule(shift);
365
366    return "DOMImplementationFront" if $name eq "DOMImplementation";
367    return "DOMWindow" if $name eq "AbstractView";
368    return $name;
369}
370
371sub GetParentImplClassName
372{
373    my $dataNode = shift;
374
375    return "Object" if @{$dataNode->parents} eq 0;
376
377    my $parent = $codeGenerator->StripModule($dataNode->parents(0));
378
379    # special cases
380    return "Object" if $parent eq "HTMLCollection";
381
382    return $parent;
383}
384
385sub GetParentAndProtocols
386{
387    my $dataNode = shift;
388    my $numParents = @{$dataNode->parents};
389
390    my $parent = "";
391    my @protocols = ();
392    if ($numParents eq 0) {
393        if ($isProtocol) {
394            push(@protocols, "NSObject");
395            push(@protocols, "NSCopying") if $dataNode->name eq "EventTarget";
396        } else {
397            $parent = "DOMObject";
398        }
399    } elsif ($numParents eq 1) {
400        my $parentName = $codeGenerator->StripModule($dataNode->parents(0));
401        if ($isProtocol) {
402            die "Parents of protocols must also be protocols." unless IsProtocolType($parentName);
403            push(@protocols, "DOM" . $parentName);
404        } else {
405            if (IsProtocolType($parentName)) {
406                push(@protocols, "DOM" . $parentName);
407            } elsif ($parentName eq "HTMLCollection") {
408                $parent = "DOMObject";
409            } else {
410                $parent = "DOM" . $parentName;
411            }
412        }
413    } else {
414        my @parents = @{$dataNode->parents};
415        my $firstParent = $codeGenerator->StripModule(shift(@parents));
416        if (IsProtocolType($firstParent)) {
417            push(@protocols, "DOM" . $firstParent);
418            if (!$isProtocol) {
419                $parent = "DOMObject";
420            }
421        } else {
422            $parent = "DOM" . $firstParent;
423        }
424
425        foreach my $parentName (@parents) {
426            $parentName = $codeGenerator->StripModule($parentName);
427            die "Everything past the first class should be a protocol!" unless IsProtocolType($parentName);
428
429            push(@protocols, "DOM" . $parentName);
430        }
431    }
432
433    return ($parent, @protocols);
434}
435
436sub GetBaseClass
437{
438    $parent = shift;
439
440    return $parent if $parent eq "Object" or IsBaseType($parent);
441    return "Event" if $parent eq "UIEvent";
442    return "CSSValue" if $parent eq "SVGColor" or $parent eq "CSSValueList";
443    return "Node";
444}
445
446sub IsBaseType
447{
448    my $type = shift;
449
450    return 1 if $baseTypeHash{$type};
451    return 0;
452}
453
454sub IsProtocolType
455{
456    my $type = shift;
457
458    return 1 if $protocolTypeHash{$type};
459    return 0;
460}
461
462sub IsNativeObjCType
463{
464    my $type = shift;
465
466    return 1 if $nativeObjCTypeHash{$type};
467    return 0;
468}
469
470sub GetObjCType
471{
472    my $type = shift;
473    my $name = GetClassName($type);
474
475    return "id <$name>" if IsProtocolType($type);
476    return $name if $codeGenerator->IsPrimitiveType($type) or $type eq "DOMTimeStamp";
477    return "unsigned short" if $type eq "CompareHow";
478    return "$name *";
479}
480
481sub GetPropertyAttributes
482{
483    my $type = $codeGenerator->StripModule(shift);
484    my $readOnly = shift;
485
486    my @attributes = ();
487
488    push(@attributes, "readonly") if $readOnly;
489
490    # FIXME: <rdar://problem/5049934> Consider using 'nonatomic' on the DOM @property declarations.
491    if ($codeGenerator->IsStringType($type) || IsNativeObjCType($type)) {
492        push(@attributes, "copy");
493    } elsif ($codeGenerator->IsSVGAnimatedType($type)) {
494        push(@attributes, "retain");
495    } elsif (!$codeGenerator->IsStringType($type) && !$codeGenerator->IsPrimitiveType($type) && $type ne "DOMTimeStamp" && $type ne "CompareHow") {
496        push(@attributes, "retain");
497    }
498
499    return "" unless @attributes > 0;
500    return "(" . join(", ", @attributes) . ")";
501}
502
503sub ConversionNeeded
504{
505    my $type = $codeGenerator->StripModule(shift);
506
507    return !$codeGenerator->IsNonPointerType($type) && !$codeGenerator->IsStringType($type) && !IsNativeObjCType($type);
508}
509
510sub GetObjCTypeGetter
511{
512    my $argName = shift;
513    my $type = $codeGenerator->StripModule(shift);
514
515    return $argName if $codeGenerator->IsPrimitiveType($type) or $codeGenerator->IsStringType($type) or IsNativeObjCType($type);
516    return $argName . "Node" if $type eq "EventTarget";
517    return "static_cast<WebCore::Range::CompareHow>($argName)" if $type eq "CompareHow";
518    return "WTF::getPtr(nativeEventListener)" if $type eq "EventListener";
519    return "WTF::getPtr(nativeNodeFilter)" if $type eq "NodeFilter";
520    return "WTF::getPtr(nativeResolver)" if $type eq "XPathNSResolver";
521
522    if ($type eq "SerializedScriptValue") {
523        $implIncludes{"SerializedScriptValue.h"} = 1;
524        return "WebCore::SerializedScriptValue::create(WTF::String($argName))";
525    }
526    return "core($argName)";
527}
528
529sub AddForwardDeclarationsForType
530{
531    my $type = $codeGenerator->StripModule(shift);
532    my $public = shift;
533
534    return if $codeGenerator->IsNonPointerType($type) ;
535
536    my $class = GetClassName($type);
537
538    if (IsProtocolType($type)) {
539        $headerForwardDeclarationsForProtocols{$class} = 1 if $public;
540        $privateHeaderForwardDeclarationsForProtocols{$class} = 1 if !$public and !$headerForwardDeclarationsForProtocols{$class};
541        return;
542    }
543
544    $headerForwardDeclarations{$class} = 1 if $public;
545
546    # Private headers include the public header, so only add a forward declaration to the private header
547    # if the public header does not already have the same forward declaration.
548    $privateHeaderForwardDeclarations{$class} = 1 if !$public and !$headerForwardDeclarations{$class};
549}
550
551sub AddIncludesForType
552{
553    my $type = $codeGenerator->StripModule(shift);
554
555    return if $codeGenerator->IsNonPointerType($type);
556
557    if (IsNativeObjCType($type)) {
558        if ($type eq "Color") {
559            $implIncludes{"ColorMac.h"} = 1;
560        }
561        return;
562    }
563
564    if ($codeGenerator->IsStringType($type)) {
565        $implIncludes{"KURL.h"} = 1;
566        return;
567    }
568
569    if ($type eq "DOMWindow") {
570        $implIncludes{"DOMAbstractViewInternal.h"} = 1;
571        $implIncludes{"DOMWindow.h"} = 1;
572        return;
573    }
574
575    if ($type eq "DOMImplementation") {
576        $implIncludes{"DOMDOMImplementationInternal.h"} = 1;
577        $implIncludes{"DOMImplementationFront.h"} = 1;
578        return;
579    }
580
581    if ($type eq "EventTarget") {
582        $implIncludes{"Node.h"} = 1;
583        $implIncludes{"DOMEventTarget.h"} = 1;
584        return;
585    }
586
587    if ($codeGenerator->IsSVGAnimatedType($type)) {
588        $implIncludes{"${type}.h"} = 1;
589        $implIncludes{"DOM${type}Internal.h"} = 1;
590        return;
591    }
592
593    if ($type =~ /(\w+)(Abs|Rel)$/) {
594        $implIncludes{"$1.h"} = 1;
595        $implIncludes{"DOM${type}Internal.h"} = 1;
596        return;
597    }
598
599    if ($type eq "NodeFilter") {
600        $implIncludes{"NodeFilter.h"} = 1;
601        $implIncludes{"ObjCNodeFilterCondition.h"} = 1;
602        return;
603    }
604
605    if ($type eq "EventListener") {
606        $implIncludes{"EventListener.h"} = 1;
607        $implIncludes{"ObjCEventListener.h"} = 1;
608        return;
609    }
610
611    if ($type eq "XPathNSResolver") {
612        $implIncludes{"DOMCustomXPathNSResolver.h"} = 1;
613        $implIncludes{"XPathNSResolver.h"} = 1;
614        return;
615    }
616
617    if ($type eq "SerializedScriptValue") {
618        $implIncludes{"SerializedScriptValue.h"} = 1;
619        return;
620    }
621
622    # FIXME: won't compile without these
623    $implIncludes{"CSSMutableStyleDeclaration.h"} = 1 if $type eq "CSSStyleDeclaration";
624    $implIncludes{"NameNodeList.h"} = 1 if $type eq "NodeList";
625
626    # Default, include the same named file (the implementation) and the same name prefixed with "DOM".
627    $implIncludes{"$type.h"} = 1 if not $codeGenerator->AvoidInclusionOfType($type);
628    $implIncludes{"DOM${type}Internal.h"} = 1;
629}
630
631sub GetSVGTypeWithNamespace
632{
633    my $type = shift;
634    my $typeWithNamespace = "WebCore::" . $codeGenerator->GetSVGTypeNeedingTearOff($type);
635
636    # Special case for DOMSVGNumber
637    $typeWithNamespace =~ s/</\<WebCore::/ unless $type eq "SVGNumber";
638    return $typeWithNamespace;
639}
640
641sub GetSVGPropertyTypes
642{
643    my $implType = shift;
644
645    my $svgPropertyType;
646    my $svgListPropertyType;
647    my $svgNativeType;
648
649    return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $implType =~ /SVG/;
650
651    $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implType);
652    return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $svgNativeType;
653
654    # Append space to avoid compilation errors when using  PassRefPtr<$svgNativeType>
655    $svgNativeType = "WebCore::$svgNativeType ";
656    $svgNativeType =~ s/</\<WebCore::/ if not $svgNativeType =~ /float/;
657
658    my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implType);
659    if ($svgNativeType =~ /SVGPropertyTearOff/) {
660        if ($svgWrappedNativeType eq "float") {
661            # Special case for DOMSVGNumber
662            $svgPropertyType = $svgWrappedNativeType;
663        } else {
664            $svgPropertyType = "WebCore::$svgWrappedNativeType";
665            $svgPropertyType =~ s/</\<WebCore::/;
666        }
667    } elsif ($svgNativeType =~ /SVGListPropertyTearOff/ or $svgNativeType =~ /SVGStaticListPropertyTearOff/) {
668        $svgListPropertyType = "WebCore::$svgWrappedNativeType";
669        $svgListPropertyType =~ s/</\<WebCore::/;
670    } elsif ($svgNativeType =~ /SVGTransformListPropertyTearOff/) {
671        $svgListPropertyType = "WebCore::$svgWrappedNativeType";
672        $svgListPropertyType =~ s/</\<WebCore::/;
673    } elsif ($svgNativeType =~ /SVGPathSegListPropertyTearOff/) {
674        $svgListPropertyType = "WebCore::$svgWrappedNativeType";
675        $svgListPropertyType =~ s/</\<WebCore::/;
676    }
677
678    return ($svgPropertyType, $svgListPropertyType, $svgNativeType);
679}
680
681sub GenerateHeader
682{
683    my $object = shift;
684    my $dataNode = shift;
685
686    my $interfaceName = $dataNode->name;
687    my $className = GetClassName($interfaceName);
688
689    my $parentName = "";
690    my @protocolsToImplement = ();
691    ($parentName, @protocolsToImplement) = GetParentAndProtocols($dataNode);
692
693    my $numConstants = @{$dataNode->constants};
694    my $numAttributes = @{$dataNode->attributes};
695    my $numFunctions = @{$dataNode->functions};
696
697    # - Add default header template
698    @headerContentHeader = split("\r", $headerLicenseTemplate);
699    push(@headerContentHeader, "\n");
700
701    # - INCLUDES -
702    my $includedWebKitAvailabilityHeader = 0;
703    unless ($isProtocol) {
704        my $parentHeaderName = GetClassHeaderName($parentName);
705        push(@headerContentHeader, "#import <WebCore/$parentHeaderName.h>\n");
706        $includedWebKitAvailabilityHeader = 1;
707    }
708
709    foreach my $parentProtocol (@protocolsToImplement) {
710        next if $parentProtocol =~ /^NS/;
711        $parentProtocol = GetClassHeaderName($parentProtocol);
712        push(@headerContentHeader, "#import <WebCore/$parentProtocol.h>\n");
713        $includedWebKitAvailabilityHeader = 1;
714    }
715
716    # Special case needed for legacy support of DOMRange
717    if ($interfaceName eq "Range") {
718        push(@headerContentHeader, "#import <WebCore/DOMCore.h>\n");
719        push(@headerContentHeader, "#import <WebCore/DOMDocument.h>\n");
720        push(@headerContentHeader, "#import <WebCore/DOMRangeException.h>\n");
721        $includedWebKitAvailabilityHeader = 1;
722    }
723
724    push(@headerContentHeader, "#import <JavaScriptCore/WebKitAvailability.h>\n") unless $includedWebKitAvailabilityHeader;
725
726    my $interfaceAvailabilityVersionCheck = "#if WEBKIT_VERSION_MAX_ALLOWED >= $interfaceAvailabilityVersion\n\n";
727
728    push(@headerContentHeader, "\n");
729    push(@headerContentHeader, $interfaceAvailabilityVersionCheck) if length $interfaceAvailabilityVersion;
730
731    # - Add constants.
732    if ($numConstants > 0) {
733        my @headerConstants = ();
734
735        # FIXME: we need a way to include multiple enums.
736        foreach my $constant (@{$dataNode->constants}) {
737            my $constantName = $constant->name;
738            my $constantValue = $constant->value;
739
740            my $output = "    DOM_" . $constantName . " = " . $constantValue;
741            push(@headerConstants, $output);
742        }
743
744        my $combinedConstants = join(",\n", @headerConstants);
745
746        # FIXME: the formatting of the enums should line up the equal signs.
747        # FIXME: enums are unconditionally placed in the public header.
748        push(@headerContent, "enum {\n");
749        push(@headerContent, $combinedConstants);
750        push(@headerContent, "\n};\n\n");
751    }
752
753    # - Begin @interface or @protocol
754    my $interfaceDeclaration = ($isProtocol ? "\@protocol $className" : "\@interface $className : $parentName");
755    $interfaceDeclaration .= " <" . join(", ", @protocolsToImplement) . ">" if @protocolsToImplement > 0;
756    $interfaceDeclaration .= "\n";
757
758    push(@headerContent, $interfaceDeclaration);
759
760    my @headerAttributes = ();
761    my @privateHeaderAttributes = ();
762
763    # - Add attribute getters/setters.
764    if ($numAttributes > 0) {
765        foreach my $attribute (@{$dataNode->attributes}) {
766            my $attributeName = $attribute->signature->name;
767
768            if ($attributeName eq "id" or $attributeName eq "hash" or $attributeName eq "description") {
769                # Special case some attributes (like id and hash) to have a "Name" suffix to avoid ObjC naming conflicts.
770                $attributeName .= "Name";
771            } elsif ($attributeName eq "frame") {
772                # Special case attribute frame to be frameBorders.
773                $attributeName .= "Borders";
774            }
775
776            my $attributeType = GetObjCType($attribute->signature->type);
777            my $attributeIsReadonly = ($attribute->type =~ /^readonly/);
778
779            my $property = "\@property" . GetPropertyAttributes($attribute->signature->type, $attributeIsReadonly);
780            # Some SVGFE*Element.idl use 'operator' as attribute name, rewrite as '_operator' to avoid clashes with C/C++
781            $attributeName =~ s/operator/_operator/ if ($attributeName =~ /operator/);
782            $property .= " " . $attributeType . ($attributeType =~ /\*$/ ? "" : " ") . $attributeName;
783
784            my $publicInterfaceKey = $property . ";";
785
786            my $availabilityMacro = "";
787            if (defined $publicInterfaces{$publicInterfaceKey} and length $publicInterfaces{$publicInterfaceKey}) {
788                $availabilityMacro = $publicInterfaces{$publicInterfaceKey};
789            }
790
791            $availabilityMacro = "WEBKIT_OBJC_METHOD_ANNOTATION($availabilityMacro)" if length $availabilityMacro and $buildingForTigerOrEarlier;
792
793            my $declarationSuffix = ";\n";
794            $declarationSuffix = " $availabilityMacro;\n" if length $availabilityMacro;
795
796            my $public = (defined $publicInterfaces{$publicInterfaceKey} or $newPublicClass);
797            delete $publicInterfaces{$publicInterfaceKey};
798
799            AddForwardDeclarationsForType($attribute->signature->type, $public);
800
801            my $setterName = "set" . ucfirst($attributeName) . ":";
802
803            my $conflict = $conflictMethod{$attributeName};
804            if ($conflict) {
805                warn "$className conflicts with $conflict method $attributeName\n";
806                $fatalError = 1;
807            }
808
809            $conflict = $conflictMethod{$setterName};
810            if ($conflict) {
811                warn "$className conflicts with $conflict method $setterName\n";
812                $fatalError = 1;
813            }
814
815            if ($buildingForLeopardOrLater) {
816                $property .= $declarationSuffix;
817                push(@headerAttributes, $property) if $public;
818                push(@privateHeaderAttributes, $property) unless $public;
819            } else {
820                my $attributeConditionalString = GenerateConditionalString($attribute->signature);
821                if ($attributeConditionalString) {
822                    push(@headerAttributes, "#if ${attributeConditionalString}\n") if $public;
823                    push(@privateHeaderAttributes, "#if ${attributeConditionalString}\n") unless $public;
824                }
825
826                # - GETTER
827                my $getter = "- (" . $attributeType . ")" . $attributeName . $declarationSuffix;
828                push(@headerAttributes, $getter) if $public;
829                push(@privateHeaderAttributes, $getter) unless $public;
830
831                # - SETTER
832                if (!$attributeIsReadonly) {
833                    my $setter = "- (void)$setterName(" . $attributeType . ")new" . ucfirst($attributeName) . $declarationSuffix;
834                    push(@headerAttributes, $setter) if $public;
835                    push(@privateHeaderAttributes, $setter) unless $public;
836                }
837
838                if ($attributeConditionalString) {
839                    push(@headerAttributes, "#endif\n") if $public;
840                    push(@privateHeaderAttributes, "#endif\n") unless $public;
841                }
842            }
843        }
844
845        push(@headerContent, @headerAttributes) if @headerAttributes > 0;
846    }
847
848    my @headerFunctions = ();
849    my @privateHeaderFunctions = ();
850    my @deprecatedHeaderFunctions = ();
851
852    # - Add functions.
853    if ($numFunctions > 0) {
854        foreach my $function (@{$dataNode->functions}) {
855            my $functionName = $function->signature->name;
856
857            my $returnType = GetObjCType($function->signature->type);
858            my $needsDeprecatedVersion = (@{$function->parameters} > 1 and $function->signature->extendedAttributes->{"OldStyleObjC"});
859            my $numberOfParameters = @{$function->parameters};
860            my %typesToForwardDeclare = ($function->signature->type => 1);
861
862            my $parameterIndex = 0;
863            my $functionSig = "- ($returnType)$functionName";
864            my $methodName = $functionName;
865            foreach my $param (@{$function->parameters}) {
866                my $paramName = $param->name;
867                my $paramType = GetObjCType($param->type);
868
869                $typesToForwardDeclare{$param->type} = 1;
870
871                if ($parameterIndex >= 1) {
872                    my $paramPrefix = $param->extendedAttributes->{"ObjCPrefix"};
873                    $paramPrefix = $paramName unless defined($paramPrefix);
874                    $functionSig .= " $paramPrefix";
875                    $methodName .= $paramPrefix;
876                }
877
878                $functionSig .= ":($paramType)$paramName";
879                $methodName .= ":";
880
881                $parameterIndex++;
882            }
883
884            my $publicInterfaceKey = $functionSig . ";";
885
886            my $conflict = $conflictMethod{$methodName};
887            if ($conflict) {
888                warn "$className conflicts with $conflict method $methodName\n";
889                $fatalError = 1;
890            }
891
892            if ($isProtocol && !$newPublicClass && !defined $publicInterfaces{$publicInterfaceKey}) {
893                warn "Protocol method $publicInterfaceKey is not in PublicDOMInterfaces.h. Protocols require all methods to be public";
894                $fatalError = 1;
895            }
896
897            my $availabilityMacro = "";
898            if (defined $publicInterfaces{$publicInterfaceKey} and length $publicInterfaces{$publicInterfaceKey}) {
899                $availabilityMacro = $publicInterfaces{$publicInterfaceKey};
900            }
901
902            $availabilityMacro = "WEBKIT_OBJC_METHOD_ANNOTATION($availabilityMacro)" if length $availabilityMacro and $buildingForTigerOrEarlier;
903
904            my $functionDeclaration = $functionSig;
905            $functionDeclaration .= " " . $availabilityMacro if length $availabilityMacro;
906            $functionDeclaration .= ";\n";
907
908            my $public = (defined $publicInterfaces{$publicInterfaceKey} or $newPublicClass);
909            delete $publicInterfaces{$publicInterfaceKey};
910
911            foreach my $type (keys %typesToForwardDeclare) {
912                # add any forward declarations to the public header if a deprecated version will be generated
913                AddForwardDeclarationsForType($type, 1) if $needsDeprecatedVersion;
914                AddForwardDeclarationsForType($type, $public) unless $public and $needsDeprecatedVersion;
915            }
916
917            push(@headerFunctions, $functionDeclaration) if $public;
918            push(@privateHeaderFunctions, $functionDeclaration) unless $public;
919
920            # generate the old style method names with un-named parameters, these methods are deprecated
921            if ($needsDeprecatedVersion) {
922                my $deprecatedFunctionSig = $functionSig;
923                $deprecatedFunctionSig =~ s/\s\w+:/ :/g; # remove parameter names
924
925                $publicInterfaceKey = $deprecatedFunctionSig . ";";
926
927                my $availabilityMacro = "AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0";
928                if (defined $publicInterfaces{$publicInterfaceKey} and length $publicInterfaces{$publicInterfaceKey}) {
929                    $availabilityMacro = $publicInterfaces{$publicInterfaceKey};
930                }
931
932                $availabilityMacro = "WEBKIT_OBJC_METHOD_ANNOTATION($availabilityMacro)" if $buildingForTigerOrEarlier;
933
934                $functionDeclaration = "$deprecatedFunctionSig $availabilityMacro;\n";
935
936                push(@deprecatedHeaderFunctions, $functionDeclaration);
937
938                unless (defined $publicInterfaces{$publicInterfaceKey}) {
939                    warn "Deprecated method $publicInterfaceKey is not in PublicDOMInterfaces.h. All deprecated methods need to be public, or should have the OldStyleObjC IDL attribute removed";
940                    $fatalError = 1;
941                }
942
943                delete $publicInterfaces{$publicInterfaceKey};
944            }
945        }
946
947        if (@headerFunctions > 0) {
948            push(@headerContent, "\n") if $buildingForLeopardOrLater and @headerAttributes > 0;
949            push(@headerContent, @headerFunctions);
950        }
951    }
952
953    if (@deprecatedHeaderFunctions > 0 && $isProtocol) {
954        push(@headerContent, @deprecatedHeaderFunctions);
955    }
956
957    # - End @interface or @protocol
958    push(@headerContent, "\@end\n");
959
960    if (@deprecatedHeaderFunctions > 0 && !$isProtocol) {
961        # - Deprecated category @interface
962        push(@headerContent, "\n\@interface $className (" . $className . "Deprecated)\n");
963        push(@headerContent, @deprecatedHeaderFunctions);
964        push(@headerContent, "\@end\n");
965    }
966
967    push(@headerContent, "\n#endif\n") if length $interfaceAvailabilityVersion;
968
969    my %alwaysGenerateForNoSVGBuild = map { $_ => 1 } qw(DOMHTMLEmbedElement DOMHTMLObjectElement);
970
971    if (@privateHeaderAttributes > 0 or @privateHeaderFunctions > 0 or exists $alwaysGenerateForNoSVGBuild{$className}) {
972        # - Private category @interface
973        @privateHeaderContentHeader = split("\r", $headerLicenseTemplate);
974        push(@privateHeaderContentHeader, "\n");
975
976        my $classHeaderName = GetClassHeaderName($className);
977        push(@privateHeaderContentHeader, "#import <WebCore/$classHeaderName.h>\n\n");
978        push(@privateHeaderContentHeader, $interfaceAvailabilityVersionCheck) if length $interfaceAvailabilityVersion;
979
980        @privateHeaderContent = ();
981        push(@privateHeaderContent, "\@interface $className (" . $className . "Private)\n");
982        push(@privateHeaderContent, @privateHeaderAttributes) if @privateHeaderAttributes > 0;
983        push(@privateHeaderContent, "\n") if $buildingForLeopardOrLater and @privateHeaderAttributes > 0 and @privateHeaderFunctions > 0;
984        push(@privateHeaderContent, @privateHeaderFunctions) if @privateHeaderFunctions > 0;
985        push(@privateHeaderContent, "\@end\n");
986
987        push(@privateHeaderContent, "\n#endif\n") if length $interfaceAvailabilityVersion;
988    }
989
990    unless ($isProtocol) {
991        # Generate internal interfaces
992        my $implClassName = GetImplClassName($interfaceName);
993        my $implClassNameWithNamespace = "WebCore::" . $implClassName;
994
995        my $implType = $implClassNameWithNamespace;
996        my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implClassName);
997        $implType = $svgNativeType if $svgNativeType;
998
999        # Generate interface definitions.
1000        @internalHeaderContent = split("\r", $implementationLicenseTemplate);
1001
1002        push(@internalHeaderContent, "\n#import <WebCore/$className.h>\n\n");
1003        push(@internalHeaderContent, "#import <WebCore/SVGAnimatedPropertyTearOff.h>\n\n") if $svgPropertyType;
1004        if ($svgListPropertyType) {
1005            push(@internalHeaderContent, "#import <WebCore/SVGAnimatedListPropertyTearOff.h>\n\n");
1006            push(@internalHeaderContent, "#import <WebCore/SVGTransformListPropertyTearOff.h>\n\n") if $svgListPropertyType =~ /SVGTransformList/;
1007            push(@internalHeaderContent, "#import <WebCore/SVGPathSegListPropertyTearOff.h>\n\n") if $svgListPropertyType =~ /SVGPathSegList/;
1008        }
1009        push(@internalHeaderContent, $interfaceAvailabilityVersionCheck) if length $interfaceAvailabilityVersion;
1010
1011        if ($interfaceName eq "Node") {
1012            push(@internalHeaderContent, "\@protocol DOMEventTarget;\n\n");
1013        }
1014
1015        my $startedNamespace = 0;
1016
1017        if ($codeGenerator->IsSVGAnimatedType($interfaceName)) {
1018            push(@internalHeaderContent, "#import <WebCore/$implClassName.h>\n\n");
1019        } else {
1020            push(@internalHeaderContent, "namespace WebCore {\n");
1021            $startedNamespace = 1;
1022            if ($interfaceName eq "Node") {
1023                push(@internalHeaderContent, "    class EventTarget;\n    class Node;\n");
1024            } else {
1025                push(@internalHeaderContent, "    class $implClassName;\n");
1026            }
1027            push(@internalHeaderContent, "}\n\n");
1028        }
1029
1030        push(@internalHeaderContent, "$implType* core($className *);\n");
1031        push(@internalHeaderContent, "$className *kit($implType*);\n");
1032
1033        if ($dataNode->extendedAttributes->{Polymorphic}) {
1034            push(@internalHeaderContent, "Class kitClass($implType*);\n");
1035        }
1036
1037        if ($interfaceName eq "Node") {
1038            push(@internalHeaderContent, "id <DOMEventTarget> kit(WebCore::EventTarget*);\n");
1039        }
1040
1041        push(@internalHeaderContent, "\n#endif\n") if length $interfaceAvailabilityVersion;
1042    }
1043}
1044
1045sub GenerateImplementation
1046{
1047    my $object = shift;
1048    my $dataNode = shift;
1049
1050    my @ancestorInterfaceNames = ();
1051
1052    if (@{$dataNode->parents} > 1) {
1053        $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@ancestorInterfaceNames);
1054    }
1055
1056    my $interfaceName = $dataNode->name;
1057    my $className = GetClassName($interfaceName);
1058    my $implClassName = GetImplClassName($interfaceName);
1059    my $parentImplClassName = GetParentImplClassName($dataNode);
1060    my $implClassNameWithNamespace = "WebCore::" . $implClassName;
1061    my $baseClass = GetBaseClass($parentImplClassName);
1062    my $classHeaderName = GetClassHeaderName($className);
1063
1064    my $numAttributes = @{$dataNode->attributes};
1065    my $numFunctions = @{$dataNode->functions};
1066    my $implType = $implClassNameWithNamespace;
1067
1068    my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implClassName);
1069    $implType = $svgNativeType if $svgNativeType;
1070
1071    # - Add default header template.
1072    @implContentHeader = split("\r", $implementationLicenseTemplate);
1073
1074    # - INCLUDES -
1075    push(@implContentHeader, "\n#import \"config.h\"\n");
1076
1077    my $conditionalString = GenerateConditionalString($dataNode);
1078    push(@implContentHeader, "\n#if ${conditionalString}\n\n") if $conditionalString;
1079
1080    push(@implContentHeader, "#import \"DOMInternal.h\"\n\n");
1081    push(@implContentHeader, "#import \"$classHeaderName.h\"\n\n");
1082
1083    $implIncludes{"ExceptionHandlers.h"} = 1;
1084    $implIncludes{"ThreadCheck.h"} = 1;
1085    $implIncludes{"JSMainThreadExecState.h"} = 1;
1086    $implIncludes{"WebScriptObjectPrivate.h"} = 1;
1087    $implIncludes{$classHeaderName . "Internal.h"} = 1;
1088
1089    # FIXME: These includes are only needed when the class is a subclass of one of these polymorphic classes.
1090    $implIncludes{"DOMBlobInternal.h"} = 1;
1091    $implIncludes{"DOMCSSRuleInternal.h"} = 1;
1092    $implIncludes{"DOMCSSValueInternal.h"} = 1;
1093    $implIncludes{"DOMEventInternal.h"} = 1;
1094    $implIncludes{"DOMNodeInternal.h"} = 1;
1095    $implIncludes{"DOMStyleSheetInternal.h"} = 1;
1096
1097    $implIncludes{"DOMSVGPathSegInternal.h"} = 1 if $interfaceName =~ /^SVGPathSeg.+/;
1098
1099    if ($interfaceName =~ /(\w+)(Abs|Rel)$/) {
1100        $implIncludes{"$1.h"} = 1;
1101    } else {
1102        if (!$codeGenerator->AvoidInclusionOfType($implClassName)) {
1103            $implIncludes{"$implClassName.h"} = 1 ;
1104        } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($implClassName)) {
1105            my $includeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implClassName);
1106            $implIncludes{"${includeType}.h"} = 1;
1107        }
1108    }
1109
1110    @implContent = ();
1111
1112    push(@implContent, "#import <wtf/GetPtr.h>\n\n");
1113
1114    # add implementation accessor
1115    if ($parentImplClassName eq "Object") {
1116        push(@implContent, "#define IMPL reinterpret_cast<$implType*>(_internal)\n\n");
1117    } else {
1118        my $baseClassWithNamespace = "WebCore::$baseClass";
1119        push(@implContent, "#define IMPL static_cast<$implClassNameWithNamespace*>(reinterpret_cast<$baseClassWithNamespace*>(_internal))\n\n");
1120    }
1121
1122    # START implementation
1123    push(@implContent, "\@implementation $className\n\n");
1124
1125    # Only generate 'dealloc' and 'finalize' methods for direct subclasses of DOMObject.
1126    if ($parentImplClassName eq "Object") {
1127        $implIncludes{"WebCoreObjCExtras.h"} = 1;
1128        push(@implContent, "- (void)dealloc\n");
1129        push(@implContent, "{\n");
1130        push(@implContent, "    if (WebCoreObjCScheduleDeallocateOnMainThread([$className class], self))\n");
1131        push(@implContent, "        return;\n");
1132        push(@implContent, "\n");
1133        if ($interfaceName eq "NodeIterator") {
1134            push(@implContent, "    if (_internal) {\n");
1135            push(@implContent, "        [self detach];\n");
1136            push(@implContent, "        IMPL->deref();\n");
1137            push(@implContent, "    };\n");
1138        } else {
1139            push(@implContent, "    if (_internal)\n");
1140            push(@implContent, "        IMPL->deref();\n");
1141        }
1142        push(@implContent, "    [super dealloc];\n");
1143        push(@implContent, "}\n\n");
1144
1145        push(@implContent, "- (void)finalize\n");
1146        push(@implContent, "{\n");
1147        if ($interfaceName eq "NodeIterator") {
1148            push(@implContent, "    if (_internal) {\n");
1149            push(@implContent, "        [self detach];\n");
1150            push(@implContent, "        IMPL->deref();\n");
1151            push(@implContent, "    };\n");
1152        } else {
1153            push(@implContent, "    if (_internal)\n");
1154            push(@implContent, "        IMPL->deref();\n");
1155        }
1156        push(@implContent, "    [super finalize];\n");
1157        push(@implContent, "}\n\n");
1158
1159    }
1160
1161    %attributeNames = ();
1162
1163    # - Attributes
1164    if ($numAttributes > 0) {
1165        foreach my $attribute (@{$dataNode->attributes}) {
1166            AddIncludesForType($attribute->signature->type);
1167
1168            my $idlType = $codeGenerator->StripModule($attribute->signature->type);
1169
1170            my $attributeName = $attribute->signature->name;
1171            my $attributeType = GetObjCType($attribute->signature->type);
1172            my $attributeIsReadonly = ($attribute->type =~ /^readonly/);
1173            my $attributeClassName = GetClassName($attribute->signature->type);
1174
1175            my $attributeInterfaceName = $attributeName;
1176            if ($attributeName eq "id" or $attributeName eq "hash" or $attributeName eq "description") {
1177                # Special case some attributes (like id and hash) to have a "Name" suffix to avoid ObjC naming conflicts.
1178                $attributeInterfaceName .= "Name";
1179            } elsif ($attributeName eq "frame") {
1180                # Special case attribute frame to be frameBorders.
1181                $attributeInterfaceName .= "Borders";
1182            } elsif ($attributeName eq "operator") {
1183                # Avoid clash with C++ keyword.
1184                $attributeInterfaceName = "_operator";
1185            }
1186
1187            $attributeNames{$attributeInterfaceName} = 1;
1188
1189            # - GETTER
1190            my $getterSig = "- ($attributeType)$attributeInterfaceName\n";
1191
1192            my $getterExpressionPrefix = $codeGenerator->GetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute);
1193
1194            # FIXME: Special case attribute ownerDocument to call document. This makes it return the
1195            # document when called on the document itself. Legacy behavior, see <https://bugs.webkit.org/show_bug.cgi?id=10889>.
1196            $getterExpressionPrefix =~ s/\bownerDocument\b/document/;
1197
1198            my $hasGetterException = @{$attribute->getterExceptions};
1199            my $getterContentHead = "IMPL->$getterExpressionPrefix";
1200            my $getterContentTail = ")";
1201
1202            if ($svgPropertyType) {
1203                $getterContentHead = "$getterExpressionPrefix";
1204
1205                # TODO: Handle special case for DOMSVGLength. We do need Custom code support for this.
1206                if ($svgPropertyType eq "WebCore::SVGLength" and $attributeName eq "value") {
1207                    $getterContentHead = "value(IMPL->contextElement(), ";
1208                }
1209            }
1210
1211            my $attributeTypeSansPtr = $attributeType;
1212            $attributeTypeSansPtr =~ s/ \*$//; # Remove trailing " *" from pointer types.
1213
1214            # special case for EventTarget protocol
1215            $attributeTypeSansPtr = "DOMNode" if $idlType eq "EventTarget";
1216
1217            # Special cases
1218            my @customGetterContent = ();
1219            if ($attributeTypeSansPtr eq "DOMImplementation") {
1220                # FIXME: We have to special case DOMImplementation until DOMImplementationFront is removed
1221                $getterContentHead = "kit(implementationFront(IMPL";
1222                $getterContentTail .= ")";
1223            } elsif ($attributeName =~ /(\w+)DisplayString$/) {
1224                my $attributeToDisplay = $1;
1225                $getterContentHead = "WebCore::displayString(IMPL->$attributeToDisplay(), core(self)";
1226                $implIncludes{"HitTestResult.h"} = 1;
1227            } elsif ($attributeName =~ /^absolute(\w+)URL$/) {
1228                my $typeOfURL = $1;
1229                $getterContentHead = "[self _getURLAttribute:";
1230                if ($typeOfURL eq "Link") {
1231                    $getterContentTail = "\@\"href\"]";
1232                } elsif ($typeOfURL eq "Image") {
1233                    if ($interfaceName eq "HTMLObjectElement") {
1234                        $getterContentTail = "\@\"data\"]";
1235                    } else {
1236                        $getterContentTail = "\@\"src\"]";
1237                    }
1238                    unless ($interfaceName eq "HTMLImageElement") {
1239                        push(@customGetterContent, "    if (!IMPL->renderer() || !IMPL->renderer()->isImage())\n");
1240                        push(@customGetterContent, "        return nil;\n");
1241                        $implIncludes{"RenderObject.h"} = 1;
1242                    }
1243                }
1244                $implIncludes{"DOMPrivate.h"} = 1;
1245            } elsif ($attribute->signature->extendedAttributes->{"ConvertToString"}) {
1246                $getterContentHead = "WTF::String::number(" . $getterContentHead;
1247                $getterContentTail .= ")";
1248            } elsif ($idlType eq "Date") {
1249                $getterContentHead = "kit($getterContentHead";
1250                $getterContentTail .= ")";
1251            } elsif ($svgPropertyType) {
1252                # Special case for DOMSVGNumber
1253                if ($svgPropertyType eq "float") {
1254                    # Intentional leave out closing brace, it's already contained in getterContentTail
1255                    $getterContentHead = "IMPL->propertyReference(";
1256                } else {
1257                    $getterContentHead = "IMPL->propertyReference().$getterContentHead";
1258                }
1259
1260                if ($codeGenerator->IsSVGTypeWithWritablePropertiesNeedingTearOff($idlType) and not defined $attribute->signature->extendedAttributes->{"Immutable"}) {
1261                    my $getter = $getterContentHead;
1262                    $getter =~ s/\(\)//;
1263
1264                    my $tearOffType = GetSVGTypeWithNamespace($idlType);
1265                    my $selfIsTearOffType = $codeGenerator->IsSVGTypeNeedingTearOff($implClassName);
1266                    if ($selfIsTearOffType) {
1267                        $implIncludes{"SVGStaticPropertyWithParentTearOff.h"} = 1;
1268                        $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyWithParentTearOff<$implClassNameWithNamespace, /;
1269
1270                        my $getter = $getterExpressionPrefix;
1271                        $getter =~ s/IMPL->//;
1272                        $getter =~ s/\(//;
1273                        my $updateMethod = "&${implClassNameWithNamespace}::update" . $codeGenerator->WK_ucfirst($getter);
1274
1275                        if ($getterContentHead =~ /matrix/ and $implClassName eq "SVGTransform") {
1276                            # SVGTransform offers a matrix() method for internal usage that returns an AffineTransform
1277                            # and a svgMatrix() method returning a SVGMatrix, used for the bindings.
1278                            $getterContentHead =~ s/matrix/svgMatrix/;
1279                        }
1280
1281                        $getterContentHead = "${tearOffType}::create(IMPL, $getterContentHead$getterContentTail, $updateMethod)";
1282
1283                        $getterContentHead = "kit(WTF::getPtr($getterContentHead";
1284                        $getterContentTail = "))";
1285                    }
1286                }
1287            } elsif ($codeGenerator->IsSVGAnimatedType($implClassName) and $codeGenerator->IsSVGTypeNeedingTearOff($idlType)) {
1288                my $idlTypeWithNamespace = GetSVGTypeWithNamespace($idlType);
1289                $getterContentHead = "kit(static_cast<$idlTypeWithNamespace*>($getterContentHead)";
1290                $getterContentTail .= ")";
1291            } elsif (IsProtocolType($idlType) and $idlType ne "EventTarget") {
1292                $getterContentHead = "kit($getterContentHead";
1293                $getterContentTail .= ")";
1294            } elsif ($idlType eq "Color") {
1295                $getterContentHead = "WebCore::nsColor($getterContentHead";
1296                $getterContentTail .= ")";
1297            } elsif ($attribute->signature->type eq "SerializedScriptValue") {
1298                $getterContentHead = "$getterContentHead";
1299                $getterContentTail .= "->toString()";
1300            } elsif (ConversionNeeded($attribute->signature->type)) {
1301                my $type = $attribute->signature->type;
1302                if ($codeGenerator->IsSVGTypeNeedingTearOff($type) and not $implClassName =~ /List$/) {
1303                    my $idlTypeWithNamespace = GetSVGTypeWithNamespace($type);
1304                    $implIncludes{"$type.h"} = 1 if not $codeGenerator->AvoidInclusionOfType($type);
1305                    if ($codeGenerator->IsSVGTypeWithWritablePropertiesNeedingTearOff($type) and not defined $attribute->signature->extendedAttributes->{"Immutable"}) {
1306                        $idlTypeWithNamespace =~ s/SVGPropertyTearOff</SVGStaticPropertyTearOff<$implClassNameWithNamespace, /;
1307                        $implIncludes{"SVGStaticPropertyTearOff.h"} = 1;
1308
1309                        my $getter = $getterContentHead;
1310                        $getter =~ s/IMPL->//;
1311                        $getter =~ s/\(//;
1312                        my $updateMethod = "&${implClassNameWithNamespace}::update" . $codeGenerator->WK_ucfirst($getter);
1313                        $getterContentHead = "kit(WTF::getPtr(${idlTypeWithNamespace}::create(IMPL, $getterContentHead$getterContentTail, $updateMethod";
1314                        $getterContentTail .= "))";
1315                    } elsif ($idlTypeWithNamespace =~ /SVG(Point|PathSeg)List/) {
1316                        $getterContentHead = "kit(WTF::getPtr($getterContentHead";
1317                        $getterContentTail .= "))";
1318                    } elsif ($idlTypeWithNamespace =~ /SVGStaticListPropertyTearOff/) {
1319                        my $extraImp = "WebCore::GetOwnerElementForType<$implClassNameWithNamespace, WebCore::IsDerivedFromSVGElement<$implClassNameWithNamespace>::value>::ownerElement(IMPL), ";
1320                        $getterContentHead = "kit(WTF::getPtr(${idlTypeWithNamespace}::create($extraImp$getterContentHead";
1321                        $getterContentTail .= ")))";
1322                    } else {
1323                        $getterContentHead = "kit(WTF::getPtr(${idlTypeWithNamespace}::create($getterContentHead";
1324                        $getterContentTail .= ")))";
1325                    }
1326                } else {
1327                    $getterContentHead = "kit(WTF::getPtr($getterContentHead";
1328                    $getterContentTail .= "))";
1329                }
1330            }
1331
1332            my $getterContent;
1333            if ($hasGetterException) {
1334                $getterContent = $getterContentHead . "ec" . $getterContentTail;
1335            } else {
1336                $getterContent = $getterContentHead . $getterContentTail;
1337            }
1338
1339            my $attributeConditionalString = GenerateConditionalString($attribute->signature);
1340            push(@implContent, "#if ${attributeConditionalString}\n") if $attributeConditionalString;
1341            push(@implContent, $getterSig);
1342            push(@implContent, "{\n");
1343            push(@implContent, "    $jsContextSetter\n");
1344            push(@implContent, @customGetterContent);
1345            if ($hasGetterException) {
1346                # Differentiated between when the return type is a pointer and
1347                # not for white space issue (ie. Foo *result vs. int result).
1348                if ($attributeType =~ /\*$/) {
1349                    $getterContent = $attributeType . "result = " . $getterContent;
1350                } else {
1351                    $getterContent = $attributeType . " result = " . $getterContent;
1352                }
1353
1354                push(@implContent, "    $exceptionInit\n");
1355                push(@implContent, "    $getterContent;\n");
1356                push(@implContent, "    $exceptionRaiseOnError\n");
1357                push(@implContent, "    return result;\n");
1358            } else {
1359                push(@implContent, "    return $getterContent;\n");
1360            }
1361            push(@implContent, "}\n");
1362
1363            # - SETTER
1364            if (!$attributeIsReadonly) {
1365                # Exception handling
1366                my $hasSetterException = @{$attribute->setterExceptions};
1367
1368                my $coreSetterName = "set" . $codeGenerator->WK_ucfirst($attributeName);
1369                my $setterName = "set" . ucfirst($attributeInterfaceName);
1370                my $argName = "new" . ucfirst($attributeInterfaceName);
1371                my $arg = GetObjCTypeGetter($argName, $idlType);
1372
1373                # The definition of ConvertToString is flipped for the setter
1374                if ($attribute->signature->extendedAttributes->{"ConvertToString"}) {
1375                    $arg = "WTF::String($arg).toInt()";
1376                }
1377
1378                my $setterSig = "- (void)$setterName:($attributeType)$argName\n";
1379
1380                push(@implContent, "\n");
1381                push(@implContent, $setterSig);
1382                push(@implContent, "{\n");
1383                push(@implContent, "    $jsContextSetter\n");
1384
1385                unless ($codeGenerator->IsPrimitiveType($idlType) or $codeGenerator->IsStringType($idlType)) {
1386                    push(@implContent, "    ASSERT($argName);\n\n");
1387                }
1388
1389                if ($idlType eq "Date") {
1390                    $arg = "core(" . $arg . ")";
1391                }
1392
1393                if ($svgPropertyType) {
1394                    $getterContentHead = "$getterExpressionPrefix";
1395                    push(@implContent, "    if (IMPL->role() == WebCore::AnimValRole) {\n");
1396                    push(@implContent, "        WebCore::raiseOnDOMError(WebCore::NO_MODIFICATION_ALLOWED_ERR);\n");
1397                    push(@implContent, "        return;\n");
1398                    push(@implContent, "    }\n");
1399                    push(@implContent, "    $svgPropertyType& podImpl = IMPL->propertyReference();\n");
1400                    my $ec = $hasSetterException ? ", ec" : "";
1401                    push(@implContent, "    $exceptionInit\n") if $hasSetterException;
1402
1403                    # Special case for DOMSVGNumber
1404                    if ($svgPropertyType eq "float") {
1405                        push(@implContent, "    podImpl = $arg;\n");
1406                    } else {
1407                        # FIXME: Special case for DOMSVGLength. We do need Custom code support for this.
1408                        if ($svgPropertyType eq "WebCore::SVGLength" and $attributeName eq "value") {
1409                            push(@implContent, "    podImpl.$coreSetterName($arg, IMPL->contextElement()$ec);\n");
1410                        } else {
1411                            push(@implContent, "    podImpl.$coreSetterName($arg$ec);\n");
1412                        }
1413                    }
1414
1415                    if ($hasSetterException) {
1416                        push(@implContent, "    if (!ec)\n");
1417                        push(@implContent, "        IMPL->commitChange();\n");
1418                        push(@implContent, "    $exceptionRaiseOnError\n");
1419                    } else {
1420                        push(@implContent, "    IMPL->commitChange();\n");
1421                    }
1422                } elsif ($svgListPropertyType) {
1423                    $getterContentHead = "$getterExpressionPrefix";
1424                    push(@implContent, "    IMPL->$coreSetterName($arg);\n");
1425                } else {
1426                    my $setterExpressionPrefix = $codeGenerator->SetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute);
1427                    my $ec = $hasSetterException ? ", ec" : "";
1428                    push(@implContent, "    $exceptionInit\n") if $hasSetterException;
1429                    push(@implContent, "    IMPL->$setterExpressionPrefix$arg$ec);\n");
1430                    push(@implContent, "    $exceptionRaiseOnError\n") if $hasSetterException;
1431                }
1432
1433                push(@implContent, "}\n");
1434            }
1435
1436            push(@implContent, "#endif\n") if $attributeConditionalString;
1437            push(@implContent, "\n");
1438        }
1439    }
1440
1441    # - Functions
1442    if ($numFunctions > 0) {
1443        foreach my $function (@{$dataNode->functions}) {
1444            AddIncludesForType($function->signature->type);
1445
1446            my $functionName = $function->signature->name;
1447            my $returnType = GetObjCType($function->signature->type);
1448            my $hasParameters = @{$function->parameters};
1449            my $raisesExceptions = @{$function->raisesExceptions};
1450
1451            my @parameterNames = ();
1452            my @needsAssert = ();
1453            my %needsCustom = ();
1454
1455            my $parameterIndex = 0;
1456            my $functionSig = "- ($returnType)$functionName";
1457            foreach my $param (@{$function->parameters}) {
1458                my $paramName = $param->name;
1459                my $paramType = GetObjCType($param->type);
1460
1461                # make a new parameter name if the original conflicts with a property name
1462                $paramName = "in" . ucfirst($paramName) if $attributeNames{$paramName};
1463
1464                AddIncludesForType($param->type);
1465
1466                my $idlType = $codeGenerator->StripModule($param->type);
1467                my $implGetter = GetObjCTypeGetter($paramName, $idlType);
1468
1469                push(@parameterNames, $implGetter);
1470                $needsCustom{"XPathNSResolver"} = $paramName if $idlType eq "XPathNSResolver";
1471                $needsCustom{"NodeFilter"} = $paramName if $idlType eq "NodeFilter";
1472                $needsCustom{"EventListener"} = $paramName if $idlType eq "EventListener";
1473                $needsCustom{"EventTarget"} = $paramName if $idlType eq "EventTarget";
1474                $needsCustom{"NodeToReturn"} = $paramName if $param->extendedAttributes->{"Return"};
1475
1476                unless ($codeGenerator->IsPrimitiveType($idlType) or $codeGenerator->IsStringType($idlType)) {
1477                    push(@needsAssert, "    ASSERT($paramName);\n");
1478                }
1479
1480                if ($parameterIndex >= 1) {
1481                    my $paramPrefix = $param->extendedAttributes->{"ObjCPrefix"};
1482                    $paramPrefix = $param->name unless defined($paramPrefix);
1483                    $functionSig .= " $paramPrefix";
1484                }
1485
1486                $functionSig .= ":($paramType)$paramName";
1487
1488                $parameterIndex++;
1489            }
1490
1491            my @functionContent = ();
1492            my $caller = "IMPL";
1493
1494            # special case the XPathNSResolver
1495            if (defined $needsCustom{"XPathNSResolver"}) {
1496                my $paramName = $needsCustom{"XPathNSResolver"};
1497                push(@functionContent, "    WebCore::XPathNSResolver* nativeResolver = 0;\n");
1498                push(@functionContent, "    RefPtr<WebCore::XPathNSResolver> customResolver;\n");
1499                push(@functionContent, "    if ($paramName) {\n");
1500                push(@functionContent, "        if ([$paramName isMemberOfClass:[DOMNativeXPathNSResolver class]])\n");
1501                push(@functionContent, "            nativeResolver = core(static_cast<DOMNativeXPathNSResolver *>($paramName));\n");
1502                push(@functionContent, "        else {\n");
1503                push(@functionContent, "            customResolver = WebCore::DOMCustomXPathNSResolver::create($paramName);\n");
1504                push(@functionContent, "            nativeResolver = WTF::getPtr(customResolver);\n");
1505                push(@functionContent, "        }\n");
1506                push(@functionContent, "    }\n");
1507            }
1508
1509            # special case the EventTarget
1510            if (defined $needsCustom{"EventTarget"}) {
1511                my $paramName = $needsCustom{"EventTarget"};
1512                push(@functionContent, "    DOMNode* ${paramName}ObjC = $paramName;\n");
1513                push(@functionContent, "    WebCore::Node* ${paramName}Node = core(${paramName}ObjC);\n");
1514                $implIncludes{"DOMNode.h"} = 1;
1515                $implIncludes{"Node.h"} = 1;
1516            }
1517
1518            if ($function->signature->extendedAttributes->{"UsesView"}) {
1519                push(@functionContent, "    WebCore::DOMWindow* dv = $caller->defaultView();\n");
1520                push(@functionContent, "    if (!dv)\n");
1521                push(@functionContent, "        return nil;\n");
1522                $implIncludes{"DOMWindow.h"} = 1;
1523                $caller = "dv";
1524            }
1525
1526            # special case the EventListener
1527            if (defined $needsCustom{"EventListener"}) {
1528                my $paramName = $needsCustom{"EventListener"};
1529                push(@functionContent, "    RefPtr<WebCore::EventListener> nativeEventListener = WebCore::ObjCEventListener::wrap($paramName);\n");
1530            }
1531
1532            # special case the NodeFilter
1533            if (defined $needsCustom{"NodeFilter"}) {
1534                my $paramName = $needsCustom{"NodeFilter"};
1535                push(@functionContent, "    RefPtr<WebCore::NodeFilter> nativeNodeFilter;\n");
1536                push(@functionContent, "    if ($paramName)\n");
1537                push(@functionContent, "        nativeNodeFilter = WebCore::NodeFilter::create(WebCore::ObjCNodeFilterCondition::create($paramName));\n");
1538            }
1539
1540            # FIXME! We need [Custom] support for ObjC, to move these hacks into DOMSVGLength/MatrixCustom.mm
1541            my $svgLengthConvertToSpecifiedUnits = ($svgPropertyType and $svgPropertyType eq "WebCore::SVGLength" and $functionName eq "convertToSpecifiedUnits");
1542
1543            push(@parameterNames, "IMPL->contextElement()") if $svgLengthConvertToSpecifiedUnits;
1544            push(@parameterNames, "ec") if $raisesExceptions;
1545
1546            # Handle arguments that are 'SVGProperty' based (SVGAngle/SVGLength). We need to convert from SVGPropertyTearOff<Type>* to Type,
1547            # to be able to call the desired WebCore function. If the conversion fails, we can't extract Type and need to raise an exception.
1548            my $currentParameter = -1;
1549            foreach my $param (@{$function->parameters}) {
1550                $currentParameter++;
1551
1552                my $paramName = $param->name;
1553
1554                # make a new parameter name if the original conflicts with a property name
1555                $paramName = "in" . ucfirst($paramName) if $attributeNames{$paramName};
1556
1557                my $idlType = $codeGenerator->StripModule($param->type);
1558                next if not $codeGenerator->IsSVGTypeNeedingTearOff($idlType) or $implClassName =~ /List$/;
1559
1560                my $implGetter = GetObjCTypeGetter($paramName, $idlType);
1561                my $idlTypeWithNamespace = GetSVGTypeWithNamespace($idlType);
1562
1563                push(@functionContent, "    $idlTypeWithNamespace* ${paramName}Core = $implGetter;\n");
1564                push(@functionContent, "    if (!${paramName}Core) {\n");
1565                push(@functionContent, "        WebCore::ExceptionCode ec = WebCore::TYPE_MISMATCH_ERR;\n");
1566                push(@functionContent, "        $exceptionRaiseOnError\n");
1567                if ($returnType eq "void") {
1568                    push(@functionContent, "        return;\n");
1569                } else {
1570                    push(@functionContent, "        return nil;\n");
1571                }
1572                push(@functionContent, "    }\n");
1573
1574                # Replace the paramter core() getter, by the cached variable.
1575                splice(@parameterNames, $currentParameter, 1, "${paramName}Core->propertyReference()");
1576            }
1577
1578            my $content = $codeGenerator->WK_lcfirst($functionName) . "(" . join(", ", @parameterNames) . ")";
1579
1580            if ($svgPropertyType) {
1581                push(@functionContent, "    if (IMPL->role() == WebCore::AnimValRole) {\n");
1582                push(@functionContent, "        WebCore::raiseOnDOMError(WebCore::NO_MODIFICATION_ALLOWED_ERR);\n");
1583                if ($returnType eq "void") {
1584                    push(@functionContent, "        return;\n");
1585                } else {
1586                    push(@functionContent, "        return nil;\n");
1587                }
1588                push(@functionContent, "    }\n");
1589                push(@functionContent, "    $svgPropertyType& podImpl = IMPL->propertyReference();\n");
1590                $content = "podImpl.$content";
1591            } else {
1592                $content = $caller . "->$content";
1593            }
1594
1595            if ($returnType eq "void") {
1596                # Special case 'void' return type.
1597                if ($raisesExceptions) {
1598                    push(@functionContent, "    $exceptionInit\n");
1599                    push(@functionContent, "    $content;\n");
1600                    if ($svgPropertyType) {
1601                        push(@functionContent, "    if (!ec)\n");
1602                        push(@functionContent, "        IMPL->commitChange();\n");
1603                    }
1604                    push(@functionContent, "    $exceptionRaiseOnError\n");
1605                } else {
1606                    push(@functionContent, "    $content;\n");
1607                    push(@functionContent, "    IMPL->commitChange();\n") if $svgPropertyType;
1608                }
1609            } elsif (defined $needsCustom{"NodeToReturn"}) {
1610                # Special case the insertBefore, replaceChild, removeChild
1611                # and appendChild functions from DOMNode
1612                my $toReturn = $needsCustom{"NodeToReturn"};
1613                if ($raisesExceptions) {
1614                    push(@functionContent, "    $exceptionInit\n");
1615                    push(@functionContent, "    if ($content)\n");
1616                    push(@functionContent, "        return $toReturn;\n");
1617                    push(@functionContent, "    $exceptionRaiseOnError\n");
1618                    push(@functionContent, "    return nil;\n");
1619                } else {
1620                    push(@functionContent, "    if ($content)\n");
1621                    push(@functionContent, "        return $toReturn;\n");
1622                    push(@functionContent, "    return nil;\n");
1623                }
1624            } elsif ($returnType eq "SerializedScriptValue") {
1625                $content = "foo";
1626            } else {
1627                if (ConversionNeeded($function->signature->type)) {
1628                    if ($codeGenerator->IsSVGTypeNeedingTearOff($function->signature->type) and not $implClassName =~ /List$/) {
1629                        my $idlTypeWithNamespace = GetSVGTypeWithNamespace($function->signature->type);
1630                        $content = "kit(WTF::getPtr(${idlTypeWithNamespace}::create($content)))";
1631                    } else {
1632                        $content = "kit(WTF::getPtr($content))";
1633                    }
1634                }
1635
1636                if ($raisesExceptions) {
1637                    # Differentiated between when the return type is a pointer and
1638                    # not for white space issue (ie. Foo *result vs. int result).
1639                    if ($returnType =~ /\*$/) {
1640                        $content = $returnType . "result = " . $content;
1641                    } else {
1642                        $content = $returnType . " result = " . $content;
1643                    }
1644
1645                    push(@functionContent, "    $exceptionInit\n");
1646                    push(@functionContent, "    $content;\n");
1647                    push(@functionContent, "    $exceptionRaiseOnError\n");
1648                    push(@functionContent, "    return result;\n");
1649                } else {
1650                    push(@functionContent, "    return $content;\n");
1651                }
1652            }
1653
1654            push(@implContent, "$functionSig\n");
1655            push(@implContent, "{\n");
1656            push(@implContent, "    $jsContextSetter\n");
1657            push(@implContent, @functionContent);
1658            push(@implContent, "}\n\n");
1659
1660            # generate the old style method names with un-named parameters, these methods are deprecated
1661            if (@{$function->parameters} > 1 and $function->signature->extendedAttributes->{"OldStyleObjC"}) {
1662                my $deprecatedFunctionSig = $functionSig;
1663                $deprecatedFunctionSig =~ s/\s\w+:/ :/g; # remove parameter names
1664
1665                push(@implContent, "$deprecatedFunctionSig\n");
1666                push(@implContent, "{\n");
1667                push(@implContent, "    $jsContextSetter\n");
1668                push(@implContent, @functionContent);
1669                push(@implContent, "}\n\n");
1670            }
1671
1672            # Clear the hash
1673            %needsCustom = ();
1674        }
1675    }
1676
1677    # END implementation
1678    push(@implContent, "\@end\n");
1679
1680    # Generate internal interfaces
1681    push(@implContent, "\n$implType* core($className *wrapper)\n");
1682    push(@implContent, "{\n");
1683    push(@implContent, "    return wrapper ? reinterpret_cast<$implType*>(wrapper->_internal) : 0;\n");
1684    push(@implContent, "}\n\n");
1685
1686    if ($parentImplClassName eq "Object") {
1687        push(@implContent, "$className *kit($implType* value)\n");
1688        push(@implContent, "{\n");
1689        push(@implContent, "    $assertMainThread;\n");
1690        push(@implContent, "    if (!value)\n");
1691        push(@implContent, "        return nil;\n");
1692        push(@implContent, "    if ($className *wrapper = getDOMWrapper(value))\n");
1693        push(@implContent, "        return [[wrapper retain] autorelease];\n");
1694        if ($dataNode->extendedAttributes->{Polymorphic}) {
1695            push(@implContent, "    $className *wrapper = [[kitClass(value) alloc] _init];\n");
1696            push(@implContent, "    if (!wrapper)\n");
1697            push(@implContent, "        return nil;\n");
1698        } else {
1699            push(@implContent, "    $className *wrapper = [[$className alloc] _init];\n");
1700        }
1701        push(@implContent, "    wrapper->_internal = reinterpret_cast<DOMObjectInternal*>(value);\n");
1702        push(@implContent, "    value->ref();\n");
1703        push(@implContent, "    addDOMWrapper(wrapper, value);\n");
1704        push(@implContent, "    return [wrapper autorelease];\n");
1705        push(@implContent, "}\n");
1706    } else {
1707        push(@implContent, "$className *kit($implType* value)\n");
1708        push(@implContent, "{\n");
1709        push(@implContent, "    $assertMainThread;\n");
1710        push(@implContent, "    return static_cast<$className*>(kit(static_cast<WebCore::$baseClass*>(value)));\n");
1711        push(@implContent, "}\n");
1712    }
1713
1714    # - End the ifdef conditional if necessary
1715    push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
1716
1717    # - Generate dependencies.
1718    if ($writeDependencies && @ancestorInterfaceNames) {
1719        push(@depsContent, "$className.h : ", join(" ", map { "$_.idl" } @ancestorInterfaceNames), "\n");
1720        push(@depsContent, map { "$_.idl :\n" } @ancestorInterfaceNames);
1721    }
1722}
1723
1724# Internal helper
1725sub WriteData
1726{
1727    my $object = shift;
1728    my $name = shift;
1729
1730    # Open files for writing...
1731    my $headerFileName = "$outputDir/" . $name . ".h";
1732    my $privateHeaderFileName = "$outputDir/" . $name . "Private.h";
1733    my $implFileName = "$outputDir/" . $name . ".mm";
1734    my $internalHeaderFileName = "$outputDir/" . $name . "Internal.h";
1735    my $depsFileName = "$outputDir/" . $name . ".dep";
1736
1737    # Remove old files.
1738    unlink($headerFileName);
1739    unlink($privateHeaderFileName);
1740    unlink($implFileName);
1741    unlink($internalHeaderFileName);
1742    unlink($depsFileName);
1743
1744    # Write public header.
1745    open(HEADER, ">$headerFileName") or die "Couldn't open file $headerFileName";
1746
1747    print HEADER @headerContentHeader;
1748    print HEADER map { "\@class $_;\n" } sort keys(%headerForwardDeclarations);
1749    print HEADER map { "\@protocol $_;\n" } sort keys(%headerForwardDeclarationsForProtocols);
1750
1751    my $hasForwardDeclarations = keys(%headerForwardDeclarations) + keys(%headerForwardDeclarationsForProtocols);
1752    print HEADER "\n" if $hasForwardDeclarations;
1753    print HEADER @headerContent;
1754
1755    close(HEADER);
1756
1757    @headerContentHeader = ();
1758    @headerContent = ();
1759    %headerForwardDeclarations = ();
1760    %headerForwardDeclarationsForProtocols = ();
1761
1762    if (@privateHeaderContent > 0) {
1763        open(PRIVATE_HEADER, ">$privateHeaderFileName") or die "Couldn't open file $privateHeaderFileName";
1764
1765        print PRIVATE_HEADER @privateHeaderContentHeader;
1766        print PRIVATE_HEADER map { "\@class $_;\n" } sort keys(%privateHeaderForwardDeclarations);
1767        print PRIVATE_HEADER map { "\@protocol $_;\n" } sort keys(%privateHeaderForwardDeclarationsForProtocols);
1768
1769        $hasForwardDeclarations = keys(%privateHeaderForwardDeclarations) + keys(%privateHeaderForwardDeclarationsForProtocols);
1770        print PRIVATE_HEADER "\n" if $hasForwardDeclarations;
1771        print PRIVATE_HEADER @privateHeaderContent;
1772
1773        close(PRIVATE_HEADER);
1774
1775        @privateHeaderContentHeader = ();
1776        @privateHeaderContent = ();
1777        %privateHeaderForwardDeclarations = ();
1778        %privateHeaderForwardDeclarationsForProtocols = ();
1779    }
1780
1781    # Write implementation file.
1782    unless ($noImpl) {
1783        open(IMPL, ">$implFileName") or die "Couldn't open file $implFileName";
1784
1785        print IMPL @implContentHeader;
1786        print IMPL map { "#import \"$_\"\n" } sort keys(%implIncludes);
1787        print IMPL @implContent;
1788
1789        close(IMPL);
1790
1791        @implContentHeader = ();
1792        @implContent = ();
1793        %implIncludes = ();
1794    }
1795
1796    if (@internalHeaderContent > 0) {
1797       open(INTERNAL_HEADER, ">$internalHeaderFileName") or die "Couldn't open file $internalHeaderFileName";
1798
1799       print INTERNAL_HEADER @internalHeaderContent;
1800
1801       close(INTERNAL_HEADER);
1802
1803       @internalHeaderContent = ();
1804    }
1805
1806    # Write dependency file.
1807    if (@depsContent) {
1808        open(DEPS, ">$depsFileName") or die "Couldn't open file $depsFileName";
1809        print DEPS @depsContent;
1810        close(DEPS);
1811        @depsContent = ();
1812    }
1813}
1814
18151;
1816