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 # The only usage is HTMLIFrameElement.contentDocument. |
| 318 return 1 if $attribute->signature->extendedAttributes->{CheckFrameSecurity}; |
| 319 |
| 320 return 1 if HasCustomGetter($attribute) && exists $classesWithUnsupportedCus
tomGetters{$interfaceName}; |
| 321 |
| 322 return 0; |
| 323 } |
| 324 |
| 325 |
| 326 sub HasSetter |
| 327 { |
| 328 my ($attribute,) = @_; |
| 329 |
| 330 return 0 if $attribute->type =~ /^readonly/; |
| 331 # FIXME: Replaceable apparently means that the value can be overwritten by J
S and |
| 332 # hence there is no correspondence to this in Dart. |
| 333 return 0 if $attribute->signature->extendedAttributes->{"Replaceable"}; |
| 334 return 1; |
| 335 } |
| 336 |
| 337 |
| 338 sub IgnoredCallback |
| 339 { |
| 340 my ($interfaceName, $function) = @_; |
| 341 |
| 342 # FIXME: WebGLContextEvent.initEvent overloads initEvent in base interface E
vent and adds |
| 343 # another argument. |
| 344 # In the current architecture it's difficult to solve as IDL files are proce
ssed one by one. |
| 345 # As this is the only case, I'd suggest to put Custom attribute on WebGLCont
extEvent.initEvent. |
| 346 return 1 if $interfaceName eq "WebGLContextEvent" && $function->signature->n
ame eq "initEvent"; |
| 347 |
| 348 # FIXME: implement callbacks with ScriptState. |
| 349 my $callWith = $function->signature->extendedAttributes->{CallWith}; |
| 350 return 1 if $callWith and $callWith eq "ScriptState"; |
| 351 |
| 352 return 0; |
| 353 } |
| 354 |
| 355 # FIXME: Consider adding this to IDL as an attribute. |
| 356 my %idlTypeToW3C = ( |
| 357 "DOMWindow" => "Window", |
| 358 "DOMCoreException" => "DOMException" |
| 359 ); |
| 360 |
| 361 sub HasW3CName |
| 362 { |
| 363 my ($idlType,) = @_; |
| 364 return 1 if exists $idlTypeToW3C{$idlType}; |
| 365 return 0; |
| 366 } |
| 367 |
| 368 sub IDLTypeToW3C |
| 369 { |
| 370 my ($idlType,) = @_; |
| 371 return $idlTypeToW3C{$idlType} if exists $idlTypeToW3C{$idlType}; |
| 372 return $idlType; |
| 373 } |
| 374 |
| 375 my %idlTypeToDart = ( |
| 376 "any" => "Object", |
| 377 "boolean" => "bool", |
| 378 "Array" => "List", |
| 379 "DOMObject" => "Object", |
| 380 "DOMString" => "String", |
| 381 "DOMString[]" => "DOMStringList", |
| 382 "DOMTimeStamp" => "int", |
| 383 "ObjectArray" => "List", |
| 384 "SerializedScriptValue" => "Object", |
| 385 "Date" => "Date", |
| 386 "float" => "num", |
| 387 "short" => "int", |
| 388 "long" => "int", |
| 389 "long long" => "int", |
| 390 "unsigned int" => "int", |
| 391 "unsigned short" => "int", |
| 392 "unsigned long" => "int", |
| 393 "unsigned long long" => "int", |
| 394 "string" => "String", |
| 395 ); |
| 396 |
| 397 my %primitiveDartTypes = ( |
| 398 "int" => 1, |
| 399 "String" => 1, |
| 400 "Object" => 1, |
| 401 "Date" => 1, |
| 402 "SerializedScriptValue" => 1, |
| 403 ); |
| 404 |
| 405 sub IDLTypeToDart |
| 406 { |
| 407 my ($idlType,) = @_; |
| 408 return $idlTypeToDart{$idlType} if exists $idlTypeToDart{$idlType}; |
| 409 return $idlType; |
| 410 } |
| 411 |
| 412 # FIXME: pretty much %non_wrapper_types in CodeGeneratorV8. |
| 413 my %nonWrapperTypes = ( |
| 414 "CompareHow" => 1, |
| 415 "EventListener" => 1, |
| 416 "EventTarget" => 1, |
| 417 "MediaQueryListListener" => 1, |
| 418 "OptionsObject" => 1, |
| 419 "VoidCallback" => 1, |
| 420 ); |
| 421 |
| 422 sub IsIDLTypeWithDartBindings |
| 423 { |
| 424 my ($idlType,) = @_; |
| 425 |
| 426 return 0 if exists $idlTypeToDart{$idlType}; |
| 427 return 0 if exists $primitiveDartTypes{$idlType}; |
| 428 return 0 if !IsRefPtrType(IDLTypeToDart($idlType)); |
| 429 return 0 if exists $nonWrapperTypes{$idlType}; |
| 430 |
| 431 return 1; |
| 432 } |
| 433 |
| 434 sub ParameterAdapterType |
| 435 { |
| 436 my ($idlType,) = @_; |
| 437 |
| 438 my $webkitParameterType = IDLTypeToWebkit($idlType); |
| 439 |
| 440 my $suffix = ""; |
| 441 if (IsIDLTypeWithDartBindings($idlType)) { |
| 442 my $bindingsClass = ClassName($idlType); |
| 443 $implIncludes{"$bindingsClass.h"} = 1; |
| 444 $suffix = ", $bindingsClass"; |
| 445 } |
| 446 |
| 447 return "ParameterAdapter< $webkitParameterType$suffix >"; |
| 448 } |
| 449 |
| 450 # FIXME: common with CodeGeneratorV8 |
| 451 sub GetNativeTypeForConversions |
| 452 { |
| 453 my ($type,) = @_; |
| 454 $type = $codeGenerator->GetSVGTypeNeedingTearOff($type) if $codeGenerator->I
sSVGTypeNeedingTearOff($type); |
| 455 return $type; |
| 456 } |
| 457 |
| 458 |
| 459 sub AddHeaderForIDLType |
| 460 { |
| 461 my ($idlType, $includes) = @_; |
| 462 |
| 463 $idlType =~ s/Abs|Rel// if $idlType =~ /SVGPathSeg/; |
| 464 |
| 465 return if $codeGenerator->IsPrimitiveType($idlType); |
| 466 |
| 467 return if exists $primitiveDartTypes{IDLTypeToDart($idlType)}; |
| 468 |
| 469 return if $codeGenerator->AvoidInclusionOfType($idlType); |
| 470 |
| 471 return if $idlType eq "CompareHow"; |
| 472 |
| 473 $includes->{"$idlType.h"} = 1; |
| 474 $includes->{"SVGPropertyTearOff.h"} = 1 if $codeGenerator->IsSVGTypeNeedingT
earOff($idlType); |
| 475 } |
| 476 |
| 477 # FIXME: common with CodeGeneratorV8 |
| 478 sub AddHeaderClassIncludes |
| 479 { |
| 480 my ($idlType,) = @_; |
| 481 |
| 482 AddHeaderForIDLType($idlType, \%headerIncludes); |
| 483 |
| 484 $headerIncludes{"DartDOMWrapper.h"} = 1; |
| 485 } |
| 486 |
| 487 sub GenerateIncludes |
| 488 { |
| 489 return map { "#include " . (/wtf|dart_api\.h/ ? "<$_>" : "\"$_\"") . "\n"; }
sort(@_); |
| 490 } |
| 491 |
| 492 my %withCustomConverters = ( |
| 493 "DOMWindow" => 1, |
| 494 "Element" => 1, |
| 495 "HTMLElement" => 1, |
| 496 "SVGElement" => 1, |
| 497 ); |
| 498 |
| 499 sub RequiresCustomToDartConverter |
| 500 { |
| 501 my ($dataNode,) = @_; |
| 502 |
| 503 return 1 if $dataNode->extendedAttributes->{CustomToJS}; |
| 504 return 1 if $dataNode->extendedAttributes->{PureInterface}; |
| 505 return exists $withCustomConverters{$dataNode->name}; |
| 506 } |
| 507 |
| 508 sub GenerateHeader |
| 509 { |
| 510 my ($object, $dataNode) = @_; |
| 511 |
| 512 my $interfaceName = $dataNode->name; |
| 513 my $className = ClassName($interfaceName); |
| 514 my $webkitClassName = GetNativeTypeForConversions($interfaceName); |
| 515 |
| 516 my $conditionalString = GenerateConditionalString($dataNode); |
| 517 |
| 518 my $toDartValue = ""; |
| 519 if (!RequiresCustomToDartConverter($dataNode)) { |
| 520 $toDartValue = <<END; |
| 521 inline Dart_Handle toDartValue($webkitClassName* value) |
| 522 { |
| 523 return DartDOMWrapper::toDart<$className>(value); |
| 524 } |
| 525 END |
| 526 } else { |
| 527 $toDartValue = <<END; |
| 528 Dart_Handle toDartValue($webkitClassName*); |
| 529 END |
| 530 } |
| 531 |
| 532 my $customCallbackDeclarations = join("\n\n", @customCallbackDeclarations); |
| 533 |
| 534 push(@headerContent, $headerTemplate); |
| 535 |
| 536 push(@headerContent, "\n#if ${conditionalString}\n") if $conditionalString; |
| 537 push(@headerContent, <<END); |
| 538 |
| 539 #ifndef ${className}_h |
| 540 #define ${className}_h |
| 541 |
| 542 END |
| 543 |
| 544 AddHeaderClassIncludes($interfaceName); |
| 545 |
| 546 $headerIncludes{"dart_api.h"} = 1; |
| 547 push(@headerContent, GenerateIncludes(keys(%headerIncludes))); |
| 548 |
| 549 push(@headerContent, <<END); |
| 550 |
| 551 namespace WebCore { |
| 552 |
| 553 struct $className { |
| 554 static const char* const dartImplementationClassName; |
| 555 typedef $webkitClassName NativeType; |
| 556 |
| 557 static PassRefPtr<NativeType> toNative(Dart_Handle handle, Dart_Handle& exce
ption) |
| 558 { |
| 559 return DartDOMWrapper::unwrapDartWrapper<$className>(handle, exception); |
| 560 } |
| 561 }; |
| 562 |
| 563 $toDartValue |
| 564 namespace Dart${interfaceName}Internal { |
| 565 |
| 566 $customCallbackDeclarations |
| 567 |
| 568 } |
| 569 |
| 570 } |
| 571 |
| 572 #endif // ${className}_h |
| 573 END |
| 574 |
| 575 push(@headerContent, "\n#endif // ${conditionalString}\n") if $conditionalSt
ring; |
| 576 } |
| 577 |
| 578 sub HasCustomGetter |
| 579 { |
| 580 my ($attribute,) = @_; |
| 581 my $extendedAttributes = $attribute->signature->extendedAttributes; |
| 582 return $extendedAttributes->{"CustomGetter"} || $extendedAttributes->{"Custo
m"}; |
| 583 } |
| 584 |
| 585 sub HasCustomSetter |
| 586 { |
| 587 my ($attribute,) = @_; |
| 588 my $extendedAttributes = $attribute->signature->extendedAttributes; |
| 589 return $extendedAttributes->{"CustomSetter"} || $extendedAttributes->{"Custo
m"} || $extendedAttributes->{"V8CustomSetter"}; |
| 590 } |
| 591 |
| 592 sub GenerateUnimplementedNative |
| 593 { |
| 594 my ($name,) = @_; |
| 595 |
| 596 push(@implContent, <<END); |
| 597 static void $name(Dart_NativeArguments args) |
| 598 { |
| 599 DART_UNIMPLEMENTED(); |
| 600 } |
| 601 |
| 602 END |
| 603 } |
| 604 |
| 605 sub WithTearOffNotList |
| 606 { |
| 607 my ($interfaceName) = @_; |
| 608 |
| 609 return ($codeGenerator->IsSVGTypeNeedingTearOff($interfaceName) and (not ($i
nterfaceName =~ /List$/))); |
| 610 } |
| 611 |
| 612 sub PrepareInvocation |
| 613 { |
| 614 my ($receiver, $interfaceName, $invocationPrefix, $invocationParameters) = @
_; |
| 615 |
| 616 my $invocationPostfix; |
| 617 $receiver .= "->"; |
| 618 if ($interfaceName eq "SVGNumber") { |
| 619 $receiver .= "propertyReference()"; |
| 620 if ($invocationPrefix =~ /^setValue/) { |
| 621 $invocationPrefix = " = "; |
| 622 } else { |
| 623 $invocationPrefix = ""; |
| 624 } |
| 625 $invocationPostfix = ""; |
| 626 } else { |
| 627 $receiver .= "propertyReference()." if WithTearOffNotList($interfaceName
); |
| 628 $invocationPostfix = ")"; |
| 629 } |
| 630 return "$receiver$invocationPrefix$invocationParameters$invocationPostfix"; |
| 631 } |
| 632 |
| 633 my %svgPrimitiveTypes = ( |
| 634 "SVGAngle" => 1, |
| 635 "SVGLength" => 1, |
| 636 "SVGMatrix" => 1, |
| 637 "SVGNumber" => 1, |
| 638 "SVGPoint" => 1, |
| 639 "SVGRect" => 1, |
| 640 "SVGTransform" => 1); |
| 641 |
| 642 sub ProcessInvocationResult |
| 643 { |
| 644 my ($invocation, $interfaceName, $returnType) = @_; |
| 645 my $svgNativeReturnType = $codeGenerator->GetSVGTypeNeedingTearOff($returnTy
pe); |
| 646 |
| 647 return $invocation if (not $svgNativeReturnType); |
| 648 |
| 649 return "static_cast<${svgNativeReturnType}*>(${invocation})" if ($interfaceN
ame =~ /^SVGAnimated/); |
| 650 |
| 651 return "${svgNativeReturnType}::create(receiver, ${invocation})" if ($return
Type eq "SVGStringList"); |
| 652 |
| 653 return "static_cast<${svgNativeReturnType}*>(${invocation}.get())" if ($inte
rfaceName =~ /List$/); |
| 654 |
| 655 if (exists $svgPrimitiveTypes{$returnType}) { |
| 656 return "${svgNativeReturnType}::create(${invocation})"; |
| 657 } else { |
| 658 return "static_cast<${svgNativeReturnType}*>(${invocation})"; |
| 659 } |
| 660 } |
| 661 |
| 662 sub GenerateGenericBindingsFunction |
| 663 { |
| 664 my ($name, $interfaceName, $invocationPrefix, $parameters, $returnType, $rai
sesExceptions, $attributes, $isSetter) = @_; |
| 665 |
| 666 my $webkitClassName = GetNativeTypeForConversions($interfaceName); |
| 667 |
| 668 my $exceptionManagementPrologue = ""; |
| 669 my $exceptionManagementEpilogue = ""; |
| 670 if (@{$parameters} || $raisesExceptions) { |
| 671 $exceptionManagementPrologue = <<END; |
| 672 Dart_Handle exception; |
| 673 END |
| 674 $exceptionManagementEpilogue = <<END; |
| 675 |
| 676 fail: |
| 677 Dart_ThrowException(exception); |
| 678 ASSERT_NOT_REACHED(); |
| 679 END |
| 680 } |
| 681 |
| 682 my @defineInvocationParameters = (); |
| 683 my @invocationParameters = (); |
| 684 |
| 685 my $callWith = $attributes->{CallWith}; |
| 686 if ($callWith) { |
| 687 # Generate code for "CallWith" parameter. |
| 688 if ($callWith eq "ScriptExecutionContext") { |
| 689 push(@defineInvocationParameters, <<END); |
| 690 ScriptExecutionContext* context = DartUtilities::scriptExecutionContext(
); |
| 691 if (!context) |
| 692 return; |
| 693 END |
| 694 push(@invocationParameters, "context"); |
| 695 } |
| 696 } |
| 697 |
| 698 # Generate code for parameters conversion. |
| 699 my $parameterCount = @$parameters; |
| 700 foreach my $parameterIndex (0..$parameterCount - 1) { |
| 701 my $parameter = @$parameters[$parameterIndex]; |
| 702 my $parameterType = $parameter->type; |
| 703 $parameterType = "DOMStringList" if $parameterType eq "DOMString[]"; |
| 704 AddHeaderForIDLType($parameterType, \%implIncludes); |
| 705 my $name = $parameter->name; |
| 706 my $parameterAdapterType = ParameterAdapterType($parameterType); |
| 707 my $dartArgumentIndex = $parameterIndex + 1; # 0 is for the receiver. |
| 708 my @adapterParameters = ("Dart_GetNativeArgument(args, $dartArgumentInde
x)"); |
| 709 my $adapterParameters = join(", ", @adapterParameters); |
| 710 push(@defineInvocationParameters, <<END); |
| 711 const $parameterAdapterType $name($adapterParameters); |
| 712 if (!$name.conversionSuccessful()) { |
| 713 exception = $name.exception(); |
| 714 goto fail; |
| 715 } |
| 716 END |
| 717 } |
| 718 @invocationParameters = (@invocationParameters, map { $_->name; } @{$paramet
ers}); |
| 719 |
| 720 if ($attributes->{CustomArgumentHandling}) { |
| 721 $implIncludes{"ScriptArguments.h"} = 1; |
| 722 $implIncludes{"ScriptCallStack.h"} = 1; |
| 723 my $customArgument = $parameterCount + 1; |
| 724 push(@defineInvocationParameters, <<END); |
| 725 Dart_Handle customArgument = Dart_GetNativeArgument(args, $customArgumen
t); |
| 726 RefPtr<ScriptArguments> scriptArguments(DartUtilities::createScriptArgum
ents(customArgument)); |
| 727 size_t maxStackSize = receiver->shouldCaptureFullStackTrace() ? ScriptCa
llStack::maxCallStackSizeToCapture : 1; |
| 728 RefPtr<ScriptCallStack> scriptCallStack(DartUtilities::createScriptCallS
tack(maxStackSize)); |
| 729 if (!scriptCallStack->size()) |
| 730 return; |
| 731 END |
| 732 push(@invocationParameters, "scriptArguments", "scriptCallStack"); |
| 733 } |
| 734 |
| 735 if ($attributes->{NeedsUserGestureCheck}) { |
| 736 push(@invocationParameters, "DartUtilities::processingUserGesture()"); |
| 737 } |
| 738 |
| 739 if ($raisesExceptions) { |
| 740 push(@invocationParameters, "ec"); |
| 741 } |
| 742 |
| 743 my $defineInvocationParameters = join "", @defineInvocationParameters; |
| 744 my $invocationParameters = join ", ", @invocationParameters; |
| 745 my $invocation = PrepareInvocation("receiver", $interfaceName, $invocationPr
efix, $invocationParameters); |
| 746 # Generate code for setting return value. |
| 747 my $invocationAndReturn = $invocation; |
| 748 if ($returnType ne "void") { |
| 749 $invocation = ProcessInvocationResult($invocation, $interfaceName, $retu
rnType); |
| 750 my $dartType = IDLTypeToDart($returnType); |
| 751 if (!$codeGenerator->IsPrimitiveType($returnType) && !exists $primitiveD
artTypes{$dartType}) { |
| 752 $implIncludes{"@{[ClassName($dartType)]}.h"} = 1; |
| 753 } |
| 754 $invocation = "static_pointer_cast<SVGAnimatedEnumeration>($invocation)"
if $returnType eq "SVGAnimatedEnumeration"; |
| 755 # FIXME: this is too simplistic for long return types, reconsider. |
| 756 $invocation = "static_cast<int64_t>($invocation)" if $dartType eq "int"; |
| 757 # There is GC3Dboolean which is not a bool, but unsigned char for OpenGL
compatibility. |
| 758 $invocation = "static_cast<bool>($invocation)" if $dartType eq "bool"; |
| 759 $conversion = ($codeGenerator->IsStringType($returnType) and defined |
| 760 $attributes->{ConvertNullStringTo}) ? ", ConvertDefaultToNull" : ""; |
| 761 $invocationAndReturn = "DartDOMWrapper::returnValue(args, $invocation$co
nversion)"; |
| 762 } |
| 763 |
| 764 my $webkitInvocation = <<END; |
| 765 $invocationAndReturn; |
| 766 END |
| 767 if ($raisesExceptions) { |
| 768 $implIncludes{"ExceptionCode.h"} = 1; |
| 769 $webkitInvocation = <<END; |
| 770 ExceptionCode ec = 0; |
| 771 $invocationAndReturn; |
| 772 if (UNLIKELY(ec)) { |
| 773 exception = DartDOMWrapper::exceptionCodeToDartException(ec); |
| 774 goto fail; |
| 775 } |
| 776 END |
| 777 } |
| 778 |
| 779 my $conditionalString = GenerateConditionalStringForAttributes($attributes); |
| 780 if ($conditionalString) { |
| 781 push(@implContent, <<END); |
| 782 #if $conditionalString |
| 783 END |
| 784 } |
| 785 |
| 786 push(@implContent, <<END); |
| 787 static void $name(Dart_NativeArguments args) |
| 788 { |
| 789 DartApiScope dartApiScope; |
| 790 $exceptionManagementPrologue { |
| 791 $webkitClassName* receiver = DartDOMWrapper::receiver< $webkitClassName
>(args); |
| 792 $defineInvocationParameters |
| 793 $webkitInvocation return; |
| 794 } |
| 795 $exceptionManagementEpilogue} |
| 796 |
| 797 END |
| 798 |
| 799 if ($conditionalString) { |
| 800 push(@implContent, <<END); |
| 801 #else |
| 802 static void $name(Dart_NativeArguments args) |
| 803 { |
| 804 DartApiScope dartApiScope; |
| 805 Dart_ThrowException(DartUtilities::conditionalFunctionalityException()); |
| 806 } |
| 807 #endif |
| 808 |
| 809 END |
| 810 } |
| 811 } |
| 812 |
| 813 # FIXME: copied from CodeGeneratorV8.pm |
| 814 sub IsRefPtrType |
| 815 { |
| 816 my ($type,) = @_; |
| 817 |
| 818 return 0 if $type eq "boolean"; |
| 819 return 0 if $type eq "float"; |
| 820 return 0 if $type eq "int"; |
| 821 return 0 if $type eq "Date"; |
| 822 return 0 if $type eq "DOMString"; |
| 823 return 0 if $type eq "double"; |
| 824 return 0 if $type eq "short"; |
| 825 return 0 if $type eq "long"; |
| 826 return 0 if $type eq "unsigned"; |
| 827 return 0 if $type eq "unsigned long"; |
| 828 return 0 if $type eq "unsigned short"; |
| 829 |
| 830 return 1; |
| 831 } |
| 832 |
| 833 # FIXME: partially copied from GetNativeType of CodeGeneratorV8.pm |
| 834 sub IDLTypeToWebkit |
| 835 { |
| 836 my ($type, $isParameter) = @_; |
| 837 |
| 838 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($type); |
| 839 if ($svgNativeType) { |
| 840 if ($svgNativeType =~ /List$/) { |
| 841 return "${svgNativeType}*"; |
| 842 } else { |
| 843 return "RefPtr<${svgNativeType} >"; |
| 844 } |
| 845 } |
| 846 |
| 847 if ($type eq "float" or $type eq "double") { |
| 848 return $type; |
| 849 } |
| 850 |
| 851 return ($isParameter ? "const String&" : "String") if ($type eq "DOMString"
or $type eq "DOMUserData"); |
| 852 return "int" if $type eq "int"; |
| 853 return "int" if $type eq "short" or $type eq "unsigned short"; |
| 854 return "unsigned" if $type eq "unsigned long"; |
| 855 return "int" if $type eq "long"; |
| 856 return "long long" if $type eq "long long"; |
| 857 return "unsigned long long" if $type eq "unsigned long long"; |
| 858 return "bool" if $type eq "boolean"; |
| 859 return "Range::CompareHow" if $type eq "CompareHow"; |
| 860 return "DOMTimeStamp" if $type eq "DOMTimeStamp"; |
| 861 return "unsigned" if $type eq "unsigned int"; |
| 862 # FIXME: EventTarget are evils! |
| 863 # return "Node*" if $type eq "EventTarget" and $isParameter; |
| 864 return "double" if $type eq "Date"; |
| 865 return "ScriptValue" if $type eq "DOMObject"; |
| 866 return "OptionsObject" if $type eq "OptionsObject"; |
| 867 |
| 868 # temporary hack |
| 869 return "RefPtr<NodeFilter>" if $type eq "NodeFilter"; |
| 870 |
| 871 return "RefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValue"; |
| 872 |
| 873 return "RefPtr<IDBKey>" if $type eq "IDBKey"; |
| 874 |
| 875 # necessary as resolvers could be constructed on fly. |
| 876 return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver"; |
| 877 |
| 878 return ($isParameter ? "${type}*" : "RefPtr<${type}>") if IsRefPtrType($type
); |
| 879 |
| 880 return "RefPtr<DOMStringList>" if $type eq "DOMStringList"; |
| 881 |
| 882 return "RefPtr<MediaQueryListListener>" if $type eq "MediaQueryListListener"
; |
| 883 |
| 884 # Default, assume native type is a pointer with same type name as idl type |
| 885 return "${type}*"; |
| 886 } |
| 887 |
| 888 sub GenerateResolver |
| 889 { |
| 890 my ($interfaceName,) = @_; |
| 891 |
| 892 push(@implContent, <<END); |
| 893 |
| 894 static Dart_NativeFunction resolver(Dart_Handle name, int argumentCount) |
| 895 { |
| 896 String str = DartUtilities::dartStringToString(name); |
| 897 |
| 898 END |
| 899 |
| 900 foreach my $nativeDescriptor (@dartNatives) { |
| 901 my $cppCallbackName = $nativeDescriptor->cppCallbackName; |
| 902 my $nativeId = $nativeDescriptor->nativeId; |
| 903 my $argumentCount = $nativeDescriptor->argumentCount; |
| 904 push(@implContent, <<END); |
| 905 if ($argumentCount == argumentCount && str == "$nativeId") |
| 906 return $cppCallbackName; |
| 907 END |
| 908 } |
| 909 |
| 910 push(@implContent, <<END); |
| 911 return 0; |
| 912 } |
| 913 |
| 914 END |
| 915 } |
| 916 |
| 917 sub GenerateScriptConstant |
| 918 { |
| 919 push(@implContent, <<END); |
| 920 |
| 921 static const char* script = |
| 922 END |
| 923 |
| 924 foreach my $element (@dartInterfaceContent, @dartImplContent) { |
| 925 foreach my $line (split("\n", $element)) { |
| 926 $line =~ s/\"/\\\"/g; |
| 927 push(@implContent, " \"$line\\n\"\n") |
| 928 } |
| 929 } |
| 930 |
| 931 push(@implContent, <<END); |
| 932 ; |
| 933 END |
| 934 } |
| 935 |
| 936 sub GenerateCallbackScriptConstant |
| 937 { |
| 938 push(@implContent, <<END); |
| 939 |
| 940 static const char* script = |
| 941 END |
| 942 |
| 943 foreach my $element (@dartInterfaceContent) { |
| 944 foreach my $line (split("\n", $element)) { |
| 945 $line =~ s/\"/\\\"/g; |
| 946 push(@implContent, " \"$line\\n\"\n") |
| 947 } |
| 948 } |
| 949 |
| 950 push(@implContent, <<END); |
| 951 ; |
| 952 END |
| 953 } |
| 954 |
| 955 sub GenerateDartImplementationClassname |
| 956 { |
| 957 my ($interfaceName,) = @_; |
| 958 |
| 959 my $className = ClassName($interfaceName); |
| 960 |
| 961 push(@implContent, <<END); |
| 962 |
| 963 const char* const ${className}::dartImplementationClassName = "${interfaceName}I
mplementation"; |
| 964 END |
| 965 } |
| 966 |
| 967 sub GenerateRegistryEntry |
| 968 { |
| 969 my ($interfaceName,) = @_; |
| 970 |
| 971 push(@implContent, <<END); |
| 972 |
| 973 REGISTER_API($interfaceName) |
| 974 |
| 975 END |
| 976 } |
| 977 |
| 978 sub GenerateImplementationPrologue |
| 979 { |
| 980 my ($dataNode) = @_; |
| 981 |
| 982 my $interfaceName = $dataNode->name; |
| 983 my $className = ClassName($interfaceName); |
| 984 my $internalNamespaceName = "Dart${interfaceName}Internal"; |
| 985 |
| 986 my $conditionalString = GenerateConditionalString($dataNode); |
| 987 |
| 988 push(@implContentHeader, $headerTemplate); |
| 989 |
| 990 push(@implContentHeader, <<END); |
| 991 |
| 992 #include "config.h" |
| 993 #include "$className.h" |
| 994 |
| 995 END |
| 996 |
| 997 push(@implContentHeader, "#if $conditionalString\n\n") if $conditionalString
; |
| 998 |
| 999 $implIncludes{"DartBindingsCommonIncludes.h"} = 1; |
| 1000 |
| 1001 push(@implContent, <<END); |
| 1002 namespace WebCore { |
| 1003 |
| 1004 namespace $internalNamespaceName { |
| 1005 END |
| 1006 } |
| 1007 |
| 1008 sub GenerateImplementationEpilogue |
| 1009 { |
| 1010 my ($dataNode) = @_; |
| 1011 |
| 1012 my $interfaceName = $dataNode->name; |
| 1013 my $className = ClassName($interfaceName); |
| 1014 my $internalNamespaceName = "Dart${interfaceName}Internal"; |
| 1015 |
| 1016 my $conditionalString = GenerateConditionalString($dataNode); |
| 1017 |
| 1018 push(@implContent, "\n// Class info.\n"); |
| 1019 GenerateResolver($interfaceName); |
| 1020 GenerateScriptConstant(); |
| 1021 |
| 1022 push(@implContent, "}\n"); |
| 1023 |
| 1024 GenerateDartImplementationClassname($interfaceName); |
| 1025 GenerateRegistryEntry($interfaceName); |
| 1026 |
| 1027 push(@implContent, <<END); |
| 1028 } |
| 1029 END |
| 1030 |
| 1031 push(@implContent, "\n#endif // $conditionalString\n") if $conditionalString
; |
| 1032 |
| 1033 # We've already added the header for this file in implFixedHeader, so remove |
| 1034 # it from implIncludes to ensure we don't #include it twice. |
| 1035 delete $implIncludes{"$className.h"}; |
| 1036 } |
| 1037 |
| 1038 sub GenerateCallbackDartInterface |
| 1039 { |
| 1040 my ($object, $dataNode) = @_; |
| 1041 my $function = $dataNode->functions->[0]; |
| 1042 my $functionDecl = DartInterfaceMethodDeclaration($interfaceName, $function,
$dataNode->name); |
| 1043 push(@dartInterfaceContent, $headerTemplate); |
| 1044 push(@dartInterfaceContent, <<END); |
| 1045 typedef $functionDecl; |
| 1046 END |
| 1047 } |
| 1048 |
| 1049 sub FormatCallbackArgument |
| 1050 { |
| 1051 my ($argument,) = @_; |
| 1052 my $webkitType = IDLTypeToWebkit($argument->type, 1); |
| 1053 my $name = $argument->name; |
| 1054 return "$webkitType $name"; |
| 1055 } |
| 1056 |
| 1057 sub GenerateCallbackHeader |
| 1058 { |
| 1059 my ($object, $dataNode) = @_; |
| 1060 |
| 1061 my $interfaceName = $dataNode->name; |
| 1062 my $className = ClassName($interfaceName); |
| 1063 my $webkitClassName = GetNativeTypeForConversions($interfaceName); |
| 1064 |
| 1065 my $conditionalString = GenerateConditionalString($dataNode); |
| 1066 |
| 1067 push(@headerContent, $headerTemplate); |
| 1068 |
| 1069 push(@headerContent, "\n#if ${conditionalString}\n") if $conditionalString; |
| 1070 push(@headerContent, <<END); |
| 1071 |
| 1072 #ifndef ${className}_h |
| 1073 #define ${className}_h |
| 1074 |
| 1075 END |
| 1076 |
| 1077 AddHeaderClassIncludes($interfaceName); |
| 1078 |
| 1079 $headerIncludes{"ActiveDOMCallback.h"} = 1; |
| 1080 $headerIncludes{"DartCallback.h"} = 1; |
| 1081 push(@headerContent, GenerateIncludes(keys(%headerIncludes))); |
| 1082 |
| 1083 my @handleEventMethods = (); |
| 1084 foreach my $function (@{$dataNode->functions}) { |
| 1085 die "Expect only handleEvent methods" if ($function->signature->type ne
"boolean") || ($function->signature->name ne "handleEvent"); |
| 1086 |
| 1087 my $arguments = join ", ", map { FormatCallbackArgument($_); } @{$functi
on->parameters}; |
| 1088 push(@handleEventMethods, " virtual bool handleEvent($arguments);"); |
| 1089 } |
| 1090 my $methods = join "\n", @handleEventMethods; |
| 1091 |
| 1092 push(@headerContent, <<END); |
| 1093 |
| 1094 namespace WebCore { |
| 1095 |
| 1096 class ScriptExecutionContext; |
| 1097 |
| 1098 class $className : public $interfaceName, public ActiveDOMCallback { |
| 1099 public: |
| 1100 typedef $interfaceName NativeType; |
| 1101 |
| 1102 static PassRefPtr<NativeType> toNative(Dart_Handle object, Dart_Handle& exce
ption) |
| 1103 { |
| 1104 return adoptRef(new $className(object, exception, DartUtilities::scriptE
xecutionContext())); |
| 1105 } |
| 1106 |
| 1107 $methods |
| 1108 |
| 1109 private: |
| 1110 $className(Dart_Handle object, Dart_Handle& exception, ScriptExecutionContex
t* context) |
| 1111 : ActiveDOMCallback(context) |
| 1112 , m_callback(object, exception) |
| 1113 { |
| 1114 } |
| 1115 |
| 1116 DartCallback m_callback; |
| 1117 }; |
| 1118 |
| 1119 } |
| 1120 |
| 1121 #endif // ${className}_h |
| 1122 END |
| 1123 |
| 1124 push(@headerContent, "\n#endif // ${conditionalString}\n") if $conditionalSt
ring; |
| 1125 } |
| 1126 |
| 1127 sub GenerateCallbackImplementation |
| 1128 { |
| 1129 my ($object, $dataNode) = @_; |
| 1130 |
| 1131 my $interfaceName = $dataNode->name; |
| 1132 my $className = ClassName($interfaceName); |
| 1133 my $internalNamespaceName = "Dart${interfaceName}Internal"; |
| 1134 |
| 1135 my $conditionalString = GenerateConditionalString($dataNode); |
| 1136 |
| 1137 push(@implContentHeader, $headerTemplate); |
| 1138 |
| 1139 $implIncludes{"DartBindingsCommonIncludes.h"} = 1; |
| 1140 |
| 1141 push(@implContentHeader, <<END); |
| 1142 |
| 1143 #include "config.h" |
| 1144 #include "$className.h" |
| 1145 |
| 1146 END |
| 1147 |
| 1148 push(@implContentHeader, "#if $conditionalString\n\n") if $conditionalString
; |
| 1149 |
| 1150 my @handleEventMethods = (); |
| 1151 foreach my $function (@{$dataNode->functions}) { |
| 1152 die "Expect only handleEvent methods" if ($function->signature->type ne
"boolean") || ($function->signature->name ne "handleEvent"); |
| 1153 |
| 1154 my $arguments = join ", ", map { FormatCallbackArgument($_); } @{$functi
on->parameters}; |
| 1155 my $parameters = join ", ", map { $_->name; } @{$function->parameters}; |
| 1156 push(@handleEventMethods, <<END); |
| 1157 bool ${className}::handleEvent($arguments) |
| 1158 { |
| 1159 return m_callback.handleEvent($parameters); |
| 1160 } |
| 1161 END |
| 1162 } |
| 1163 my $methods = join "\n", @handleEventMethods; |
| 1164 |
| 1165 push(@implContent, <<END); |
| 1166 namespace WebCore { |
| 1167 |
| 1168 $methods |
| 1169 |
| 1170 namespace $internalNamespaceName { |
| 1171 END |
| 1172 |
| 1173 GenerateCallbackScriptConstant(); |
| 1174 push(@implContent, "}\n"); |
| 1175 |
| 1176 push(@implContent, <<END); |
| 1177 |
| 1178 REGISTER_CALLBACK($interfaceName) |
| 1179 |
| 1180 } |
| 1181 END |
| 1182 |
| 1183 push(@implContent, "\n#endif // $conditionalString\n") if $conditionalString
; |
| 1184 |
| 1185 # We've already added the header for this file in implFixedHeader, so remove |
| 1186 # it from implIncludes to ensure we don't #include it twice. |
| 1187 delete $implIncludes{"$className.h"}; |
| 1188 } |
| 1189 |
| 1190 sub DartMethodDeclaration |
| 1191 { |
| 1192 my ($functionName, $parameters, $returnType) = @_; |
| 1193 |
| 1194 $returnType = IDLTypeToDart($codeGenerator->StripModule($returnType)); |
| 1195 return "$returnType $functionName($parameters)"; |
| 1196 } |
| 1197 |
| 1198 sub DartInterfaceMethodDeclaration |
| 1199 { |
| 1200 my ($interfaceName, $function, $name) = @_; |
| 1201 |
| 1202 my $parameters; |
| 1203 if (HasOverloads($function)) { |
| 1204 my $maxParameterCount = MaxOverloadParameterCount($function); |
| 1205 $parameters = DartAnonymousNamedOptionalParameters($maxParameterCount); |
| 1206 } else { |
| 1207 $parameters = DartParameters($function, $function->parameters, 1); |
| 1208 } |
| 1209 return DartMethodDeclaration($name || DartName($interfaceName, $function->si
gnature->name), $parameters, $function->signature->type); |
| 1210 } |
| 1211 |
| 1212 sub DartParameters |
| 1213 { |
| 1214 my ($function, $parameters, $useDefaultValues) = @_; |
| 1215 |
| 1216 my @mandatoryParameters = (); |
| 1217 my @optionalParameters = (); |
| 1218 foreach my $parameter (@{$parameters}) { |
| 1219 # FIXME: parameter modifiers. |
| 1220 my $type = IDLTypeToDart($parameter->type); |
| 1221 my $name = $parameter->name; |
| 1222 if ($useDefaultValues && IsParameterOptionalInWebKit($parameter)) { |
| 1223 push(@optionalParameters, "$type ${name}"); |
| 1224 } else { |
| 1225 push(@mandatoryParameters, "$type ${name}"); |
| 1226 } |
| 1227 } |
| 1228 if ($function->signature->extendedAttributes->{CustomArgumentHandling}) { |
| 1229 die "Optional parameters in function with custom argument handling. " if
@optionalParameters; |
| 1230 push(@mandatoryParameters, "argument"); |
| 1231 } |
| 1232 my $dartParameters = join(", ", @mandatoryParameters); |
| 1233 if (@optionalParameters) { |
| 1234 $dartParameters .= ", " if $dartParameters; |
| 1235 $dartParameters .= "[" . join(", ", @optionalParameters) . "]"; |
| 1236 } |
| 1237 return $dartParameters; |
| 1238 } |
| 1239 |
| 1240 sub DartParameterCount |
| 1241 { |
| 1242 my ($function, $parameters) = @_; |
| 1243 |
| 1244 my $parameterCount = @{$parameters}; |
| 1245 $parameterCount += 1 if $function->signature->extendedAttributes->{CustomArg
umentHandling}; |
| 1246 return $parameterCount; |
| 1247 } |
| 1248 |
| 1249 sub DartAnonymousArguments |
| 1250 { |
| 1251 my ($parameterCount) = @_; |
| 1252 return "" unless $parameterCount; |
| 1253 return join(", ", map { "_arg$_" } (0..$parameterCount - 1)); |
| 1254 } |
| 1255 |
| 1256 sub DartAnonymousNamedOptionalParameters |
| 1257 { |
| 1258 my ($parameterCount) = @_; |
| 1259 return "" unless $parameterCount; |
| 1260 return "[" . DartAnonymousArguments($parameterCount) . "]"; |
| 1261 } |
| 1262 |
| 1263 sub CreateFunctionNativeDescriptor |
| 1264 { |
| 1265 my ($interfaceName, $functionName, $argumentCount) = @_; |
| 1266 my $descriptor = NativeBindingDescriptor->new( |
| 1267 cppCallbackName => "${functionName}Callback", |
| 1268 nativeId => "${interfaceName}_${functionName}_Callback", |
| 1269 argumentCount => $argumentCount); |
| 1270 push(@dartNatives, $descriptor); |
| 1271 return $descriptor; |
| 1272 } |
| 1273 |
| 1274 sub CreateGetterNativeDescriptor |
| 1275 { |
| 1276 my ($interfaceName, $attributeName) = @_; |
| 1277 my $descriptor = NativeBindingDescriptor->new( |
| 1278 cppCallbackName => "${attributeName}Getter", |
| 1279 nativeId => "${interfaceName}_${attributeName}_Getter", |
| 1280 argumentCount => 1); |
| 1281 push(@dartNatives, $descriptor); |
| 1282 return $descriptor; |
| 1283 } |
| 1284 |
| 1285 sub CreateSetterNativeDescriptor |
| 1286 { |
| 1287 my ($interfaceName, $attributeName) = @_; |
| 1288 my $descriptor = NativeBindingDescriptor->new( |
| 1289 cppCallbackName => "${attributeName}Setter", |
| 1290 nativeId => "${interfaceName}_${attributeName}_Setter", |
| 1291 argumentCount => 2); |
| 1292 push(@dartNatives, $descriptor); |
| 1293 return $descriptor; |
| 1294 } |
| 1295 |
| 1296 sub GenerateDartOptionalArgumentsResolver |
| 1297 { |
| 1298 my ($interfaceName, $function) = @_; |
| 1299 |
| 1300 my $interfaceMethodDeclaration = DartInterfaceMethodDeclaration($interfaceNa
me, $function); |
| 1301 push(@dartInterfaceContent, " $interfaceMethodDeclaration;\n"); |
| 1302 |
| 1303 my @resolver = (); |
| 1304 push(@resolver, " $interfaceMethodDeclaration {\n"); |
| 1305 my @parameters = (); |
| 1306 foreach my $parameterIndex (0..@{$function->parameters}) { |
| 1307 my $parameter = @{$function->parameters}[$parameterIndex]; |
| 1308 if (!$parameter || IsParameterOptionalInWebKit($parameter)) { |
| 1309 my $functionName = GenerateNativeBinding($interfaceName, $function,
\@parameters); |
| 1310 if ($parameter) { |
| 1311 my $parameterName = $parameter->name; |
| 1312 push(@resolver, " if ($parameterName === null)\n "); |
| 1313 } |
| 1314 my $parameterNames = join(", ", map { $_->name } @parameters); |
| 1315 push(@resolver, " return $functionName($parameterNames);\n"); |
| 1316 } |
| 1317 push(@parameters, $parameter); |
| 1318 } |
| 1319 push(@resolver, " }\n"); |
| 1320 push(@dartImplContent, join("", @resolver)); |
| 1321 } |
| 1322 |
| 1323 sub GenerateDartOverloadResolver |
| 1324 { |
| 1325 my ($interfaceName, $function) = @_; |
| 1326 |
| 1327 # Generate code for choosing the correct overload to call. Overloads are |
| 1328 # chosen based on the the type of the arguments. When more than a single |
| 1329 # overload is applicable, precedence is given according to the order of |
| 1330 # declaration in the IDL. |
| 1331 |
| 1332 my $interfaceMethodDeclaration = DartInterfaceMethodDeclaration($interfaceNa
me, $function); |
| 1333 push(@dartInterfaceContent, " $interfaceMethodDeclaration;\n"); |
| 1334 |
| 1335 my @resolver = (); |
| 1336 push(@resolver, " $interfaceMethodDeclaration {\n"); |
| 1337 my $maxParameterCount = MaxOverloadParameterCount($function); |
| 1338 foreach my $overload (@{$function->{overloads}}) { |
| 1339 my @parameters = (); |
| 1340 my @parameterNames = (); |
| 1341 my @parameterChecks = map { "_arg$_ === null" } (0..$maxParameterCount -
1); |
| 1342 foreach my $parameterIndex (0..@{$overload->parameters}) { |
| 1343 my $parameter = @{$overload->parameters}[$parameterIndex]; |
| 1344 if (!$parameter || IsParameterOptionalInWebKit($parameter)) { |
| 1345 my $functionName = GenerateNativeBinding($interfaceName, $overlo
ad, \@parameters); |
| 1346 my $parameterNames = join(", ", @parameterNames); |
| 1347 my $parameterChecks = join(" && ", @parameterChecks); |
| 1348 push(@resolver, <<END); |
| 1349 if ($parameterChecks) |
| 1350 return $functionName($parameterNames); |
| 1351 END |
| 1352 } |
| 1353 last if !$parameter; |
| 1354 my $idlType = $codeGenerator->StripModule($parameter->type); |
| 1355 my $dartType = IDLTypeToDart($idlType); |
| 1356 push(@parameterNames, "_arg$parameterIndex"); |
| 1357 $parameterChecks[$parameterIndex] = "_arg$parameterIndex is $dartTyp
e"; |
| 1358 push(@parameters, $parameter); |
| 1359 } |
| 1360 } |
| 1361 |
| 1362 # FIXME: throw appropriate exception when overload is not found. |
| 1363 push(@resolver, <<END); |
| 1364 throw "Failed to find overload of @{[$function->signature->name]}"; |
| 1365 } |
| 1366 END |
| 1367 push(@dartImplContent, join("", @resolver)); |
| 1368 } |
| 1369 |
| 1370 sub ParentInterface |
| 1371 { |
| 1372 my $dataNode = shift; |
| 1373 |
| 1374 foreach (@{$dataNode->parents}) { |
| 1375 my $parent = $codeGenerator->StripModule($_); |
| 1376 if ($parent eq "EventTarget") { |
| 1377 next; |
| 1378 } |
| 1379 return $parent; |
| 1380 } |
| 1381 } |
| 1382 |
| 1383 my %excludedInterfaces = ( |
| 1384 "SVGURIReference" => 1, # Is not in the list of SVG idls files (see WebCore.gy
pi), v8 bindings do not immediately compile |
| 1385 # Explicitly excluded in WebCore.gyp |
| 1386 "ElementTimeControl" => 1, |
| 1387 "SVGExternalResourcesRequired" => 1, |
| 1388 "SVGFilterPrimitiveStandardAttributes" => 1, |
| 1389 "SVGFitToViewBox" => 1, |
| 1390 "SVGLangSpace" => 1, |
| 1391 "SVGLocatable" => 1, |
| 1392 "SVGStylable" => 1, |
| 1393 "SVGTests" => 1, |
| 1394 "SVGTransformable" => 1, |
| 1395 "SVGViewSpec" => 1, |
| 1396 "SVGZoomAndPan" => 1, |
| 1397 ); |
| 1398 |
| 1399 sub ListLike |
| 1400 { |
| 1401 my ($elementType, $needsAuxiliaryAccessors) = @_; |
| 1402 |
| 1403 my @auxiliaryMethods = (); |
| 1404 if ($needsAuxiliaryAccessors) { |
| 1405 push(@auxiliaryMethods, ["$elementType operator [] (int index)", "numeri
cIndexGetter", 2]); |
| 1406 push(@auxiliaryMethods, ["void operator []= (int index, $elementType val
ue)", "numericIndexSetter", 3]); |
| 1407 } |
| 1408 |
| 1409 return IDLTypeInfoStruct->new( |
| 1410 additionalInterfaces => ["List<$elementType>"], |
| 1411 superClass => "ListBase<$elementType>", |
| 1412 auxilaryMethods => \@auxiliaryMethods |
| 1413 ); |
| 1414 } |
| 1415 |
| 1416 sub MapLike |
| 1417 { |
| 1418 # FIXME: most probably we need to deduce more types using hints like |
| 1419 # HasNameGetter, CustomDeleteProperty, CustomGetPropertyNames, DelegatingPut
Function |
| 1420 # attributes. |
| 1421 # FIXME: technically at least DOMStringMap.setItem and DOMStringMap.item cou
ld be automatically |
| 1422 # generated and then used from [] and []=. I don't do it for now not to mes
s up with IDLs too |
| 1423 # much. |
| 1424 # FIXME: support removal of elements if allowed (it is at least for DOMStrin
gMap.) |
| 1425 my ($interfaceName, $keyType, $elementType) = @_; |
| 1426 return IDLTypeInfoStruct->new( |
| 1427 additionalInterfaces => ["Map<$keyType, $elementType>"], |
| 1428 superClass => "MapBase<$keyType, $elementType>", |
| 1429 auxilaryMethods => [ |
| 1430 ["Collection<$keyType> getKeys()", "getKeys", 1], |
| 1431 ["$elementType operator [] ($keyType k)", "item", 2], |
| 1432 ["operator []= ($keyType k, $elementType v)", "setItem", 3], |
| 1433 ["$elementType remove($keyType k)", "deleteItem", 2], |
| 1434 ], |
| 1435 ); |
| 1436 } |
| 1437 |
| 1438 my %idlTypeInfoOverrides = ( |
| 1439 "CanvasPixelArray" => ListLike("int", 1), |
| 1440 "DOMStringMap" => MapLike("DOMStringMap", "String", "String"), |
| 1441 "HTMLCollection" => ListLike("Node"), |
| 1442 "NodeList" => ListLike("Node"), |
| 1443 "StyleSheetList" => ListLike("StyleSheet"), |
| 1444 ); |
| 1445 |
| 1446 # FIXME: turn into the single IDL type info registry. |
| 1447 sub IDLTypeInfo |
| 1448 { |
| 1449 my ($dataNode,) = @_; |
| 1450 my $override = $idlTypeInfoOverrides{$dataNode->name}; |
| 1451 return $override if $override; |
| 1452 |
| 1453 my $parentInterface = ParentInterface($dataNode); |
| 1454 return IDLTypeInfoStruct->new( |
| 1455 superClass => $parentInterface ? "${parentInterface}Implementation" : "D
OMType", |
| 1456 ); |
| 1457 } |
| 1458 |
| 1459 sub GenerateSource |
| 1460 { |
| 1461 my ($object, $dataNode) = @_; |
| 1462 |
| 1463 my $interfaceName = $dataNode->name; |
| 1464 my $w3cInterfaceName = IDLTypeToW3C($interfaceName); |
| 1465 |
| 1466 push(@dartInterfaceContent, $headerTemplate); |
| 1467 |
| 1468 # Build extends clause if any. |
| 1469 my $extendsClause = ""; |
| 1470 my $parentInterface = ParentInterface($dataNode); |
| 1471 my $isEventTarget = $dataNode->extendedAttributes->{EventTarget}; |
| 1472 my @implementedInterfaces = (); |
| 1473 push(@implementedInterfaces, $parentInterface) if $parentInterface; |
| 1474 push(@implementedInterfaces, "EventTarget") if $isEventTarget; |
| 1475 |
| 1476 push(@implementedInterfaces, @{IDLTypeInfo($dataNode)->additionalInterfaces}
); |
| 1477 push(@implementedInterfaces, @allParents); |
| 1478 |
| 1479 if (@implementedInterfaces) { |
| 1480 $extendsClause = " extends " . join(", ", @implementedInterfaces); |
| 1481 } |
| 1482 |
| 1483 # Build default clause if any. |
| 1484 my $defaultClause = ""; |
| 1485 if (HasCustomConstructor($dataNode)) { |
| 1486 $defaultClause = " factory ${w3cInterfaceName}Implementation"; |
| 1487 push(@customCallbackDeclarations, GenerateCustomCallbackDeclaration("con
structorCallback")); |
| 1488 } |
| 1489 |
| 1490 push(@dartInterfaceContent, "\ninterface ${w3cInterfaceName}${extendsClause}
${defaultClause} {\n"); |
| 1491 push(@dartInterfaceContent, "\n // Constants.\n"); |
| 1492 foreach my $constant (@{$dataNode->constants}) { |
| 1493 my $name = $constant->name; |
| 1494 my $value = $constant->value; |
| 1495 |
| 1496 push(@dartInterfaceContent, " static final int $name = $value;\n"); |
| 1497 } |
| 1498 |
| 1499 # Generate Dart implementation prologue. |
| 1500 my $implementationClassName = "${interfaceName}Implementation"; |
| 1501 my $superClass = IDLTypeInfo($dataNode)->superClass; |
| 1502 push(@dartImplContent, $headerTemplate); |
| 1503 push(@dartImplContent, "\nclass $implementationClassName extends $superClass
implements $interfaceName {\n"); |
| 1504 |
| 1505 GenerateImplementationPrologue($dataNode); |
| 1506 |
| 1507 # Generate fields. |
| 1508 # FIXME: special treatment of constructors attributes (see V8 code generator
). |
| 1509 push(@dartInterfaceContent, "\n // Fields.\n"); |
| 1510 push(@dartImplContent, "\n // Fields.\n"); |
| 1511 push(@implContent, "\n// Getters & setters.\n"); |
| 1512 foreach my $attribute (@{$dataNode->attributes}) { |
| 1513 next if IgnoredAttribute($interfaceName, $attribute); |
| 1514 GenerateField($interfaceName, $attribute); |
| 1515 } |
| 1516 |
| 1517 # Generate methods. |
| 1518 push(@dartInterfaceContent, "\n // Methods.\n"); |
| 1519 push(@dartImplContent, "\n // Methods.\n"); |
| 1520 push(@implContent, "\n// Callbacks.\n"); |
| 1521 foreach my $function (@{$dataNode->functions}) { |
| 1522 next if IgnoredCallback($interfaceName, $function); |
| 1523 next if HasOverloads($function) && $function->{overloadIndex} != 1; |
| 1524 GenerateMethod($interfaceName, $function); |
| 1525 } |
| 1526 |
| 1527 foreach my $auxilaryMethod (@{IDLTypeInfo($dataNode)->auxilaryMethods}) { |
| 1528 my $dartDeclaration = $auxilaryMethod->[0]; |
| 1529 my $descriptor = CreateFunctionNativeDescriptor($interfaceName, $auxilar
yMethod->[1], $auxilaryMethod->[2]); |
| 1530 my $nativeId = $descriptor->nativeId; |
| 1531 push(@dartImplContent, " $dartDeclaration native \"$nativeId\";\n"); |
| 1532 push(@customCallbackDeclarations, GenerateCustomCallbackDeclaration($des
criptor->cppCallbackName)); |
| 1533 } |
| 1534 |
| 1535 if (HasCustomConstructor($dataNode)) { |
| 1536 my $parameterCount = $dataNode->extendedAttributes->{"ConstructorParamet
ers"} || 0; |
| 1537 my $descriptor = CreateFunctionNativeDescriptor($interfaceName, "constru
ctor", 1 + $parameterCount); |
| 1538 my $nativeId = $descriptor->nativeId; |
| 1539 my $parameters = DartAnonymousNamedOptionalParameters($parameterCount); |
| 1540 my $arguments = DartAnonymousArguments($parameterCount); |
| 1541 push(@dartInterfaceContent, " $w3cInterfaceName($parameters);\n"); |
| 1542 push(@dartImplContent, <<END); |
| 1543 $implementationClassName($parameters) { |
| 1544 this._bind($arguments); |
| 1545 } |
| 1546 END |
| 1547 push(@dartImplContent, " void _bind($arguments) native \"$nativeId\";\n
"); |
| 1548 } |
| 1549 |
| 1550 # Generate implementation support. |
| 1551 # FIXME: get rid of implementation support completely. |
| 1552 push(@dartImplContent, <<END); |
| 1553 // Implementation support. |
| 1554 static $implementationClassName _create$implementationClassName() => new $impl
ementationClassName._create$implementationClassName(); |
| 1555 $implementationClassName._create$implementationClassName(); |
| 1556 |
| 1557 String get typeName() => \"$interfaceName\"; |
| 1558 END |
| 1559 |
| 1560 push(@dartInterfaceContent, "}\n"); |
| 1561 push(@dartImplContent, "}\n"); |
| 1562 |
| 1563 if (HasW3CName($interfaceName)) { |
| 1564 push(@dartInterfaceContent, "\ninterface ${interfaceName} extends ${w3cI
nterfaceName} {}\n"); |
| 1565 } |
| 1566 |
| 1567 GenerateImplementationEpilogue($dataNode); |
| 1568 } |
| 1569 |
| 1570 sub GenerateField |
| 1571 { |
| 1572 my ($interfaceName, $attribute) = @_; |
| 1573 |
| 1574 my $attributeName = DartName($interfaceName, $attribute->signature->name); |
| 1575 my $attributeType = $attribute->signature->type; |
| 1576 my $dartAttributeType = IDLTypeToDart($attributeType); |
| 1577 |
| 1578 # Generate field declaration. |
| 1579 my $final = HasSetter($attribute) ? "" : "final "; |
| 1580 push(@dartInterfaceContent, " $final$dartAttributeType $attributeName;\n"); |
| 1581 |
| 1582 # Generate getter implementation. |
| 1583 my $getterDescriptor = CreateGetterNativeDescriptor($interfaceName, $attribu
teName); |
| 1584 my $getterNativeId = $getterDescriptor->nativeId; |
| 1585 push(@dartImplContent, " $dartAttributeType get $attributeName() native \"$
getterNativeId\";\n"); |
| 1586 if (HasCustomGetter($attribute)) { |
| 1587 push(@customCallbackDeclarations, GenerateCustomCallbackDeclaration($get
terDescriptor->cppCallbackName)); |
| 1588 } else { |
| 1589 my $invocationPrefix = $codeGenerator->GetterExpressionPrefix(\%implIncl
udes, $interfaceName, $attribute); |
| 1590 my $raisesExceptions = scalar(@{$attribute->getterExceptions}); |
| 1591 GenerateGenericBindingsFunction($getterDescriptor->cppCallbackName, $int
erfaceName, $invocationPrefix, [], $attributeType, $raisesExceptions, $attribute
->signature->extendedAttributes); |
| 1592 } |
| 1593 |
| 1594 return unless HasSetter($attribute); |
| 1595 |
| 1596 # Generate setter implementation. |
| 1597 my $setterDescriptor = CreateSetterNativeDescriptor($interfaceName, $attribu
teName); |
| 1598 my $setterNativeId = $setterDescriptor->nativeId; |
| 1599 push(@dartImplContent, " void set $attributeName($dartAttributeType) native
\"$setterNativeId\";\n"); |
| 1600 if (HasCustomSetter($attribute)) { |
| 1601 push(@customCallbackDeclarations, GenerateCustomCallbackDeclaration($set
terDescriptor->cppCallbackName)); |
| 1602 } else { |
| 1603 my $invocationPrefix = $codeGenerator->SetterExpressionPrefix(\%implIncl
udes, $interfaceName, $attribute); |
| 1604 my $raisesExceptions = scalar(@{$attribute->setterExceptions}); |
| 1605 GenerateGenericBindingsFunction($setterDescriptor->cppCallbackName, $int
erfaceName, $invocationPrefix, [$attribute->signature], "void", $raisesException
s, $attribute->signature->extendedAttributes, 1); |
| 1606 } |
| 1607 } |
| 1608 |
| 1609 sub GenerateMethod |
| 1610 { |
| 1611 my ($interfaceName, $function) = @_; |
| 1612 |
| 1613 my $functionName = DartName($interfaceName, $function->signature->name); |
| 1614 |
| 1615 if (!$function->signature->extendedAttributes->{"Custom"}) { |
| 1616 if (HasOverloads($function)) { |
| 1617 GenerateDartOverloadResolver($interfaceName, $function); |
| 1618 } elsif (HasOptionalParameters($function)) { |
| 1619 GenerateDartOptionalArgumentsResolver($interfaceName, $function); |
| 1620 } else { |
| 1621 my $interfaceMethodDeclaration = DartInterfaceMethodDeclaration($int
erfaceName, $function); |
| 1622 push(@dartInterfaceContent, " $interfaceMethodDeclaration;\n"); |
| 1623 my $bindingFunctionName = GenerateNativeBinding($interfaceName, $fun
ction, $function->parameters); |
| 1624 die if $bindingFunctionName ne $functionName; |
| 1625 } |
| 1626 } else { |
| 1627 my $parameters; |
| 1628 my $parameterCount; |
| 1629 if (HasOverloads($function)) { |
| 1630 $parameterCount = MaxOverloadParameterCount($function); |
| 1631 $parameters = DartAnonymousNamedOptionalParameters($parameterCount); |
| 1632 } else { |
| 1633 $parameters = DartParameters($function, $function->parameters, 1); |
| 1634 $parameterCount = DartParameterCount($function, $function->parameter
s); |
| 1635 } |
| 1636 my $methodDeclaration = DartMethodDeclaration($functionName, $parameters
, $function->signature->type); |
| 1637 my $descriptor = CreateFunctionNativeDescriptor($interfaceName, $functio
nName, 1 + $parameterCount); |
| 1638 my $nativeId = $descriptor->nativeId; |
| 1639 push(@dartInterfaceContent, " $methodDeclaration;\n"); |
| 1640 push(@dartImplContent, " $methodDeclaration native \"$nativeId\";\n"); |
| 1641 push(@customCallbackDeclarations, GenerateCustomCallbackDeclaration($des
criptor->cppCallbackName)); |
| 1642 } |
| 1643 |
| 1644 # If there is a method named "item", duplicate it as operator []. |
| 1645 if ($functionName eq "item") { |
| 1646 # Consider operator [] should support overloads and optional arguments. |
| 1647 die "$interfaceName.item has overloads" if HasOverloads($function); |
| 1648 die "$interfaceName.item has optional arguments" if HasOptionalParameter
s($function); |
| 1649 |
| 1650 my $subscriptOperatorDeclaration = DartInterfaceMethodDeclaration($inter
faceName, $function, "operator []"); |
| 1651 my $parameters = join ", ", (map { $_->name } @{$function->parameters}); |
| 1652 push(@dartInterfaceContent, " $subscriptOperatorDeclaration;\n"); |
| 1653 push(@dartImplContent, " $subscriptOperatorDeclaration { return item($p
arameters); }\n"); |
| 1654 } |
| 1655 } |
| 1656 |
| 1657 sub GenerateNativeBinding |
| 1658 { |
| 1659 my ($interfaceName, $function, $parameters) = @_; |
| 1660 |
| 1661 my $functionName = DartName($interfaceName, $function->signature->name); |
| 1662 if (HasOverloads($function)) { |
| 1663 $functionName .= $function->{overloadIndex}; |
| 1664 } |
| 1665 if (HasOptionalParameters($function)) { |
| 1666 $functionName .= "_" . @$parameters; |
| 1667 } |
| 1668 |
| 1669 my $extendedAttributes = $function->signature->extendedAttributes; |
| 1670 my $returnType = $function->signature->type; |
| 1671 |
| 1672 my $dartParameters = DartParameters($function, $parameters, 0); |
| 1673 my $dartParameterCount = DartParameterCount($function, $parameters); |
| 1674 my $methodDeclaration = DartMethodDeclaration($functionName, $dartParameters
, $returnType); |
| 1675 my $descriptor = CreateFunctionNativeDescriptor($interfaceName, $functionNam
e, 1 + $dartParameterCount); |
| 1676 my $nativeId = $descriptor->nativeId; |
| 1677 push(@dartImplContent, <<END); |
| 1678 $methodDeclaration native "$nativeId"; |
| 1679 END |
| 1680 |
| 1681 my $invocationPrefix; |
| 1682 if ($extendedAttributes->{ImplementationFunction}) { |
| 1683 $invocationPrefix = $extendedAttributes->{ImplementationFunction} . "("; |
| 1684 } else { |
| 1685 $invocationPrefix = $function->signature->name . "("; |
| 1686 } |
| 1687 my $raisesExceptions = scalar(@{$function->raisesExceptions}); |
| 1688 GenerateGenericBindingsFunction($descriptor->cppCallbackName, $interfaceName
, $invocationPrefix, $parameters, $returnType, $raisesExceptions, $extendedAttri
butes); |
| 1689 |
| 1690 return $functionName; |
| 1691 } |
| 1692 |
| 1693 # Internal helper |
| 1694 sub WriteData |
| 1695 { |
| 1696 if (defined($IMPL)) { |
| 1697 # Write content to file. |
| 1698 print $IMPL @implContentHeader; |
| 1699 |
| 1700 print $IMPL @implFixedHeader; |
| 1701 |
| 1702 print $IMPL GenerateIncludes(keys(%implIncludes)); |
| 1703 |
| 1704 print $IMPL "\n"; |
| 1705 print $IMPL @implContent; |
| 1706 close($IMPL); |
| 1707 undef($IMPL); |
| 1708 |
| 1709 %implIncludes = (); |
| 1710 @implFixedHeader = (); |
| 1711 @implHeaderContent = (); |
| 1712 @implContent = (); |
| 1713 @dartNatives = (); |
| 1714 } |
| 1715 |
| 1716 if (defined($HEADER)) { |
| 1717 # Write content to file. |
| 1718 print $HEADER @headerContent; |
| 1719 close($HEADER); |
| 1720 undef($HEADER); |
| 1721 |
| 1722 @headerContent = (); |
| 1723 } |
| 1724 |
| 1725 if (defined($DART_INTERFACE)) { |
| 1726 # Write content of Dart file. |
| 1727 print $DART_INTERFACE @dartInterfaceContent; |
| 1728 close($DART_INTERFACE); |
| 1729 undef($DART_INTERFACE); |
| 1730 |
| 1731 @dartInterfaceContent = (); |
| 1732 } |
| 1733 |
| 1734 if (defined($DART_IMPL)) { |
| 1735 # Write content of Dart file. |
| 1736 print $DART_IMPL @dartImplContent; |
| 1737 close($DART_IMPL); |
| 1738 undef($DART_IMPL); |
| 1739 |
| 1740 @dartImplContent = (); |
| 1741 } |
| 1742 } |
OLD | NEW |