1 # 2 # Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann (at] kde.org> 3 # Copyright (C) 2006 Anders Carlsson <andersca (at] mac.com> 4 # Copyright (C) 2006, 2007 Samuel Weinig <sam (at] webkit.org> 5 # Copyright (C) 2006 Alexey Proskuryakov <ap (at] webkit.org> 6 # Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. 7 # Copyright (C) 2009 Cameron McCormack <cam (at] 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 27 package CodeGeneratorObjC; 28 29 # Global Variables 30 my $module = ""; 31 my $outputDir = ""; 32 my $writeDependencies = 0; 33 my %publicInterfaces = (); 34 my $newPublicClass = 0; 35 my $interfaceAvailabilityVersion = ""; 36 my $isProtocol = 0; 37 my $noImpl = 0; 38 39 my @headerContentHeader = (); 40 my @headerContent = (); 41 my %headerForwardDeclarations = (); 42 my %headerForwardDeclarationsForProtocols = (); 43 44 my @privateHeaderContentHeader = (); 45 my @privateHeaderContent = (); 46 my %privateHeaderForwardDeclarations = (); 47 my %privateHeaderForwardDeclarationsForProtocols = (); 48 49 my @internalHeaderContent = (); 50 51 my @implContentHeader = (); 52 my @implContent = (); 53 my %implIncludes = (); 54 my @depsContent = (); 55 56 # Hashes 57 my %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); 61 my %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. 65 my %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 79 my $buildingForTigerOrEarlier = 1 if $ENV{"MACOSX_DEPLOYMENT_TARGET"} and $ENV{"MACOSX_DEPLOYMENT_TARGET"} <= 10.4; 80 my $buildingForLeopardOrLater = 1 if $ENV{"MACOSX_DEPLOYMENT_TARGET"} and $ENV{"MACOSX_DEPLOYMENT_TARGET"} >= 10.5; 81 my $exceptionInit = "WebCore::ExceptionCode ec = 0;"; 82 my $jsContextSetter = "WebCore::JSMainThreadNullState state;"; 83 my $exceptionRaiseOnError = "WebCore::raiseOnDOMError(ec);"; 84 my $assertMainThread = "{ DOM_ASSERT_MAIN_THREAD(); WebCoreThreadViolationCheckRoundOne(); }"; 85 86 my %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 133 my $fatalError = 0; 134 135 # Default License Templates 136 my $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 */ 162 EOF 163 164 my $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 */ 190 EOF 191 192 # Default constructor 193 sub 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 209 sub finish 210 { 211 my $object = shift; 212 } 213 214 sub 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 275 sub 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 293 sub 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 327 sub GenerateModule 328 { 329 my $object = shift; 330 my $dataNode = shift; 331 332 $module = $dataNode->module; 333 } 334 335 sub 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 354 sub GetClassHeaderName 355 { 356 my $name = shift; 357 358 return "DOMDOMImplementation" if $name eq "DOMImplementation"; 359 return $name; 360 } 361 362 sub 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 371 sub 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 385 sub 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 436 sub 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 446 sub IsBaseType 447 { 448 my $type = shift; 449 450 return 1 if $baseTypeHash{$type}; 451 return 0; 452 } 453 454 sub IsProtocolType 455 { 456 my $type = shift; 457 458 return 1 if $protocolTypeHash{$type}; 459 return 0; 460 } 461 462 sub IsNativeObjCType 463 { 464 my $type = shift; 465 466 return 1 if $nativeObjCTypeHash{$type}; 467 return 0; 468 } 469 470 sub 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 481 sub 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 503 sub ConversionNeeded 504 { 505 my $type = $codeGenerator->StripModule(shift); 506 507 return !$codeGenerator->IsNonPointerType($type) && !$codeGenerator->IsStringType($type) && !IsNativeObjCType($type); 508 } 509 510 sub 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 529 sub 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 551 sub 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 631 sub 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 641 sub 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 681 sub 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 1045 sub 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 1725 sub 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 1815 1; 1816