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