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