| OLD | NEW |
| (Empty) |
| 1 # Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org> | |
| 2 # Copyright (C) 2006 Anders Carlsson <andersca@mac.com> | |
| 3 # Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> | |
| 4 # Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org> | |
| 5 # Copyright (C) 2006 Apple Computer, Inc. | |
| 6 # Copyright (C) 2007, 2008, 2009 Google Inc. | |
| 7 # Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au> | |
| 8 # Copyright (C) Research In Motion Limited 2010. All rights reserved. | |
| 9 # Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) | |
| 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., 59 Temple Place - Suite 330, | |
| 24 # Boston, MA 02111-1307, USA. | |
| 25 # | |
| 26 | |
| 27 package CodeGeneratorDart; | |
| 28 | |
| 29 use Class::Struct; | |
| 30 | |
| 31 my $outputDir = ""; | |
| 32 my $outputHeadersDir = ""; | |
| 33 | |
| 34 my @headerContent = (); | |
| 35 my %headerIncludes = (); | |
| 36 | |
| 37 my @allParents = (); | |
| 38 | |
| 39 my @customCallbackDeclarations = (); | |
| 40 my @implContentHeader = (); | |
| 41 my @implFixedHeader = (); | |
| 42 my @implContent = (); | |
| 43 my %implIncludes = (); | |
| 44 my @dartNatives = (); | |
| 45 | |
| 46 my @dartInterfaceContent = (); | |
| 47 my @dartImplContent = (); | |
| 48 | |
| 49 # Default .h template | |
| 50 my $headerTemplate = << "EOF"; | |
| 51 /* | |
| 52 This file is part of the WebKit open source project. | |
| 53 This file has been generated by generate-bindings.pl. DO NOT MODIFY! | |
| 54 | |
| 55 This library is free software; you can redistribute it and/or | |
| 56 modify it under the terms of the GNU Library General Public | |
| 57 License as published by the Free Software Foundation; either | |
| 58 version 2 of the License, or (at your option) any later version. | |
| 59 | |
| 60 This library is distributed in the hope that it will be useful, | |
| 61 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 62 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 63 Library General Public License for more details. | |
| 64 | |
| 65 You should have received a copy of the GNU Library General Public License | |
| 66 along with this library; see the file COPYING.LIB. If not, write to | |
| 67 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
| 68 Boston, MA 02111-1307, USA. | |
| 69 */ | |
| 70 EOF | |
| 71 | |
| 72 struct(NativeBindingDescriptor => { | |
| 73 cppCallbackName => '$', | |
| 74 nativeId => '$', | |
| 75 argumentCount => '$', | |
| 76 }); | |
| 77 | |
| 78 struct(IDLTypeInfoStruct => { | |
| 79 additionalInterfaces => '@', | |
| 80 superClass => '$', | |
| 81 auxilaryMethods => '@', | |
| 82 }); | |
| 83 | |
| 84 # Default constructor | |
| 85 sub new | |
| 86 { | |
| 87 my $object = shift; | |
| 88 | |
| 89 $codeGenerator = shift; | |
| 90 $outputDir = shift; | |
| 91 $outputHeadersDir = shift; | |
| 92 | |
| 93 my $reference = { }; | |
| 94 bless($reference, $object); | |
| 95 return $reference; | |
| 96 } | |
| 97 | |
| 98 sub finish | |
| 99 { | |
| 100 my ($object,) = @_; | |
| 101 | |
| 102 # Commit changes! | |
| 103 $object->WriteData(); | |
| 104 } | |
| 105 | |
| 106 sub GenerateModule | |
| 107 { | |
| 108 my ($object, $dataNode) = @_; | |
| 109 } | |
| 110 | |
| 111 sub GenerateInterface | |
| 112 { | |
| 113 my ($object, $dataNode, $defines) = @_; | |
| 114 | |
| 115 # Add parent classes (for multiple-inheritance) fields as needed. | |
| 116 @allParents = (); | |
| 117 $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode,
\@allParents, 0); | |
| 118 # Prepare internal structures. | |
| 119 $codeGenerator->LinkOverloadedFunctions($dataNode); | |
| 120 | |
| 121 # Start actual generation | |
| 122 if ($dataNode->extendedAttributes->{Callback}) { | |
| 123 $object->GenerateCallbackDartInterface($dataNode); | |
| 124 $object->GenerateCallbackHeader($dataNode); | |
| 125 $object->GenerateCallbackImplementation($dataNode); | |
| 126 } else { | |
| 127 $object->GenerateSource($dataNode); | |
| 128 $object->GenerateHeader($dataNode); | |
| 129 } | |
| 130 | |
| 131 my $name = $dataNode->name; | |
| 132 | |
| 133 # Open files for writing | |
| 134 my $headerFileName = "$outputHeadersDir/Dart${name}.h"; | |
| 135 my $implFileName = "$outputDir/Dart${name}.cpp"; | |
| 136 my $dartInterfaceFileName = "$outputHeadersDir/${name}.dart"; | |
| 137 my $dartImplFileName = "$outputHeadersDir/${name}Implementation.dart"; | |
| 138 | |
| 139 open($IMPL, ">$implFileName") || die "Couldn't open file $implFileName"; | |
| 140 open($HEADER, ">$headerFileName") || die "Couldn't open file $headerFileName
"; | |
| 141 open($DART_INTERFACE, ">$dartInterfaceFileName") || die "Couldn't open file
$dartInterfaceFileName"; | |
| 142 open($DART_IMPL, ">$dartImplFileName") || die "Couldn't open file $dartImplF
ileName"; | |
| 143 } | |
| 144 | |
| 145 # If the node has a [Conditional=XXX] attribute, returns an "ENABLE(XXX)" string
for use in an #if. | |
| 146 # FIXME: common with CodeGeneratorV8 | |
| 147 sub GenerateConditionalStringForAttributes | |
| 148 { | |
| 149 my ($attributes,) = @_; | |
| 150 | |
| 151 my $conditional = $attributes->{Conditional}; | |
| 152 if ($conditional) { | |
| 153 if ($conditional =~ /&/) { | |
| 154 return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) .
")"; | |
| 155 } elsif ($conditional =~ /\|/) { | |
| 156 return "ENABLE(" . join(") || ENABLE(", split(/\|/, $conditional)) .
")"; | |
| 157 } else { | |
| 158 return "ENABLE(" . $conditional . ")"; | |
| 159 } | |
| 160 } else { | |
| 161 return ""; | |
| 162 } | |
| 163 } | |
| 164 | |
| 165 sub GenerateConditionalString | |
| 166 { | |
| 167 my ($node,) = @_; | |
| 168 return GenerateConditionalStringForAttributes($node->extendedAttributes); | |
| 169 } | |
| 170 | |
| 171 sub GenerateCustomCallbackDeclaration | |
| 172 { | |
| 173 my ($callbackName) = @_; | |
| 174 return "void $callbackName(Dart_NativeArguments);"; | |
| 175 } | |
| 176 | |
| 177 sub ClassName | |
| 178 { | |
| 179 my ($interfaceName,) = @_; | |
| 180 return "Dart$interfaceName"; | |
| 181 } | |
| 182 | |
| 183 sub HasOverloads | |
| 184 { | |
| 185 my ($function,) = @_; | |
| 186 return 1 if @{$function->{overloads}} > 1; | |
| 187 } | |
| 188 | |
| 189 sub MaxOverloadParameterCount | |
| 190 { | |
| 191 my ($function,) = @_; | |
| 192 | |
| 193 my $maxParameterCount = 0; | |
| 194 foreach my $overload (@{$function->{overloads}}) { | |
| 195 my $parameterCount = @{$overload->parameters}; | |
| 196 $maxParameterCount = $maxParameterCount > $parameterCount ? $maxParamete
rCount : $parameterCount; | |
| 197 } | |
| 198 return $maxParameterCount; | |
| 199 } | |
| 200 | |
| 201 sub HasOptionalParameters | |
| 202 { | |
| 203 my ($function) = @_; | |
| 204 | |
| 205 # FIXME: useCapture was marked as optional upstream, however native | |
| 206 # implementation still requires all three parameters. JavaScript bindings | |
| 207 # have custom generation for addEventListener and removeEventListener. | |
| 208 return 0 if $function->signature->name eq "addEventListener" || $function->s
ignature->name eq "removeEventListener"; | |
| 209 | |
| 210 foreach my $parameter (@{$function->parameters}) { | |
| 211 return 1 if IsParameterOptionalInWebKit($parameter); | |
| 212 } | |
| 213 } | |
| 214 | |
| 215 sub HasCustomConstructor | |
| 216 { | |
| 217 my ($dataNode) = @_; | |
| 218 | |
| 219 # FIXME: switch to using CanBeConstructed attribute. | |
| 220 return 1 if $dataNode->name eq "FileReader"; | |
| 221 return 1 if $dataNode->name eq "XMLHttpRequest"; | |
| 222 return 1 if $dataNode->name eq "WebKitCSSMatrix"; | |
| 223 return 1 if $dataNode->name eq "WebKitPoint"; | |
| 224 | |
| 225 return 0; | |
| 226 } | |
| 227 | |
| 228 sub IsParameterOptionalInWebKit | |
| 229 { | |
| 230 my ($parameter) = @_; | |
| 231 | |
| 232 # Optional callbacks are not optional parameters in native implementations,
they always have a default value (0). | |
| 233 my $optional = $parameter->extendedAttributes->{Optional}; | |
| 234 return $optional && $optional ne "CallWithDefaultValue" && !$parameter->exte
ndedAttributes->{Callback}; | |
| 235 } | |
| 236 | |
| 237 my %renames = ( | |
| 238 "IDBCursor" => { | |
| 239 "continue" => "continueFunction", | |
| 240 }, | |
| 241 "IDBIndex" => { | |
| 242 "get" => "getObject", | |
| 243 }, | |
| 244 "IDBObjectStore" => { | |
| 245 "get" => "getObject", | |
| 246 }, | |
| 247 "Int8Array" => { | |
| 248 "set" => "setElements", | |
| 249 }, | |
| 250 "Int16Array" => { | |
| 251 "set" => "setElements", | |
| 252 }, | |
| 253 "Int32Array" => { | |
| 254 "set" => "setElements", | |
| 255 }, | |
| 256 "Uint8Array" => { | |
| 257 "set" => "setElements", | |
| 258 }, | |
| 259 "Uint16Array" => { | |
| 260 "set" => "setElements", | |
| 261 }, | |
| 262 "Uint32Array" => { | |
| 263 "set" => "setElements", | |
| 264 }, | |
| 265 "Float32Array" => { | |
| 266 "set" => "setElements", | |
| 267 }, | |
| 268 "Float64Array" => { | |
| 269 "set" => "setElements", | |
| 270 }, | |
| 271 "SVGFEMorphologyElement" => { | |
| 272 "operator" => "operatorValue", | |
| 273 }, | |
| 274 "SVGFECompositeElement" => { | |
| 275 "operator" => "operatorValue", | |
| 276 }, | |
| 277 "Console" => { | |
| 278 "assert" => "assert_", | |
| 279 }, | |
| 280 ); | |
| 281 | |
| 282 sub DartName | |
| 283 { | |
| 284 my ($interfaceName, $memberName) = @_; | |
| 285 return $memberName unless $renames{$interfaceName}; | |
| 286 my $class = $renames{$interfaceName}; | |
| 287 return $memberName unless $class->{$memberName}; | |
| 288 return $class->{$memberName}; | |
| 289 } | |
| 290 | |
| 291 # FIXME: eventually those should go away. | |
| 292 my %classesWithUnsupportedCustomGetters = ( | |
| 293 "Clipboard" => 1, | |
| 294 "Console" => 1, | |
| 295 "Coordinates" => 1, | |
| 296 "DeviceMotionEvent" => 1, | |
| 297 "DeviceOrientationEvent" => 1, | |
| 298 "FileReader" => 1, | |
| 299 "JavaScriptCallFrame" => 1, | |
| 300 "HTMLInputElement" => 1, | |
| 301 "HTMLOptionsCollection" => 1, | |
| 302 "HTMLOutputElement" => 1, | |
| 303 "ScriptProfileNode" => 1, | |
| 304 "WebKitAnimation" => 1, | |
| 305 ); | |
| 306 | |
| 307 sub IgnoredAttribute | |
| 308 { | |
| 309 my ($interfaceName, $attribute) = @_; | |
| 310 | |
| 311 # FIXME: reconsider if need to be supported in Dart bindings at all. | |
| 312 return 1 if $attribute->signature->type =~ /Constructor$/; | |
| 313 | |
| 314 # Attribute event listeners are not supported in Dart. | |
| 315 return 1 if $attribute->signature->type eq "EventListener"; | |
| 316 | |
| 317 # FIXME: support float[]. | |
| 318 return 1 if $attribute->signature->type eq "float[]"; | |
| 319 | |
| 320 # The only usage is HTMLIFrameElement.contentDocument. | |
| 321 return 1 if $attribute->signature->extendedAttributes->{CheckFrameSecurity}; | |
| 322 | |
| 323 return 1 if HasCustomGetter($attribute) && exists $classesWithUnsupportedCus
tomGetters{$interfaceName}; | |
| 324 | |
| 325 return 0; | |
| 326 } | |
| 327 | |
| 328 | |
| 329 sub HasSetter | |
| 330 { | |
| 331 my ($attribute,) = @_; | |
| 332 | |
| 333 return 0 if $attribute->type =~ /^readonly/; | |
| 334 # FIXME: Replaceable apparently means that the value can be overwritten by J
S and | |
| 335 # hence there is no correspondence to this in Dart. | |
| 336 return 0 if $attribute->signature->extendedAttributes->{"Replaceable"}; | |
| 337 return 1; | |
| 338 } | |
| 339 | |
| 340 | |
| 341 sub IgnoredCallback | |
| 342 { | |
| 343 my ($interfaceName, $function) = @_; | |
| 344 | |
| 345 # FIXME: WebGLContextEvent.initEvent overloads initEvent in base interface E
vent and adds | |
| 346 # another argument. | |
| 347 # In the current architecture it's difficult to solve as IDL files are proce
ssed one by one. | |
| 348 # As this is the only case, I'd suggest to put Custom attribute on WebGLCont
extEvent.initEvent. | |
| 349 return 1 if $interfaceName eq "WebGLContextEvent" && $function->signature->n
ame eq "initEvent"; | |
| 350 | |
| 351 # FIXME: implement callbacks with ScriptState. | |
| 352 my $callWith = $function->signature->extendedAttributes->{CallWith}; | |
| 353 return 1 if $callWith and $callWith eq "ScriptState"; | |
| 354 | |
| 355 return 0; | |
| 356 } | |
| 357 | |
| 358 # FIXME: Consider adding this to IDL as an attribute. | |
| 359 my %idlTypeToW3C = ( | |
| 360 "DOMWindow" => "Window", | |
| 361 "DOMCoreException" => "DOMException" | |
| 362 ); | |
| 363 | |
| 364 sub HasW3CName | |
| 365 { | |
| 366 my ($idlType,) = @_; | |
| 367 return 1 if exists $idlTypeToW3C{$idlType}; | |
| 368 return 0; | |
| 369 } | |
| 370 | |
| 371 sub IDLTypeToW3C | |
| 372 { | |
| 373 my ($idlType,) = @_; | |
| 374 return $idlTypeToW3C{$idlType} if exists $idlTypeToW3C{$idlType}; | |
| 375 return $idlType; | |
| 376 } | |
| 377 | |
| 378 my %idlTypeToDart = ( | |
| 379 "any" => "Object", | |
| 380 "boolean" => "bool", | |
| 381 "custom" => "Object", | |
| 382 "object" => "Object", | |
| 383 "Array" => "List", | |
| 384 "DOMObject" => "Object", | |
| 385 "DOMString" => "String", | |
| 386 "DOMString[]" => "DOMStringList", | |
| 387 "DOMTimeStamp" => "int", | |
| 388 "ObjectArray" => "List", | |
| 389 "SerializedScriptValue" => "Object", | |
| 390 "Date" => "Date", | |
| 391 "float" => "num", | |
| 392 "short" => "int", | |
| 393 "long" => "int", | |
| 394 "long long" => "int", | |
| 395 "unsigned int" => "int", | |
| 396 "unsigned short" => "int", | |
| 397 "unsigned long" => "int", | |
| 398 "unsigned long long" => "int", | |
| 399 "string" => "String", | |
| 400 "WebKitFlags" => "num", | |
| 401 ); | |
| 402 | |
| 403 my %primitiveDartTypes = ( | |
| 404 "int" => 1, | |
| 405 "String" => 1, | |
| 406 "Object" => 1, | |
| 407 "Date" => 1, | |
| 408 "SerializedScriptValue" => 1, | |
| 409 ); | |
| 410 | |
| 411 sub IDLTypeToDart | |
| 412 { | |
| 413 my ($idlType,) = @_; | |
| 414 return $idlTypeToDart{$idlType} if exists $idlTypeToDart{$idlType}; | |
| 415 return $idlType; | |
| 416 } | |
| 417 | |
| 418 # FIXME: pretty much %non_wrapper_types in CodeGeneratorV8. | |
| 419 my %nonWrapperTypes = ( | |
| 420 "CompareHow" => 1, | |
| 421 "EventListener" => 1, | |
| 422 "EventTarget" => 1, | |
| 423 "MediaQueryListListener" => 1, | |
| 424 "OptionsObject" => 1, | |
| 425 "VoidCallback" => 1, | |
| 426 "WebKitFlags" => 1, | |
| 427 ); | |
| 428 | |
| 429 sub IsIDLTypeWithDartBindings | |
| 430 { | |
| 431 my ($idlType,) = @_; | |
| 432 | |
| 433 return 0 if exists $idlTypeToDart{$idlType}; | |
| 434 return 0 if exists $primitiveDartTypes{$idlType}; | |
| 435 return 0 if !IsRefPtrType(IDLTypeToDart($idlType)); | |
| 436 return 0 if exists $nonWrapperTypes{$idlType}; | |
| 437 | |
| 438 return 1; | |
| 439 } | |
| 440 | |
| 441 sub ParameterAdapterType | |
| 442 { | |
| 443 my ($idlType,) = @_; | |
| 444 | |
| 445 my $webkitParameterType = IDLTypeToWebkit($idlType); | |
| 446 | |
| 447 my $suffix = ""; | |
| 448 if (IsIDLTypeWithDartBindings($idlType)) { | |
| 449 my $bindingsClass = ClassName($idlType); | |
| 450 $implIncludes{"$bindingsClass.h"} = 1; | |
| 451 $suffix = ", $bindingsClass"; | |
| 452 } | |
| 453 | |
| 454 return "ParameterAdapter< $webkitParameterType$suffix >"; | |
| 455 } | |
| 456 | |
| 457 # FIXME: common with CodeGeneratorV8 | |
| 458 sub GetNativeTypeForConversions | |
| 459 { | |
| 460 my ($type,) = @_; | |
| 461 $type = $codeGenerator->GetSVGTypeNeedingTearOff($type) if $codeGenerator->I
sSVGTypeNeedingTearOff($type); | |
| 462 return $type; | |
| 463 } | |
| 464 | |
| 465 | |
| 466 sub AddHeaderForIDLType | |
| 467 { | |
| 468 my ($idlType, $includes) = @_; | |
| 469 | |
| 470 $idlType =~ s/Abs|Rel// if $idlType =~ /SVGPathSeg/; | |
| 471 | |
| 472 return if $codeGenerator->IsPrimitiveType($idlType); | |
| 473 | |
| 474 return if exists $primitiveDartTypes{IDLTypeToDart($idlType)}; | |
| 475 | |
| 476 return if $codeGenerator->AvoidInclusionOfType($idlType); | |
| 477 | |
| 478 return if $idlType eq "CompareHow"; | |
| 479 | |
| 480 $includes->{"$idlType.h"} = 1; | |
| 481 $includes->{"SVGPropertyTearOff.h"} = 1 if $codeGenerator->IsSVGTypeNeedingT
earOff($idlType); | |
| 482 } | |
| 483 | |
| 484 # FIXME: common with CodeGeneratorV8 | |
| 485 sub AddHeaderClassIncludes | |
| 486 { | |
| 487 my ($idlType,) = @_; | |
| 488 | |
| 489 AddHeaderForIDLType($idlType, \%headerIncludes); | |
| 490 | |
| 491 $headerIncludes{"DartDOMWrapper.h"} = 1; | |
| 492 } | |
| 493 | |
| 494 sub GenerateIncludes | |
| 495 { | |
| 496 return map { "#include " . (/wtf|dart_api\.h/ ? "<$_>" : "\"$_\"") . "\n"; }
sort(@_); | |
| 497 } | |
| 498 | |
| 499 my %withCustomConverters = ( | |
| 500 "DOMWindow" => 1, | |
| 501 "Element" => 1, | |
| 502 "HTMLElement" => 1, | |
| 503 "SVGElement" => 1, | |
| 504 ); | |
| 505 | |
| 506 sub RequiresCustomToDartConverter | |
| 507 { | |
| 508 my ($dataNode,) = @_; | |
| 509 | |
| 510 return 1 if $dataNode->extendedAttributes->{CustomToJS}; | |
| 511 return 1 if $dataNode->extendedAttributes->{PureInterface}; | |
| 512 return exists $withCustomConverters{$dataNode->name}; | |
| 513 } | |
| 514 | |
| 515 sub GenerateHeader | |
| 516 { | |
| 517 my ($object, $dataNode) = @_; | |
| 518 | |
| 519 my $interfaceName = $dataNode->name; | |
| 520 my $className = ClassName($interfaceName); | |
| 521 my $webkitClassName = GetNativeTypeForConversions($interfaceName); | |
| 522 | |
| 523 my $conditionalString = GenerateConditionalString($dataNode); | |
| 524 | |
| 525 my $toDartValue = ""; | |
| 526 if (!RequiresCustomToDartConverter($dataNode)) { | |
| 527 $toDartValue = <<END; | |
| 528 inline Dart_Handle toDartValue($webkitClassName* value) | |
| 529 { | |
| 530 return DartDOMWrapper::toDart<$className>(value); | |
| 531 } | |
| 532 END | |
| 533 } else { | |
| 534 $toDartValue = <<END; | |
| 535 Dart_Handle toDartValue($webkitClassName*); | |
| 536 END | |
| 537 } | |
| 538 | |
| 539 $toDartValue .= <<END; | |
| 540 inline Dart_Handle toDartValue(PassRefPtr< $webkitClassName > value) | |
| 541 { | |
| 542 return toDartValue(value.get()); | |
| 543 } | |
| 544 END | |
| 545 | |
| 546 my $customCallbackDeclarations = join("\n\n", @customCallbackDeclarations); | |
| 547 | |
| 548 push(@headerContent, $headerTemplate); | |
| 549 | |
| 550 push(@headerContent, "\n#if ${conditionalString}\n") if $conditionalString; | |
| 551 push(@headerContent, <<END); | |
| 552 | |
| 553 #ifndef ${className}_h | |
| 554 #define ${className}_h | |
| 555 | |
| 556 END | |
| 557 | |
| 558 AddHeaderClassIncludes($interfaceName); | |
| 559 | |
| 560 $headerIncludes{"dart_api.h"} = 1; | |
| 561 push(@headerContent, GenerateIncludes(keys(%headerIncludes))); | |
| 562 | |
| 563 push(@headerContent, <<END); | |
| 564 | |
| 565 namespace WebCore { | |
| 566 | |
| 567 struct $className { | |
| 568 static const char* const dartImplementationClassName; | |
| 569 typedef $webkitClassName NativeType; | |
| 570 | |
| 571 static PassRefPtr<NativeType> toNative(Dart_Handle handle, Dart_Handle& exce
ption) | |
| 572 { | |
| 573 return DartDOMWrapper::unwrapDartWrapper<$className>(handle, exception); | |
| 574 } | |
| 575 | |
| 576 static Dart_NativeFunction resolver(Dart_Handle name, int argumentCount); | |
| 577 }; | |
| 578 | |
| 579 $toDartValue | |
| 580 namespace Dart${interfaceName}Internal { | |
| 581 | |
| 582 $customCallbackDeclarations | |
| 583 | |
| 584 } | |
| 585 | |
| 586 } | |
| 587 | |
| 588 #endif // ${className}_h | |
| 589 END | |
| 590 | |
| 591 push(@headerContent, "\n#endif // ${conditionalString}\n") if $conditionalSt
ring; | |
| 592 } | |
| 593 | |
| 594 sub HasCustomGetter | |
| 595 { | |
| 596 my ($attribute,) = @_; | |
| 597 my $extendedAttributes = $attribute->signature->extendedAttributes; | |
| 598 return $extendedAttributes->{"CustomGetter"} || $extendedAttributes->{"Custo
m"}; | |
| 599 } | |
| 600 | |
| 601 sub HasCustomSetter | |
| 602 { | |
| 603 my ($attribute,) = @_; | |
| 604 my $extendedAttributes = $attribute->signature->extendedAttributes; | |
| 605 return $extendedAttributes->{"CustomSetter"} || $extendedAttributes->{"Custo
m"} || $extendedAttributes->{"V8CustomSetter"}; | |
| 606 } | |
| 607 | |
| 608 sub WithTearOffNotList | |
| 609 { | |
| 610 my ($interfaceName) = @_; | |
| 611 | |
| 612 return ($codeGenerator->IsSVGTypeNeedingTearOff($interfaceName) and (not ($i
nterfaceName =~ /List$/))); | |
| 613 } | |
| 614 | |
| 615 sub PrepareInvocation | |
| 616 { | |
| 617 my ($receiver, $interfaceName, $invocationPrefix, $invocationParameters) = @
_; | |
| 618 | |
| 619 my $invocationPostfix; | |
| 620 $receiver .= "->"; | |
| 621 if ($interfaceName eq "SVGNumber") { | |
| 622 $receiver .= "propertyReference()"; | |
| 623 if ($invocationPrefix =~ /^setValue/) { | |
| 624 $invocationPrefix = " = "; | |
| 625 } else { | |
| 626 $invocationPrefix = ""; | |
| 627 } | |
| 628 $invocationPostfix = ""; | |
| 629 } else { | |
| 630 $receiver .= "propertyReference()." if WithTearOffNotList($interfaceName
); | |
| 631 $invocationPostfix = ")"; | |
| 632 } | |
| 633 return "$receiver$invocationPrefix$invocationParameters$invocationPostfix"; | |
| 634 } | |
| 635 | |
| 636 my %svgPrimitiveTypes = ( | |
| 637 "SVGAngle" => 1, | |
| 638 "SVGLength" => 1, | |
| 639 "SVGMatrix" => 1, | |
| 640 "SVGNumber" => 1, | |
| 641 "SVGPoint" => 1, | |
| 642 "SVGRect" => 1, | |
| 643 "SVGTransform" => 1); | |
| 644 | |
| 645 sub ProcessInvocationResult | |
| 646 { | |
| 647 my ($invocation, $interfaceName, $returnType) = @_; | |
| 648 my $svgNativeReturnType = $codeGenerator->GetSVGTypeNeedingTearOff($returnTy
pe); | |
| 649 | |
| 650 return $invocation if (not $svgNativeReturnType); | |
| 651 | |
| 652 return "static_cast<${svgNativeReturnType}*>(${invocation})" if ($interfaceN
ame =~ /^SVGAnimated/); | |
| 653 | |
| 654 return "${svgNativeReturnType}::create(receiver, ${invocation})" if ($return
Type eq "SVGStringList"); | |
| 655 | |
| 656 return "static_cast<${svgNativeReturnType}*>(${invocation}.get())" if ($inte
rfaceName =~ /List$/); | |
| 657 | |
| 658 if (exists $svgPrimitiveTypes{$returnType}) { | |
| 659 return "${svgNativeReturnType}::create(${invocation})"; | |
| 660 } else { | |
| 661 return "static_cast<${svgNativeReturnType}*>(${invocation})"; | |
| 662 } | |
| 663 } | |
| 664 | |
| 665 sub GenerateGenericBindingsFunction | |
| 666 { | |
| 667 my ($name, $interfaceName, $functionName, $constantParameters, $parameters,
$returnType, $raisesExceptions, $attributes, $isSetter) = @_; | |
| 668 | |
| 669 my $webkitClassName = GetNativeTypeForConversions($interfaceName); | |
| 670 my $invocationPrefix = "$functionName("; | |
| 671 | |
| 672 my $exceptionManagementPrologue = ""; | |
| 673 my $exceptionManagementEpilogue = ""; | |
| 674 if (@{$parameters} || $raisesExceptions || $attributes->{CustomArgumentHandl
ing}) { | |
| 675 $exceptionManagementPrologue = <<END; | |
| 676 Dart_Handle exception; | |
| 677 END | |
| 678 $exceptionManagementEpilogue = <<END; | |
| 679 | |
| 680 fail: | |
| 681 Dart_ThrowException(exception); | |
| 682 ASSERT_NOT_REACHED(); | |
| 683 END | |
| 684 } | |
| 685 | |
| 686 my @defineInvocationParameters = (); | |
| 687 my @invocationParameters = @{$constantParameters}; | |
| 688 | |
| 689 my $callWith = $attributes->{CallWith}; | |
| 690 if ($callWith) { | |
| 691 # Generate code for "CallWith" parameter. | |
| 692 if ($callWith eq "ScriptExecutionContext") { | |
| 693 push(@defineInvocationParameters, <<END); | |
| 694 ScriptExecutionContext* context = DartUtilities::scriptExecutionContext(
); | |
| 695 if (!context) | |
| 696 return; | |
| 697 END | |
| 698 push(@invocationParameters, "context"); | |
| 699 } | |
| 700 } | |
| 701 | |
| 702 # Generate code for parameters conversion. | |
| 703 my $parameterCount = @$parameters; | |
| 704 foreach my $parameterIndex (0..$parameterCount - 1) { | |
| 705 my $parameter = @$parameters[$parameterIndex]; | |
| 706 my $parameterType = $parameter->type; | |
| 707 $parameterType = "DOMStringList" if $parameterType eq "DOMString[]"; | |
| 708 AddHeaderForIDLType($parameterType, \%implIncludes); | |
| 709 my $name = $parameter->name; | |
| 710 my $parameterAdapterType = ParameterAdapterType($parameterType); | |
| 711 my $dartArgumentIndex = $parameterIndex + 1; # 0 is for the receiver. | |
| 712 my @adapterParameters = ("Dart_GetNativeArgument(args, $dartArgumentInde
x)"); | |
| 713 my $adapterParameters = join(", ", @adapterParameters); | |
| 714 push(@defineInvocationParameters, <<END); | |
| 715 const $parameterAdapterType $name($adapterParameters); | |
| 716 if (!$name.conversionSuccessful()) { | |
| 717 exception = $name.exception(); | |
| 718 goto fail; | |
| 719 } | |
| 720 END | |
| 721 } | |
| 722 @invocationParameters = (@invocationParameters, map { $_->name; } @{$paramet
ers}); | |
| 723 | |
| 724 if ($attributes->{CustomArgumentHandling}) { | |
| 725 $implIncludes{"ScriptArguments.h"} = 1; | |
| 726 $implIncludes{"ScriptCallStack.h"} = 1; | |
| 727 $implIncludes{"V8Proxy.h"} = 1; | |
| 728 $implIncludes{"v8.h"} = 1; | |
| 729 my $customArgument = $parameterCount + 1; | |
| 730 push(@defineInvocationParameters, <<END); | |
| 731 v8::HandleScope handleScope; | |
| 732 v8::Context::Scope scope(V8Proxy::mainWorldContext(DartUtilities::domWin
dowForCurrentIsolate()->frame())); | |
| 733 | |
| 734 Dart_Handle customArgument = Dart_GetNativeArgument(args, $customArgumen
t); | |
| 735 RefPtr<ScriptArguments> scriptArguments(DartUtilities::createScriptArgum
ents(customArgument, exception)); | |
| 736 if (!scriptArguments) | |
| 737 goto fail; | |
| 738 | |
| 739 RefPtr<ScriptCallStack> scriptCallStack(DartUtilities::createScriptCallS
tack()); | |
| 740 if (!scriptCallStack->size()) | |
| 741 return; | |
| 742 END | |
| 743 push(@invocationParameters, "scriptArguments", "scriptCallStack"); | |
| 744 } | |
| 745 | |
| 746 if ($attributes->{NeedsUserGestureCheck}) { | |
| 747 push(@invocationParameters, "DartUtilities::processingUserGesture()"); | |
| 748 } | |
| 749 | |
| 750 if ($raisesExceptions) { | |
| 751 push(@invocationParameters, "ec"); | |
| 752 } | |
| 753 | |
| 754 my $defineInvocationParameters = join "", @defineInvocationParameters; | |
| 755 my $invocationParameters = join ", ", @invocationParameters; | |
| 756 my $invocation = PrepareInvocation("receiver", $interfaceName, $invocationPr
efix, $invocationParameters); | |
| 757 # Generate code for setting return value. | |
| 758 my $invocationAndReturn = <<END; | |
| 759 $invocation; | |
| 760 END | |
| 761 if ($returnType ne "void") { | |
| 762 $invocation = ProcessInvocationResult($invocation, $interfaceName, $retu
rnType); | |
| 763 my $dartType = IDLTypeToDart($returnType); | |
| 764 if (!$codeGenerator->IsPrimitiveType($returnType) && !exists $primitiveD
artTypes{$dartType}) { | |
| 765 $implIncludes{"@{[ClassName($dartType)]}.h"} = 1; | |
| 766 } | |
| 767 $invocation = "static_pointer_cast<SVGAnimatedEnumeration>($invocation)"
if $returnType eq "SVGAnimatedEnumeration"; | |
| 768 # FIXME: this is too simplistic for long return types, reconsider. | |
| 769 $invocation = "static_cast<int64_t>($invocation)" if $dartType eq "int"; | |
| 770 # There is GC3Dboolean which is not a bool, but unsigned char for OpenGL
compatibility. | |
| 771 $invocation = "static_cast<bool>($invocation)" if $dartType eq "bool"; | |
| 772 $conversion = ($codeGenerator->IsStringType($returnType) and defined | |
| 773 $attributes->{ConvertNullStringTo}) ? ", ConvertDefaultToNull" : ""; | |
| 774 $invocationAndReturn = <<END; | |
| 775 Dart_Handle returnValue = toDartValue($invocation$conversion); | |
| 776 if (returnValue) | |
| 777 Dart_SetReturnValue(args, returnValue); | |
| 778 END | |
| 779 } | |
| 780 | |
| 781 my $webkitInvocation = $invocationAndReturn; | |
| 782 if ($raisesExceptions) { | |
| 783 $implIncludes{"ExceptionCode.h"} = 1; | |
| 784 $webkitInvocation = <<END; | |
| 785 ExceptionCode ec = 0; | |
| 786 $invocationAndReturn; | |
| 787 if (UNLIKELY(ec)) { | |
| 788 exception = DartDOMWrapper::exceptionCodeToDartException(ec); | |
| 789 goto fail; | |
| 790 } | |
| 791 END | |
| 792 } | |
| 793 | |
| 794 my $conditionalString = GenerateConditionalStringForAttributes($attributes); | |
| 795 if ($conditionalString) { | |
| 796 push(@implContent, <<END); | |
| 797 #if $conditionalString | |
| 798 END | |
| 799 } | |
| 800 | |
| 801 push(@implContent, <<END); | |
| 802 static void $name(Dart_NativeArguments args) | |
| 803 { | |
| 804 DartApiScope dartApiScope; | |
| 805 $exceptionManagementPrologue { | |
| 806 $webkitClassName* receiver = DartDOMWrapper::receiver< $webkitClassName
>(args); | |
| 807 $defineInvocationParameters | |
| 808 $webkitInvocation return; | |
| 809 } | |
| 810 $exceptionManagementEpilogue} | |
| 811 | |
| 812 END | |
| 813 | |
| 814 if ($conditionalString) { | |
| 815 push(@implContent, <<END); | |
| 816 #else | |
| 817 static void $name(Dart_NativeArguments args) | |
| 818 { | |
| 819 DartApiScope dartApiScope; | |
| 820 Dart_ThrowException(DartUtilities::conditionalFunctionalityException()); | |
| 821 } | |
| 822 #endif | |
| 823 | |
| 824 END | |
| 825 } | |
| 826 } | |
| 827 | |
| 828 # FIXME: copied from CodeGeneratorV8.pm | |
| 829 sub IsRefPtrType | |
| 830 { | |
| 831 my ($type,) = @_; | |
| 832 | |
| 833 return 0 if $type eq "boolean"; | |
| 834 return 0 if $type eq "float"; | |
| 835 return 0 if $type eq "int"; | |
| 836 return 0 if $type eq "Date"; | |
| 837 return 0 if $type eq "DOMString"; | |
| 838 return 0 if $type eq "double"; | |
| 839 return 0 if $type eq "short"; | |
| 840 return 0 if $type eq "long"; | |
| 841 return 0 if $type eq "unsigned"; | |
| 842 return 0 if $type eq "unsigned long"; | |
| 843 return 0 if $type eq "unsigned short"; | |
| 844 | |
| 845 return 1; | |
| 846 } | |
| 847 | |
| 848 # FIXME: partially copied from GetNativeType of CodeGeneratorV8.pm | |
| 849 sub IDLTypeToWebkit | |
| 850 { | |
| 851 my ($type, $isParameter) = @_; | |
| 852 | |
| 853 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($type); | |
| 854 if ($svgNativeType) { | |
| 855 if ($svgNativeType =~ /List$/) { | |
| 856 return "${svgNativeType}*"; | |
| 857 } else { | |
| 858 return "RefPtr<${svgNativeType} >"; | |
| 859 } | |
| 860 } | |
| 861 | |
| 862 if ($type eq "float" or $type eq "double") { | |
| 863 return $type; | |
| 864 } | |
| 865 | |
| 866 return ($isParameter ? "const String&" : "String") if ($type eq "DOMString"
or $type eq "DOMUserData"); | |
| 867 return "int" if $type eq "int"; | |
| 868 return "int" if $type eq "short" or $type eq "unsigned short"; | |
| 869 return "unsigned" if $type eq "unsigned long"; | |
| 870 return "int" if $type eq "long"; | |
| 871 return "long long" if $type eq "long long"; | |
| 872 return "unsigned long long" if $type eq "unsigned long long"; | |
| 873 return "bool" if $type eq "boolean"; | |
| 874 return "Range::CompareHow" if $type eq "CompareHow"; | |
| 875 return "DOMTimeStamp" if $type eq "DOMTimeStamp"; | |
| 876 return "unsigned" if $type eq "unsigned int"; | |
| 877 # FIXME: EventTarget are evils! | |
| 878 # return "Node*" if $type eq "EventTarget" and $isParameter; | |
| 879 return "double" if $type eq "Date"; | |
| 880 return "ScriptValue" if $type eq "DOMObject"; | |
| 881 return "OptionsObject" if $type eq "OptionsObject"; | |
| 882 | |
| 883 # temporary hack | |
| 884 return "RefPtr<NodeFilter>" if $type eq "NodeFilter"; | |
| 885 | |
| 886 return "RefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValue"; | |
| 887 | |
| 888 return "RefPtr<IDBKey>" if $type eq "IDBKey"; | |
| 889 | |
| 890 # necessary as resolvers could be constructed on fly. | |
| 891 return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver"; | |
| 892 | |
| 893 return ($isParameter ? "${type}*" : "RefPtr<${type}>") if IsRefPtrType($type
); | |
| 894 | |
| 895 return "RefPtr<DOMStringList>" if $type eq "DOMStringList"; | |
| 896 | |
| 897 return "RefPtr<MediaQueryListListener>" if $type eq "MediaQueryListListener"
; | |
| 898 | |
| 899 # Default, assume native type is a pointer with same type name as idl type | |
| 900 return "${type}*"; | |
| 901 } | |
| 902 | |
| 903 sub GenerateResolver | |
| 904 { | |
| 905 my ($interfaceName,) = @_; | |
| 906 | |
| 907 my $className = ClassName($interfaceName); | |
| 908 | |
| 909 push(@implContent, <<END); | |
| 910 | |
| 911 Dart_NativeFunction ${className}::resolver(Dart_Handle name, int argumentCount) | |
| 912 { | |
| 913 String str = DartUtilities::dartStringToString(name); | |
| 914 | |
| 915 END | |
| 916 | |
| 917 foreach my $nativeDescriptor (@dartNatives) { | |
| 918 my $cppCallbackName = $nativeDescriptor->cppCallbackName; | |
| 919 my $nativeId = $nativeDescriptor->nativeId; | |
| 920 my $argumentCount = $nativeDescriptor->argumentCount; | |
| 921 push(@implContent, <<END); | |
| 922 if ($argumentCount == argumentCount && str == "$nativeId") | |
| 923 return Dart${interfaceName}Internal::$cppCallbackName; | |
| 924 END | |
| 925 } | |
| 926 | |
| 927 push(@implContent, <<END); | |
| 928 return 0; | |
| 929 } | |
| 930 | |
| 931 END | |
| 932 } | |
| 933 | |
| 934 sub GenerateDartImplementationClassname | |
| 935 { | |
| 936 my ($interfaceName,) = @_; | |
| 937 | |
| 938 my $className = ClassName($interfaceName); | |
| 939 | |
| 940 push(@implContent, <<END); | |
| 941 | |
| 942 const char* const ${className}::dartImplementationClassName = "${interfaceName}I
mplementation"; | |
| 943 END | |
| 944 } | |
| 945 | |
| 946 sub GenerateImplementationPrologue | |
| 947 { | |
| 948 my ($dataNode) = @_; | |
| 949 | |
| 950 my $interfaceName = $dataNode->name; | |
| 951 my $className = ClassName($interfaceName); | |
| 952 my $internalNamespaceName = "Dart${interfaceName}Internal"; | |
| 953 | |
| 954 my $conditionalString = GenerateConditionalString($dataNode); | |
| 955 | |
| 956 push(@implContentHeader, $headerTemplate); | |
| 957 | |
| 958 push(@implContentHeader, <<END); | |
| 959 | |
| 960 #include "config.h" | |
| 961 #include "$className.h" | |
| 962 | |
| 963 END | |
| 964 | |
| 965 push(@implContentHeader, "#if $conditionalString\n\n") if $conditionalString
; | |
| 966 | |
| 967 $implIncludes{"DartBindingsCommonIncludes.h"} = 1; | |
| 968 | |
| 969 push(@implContent, <<END); | |
| 970 namespace WebCore { | |
| 971 | |
| 972 namespace $internalNamespaceName { | |
| 973 END | |
| 974 } | |
| 975 | |
| 976 sub GenerateImplementationEpilogue | |
| 977 { | |
| 978 my ($dataNode) = @_; | |
| 979 | |
| 980 my $interfaceName = $dataNode->name; | |
| 981 my $className = ClassName($interfaceName); | |
| 982 my $internalNamespaceName = "Dart${interfaceName}Internal"; | |
| 983 | |
| 984 my $conditionalString = GenerateConditionalString($dataNode); | |
| 985 | |
| 986 push(@implContent, "}\n"); | |
| 987 | |
| 988 GenerateResolver($interfaceName); | |
| 989 GenerateDartImplementationClassname($interfaceName); | |
| 990 | |
| 991 push(@implContent, <<END); | |
| 992 } | |
| 993 END | |
| 994 | |
| 995 push(@implContent, "\n#endif // $conditionalString\n") if $conditionalString
; | |
| 996 | |
| 997 # We've already added the header for this file in implFixedHeader, so remove | |
| 998 # it from implIncludes to ensure we don't #include it twice. | |
| 999 delete $implIncludes{"$className.h"}; | |
| 1000 } | |
| 1001 | |
| 1002 sub GenerateCallbackDartInterface | |
| 1003 { | |
| 1004 my ($object, $dataNode) = @_; | |
| 1005 my $function = $dataNode->functions->[0]; | |
| 1006 my $functionDecl = DartInterfaceMethodDeclaration($interfaceName, $function,
$dataNode->name); | |
| 1007 push(@dartInterfaceContent, $headerTemplate); | |
| 1008 push(@dartInterfaceContent, <<END); | |
| 1009 typedef $functionDecl; | |
| 1010 END | |
| 1011 } | |
| 1012 | |
| 1013 sub FormatCallbackArgument | |
| 1014 { | |
| 1015 my ($argument,) = @_; | |
| 1016 my $webkitType = IDLTypeToWebkit($argument->type, 1); | |
| 1017 my $name = $argument->name; | |
| 1018 return "$webkitType $name"; | |
| 1019 } | |
| 1020 | |
| 1021 sub GenerateCallbackHeader | |
| 1022 { | |
| 1023 my ($object, $dataNode) = @_; | |
| 1024 | |
| 1025 my $interfaceName = $dataNode->name; | |
| 1026 my $className = ClassName($interfaceName); | |
| 1027 my $webkitClassName = GetNativeTypeForConversions($interfaceName); | |
| 1028 | |
| 1029 my $conditionalString = GenerateConditionalString($dataNode); | |
| 1030 | |
| 1031 push(@headerContent, $headerTemplate); | |
| 1032 | |
| 1033 push(@headerContent, "\n#if ${conditionalString}\n") if $conditionalString; | |
| 1034 push(@headerContent, <<END); | |
| 1035 | |
| 1036 #ifndef ${className}_h | |
| 1037 #define ${className}_h | |
| 1038 | |
| 1039 END | |
| 1040 | |
| 1041 AddHeaderClassIncludes($interfaceName); | |
| 1042 | |
| 1043 $headerIncludes{"ActiveDOMCallback.h"} = 1; | |
| 1044 $headerIncludes{"DartCallback.h"} = 1; | |
| 1045 push(@headerContent, GenerateIncludes(keys(%headerIncludes))); | |
| 1046 | |
| 1047 my @handleEventMethods = (); | |
| 1048 foreach my $function (@{$dataNode->functions}) { | |
| 1049 die "Expect only handleEvent methods" if ($function->signature->type ne
"boolean") || ($function->signature->name ne "handleEvent"); | |
| 1050 | |
| 1051 my $arguments = join ", ", map { FormatCallbackArgument($_); } @{$functi
on->parameters}; | |
| 1052 push(@handleEventMethods, " virtual bool handleEvent($arguments);"); | |
| 1053 } | |
| 1054 my $methods = join "\n", @handleEventMethods; | |
| 1055 | |
| 1056 push(@headerContent, <<END); | |
| 1057 | |
| 1058 namespace WebCore { | |
| 1059 | |
| 1060 class ScriptExecutionContext; | |
| 1061 | |
| 1062 class $className : public $interfaceName, public ActiveDOMCallback { | |
| 1063 public: | |
| 1064 typedef $interfaceName NativeType; | |
| 1065 | |
| 1066 static PassRefPtr<NativeType> toNative(Dart_Handle object, Dart_Handle& exce
ption) | |
| 1067 { | |
| 1068 return adoptRef(new $className(object, exception, DartUtilities::scriptE
xecutionContext())); | |
| 1069 } | |
| 1070 | |
| 1071 $methods | |
| 1072 | |
| 1073 private: | |
| 1074 $className(Dart_Handle object, Dart_Handle& exception, ScriptExecutionContex
t* context) | |
| 1075 : ActiveDOMCallback(context) | |
| 1076 , m_callback(object, exception) | |
| 1077 { | |
| 1078 } | |
| 1079 | |
| 1080 DartCallback m_callback; | |
| 1081 }; | |
| 1082 | |
| 1083 } | |
| 1084 | |
| 1085 #endif // ${className}_h | |
| 1086 END | |
| 1087 | |
| 1088 push(@headerContent, "\n#endif // ${conditionalString}\n") if $conditionalSt
ring; | |
| 1089 } | |
| 1090 | |
| 1091 sub GenerateCallbackImplementation | |
| 1092 { | |
| 1093 my ($object, $dataNode) = @_; | |
| 1094 | |
| 1095 my $interfaceName = $dataNode->name; | |
| 1096 my $className = ClassName($interfaceName); | |
| 1097 my $internalNamespaceName = "Dart${interfaceName}Internal"; | |
| 1098 | |
| 1099 my $conditionalString = GenerateConditionalString($dataNode); | |
| 1100 | |
| 1101 push(@implContentHeader, $headerTemplate); | |
| 1102 | |
| 1103 $implIncludes{"DartBindingsCommonIncludes.h"} = 1; | |
| 1104 | |
| 1105 push(@implContentHeader, <<END); | |
| 1106 | |
| 1107 #include "config.h" | |
| 1108 #include "$className.h" | |
| 1109 | |
| 1110 END | |
| 1111 | |
| 1112 push(@implContentHeader, "#if $conditionalString\n\n") if $conditionalString
; | |
| 1113 | |
| 1114 my @handleEventMethods = (); | |
| 1115 foreach my $function (@{$dataNode->functions}) { | |
| 1116 die "Expect only handleEvent methods" if ($function->signature->type ne
"boolean") || ($function->signature->name ne "handleEvent"); | |
| 1117 | |
| 1118 my $arguments = join ", ", map { FormatCallbackArgument($_); } @{$functi
on->parameters}; | |
| 1119 my $parameters = join ", ", map { $_->name; } @{$function->parameters}; | |
| 1120 push(@handleEventMethods, <<END); | |
| 1121 bool ${className}::handleEvent($arguments) | |
| 1122 { | |
| 1123 return m_callback.handleEvent($parameters); | |
| 1124 } | |
| 1125 END | |
| 1126 } | |
| 1127 my $methods = join "\n", @handleEventMethods; | |
| 1128 | |
| 1129 push(@implContent, <<END); | |
| 1130 namespace WebCore { | |
| 1131 | |
| 1132 $methods | |
| 1133 | |
| 1134 } | |
| 1135 END | |
| 1136 | |
| 1137 push(@implContent, "\n#endif // $conditionalString\n") if $conditionalString
; | |
| 1138 | |
| 1139 # We've already added the header for this file in implFixedHeader, so remove | |
| 1140 # it from implIncludes to ensure we don't #include it twice. | |
| 1141 delete $implIncludes{"$className.h"}; | |
| 1142 } | |
| 1143 | |
| 1144 sub DartMethodDeclaration | |
| 1145 { | |
| 1146 my ($functionName, $parameters, $returnType) = @_; | |
| 1147 | |
| 1148 $returnType = IDLTypeToDart($codeGenerator->StripModule($returnType)); | |
| 1149 return "$returnType $functionName($parameters)"; | |
| 1150 } | |
| 1151 | |
| 1152 sub DartInterfaceMethodDeclaration | |
| 1153 { | |
| 1154 my ($interfaceName, $function, $name) = @_; | |
| 1155 | |
| 1156 my $parameters; | |
| 1157 if (HasOverloads($function)) { | |
| 1158 my $maxParameterCount = MaxOverloadParameterCount($function); | |
| 1159 $parameters = DartAnonymousNamedOptionalParameters($maxParameterCount); | |
| 1160 } else { | |
| 1161 $parameters = DartParameters($function, $function->parameters, 1); | |
| 1162 } | |
| 1163 return DartMethodDeclaration($name || DartName($interfaceName, $function->si
gnature->name), $parameters, $function->signature->type); | |
| 1164 } | |
| 1165 | |
| 1166 sub DartParameters | |
| 1167 { | |
| 1168 my ($function, $parameters, $useDefaultValues) = @_; | |
| 1169 | |
| 1170 my @mandatoryParameters = (); | |
| 1171 my @optionalParameters = (); | |
| 1172 foreach my $parameter (@{$parameters}) { | |
| 1173 # FIXME: parameter modifiers. | |
| 1174 my $type = IDLTypeToDart($parameter->type); | |
| 1175 my $name = $parameter->name; | |
| 1176 if ($useDefaultValues && IsParameterOptionalInWebKit($parameter)) { | |
| 1177 push(@optionalParameters, "$type ${name}"); | |
| 1178 } else { | |
| 1179 push(@mandatoryParameters, "$type ${name}"); | |
| 1180 } | |
| 1181 } | |
| 1182 if ($function->signature->extendedAttributes->{CustomArgumentHandling}) { | |
| 1183 die "Optional parameters in function with custom argument handling. " if
@optionalParameters; | |
| 1184 push(@mandatoryParameters, "argument"); | |
| 1185 } | |
| 1186 my $dartParameters = join(", ", @mandatoryParameters); | |
| 1187 if (@optionalParameters) { | |
| 1188 $dartParameters .= ", " if $dartParameters; | |
| 1189 $dartParameters .= "[" . join(", ", @optionalParameters) . "]"; | |
| 1190 } | |
| 1191 return $dartParameters; | |
| 1192 } | |
| 1193 | |
| 1194 sub DartParameterCount | |
| 1195 { | |
| 1196 my ($function, $parameters) = @_; | |
| 1197 | |
| 1198 my $parameterCount = @{$parameters}; | |
| 1199 $parameterCount += 1 if $function->signature->extendedAttributes->{CustomArg
umentHandling}; | |
| 1200 return $parameterCount; | |
| 1201 } | |
| 1202 | |
| 1203 sub DartAnonymousArguments | |
| 1204 { | |
| 1205 my ($parameterCount) = @_; | |
| 1206 return "" unless $parameterCount; | |
| 1207 return join(", ", map { "_arg$_" } (0..$parameterCount - 1)); | |
| 1208 } | |
| 1209 | |
| 1210 sub DartAnonymousNamedOptionalParameters | |
| 1211 { | |
| 1212 my ($parameterCount) = @_; | |
| 1213 return "" unless $parameterCount; | |
| 1214 return "[" . DartAnonymousArguments($parameterCount) . "]"; | |
| 1215 } | |
| 1216 | |
| 1217 sub CreateFunctionNativeDescriptor | |
| 1218 { | |
| 1219 my ($interfaceName, $functionName, $argumentCount) = @_; | |
| 1220 my $descriptor = NativeBindingDescriptor->new( | |
| 1221 cppCallbackName => "${functionName}Callback", | |
| 1222 nativeId => "${interfaceName}_${functionName}_Callback", | |
| 1223 argumentCount => $argumentCount); | |
| 1224 push(@dartNatives, $descriptor); | |
| 1225 return $descriptor; | |
| 1226 } | |
| 1227 | |
| 1228 sub CreateGetterNativeDescriptor | |
| 1229 { | |
| 1230 my ($interfaceName, $attributeName) = @_; | |
| 1231 my $descriptor = NativeBindingDescriptor->new( | |
| 1232 cppCallbackName => "${attributeName}Getter", | |
| 1233 nativeId => "${interfaceName}_${attributeName}_Getter", | |
| 1234 argumentCount => 1); | |
| 1235 push(@dartNatives, $descriptor); | |
| 1236 return $descriptor; | |
| 1237 } | |
| 1238 | |
| 1239 sub CreateSetterNativeDescriptor | |
| 1240 { | |
| 1241 my ($interfaceName, $attributeName) = @_; | |
| 1242 my $descriptor = NativeBindingDescriptor->new( | |
| 1243 cppCallbackName => "${attributeName}Setter", | |
| 1244 nativeId => "${interfaceName}_${attributeName}_Setter", | |
| 1245 argumentCount => 2); | |
| 1246 push(@dartNatives, $descriptor); | |
| 1247 return $descriptor; | |
| 1248 } | |
| 1249 | |
| 1250 sub GenerateDartOptionalArgumentsResolver | |
| 1251 { | |
| 1252 my ($interfaceName, $function) = @_; | |
| 1253 | |
| 1254 my $interfaceMethodDeclaration = DartInterfaceMethodDeclaration($interfaceNa
me, $function); | |
| 1255 push(@dartInterfaceContent, " $interfaceMethodDeclaration;\n"); | |
| 1256 | |
| 1257 my @resolver = (); | |
| 1258 push(@resolver, " $interfaceMethodDeclaration {\n"); | |
| 1259 my @parameters = (); | |
| 1260 foreach my $parameterIndex (0..@{$function->parameters}) { | |
| 1261 my $parameter = @{$function->parameters}[$parameterIndex]; | |
| 1262 if (!$parameter || IsParameterOptionalInWebKit($parameter)) { | |
| 1263 my $functionName = GenerateNativeBinding($interfaceName, $function,
\@parameters); | |
| 1264 if ($parameter) { | |
| 1265 my $parameterName = $parameter->name; | |
| 1266 push(@resolver, " if ($parameterName === null)\n "); | |
| 1267 } | |
| 1268 my $parameterNames = join(", ", map { $_->name } @parameters); | |
| 1269 push(@resolver, " return $functionName($parameterNames);\n"); | |
| 1270 } | |
| 1271 push(@parameters, $parameter); | |
| 1272 } | |
| 1273 push(@resolver, " }\n"); | |
| 1274 push(@dartImplContent, join("", @resolver)); | |
| 1275 } | |
| 1276 | |
| 1277 sub GenerateDartOverloadResolver | |
| 1278 { | |
| 1279 my ($interfaceName, $function) = @_; | |
| 1280 | |
| 1281 # Generate code for choosing the correct overload to call. Overloads are | |
| 1282 # chosen based on the the type of the arguments. When more than a single | |
| 1283 # overload is applicable, precedence is given according to the order of | |
| 1284 # declaration in the IDL. | |
| 1285 | |
| 1286 my $interfaceMethodDeclaration = DartInterfaceMethodDeclaration($interfaceNa
me, $function); | |
| 1287 push(@dartInterfaceContent, " $interfaceMethodDeclaration;\n"); | |
| 1288 | |
| 1289 my @resolver = (); | |
| 1290 push(@resolver, " $interfaceMethodDeclaration {\n"); | |
| 1291 my $maxParameterCount = MaxOverloadParameterCount($function); | |
| 1292 foreach my $overload (@{$function->{overloads}}) { | |
| 1293 my @parameters = (); | |
| 1294 my @parameterNames = (); | |
| 1295 my @parameterChecks = map { "_arg$_ === null" } (0..$maxParameterCount -
1); | |
| 1296 foreach my $parameterIndex (0..@{$overload->parameters}) { | |
| 1297 my $parameter = @{$overload->parameters}[$parameterIndex]; | |
| 1298 if (!$parameter || IsParameterOptionalInWebKit($parameter)) { | |
| 1299 my $functionName = GenerateNativeBinding($interfaceName, $overlo
ad, \@parameters); | |
| 1300 my $parameterNames = join(", ", @parameterNames); | |
| 1301 my $parameterChecks = join(" && ", @parameterChecks); | |
| 1302 push(@resolver, <<END); | |
| 1303 if ($parameterChecks) | |
| 1304 return $functionName($parameterNames); | |
| 1305 END | |
| 1306 } | |
| 1307 last if !$parameter; | |
| 1308 my $idlType = $codeGenerator->StripModule($parameter->type); | |
| 1309 my $dartType = IDLTypeToDart($idlType); | |
| 1310 push(@parameterNames, "_arg$parameterIndex"); | |
| 1311 $parameterChecks[$parameterIndex] = "_arg$parameterIndex is $dartTyp
e"; | |
| 1312 push(@parameters, $parameter); | |
| 1313 } | |
| 1314 } | |
| 1315 | |
| 1316 # FIXME: throw appropriate exception when overload is not found. | |
| 1317 push(@resolver, <<END); | |
| 1318 throw "Failed to find overload of @{[$function->signature->name]}"; | |
| 1319 } | |
| 1320 END | |
| 1321 push(@dartImplContent, join("", @resolver)); | |
| 1322 } | |
| 1323 | |
| 1324 sub ParentInterface | |
| 1325 { | |
| 1326 my $dataNode = shift; | |
| 1327 | |
| 1328 foreach (@{$dataNode->parents}) { | |
| 1329 my $parent = $codeGenerator->StripModule($_); | |
| 1330 if ($parent eq "EventTarget") { | |
| 1331 next; | |
| 1332 } | |
| 1333 return $parent; | |
| 1334 } | |
| 1335 } | |
| 1336 | |
| 1337 my %excludedInterfaces = ( | |
| 1338 "SVGURIReference" => 1, # Is not in the list of SVG idls files (see WebCore.gy
pi), v8 bindings do not immediately compile | |
| 1339 # Explicitly excluded in WebCore.gyp | |
| 1340 "ElementTimeControl" => 1, | |
| 1341 "SVGExternalResourcesRequired" => 1, | |
| 1342 "SVGFilterPrimitiveStandardAttributes" => 1, | |
| 1343 "SVGFitToViewBox" => 1, | |
| 1344 "SVGLangSpace" => 1, | |
| 1345 "SVGLocatable" => 1, | |
| 1346 "SVGStylable" => 1, | |
| 1347 "SVGTests" => 1, | |
| 1348 "SVGTransformable" => 1, | |
| 1349 "SVGViewSpec" => 1, | |
| 1350 "SVGZoomAndPan" => 1, | |
| 1351 ); | |
| 1352 | |
| 1353 sub ListLike | |
| 1354 { | |
| 1355 my ($elementType, $needsAuxiliaryAccessors) = @_; | |
| 1356 | |
| 1357 my @auxiliaryMethods = (); | |
| 1358 if ($needsAuxiliaryAccessors) { | |
| 1359 push(@auxiliaryMethods, ["$elementType operator [] (int index)", "numeri
cIndexGetter", 2]); | |
| 1360 push(@auxiliaryMethods, ["void operator []= (int index, $elementType val
ue)", "numericIndexSetter", 3]); | |
| 1361 } | |
| 1362 | |
| 1363 return IDLTypeInfoStruct->new( | |
| 1364 additionalInterfaces => ["List<$elementType>"], | |
| 1365 superClass => "ListBase<$elementType>", | |
| 1366 auxilaryMethods => \@auxiliaryMethods | |
| 1367 ); | |
| 1368 } | |
| 1369 | |
| 1370 sub MapLike | |
| 1371 { | |
| 1372 # FIXME: most probably we need to deduce more types using hints like | |
| 1373 # HasNameGetter, CustomDeleteProperty, CustomGetPropertyNames, DelegatingPut
Function | |
| 1374 # attributes. | |
| 1375 # FIXME: technically at least DOMStringMap.setItem and DOMStringMap.item cou
ld be automatically | |
| 1376 # generated and then used from [] and []=. I don't do it for now not to mes
s up with IDLs too | |
| 1377 # much. | |
| 1378 # FIXME: support removal of elements if allowed (it is at least for DOMStrin
gMap.) | |
| 1379 my ($interfaceName, $keyType, $elementType) = @_; | |
| 1380 return IDLTypeInfoStruct->new( | |
| 1381 additionalInterfaces => ["Map<$keyType, $elementType>"], | |
| 1382 superClass => "MapBase<$keyType, $elementType>", | |
| 1383 auxilaryMethods => [ | |
| 1384 ["Collection<$keyType> getKeys()", "getKeys", 1], | |
| 1385 ["$elementType operator [] ($keyType k)", "item", 2], | |
| 1386 ["operator []= ($keyType k, $elementType v)", "setItem", 3], | |
| 1387 ["$elementType remove($keyType k)", "deleteItem", 2], | |
| 1388 ], | |
| 1389 ); | |
| 1390 } | |
| 1391 | |
| 1392 my %idlTypeInfoOverrides = ( | |
| 1393 "CanvasPixelArray" => ListLike("int", 1), | |
| 1394 "DOMStringMap" => MapLike("DOMStringMap", "String", "String"), | |
| 1395 "HTMLCollection" => ListLike("Node"), | |
| 1396 "NodeList" => ListLike("Node"), | |
| 1397 "StyleSheetList" => ListLike("StyleSheet"), | |
| 1398 ); | |
| 1399 | |
| 1400 # FIXME: turn into the single IDL type info registry. | |
| 1401 sub IDLTypeInfo | |
| 1402 { | |
| 1403 my ($dataNode,) = @_; | |
| 1404 my $override = $idlTypeInfoOverrides{$dataNode->name}; | |
| 1405 return $override if $override; | |
| 1406 | |
| 1407 my $parentInterface = ParentInterface($dataNode); | |
| 1408 return IDLTypeInfoStruct->new( | |
| 1409 superClass => $parentInterface ? "${parentInterface}Implementation" : "D
OMType", | |
| 1410 ); | |
| 1411 } | |
| 1412 | |
| 1413 sub GenerateSource | |
| 1414 { | |
| 1415 my ($object, $dataNode) = @_; | |
| 1416 | |
| 1417 my $interfaceName = $dataNode->name; | |
| 1418 my $w3cInterfaceName = IDLTypeToW3C($interfaceName); | |
| 1419 | |
| 1420 push(@dartInterfaceContent, $headerTemplate); | |
| 1421 | |
| 1422 # Build extends clause if any. | |
| 1423 my $extendsClause = ""; | |
| 1424 my $parentInterface = ParentInterface($dataNode); | |
| 1425 my $isEventTarget = $dataNode->extendedAttributes->{EventTarget}; | |
| 1426 my @implementedInterfaces = (); | |
| 1427 push(@implementedInterfaces, $parentInterface) if $parentInterface; | |
| 1428 push(@implementedInterfaces, "EventTarget") if $isEventTarget; | |
| 1429 | |
| 1430 push(@implementedInterfaces, @{IDLTypeInfo($dataNode)->additionalInterfaces}
); | |
| 1431 push(@implementedInterfaces, @allParents); | |
| 1432 | |
| 1433 if (@implementedInterfaces) { | |
| 1434 $extendsClause = " extends " . join(", ", @implementedInterfaces); | |
| 1435 } | |
| 1436 | |
| 1437 # Build default clause if any. | |
| 1438 my $defaultClause = ""; | |
| 1439 if (HasCustomConstructor($dataNode)) { | |
| 1440 $defaultClause = " default ${w3cInterfaceName}Implementation"; | |
| 1441 push(@customCallbackDeclarations, GenerateCustomCallbackDeclaration("con
structorCallback")); | |
| 1442 } | |
| 1443 | |
| 1444 push(@dartInterfaceContent, "\ninterface ${w3cInterfaceName}${extendsClause}
${defaultClause} {\n"); | |
| 1445 push(@dartInterfaceContent, "\n // Constants.\n"); | |
| 1446 foreach my $constant (@{$dataNode->constants}) { | |
| 1447 my $name = $constant->name; | |
| 1448 my $value = $constant->value; | |
| 1449 | |
| 1450 push(@dartInterfaceContent, " static final int $name = $value;\n"); | |
| 1451 } | |
| 1452 | |
| 1453 # Generate Dart implementation prologue. | |
| 1454 my $implementationClassName = "${interfaceName}Implementation"; | |
| 1455 my $superClass = IDLTypeInfo($dataNode)->superClass; | |
| 1456 push(@dartImplContent, $headerTemplate); | |
| 1457 push(@dartImplContent, "\nclass $implementationClassName extends $superClass
implements $interfaceName {\n"); | |
| 1458 | |
| 1459 GenerateImplementationPrologue($dataNode); | |
| 1460 | |
| 1461 # Generate fields. | |
| 1462 # FIXME: special treatment of constructors attributes (see V8 code generator
). | |
| 1463 push(@dartInterfaceContent, "\n // Fields.\n"); | |
| 1464 push(@dartImplContent, "\n // Fields.\n"); | |
| 1465 push(@implContent, "\n// Getters & setters.\n"); | |
| 1466 foreach my $attribute (@{$dataNode->attributes}) { | |
| 1467 next if IgnoredAttribute($interfaceName, $attribute); | |
| 1468 GenerateField($interfaceName, $attribute); | |
| 1469 } | |
| 1470 | |
| 1471 # Generate methods. | |
| 1472 push(@dartInterfaceContent, "\n // Methods.\n"); | |
| 1473 push(@dartImplContent, "\n // Methods.\n"); | |
| 1474 push(@implContent, "\n// Callbacks.\n"); | |
| 1475 foreach my $function (@{$dataNode->functions}) { | |
| 1476 next if IgnoredCallback($interfaceName, $function); | |
| 1477 next if HasOverloads($function) && $function->{overloadIndex} != 1; | |
| 1478 GenerateMethod($interfaceName, $function); | |
| 1479 } | |
| 1480 | |
| 1481 foreach my $auxilaryMethod (@{IDLTypeInfo($dataNode)->auxilaryMethods}) { | |
| 1482 my $dartDeclaration = $auxilaryMethod->[0]; | |
| 1483 my $descriptor = CreateFunctionNativeDescriptor($interfaceName, $auxilar
yMethod->[1], $auxilaryMethod->[2]); | |
| 1484 my $nativeId = $descriptor->nativeId; | |
| 1485 push(@dartImplContent, " $dartDeclaration native \"$nativeId\";\n"); | |
| 1486 push(@customCallbackDeclarations, GenerateCustomCallbackDeclaration($des
criptor->cppCallbackName)); | |
| 1487 } | |
| 1488 | |
| 1489 if (HasCustomConstructor($dataNode)) { | |
| 1490 my $parameterCount = $dataNode->extendedAttributes->{"ConstructorParamet
ers"} || 0; | |
| 1491 my $descriptor = CreateFunctionNativeDescriptor($interfaceName, "constru
ctor", 1 + $parameterCount); | |
| 1492 my $nativeId = $descriptor->nativeId; | |
| 1493 my $parameters = DartAnonymousNamedOptionalParameters($parameterCount); | |
| 1494 my $arguments = DartAnonymousArguments($parameterCount); | |
| 1495 push(@dartInterfaceContent, " $w3cInterfaceName($parameters);\n"); | |
| 1496 push(@dartImplContent, <<END); | |
| 1497 $implementationClassName($parameters) { | |
| 1498 this._bind($arguments); | |
| 1499 } | |
| 1500 END | |
| 1501 push(@dartImplContent, " void _bind($arguments) native \"$nativeId\";\n
"); | |
| 1502 } | |
| 1503 | |
| 1504 # Generate implementation support. | |
| 1505 # FIXME: get rid of implementation support completely. | |
| 1506 push(@dartImplContent, <<END); | |
| 1507 // Implementation support. | |
| 1508 static $implementationClassName _create$implementationClassName() => new $impl
ementationClassName._create$implementationClassName(); | |
| 1509 $implementationClassName._create$implementationClassName(); | |
| 1510 | |
| 1511 String get typeName() => \"$interfaceName\"; | |
| 1512 END | |
| 1513 | |
| 1514 push(@dartInterfaceContent, "}\n"); | |
| 1515 push(@dartImplContent, "}\n"); | |
| 1516 | |
| 1517 if (HasW3CName($interfaceName)) { | |
| 1518 push(@dartInterfaceContent, "\ninterface ${interfaceName} extends ${w3cI
nterfaceName} {}\n"); | |
| 1519 } | |
| 1520 | |
| 1521 GenerateImplementationEpilogue($dataNode); | |
| 1522 } | |
| 1523 | |
| 1524 sub GenerateField | |
| 1525 { | |
| 1526 my ($interfaceName, $attribute) = @_; | |
| 1527 | |
| 1528 my $attributeName = DartName($interfaceName, $attribute->signature->name); | |
| 1529 my $attributeType = $attribute->signature->type; | |
| 1530 my $dartAttributeType = IDLTypeToDart($attributeType); | |
| 1531 | |
| 1532 # Generate field declaration. | |
| 1533 my $final = HasSetter($attribute) ? "" : "final "; | |
| 1534 push(@dartInterfaceContent, " $final$dartAttributeType $attributeName;\n"); | |
| 1535 | |
| 1536 # Generate getter implementation. | |
| 1537 my $getterDescriptor = CreateGetterNativeDescriptor($interfaceName, $attribu
teName); | |
| 1538 my $getterNativeId = $getterDescriptor->nativeId; | |
| 1539 push(@dartImplContent, " $dartAttributeType get $attributeName() native \"$
getterNativeId\";\n"); | |
| 1540 if (HasCustomGetter($attribute)) { | |
| 1541 push(@customCallbackDeclarations, GenerateCustomCallbackDeclaration($get
terDescriptor->cppCallbackName)); | |
| 1542 } else { | |
| 1543 my ($functionName, @arguments) = $codeGenerator->GetterExpression(\%impl
Includes, $interfaceName, $attribute); | |
| 1544 my $raisesExceptions = scalar(@{$attribute->getterExceptions}); | |
| 1545 GenerateGenericBindingsFunction($getterDescriptor->cppCallbackName, $int
erfaceName, $functionName, \@arguments, [], $attributeType, $raisesExceptions, $
attribute->signature->extendedAttributes); | |
| 1546 } | |
| 1547 | |
| 1548 return unless HasSetter($attribute); | |
| 1549 | |
| 1550 # Generate setter implementation. | |
| 1551 my $setterDescriptor = CreateSetterNativeDescriptor($interfaceName, $attribu
teName); | |
| 1552 my $setterNativeId = $setterDescriptor->nativeId; | |
| 1553 push(@dartImplContent, " void set $attributeName($dartAttributeType) native
\"$setterNativeId\";\n"); | |
| 1554 if (HasCustomSetter($attribute)) { | |
| 1555 push(@customCallbackDeclarations, GenerateCustomCallbackDeclaration($set
terDescriptor->cppCallbackName)); | |
| 1556 } else { | |
| 1557 my ($functionName, @arguments) = $codeGenerator->SetterExpression(\%impl
Includes, $interfaceName, $attribute); | |
| 1558 my $raisesExceptions = scalar(@{$attribute->setterExceptions}); | |
| 1559 GenerateGenericBindingsFunction($setterDescriptor->cppCallbackName, $int
erfaceName, $functionName, \@arguments, [$attribute->signature], "void", $raises
Exceptions, $attribute->signature->extendedAttributes, 1); | |
| 1560 } | |
| 1561 } | |
| 1562 | |
| 1563 sub GenerateMethod | |
| 1564 { | |
| 1565 my ($interfaceName, $function) = @_; | |
| 1566 | |
| 1567 my $functionName = DartName($interfaceName, $function->signature->name); | |
| 1568 | |
| 1569 if (!$function->signature->extendedAttributes->{"Custom"}) { | |
| 1570 if (HasOverloads($function)) { | |
| 1571 GenerateDartOverloadResolver($interfaceName, $function); | |
| 1572 } elsif (HasOptionalParameters($function)) { | |
| 1573 GenerateDartOptionalArgumentsResolver($interfaceName, $function); | |
| 1574 } else { | |
| 1575 my $interfaceMethodDeclaration = DartInterfaceMethodDeclaration($int
erfaceName, $function); | |
| 1576 push(@dartInterfaceContent, " $interfaceMethodDeclaration;\n"); | |
| 1577 my $bindingFunctionName = GenerateNativeBinding($interfaceName, $fun
ction, $function->parameters); | |
| 1578 die if $bindingFunctionName ne $functionName; | |
| 1579 } | |
| 1580 } else { | |
| 1581 my $parameters; | |
| 1582 my $parameterCount; | |
| 1583 if (HasOverloads($function)) { | |
| 1584 $parameterCount = MaxOverloadParameterCount($function); | |
| 1585 $parameters = DartAnonymousNamedOptionalParameters($parameterCount); | |
| 1586 } else { | |
| 1587 $parameters = DartParameters($function, $function->parameters, 1); | |
| 1588 $parameterCount = DartParameterCount($function, $function->parameter
s); | |
| 1589 } | |
| 1590 my $methodDeclaration = DartMethodDeclaration($functionName, $parameters
, $function->signature->type); | |
| 1591 my $descriptor = CreateFunctionNativeDescriptor($interfaceName, $functio
nName, 1 + $parameterCount); | |
| 1592 my $nativeId = $descriptor->nativeId; | |
| 1593 push(@dartInterfaceContent, " $methodDeclaration;\n"); | |
| 1594 push(@dartImplContent, " $methodDeclaration native \"$nativeId\";\n"); | |
| 1595 push(@customCallbackDeclarations, GenerateCustomCallbackDeclaration($des
criptor->cppCallbackName)); | |
| 1596 } | |
| 1597 | |
| 1598 # If there is a method named "item", duplicate it as operator []. | |
| 1599 if ($functionName eq "item") { | |
| 1600 # Consider operator [] should support overloads and optional arguments. | |
| 1601 die "$interfaceName.item has overloads" if HasOverloads($function); | |
| 1602 die "$interfaceName.item has optional arguments" if HasOptionalParameter
s($function); | |
| 1603 | |
| 1604 my $subscriptOperatorDeclaration = DartInterfaceMethodDeclaration($inter
faceName, $function, "operator []"); | |
| 1605 my $parameters = join ", ", (map { $_->name } @{$function->parameters}); | |
| 1606 push(@dartInterfaceContent, " $subscriptOperatorDeclaration;\n"); | |
| 1607 push(@dartImplContent, " $subscriptOperatorDeclaration { return item($p
arameters); }\n"); | |
| 1608 } | |
| 1609 } | |
| 1610 | |
| 1611 sub GenerateNativeBinding | |
| 1612 { | |
| 1613 my ($interfaceName, $function, $parameters) = @_; | |
| 1614 | |
| 1615 my $functionName = DartName($interfaceName, $function->signature->name); | |
| 1616 if (HasOverloads($function)) { | |
| 1617 $functionName .= $function->{overloadIndex}; | |
| 1618 } | |
| 1619 if (HasOptionalParameters($function)) { | |
| 1620 $functionName .= "_" . @$parameters; | |
| 1621 } | |
| 1622 | |
| 1623 my $extendedAttributes = $function->signature->extendedAttributes; | |
| 1624 my $returnType = $function->signature->type; | |
| 1625 | |
| 1626 my $dartParameters = DartParameters($function, $parameters, 0); | |
| 1627 my $dartParameterCount = DartParameterCount($function, $parameters); | |
| 1628 my $methodDeclaration = DartMethodDeclaration($functionName, $dartParameters
, $returnType); | |
| 1629 my $descriptor = CreateFunctionNativeDescriptor($interfaceName, $functionNam
e, 1 + $dartParameterCount); | |
| 1630 my $nativeId = $descriptor->nativeId; | |
| 1631 push(@dartImplContent, <<END); | |
| 1632 $methodDeclaration native "$nativeId"; | |
| 1633 END | |
| 1634 | |
| 1635 my $nativeFunctionName; | |
| 1636 if ($extendedAttributes->{ImplementationFunction}) { | |
| 1637 $nativeFunctionName = $extendedAttributes->{ImplementationFunction}; | |
| 1638 } else { | |
| 1639 $nativeFunctionName = $function->signature->name; | |
| 1640 } | |
| 1641 my $raisesExceptions = scalar(@{$function->raisesExceptions}); | |
| 1642 GenerateGenericBindingsFunction($descriptor->cppCallbackName, $interfaceName
, $nativeFunctionName, [], $parameters, $returnType, $raisesExceptions, $extende
dAttributes); | |
| 1643 | |
| 1644 return $functionName; | |
| 1645 } | |
| 1646 | |
| 1647 # Internal helper | |
| 1648 sub WriteData | |
| 1649 { | |
| 1650 if (defined($IMPL)) { | |
| 1651 # Write content to file. | |
| 1652 print $IMPL @implContentHeader; | |
| 1653 | |
| 1654 print $IMPL @implFixedHeader; | |
| 1655 | |
| 1656 print $IMPL GenerateIncludes(keys(%implIncludes)); | |
| 1657 | |
| 1658 print $IMPL "\n"; | |
| 1659 print $IMPL @implContent; | |
| 1660 close($IMPL); | |
| 1661 undef($IMPL); | |
| 1662 | |
| 1663 %implIncludes = (); | |
| 1664 @implFixedHeader = (); | |
| 1665 @implHeaderContent = (); | |
| 1666 @implContent = (); | |
| 1667 @dartNatives = (); | |
| 1668 } | |
| 1669 | |
| 1670 if (defined($HEADER)) { | |
| 1671 # Write content to file. | |
| 1672 print $HEADER @headerContent; | |
| 1673 close($HEADER); | |
| 1674 undef($HEADER); | |
| 1675 | |
| 1676 @headerContent = (); | |
| 1677 } | |
| 1678 | |
| 1679 if (defined($DART_INTERFACE)) { | |
| 1680 # Write content of Dart file. | |
| 1681 print $DART_INTERFACE @dartInterfaceContent; | |
| 1682 close($DART_INTERFACE); | |
| 1683 undef($DART_INTERFACE); | |
| 1684 | |
| 1685 @dartInterfaceContent = (); | |
| 1686 } | |
| 1687 | |
| 1688 if (defined($DART_IMPL)) { | |
| 1689 # Write content of Dart file. | |
| 1690 print $DART_IMPL @dartImplContent; | |
| 1691 close($DART_IMPL); | |
| 1692 undef($DART_IMPL); | |
| 1693 | |
| 1694 @dartImplContent = (); | |
| 1695 } | |
| 1696 } | |
| OLD | NEW |