| Index: Source/WebCore/bindings/scripts/CodeGeneratorDart.pm
|
| diff --git a/Source/WebCore/bindings/scripts/CodeGeneratorDart.pm b/Source/WebCore/bindings/scripts/CodeGeneratorDart.pm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..352084eb48a25b13f6c4aa418e0ba7f9bcef13fc
|
| --- /dev/null
|
| +++ b/Source/WebCore/bindings/scripts/CodeGeneratorDart.pm
|
| @@ -0,0 +1,1742 @@
|
| +# Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
|
| +# Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
|
| +# Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
|
| +# Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
|
| +# Copyright (C) 2006 Apple Computer, Inc.
|
| +# Copyright (C) 2007, 2008, 2009 Google Inc.
|
| +# Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
|
| +# Copyright (C) Research In Motion Limited 2010. All rights reserved.
|
| +# Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
|
| +#
|
| +# This library is free software; you can redistribute it and/or
|
| +# modify it under the terms of the GNU Library General Public
|
| +# License as published by the Free Software Foundation; either
|
| +# version 2 of the License, or (at your option) any later version.
|
| +#
|
| +# This library is distributed in the hope that it will be useful,
|
| +# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
| +# Library General Public License for more details.
|
| +#
|
| +# You should have received a copy of the GNU Library General Public License
|
| +# along with this library; see the file COPYING.LIB. If not, write to
|
| +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
| +# Boston, MA 02111-1307, USA.
|
| +#
|
| +
|
| +package CodeGeneratorDart;
|
| +
|
| +use Class::Struct;
|
| +
|
| +my $outputDir = "";
|
| +my $outputHeadersDir = "";
|
| +
|
| +my @headerContent = ();
|
| +my %headerIncludes = ();
|
| +
|
| +my @allParents = ();
|
| +
|
| +my @customCallbackDeclarations = ();
|
| +my @implContentHeader = ();
|
| +my @implFixedHeader = ();
|
| +my @implContent = ();
|
| +my %implIncludes = ();
|
| +my @dartNatives = ();
|
| +
|
| +my @dartInterfaceContent = ();
|
| +my @dartImplContent = ();
|
| +
|
| +# Default .h template
|
| +my $headerTemplate = << "EOF";
|
| +/*
|
| + This file is part of the WebKit open source project.
|
| + This file has been generated by generate-bindings.pl. DO NOT MODIFY!
|
| +
|
| + This library is free software; you can redistribute it and/or
|
| + modify it under the terms of the GNU Library General Public
|
| + License as published by the Free Software Foundation; either
|
| + version 2 of the License, or (at your option) any later version.
|
| +
|
| + This library is distributed in the hope that it will be useful,
|
| + but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
| + Library General Public License for more details.
|
| +
|
| + You should have received a copy of the GNU Library General Public License
|
| + along with this library; see the file COPYING.LIB. If not, write to
|
| + the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
| + Boston, MA 02111-1307, USA.
|
| +*/
|
| +EOF
|
| +
|
| +struct(NativeBindingDescriptor => {
|
| + cppCallbackName => '$',
|
| + nativeId => '$',
|
| + argumentCount => '$',
|
| +});
|
| +
|
| +struct(IDLTypeInfoStruct => {
|
| + additionalInterfaces => '@',
|
| + superClass => '$',
|
| + auxilaryMethods => '@',
|
| +});
|
| +
|
| +# Default constructor
|
| +sub new
|
| +{
|
| + my $object = shift;
|
| +
|
| + $codeGenerator = shift;
|
| + $outputDir = shift;
|
| + $outputHeadersDir = shift;
|
| +
|
| + my $reference = { };
|
| + bless($reference, $object);
|
| + return $reference;
|
| +}
|
| +
|
| +sub finish
|
| +{
|
| + my ($object,) = @_;
|
| +
|
| + # Commit changes!
|
| + $object->WriteData();
|
| +}
|
| +
|
| +sub GenerateModule
|
| +{
|
| + my ($object, $dataNode) = @_;
|
| +}
|
| +
|
| +sub GenerateInterface
|
| +{
|
| + my ($object, $dataNode, $defines) = @_;
|
| +
|
| + # Add parent classes (for multiple-inheritance) fields as needed.
|
| + @allParents = ();
|
| + $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@allParents, 0);
|
| + # Prepare internal structures.
|
| + $codeGenerator->LinkOverloadedFunctions($dataNode);
|
| +
|
| + # Start actual generation
|
| + if ($dataNode->extendedAttributes->{Callback}) {
|
| + $object->GenerateCallbackDartInterface($dataNode);
|
| + $object->GenerateCallbackHeader($dataNode);
|
| + $object->GenerateCallbackImplementation($dataNode);
|
| + } else {
|
| + $object->GenerateSource($dataNode);
|
| + $object->GenerateHeader($dataNode);
|
| + }
|
| +
|
| + my $name = $dataNode->name;
|
| +
|
| + # Open files for writing
|
| + my $headerFileName = "$outputHeadersDir/Dart${name}.h";
|
| + my $implFileName = "$outputDir/Dart${name}.cpp";
|
| + my $dartInterfaceFileName = "$outputHeadersDir/${name}.dart";
|
| + my $dartImplFileName = "$outputHeadersDir/${name}Implementation.dart";
|
| +
|
| + open($IMPL, ">$implFileName") || die "Couldn't open file $implFileName";
|
| + open($HEADER, ">$headerFileName") || die "Couldn't open file $headerFileName";
|
| + open($DART_INTERFACE, ">$dartInterfaceFileName") || die "Couldn't open file $dartInterfaceFileName";
|
| + open($DART_IMPL, ">$dartImplFileName") || die "Couldn't open file $dartImplFileName";
|
| +}
|
| +
|
| +# If the node has a [Conditional=XXX] attribute, returns an "ENABLE(XXX)" string for use in an #if.
|
| +# FIXME: common with CodeGeneratorV8
|
| +sub GenerateConditionalStringForAttributes
|
| +{
|
| + my ($attributes,) = @_;
|
| +
|
| + my $conditional = $attributes->{Conditional};
|
| + if ($conditional) {
|
| + if ($conditional =~ /&/) {
|
| + return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
|
| + } elsif ($conditional =~ /\|/) {
|
| + return "ENABLE(" . join(") || ENABLE(", split(/\|/, $conditional)) . ")";
|
| + } else {
|
| + return "ENABLE(" . $conditional . ")";
|
| + }
|
| + } else {
|
| + return "";
|
| + }
|
| +}
|
| +
|
| +sub GenerateConditionalString
|
| +{
|
| + my ($node,) = @_;
|
| + return GenerateConditionalStringForAttributes($node->extendedAttributes);
|
| +}
|
| +
|
| +sub GenerateCustomCallbackDeclaration
|
| +{
|
| + my ($callbackName) = @_;
|
| + return "void $callbackName(Dart_NativeArguments);";
|
| +}
|
| +
|
| +sub ClassName
|
| +{
|
| + my ($interfaceName,) = @_;
|
| + return "Dart$interfaceName";
|
| +}
|
| +
|
| +sub HasOverloads
|
| +{
|
| + my ($function,) = @_;
|
| + return 1 if @{$function->{overloads}} > 1;
|
| +}
|
| +
|
| +sub MaxOverloadParameterCount
|
| +{
|
| + my ($function,) = @_;
|
| +
|
| + my $maxParameterCount = 0;
|
| + foreach my $overload (@{$function->{overloads}}) {
|
| + my $parameterCount = @{$overload->parameters};
|
| + $maxParameterCount = $maxParameterCount > $parameterCount ? $maxParameterCount : $parameterCount;
|
| + }
|
| + return $maxParameterCount;
|
| +}
|
| +
|
| +sub HasOptionalParameters
|
| +{
|
| + my ($function) = @_;
|
| +
|
| + # FIXME: useCapture was marked as optional upstream, however native
|
| + # implementation still requires all three parameters. JavaScript bindings
|
| + # have custom generation for addEventListener and removeEventListener.
|
| + return 0 if $function->signature->name eq "addEventListener" || $function->signature->name eq "removeEventListener";
|
| +
|
| + foreach my $parameter (@{$function->parameters}) {
|
| + return 1 if IsParameterOptionalInWebKit($parameter);
|
| + }
|
| +}
|
| +
|
| +sub HasCustomConstructor
|
| +{
|
| + my ($dataNode) = @_;
|
| +
|
| + # FIXME: switch to using CanBeConstructed attribute.
|
| + return 1 if $dataNode->name eq "FileReader";
|
| + return 1 if $dataNode->name eq "XMLHttpRequest";
|
| + return 1 if $dataNode->name eq "WebKitCSSMatrix";
|
| + return 1 if $dataNode->name eq "WebKitPoint";
|
| +
|
| + return 0;
|
| +}
|
| +
|
| +sub IsParameterOptionalInWebKit
|
| +{
|
| + my ($parameter) = @_;
|
| +
|
| + # Optional callbacks are not optional parameters in native implementations, they always have a default value (0).
|
| + my $optional = $parameter->extendedAttributes->{Optional};
|
| + return $optional && $optional ne "CallWithDefaultValue" && !$parameter->extendedAttributes->{Callback};
|
| +}
|
| +
|
| +my %renames = (
|
| + "IDBCursor" => {
|
| + "continue" => "continueFunction",
|
| + },
|
| + "IDBIndex" => {
|
| + "get" => "getObject",
|
| + },
|
| + "IDBObjectStore" => {
|
| + "get" => "getObject",
|
| + },
|
| + "Int8Array" => {
|
| + "set" => "setElements",
|
| + },
|
| + "Int16Array" => {
|
| + "set" => "setElements",
|
| + },
|
| + "Int32Array" => {
|
| + "set" => "setElements",
|
| + },
|
| + "Uint8Array" => {
|
| + "set" => "setElements",
|
| + },
|
| + "Uint16Array" => {
|
| + "set" => "setElements",
|
| + },
|
| + "Uint32Array" => {
|
| + "set" => "setElements",
|
| + },
|
| + "Float32Array" => {
|
| + "set" => "setElements",
|
| + },
|
| + "Float64Array" => {
|
| + "set" => "setElements",
|
| + },
|
| + "SVGFEMorphologyElement" => {
|
| + "operator" => "operatorValue",
|
| + },
|
| + "SVGFECompositeElement" => {
|
| + "operator" => "operatorValue",
|
| + },
|
| + "Console" => {
|
| + "assert" => "assert_",
|
| + },
|
| +);
|
| +
|
| +sub DartName
|
| +{
|
| + my ($interfaceName, $memberName) = @_;
|
| + return $memberName unless $renames{$interfaceName};
|
| + my $class = $renames{$interfaceName};
|
| + return $memberName unless $class->{$memberName};
|
| + return $class->{$memberName};
|
| +}
|
| +
|
| +# FIXME: eventually those should go away.
|
| +my %classesWithUnsupportedCustomGetters = (
|
| + "Clipboard" => 1,
|
| + "Console" => 1,
|
| + "Coordinates" => 1,
|
| + "DeviceMotionEvent" => 1,
|
| + "DeviceOrientationEvent" => 1,
|
| + "FileReader" => 1,
|
| + "JavaScriptCallFrame" => 1,
|
| + "HTMLInputElement" => 1,
|
| + "HTMLOptionsCollection" => 1,
|
| + "HTMLOutputElement" => 1,
|
| + "ScriptProfileNode" => 1,
|
| + "WebKitAnimation" => 1,
|
| +);
|
| +
|
| +sub IgnoredAttribute
|
| +{
|
| + my ($interfaceName, $attribute) = @_;
|
| +
|
| + # FIXME: reconsider if need to be supported in Dart bindings at all.
|
| + return 1 if $attribute->signature->type =~ /Constructor$/;
|
| +
|
| + # Attribute event listeners are not supported in Dart.
|
| + return 1 if $attribute->signature->type eq "EventListener";
|
| +
|
| + # The only usage is HTMLIFrameElement.contentDocument.
|
| + return 1 if $attribute->signature->extendedAttributes->{CheckFrameSecurity};
|
| +
|
| + return 1 if HasCustomGetter($attribute) && exists $classesWithUnsupportedCustomGetters{$interfaceName};
|
| +
|
| + return 0;
|
| +}
|
| +
|
| +
|
| +sub HasSetter
|
| +{
|
| + my ($attribute,) = @_;
|
| +
|
| + return 0 if $attribute->type =~ /^readonly/;
|
| + # FIXME: Replaceable apparently means that the value can be overwritten by JS and
|
| + # hence there is no correspondence to this in Dart.
|
| + return 0 if $attribute->signature->extendedAttributes->{"Replaceable"};
|
| + return 1;
|
| +}
|
| +
|
| +
|
| +sub IgnoredCallback
|
| +{
|
| + my ($interfaceName, $function) = @_;
|
| +
|
| + # FIXME: WebGLContextEvent.initEvent overloads initEvent in base interface Event and adds
|
| + # another argument.
|
| + # In the current architecture it's difficult to solve as IDL files are processed one by one.
|
| + # As this is the only case, I'd suggest to put Custom attribute on WebGLContextEvent.initEvent.
|
| + return 1 if $interfaceName eq "WebGLContextEvent" && $function->signature->name eq "initEvent";
|
| +
|
| + # FIXME: implement callbacks with ScriptState.
|
| + my $callWith = $function->signature->extendedAttributes->{CallWith};
|
| + return 1 if $callWith and $callWith eq "ScriptState";
|
| +
|
| + return 0;
|
| +}
|
| +
|
| +# FIXME: Consider adding this to IDL as an attribute.
|
| +my %idlTypeToW3C = (
|
| + "DOMWindow" => "Window",
|
| + "DOMCoreException" => "DOMException"
|
| +);
|
| +
|
| +sub HasW3CName
|
| +{
|
| + my ($idlType,) = @_;
|
| + return 1 if exists $idlTypeToW3C{$idlType};
|
| + return 0;
|
| +}
|
| +
|
| +sub IDLTypeToW3C
|
| +{
|
| + my ($idlType,) = @_;
|
| + return $idlTypeToW3C{$idlType} if exists $idlTypeToW3C{$idlType};
|
| + return $idlType;
|
| +}
|
| +
|
| +my %idlTypeToDart = (
|
| + "any" => "Object",
|
| + "boolean" => "bool",
|
| + "Array" => "List",
|
| + "DOMObject" => "Object",
|
| + "DOMString" => "String",
|
| + "DOMString[]" => "DOMStringList",
|
| + "DOMTimeStamp" => "int",
|
| + "ObjectArray" => "List",
|
| + "SerializedScriptValue" => "Object",
|
| + "Date" => "Date",
|
| + "float" => "num",
|
| + "short" => "int",
|
| + "long" => "int",
|
| + "long long" => "int",
|
| + "unsigned int" => "int",
|
| + "unsigned short" => "int",
|
| + "unsigned long" => "int",
|
| + "unsigned long long" => "int",
|
| + "string" => "String",
|
| +);
|
| +
|
| +my %primitiveDartTypes = (
|
| + "int" => 1,
|
| + "String" => 1,
|
| + "Object" => 1,
|
| + "Date" => 1,
|
| + "SerializedScriptValue" => 1,
|
| +);
|
| +
|
| +sub IDLTypeToDart
|
| +{
|
| + my ($idlType,) = @_;
|
| + return $idlTypeToDart{$idlType} if exists $idlTypeToDart{$idlType};
|
| + return $idlType;
|
| +}
|
| +
|
| +# FIXME: pretty much %non_wrapper_types in CodeGeneratorV8.
|
| +my %nonWrapperTypes = (
|
| + "CompareHow" => 1,
|
| + "EventListener" => 1,
|
| + "EventTarget" => 1,
|
| + "MediaQueryListListener" => 1,
|
| + "OptionsObject" => 1,
|
| + "VoidCallback" => 1,
|
| +);
|
| +
|
| +sub IsIDLTypeWithDartBindings
|
| +{
|
| + my ($idlType,) = @_;
|
| +
|
| + return 0 if exists $idlTypeToDart{$idlType};
|
| + return 0 if exists $primitiveDartTypes{$idlType};
|
| + return 0 if !IsRefPtrType(IDLTypeToDart($idlType));
|
| + return 0 if exists $nonWrapperTypes{$idlType};
|
| +
|
| + return 1;
|
| +}
|
| +
|
| +sub ParameterAdapterType
|
| +{
|
| + my ($idlType,) = @_;
|
| +
|
| + my $webkitParameterType = IDLTypeToWebkit($idlType);
|
| +
|
| + my $suffix = "";
|
| + if (IsIDLTypeWithDartBindings($idlType)) {
|
| + my $bindingsClass = ClassName($idlType);
|
| + $implIncludes{"$bindingsClass.h"} = 1;
|
| + $suffix = ", $bindingsClass";
|
| + }
|
| +
|
| + return "ParameterAdapter< $webkitParameterType$suffix >";
|
| +}
|
| +
|
| +# FIXME: common with CodeGeneratorV8
|
| +sub GetNativeTypeForConversions
|
| +{
|
| + my ($type,) = @_;
|
| + $type = $codeGenerator->GetSVGTypeNeedingTearOff($type) if $codeGenerator->IsSVGTypeNeedingTearOff($type);
|
| + return $type;
|
| +}
|
| +
|
| +
|
| +sub AddHeaderForIDLType
|
| +{
|
| + my ($idlType, $includes) = @_;
|
| +
|
| + $idlType =~ s/Abs|Rel// if $idlType =~ /SVGPathSeg/;
|
| +
|
| + return if $codeGenerator->IsPrimitiveType($idlType);
|
| +
|
| + return if exists $primitiveDartTypes{IDLTypeToDart($idlType)};
|
| +
|
| + return if $codeGenerator->AvoidInclusionOfType($idlType);
|
| +
|
| + return if $idlType eq "CompareHow";
|
| +
|
| + $includes->{"$idlType.h"} = 1;
|
| + $includes->{"SVGPropertyTearOff.h"} = 1 if $codeGenerator->IsSVGTypeNeedingTearOff($idlType);
|
| +}
|
| +
|
| +# FIXME: common with CodeGeneratorV8
|
| +sub AddHeaderClassIncludes
|
| +{
|
| + my ($idlType,) = @_;
|
| +
|
| + AddHeaderForIDLType($idlType, \%headerIncludes);
|
| +
|
| + $headerIncludes{"DartDOMWrapper.h"} = 1;
|
| +}
|
| +
|
| +sub GenerateIncludes
|
| +{
|
| + return map { "#include " . (/wtf|dart_api\.h/ ? "<$_>" : "\"$_\"") . "\n"; } sort(@_);
|
| +}
|
| +
|
| +my %withCustomConverters = (
|
| + "DOMWindow" => 1,
|
| + "Element" => 1,
|
| + "HTMLElement" => 1,
|
| + "SVGElement" => 1,
|
| +);
|
| +
|
| +sub RequiresCustomToDartConverter
|
| +{
|
| + my ($dataNode,) = @_;
|
| +
|
| + return 1 if $dataNode->extendedAttributes->{CustomToJS};
|
| + return 1 if $dataNode->extendedAttributes->{PureInterface};
|
| + return exists $withCustomConverters{$dataNode->name};
|
| +}
|
| +
|
| +sub GenerateHeader
|
| +{
|
| + my ($object, $dataNode) = @_;
|
| +
|
| + my $interfaceName = $dataNode->name;
|
| + my $className = ClassName($interfaceName);
|
| + my $webkitClassName = GetNativeTypeForConversions($interfaceName);
|
| +
|
| + my $conditionalString = GenerateConditionalString($dataNode);
|
| +
|
| + my $toDartValue = "";
|
| + if (!RequiresCustomToDartConverter($dataNode)) {
|
| + $toDartValue = <<END;
|
| +inline Dart_Handle toDartValue($webkitClassName* value)
|
| +{
|
| + return DartDOMWrapper::toDart<$className>(value);
|
| +}
|
| +END
|
| + } else {
|
| + $toDartValue = <<END;
|
| +Dart_Handle toDartValue($webkitClassName*);
|
| +END
|
| + }
|
| +
|
| + my $customCallbackDeclarations = join("\n\n", @customCallbackDeclarations);
|
| +
|
| + push(@headerContent, $headerTemplate);
|
| +
|
| + push(@headerContent, "\n#if ${conditionalString}\n") if $conditionalString;
|
| + push(@headerContent, <<END);
|
| +
|
| +#ifndef ${className}_h
|
| +#define ${className}_h
|
| +
|
| +END
|
| +
|
| + AddHeaderClassIncludes($interfaceName);
|
| +
|
| + $headerIncludes{"dart_api.h"} = 1;
|
| + push(@headerContent, GenerateIncludes(keys(%headerIncludes)));
|
| +
|
| + push(@headerContent, <<END);
|
| +
|
| +namespace WebCore {
|
| +
|
| +struct $className {
|
| + static const char* const dartImplementationClassName;
|
| + typedef $webkitClassName NativeType;
|
| +
|
| + static PassRefPtr<NativeType> toNative(Dart_Handle handle, Dart_Handle& exception)
|
| + {
|
| + return DartDOMWrapper::unwrapDartWrapper<$className>(handle, exception);
|
| + }
|
| +};
|
| +
|
| +$toDartValue
|
| +namespace Dart${interfaceName}Internal {
|
| +
|
| +$customCallbackDeclarations
|
| +
|
| +}
|
| +
|
| +}
|
| +
|
| +#endif // ${className}_h
|
| +END
|
| +
|
| + push(@headerContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
|
| +}
|
| +
|
| +sub HasCustomGetter
|
| +{
|
| + my ($attribute,) = @_;
|
| + my $extendedAttributes = $attribute->signature->extendedAttributes;
|
| + return $extendedAttributes->{"CustomGetter"} || $extendedAttributes->{"Custom"};
|
| +}
|
| +
|
| +sub HasCustomSetter
|
| +{
|
| + my ($attribute,) = @_;
|
| + my $extendedAttributes = $attribute->signature->extendedAttributes;
|
| + return $extendedAttributes->{"CustomSetter"} || $extendedAttributes->{"Custom"} || $extendedAttributes->{"V8CustomSetter"};
|
| +}
|
| +
|
| +sub GenerateUnimplementedNative
|
| +{
|
| + my ($name,) = @_;
|
| +
|
| + push(@implContent, <<END);
|
| +static void $name(Dart_NativeArguments args)
|
| +{
|
| + DART_UNIMPLEMENTED();
|
| +}
|
| +
|
| +END
|
| +}
|
| +
|
| +sub WithTearOffNotList
|
| +{
|
| + my ($interfaceName) = @_;
|
| +
|
| + return ($codeGenerator->IsSVGTypeNeedingTearOff($interfaceName) and (not ($interfaceName =~ /List$/)));
|
| +}
|
| +
|
| +sub PrepareInvocation
|
| +{
|
| + my ($receiver, $interfaceName, $invocationPrefix, $invocationParameters) = @_;
|
| +
|
| + my $invocationPostfix;
|
| + $receiver .= "->";
|
| + if ($interfaceName eq "SVGNumber") {
|
| + $receiver .= "propertyReference()";
|
| + if ($invocationPrefix =~ /^setValue/) {
|
| + $invocationPrefix = " = ";
|
| + } else {
|
| + $invocationPrefix = "";
|
| + }
|
| + $invocationPostfix = "";
|
| + } else {
|
| + $receiver .= "propertyReference()." if WithTearOffNotList($interfaceName);
|
| + $invocationPostfix = ")";
|
| + }
|
| + return "$receiver$invocationPrefix$invocationParameters$invocationPostfix";
|
| +}
|
| +
|
| +my %svgPrimitiveTypes = (
|
| + "SVGAngle" => 1,
|
| + "SVGLength" => 1,
|
| + "SVGMatrix" => 1,
|
| + "SVGNumber" => 1,
|
| + "SVGPoint" => 1,
|
| + "SVGRect" => 1,
|
| + "SVGTransform" => 1);
|
| +
|
| +sub ProcessInvocationResult
|
| +{
|
| + my ($invocation, $interfaceName, $returnType) = @_;
|
| + my $svgNativeReturnType = $codeGenerator->GetSVGTypeNeedingTearOff($returnType);
|
| +
|
| + return $invocation if (not $svgNativeReturnType);
|
| +
|
| + return "static_cast<${svgNativeReturnType}*>(${invocation})" if ($interfaceName =~ /^SVGAnimated/);
|
| +
|
| + return "${svgNativeReturnType}::create(receiver, ${invocation})" if ($returnType eq "SVGStringList");
|
| +
|
| + return "static_cast<${svgNativeReturnType}*>(${invocation}.get())" if ($interfaceName =~ /List$/);
|
| +
|
| + if (exists $svgPrimitiveTypes{$returnType}) {
|
| + return "${svgNativeReturnType}::create(${invocation})";
|
| + } else {
|
| + return "static_cast<${svgNativeReturnType}*>(${invocation})";
|
| + }
|
| +}
|
| +
|
| +sub GenerateGenericBindingsFunction
|
| +{
|
| + my ($name, $interfaceName, $invocationPrefix, $parameters, $returnType, $raisesExceptions, $attributes, $isSetter) = @_;
|
| +
|
| + my $webkitClassName = GetNativeTypeForConversions($interfaceName);
|
| +
|
| + my $exceptionManagementPrologue = "";
|
| + my $exceptionManagementEpilogue = "";
|
| + if (@{$parameters} || $raisesExceptions) {
|
| + $exceptionManagementPrologue = <<END;
|
| + Dart_Handle exception;
|
| +END
|
| + $exceptionManagementEpilogue = <<END;
|
| +
|
| +fail:
|
| + Dart_ThrowException(exception);
|
| + ASSERT_NOT_REACHED();
|
| +END
|
| + }
|
| +
|
| + my @defineInvocationParameters = ();
|
| + my @invocationParameters = ();
|
| +
|
| + my $callWith = $attributes->{CallWith};
|
| + if ($callWith) {
|
| + # Generate code for "CallWith" parameter.
|
| + if ($callWith eq "ScriptExecutionContext") {
|
| + push(@defineInvocationParameters, <<END);
|
| + ScriptExecutionContext* context = DartUtilities::scriptExecutionContext();
|
| + if (!context)
|
| + return;
|
| +END
|
| + push(@invocationParameters, "context");
|
| + }
|
| + }
|
| +
|
| + # Generate code for parameters conversion.
|
| + my $parameterCount = @$parameters;
|
| + foreach my $parameterIndex (0..$parameterCount - 1) {
|
| + my $parameter = @$parameters[$parameterIndex];
|
| + my $parameterType = $parameter->type;
|
| + $parameterType = "DOMStringList" if $parameterType eq "DOMString[]";
|
| + AddHeaderForIDLType($parameterType, \%implIncludes);
|
| + my $name = $parameter->name;
|
| + my $parameterAdapterType = ParameterAdapterType($parameterType);
|
| + my $dartArgumentIndex = $parameterIndex + 1; # 0 is for the receiver.
|
| + my @adapterParameters = ("Dart_GetNativeArgument(args, $dartArgumentIndex)");
|
| + my $adapterParameters = join(", ", @adapterParameters);
|
| + push(@defineInvocationParameters, <<END);
|
| + const $parameterAdapterType $name($adapterParameters);
|
| + if (!$name.conversionSuccessful()) {
|
| + exception = $name.exception();
|
| + goto fail;
|
| + }
|
| +END
|
| + }
|
| + @invocationParameters = (@invocationParameters, map { $_->name; } @{$parameters});
|
| +
|
| + if ($attributes->{CustomArgumentHandling}) {
|
| + $implIncludes{"ScriptArguments.h"} = 1;
|
| + $implIncludes{"ScriptCallStack.h"} = 1;
|
| + my $customArgument = $parameterCount + 1;
|
| + push(@defineInvocationParameters, <<END);
|
| + Dart_Handle customArgument = Dart_GetNativeArgument(args, $customArgument);
|
| + RefPtr<ScriptArguments> scriptArguments(DartUtilities::createScriptArguments(customArgument));
|
| + size_t maxStackSize = receiver->shouldCaptureFullStackTrace() ? ScriptCallStack::maxCallStackSizeToCapture : 1;
|
| + RefPtr<ScriptCallStack> scriptCallStack(DartUtilities::createScriptCallStack(maxStackSize));
|
| + if (!scriptCallStack->size())
|
| + return;
|
| +END
|
| + push(@invocationParameters, "scriptArguments", "scriptCallStack");
|
| + }
|
| +
|
| + if ($attributes->{NeedsUserGestureCheck}) {
|
| + push(@invocationParameters, "DartUtilities::processingUserGesture()");
|
| + }
|
| +
|
| + if ($raisesExceptions) {
|
| + push(@invocationParameters, "ec");
|
| + }
|
| +
|
| + my $defineInvocationParameters = join "", @defineInvocationParameters;
|
| + my $invocationParameters = join ", ", @invocationParameters;
|
| + my $invocation = PrepareInvocation("receiver", $interfaceName, $invocationPrefix, $invocationParameters);
|
| + # Generate code for setting return value.
|
| + my $invocationAndReturn = $invocation;
|
| + if ($returnType ne "void") {
|
| + $invocation = ProcessInvocationResult($invocation, $interfaceName, $returnType);
|
| + my $dartType = IDLTypeToDart($returnType);
|
| + if (!$codeGenerator->IsPrimitiveType($returnType) && !exists $primitiveDartTypes{$dartType}) {
|
| + $implIncludes{"@{[ClassName($dartType)]}.h"} = 1;
|
| + }
|
| + $invocation = "static_pointer_cast<SVGAnimatedEnumeration>($invocation)" if $returnType eq "SVGAnimatedEnumeration";
|
| + # FIXME: this is too simplistic for long return types, reconsider.
|
| + $invocation = "static_cast<int64_t>($invocation)" if $dartType eq "int";
|
| + # There is GC3Dboolean which is not a bool, but unsigned char for OpenGL compatibility.
|
| + $invocation = "static_cast<bool>($invocation)" if $dartType eq "bool";
|
| + $conversion = ($codeGenerator->IsStringType($returnType) and defined
|
| + $attributes->{ConvertNullStringTo}) ? ", ConvertDefaultToNull" : "";
|
| + $invocationAndReturn = "DartDOMWrapper::returnValue(args, $invocation$conversion)";
|
| + }
|
| +
|
| + my $webkitInvocation = <<END;
|
| + $invocationAndReturn;
|
| +END
|
| + if ($raisesExceptions) {
|
| + $implIncludes{"ExceptionCode.h"} = 1;
|
| + $webkitInvocation = <<END;
|
| + ExceptionCode ec = 0;
|
| + $invocationAndReturn;
|
| + if (UNLIKELY(ec)) {
|
| + exception = DartDOMWrapper::exceptionCodeToDartException(ec);
|
| + goto fail;
|
| + }
|
| +END
|
| + }
|
| +
|
| + my $conditionalString = GenerateConditionalStringForAttributes($attributes);
|
| + if ($conditionalString) {
|
| + push(@implContent, <<END);
|
| +#if $conditionalString
|
| +END
|
| + }
|
| +
|
| + push(@implContent, <<END);
|
| +static void $name(Dart_NativeArguments args)
|
| +{
|
| + DartApiScope dartApiScope;
|
| +$exceptionManagementPrologue {
|
| + $webkitClassName* receiver = DartDOMWrapper::receiver< $webkitClassName >(args);
|
| +$defineInvocationParameters
|
| +$webkitInvocation return;
|
| + }
|
| +$exceptionManagementEpilogue}
|
| +
|
| +END
|
| +
|
| + if ($conditionalString) {
|
| + push(@implContent, <<END);
|
| +#else
|
| +static void $name(Dart_NativeArguments args)
|
| +{
|
| + DartApiScope dartApiScope;
|
| + Dart_ThrowException(DartUtilities::conditionalFunctionalityException());
|
| +}
|
| +#endif
|
| +
|
| +END
|
| + }
|
| +}
|
| +
|
| +# FIXME: copied from CodeGeneratorV8.pm
|
| +sub IsRefPtrType
|
| +{
|
| + my ($type,) = @_;
|
| +
|
| + return 0 if $type eq "boolean";
|
| + return 0 if $type eq "float";
|
| + return 0 if $type eq "int";
|
| + return 0 if $type eq "Date";
|
| + return 0 if $type eq "DOMString";
|
| + return 0 if $type eq "double";
|
| + return 0 if $type eq "short";
|
| + return 0 if $type eq "long";
|
| + return 0 if $type eq "unsigned";
|
| + return 0 if $type eq "unsigned long";
|
| + return 0 if $type eq "unsigned short";
|
| +
|
| + return 1;
|
| +}
|
| +
|
| +# FIXME: partially copied from GetNativeType of CodeGeneratorV8.pm
|
| +sub IDLTypeToWebkit
|
| +{
|
| + my ($type, $isParameter) = @_;
|
| +
|
| + my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($type);
|
| + if ($svgNativeType) {
|
| + if ($svgNativeType =~ /List$/) {
|
| + return "${svgNativeType}*";
|
| + } else {
|
| + return "RefPtr<${svgNativeType} >";
|
| + }
|
| + }
|
| +
|
| + if ($type eq "float" or $type eq "double") {
|
| + return $type;
|
| + }
|
| +
|
| + return ($isParameter ? "const String&" : "String") if ($type eq "DOMString" or $type eq "DOMUserData");
|
| + return "int" if $type eq "int";
|
| + return "int" if $type eq "short" or $type eq "unsigned short";
|
| + return "unsigned" if $type eq "unsigned long";
|
| + return "int" if $type eq "long";
|
| + return "long long" if $type eq "long long";
|
| + return "unsigned long long" if $type eq "unsigned long long";
|
| + return "bool" if $type eq "boolean";
|
| + return "Range::CompareHow" if $type eq "CompareHow";
|
| + return "DOMTimeStamp" if $type eq "DOMTimeStamp";
|
| + return "unsigned" if $type eq "unsigned int";
|
| + # FIXME: EventTarget are evils!
|
| + # return "Node*" if $type eq "EventTarget" and $isParameter;
|
| + return "double" if $type eq "Date";
|
| + return "ScriptValue" if $type eq "DOMObject";
|
| + return "OptionsObject" if $type eq "OptionsObject";
|
| +
|
| + # temporary hack
|
| + return "RefPtr<NodeFilter>" if $type eq "NodeFilter";
|
| +
|
| + return "RefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValue";
|
| +
|
| + return "RefPtr<IDBKey>" if $type eq "IDBKey";
|
| +
|
| + # necessary as resolvers could be constructed on fly.
|
| + return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver";
|
| +
|
| + return ($isParameter ? "${type}*" : "RefPtr<${type}>") if IsRefPtrType($type);
|
| +
|
| + return "RefPtr<DOMStringList>" if $type eq "DOMStringList";
|
| +
|
| + return "RefPtr<MediaQueryListListener>" if $type eq "MediaQueryListListener";
|
| +
|
| + # Default, assume native type is a pointer with same type name as idl type
|
| + return "${type}*";
|
| +}
|
| +
|
| +sub GenerateResolver
|
| +{
|
| + my ($interfaceName,) = @_;
|
| +
|
| + push(@implContent, <<END);
|
| +
|
| +static Dart_NativeFunction resolver(Dart_Handle name, int argumentCount)
|
| +{
|
| + String str = DartUtilities::dartStringToString(name);
|
| +
|
| +END
|
| +
|
| + foreach my $nativeDescriptor (@dartNatives) {
|
| + my $cppCallbackName = $nativeDescriptor->cppCallbackName;
|
| + my $nativeId = $nativeDescriptor->nativeId;
|
| + my $argumentCount = $nativeDescriptor->argumentCount;
|
| + push(@implContent, <<END);
|
| + if ($argumentCount == argumentCount && str == "$nativeId")
|
| + return $cppCallbackName;
|
| +END
|
| + }
|
| +
|
| + push(@implContent, <<END);
|
| + return 0;
|
| +}
|
| +
|
| +END
|
| +}
|
| +
|
| +sub GenerateScriptConstant
|
| +{
|
| + push(@implContent, <<END);
|
| +
|
| +static const char* script =
|
| +END
|
| +
|
| + foreach my $element (@dartInterfaceContent, @dartImplContent) {
|
| + foreach my $line (split("\n", $element)) {
|
| + $line =~ s/\"/\\\"/g;
|
| + push(@implContent, " \"$line\\n\"\n")
|
| + }
|
| + }
|
| +
|
| + push(@implContent, <<END);
|
| +;
|
| +END
|
| +}
|
| +
|
| +sub GenerateCallbackScriptConstant
|
| +{
|
| + push(@implContent, <<END);
|
| +
|
| +static const char* script =
|
| +END
|
| +
|
| + foreach my $element (@dartInterfaceContent) {
|
| + foreach my $line (split("\n", $element)) {
|
| + $line =~ s/\"/\\\"/g;
|
| + push(@implContent, " \"$line\\n\"\n")
|
| + }
|
| + }
|
| +
|
| + push(@implContent, <<END);
|
| +;
|
| +END
|
| +}
|
| +
|
| +sub GenerateDartImplementationClassname
|
| +{
|
| + my ($interfaceName,) = @_;
|
| +
|
| + my $className = ClassName($interfaceName);
|
| +
|
| + push(@implContent, <<END);
|
| +
|
| +const char* const ${className}::dartImplementationClassName = "${interfaceName}Implementation";
|
| +END
|
| +}
|
| +
|
| +sub GenerateRegistryEntry
|
| +{
|
| + my ($interfaceName,) = @_;
|
| +
|
| + push(@implContent, <<END);
|
| +
|
| +REGISTER_API($interfaceName)
|
| +
|
| +END
|
| +}
|
| +
|
| +sub GenerateImplementationPrologue
|
| +{
|
| + my ($dataNode) = @_;
|
| +
|
| + my $interfaceName = $dataNode->name;
|
| + my $className = ClassName($interfaceName);
|
| + my $internalNamespaceName = "Dart${interfaceName}Internal";
|
| +
|
| + my $conditionalString = GenerateConditionalString($dataNode);
|
| +
|
| + push(@implContentHeader, $headerTemplate);
|
| +
|
| + push(@implContentHeader, <<END);
|
| +
|
| +#include "config.h"
|
| +#include "$className.h"
|
| +
|
| +END
|
| +
|
| + push(@implContentHeader, "#if $conditionalString\n\n") if $conditionalString;
|
| +
|
| + $implIncludes{"DartBindingsCommonIncludes.h"} = 1;
|
| +
|
| + push(@implContent, <<END);
|
| +namespace WebCore {
|
| +
|
| +namespace $internalNamespaceName {
|
| +END
|
| +}
|
| +
|
| +sub GenerateImplementationEpilogue
|
| +{
|
| + my ($dataNode) = @_;
|
| +
|
| + my $interfaceName = $dataNode->name;
|
| + my $className = ClassName($interfaceName);
|
| + my $internalNamespaceName = "Dart${interfaceName}Internal";
|
| +
|
| + my $conditionalString = GenerateConditionalString($dataNode);
|
| +
|
| + push(@implContent, "\n// Class info.\n");
|
| + GenerateResolver($interfaceName);
|
| + GenerateScriptConstant();
|
| +
|
| + push(@implContent, "}\n");
|
| +
|
| + GenerateDartImplementationClassname($interfaceName);
|
| + GenerateRegistryEntry($interfaceName);
|
| +
|
| + push(@implContent, <<END);
|
| +}
|
| +END
|
| +
|
| + push(@implContent, "\n#endif // $conditionalString\n") if $conditionalString;
|
| +
|
| + # We've already added the header for this file in implFixedHeader, so remove
|
| + # it from implIncludes to ensure we don't #include it twice.
|
| + delete $implIncludes{"$className.h"};
|
| +}
|
| +
|
| +sub GenerateCallbackDartInterface
|
| +{
|
| + my ($object, $dataNode) = @_;
|
| + my $function = $dataNode->functions->[0];
|
| + my $functionDecl = DartInterfaceMethodDeclaration($interfaceName, $function, $dataNode->name);
|
| + push(@dartInterfaceContent, $headerTemplate);
|
| + push(@dartInterfaceContent, <<END);
|
| +typedef $functionDecl;
|
| +END
|
| +}
|
| +
|
| +sub FormatCallbackArgument
|
| +{
|
| + my ($argument,) = @_;
|
| + my $webkitType = IDLTypeToWebkit($argument->type, 1);
|
| + my $name = $argument->name;
|
| + return "$webkitType $name";
|
| +}
|
| +
|
| +sub GenerateCallbackHeader
|
| +{
|
| + my ($object, $dataNode) = @_;
|
| +
|
| + my $interfaceName = $dataNode->name;
|
| + my $className = ClassName($interfaceName);
|
| + my $webkitClassName = GetNativeTypeForConversions($interfaceName);
|
| +
|
| + my $conditionalString = GenerateConditionalString($dataNode);
|
| +
|
| + push(@headerContent, $headerTemplate);
|
| +
|
| + push(@headerContent, "\n#if ${conditionalString}\n") if $conditionalString;
|
| + push(@headerContent, <<END);
|
| +
|
| +#ifndef ${className}_h
|
| +#define ${className}_h
|
| +
|
| +END
|
| +
|
| + AddHeaderClassIncludes($interfaceName);
|
| +
|
| + $headerIncludes{"ActiveDOMCallback.h"} = 1;
|
| + $headerIncludes{"DartCallback.h"} = 1;
|
| + push(@headerContent, GenerateIncludes(keys(%headerIncludes)));
|
| +
|
| + my @handleEventMethods = ();
|
| + foreach my $function (@{$dataNode->functions}) {
|
| + die "Expect only handleEvent methods" if ($function->signature->type ne "boolean") || ($function->signature->name ne "handleEvent");
|
| +
|
| + my $arguments = join ", ", map { FormatCallbackArgument($_); } @{$function->parameters};
|
| + push(@handleEventMethods, " virtual bool handleEvent($arguments);");
|
| + }
|
| + my $methods = join "\n", @handleEventMethods;
|
| +
|
| + push(@headerContent, <<END);
|
| +
|
| +namespace WebCore {
|
| +
|
| +class ScriptExecutionContext;
|
| +
|
| +class $className : public $interfaceName, public ActiveDOMCallback {
|
| +public:
|
| + typedef $interfaceName NativeType;
|
| +
|
| + static PassRefPtr<NativeType> toNative(Dart_Handle object, Dart_Handle& exception)
|
| + {
|
| + return adoptRef(new $className(object, exception, DartUtilities::scriptExecutionContext()));
|
| + }
|
| +
|
| +$methods
|
| +
|
| +private:
|
| + $className(Dart_Handle object, Dart_Handle& exception, ScriptExecutionContext* context)
|
| + : ActiveDOMCallback(context)
|
| + , m_callback(object, exception)
|
| + {
|
| + }
|
| +
|
| + DartCallback m_callback;
|
| +};
|
| +
|
| +}
|
| +
|
| +#endif // ${className}_h
|
| +END
|
| +
|
| + push(@headerContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
|
| +}
|
| +
|
| +sub GenerateCallbackImplementation
|
| +{
|
| + my ($object, $dataNode) = @_;
|
| +
|
| + my $interfaceName = $dataNode->name;
|
| + my $className = ClassName($interfaceName);
|
| + my $internalNamespaceName = "Dart${interfaceName}Internal";
|
| +
|
| + my $conditionalString = GenerateConditionalString($dataNode);
|
| +
|
| + push(@implContentHeader, $headerTemplate);
|
| +
|
| + $implIncludes{"DartBindingsCommonIncludes.h"} = 1;
|
| +
|
| + push(@implContentHeader, <<END);
|
| +
|
| +#include "config.h"
|
| +#include "$className.h"
|
| +
|
| +END
|
| +
|
| + push(@implContentHeader, "#if $conditionalString\n\n") if $conditionalString;
|
| +
|
| + my @handleEventMethods = ();
|
| + foreach my $function (@{$dataNode->functions}) {
|
| + die "Expect only handleEvent methods" if ($function->signature->type ne "boolean") || ($function->signature->name ne "handleEvent");
|
| +
|
| + my $arguments = join ", ", map { FormatCallbackArgument($_); } @{$function->parameters};
|
| + my $parameters = join ", ", map { $_->name; } @{$function->parameters};
|
| + push(@handleEventMethods, <<END);
|
| +bool ${className}::handleEvent($arguments)
|
| +{
|
| + return m_callback.handleEvent($parameters);
|
| +}
|
| +END
|
| + }
|
| + my $methods = join "\n", @handleEventMethods;
|
| +
|
| + push(@implContent, <<END);
|
| +namespace WebCore {
|
| +
|
| +$methods
|
| +
|
| +namespace $internalNamespaceName {
|
| +END
|
| +
|
| + GenerateCallbackScriptConstant();
|
| + push(@implContent, "}\n");
|
| +
|
| + push(@implContent, <<END);
|
| +
|
| +REGISTER_CALLBACK($interfaceName)
|
| +
|
| +}
|
| +END
|
| +
|
| + push(@implContent, "\n#endif // $conditionalString\n") if $conditionalString;
|
| +
|
| + # We've already added the header for this file in implFixedHeader, so remove
|
| + # it from implIncludes to ensure we don't #include it twice.
|
| + delete $implIncludes{"$className.h"};
|
| +}
|
| +
|
| +sub DartMethodDeclaration
|
| +{
|
| + my ($functionName, $parameters, $returnType) = @_;
|
| +
|
| + $returnType = IDLTypeToDart($codeGenerator->StripModule($returnType));
|
| + return "$returnType $functionName($parameters)";
|
| +}
|
| +
|
| +sub DartInterfaceMethodDeclaration
|
| +{
|
| + my ($interfaceName, $function, $name) = @_;
|
| +
|
| + my $parameters;
|
| + if (HasOverloads($function)) {
|
| + my $maxParameterCount = MaxOverloadParameterCount($function);
|
| + $parameters = DartAnonymousNamedOptionalParameters($maxParameterCount);
|
| + } else {
|
| + $parameters = DartParameters($function, $function->parameters, 1);
|
| + }
|
| + return DartMethodDeclaration($name || DartName($interfaceName, $function->signature->name), $parameters, $function->signature->type);
|
| +}
|
| +
|
| +sub DartParameters
|
| +{
|
| + my ($function, $parameters, $useDefaultValues) = @_;
|
| +
|
| + my @mandatoryParameters = ();
|
| + my @optionalParameters = ();
|
| + foreach my $parameter (@{$parameters}) {
|
| + # FIXME: parameter modifiers.
|
| + my $type = IDLTypeToDart($parameter->type);
|
| + my $name = $parameter->name;
|
| + if ($useDefaultValues && IsParameterOptionalInWebKit($parameter)) {
|
| + push(@optionalParameters, "$type ${name}");
|
| + } else {
|
| + push(@mandatoryParameters, "$type ${name}");
|
| + }
|
| + }
|
| + if ($function->signature->extendedAttributes->{CustomArgumentHandling}) {
|
| + die "Optional parameters in function with custom argument handling. " if @optionalParameters;
|
| + push(@mandatoryParameters, "argument");
|
| + }
|
| + my $dartParameters = join(", ", @mandatoryParameters);
|
| + if (@optionalParameters) {
|
| + $dartParameters .= ", " if $dartParameters;
|
| + $dartParameters .= "[" . join(", ", @optionalParameters) . "]";
|
| + }
|
| + return $dartParameters;
|
| +}
|
| +
|
| +sub DartParameterCount
|
| +{
|
| + my ($function, $parameters) = @_;
|
| +
|
| + my $parameterCount = @{$parameters};
|
| + $parameterCount += 1 if $function->signature->extendedAttributes->{CustomArgumentHandling};
|
| + return $parameterCount;
|
| +}
|
| +
|
| +sub DartAnonymousArguments
|
| +{
|
| + my ($parameterCount) = @_;
|
| + return "" unless $parameterCount;
|
| + return join(", ", map { "_arg$_" } (0..$parameterCount - 1));
|
| +}
|
| +
|
| +sub DartAnonymousNamedOptionalParameters
|
| +{
|
| + my ($parameterCount) = @_;
|
| + return "" unless $parameterCount;
|
| + return "[" . DartAnonymousArguments($parameterCount) . "]";
|
| +}
|
| +
|
| +sub CreateFunctionNativeDescriptor
|
| +{
|
| + my ($interfaceName, $functionName, $argumentCount) = @_;
|
| + my $descriptor = NativeBindingDescriptor->new(
|
| + cppCallbackName => "${functionName}Callback",
|
| + nativeId => "${interfaceName}_${functionName}_Callback",
|
| + argumentCount => $argumentCount);
|
| + push(@dartNatives, $descriptor);
|
| + return $descriptor;
|
| +}
|
| +
|
| +sub CreateGetterNativeDescriptor
|
| +{
|
| + my ($interfaceName, $attributeName) = @_;
|
| + my $descriptor = NativeBindingDescriptor->new(
|
| + cppCallbackName => "${attributeName}Getter",
|
| + nativeId => "${interfaceName}_${attributeName}_Getter",
|
| + argumentCount => 1);
|
| + push(@dartNatives, $descriptor);
|
| + return $descriptor;
|
| +}
|
| +
|
| +sub CreateSetterNativeDescriptor
|
| +{
|
| + my ($interfaceName, $attributeName) = @_;
|
| + my $descriptor = NativeBindingDescriptor->new(
|
| + cppCallbackName => "${attributeName}Setter",
|
| + nativeId => "${interfaceName}_${attributeName}_Setter",
|
| + argumentCount => 2);
|
| + push(@dartNatives, $descriptor);
|
| + return $descriptor;
|
| +}
|
| +
|
| +sub GenerateDartOptionalArgumentsResolver
|
| +{
|
| + my ($interfaceName, $function) = @_;
|
| +
|
| + my $interfaceMethodDeclaration = DartInterfaceMethodDeclaration($interfaceName, $function);
|
| + push(@dartInterfaceContent, " $interfaceMethodDeclaration;\n");
|
| +
|
| + my @resolver = ();
|
| + push(@resolver, " $interfaceMethodDeclaration {\n");
|
| + my @parameters = ();
|
| + foreach my $parameterIndex (0..@{$function->parameters}) {
|
| + my $parameter = @{$function->parameters}[$parameterIndex];
|
| + if (!$parameter || IsParameterOptionalInWebKit($parameter)) {
|
| + my $functionName = GenerateNativeBinding($interfaceName, $function, \@parameters);
|
| + if ($parameter) {
|
| + my $parameterName = $parameter->name;
|
| + push(@resolver, " if ($parameterName === null)\n ");
|
| + }
|
| + my $parameterNames = join(", ", map { $_->name } @parameters);
|
| + push(@resolver, " return $functionName($parameterNames);\n");
|
| + }
|
| + push(@parameters, $parameter);
|
| + }
|
| + push(@resolver, " }\n");
|
| + push(@dartImplContent, join("", @resolver));
|
| +}
|
| +
|
| +sub GenerateDartOverloadResolver
|
| +{
|
| + my ($interfaceName, $function) = @_;
|
| +
|
| + # Generate code for choosing the correct overload to call. Overloads are
|
| + # chosen based on the the type of the arguments. When more than a single
|
| + # overload is applicable, precedence is given according to the order of
|
| + # declaration in the IDL.
|
| +
|
| + my $interfaceMethodDeclaration = DartInterfaceMethodDeclaration($interfaceName, $function);
|
| + push(@dartInterfaceContent, " $interfaceMethodDeclaration;\n");
|
| +
|
| + my @resolver = ();
|
| + push(@resolver, " $interfaceMethodDeclaration {\n");
|
| + my $maxParameterCount = MaxOverloadParameterCount($function);
|
| + foreach my $overload (@{$function->{overloads}}) {
|
| + my @parameters = ();
|
| + my @parameterNames = ();
|
| + my @parameterChecks = map { "_arg$_ === null" } (0..$maxParameterCount - 1);
|
| + foreach my $parameterIndex (0..@{$overload->parameters}) {
|
| + my $parameter = @{$overload->parameters}[$parameterIndex];
|
| + if (!$parameter || IsParameterOptionalInWebKit($parameter)) {
|
| + my $functionName = GenerateNativeBinding($interfaceName, $overload, \@parameters);
|
| + my $parameterNames = join(", ", @parameterNames);
|
| + my $parameterChecks = join(" && ", @parameterChecks);
|
| + push(@resolver, <<END);
|
| + if ($parameterChecks)
|
| + return $functionName($parameterNames);
|
| +END
|
| + }
|
| + last if !$parameter;
|
| + my $idlType = $codeGenerator->StripModule($parameter->type);
|
| + my $dartType = IDLTypeToDart($idlType);
|
| + push(@parameterNames, "_arg$parameterIndex");
|
| + $parameterChecks[$parameterIndex] = "_arg$parameterIndex is $dartType";
|
| + push(@parameters, $parameter);
|
| + }
|
| + }
|
| +
|
| + # FIXME: throw appropriate exception when overload is not found.
|
| + push(@resolver, <<END);
|
| + throw "Failed to find overload of @{[$function->signature->name]}";
|
| + }
|
| +END
|
| + push(@dartImplContent, join("", @resolver));
|
| +}
|
| +
|
| +sub ParentInterface
|
| +{
|
| + my $dataNode = shift;
|
| +
|
| + foreach (@{$dataNode->parents}) {
|
| + my $parent = $codeGenerator->StripModule($_);
|
| + if ($parent eq "EventTarget") {
|
| + next;
|
| + }
|
| + return $parent;
|
| + }
|
| +}
|
| +
|
| +my %excludedInterfaces = (
|
| + "SVGURIReference" => 1, # Is not in the list of SVG idls files (see WebCore.gypi), v8 bindings do not immediately compile
|
| + # Explicitly excluded in WebCore.gyp
|
| + "ElementTimeControl" => 1,
|
| + "SVGExternalResourcesRequired" => 1,
|
| + "SVGFilterPrimitiveStandardAttributes" => 1,
|
| + "SVGFitToViewBox" => 1,
|
| + "SVGLangSpace" => 1,
|
| + "SVGLocatable" => 1,
|
| + "SVGStylable" => 1,
|
| + "SVGTests" => 1,
|
| + "SVGTransformable" => 1,
|
| + "SVGViewSpec" => 1,
|
| + "SVGZoomAndPan" => 1,
|
| +);
|
| +
|
| +sub ListLike
|
| +{
|
| + my ($elementType, $needsAuxiliaryAccessors) = @_;
|
| +
|
| + my @auxiliaryMethods = ();
|
| + if ($needsAuxiliaryAccessors) {
|
| + push(@auxiliaryMethods, ["$elementType operator [] (int index)", "numericIndexGetter", 2]);
|
| + push(@auxiliaryMethods, ["void operator []= (int index, $elementType value)", "numericIndexSetter", 3]);
|
| + }
|
| +
|
| + return IDLTypeInfoStruct->new(
|
| + additionalInterfaces => ["List<$elementType>"],
|
| + superClass => "ListBase<$elementType>",
|
| + auxilaryMethods => \@auxiliaryMethods
|
| + );
|
| +}
|
| +
|
| +sub MapLike
|
| +{
|
| + # FIXME: most probably we need to deduce more types using hints like
|
| + # HasNameGetter, CustomDeleteProperty, CustomGetPropertyNames, DelegatingPutFunction
|
| + # attributes.
|
| + # FIXME: technically at least DOMStringMap.setItem and DOMStringMap.item could be automatically
|
| + # generated and then used from [] and []=. I don't do it for now not to mess up with IDLs too
|
| + # much.
|
| + # FIXME: support removal of elements if allowed (it is at least for DOMStringMap.)
|
| + my ($interfaceName, $keyType, $elementType) = @_;
|
| + return IDLTypeInfoStruct->new(
|
| + additionalInterfaces => ["Map<$keyType, $elementType>"],
|
| + superClass => "MapBase<$keyType, $elementType>",
|
| + auxilaryMethods => [
|
| + ["Collection<$keyType> getKeys()", "getKeys", 1],
|
| + ["$elementType operator [] ($keyType k)", "item", 2],
|
| + ["operator []= ($keyType k, $elementType v)", "setItem", 3],
|
| + ["$elementType remove($keyType k)", "deleteItem", 2],
|
| + ],
|
| + );
|
| +}
|
| +
|
| +my %idlTypeInfoOverrides = (
|
| + "CanvasPixelArray" => ListLike("int", 1),
|
| + "DOMStringMap" => MapLike("DOMStringMap", "String", "String"),
|
| + "HTMLCollection" => ListLike("Node"),
|
| + "NodeList" => ListLike("Node"),
|
| + "StyleSheetList" => ListLike("StyleSheet"),
|
| +);
|
| +
|
| +# FIXME: turn into the single IDL type info registry.
|
| +sub IDLTypeInfo
|
| +{
|
| + my ($dataNode,) = @_;
|
| + my $override = $idlTypeInfoOverrides{$dataNode->name};
|
| + return $override if $override;
|
| +
|
| + my $parentInterface = ParentInterface($dataNode);
|
| + return IDLTypeInfoStruct->new(
|
| + superClass => $parentInterface ? "${parentInterface}Implementation" : "DOMType",
|
| + );
|
| +}
|
| +
|
| +sub GenerateSource
|
| +{
|
| + my ($object, $dataNode) = @_;
|
| +
|
| + my $interfaceName = $dataNode->name;
|
| + my $w3cInterfaceName = IDLTypeToW3C($interfaceName);
|
| +
|
| + push(@dartInterfaceContent, $headerTemplate);
|
| +
|
| + # Build extends clause if any.
|
| + my $extendsClause = "";
|
| + my $parentInterface = ParentInterface($dataNode);
|
| + my $isEventTarget = $dataNode->extendedAttributes->{EventTarget};
|
| + my @implementedInterfaces = ();
|
| + push(@implementedInterfaces, $parentInterface) if $parentInterface;
|
| + push(@implementedInterfaces, "EventTarget") if $isEventTarget;
|
| +
|
| + push(@implementedInterfaces, @{IDLTypeInfo($dataNode)->additionalInterfaces});
|
| + push(@implementedInterfaces, @allParents);
|
| +
|
| + if (@implementedInterfaces) {
|
| + $extendsClause = " extends " . join(", ", @implementedInterfaces);
|
| + }
|
| +
|
| + # Build default clause if any.
|
| + my $defaultClause = "";
|
| + if (HasCustomConstructor($dataNode)) {
|
| + $defaultClause = " factory ${w3cInterfaceName}Implementation";
|
| + push(@customCallbackDeclarations, GenerateCustomCallbackDeclaration("constructorCallback"));
|
| + }
|
| +
|
| + push(@dartInterfaceContent, "\ninterface ${w3cInterfaceName}${extendsClause}${defaultClause} {\n");
|
| + push(@dartInterfaceContent, "\n // Constants.\n");
|
| + foreach my $constant (@{$dataNode->constants}) {
|
| + my $name = $constant->name;
|
| + my $value = $constant->value;
|
| +
|
| + push(@dartInterfaceContent, " static final int $name = $value;\n");
|
| + }
|
| +
|
| + # Generate Dart implementation prologue.
|
| + my $implementationClassName = "${interfaceName}Implementation";
|
| + my $superClass = IDLTypeInfo($dataNode)->superClass;
|
| + push(@dartImplContent, $headerTemplate);
|
| + push(@dartImplContent, "\nclass $implementationClassName extends $superClass implements $interfaceName {\n");
|
| +
|
| + GenerateImplementationPrologue($dataNode);
|
| +
|
| + # Generate fields.
|
| + # FIXME: special treatment of constructors attributes (see V8 code generator).
|
| + push(@dartInterfaceContent, "\n // Fields.\n");
|
| + push(@dartImplContent, "\n // Fields.\n");
|
| + push(@implContent, "\n// Getters & setters.\n");
|
| + foreach my $attribute (@{$dataNode->attributes}) {
|
| + next if IgnoredAttribute($interfaceName, $attribute);
|
| + GenerateField($interfaceName, $attribute);
|
| + }
|
| +
|
| + # Generate methods.
|
| + push(@dartInterfaceContent, "\n // Methods.\n");
|
| + push(@dartImplContent, "\n // Methods.\n");
|
| + push(@implContent, "\n// Callbacks.\n");
|
| + foreach my $function (@{$dataNode->functions}) {
|
| + next if IgnoredCallback($interfaceName, $function);
|
| + next if HasOverloads($function) && $function->{overloadIndex} != 1;
|
| + GenerateMethod($interfaceName, $function);
|
| + }
|
| +
|
| + foreach my $auxilaryMethod (@{IDLTypeInfo($dataNode)->auxilaryMethods}) {
|
| + my $dartDeclaration = $auxilaryMethod->[0];
|
| + my $descriptor = CreateFunctionNativeDescriptor($interfaceName, $auxilaryMethod->[1], $auxilaryMethod->[2]);
|
| + my $nativeId = $descriptor->nativeId;
|
| + push(@dartImplContent, " $dartDeclaration native \"$nativeId\";\n");
|
| + push(@customCallbackDeclarations, GenerateCustomCallbackDeclaration($descriptor->cppCallbackName));
|
| + }
|
| +
|
| + if (HasCustomConstructor($dataNode)) {
|
| + my $parameterCount = $dataNode->extendedAttributes->{"ConstructorParameters"} || 0;
|
| + my $descriptor = CreateFunctionNativeDescriptor($interfaceName, "constructor", 1 + $parameterCount);
|
| + my $nativeId = $descriptor->nativeId;
|
| + my $parameters = DartAnonymousNamedOptionalParameters($parameterCount);
|
| + my $arguments = DartAnonymousArguments($parameterCount);
|
| + push(@dartInterfaceContent, " $w3cInterfaceName($parameters);\n");
|
| + push(@dartImplContent, <<END);
|
| + $implementationClassName($parameters) {
|
| + this._bind($arguments);
|
| + }
|
| +END
|
| + push(@dartImplContent, " void _bind($arguments) native \"$nativeId\";\n");
|
| + }
|
| +
|
| + # Generate implementation support.
|
| + # FIXME: get rid of implementation support completely.
|
| + push(@dartImplContent, <<END);
|
| + // Implementation support.
|
| + static $implementationClassName _create$implementationClassName() => new $implementationClassName._create$implementationClassName();
|
| + $implementationClassName._create$implementationClassName();
|
| +
|
| + String get typeName() => \"$interfaceName\";
|
| +END
|
| +
|
| + push(@dartInterfaceContent, "}\n");
|
| + push(@dartImplContent, "}\n");
|
| +
|
| + if (HasW3CName($interfaceName)) {
|
| + push(@dartInterfaceContent, "\ninterface ${interfaceName} extends ${w3cInterfaceName} {}\n");
|
| + }
|
| +
|
| + GenerateImplementationEpilogue($dataNode);
|
| +}
|
| +
|
| +sub GenerateField
|
| +{
|
| + my ($interfaceName, $attribute) = @_;
|
| +
|
| + my $attributeName = DartName($interfaceName, $attribute->signature->name);
|
| + my $attributeType = $attribute->signature->type;
|
| + my $dartAttributeType = IDLTypeToDart($attributeType);
|
| +
|
| + # Generate field declaration.
|
| + my $final = HasSetter($attribute) ? "" : "final ";
|
| + push(@dartInterfaceContent, " $final$dartAttributeType $attributeName;\n");
|
| +
|
| + # Generate getter implementation.
|
| + my $getterDescriptor = CreateGetterNativeDescriptor($interfaceName, $attributeName);
|
| + my $getterNativeId = $getterDescriptor->nativeId;
|
| + push(@dartImplContent, " $dartAttributeType get $attributeName() native \"$getterNativeId\";\n");
|
| + if (HasCustomGetter($attribute)) {
|
| + push(@customCallbackDeclarations, GenerateCustomCallbackDeclaration($getterDescriptor->cppCallbackName));
|
| + } else {
|
| + my $invocationPrefix = $codeGenerator->GetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute);
|
| + my $raisesExceptions = scalar(@{$attribute->getterExceptions});
|
| + GenerateGenericBindingsFunction($getterDescriptor->cppCallbackName, $interfaceName, $invocationPrefix, [], $attributeType, $raisesExceptions, $attribute->signature->extendedAttributes);
|
| + }
|
| +
|
| + return unless HasSetter($attribute);
|
| +
|
| + # Generate setter implementation.
|
| + my $setterDescriptor = CreateSetterNativeDescriptor($interfaceName, $attributeName);
|
| + my $setterNativeId = $setterDescriptor->nativeId;
|
| + push(@dartImplContent, " void set $attributeName($dartAttributeType) native \"$setterNativeId\";\n");
|
| + if (HasCustomSetter($attribute)) {
|
| + push(@customCallbackDeclarations, GenerateCustomCallbackDeclaration($setterDescriptor->cppCallbackName));
|
| + } else {
|
| + my $invocationPrefix = $codeGenerator->SetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute);
|
| + my $raisesExceptions = scalar(@{$attribute->setterExceptions});
|
| + GenerateGenericBindingsFunction($setterDescriptor->cppCallbackName, $interfaceName, $invocationPrefix, [$attribute->signature], "void", $raisesExceptions, $attribute->signature->extendedAttributes, 1);
|
| + }
|
| +}
|
| +
|
| +sub GenerateMethod
|
| +{
|
| + my ($interfaceName, $function) = @_;
|
| +
|
| + my $functionName = DartName($interfaceName, $function->signature->name);
|
| +
|
| + if (!$function->signature->extendedAttributes->{"Custom"}) {
|
| + if (HasOverloads($function)) {
|
| + GenerateDartOverloadResolver($interfaceName, $function);
|
| + } elsif (HasOptionalParameters($function)) {
|
| + GenerateDartOptionalArgumentsResolver($interfaceName, $function);
|
| + } else {
|
| + my $interfaceMethodDeclaration = DartInterfaceMethodDeclaration($interfaceName, $function);
|
| + push(@dartInterfaceContent, " $interfaceMethodDeclaration;\n");
|
| + my $bindingFunctionName = GenerateNativeBinding($interfaceName, $function, $function->parameters);
|
| + die if $bindingFunctionName ne $functionName;
|
| + }
|
| + } else {
|
| + my $parameters;
|
| + my $parameterCount;
|
| + if (HasOverloads($function)) {
|
| + $parameterCount = MaxOverloadParameterCount($function);
|
| + $parameters = DartAnonymousNamedOptionalParameters($parameterCount);
|
| + } else {
|
| + $parameters = DartParameters($function, $function->parameters, 1);
|
| + $parameterCount = DartParameterCount($function, $function->parameters);
|
| + }
|
| + my $methodDeclaration = DartMethodDeclaration($functionName, $parameters, $function->signature->type);
|
| + my $descriptor = CreateFunctionNativeDescriptor($interfaceName, $functionName, 1 + $parameterCount);
|
| + my $nativeId = $descriptor->nativeId;
|
| + push(@dartInterfaceContent, " $methodDeclaration;\n");
|
| + push(@dartImplContent, " $methodDeclaration native \"$nativeId\";\n");
|
| + push(@customCallbackDeclarations, GenerateCustomCallbackDeclaration($descriptor->cppCallbackName));
|
| + }
|
| +
|
| + # If there is a method named "item", duplicate it as operator [].
|
| + if ($functionName eq "item") {
|
| + # Consider operator [] should support overloads and optional arguments.
|
| + die "$interfaceName.item has overloads" if HasOverloads($function);
|
| + die "$interfaceName.item has optional arguments" if HasOptionalParameters($function);
|
| +
|
| + my $subscriptOperatorDeclaration = DartInterfaceMethodDeclaration($interfaceName, $function, "operator []");
|
| + my $parameters = join ", ", (map { $_->name } @{$function->parameters});
|
| + push(@dartInterfaceContent, " $subscriptOperatorDeclaration;\n");
|
| + push(@dartImplContent, " $subscriptOperatorDeclaration { return item($parameters); }\n");
|
| + }
|
| +}
|
| +
|
| +sub GenerateNativeBinding
|
| +{
|
| + my ($interfaceName, $function, $parameters) = @_;
|
| +
|
| + my $functionName = DartName($interfaceName, $function->signature->name);
|
| + if (HasOverloads($function)) {
|
| + $functionName .= $function->{overloadIndex};
|
| + }
|
| + if (HasOptionalParameters($function)) {
|
| + $functionName .= "_" . @$parameters;
|
| + }
|
| +
|
| + my $extendedAttributes = $function->signature->extendedAttributes;
|
| + my $returnType = $function->signature->type;
|
| +
|
| + my $dartParameters = DartParameters($function, $parameters, 0);
|
| + my $dartParameterCount = DartParameterCount($function, $parameters);
|
| + my $methodDeclaration = DartMethodDeclaration($functionName, $dartParameters, $returnType);
|
| + my $descriptor = CreateFunctionNativeDescriptor($interfaceName, $functionName, 1 + $dartParameterCount);
|
| + my $nativeId = $descriptor->nativeId;
|
| + push(@dartImplContent, <<END);
|
| + $methodDeclaration native "$nativeId";
|
| +END
|
| +
|
| + my $invocationPrefix;
|
| + if ($extendedAttributes->{ImplementationFunction}) {
|
| + $invocationPrefix = $extendedAttributes->{ImplementationFunction} . "(";
|
| + } else {
|
| + $invocationPrefix = $function->signature->name . "(";
|
| + }
|
| + my $raisesExceptions = scalar(@{$function->raisesExceptions});
|
| + GenerateGenericBindingsFunction($descriptor->cppCallbackName, $interfaceName, $invocationPrefix, $parameters, $returnType, $raisesExceptions, $extendedAttributes);
|
| +
|
| + return $functionName;
|
| +}
|
| +
|
| +# Internal helper
|
| +sub WriteData
|
| +{
|
| + if (defined($IMPL)) {
|
| + # Write content to file.
|
| + print $IMPL @implContentHeader;
|
| +
|
| + print $IMPL @implFixedHeader;
|
| +
|
| + print $IMPL GenerateIncludes(keys(%implIncludes));
|
| +
|
| + print $IMPL "\n";
|
| + print $IMPL @implContent;
|
| + close($IMPL);
|
| + undef($IMPL);
|
| +
|
| + %implIncludes = ();
|
| + @implFixedHeader = ();
|
| + @implHeaderContent = ();
|
| + @implContent = ();
|
| + @dartNatives = ();
|
| + }
|
| +
|
| + if (defined($HEADER)) {
|
| + # Write content to file.
|
| + print $HEADER @headerContent;
|
| + close($HEADER);
|
| + undef($HEADER);
|
| +
|
| + @headerContent = ();
|
| + }
|
| +
|
| + if (defined($DART_INTERFACE)) {
|
| + # Write content of Dart file.
|
| + print $DART_INTERFACE @dartInterfaceContent;
|
| + close($DART_INTERFACE);
|
| + undef($DART_INTERFACE);
|
| +
|
| + @dartInterfaceContent = ();
|
| + }
|
| +
|
| + if (defined($DART_IMPL)) {
|
| + # Write content of Dart file.
|
| + print $DART_IMPL @dartImplContent;
|
| + close($DART_IMPL);
|
| + undef($DART_IMPL);
|
| +
|
| + @dartImplContent = ();
|
| + }
|
| +}
|
|
|