Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(243)

Side by Side Diff: Source/WebCore/bindings/scripts/CodeGeneratorDart.pm

Issue 8802010: Dart bindings for WebKit (Closed) Base URL: http://svn.webkit.org/repository/webkit/trunk
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698