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