CodeGeneratorObjC.pm 78 KB

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