diff options
Diffstat (limited to 'WebCore/bindings/scripts')
-rw-r--r-- | WebCore/bindings/scripts/CodeGenerator.pm | 5 | ||||
-rw-r--r-- | WebCore/bindings/scripts/CodeGeneratorCOM.pm | 1319 | ||||
-rw-r--r-- | WebCore/bindings/scripts/CodeGeneratorJS.pm | 254 | ||||
-rw-r--r-- | WebCore/bindings/scripts/CodeGeneratorObjC.pm | 10 | ||||
-rw-r--r-- | WebCore/bindings/scripts/CodeGeneratorV8.pm | 760 | ||||
-rw-r--r-- | WebCore/bindings/scripts/IDLParser.pm | 5 | ||||
-rwxr-xr-x | WebCore/bindings/scripts/generate-bindings.pl | 1 |
7 files changed, 681 insertions, 1673 deletions
diff --git a/WebCore/bindings/scripts/CodeGenerator.pm b/WebCore/bindings/scripts/CodeGenerator.pm index c1cb0a0..dc3c7c0 100644 --- a/WebCore/bindings/scripts/CodeGenerator.pm +++ b/WebCore/bindings/scripts/CodeGenerator.pm @@ -43,10 +43,11 @@ my %primitiveTypeHash = ("int" => 1, "short" => 1, "long" => 1, "long long" => 1 "unsigned int" => 1, "unsigned short" => 1, "unsigned long" => 1, "unsigned long long" => 1, "float" => 1, "double" => 1, - "boolean" => 1, "void" => 1); + "boolean" => 1, "void" => 1, + "Date" => 1); my %podTypeHash = ("SVGNumber" => 1, "SVGTransform" => 1); -my %podTypesWithWritablePropertiesHash = ("SVGLength" => 1, "SVGMatrix" => 1, "SVGPoint" => 1, "SVGRect" => 1); +my %podTypesWithWritablePropertiesHash = ("SVGAngle" => 1, "SVGLength" => 1, "SVGMatrix" => 1, "SVGPoint" => 1, "SVGPreserveAspectRatio" => 1, "SVGRect" => 1); my %stringTypeHash = ("DOMString" => 1, "AtomicString" => 1); my %nonPointerTypeHash = ("DOMTimeStamp" => 1, "CompareHow" => 1, "SVGPaintType" => 1); diff --git a/WebCore/bindings/scripts/CodeGeneratorCOM.pm b/WebCore/bindings/scripts/CodeGeneratorCOM.pm deleted file mode 100644 index e98379b..0000000 --- a/WebCore/bindings/scripts/CodeGeneratorCOM.pm +++ /dev/null @@ -1,1319 +0,0 @@ -# -# Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org> -# Copyright (C) 2006 Anders Carlsson <andersca@mac.com> -# Copyright (C) 2006, 2007 Samuel Weinig <sam@webkit.org> -# Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org> -# Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. -# -# 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 CodeGeneratorCOM; - -use File::stat; - -# Global Variables -my $module = ""; -my $outputDir = ""; - -my @IDLHeader = (); -my @IDLContent = (); -my %IDLIncludes = (); -my %IDLForwardDeclarations = (); -my %IDLDontForwardDeclare = (); -my %IDLImports = (); -my %IDLDontImport = (); - -my @CPPInterfaceHeader = (); - -my @CPPHeaderHeader = (); -my @CPPHeaderContent = (); -my %CPPHeaderIncludes = (); -my %CPPHeaderIncludesAngle = (); -my %CPPHeaderForwardDeclarations = (); -my %CPPHeaderDontForwardDeclarations = (); - -my @CPPImplementationHeader = (); -my @CPPImplementationContent = (); -my %CPPImplementationIncludes = (); -my %CPPImplementationWebCoreIncludes = (); -my %CPPImplementationIncludesAngle = (); -my %CPPImplementationDontIncludes = (); - -my @additionalInterfaceDefinitions = (); - -my $DASHES = "----------------------------------------"; -my $TEMP_PREFIX = "GEN_"; - -# Hashes - -my %includeCorrector = map {($_, 1)} qw{UIEvent KeyboardEvent MouseEvent - MutationEvent OverflowEvent WheelEvent}; - -my %conflictMethod = ( - # FIXME: Add C language keywords? -); - -# Default License Templates -my @licenseTemplate = split(/\r/, << "EOF"); -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -EOF - -# Default constructor -sub new -{ - my $object = shift; - my $reference = { }; - - $codeGenerator = shift; - $outputDir = shift; - - bless($reference, $object); - return $reference; -} - -sub finish -{ - my $object = shift; -} - -# Params: 'domClass' struct -sub GenerateInterface -{ - my $object = shift; - my $dataNode = shift; - my $defines = shift; - - my $name = $dataNode->name; - - my $pureInterface = $dataNode->extendedAttributes->{"PureInterface"}; - - # Start actual generation.. - $object->GenerateIDL($dataNode, $pureInterface); - if ($pureInterface) { - $object->GenerateInterfaceHeader($dataNode); - } else { - $object->GenerateCPPHeader($dataNode); - $object->GenerateCPPImplementation($dataNode); - } - - # Write changes. - $object->WriteData($name, $pureInterface); -} - -# Params: 'idlDocument' struct -sub GenerateModule -{ - my $object = shift; - my $dataNode = shift; - - $module = $dataNode->module; -} - -sub GetInterfaceName -{ - my $name = $codeGenerator->StripModule(shift); - - die "GetInterfaceName should only be used on interfaces." if ($codeGenerator->IsStringType($name) or $codeGenerator->IsPrimitiveType($name)); - - # special cases - return "I" . $TEMP_PREFIX . "DOMAbstractView" if $name eq "DOMWindow"; - return "I" . $TEMP_PREFIX . $name if $name eq "DOMImplementation" or $name eq "DOMTimeStamp"; - - # Default, assume COM type has the same type name as - # idl type prefixed with "IDOM". - return "I" . $TEMP_PREFIX . "DOM" . $name; -} - -sub GetClassName -{ - my $name = $codeGenerator->StripModule(shift); - - # special cases - return "BSTR" if $codeGenerator->IsStringType($name); - return "BOOL" if $name eq "boolean"; - return "unsigned" if $name eq "unsigned long"; - return "int" if $name eq "long"; - return $name if $codeGenerator->IsPrimitiveType($name); - return $TEMP_PREFIX . "DOMAbstractView" if $name eq "DOMWindow"; - return $TEMP_PREFIX . $name if $name eq "DOMImplementation" or $name eq "DOMTimeStamp"; - - # Default, assume COM type has the same type name as - # idl type prefixed with "DOM". - return $TEMP_PREFIX . "DOM" . $name; -} - -sub GetCOMType -{ - my ($type) = @_; - - die "Don't use GetCOMType for string types, use one of In/Out variants instead." if $codeGenerator->IsStringType($type); - - return "BOOL" if $type eq "boolean"; - return "UINT" if $type eq "unsigned long"; - return "INT" if $type eq "long"; - return $type if $codeGenerator->IsPrimitiveType($type) or $type eq "DOMTimeStamp"; - # return "unsigned short" if $type eq "CompareHow" or $type eq "SVGPaintType"; - - return GetInterfaceName($type) . "*"; -} - -sub GetCOMTypeIn -{ - my ($type) = @_; - return "LPCTSTR" if $codeGenerator->IsStringType($type); - return GetCOMType($type); -} - -sub GetCOMTypeOut -{ - my ($type) = @_; - return "BSTR" if $codeGenerator->IsStringType($type); - return GetCOMType($type); -} - -sub IDLTypeToImplementationType -{ - my $type = $codeGenerator->StripModule(shift); - - return "bool" if $type eq "boolean"; - return "unsigned" if $type eq "unsigned long"; - return "int" if $type eq "long"; - return $type if $codeGenerator->IsPrimitiveType($type); - - return "WebCore::String" if $codeGenerator->IsStringType($type); - return "WebCore::${type}"; -} - -sub StripNamespace -{ - my ($type) = @_; - - $type =~ s/^WebCore:://; - - return $type; -} - -sub GetParentInterface -{ - my ($dataNode) = @_; - return "I" . $TEMP_PREFIX . "DOMObject" if (@{$dataNode->parents} == 0); - return GetInterfaceName($codeGenerator->StripModule($dataNode->parents(0))); -} - -sub GetParentClass -{ - my ($dataNode) = @_; - return $TEMP_PREFIX . "DOMObject" if (@{$dataNode->parents} == 0); - return GetClassName($codeGenerator->StripModule($dataNode->parents(0))); -} - -sub AddForwardDeclarationsForTypeInIDL -{ - my $type = $codeGenerator->StripModule(shift); - - return if $codeGenerator->IsNonPointerType($type) or $codeGenerator->IsStringType($type); - - my $interface = GetInterfaceName($type); - $IDLForwardDeclarations{$interface} = 1; - $IDLImports{$interface} = 1; -} - -sub AddIncludesForTypeInCPPHeader -{ - my $type = $codeGenerator->StripModule(shift); - my $useAngleBrackets = shift; - - return if $codeGenerator->IsNonPointerType($type); - - # Add special Cases HERE - - if ($type =~ m/^I/) { - $type = "WebKit"; - } - - if ($useAngleBrackets) { - $CPPHeaderIncludesAngle{"$type.h"} = 1; - return; - } - - if ($type eq "GEN_DOMImplementation") { - $CPPHeaderIncludes{"GEN_DOMDOMImplementation.h"} = 1; - return; - } - - if ($type eq "IGEN_DOMImplementation") { - $CPPHeaderIncludes{"IGEN_DOMDOMImplementation.h"} = 1; - return; - } - - $CPPHeaderIncludes{"$type.h"} = 1; -} - -sub AddForwardDeclarationsForTypeInCPPHeader -{ - my $type = $codeGenerator->StripModule(shift); - - return if $codeGenerator->IsNonPointerType($type) or $codeGenerator->IsStringType($type); - - my $interface = GetInterfaceName($type); - $CPPHeaderForwardDeclarations{$interface} = 1; -} - -sub AddIncludesForTypeInCPPImplementation -{ - my $type = $codeGenerator->StripModule(shift); - - die "Include type not supported!" if $includeCorrector{$type}; - - return if $codeGenerator->IsNonPointerType($type); - - if ($codeGenerator->IsStringType($type)) { - $CPPImplementationWebCoreIncludes{"AtomicString.h"} = 1; - $CPPImplementationWebCoreIncludes{"BString.h"} = 1; - $CPPImplementationWebCoreIncludes{"KURL.h"} = 1; - return; - } - - # Special casing - $CPPImplementationWebCoreIncludes{"NameNodeList.h"} = 1 if $type eq "NodeList"; - $CPPImplementationWebCoreIncludes{"CSSMutableStyleDeclaration.h"} = 1 if $type eq "CSSStyleDeclaration"; - - # Add implementation type - $CPPImplementationWebCoreIncludes{StripNamespace(IDLTypeToImplementationType($type)) . ".h"} = 1; - - my $COMClassName = GetClassName($type); - $CPPImplementationIncludes{"${COMClassName}.h"} = 1; -} - -sub GetAdditionalInterfaces -{ - # This function does nothing, but it stays here for future multiple inheritance support. - my $type = $codeGenerator->StripModule(shift); - return (); -} - -sub GenerateIDL -{ - my ($object, $dataNode, $pureInterface) = @_; - - my $inInterfaceName = $dataNode->name; - my $outInterfaceName = GetInterfaceName($inInterfaceName); - my $uuid = $dataNode->extendedAttributes->{"InterfaceUUID"} || die "All classes require an InterfaceUUID extended attribute."; - - my $parentInterfaceName = ($pureInterface) ? "IUnknown" : GetParentInterface($dataNode); - - my $numConstants = @{$dataNode->constants}; - my $numAttributes = @{$dataNode->attributes}; - my $numFunctions = @{$dataNode->functions}; - - # - Add default header template - @IDLHeader = @licenseTemplate; - push(@IDLHeader, "\n"); - - # - INCLUDES - - push(@IDLHeader, "#ifndef DO_NO_IMPORTS\n"); - push(@IDLHeader, "import \"oaidl.idl\";\n"); - push(@IDLHeader, "import \"ocidl.idl\";\n"); - push(@IDLHeader, "#endif\n\n"); - - unless ($pureInterface) { - push(@IDLHeader, "#ifndef DO_NO_IMPORTS\n"); - push(@IDLHeader, "import \"${parentInterfaceName}.idl\";\n"); - push(@IDLHeader, "#endif\n\n"); - - $IDLDontForwardDeclare{$outInterfaceName} = 1; - $IDLDontImport{$outInterfaceName} = 1; - $IDLDontForwardDeclare{$parentInterfaceName} = 1; - $IDLDontImport{$parentInterfaceName} = 1; - } - - # - Begin - # -- Attributes - push(@IDLContent, "[\n"); - push(@IDLContent, " object,\n"); - push(@IDLContent, " oleautomation,\n"); - push(@IDLContent, " uuid(" . $uuid . "),\n"); - push(@IDLContent, " pointer_default(unique)\n"); - push(@IDLContent, "]\n"); - - # -- Interface - push(@IDLContent, "interface " . $outInterfaceName . " : " . $parentInterfaceName . "\n"); - push(@IDLContent, "{\n"); - - - # - FIXME: Add constants. - - - # - Add attribute getters/setters. - if ($numAttributes > 0) { - foreach my $attribute (@{$dataNode->attributes}) { - my $attributeName = $attribute->signature->name; - my $attributeIDLType = $attribute->signature->type; - my $attributeTypeIn = GetCOMTypeIn($attributeIDLType); - my $attributeTypeOut = GetCOMTypeOut($attributeIDLType); - my $attributeIsReadonly = ($attribute->type =~ /^readonly/); - - AddForwardDeclarationsForTypeInIDL($attributeIDLType); - - unless ($attributeIsReadonly) { - # Setter - my $setterName = "set" . $codeGenerator->WK_ucfirst($attributeName); - my $setter = " HRESULT " . $setterName . "([in] " . $attributeTypeIn . ");\n"; - push(@IDLContent, $setter); - } - - # Getter - my $getter = " HRESULT " . $attributeName . "([out, retval] " . $attributeTypeOut . "*);\n\n"; - push(@IDLContent, $getter); - } - } - - # - Add functions. - if ($numFunctions > 0) { - foreach my $function (@{$dataNode->functions}) { - my $functionName = $function->signature->name; - my $returnIDLType = $function->signature->type; - my $returnType = GetCOMTypeOut($returnIDLType); - my $noReturn = ($returnType eq "void"); - - AddForwardDeclarationsForTypeInIDL($returnIDLType); - - my @paramArgList = (); - foreach my $param (@{$function->parameters}) { - my $paramName = $param->name; - my $paramIDLType = $param->type; - my $paramType = GetCOMTypeIn($param->type); - - AddForwardDeclarationsForTypeInIDL($paramIDLType); - - # Form parameter - my $parameter = "[in] ${paramType} ${paramName}"; - - # Add parameter to function signature - push(@paramArgList, $parameter); - } - - unless ($noReturn) { - my $resultParameter = "[out, retval] " . $returnType . "* result"; - push(@paramArgList, $resultParameter); - } - - my $functionSig = " HRESULT " . $functionName . "("; - $functionSig .= join(", ", @paramArgList); - $functionSig .= ");\n\n"; - push(@IDLContent, $functionSig); - } - } - - # - End - push(@IDLContent, "}\n\n"); -} - -sub GenerateInterfaceHeader -{ - my ($object, $dataNode) = @_; - - my $IDLType = $dataNode->name; - my $implementationClass = IDLTypeToImplementationType($IDLType); - my $implementationClassWithoutNamespace = StripNamespace($implementationClass); - my $className = GetClassName($IDLType); - my $interfaceName = GetInterfaceName($IDLType); - - # - Add default header template - @CPPInterfaceHeader = @licenseTemplate; - push(@CPPInterfaceHeader, "\n"); - - # - Header guards - - push(@CPPInterfaceHeader, "#ifndef " . $className . "_h\n"); - push(@CPPInterfaceHeader, "#define " . $className . "_h\n\n"); - - # - Forward Declarations - - push(@CPPInterfaceHeader, "interface ${interfaceName};\n\n"); - push(@CPPInterfaceHeader, "namespace WebCore {\n"); - push(@CPPInterfaceHeader, " class ${implementationClassWithoutNamespace};\n"); - push(@CPPInterfaceHeader, "}\n\n"); - - # - Default Interface Creator - - push(@CPPInterfaceHeader, "${interfaceName}* to${interfaceName}(${implementationClass}*) { return 0; }\n\n"); - - push(@CPPInterfaceHeader, "#endif // " . $className . "_h\n"); -} - -# ----------------------------------------------------------------------------- -# CPP Helper Functions -# ----------------------------------------------------------------------------- - -sub GenerateCPPAttributeSignature -{ - my ($attribute, $className, $options) = @_; - - my $attributeName = $attribute->signature->name; - my $isReadonly = ($attribute->type =~ /^readonly/); - - my $newline = $$options{"NewLines"} ? "\n" : ""; - my $indent = $$options{"Indent"} ? " " x $$options{"Indent"} : ""; - my $semicolon = $$options{"IncludeSemiColon"} ? ";" : ""; - my $virtual = $$options{"AddVirtualKeyword"} ? "virtual " : ""; - my $class = $$options{"UseClassName"} ? "${className}::" : ""; - my $forwarder = $$options{"Forwarder"} ? 1 : 0; - my $joiner = ($$options{"NewLines"} ? "\n" . $indent . " " : ""); - - my %attributeSignatures = (); - - unless ($isReadonly) { - my $attributeTypeIn = GetCOMTypeIn($attribute->signature->type); - my $setterName = "set" . $codeGenerator->WK_ucfirst($attributeName); - my $setter = $indent . $virtual . "HRESULT STDMETHODCALLTYPE ". $class . $setterName . "("; - $setter .= $joiner . "/* [in] */ ${attributeTypeIn} ${attributeName})" . $semicolon . $newline; - if ($forwarder) { - $setter .= " { return " . $$options{"Forwarder"} . "::" . $setterName . "(${attributeName}); }\n"; - } - $attributeSignatures{"Setter"} = $setter; - } - - my $attributeTypeOut = GetCOMTypeOut($attribute->signature->type); - my $getter = $indent . $virtual . "HRESULT STDMETHODCALLTYPE " . $class . $attributeName . "("; - $getter .= $joiner . "/* [retval][out] */ ${attributeTypeOut}* result)" . $semicolon . $newline; - if ($forwarder) { - $getter .= " { return " . $$options{"Forwarder"} . "::" . $attributeName . "(result); }\n"; - } - $attributeSignatures{"Getter"} = $getter; - - return %attributeSignatures; -} - - -sub GenerateCPPAttribute -{ - my ($attribute, $className, $implementationClass, $IDLType) = @_; - - my $implementationClassWithoutNamespace = StripNamespace($implementationClass); - - my $attributeName = $attribute->signature->name; - my $attributeIDLType = $attribute->signature->type; - my $hasSetterException = @{$attribute->setterExceptions}; - my $hasGetterException = @{$attribute->getterExceptions}; - my $isReadonly = ($attribute->type =~ /^readonly/); - my $attributeTypeIsPrimitive = $codeGenerator->IsPrimitiveType($attributeIDLType); - my $attributeTypeIsString = $codeGenerator->IsStringType($attributeIDLType); - my $attributeImplementationType = IDLTypeToImplementationType($attributeIDLType); - my $attributeImplementationTypeWithoutNamespace = StripNamespace($attributeImplementationType); - my $attributeTypeCOMClassName = GetClassName($attributeIDLType); - - $CPPImplementationWebCoreIncludes{"ExceptionCode.h"} = 1 if $hasSetterException or $hasGetterException; - - my %signatures = GenerateCPPAttributeSignature($attribute, $className, { "NewLines" => 1, - "Indent" => 0, - "IncludeSemiColon" => 0, - "UseClassName" => 1, - "AddVirtualKeyword" => 0 }); - - my %attrbutesToReturn = (); - - unless ($isReadonly) { - my @setterImplementation = (); - push(@setterImplementation, $signatures{"Setter"}); - push(@setterImplementation, "{\n"); - - my $setterName = "set" . $codeGenerator->WK_ucfirst($attributeName); - - my @setterParams = (); - if ($attributeTypeIsString) { - push(@setterParams, $attributeName); - if ($hasSetterException) { - push(@setterImplementation, " WebCore::ExceptionCode ec = 0;\n"); - push(@setterParams, "ec"); - } - } elsif ($attributeTypeIsPrimitive) { - if ($attribute->signature->extendedAttributes->{"ConvertFromString"}) { - push(@setterParams, "WebCore::String::number(${attributeName})"); - } elsif ($attributeIDLType eq "boolean") { - push(@setterParams, "!!${attributeName}"); - } else { - my $primitiveImplementationType = IDLTypeToImplementationType($attributeIDLType); - push(@setterParams, "static_cast<${primitiveImplementationType}>(${attributeName})"); - } - - if ($hasSetterException) { - push(@setterImplementation, " WebCore::ExceptionCode ec = 0;\n"); - push(@setterParams, "ec"); - } - } else { - $CPPImplementationWebCoreIncludes{"COMPtr.h"} = 1; - - push(@setterImplementation, " if (!${attributeName})\n"); - push(@setterImplementation, " return E_POINTER;\n\n"); - push(@setterImplementation, " COMPtr<${attributeTypeCOMClassName}> ptr(Query, ${attributeName});\n"); - push(@setterImplementation, " if (!ptr)\n"); - push(@setterImplementation, " return E_NOINTERFACE;\n"); - - push(@setterParams, "ptr->impl${attributeImplementationTypeWithoutNamespace}()"); - if ($hasSetterException) { - push(@setterImplementation, " WebCore::ExceptionCode ec = 0;\n"); - push(@setterParams, "ec"); - } - } - - # FIXME: CHECK EXCEPTION AND DO SOMETHING WITH IT - - my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; - my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"}; - if ($reflect || $reflectURL) { - my $contentAttributeName = (($reflect || $reflectURL) eq "1") ? $attributeName : ($reflect || $reflectURL); - my $namespace = $codeGenerator->NamespaceForAttributeName($IDLType, $contentAttributeName); - $CPPImplementationWebCoreIncludes{"${namespace}.h"} = 1; - push(@setterImplementation, " impl${implementationClassWithoutNamespace}()->setAttribute(WebCore::${namespace}::${contentAttributeName}Attr, " . join(", ", @setterParams) . ");\n"); - } else { - push(@setterImplementation, " impl${implementationClassWithoutNamespace}()->${setterName}(" . join(", ", @setterParams) . ");\n"); - } - push(@setterImplementation, " return S_OK;\n"); - push(@setterImplementation, "}\n\n"); - - $attrbutesToReturn{"Setter"} = join("", @setterImplementation); - } - - my @getterImplementation = (); - push(@getterImplementation, $signatures{"Getter"}); - push(@getterImplementation, "{\n"); - push(@getterImplementation, " if (!result)\n"); - push(@getterImplementation, " return E_POINTER;\n\n"); - - my $implementationGetter; - my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; - my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"}; - if ($reflect || $reflectURL) { - my $contentAttributeName = (($reflect || $reflectURL) eq "1") ? $attributeName : ($reflect || $reflectURL); - my $namespace = $codeGenerator->NamespaceForAttributeName($IDLType, $contentAttributeName); - $implIncludes{"${namespace}.h"} = 1; - my $getAttributeFunctionName = $reflectURL ? "getURLAttribute" : "getAttribute"; - $implementationGetter = "impl${implementationClassWithoutNamespace}()->${getAttributeFunctionName}(WebCore::${namespace}::${contentAttributeName}Attr)"; - } else { - $implementationGetter = "impl${implementationClassWithoutNamespace}()->" . $codeGenerator->WK_lcfirst($attributeName) . "(" . ($hasGetterException ? "ec" : ""). ")"; - } - - push(@getterImplementation, " WebCore::ExceptionCode ec = 0;\n") if $hasGetterException; - - if ($attributeTypeIsString) { - push(@getterImplementation, " *result = WebCore::BString(${implementationGetter}).release();\n"); - } elsif ($attributeTypeIsPrimitive) { - if ($attribute->signature->extendedAttributes->{"ConvertFromString"}) { - push(@getterImplementation, " *result = static_cast<${attributeTypeCOMClassName}>(${implementationGetter}.toInt());\n"); - } else { - push(@getterImplementation, " *result = static_cast<${attributeTypeCOMClassName}>(${implementationGetter});\n"); - } - } else { - $CPPImplementationIncludesAngle{"wtf/GetPtr.h"} = 1; - my $attributeTypeCOMInterfaceName = GetInterfaceName($attributeIDLType); - push(@getterImplementation, " *result = 0;\n"); - push(@getterImplementation, " ${attributeImplementationType}* resultImpl = WTF::getPtr(${implementationGetter});\n"); - push(@getterImplementation, " if (!resultImpl)\n"); - push(@getterImplementation, " return E_POINTER;\n\n"); - push(@getterImplementation, " *result = to${attributeTypeCOMInterfaceName}(resultImpl);\n"); - } - - # FIXME: CHECK EXCEPTION AND DO SOMETHING WITH IT - - push(@getterImplementation, " return S_OK;\n"); - push(@getterImplementation, "}\n\n"); - - $attrbutesToReturn{"Getter"} = join("", @getterImplementation); - - return %attrbutesToReturn; -} - -sub GenerateCPPFunctionSignature -{ - my ($function, $className, $options) = @_; - - my $functionName = $function->signature->name; - my $returnIDLType = $function->signature->type; - my $returnType = GetCOMTypeOut($returnIDLType); - my $noReturn = ($returnType eq "void"); - - my $newline = $$options{"NewLines"} ? "\n" : ""; - my $indent = $$options{"Indent"} ? " " x $$options{"Indent"} : ""; - my $semicolon = $$options{"IncludeSemiColon"} ? ";" : ""; - my $virtual = $$options{"AddVirtualKeyword"} ? "virtual " : ""; - my $class = $$options{"UseClassName"} ? "${className}::" : ""; - my $forwarder = $$options{"Forwarder"} ? 1 : 0; - my $joiner = ($$options{"NewLines"} ? "\n" . $indent . " " : " "); - - my @paramArgList = (); - foreach my $param (@{$function->parameters}) { - my $paramName = $param->name; - my $paramType = GetCOMTypeIn($param->type); - my $parameter = "/* [in] */ ${paramType} ${paramName}"; - push(@paramArgList, $parameter); - } - - unless ($noReturn) { - my $resultParameter .= "/* [out, retval] */ ${returnType}* result"; - push(@paramArgList, $resultParameter); - } - - my $functionSig = $indent . $virtual . "HRESULT STDMETHODCALLTYPE " . $class . $functionName . "("; - $functionSig .= $joiner . join("," . $joiner, @paramArgList) if @paramArgList > 0; - $functionSig .= ")" . $semicolon . $newline; - if ($forwarder) { - my @paramNameList = (); - push(@paramNameList, $_->name) foreach (@{$function->parameters}); - push(@paramNameList, "result") unless $noReturn; - $functionSig .= " { return " . $$options{"Forwarder"} . "::" . $functionName . "(" . join(", ", @paramNameList) . "); }\n"; - } - - return $functionSig -} - -sub GenerateCPPFunction -{ - my ($function, $className, $implementationClass) = @_; - - my @functionImplementation = (); - - my $signature = GenerateCPPFunctionSignature($function, $className, { "NewLines" => 1, - "Indent" => 0, - "IncludeSemiColon" => 0, - "UseClassName" => 1, - "AddVirtualKeyword" => 0 }); - - my $implementationClassWithoutNamespace = StripNamespace($implementationClass); - - my $functionName = $function->signature->name; - my $returnIDLType = $function->signature->type; - my $noReturn = ($returnIDLType eq "void"); - my $raisesExceptions = @{$function->raisesExceptions}; - - AddIncludesForTypeInCPPImplementation($returnIDLType); - $CPPImplementationWebCoreIncludes{"ExceptionCode.h"} = 1 if $raisesExceptions; - - my %needsCustom = (); - my @parameterInitialization = (); - my @parameterList = (); - foreach my $param (@{$function->parameters}) { - my $paramName = $param->name; - my $paramIDLType = $param->type; - - my $paramTypeIsPrimitive = $codeGenerator->IsPrimitiveType($paramIDLType); - my $paramTypeIsString = $codeGenerator->IsStringType($paramIDLType); - - $needsCustom{"NodeToReturn"} = $paramName if $param->extendedAttributes->{"Return"}; - - AddIncludesForTypeInCPPImplementation($paramIDLType); - - # FIXME: We may need to null check the arguments as well - - if ($paramTypeIsString) { - push(@parameterList, $paramName); - } elsif ($paramTypeIsPrimitive) { - if ($paramIDLType eq "boolean") { - push(@parameterList, "!!${paramName}"); - } else { - my $primitiveImplementationType = IDLTypeToImplementationType($paramIDLType); - push(@parameterList, "static_cast<${primitiveImplementationType}>(${paramName})"); - } - } else { - $CPPImplementationWebCoreIncludes{"COMPtr.h"} = 1; - - $needsCustom{"CanReturnEarly"} = 1; - - my $paramTypeCOMClassName = GetClassName($paramIDLType); - my $paramTypeImplementationWithoutNamespace = StripNamespace(IDLTypeToImplementationType($paramIDLType)); - my $ptrName = "ptrFor" . $codeGenerator->WK_ucfirst($paramName); - my $paramInit = " COMPtr<${paramTypeCOMClassName}> ${ptrName}(Query, ${paramName});\n"; - $paramInit .= " if (!${ptrName})\n"; - $paramInit .= " return E_NOINTERFACE;"; - push(@parameterInitialization, $paramInit); - push(@parameterList, "${ptrName}->impl${paramTypeImplementationWithoutNamespace}()"); - } - } - - push(@parameterList, "ec") if $raisesExceptions; - - my $implementationGetter = "impl${implementationClassWithoutNamespace}()"; - - my $callSigBegin = " "; - my $callSigMiddle = "${implementationGetter}->" . $codeGenerator->WK_lcfirst($functionName) . "(" . join(", ", @parameterList) . ")"; - my $callSigEnd = ";\n"; - - if (defined $needsCustom{"NodeToReturn"}) { - my $nodeToReturn = $needsCustom{"NodeToReturn"}; - $callSigBegin .= "if ("; - $callSigEnd = ")\n"; - $callSigEnd .= " *result = ${nodeToReturn};"; - } elsif (!$noReturn) { - my $returnTypeIsString = $codeGenerator->IsStringType($returnIDLType); - my $returnTypeIsPrimitive = $codeGenerator->IsPrimitiveType($returnIDLType); - - if ($returnTypeIsString) { - $callSigBegin .= "*result = WebCore::BString("; - $callSigEnd = ").release();\n"; - } elsif ($returnTypeIsPrimitive) { - my $primitiveCOMType = GetClassName($returnIDLType); - $callSigBegin .= "*result = static_cast<${primitiveCOMType}>("; - $callSigEnd = ");"; - } else { - $CPPImplementationIncludesAngle{"wtf/GetPtr.h"} = 1; - my $returnImplementationType = IDLTypeToImplementationType($returnIDLType); - my $returnTypeCOMInterfaceName = GetInterfaceName($returnIDLType); - $callSigBegin .= "${returnImplementationType}* resultImpl = WTF::getPtr("; - $callSigEnd = ");\n"; - $callSigEnd .= " if (!resultImpl)\n"; - $callSigEnd .= " return E_POINTER;\n\n"; - $callSigEnd .= " *result = to${returnTypeCOMInterfaceName}(resultImpl);"; - } - } - - push(@functionImplementation, $signature); - push(@functionImplementation, "{\n"); - unless ($noReturn) { - push(@functionImplementation, " if (!result)\n"); - push(@functionImplementation, " return E_POINTER;\n\n"); - push(@functionImplementation, " *result = 0;\n\n") if $needsCustom{"CanReturnEarly"}; - } - push(@functionImplementation, " WebCore::ExceptionCode ec = 0;\n") if $raisesExceptions; # FIXME: CHECK EXCEPTION AND DO SOMETHING WITH IT - push(@functionImplementation, join("\n", @parameterInitialization) . (@parameterInitialization > 0 ? "\n" : "")); - push(@functionImplementation, $callSigBegin . $callSigMiddle . $callSigEnd . "\n"); - push(@functionImplementation, " return S_OK;\n"); - push(@functionImplementation, "}\n\n"); - - return join("", @functionImplementation); -} - - -# ----------------------------------------------------------------------------- -# CPP Header -# ----------------------------------------------------------------------------- - -sub GenerateCPPHeader -{ - my ($object, $dataNode) = @_; - - my $IDLType = $dataNode->name; - my $implementationClass = IDLTypeToImplementationType($IDLType); - my $implementationClassWithoutNamespace = StripNamespace($implementationClass); - my $className = GetClassName($IDLType); - my $interfaceName = GetInterfaceName($IDLType); - - my $parentClassName = GetParentClass($dataNode); - my @otherInterfacesImplemented = GetAdditionalInterfaces($IDLType); - foreach my $otherInterface (@otherInterfacesImplemented) { - push(@additionalInterfaceDefinitions, $codeGenerator->ParseInterface($otherInterface)); - } - - # FIXME: strip whitespace from UUID - my $uuid = $dataNode->extendedAttributes->{"ImplementationUUID"} || die "All classes require an ImplementationUUID extended attribute."; - - my $numAttributes = @{$dataNode->attributes}; - my $numFunctions = @{$dataNode->functions}; - - # - Add default header template - @CPPHeaderHeader = @licenseTemplate; - push(@CPPHeaderHeader, "\n"); - - # - Header guards - - push(@CPPHeaderHeader, "#ifndef " . $className . "_h\n"); - push(@CPPHeaderHeader, "#define " . $className . "_h\n\n"); - - AddIncludesForTypeInCPPHeader($interfaceName); - AddIncludesForTypeInCPPHeader($parentClassName); - $CPPHeaderDontForwardDeclarations{$className} = 1; - $CPPHeaderDontForwardDeclarations{$interfaceName} = 1; - $CPPHeaderDontForwardDeclarations{$parentClassName} = 1; - - # -- Forward declare implementation type - push(@CPPHeaderContent, "namespace WebCore {\n"); - push(@CPPHeaderContent, " class ". StripNamespace($implementationClass) . ";\n"); - push(@CPPHeaderContent, "}\n\n"); - - # -- Start Class -- - my @parentsClasses = ($parentClassName, $interfaceName); - push(@parentsClasses, map { GetInterfaceName($_) } @otherInterfacesImplemented); - push(@CPPHeaderContent, "class __declspec(uuid(\"$uuid\")) ${className} : " . join(", ", map { "public $_" } @parentsClasses) . " {\n"); - - # Add includes for all additional interfaces to implement - map { AddIncludesForTypeInCPPHeader(GetInterfaceName($_)) } @otherInterfacesImplemented; - - # -- BASICS -- - # FIXME: The constructor and destructor should be protected, but the current design of - # createInstance requires them to be public. One solution is to friend the constructor - # of the top-level-class with every one of its child classes, but that requires information - # this script currently does not have, though possibly could determine. - push(@CPPHeaderContent, "public:\n"); - push(@CPPHeaderContent, " ${className}(${implementationClass}*);\n"); - push(@CPPHeaderContent, " virtual ~${className}();\n\n"); - - push(@CPPHeaderContent, "public:\n"); - push(@CPPHeaderContent, " static ${className}* createInstance(${implementationClass}*);\n\n"); - - push(@CPPHeaderContent, " // IUnknown\n"); - push(@CPPHeaderContent, " virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void** ppvObject);\n"); - push(@CPPHeaderContent, " virtual ULONG STDMETHODCALLTYPE AddRef() { return ${parentClassName}::AddRef(); }\n"); - push(@CPPHeaderContent, " virtual ULONG STDMETHODCALLTYPE Release() { return ${parentClassName}::Release(); }\n\n"); - - - # -- Parent Class Forwards -- - if (@{$dataNode->parents}) { - my %attributeNameSet = map {($_->signature->name, 1)} @{$dataNode->attributes}; - my %functionNameSet = map {($_->signature->name, 1)} @{$dataNode->functions}; - - my @parentLists = $codeGenerator->GetMethodsAndAttributesFromParentClasses($dataNode); - push(@CPPHeaderContent, "\n"); - foreach my $parentHash (@parentLists) { - - push(@CPPHeaderContent, " // " . GetInterfaceName($parentHash->{'name'}) . $DASHES . "\n"); - - my @attributeList = @{$parentHash->{'attributes'}}; - push(@CPPHeaderContent, " // Attributes\n"); - foreach my $attribute (@attributeList) { - # Don't forward an attribute that this class redefines. - next if $attributeNameSet{$attribute->signature->name}; - - AddForwardDeclarationsForTypeInCPPHeader($attribute->signature->type); - - my %attributes = GenerateCPPAttributeSignature($attribute, $className, { "NewLines" => 0, - "Indent" => 4, - "IncludeSemiColon" => 0, - "AddVirtualKeyword" => 1, - "UseClassName" => 0, - "Forwarder" => $parentClassName }); - push(@CPPHeaderContent, values(%attributes)); - } - - # Add attribute names to attribute names set in case other ancestors - # also define them. - $attributeNameSet{$_->signature->name} = 1 foreach @attributeList; - - push(@CPPHeaderContent, "\n"); - - my @functionList = @{$parentHash->{'functions'}}; - push(@CPPHeaderContent, " // Functions\n"); - foreach my $function (@functionList) { - # Don't forward a function that this class redefines. - next if $functionNameSet{$function->signature->name}; - - AddForwardDeclarationsForTypeInCPPHeader($function->signature->type); - AddForwardDeclarationsForTypeInCPPHeader($_->type) foreach (@{$function->parameters}); - - my $functionSig = GenerateCPPFunctionSignature($function, $className, { "NewLines" => 0, - "Indent" => 4, - "IncludeSemiColon" => 0, - "AddVirtualKeyword" => 1, - "UseClassName" => 0, - "Forwarder" => $parentClassName }); - - push(@CPPHeaderContent, $functionSig); - } - # Add functions names to functions names set in case other ancestors - # also define them. - $functionNameSet{$_->signature->name} = 1 foreach @functionList; - - push(@CPPHeaderContent, "\n"); - } - } - - # - Additional interfaces to implement - - foreach my $interfaceToImplement (@additionalInterfaceDefinitions) { - my $IDLTypeOfInterfaceToImplement = $interfaceToImplement->name; - my $nameOfInterfaceToImplement = GetInterfaceName($IDLTypeOfInterfaceToImplement); - my $numAttributesInInterface = @{$interfaceToImplement->attributes}; - my $numFunctionsInInterface = @{$interfaceToImplement->functions}; - - push(@CPPHeaderContent, " // ${nameOfInterfaceToImplement} ${DASHES}\n\n"); - - # - Add attribute getters/setters. - if ($numAttributesInInterface > 0) { - push(@CPPHeaderContent, " // Attributes\n\n"); - foreach my $attribute (@{$interfaceToImplement->attributes}) { - AddForwardDeclarationsForTypeInCPPHeader($attribute->signature->type); - - my %attributeSigs = GenerateCPPAttributeSignature($attribute, $className, { "NewLines" => 1, - "Indent" => 4, - "IncludeSemiColon" => 1, - "AddVirtualKeyword" => 1, - "UseClassName" => 0 }); - - push(@CPPHeaderContent, values(%attributeSigs)); - push(@CPPHeaderContent, "\n"); - } - } - - # - Add functions. - if ($numFunctionsInInterface > 0) { - push(@CPPHeaderContent, " // Functions\n\n"); - foreach my $function (@{$interfaceToImplement->functions}) { - AddForwardDeclarationsForTypeInCPPHeader($function->signature->type); - AddForwardDeclarationsForTypeInCPPHeader($_->type) foreach (@{$function->parameters}); - - my $functionSig = GenerateCPPFunctionSignature($function, $className, { "NewLines" => 1, - "Indent" => 4, - "IncludeSemiColon" => 1, - "AddVirtualKeyword" => 1, - "UseClassName" => 0 }); - - push(@CPPHeaderContent, $functionSig); - push(@CPPHeaderContent, "\n"); - } - } - } - - if ($numAttributes > 0 || $numFunctions > 0) { - push(@CPPHeaderContent, " // ${interfaceName} ${DASHES}\n\n"); - } - - # - Add constants COMING SOON - - # - Add attribute getters/setters. - if ($numAttributes > 0) { - push(@CPPHeaderContent, " // Attributes\n\n"); - foreach my $attribute (@{$dataNode->attributes}) { - AddForwardDeclarationsForTypeInCPPHeader($attribute->signature->type); - - my %attributeSigs = GenerateCPPAttributeSignature($attribute, $className, { "NewLines" => 1, - "Indent" => 4, - "IncludeSemiColon" => 1, - "AddVirtualKeyword" => 1, - "UseClassName" => 0 }); - - push(@CPPHeaderContent, values(%attributeSigs)); - push(@CPPHeaderContent, "\n"); - } - } - - # - Add functions. - if ($numFunctions > 0) { - push(@CPPHeaderContent, " // Functions\n\n"); - foreach my $function (@{$dataNode->functions}) { - AddForwardDeclarationsForTypeInCPPHeader($function->signature->type); - AddForwardDeclarationsForTypeInCPPHeader($_->type) foreach (@{$function->parameters}); - - my $functionSig = GenerateCPPFunctionSignature($function, $className, { "NewLines" => 1, - "Indent" => 4, - "IncludeSemiColon" => 1, - "AddVirtualKeyword" => 1, - "UseClassName" => 0 }); - - push(@CPPHeaderContent, $functionSig); - push(@CPPHeaderContent, "\n"); - } - } - - push(@CPPHeaderContent, " ${implementationClass}* impl${implementationClassWithoutNamespace}() const;\n"); - - if (@{$dataNode->parents} == 0) { - AddIncludesForTypeInCPPHeader("wtf/RefPtr", 1); - push(@CPPHeaderContent, "\n"); - push(@CPPHeaderContent, " ${implementationClass}* impl() const { return m_impl.get(); }\n\n"); - push(@CPPHeaderContent, "private:\n"); - push(@CPPHeaderContent, " RefPtr<${implementationClass}> m_impl;\n"); - } - - # -- End Class -- - push(@CPPHeaderContent, "};\n\n"); - - # -- Default Interface Creator -- - push(@CPPHeaderContent, "${interfaceName}* to${interfaceName}(${implementationClass}*);\n\n"); - - push(@CPPHeaderContent, "#endif // " . $className . "_h\n"); -} - - -# ----------------------------------------------------------------------------- -# CPP Implementation -# ----------------------------------------------------------------------------- - -sub GenerateCPPImplementation -{ - my ($object, $dataNode) = @_; - - my $IDLType = $dataNode->name; - my $implementationClass = IDLTypeToImplementationType($IDLType); - my $implementationClassWithoutNamespace = StripNamespace($implementationClass); - my $className = GetClassName($IDLType); - my $interfaceName = GetInterfaceName($IDLType); - - my $parentClassName = GetParentClass($dataNode); - my $isBaseClass = (@{$dataNode->parents} == 0); - - my $uuid = $dataNode->extendedAttributes->{"ImplementationUUID"} || die "All classes require an ImplementationUUID extended attribute."; - - my $numAttributes = @{$dataNode->attributes}; - my $numFunctions = @{$dataNode->functions}; - - # - Add default header template - @CPPImplementationHeader = @licenseTemplate; - push(@CPPImplementationHeader, "\n"); - - push(@CPPImplementationHeader, "#include \"config.h\"\n"); - push(@CPPImplementationHeader, "#include \"WebKitDLL.h\"\n"); - push(@CPPImplementationHeader, "#include " . ($className eq "GEN_DOMImplementation" ? "\"GEN_DOMDOMImplementation.h\"" : "\"${className}.h\"") . "\n"); - $CPPImplementationDontIncludes{"${className}.h"} = 1; - $CPPImplementationWebCoreIncludes{"${implementationClassWithoutNamespace}.h"} = 1; - - # -- Constructor -- - push(@CPPImplementationContent, "${className}::${className}(${implementationClass}* impl)\n"); - if ($isBaseClass) { - push(@CPPImplementationContent, " : m_impl(impl)\n"); - push(@CPPImplementationContent, "{\n"); - push(@CPPImplementationContent, " ASSERT_ARG(impl, impl);\n"); - push(@CPPImplementationContent, "}\n\n"); - } else { - push(@CPPImplementationContent, " : ${parentClassName}(impl)\n"); - push(@CPPImplementationContent, "{\n"); - push(@CPPImplementationContent, "}\n\n"); - } - - # -- Destructor -- - push(@CPPImplementationContent, "${className}::~${className}()\n"); - push(@CPPImplementationContent, "{\n"); - if ($isBaseClass) { - $CPPImplementationIncludes{"DOMCreateInstance.h"} = 1; - push(@CPPImplementationContent, " removeDOMWrapper(impl());\n"); - } - push(@CPPImplementationContent, "}\n\n"); - - push(@CPPImplementationContent, "${implementationClass}* ${className}::impl${implementationClassWithoutNamespace}() const\n"); - push(@CPPImplementationContent, "{\n"); - push(@CPPImplementationContent, " return static_cast<${implementationClass}*>(impl());\n"); - push(@CPPImplementationContent, "}\n\n"); - - # Base classes must implement the createInstance method externally. - if (@{$dataNode->parents} != 0) { - push(@CPPImplementationContent, "${className}* ${className}::createInstance(${implementationClass}* impl)\n"); - push(@CPPImplementationContent, "{\n"); - push(@CPPImplementationContent, " return static_cast<${className}*>(${parentClassName}::createInstance(impl));\n"); - push(@CPPImplementationContent, "}\n"); - } - - push(@CPPImplementationContent, "// IUnknown $DASHES\n\n"); - - # -- QueryInterface -- - push(@CPPImplementationContent, "HRESULT STDMETHODCALLTYPE ${className}::QueryInterface(REFIID riid, void** ppvObject)\n"); - push(@CPPImplementationContent, "{\n"); - push(@CPPImplementationContent, " *ppvObject = 0;\n"); - push(@CPPImplementationContent, " if (IsEqualGUID(riid, IID_${interfaceName}))\n"); - push(@CPPImplementationContent, " *ppvObject = reinterpret_cast<${interfaceName}*>(this);\n"); - push(@CPPImplementationContent, " else if (IsEqualGUID(riid, __uuidof(${className})))\n"); - push(@CPPImplementationContent, " *ppvObject = reinterpret_cast<${className}*>(this);\n"); - push(@CPPImplementationContent, " else\n"); - push(@CPPImplementationContent, " return ${parentClassName}::QueryInterface(riid, ppvObject);\n\n"); - push(@CPPImplementationContent, " AddRef();\n"); - push(@CPPImplementationContent, " return S_OK;\n"); - push(@CPPImplementationContent, "}\n\n"); - - # - Additional interfaces to implement - - foreach my $interfaceToImplement (@additionalInterfaceDefinitions) { - my $IDLTypeOfInterfaceToImplement = $interfaceToImplement->name; - my $nameOfInterfaceToImplement = GetInterfaceName($IDLTypeOfInterfaceToImplement); - my $numAttributesInInterface = @{$interfaceToImplement->attributes}; - my $numFunctionsInInterface = @{$interfaceToImplement->functions}; - - push(@CPPImplementationContent, " // ${nameOfInterfaceToImplement} ${DASHES}\n\n"); - - if ($numAttributesInInterface > 0) { - push(@CPPImplementationContent, "// Attributes\n\n"); - foreach my $attribute (@{$interfaceToImplement->attributes}) { - # FIXME: Do this in one step. - # FIXME: Implement exception handling. - - AddIncludesForTypeInCPPImplementation($attribute->signature->type); - - my %attributes = GenerateCPPAttribute($attribute, $className, $implementationClass, $IDLType); - push(@CPPImplementationContent, values(%attributes)); - } - } - - # - Add functions. - if ($numFunctionsInInterface > 0) { - push(@CPPImplementationContent, "// Functions\n\n"); - - foreach my $function (@{$interfaceToImplement->functions}) { - my $functionImplementation = GenerateCPPFunction($function, $className, $implementationClass); - push(@CPPImplementationContent, $functionImplementation); - } - } - } - - push(@CPPImplementationContent, "// ${interfaceName} $DASHES\n\n"); - - # - Add attribute getters/setters. - if ($numAttributes > 0) { - push(@CPPImplementationContent, "// Attributes\n\n"); - foreach my $attribute (@{$dataNode->attributes}) { - # FIXME: do this in one step - my $hasSetterException = @{$attribute->setterExceptions}; - my $hasGetterException = @{$attribute->getterExceptions}; - - AddIncludesForTypeInCPPImplementation($attribute->signature->type); - - my %attributes = GenerateCPPAttribute($attribute, $className, $implementationClass, $IDLType); - push(@CPPImplementationContent, values(%attributes)); - } - } - - # - Add functions. - if ($numFunctions > 0) { - push(@CPPImplementationContent, "// Functions\n\n"); - - foreach my $function (@{$dataNode->functions}) { - my $functionImplementation = GenerateCPPFunction($function, $className, $implementationClass); - push(@CPPImplementationContent, $functionImplementation); - } - } - - # - Default implementation for interface creator. - # FIXME: add extended attribute to add custom implementation if necessary. - push(@CPPImplementationContent, "${interfaceName}* to${interfaceName}(${implementationClass}* impl)\n"); - push(@CPPImplementationContent, "{\n"); - push(@CPPImplementationContent, " return ${className}::createInstance(impl);\n"); - push(@CPPImplementationContent, "}\n"); -} - -sub WriteData -{ - my ($object, $name, $pureInterface) = @_; - - # -- IDL -- - my $IDLFileName = "$outputDir/I" . $TEMP_PREFIX . "DOM" . $name . ".idl"; - unlink($IDLFileName); - - # Write to output IDL. - open(OUTPUTIDL, ">$IDLFileName") or die "Couldn't open file $IDLFileName"; - - # Add header - print OUTPUTIDL @IDLHeader; - - # Add forward declarations and imorts - delete $IDLForwardDeclarations{keys(%IDLDontForwardDeclare)}; - delete $IDLImports{keys(%IDLDontImport)}; - - print OUTPUTIDL map { "cpp_quote(\"interface $_;\")\n" } sort keys(%IDLForwardDeclarations); - print OUTPUTIDL "\n"; - - print OUTPUTIDL map { "interface $_;\n" } sort keys(%IDLForwardDeclarations); - print OUTPUTIDL "\n"; - print OUTPUTIDL "#ifndef DO_NO_IMPORTS\n"; - print OUTPUTIDL map { ($_ eq "IGEN_DOMImplementation") ? "import \"IGEN_DOMDOMImplementation.idl\";\n" : "import \"$_.idl\";\n" } sort keys(%IDLImports); - print OUTPUTIDL "#endif\n"; - print OUTPUTIDL "\n"; - - # Add content - print OUTPUTIDL @IDLContent; - - close(OUTPUTIDL); - - @IDLHeader = (); - @IDLContent = (); - - if ($pureInterface) { - my $CPPInterfaceHeaderFileName = "$outputDir/" . $TEMP_PREFIX . "DOM" . $name . ".h"; - unlink($CPPInterfaceHeaderFileName); - - open(OUTPUTCPPInterfaceHeader, ">$CPPInterfaceHeaderFileName") or die "Couldn't open file $CPPInterfaceHeaderFileName"; - - print OUTPUTCPPInterfaceHeader @CPPInterfaceHeader; - - close(OUTPUTCPPInterfaceHeader); - - @CPPInterfaceHeader = (); - } else { - my $CPPHeaderFileName = "$outputDir/" . $TEMP_PREFIX . "DOM" . $name . ".h"; - unlink($CPPHeaderFileName); - - # -- CPP Header -- - open(OUTPUTCPPHeader, ">$CPPHeaderFileName") or die "Couldn't open file $CPPHeaderFileName"; - - # Add header - print OUTPUTCPPHeader @CPPHeaderHeader; - - # Add includes - print OUTPUTCPPHeader map { ($_ eq "GEN_DOMImplementation.h") ? "#include \"GEN_DOMDOMImplementation.h\"\n" : "#include \"$_\"\n" } sort keys(%CPPHeaderIncludes); - print OUTPUTCPPHeader map { "#include <$_>\n" } sort keys(%CPPHeaderIncludesAngle); - - foreach my $dontDeclare (keys(%CPPHeaderDontForwardDeclarations)) { - delete $CPPHeaderForwardDeclarations{$dontDeclare} if ($CPPHeaderForwardDeclarations{$dontDeclare}); - } - print OUTPUTCPPHeader "\n"; - print OUTPUTCPPHeader map { "interface $_;\n" } sort keys(%CPPHeaderForwardDeclarations); - print OUTPUTCPPHeader "\n"; - - # Add content - print OUTPUTCPPHeader @CPPHeaderContent; - - close(OUTPUTCPPHeader); - - @CPPHeaderHeader = (); - @CPPHeaderContent = (); - - - # -- CPP Implementation -- - my $CPPImplementationFileName = "$outputDir/" . $TEMP_PREFIX . "DOM" . $name . ".cpp"; - unlink($CPPImplementationFileName); - - open(OUTPUTCPPImplementation, ">$CPPImplementationFileName") or die "Couldn't open file $CPPImplementationFileName"; - - # Add header - print OUTPUTCPPImplementation @CPPImplementationHeader; - print OUTPUTCPPImplementation "\n"; - - # Add includes - foreach my $dontInclude (keys(%CPPImplementationDontIncludes)) { - delete $CPPImplementationIncludes{$dontInclude} if ($CPPImplementationIncludes{$dontInclude}); - } - print OUTPUTCPPImplementation map { ($_ eq "GEN_DOMImplementation.h") ? "#include \"GEN_DOMDOMImplementation.h\"\n" : "#include \"$_\"\n" } sort keys(%CPPImplementationIncludes); - print OUTPUTCPPImplementation map { "#include <$_>\n" } sort keys(%CPPImplementationIncludesAngle); - print OUTPUTCPPImplementation "\n"; - - print OUTPUTCPPImplementation "#pragma warning(push, 0)\n"; - print OUTPUTCPPImplementation map { "#include <WebCore/$_>\n" } sort keys(%CPPImplementationWebCoreIncludes); - print OUTPUTCPPImplementation "#pragma warning(pop)\n"; - - # Add content - print OUTPUTCPPImplementation @CPPImplementationContent; - - close(OUTPUTCPPImplementation); - - @CPPImplementationHeader = (); - @CPPImplementationContent = (); - } -} - -1; diff --git a/WebCore/bindings/scripts/CodeGeneratorJS.pm b/WebCore/bindings/scripts/CodeGeneratorJS.pm index 6ccf739..7a55a3d 100644 --- a/WebCore/bindings/scripts/CodeGeneratorJS.pm +++ b/WebCore/bindings/scripts/CodeGeneratorJS.pm @@ -37,6 +37,8 @@ my @implContentHeader = (); my @implContent = (); my %implIncludes = (); my @depsContent = (); +my $numCachedAttributes = 0; +my $currentCachedAttribute = 0; # Default .h template my $headerTemplate = << "EOF"; @@ -132,15 +134,7 @@ sub GetParentClassName my $dataNode = shift; return $dataNode->extendedAttributes->{"LegacyParent"} if $dataNode->extendedAttributes->{"LegacyParent"}; - if (@{$dataNode->parents} eq 0) { - # FIXME: SVG types requiring a context() pointer do not have enough - # space to hold a globalObject pointer as well w/o hitting the CELL_SIZE limit. - # This could be fixed by moving context() into the various impl() classes. - # Until then, we special case these SVG bindings and allow them to return - # the wrong prototypes and constructors during x-frame access. See bug 27088. - return "DOMObjectWithSVGContext" if IsSVGTypeNeedingContextParameter($dataNode->name); - return "DOMObjectWithGlobalPointer"; - } + return "DOMObjectWithGlobalPointer" if (@{$dataNode->parents} eq 0); return "JS" . $codeGenerator->StripModule($dataNode->parents(0)); } @@ -169,16 +163,6 @@ sub IndexGetterReturnsStrings return 0; } -sub CreateSVGContextInterfaceName -{ - my $type = shift; - - return $type if $codeGenerator->IsSVGAnimatedType($type); - return "SVGPathSeg" if $type =~ /^SVGPathSeg/ and $type ne "SVGPathSegList"; - - return ""; -} - sub AddIncludesForType { my $type = $codeGenerator->StripModule(shift); @@ -491,7 +475,6 @@ sub GenerateHeader my $hasParent = $hasLegacyParent || $hasRealParent; my $parentClassName = GetParentClassName($dataNode); my $conditional = $dataNode->extendedAttributes->{"Conditional"}; - my $needsSVGContext = IsSVGTypeNeedingContextParameter($interfaceName); my $eventTarget = $dataNode->extendedAttributes->{"EventTarget"}; my $needsMarkChildren = $dataNode->extendedAttributes->{"CustomMarkFunction"} || $dataNode->extendedAttributes->{"EventTarget"}; @@ -511,8 +494,7 @@ sub GenerateHeader if ($hasParent) { $headerIncludes{"$parentClassName.h"} = 1; } else { - $headerIncludes{"DOMObjectWithSVGContext.h"} = $needsSVGContext; - $headerIncludes{"JSDOMBinding.h"} = !$needsSVGContext; + $headerIncludes{"JSDOMBinding.h"} = 1; $headerIncludes{"<runtime/JSGlobalObject.h>"} = 1; $headerIncludes{"<runtime/ObjectPrototype.h>"} = 1; } @@ -559,14 +541,12 @@ sub GenerateHeader push(@headerContent, " $className(NonNullPassRefPtr<JSC::Structure>, PassRefPtr<$implType>, JSDOMWindowShell*);\n"); } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) { push(@headerContent, " $className(NonNullPassRefPtr<JSC::Structure>, PassRefPtr<$implType>);\n"); - } elsif (IsSVGTypeNeedingContextParameter($implClassName)) { - push(@headerContent, " $className(NonNullPassRefPtr<JSC::Structure>, JSDOMGlobalObject*, PassRefPtr<$implType>, SVGElement* context);\n"); } else { push(@headerContent, " $className(NonNullPassRefPtr<JSC::Structure>, JSDOMGlobalObject*, PassRefPtr<$implType>);\n"); } # Destructor - push(@headerContent, " virtual ~$className();\n") if (!$hasParent or $eventTarget or $interfaceName eq "Document" or $interfaceName eq "DOMWindow"); + push(@headerContent, " virtual ~$className();\n") if (!$hasParent or $eventTarget or $interfaceName eq "DOMWindow"); # Prototype push(@headerContent, " static JSC::JSObject* createPrototype(JSC::ExecState*, JSC::JSGlobalObject*);\n") unless ($dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"}); @@ -574,7 +554,8 @@ sub GenerateHeader $implIncludes{"${className}Custom.h"} = 1 if $dataNode->extendedAttributes->{"CustomHeader"} || $dataNode->extendedAttributes->{"CustomPutFunction"} || $dataNode->extendedAttributes->{"DelegatingPutFunction"}; my $hasGetter = $numAttributes > 0 - || $dataNode->extendedAttributes->{"GenerateConstructor"} + || !($dataNode->extendedAttributes->{"OmitConstructor"} + || $dataNode->extendedAttributes->{"CustomConstructor"}) || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"} @@ -625,7 +606,7 @@ sub GenerateHeader push(@headerContent, " static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype)\n" . " {\n" . - " return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags));\n" . + " return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount);\n" . " }\n\n"); # markChildren function @@ -645,7 +626,7 @@ sub GenerateHeader # Custom getPropertyNames function exists on DOMWindow if ($interfaceName eq "DOMWindow") { - push(@headerContent, " virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);\n"); + push(@headerContent, " virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n"); $structureFlags{"JSC::OverridesGetPropertyNames"} = 1; } @@ -654,7 +635,7 @@ sub GenerateHeader # Custom getOwnPropertyNames function if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"} || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) { - push(@headerContent, " virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);\n"); + push(@headerContent, " virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n"); $structureFlags{"JSC::OverridesGetPropertyNames"} = 1; } @@ -677,7 +658,7 @@ sub GenerateHeader } # Constructor object getter - push(@headerContent, " static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*);\n") if $dataNode->extendedAttributes->{"GenerateConstructor"}; + push(@headerContent, " static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*);\n") if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})); my $numCustomFunctions = 0; my $numCustomAttributes = 0; @@ -689,9 +670,17 @@ sub GenerateHeader $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"}; $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"CustomGetter"} || $attribute->signature->extendedAttributes->{"JSCCustomGetter"}; $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"CustomSetter"} || $attribute->signature->extendedAttributes->{"JSCCustomSetter"}; + if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) { + push(@headerContent, " static const unsigned " . $attribute->signature->name . "Slot = $numCachedAttributes + Base::AnonymousSlotCount;\n"); + $numCachedAttributes++; + } } } + if ($numCachedAttributes > 0) { + push(@headerContent, " using $parentClassName" . "::putAnonymousValue;\n"); + push(@headerContent, " using $parentClassName" . "::getAnonymousValue;\n"); + } if ($numCustomAttributes > 0) { push(@headerContent, "\n // Custom attributes\n"); @@ -738,6 +727,12 @@ sub GenerateHeader push(@headerContent, " }\n"); } + # anonymous slots + if ($numCachedAttributes) { + push(@headerContent, "public:\n"); + push(@headerContent, " static const unsigned AnonymousSlotCount = $numCachedAttributes + Base::AnonymousSlotCount;\n"); + } + # structure flags push(@headerContent, "protected:\n"); push(@headerContent, " static const unsigned StructureFlags = "); @@ -781,7 +776,7 @@ sub GenerateHeader if (!$hasParent || $dataNode->extendedAttributes->{"GenerateToJS"} || $dataNode->extendedAttributes->{"CustomToJS"}) { if ($podType) { - push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, JSSVGPODTypeWrapper<$podType>*, SVGElement* context);\n"); + push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, JSSVGPODTypeWrapper<$podType>*, SVGElement*);\n"); } elsif (IsSVGTypeNeedingContextParameter($implClassName)) { push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType*, SVGElement* context);\n"); } else { @@ -830,7 +825,7 @@ sub GenerateHeader push(@headerContent, " static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype)\n" . " {\n" . - " return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags));\n" . + " return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount);\n" . " }\n"); if ($dataNode->extendedAttributes->{"DelegatingPrototypePutFunction"}) { push(@headerContent, " virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);\n"); @@ -860,7 +855,7 @@ sub GenerateHeader } } - if ($numAttributes > 0 || $dataNode->extendedAttributes->{"GenerateConstructor"}) { + if ($numAttributes > 0 || !($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { push(@headerContent,"// Attributes\n\n"); foreach my $attribute (@{$dataNode->attributes}) { my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : ""); @@ -871,7 +866,7 @@ sub GenerateHeader } } - if ($dataNode->extendedAttributes->{"GenerateConstructor"}) { + if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { my $getter = "js" . $interfaceName . "Constructor"; push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n"); } @@ -940,7 +935,7 @@ sub GenerateImplementation # - Add all attributes in a hashtable definition my $numAttributes = @{$dataNode->attributes}; - $numAttributes++ if $dataNode->extendedAttributes->{"GenerateConstructor"}; + $numAttributes++ if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})); if ($numAttributes > 0) { my $hashSize = $numAttributes; @@ -981,7 +976,7 @@ sub GenerateImplementation } } - if ($dataNode->extendedAttributes->{"GenerateConstructor"}) { + if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { push(@hashKeys, "constructor"); my $getter = "js" . $interfaceName . "Constructor"; push(@hashValue1, $getter); @@ -999,7 +994,7 @@ sub GenerateImplementation my $numFunctions = @{$dataNode->functions}; # - Add all constants - if ($dataNode->extendedAttributes->{"GenerateConstructor"}) { + if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { $hashSize = $numConstants; $hashName = $className . "ConstructorTable"; @@ -1171,9 +1166,6 @@ sub GenerateImplementation my $podType = $dataNode->extendedAttributes->{"PODType"}; my $implType = $podType ? "JSSVGPODTypeWrapper<$podType> " : $implClassName; - my $needsSVGContext = IsSVGTypeNeedingContextParameter($implClassName); - my $parentNeedsSVGContext = ($needsSVGContext and $parentClassName =~ /SVG/); - # Constructor if ($interfaceName eq "DOMWindow") { AddIncludesForType("JSDOMWindowShell"); @@ -1184,16 +1176,19 @@ sub GenerateImplementation push(@implContent, "${className}::$className(NonNullPassRefPtr<Structure> structure, PassRefPtr<$implType> impl)\n"); push(@implContent, " : $parentClassName(structure, impl)\n"); } else { - my $contextArg = $needsSVGContext ? ", SVGElement* context" : ""; - push(@implContent, "${className}::$className(NonNullPassRefPtr<Structure> structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl$contextArg)\n"); + push(@implContent, "${className}::$className(NonNullPassRefPtr<Structure> structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl)\n"); if ($hasParent) { - push(@implContent, " : $parentClassName(structure, globalObject, impl" . ($parentNeedsSVGContext ? ", context" : "") . ")\n"); + push(@implContent, " : $parentClassName(structure, globalObject, impl)\n"); } else { - push(@implContent, " : $parentClassName(structure, globalObject" . ($needsSVGContext ? ", context" : "") . ")\n"); + push(@implContent, " : $parentClassName(structure, globalObject)\n"); push(@implContent, " , m_impl(impl)\n"); } } push(@implContent, "{\n"); + if ($numCachedAttributes > 0) { + push(@implContent, " for (unsigned i = Base::AnonymousSlotCount; i < AnonymousSlotCount; i++)\n"); + push(@implContent, " putAnonymousValue(i, JSValue());\n"); + } push(@implContent, "}\n\n"); # Destructor @@ -1210,29 +1205,15 @@ sub GenerateImplementation if ($interfaceName eq "Node") { push(@implContent, " forgetDOMNode(this, impl(), impl()->document());\n"); } else { - if ($podType) { - my $animatedType = $implClassName; - $animatedType =~ s/SVG/SVGAnimated/; - - # Special case for JSSVGNumber - if ($codeGenerator->IsSVGAnimatedType($animatedType) and $podType ne "float") { - push(@implContent, " JSSVGDynamicPODTypeWrapperCache<$podType, $animatedType>::forgetWrapper(m_impl.get());\n"); - } - } push(@implContent, " forgetDOMObject(this, impl());\n"); } + + push(@implContent, " JSSVGContextCache::forgetWrapper(this);\n") if IsSVGTypeNeedingContextParameter($implClassName); } push(@implContent, "}\n\n"); } - # Document needs a special destructor because it's a special case for caching. It needs - # its own special handling rather than relying on the caching that Node normally does. - if ($interfaceName eq "Document") { - push(@implContent, "${className}::~$className()\n"); - push(@implContent, "{\n forgetDOMObject(this, static_cast<${implClassName}*>(impl()));\n}\n\n"); - } - if ($needsMarkChildren && !$dataNode->extendedAttributes->{"CustomMarkFunction"}) { push(@implContent, "void ${className}::markChildren(MarkStack& markStack)\n"); push(@implContent, "{\n"); @@ -1253,7 +1234,8 @@ sub GenerateImplementation } my $hasGetter = $numAttributes > 0 - || $dataNode->extendedAttributes->{"GenerateConstructor"} + || !($dataNode->extendedAttributes->{"OmitConstructor"} + || $dataNode->extendedAttributes->{"CustomConstructor"}) || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"} @@ -1352,12 +1334,19 @@ sub GenerateImplementation push(@implContent, " return JS" . $constructorType . "::getConstructor(exec, castedThis);\n"); } elsif (!@{$attribute->getterExceptions}) { push(@implContent, " UNUSED_PARAM(exec);\n"); + my $cacheIndex = 0; + if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) { + $cacheIndex = $currentCachedAttribute; + $currentCachedAttribute++; + push(@implContent, " if (JSValue cachedValue = castedThis->getAnonymousValue(" . $className . "::" . $attribute->signature->name . "Slot))\n"); + push(@implContent, " return cachedValue;\n"); + } if ($podType) { push(@implContent, " $podType imp(*castedThis->impl());\n"); if ($podType eq "float") { # Special case for JSSVGNumber - push(@implContent, " return " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp", "castedThis") . ";\n"); + push(@implContent, " JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp", "castedThis") . ";\n"); } else { - push(@implContent, " return " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$implGetterFunctionName()", "castedThis") . ";\n"); + push(@implContent, " JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$implGetterFunctionName()", "castedThis") . ";\n"); } } else { push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n"); @@ -1376,11 +1365,15 @@ sub GenerateImplementation my $jsType = NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, $value, "castedThis"); if ($codeGenerator->IsSVGAnimatedType($type)) { push(@implContent, " RefPtr<$type> obj = $jsType;\n"); - push(@implContent, " return toJS(exec, castedThis->globalObject(), obj.get(), imp);\n"); + push(@implContent, " JSValue result = toJS(exec, castedThis->globalObject(), obj.get(), imp);\n"); } else { - push(@implContent, " return $jsType;\n"); + push(@implContent, " JSValue result = $jsType;\n"); } } + + push(@implContent, " castedThis->putAnonymousValue(" . $className . "::" . $attribute->signature->name . "Slot, result);\n") if ($attribute->signature->extendedAttributes->{"CachedAttribute"}); + push(@implContent, " return result;\n"); + } else { push(@implContent, " ExceptionCode ec = 0;\n"); if ($podType) { @@ -1404,20 +1397,13 @@ sub GenerateImplementation push(@implContent, "\n"); } - if ($dataNode->extendedAttributes->{"GenerateConstructor"}) { + if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { my $constructorFunctionName = "js" . $interfaceName . "Constructor"; push(@implContent, "JSValue ${constructorFunctionName}(ExecState* exec, const Identifier&, const PropertySlot& slot)\n"); push(@implContent, "{\n"); - if (IsSVGTypeNeedingContextParameter($interfaceName)) { - # FIXME: SVG bindings with a context pointer have no space to store a globalObject - # so we use deprecatedGlobalObjectForPrototype instead. - push(@implContent, " UNUSED_PARAM(slot);\n"); - push(@implContent, " return ${className}::getConstructor(exec, deprecatedGlobalObjectForPrototype(exec));\n"); - } else { - push(@implContent, " ${className}* domObject = static_cast<$className*>(asObject(slot.slotBase()));\n"); - push(@implContent, " return ${className}::getConstructor(exec, domObject->globalObject());\n"); - } + push(@implContent, " ${className}* domObject = static_cast<$className*>(asObject(slot.slotBase()));\n"); + push(@implContent, " return ${className}::getConstructor(exec, domObject->globalObject());\n"); push(@implContent, "}\n"); } } @@ -1491,16 +1477,7 @@ sub GenerateImplementation $implIncludes{"JSEventListener.h"} = 1; push(@implContent, " UNUSED_PARAM(exec);\n"); push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(thisObject)->impl());\n"); - if ($dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"}) { - push(@implContent, " JSDOMGlobalObject* globalObject = static_cast<$className*>(thisObject);\n"); - } else { - $implIncludes{"Frame.h"} = 1; - $implIncludes{"JSDOMGlobalObject.h"} = 1; - push(@implContent, " JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(imp->scriptExecutionContext(), exec);\n"); - push(@implContent, " if (!globalObject)\n"); - push(@implContent, " return;\n"); - } - push(@implContent, " imp->set$implSetterFunctionName(globalObject->createJSAttributeEventListener(value));\n"); + push(@implContent, " imp->set$implSetterFunctionName(createJSAttributeEventListener(exec, value));\n"); } elsif ($attribute->signature->type =~ /Constructor$/) { my $constructorType = $attribute->signature->type; $constructorType =~ s/Constructor$//; @@ -1511,16 +1488,17 @@ sub GenerateImplementation push(@implContent, " // Shadowing a built-in object\n"); push(@implContent, " static_cast<$className*>(thisObject)->putDirect(Identifier(exec, \"$name\"), value);\n"); } else { + push(@implContent, " $className* castedThisObj = static_cast<$className*>(thisObject);\n"); + push(@implContent, " $implType* imp = static_cast<$implType*>(castedThisObj->impl());\n"); if ($podType) { - push(@implContent, " $podType imp(*static_cast<$className*>(thisObject)->impl());\n"); + push(@implContent, " $podType podImp(*imp);\n"); if ($podType eq "float") { # Special case for JSSVGNumber - push(@implContent, " imp = " . JSValueToNative($attribute->signature, "value") . ";\n"); + push(@implContent, " podImp = " . JSValueToNative($attribute->signature, "value") . ";\n"); } else { - push(@implContent, " imp.set$implSetterFunctionName(" . JSValueToNative($attribute->signature, "value") . ");\n"); + push(@implContent, " podImp.set$implSetterFunctionName(" . JSValueToNative($attribute->signature, "value") . ");\n"); } - push(@implContent, " static_cast<$className*>(thisObject)->impl()->commitChange(imp, static_cast<$className*>(thisObject)->context());\n"); + push(@implContent, " imp->commitChange(podImp, castedThisObj);\n"); } else { - push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(thisObject)->impl());\n"); my $nativeValue = JSValueToNative($attribute->signature, "value"); push(@implContent, " ExceptionCode ec = 0;\n") if @{$attribute->setterExceptions}; my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; @@ -1536,10 +1514,8 @@ sub GenerateImplementation push(@implContent, ", ec") if @{$attribute->setterExceptions}; push(@implContent, ");\n"); push(@implContent, " setDOMException(exec, ec);\n") if @{$attribute->setterExceptions}; - if (IsSVGTypeNeedingContextParameter($implClassName)) { - push(@implContent, " if (static_cast<$className*>(thisObject)->context())\n"); - push(@implContent, " static_cast<$className*>(thisObject)->context()->svgAttributeChanged(static_cast<$className*>(thisObject)->impl()->associatedAttributeName());\n"); + push(@implContent, " JSSVGContextCache::propagateSVGDOMChange(castedThisObj, imp->associatedAttributeName());\n"); } } } @@ -1552,17 +1528,17 @@ sub GenerateImplementation } if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) && !$dataNode->extendedAttributes->{"CustomGetPropertyNames"}) { - push(@implContent, "void ${className}::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)\n"); + push(@implContent, "void ${className}::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)\n"); push(@implContent, "{\n"); if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) { push(@implContent, " for (unsigned i = 0; i < static_cast<${implClassName}*>(impl())->length(); ++i)\n"); push(@implContent, " propertyNames.add(Identifier::from(exec, i));\n"); } - push(@implContent, " Base::getOwnPropertyNames(exec, propertyNames);\n"); + push(@implContent, " Base::getOwnPropertyNames(exec, propertyNames, mode);\n"); push(@implContent, "}\n\n"); } - if ($dataNode->extendedAttributes->{"GenerateConstructor"}) { + if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { push(@implContent, "JSValue ${className}::getConstructor(ExecState* exec, JSGlobalObject* globalObject)\n{\n"); push(@implContent, " return getDOMConstructor<${className}Constructor>(exec, static_cast<JSDOMGlobalObject*>(globalObject));\n"); push(@implContent, "}\n\n"); @@ -1602,15 +1578,31 @@ sub GenerateImplementation push(@implContent, " return jsUndefined();\n"); } + # Special case for JSSVGLengthList / JSSVGTransformList / JSSVGPointList / JSSVGNumberList + # Instead of having JSSVG*Custom.cpp implementations for the SVGList interface for all of these + # classes, we directly forward the calls to JSSVGPODListCustom, which centralizes the otherwise + # duplicated code for the JSSVG*List classes mentioned above. + my $svgPODListType; + if ($implClassName =~ /SVG.*List/) { + $svgPODListType = $implClassName; + $svgPODListType =~ s/List$//; + $svgPODListType = "" unless $codeGenerator->IsPodType($svgPODListType); + + # Ignore additional (non-SVGList) SVGTransformList methods, that are not handled through JSSVGPODListCustom + $svgPODListType = "" if $functionImplementationName =~ /createSVGTransformFromMatrix/; + $svgPODListType = "" if $functionImplementationName =~ /consolidate/; + } + if ($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"JSCCustom"}) { push(@implContent, " return castedThisObj->" . $functionImplementationName . "(exec, args);\n"); + } elsif ($svgPODListType) { + $implIncludes{"JS${svgPODListType}.h"} = 1; + $implIncludes{"JSSVGPODListCustom.h"} = 1; + push(@implContent, " return JSSVGPODListCustom::$functionImplementationName<$className, " . GetNativeType($svgPODListType) + . ">(castedThisObj, exec, args, to" . $svgPODListType . ");\n"); } else { - if ($podType) { - push(@implContent, " JSSVGPODTypeWrapper<$podType>* wrapper = castedThisObj->impl();\n"); - push(@implContent, " $podType imp(*wrapper);\n"); - } else { - push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThisObj->impl());\n"); - } + push(@implContent, " $implType* imp = static_cast<$implType*>(castedThisObj->impl());\n"); + push(@implContent, " $podType podImp(*imp);\n") if $podType; my $numParameters = @{$function->parameters}; @@ -1630,7 +1622,7 @@ sub GenerateImplementation } my $paramIndex = 0; - my $functionString = "imp" . ($podType ? "." : "->") . $functionImplementationName . "("; + my $functionString = ($podType ? "podImp." : "imp->") . $functionImplementationName . "("; my $hasOptionalArguments = 0; @@ -1741,11 +1733,10 @@ sub GenerateImplementation if ($podType) { push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, JSSVGPODTypeWrapper<$podType>* object, SVGElement* context)\n"); } elsif (IsSVGTypeNeedingContextParameter($implClassName)) { - push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* object, SVGElement* context)\n"); + push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* object, SVGElement* context)\n"); } else { push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* object)\n"); } - push(@implContent, "{\n"); if ($podType) { push(@implContent, " return getDOMObjectWrapper<$className, JSSVGPODTypeWrapper<$podType> >(exec, globalObject, object, context);\n"); @@ -1803,11 +1794,7 @@ sub GenerateImplementationFunctionCall() if ($function->signature->type eq "void") { push(@implContent, $indent . "$functionString;\n"); push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions}; - - if ($podType) { - push(@implContent, $indent . "wrapper->commitChange(imp, castedThisObj->context());\n"); - } - + push(@implContent, $indent . "imp->commitChange(podImp, castedThisObj);\n") if $podType; push(@implContent, $indent . "return jsUndefined();\n"); } else { push(@implContent, "\n" . $indent . "JSC::JSValue result = " . NativeToJSValue($function->signature, 1, $implClassName, "", $functionString, "castedThisObj") . ";\n"); @@ -1816,7 +1803,7 @@ sub GenerateImplementationFunctionCall() if ($podType and not $function->signature->extendedAttributes->{"Immutable"}) { # Immutable methods do not commit changes back to the instance, thus producing # a new instance rather than mutating existing one. - push(@implContent, $indent . "wrapper->commitChange(imp, castedThisObj->context());\n"); + push(@implContent, $indent . "imp->commitChange(podImp, castedThisObj);\n"); } push(@implContent, $indent . "return result;\n"); @@ -1840,10 +1827,12 @@ my %nativeType = ( "CompareHow" => "Range::CompareHow", "DOMString" => "const UString&", "NodeFilter" => "RefPtr<NodeFilter>", + "SVGAngle" => "SVGAngle", "SVGLength" => "SVGLength", "SVGMatrix" => "TransformationMatrix", "SVGNumber" => "float", "SVGPaintType" => "SVGPaint::SVGPaintType", + "SVGPreserveAspectRatio" => "SVGPreserveAspectRatio", "SVGPoint" => "FloatPoint", "SVGRect" => "FloatRect", "SVGTransform" => "SVGTransform", @@ -1853,6 +1842,8 @@ my %nativeType = ( "long" => "int", "unsigned long" => "unsigned", "unsigned short" => "unsigned short", + "long long" => "long long", + "unsigned long long" => "unsigned long long", ); sub GetNativeType @@ -1876,7 +1867,9 @@ sub JSValueToNative return "$value.toNumber(exec)" if $type eq "double"; return "$value.toFloat(exec)" if $type eq "float" or $type eq "SVGNumber"; return "$value.toInt32(exec)" if $type eq "unsigned long" or $type eq "long" or $type eq "unsigned short"; + return "static_cast<$type>($value.toInteger(exec))" if $type eq "long long" or $type eq "unsigned long long"; + return "valueToDate(exec, $value)" if $type eq "Date"; return "static_cast<Range::CompareHow>($value.toInt32(exec))" if $type eq "CompareHow"; return "static_cast<SVGPaint::SVGPaintType>($value.toInt32(exec))" if $type eq "SVGPaintType"; @@ -1886,7 +1879,7 @@ sub JSValueToNative return "$value.toString(exec)"; } - if ($type eq "SerializedScriptValue") { + if ($type eq "SerializedScriptValue" or $type eq "any") { $implIncludes{"SerializedScriptValue.h"} = 1; return "SerializedScriptValue::create(exec, $value)"; } @@ -1914,7 +1907,11 @@ sub NativeToJSValue my $type = $codeGenerator->StripModule($signature->type); return "jsBoolean($value)" if $type eq "boolean"; - + + # Need to check Date type before IsPrimitiveType(). + if ($type eq "Date") { + return "jsDateOrNull(exec, $value)"; + } if ($codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType" or $type eq "DOMTimeStamp") { $implIncludes{"<runtime/JSNumberCell.h>"} = 1; return "jsNumber(exec, $value)"; @@ -1934,9 +1931,7 @@ sub NativeToJSValue return "jsString(exec, $value)"; } - # Some SVG bindings don't have space to store a globalObject pointer, for those, we use the deprecatedGlobalObjectForPrototype hack for now. - my $globalObject = IsSVGTypeNeedingContextParameter($implClassName) ? "deprecatedGlobalObjectForPrototype(exec)" : "$thisValue->globalObject()"; - + my $globalObject = "$thisValue->globalObject()"; if ($codeGenerator->IsPodType($type)) { $implIncludes{"JS$type.h"} = 1; @@ -1954,25 +1949,16 @@ sub NativeToJSValue and $codeGenerator->IsPodTypeWithWriteableProperties($type) and not defined $signature->extendedAttributes->{"Immutable"}) { if ($codeGenerator->IsPodType($implClassName)) { - return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($value, $thisValue->impl()).get(), $thisValue->context())"; + return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($value, $thisValue->impl()).get(), JSSVGContextCache::svgContextForDOMObject(castedThis))"; } else { return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName>::create(imp, &${implClassName}::$getter, &${implClassName}::$setter).get(), imp)"; } } if ($implClassNameForValueConversion eq "") { - # SVGZoomEvent has no context() pointer, and is also not an SVGElement. - # This is not a problem, because SVGZoomEvent has no read/write properties. - return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), 0)" if $implClassName eq "SVGZoomEvent"; - - if (IsSVGTypeNeedingContextParameter($implClassName)) { - return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), castedThisObj->context())" if $inFunctionCall; - return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), $thisValue->context())"; - } else { - return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), imp)"; - } - } else { # These classes, always have a m_context pointer! - return "toJS(exec, $globalObject, JSSVGDynamicPODTypeWrapperCache<$nativeType, $implClassNameForValueConversion>::lookupOrCreateWrapper(imp, &${implClassNameForValueConversion}::$getter, &${implClassNameForValueConversion}::$setter).get(), $thisValue->context())"; + return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), 0 /* no context on purpose */)"; + } else { + return "toJS(exec, $globalObject, JSSVGDynamicPODTypeWrapperCache<$nativeType, $implClassNameForValueConversion>::lookupOrCreateWrapper(imp, &${implClassNameForValueConversion}::$getter, &${implClassNameForValueConversion}::$setter).get(), JSSVGContextCache::svgContextForDOMObject(castedThis));" } } @@ -1998,9 +1984,9 @@ sub NativeToJSValue $joinedName = $type; $joinedName =~ s/Abs|Rel//; $implIncludes{"$joinedName.h"} = 1; - } elsif ($type eq "SerializedScriptValue") { - $implIncludes{"$type.h"} = 1; - return "$value->deserialize(exec)"; + } elsif ($type eq "SerializedScriptValue" or $type eq "any") { + $implIncludes{"SerializedScriptValue.h"} = 1; + return "$value ? $value->deserialize(exec, castedThis->globalObject()) : jsNull()"; } else { # Default, include header with same name. $implIncludes{"JS$type.h"} = 1; @@ -2010,7 +1996,7 @@ sub NativeToJSValue return $value if $codeGenerator->IsSVGAnimatedType($type); if (IsSVGTypeNeedingContextParameter($type)) { - my $contextPtr = IsSVGTypeNeedingContextParameter($implClassName) ? "$thisValue->context()" : "imp"; + my $contextPtr = IsSVGTypeNeedingContextParameter($implClassName) ? "JSSVGContextCache::svgContextForDOMObject(castedThis)" : "imp"; return "toJS(exec, $globalObject, WTF::getPtr($value), $contextPtr)"; } @@ -2295,7 +2281,7 @@ public: static PassRefPtr<Structure> createStructure(JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, StructureFlags)); + return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); } protected: diff --git a/WebCore/bindings/scripts/CodeGeneratorObjC.pm b/WebCore/bindings/scripts/CodeGeneratorObjC.pm index 91248c5..698b4f5 100644 --- a/WebCore/bindings/scripts/CodeGeneratorObjC.pm +++ b/WebCore/bindings/scripts/CodeGeneratorObjC.pm @@ -66,7 +66,7 @@ my %nativeObjCTypeHash = ("URL" => 1, "Color" => 1); my %baseTypeHash = ("Object" => 1, "Node" => 1, "NodeList" => 1, "NamedNodeMap" => 1, "DOMImplementation" => 1, "Event" => 1, "CSSRule" => 1, "CSSValue" => 1, "StyleSheet" => 1, "MediaList" => 1, "Counter" => 1, "Rect" => 1, "RGBColor" => 1, "XPathExpression" => 1, "XPathResult" => 1, - "NodeIterator" => 1, "TreeWalker" => 1, "AbstractView" => 1, + "NodeIterator" => 1, "TreeWalker" => 1, "AbstractView" => 1, "Blob" => 1, "SVGAngle" => 1, "SVGAnimatedAngle" => 1, "SVGAnimatedBoolean" => 1, "SVGAnimatedEnumeration" => 1, "SVGAnimatedInteger" => 1, "SVGAnimatedLength" => 1, "SVGAnimatedLengthList" => 1, "SVGAnimatedNumber" => 1, "SVGAnimatedNumberList" => 1, "SVGAnimatedPoints" => 1, @@ -316,6 +316,7 @@ sub GetClassName return "BOOL" if $name eq "boolean"; return "unsigned" if $name eq "unsigned long"; return "int" if $name eq "long"; + return "NSTimeInterval" if $name eq "Date"; return "DOMAbstractView" if $name eq "DOMWindow"; return $name if $codeGenerator->IsPrimitiveType($name) or $name eq "DOMImplementation" or $name eq "DOMTimeStamp"; @@ -1040,6 +1041,7 @@ sub GenerateImplementation $implIncludes{$classHeaderName . "Internal.h"} = 1; # FIXME: These includes are only needed when the class is a subclass of one of these polymorphic classes. + $implIncludes{"DOMBlobInternal.h"} = 1; $implIncludes{"DOMCSSRuleInternal.h"} = 1; $implIncludes{"DOMCSSValueInternal.h"} = 1; $implIncludes{"DOMEventInternal.h"} = 1; @@ -1221,7 +1223,7 @@ sub GenerateImplementation $getterContentTail .= ")"; } elsif ($attribute->signature->extendedAttributes->{"ConvertFromString"}) { $getterContentTail .= ".toInt()"; - } elsif ($codeGenerator->IsPodType($idlType)) { + } elsif ($codeGenerator->IsPodType($idlType) or $idlType eq "Date") { $getterContentHead = "kit($getterContentHead"; $getterContentTail .= ")"; } elsif (IsProtocolType($idlType) and $idlType ne "EventTarget") { @@ -1292,6 +1294,10 @@ sub GenerateImplementation push(@implContent, " ASSERT($argName);\n\n"); } + if ($idlType eq "Date") { + $arg = "core(" . $arg . ")"; + } + if ($podType) { # Special case for DOMSVGNumber if ($podType eq "float") { diff --git a/WebCore/bindings/scripts/CodeGeneratorV8.pm b/WebCore/bindings/scripts/CodeGeneratorV8.pm index 77e9512..305fdfd 100644 --- a/WebCore/bindings/scripts/CodeGeneratorV8.pm +++ b/WebCore/bindings/scripts/CodeGeneratorV8.pm @@ -265,15 +265,18 @@ sub GenerateHeader push(@headerContent, "#include <v8.h>\n"); push(@headerContent, "#include <wtf/HashMap.h>\n"); push(@headerContent, "#include \"StringHash.h\"\n"); - - push(@headerContent, "\nnamespace WebCore {\n\n"); - push(@headerContent, "class V8ClassIndex;\n"); + push(@headerContent, "#include \"V8Index.h\"\n"); + push(@headerContent, GetHeaderClassInclude($implClassName)); + push(@headerContent, "\nnamespace WebCore {\n"); push(@headerContent, "\nclass $className {\n"); + + my $toNativeReturnType = GetReturnTypeForToNative($interfaceName); push(@headerContent, <<END); public: static bool HasInstance(v8::Handle<v8::Value> value); static v8::Persistent<v8::FunctionTemplate> GetRawTemplate(); + static ${toNativeReturnType}* toNative(v8::Handle<v8::Object>); END if ($implClassName eq "DOMWindow") { @@ -282,6 +285,59 @@ END END } + my @enabledAtRuntime; + foreach my $function (@{$dataNode->functions}) { + my $name = $function->signature->name; + my $attrExt = $function->signature->extendedAttributes; + + # FIXME: We should only be generating callback declarations for functions labeled [Custom] or [V8Custom], + # but we can't do that due to some mislabeled functions in the idl's (https://bugs.webkit.org/show_bug.cgi?id=33066). + push(@headerContent, <<END); + static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments&); +END + if ($attrExt->{"EnabledAtRuntime"}) { + push(@enabledAtRuntime, $function); + } + } + + if ($dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"CanBeConstructed"}) { + push(@headerContent, <<END); + static v8::Handle<v8::Value> constructorCallback(const v8::Arguments& args); +END + } + + foreach my $attribute (@{$dataNode->attributes}) { + my $name = $attribute->signature->name; + my $attrExt = $attribute->signature->extendedAttributes; + if ($attrExt->{"V8CustomGetter"} || $attrExt->{"CustomGetter"} + || $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) { + push(@headerContent, <<END); + static v8::Handle<v8::Value> ${name}AccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info); +END + } + if ($attrExt->{"V8CustomSetter"} || $attrExt->{"CustomSetter"} + || $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) { + push(@headerContent, <<END); + static void ${name}AccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info); +END + } + if ($attrExt->{"EnabledAtRuntime"}) { + push(@enabledAtRuntime, $attribute); + } + } + + GenerateHeaderRuntimeEnablerDeclarations(@enabledAtRuntime); + GenerateHeaderNamedAndIndexedPropertyAccessors($dataNode); + GenerateHeaderCustomCall($dataNode); + GenerateHeaderCustomInternalFieldIndices($dataNode); + + if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) { + push(@headerContent, <<END); + static bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType, v8::Local<v8::Value> data); + static bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType, v8::Local<v8::Value> data); +END + } + push(@headerContent, <<END); private: @@ -298,6 +354,172 @@ END push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString; } +sub GetInternalFields +{ + my $dataNode = shift; + my $name = $dataNode->name; + + # FIXME: I am hideous and hard-coded. Make me beautiful. + return ("cacheIndex", "implementationIndex") if ($name eq "Document") || ($name eq "SVGDocument"); + return ("cacheIndex", "implementationIndex", "markerIndex", "shadowIndex") if $name eq "HTMLDocument"; + return ("cacheIndex") if IsNodeSubType($dataNode); + return ("cacheIndex") if $name eq "EventSource"; + return ("cacheIndex") if $name eq "XMLHttpRequest"; + return ("cacheIndex") if $name eq "XMLHttpRequestUpload"; + return ("cacheIndex") if $name eq "MessagePort"; + return ("port1Index", "port2Index") if ($name eq "MessageChannel"); + return ("cacheIndex") if $name eq "AbstractWorker"; + return ("abstractWorkerCacheIndex", "cacheIndex") if $name eq "Worker"; + return ("abstractWorkerCacheIndex", "cacheIndex") if $name eq "WorkerContext"; + return ("abstractWorkerCacheIndex", "workerContextCacheIndex", "cacheIndex") if $name eq "DedicatedWorkerContext"; + return ("abstractWorkerCacheIndex", "cacheIndex") if $name eq "SharedWorker"; + return ("abstractWorkerCacheIndex", "workerContextCacheIndex", "cacheIndex") if $name eq "SharedWorkerContext"; + return ("cacheIndex") if $name eq "Notification"; + return ("cacheIndex") if $name eq "IDBRequest"; + return ("cacheIndex") if $name eq "SVGElementInstance"; + return ("consoleIndex", "historyIndex", "locationbarIndex", "menubarIndex", "navigatorIndex", "personalbarIndex", + "screenIndex", "scrollbarsIndex", "selectionIndex", "statusbarIndex", "toolbarIndex", "locationIndex", + "domSelectionIndex", "cacheIndex", "enteredIsolatedWorldIndex") if $name eq "DOMWindow"; + return ("cacheIndex") if $name eq "DOMApplicationCache"; + return ("cacheIndex") if $name eq "WebSocket"; + return ("ownerNodeIndex") if ($name eq "StyleSheet") || ($name eq "CSSStyleSheet"); + return ("ownerNodeIndex") if ($name eq "NamedNodeMap"); + return (); +} + +sub GetHeaderClassInclude +{ + my $className = shift; + if ($className =~ /SVGPathSeg/) { + $className =~ s/Abs|Rel//; + } + return "" if (AvoidInclusionOfType($className)); + return "#include \"SVGAnimatedTemplate.h\"\n" if ($codeGenerator->IsSVGAnimatedType($className)); + return "#include \"${className}.h\"\n"; +} + +sub GenerateHeaderCustomInternalFieldIndices +{ + my $dataNode = shift; + my @customInternalFields = GetInternalFields($dataNode); + my $customFieldCounter = 0; + foreach my $customInternalField (@customInternalFields) { + push(@headerContent, <<END); + static const int ${customInternalField} = v8DefaultWrapperInternalFieldCount + ${customFieldCounter}; +END + $customFieldCounter++; + } + push(@headerContent, <<END); + static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + ${customFieldCounter}; +END +} + +sub GenerateHeaderRuntimeEnablerDeclarations +{ + my @enabledAtRuntime = @_; + + foreach my $runtime_attr (@enabledAtRuntime) { + my $enabledAtRuntimeConditionalString = GenerateConditionalString($runtime_attr->signature); + my $enabler = $codeGenerator->WK_ucfirst($runtime_attr->signature->name); + if ($enabledAtRuntimeConditionalString) { + push(@headerContent, "\n#if ${enabledAtRuntimeConditionalString}\n"); + } + push(@headerContent, <<END); + static bool ${enabler}Enabled(); +END + if ($enabledAtRuntimeConditionalString) { + push(@headerContent, "#endif\n"); + } + } +} + +my %indexerSpecialCases = ( + "Storage" => 1, + "HTMLAppletElement" => 1, + "HTMLDocument" => 1, + "HTMLEmbedElement" => 1, + "HTMLObjectElement" => 1 +); + +sub GenerateHeaderNamedAndIndexedPropertyAccessors +{ + my $dataNode = shift; + my $interfaceName = $dataNode->name; + my $hasCustomIndexedGetter = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}; + my $hasCustomIndexedSetter = $dataNode->extendedAttributes->{"HasCustomIndexSetter"} && !$dataNode->extendedAttributes->{"HasNumericIndexGetter"}; + my $hasCustomNamedGetter = $dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}; + my $hasCustomNamedSetter = $dataNode->extendedAttributes->{"DelegatingPutFunction"}; + my $hasCustomDeleters = $dataNode->extendedAttributes->{"CustomDeleteProperty"}; + my $hasCustomEnumerator = $dataNode->extendedAttributes->{"CustomGetPropertyNames"}; + if ($interfaceName eq "HTMLOptionsCollection") { + $interfaceName = "HTMLCollection"; + $hasCustomIndexedGetter = 1; + $hasCustomNamedGetter = 1; + } + if ($interfaceName eq "DOMWindow") { + $hasCustomDeleterr = 0; + $hasEnumerator = 0; + } + if ($interfaceName eq "HTMLSelectElement") { + $hasCustomNamedGetter = 1; + } + my $isIndexerSpecialCase = exists $indexerSpecialCases{$interfaceName}; + + if ($hasCustomIndexedGetter || $isIndexerSpecialCase) { + push(@headerContent, <<END); + static v8::Handle<v8::Value> indexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info); +END + } + + if ($isIndexerSpecialCase || $hasCustomIndexedSetter) { + push(@headerContent, <<END); + static v8::Handle<v8::Value> indexedPropertySetter(uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info); +END + } + if ($hasCustomDeleters) { + push(@headerContent, <<END); + static v8::Handle<v8::Boolean> indexedPropertyDeleter(uint32_t index, const v8::AccessorInfo& info); +END + } + if ($hasCustomNamedGetter) { + push(@headerContent, <<END); + static v8::Handle<v8::Value> namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info); +END + } + if ($hasCustomNamedSetter) { + push(@headerContent, <<END); + static v8::Handle<v8::Value> namedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info); +END + } + if ($hasCustomDeleters || $interfaceName eq "HTMLDocument") { + push(@headerContent, <<END); + static v8::Handle<v8::Boolean> namedPropertyDeleter(v8::Local<v8::String> name, const v8::AccessorInfo& info); +END + } + if ($hasCustomEnumerator) { + push(@headerContent, <<END); + static v8::Handle<v8::Array> namedPropertyEnumerator(const v8::AccessorInfo& info); +END + } +} + +sub GenerateHeaderCustomCall +{ + my $dataNode = shift; + + if ($dataNode->extendedAttributes->{"CustomCall"}) { + push(@headerContent, " static v8::Handle<v8::Value> callAsFunctionCallback(const v8::Arguments&);\n"); + } + if ($dataNode->name eq "Event") { + push(@headerContent, " static v8::Handle<v8::Value> dataTransferAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n"); + push(@headerContent, " static void valueAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info);\n"); + } + if ($dataNode->name eq "Location") { + push(@headerContent, " static v8::Handle<v8::Value> assignAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n"); + push(@headerContent, " static v8::Handle<v8::Value> reloadAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n"); + push(@headerContent, " static v8::Handle<v8::Value> replaceAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n"); + } +} sub GenerateSetDOMException { @@ -323,48 +545,6 @@ sub IsNodeSubType return 0; } -sub GetHiddenDependencyIndex -{ - my $dataNode = shift; - my $attribute = shift; - my $name = $dataNode->name; - return "V8Custom::kNodeEventListenerCacheIndex" if IsNodeSubType($dataNode); - return "V8Custom::kSVGElementInstanceEventListenerCacheIndex" if $name eq "SVGElementInstance"; - return "V8Custom::kAbstractWorkerRequestCacheIndex" if $name eq "AbstractWorker"; - return "V8Custom::kWorkerRequestCacheIndex" if $name eq "Worker"; - return "V8Custom::kDedicatedWorkerContextRequestCacheIndex" if $name eq "DedicatedWorkerContext"; - return "V8Custom::kWorkerContextRequestCacheIndex" if $name eq "WorkerContext"; - return "V8Custom::kWorkerContextRequestCacheIndex" if $name eq "SharedWorkerContext"; - return "V8Custom::kMessagePortRequestCacheIndex" if $name eq "MessagePort"; - return "V8Custom::kWebSocketCacheIndex" if $name eq "WebSocket"; - return "V8Custom::kXMLHttpRequestCacheIndex" if $name eq "XMLHttpRequest"; - return "V8Custom::kXMLHttpRequestCacheIndex" if $name eq "XMLHttpRequestUpload"; - return "V8Custom::kDOMApplicationCacheCacheIndex" if $name eq "DOMApplicationCache"; - return "V8Custom::kNotificationRequestCacheIndex" if $name eq "Notification"; - return "V8Custom::kDOMWindowEventListenerCacheIndex" if $name eq "DOMWindow"; - die "Unexpected name " . $name . " when generating " . $attribute; -} - -sub HolderToNative -{ - my $dataNode = shift; - my $implClassName = shift; - my $classIndex = shift; - my $holder = shift || "holder"; # optional param - - if (IsNodeSubType($dataNode)) { - push(@implContentDecls, <<END); - $implClassName* imp = v8DOMWrapperToNode<$implClassName>($holder); -END - - } else { - push(@implContentDecls, <<END); - $implClassName* imp = v8DOMWrapperTo<$implClassName>(V8ClassIndex::$classIndex, $holder); -END - - } -} - sub GenerateDomainSafeFunctionGetter { my $function = shift; @@ -382,8 +562,6 @@ sub GenerateDomainSafeFunctionGetter my $newTemplateString = GenerateNewFunctionTemplate($function, $dataNode, $signature); - $implIncludes{"V8Proxy.h"} = 1; - push(@implContentDecls, <<END); static v8::Handle<v8::Value> ${funcName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS(\"DOM.$implClassName.$funcName._get\"); @@ -393,15 +571,10 @@ sub GenerateDomainSafeFunctionGetter if (holder.IsEmpty()) { // can only reach here by 'object.__proto__.func', and it should passed // domain security check already - return private_template->GetFunction(); } -END - - HolderToNative($dataNode, $implClassName, $classIndex); - - push(@implContentDecls, <<END); - if (!V8Proxy::canAccessFrame(imp->frame(), false)) { + ${implClassName}* imp = ${className}::toNative(holder); + if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false)) { static v8::Persistent<v8::FunctionTemplate> shared_template = v8::Persistent<v8::FunctionTemplate>::New($newTemplateString); return shared_template->GetFunction(); @@ -429,17 +602,15 @@ END if ($classIndex eq "DOMWINDOW") { push(@implContentDecls, <<END); - DOMWindow* window = v8DOMWrapperTo<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder()); // Get the proxy corresponding to the DOMWindow if possible to // make sure that the constructor function is constructed in the // context of the DOMWindow and not in the context of the caller. - return V8DOMWrapper::getConstructor(type, window); + return V8DOMWrapper::getConstructor(type, V8DOMWindow::toNative(info.Holder())); END } elsif ($classIndex eq "DEDICATEDWORKERCONTEXT" or $classIndex eq "WORKERCONTEXT" or $classIndex eq "SHAREDWORKERCONTEXT") { $implIncludes{"WorkerContextExecutionProxy.h"} = 1; push(@implContentDecls, <<END); - WorkerContext* workerContext = v8DOMWrapperTo<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder()); - return V8DOMWrapper::getConstructor(type, workerContext); + return V8DOMWrapper::getConstructor(type, V8WorkerContext::toNative(info.Holder())); END } else { push(@implContentDecls, " return v8::Handle<v8::Value>();"); @@ -463,7 +634,6 @@ sub GenerateNormalAttrGetter my $attrExt = $attribute->signature->extendedAttributes; my $attrName = $attribute->signature->name; - $implIncludes{"V8Proxy.h"} = 1; my $attrType = GetTypeFromSignature($attribute->signature); my $attrIsPodType = IsPodType($attrType); @@ -505,7 +675,7 @@ END if ($isPodType) { push(@implContentDecls, <<END); - V8SVGPODTypeWrapper<$implClassName>* imp_wrapper = v8DOMWrapperTo<V8SVGPODTypeWrapper<$implClassName> >(V8ClassIndex::$classIndex, info.Holder()); + V8SVGPODTypeWrapper<$implClassName>* imp_wrapper = V8SVGPODTypeWrapper<$implClassName>::toNative(info.Holder()); $implClassName imp_instance = *imp_wrapper; END if ($getterStringUsesImp) { @@ -526,7 +696,9 @@ END if (holder.IsEmpty()) return v8::Handle<v8::Value>(); END } - HolderToNative($dataNode, $implClassName, $classIndex, "info"); + push(@implContentDecls, <<END); + ${implClassName}* imp = V8${implClassName}::toNative(holder); +END } else { my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; if ($getterStringUsesImp && $reflect && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) { @@ -539,18 +711,16 @@ END return; # Skip the rest of the function! } - push(@implContentDecls, <<END); - v8::Handle<v8::Object> holder = info.Holder(); + ${implClassName}* imp = V8${implClassName}::toNative(info.Holder()); END - HolderToNative($dataNode, $implClassName, $classIndex, "info"); } # Generate security checks if necessary if ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) { - push(@implContentDecls, " if (!V8Proxy::checkNodeSecurity(imp->$attrName())) return v8::Handle<v8::Value>();\n\n"); + push(@implContentDecls, " if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->$attrName())) return v8::Handle<v8::Value>();\n\n"); } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) { - push(@implContentDecls, " if (!V8Proxy::checkNodeSecurity(imp->contentDocument())) return v8::Handle<v8::Value>();\n\n"); + push(@implContentDecls, " if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->contentDocument())) return v8::Handle<v8::Value>();\n\n"); } my $useExceptions = 1 if @{$attribute->getterExceptions} and !($isPodType); @@ -670,8 +840,6 @@ sub GenerateReplaceableAttrSetter { my $implClassName = shift; - $implIncludes{"V8Proxy.h"} = 1; - push(@implContentDecls, " static void ${attrName}AttrSetter(v8::Local<v8::String> name," . " v8::Local<v8::Value> value, const v8::AccessorInfo& info) {\n"); @@ -695,8 +863,6 @@ sub GenerateNormalAttrSetter my $attrExt = $attribute->signature->extendedAttributes; - $implIncludes{"V8Proxy.h"} = 1; - push(@implContentDecls, " static void ${attrName}AttrSetter(v8::Local<v8::String> name," . " v8::Local<v8::Value> value, const v8::AccessorInfo& info) {\n"); @@ -708,7 +874,7 @@ sub GenerateNormalAttrSetter if ($isPodType) { $implClassName = GetNativeType($implClassName); $implIncludes{"V8SVGPODTypeWrapper.h"} = 1; - push(@implContentDecls, " V8SVGPODTypeWrapper<$implClassName>* wrapper = v8DOMWrapperTo<V8SVGPODTypeWrapper<$implClassName> >(V8ClassIndex::$classIndex, info.Holder());\n"); + push(@implContentDecls, " V8SVGPODTypeWrapper<$implClassName>* wrapper = V8SVGPODTypeWrapper<$implClassName>::toNative(info.Holder());\n"); push(@implContentDecls, " $implClassName imp_instance = *wrapper;\n"); push(@implContentDecls, " $implClassName* imp = &imp_instance;\n"); @@ -724,7 +890,9 @@ END if (holder.IsEmpty()) return; END } - HolderToNative($dataNode, $implClassName, $classIndex, "info"); + push(@implContentDecls, <<END); + ${implClassName}* imp = V8${implClassName}::toNative(holder); +END } else { my $attrType = GetTypeFromSignature($attribute->signature); my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; @@ -741,9 +909,8 @@ END } push(@implContentDecls, <<END); - v8::Handle<v8::Object> holder = info.Holder(); + ${implClassName}* imp = V8${implClassName}::toNative(info.Holder()); END - HolderToNative($dataNode, $implClassName, $classIndex, "info"); } my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0); @@ -790,8 +957,7 @@ END } elsif ($attribute->signature->type eq "EventListener") { $implIncludes{"V8AbstractEventListener.h"} = 1; $implIncludes{"V8CustomBinding.h"} = 1; - $cacheIndex = GetHiddenDependencyIndex($dataNode, $attrName); - push(@implContentDecls, " transferHiddenDependency(holder, imp->$attrName(), value, $cacheIndex);\n"); + push(@implContentDecls, " transferHiddenDependency(info.Holder(), imp->$attrName(), value, V8${interfaceName}::cacheIndex);\n"); push(@implContentDecls, " imp->set$implSetterFunctionName(V8DOMWrapper::getEventListener(imp, value, true, ListenerFindOrCreate)"); } else { push(@implContentDecls, " imp->set$implSetterFunctionName($result"); @@ -838,12 +1004,7 @@ sub GetFunctionTemplateCallbackName $function->signature->extendedAttributes->{"V8Custom"}) { die "Custom and V8Custom should be mutually exclusive!" } - my $customFunc = $function->signature->extendedAttributes->{"Custom"} || - $function->signature->extendedAttributes->{"V8Custom"}; - if ($customFunc eq 1) { - $customFunc = $interfaceName . $codeGenerator->WK_ucfirst($name); - } - return "V8Custom::v8${customFunc}Callback"; + return "V8${interfaceName}::${name}Callback"; } else { return "${interfaceName}Internal::${name}Callback"; } @@ -882,14 +1043,13 @@ sub GenerateFunctionCallback if (IsPodType($implClassName)) { my $nativeClassName = GetNativeType($implClassName); - push(@implContentDecls, " V8SVGPODTypeWrapper<$nativeClassName>* imp_wrapper = v8DOMWrapperTo<V8SVGPODTypeWrapper<$nativeClassName> >(V8ClassIndex::$classIndex, args.Holder());\n"); + push(@implContentDecls, " V8SVGPODTypeWrapper<$nativeClassName>* imp_wrapper = V8SVGPODTypeWrapper<$nativeClassName>::toNative(args.Holder());\n"); push(@implContentDecls, " $nativeClassName imp_instance = *imp_wrapper;\n"); push(@implContentDecls, " $nativeClassName* imp = &imp_instance;\n"); } else { push(@implContentDecls, <<END); - v8::Handle<v8::Object> holder = args.Holder(); + ${implClassName}* imp = V8${implClassName}::toNative(args.Holder()); END - HolderToNative($dataNode, $implClassName, $classIndex); } # Check domain security if needed @@ -898,7 +1058,7 @@ END && !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) { # We have not find real use cases yet. push(@implContentDecls, -" if (!V8Proxy::canAccessFrame(imp->frame(), true)) {\n". +" if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) {\n". " return v8::Handle<v8::Value>();\n" . " }\n"); } @@ -930,7 +1090,7 @@ END } if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) { push(@implContentDecls, -" if (!V8Proxy::checkNodeSecurity(imp->getSVGDocument(ec)))\n" . +" if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->getSVGDocument(ec)))\n" . " return v8::Handle<v8::Value>();\n"); } @@ -1040,7 +1200,7 @@ sub GenerateSingleBatchedAttribute ""; if ($customAccessor eq 1) { # use the naming convension, interface + (capitalize) attr name - $customAccessor = $interfaceName . $codeGenerator->WK_ucfirst($attrName); + $customAccessor = $interfaceName . "::" . $attrName; } my $getter; @@ -1065,7 +1225,7 @@ sub GenerateSingleBatchedAttribute $constructorType =~ s/Constructor$//; my $constructorIndex = uc($constructorType); if ($customAccessor) { - $getter = "V8Custom::v8${customAccessor}AccessorGetter"; + $getter = "V8${customAccessor}AccessorGetter"; } else { $data = "V8ClassIndex::${constructorIndex}"; $getter = "${interfaceName}Internal::${interfaceName}ConstructorGetter"; @@ -1081,12 +1241,12 @@ sub GenerateSingleBatchedAttribute # Custom Setter if ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) { $hasCustomSetter = 1; - $setter = "V8Custom::v8${customAccessor}AccessorSetter"; + $setter = "V8${customAccessor}AccessorSetter"; } # Custom Getter - if ($attrExt->{"CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) { - $getter = "V8Custom::v8${customAccessor}AccessorGetter"; + if ($attrExt->{"CustomGetter"} || $attrExt->{"V8CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) { + $getter = "V8${customAccessor}AccessorGetter"; } } @@ -1127,6 +1287,172 @@ sub GenerateSingleBatchedAttribute END } +sub GenerateImplementationIndexer +{ + my $dataNode = shift; + my $indexer = shift; + my $interfaceName = $dataNode->name; + + # FIXME: Figure out what HasNumericIndexGetter is really supposed to do. Right now, it's only set on WebGL-related files. + my $hasCustomSetter = $dataNode->extendedAttributes->{"HasCustomIndexSetter"} && !$dataNode->extendedAttributes->{"HasNumericIndexGetter"}; + my $hasGetter = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}; + + # FIXME: Find a way to not have to special-case HTMLOptionsCollection. + if ($interfaceName eq "HTMLOptionsCollection") { + $hasGetter = 1; + } + # FIXME: If the parent interface of $dataNode already has + # HasIndexGetter, we don't need to handle the getter here. + if ($interfaceName eq "WebKitCSSTransformValue") { + $hasGetter = 0; + } + + # FIXME: Investigate and remove this nastinesss. In V8, named property handling and indexer handling are apparently decoupled, + # which means that object[X] where X is a number doesn't reach named property indexer. So we need to provide + # simplistic, mirrored indexer handling in addition to named property handling. + my $isSpecialCase = exists $indexerSpecialCases{$interfaceName}; + if ($isSpecialCase) { + $hasGetter = 1; + if ($dataNode->extendedAttributes->{"DelegatingPutFunction"}) { + $hasCustomSetter = 1; + } + } + + if (!$hasGetter) { + return; + } + + $implIncludes{"V8Collection.h"} = 1; + + my $indexerType = $indexer ? $indexer->type : 0; + + # FIXME: Remove this once toV8 helper methods are implemented (see https://bugs.webkit.org/show_bug.cgi?id=32563). + if ($interfaceName eq "WebKitCSSKeyframesRule") { + $indexerType = "WebKitCSSKeyframeRule"; + } + + if ($indexerType && !$hasCustomSetter) { + if ($indexerType eq "DOMString") { + my $conversion = $indexer->extendedAttributes->{"ConvertNullStringTo"}; + if ($conversion && $conversion eq "Null") { + push(@implContent, <<END); + setCollectionStringOrNullIndexedGetter<${interfaceName}>(desc); +END + } else { + push(@implContent, <<END); + setCollectionStringIndexedGetter<${interfaceName}>(desc); +END + } + } else { + my $indexerClassIndex = uc($indexerType); + push(@implContent, <<END); + setCollectionIndexedGetter<${interfaceName}, ${indexerType}>(desc, V8ClassIndex::${indexerClassIndex}); +END + } + + return; + } + + my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"}; + my $hasEnumerator = !$isSpecialCase && IsNodeSubType($dataNode); + my $setOn = "Instance"; + + # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow + # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to + # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set + # on the object. + if ($interfaceName eq "DOMWindow") { + $setOn = "Prototype"; + $hasDeleter = 0; + } + + push(@implContent, " desc->${setOn}Template()->SetIndexedPropertyHandler(V8${interfaceName}::indexedPropertyGetter"); + push(@implContent, $hasCustomSetter ? ", V8${interfaceName}::indexedPropertySetter" : ", 0"); + push(@implContent, ", 0"); # IndexedPropertyQuery -- not being used at the moment. + push(@implContent, $hasDeleter ? ", V8${interfaceName}::indexedPropertyDeleter" : ", 0"); + push(@implContent, ", nodeCollectionIndexedPropertyEnumerator<${interfaceName}>, v8::Integer::New(V8ClassIndex::NODE)") if $hasEnumerator; + push(@implContent, ");\n"); +} + +sub GenerateImplementationNamedPropertyGetter +{ + my $dataNode = shift; + my $namedPropertyGetter = shift; + my $interfaceName = $dataNode->name; + my $hasCustomGetter = $dataNode->extendedAttributes->{"HasOverridingNameGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}; + + # FIXME: Remove hard-coded HTMLOptionsCollection reference by changing HTMLOptionsCollection to not inherit + # from HTMLCollection per W3C spec (http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/html.html#HTMLOptionsCollection). + if ($interfaceName eq "HTMLOptionsCollection") { + $interfaceName = "HTMLCollection"; + $hasCustomGetter = 1; + } + + my $hasGetter = $dataNode->extendedAttributes->{"HasNameGetter"} || $hasCustomGetter || $namedPropertyGetter; + if (!$hasGetter) { + return; + } + + if ($namedPropertyGetter && $namedPropertyGetter->type ne "Node" && !$namedPropertyGetter->extendedAttributes->{"Custom"} && !$hasCustomGetter) { + $implIncludes{"V8Collection.h"} = 1; + my $type = $namedPropertyGetter->type; + my $classIndex = uc($type); + push(@implContent, <<END); + setCollectionNamedGetter<${interfaceName}, ${type}>(desc, V8ClassIndex::${classIndex}); +END + return; + } + + my $hasSetter = $dataNode->extendedAttributes->{"DelegatingPutFunction"}; + # FIXME: Try to remove hard-coded HTMLDocument reference by aligning handling of document.all with JSC bindings. + my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"} || $interfaceName eq "HTMLDocument"; + my $hasEnumerator = $dataNode->extendedAttributes->{"CustomGetPropertyNames"}; + my $setOn = "Instance"; + + # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow + # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to + # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set + # on the object. + if ($interfaceName eq "DOMWindow") { + $setOn = "Prototype"; + $hasDeleter = 0; + $hasEnumerator = 0; + } + + push(@implContent, " desc->${setOn}Template()->SetNamedPropertyHandler(V8${interfaceName}::namedPropertyGetter, "); + push(@implContent, $hasSetter ? "V8${interfaceName}::namedPropertySetter, " : "0, "); + push(@implContent, "0, "); # NamedPropertyQuery -- not being used at the moment. + push(@implContent, $hasDeleter ? "V8${interfaceName}::namedPropertyDeleter, " : "0, "); + push(@implContent, $hasEnumerator ? "V8${interfaceName}::namedPropertyEnumerator" : "0"); + push(@implContent, ");\n"); +} + +sub GenerateImplementationCustomCall +{ + my $dataNode = shift; + my $interfaceName = $dataNode->name; + my $hasCustomCall = $dataNode->extendedAttributes->{"CustomCall"}; + + # FIXME: Remove hard-coded HTMLOptionsCollection reference. + if ($interfaceName eq "HTMLOptionsCollection") { + $interfaceName = "HTMLCollection"; + $hasCustomCall = 1; + } + + if ($hasCustomCall) { + push(@implContent, " desc->InstanceTemplate()->SetCallAsFunctionHandler(V8${interfaceName}::callAsFunctionCallback);\n"); + } +} + +sub GenerateImplementationMasqueradesAsUndefined +{ + my $dataNode = shift; + if ($dataNode->extendedAttributes->{"MasqueradesAsUndefined"}) + { + push(@implContent, " desc->InstanceTemplate()->MarkAsUndetectable();\n"); + } +} + sub GenerateImplementation { my $object = shift; @@ -1145,7 +1471,8 @@ sub GenerateImplementation push(@implFixedHeader, "#include \"config.h\"\n" . "#include \"V8Proxy.h\"\n" . - "#include \"V8Binding.h\"\n\n" . + "#include \"V8Binding.h\"\n" . + "#include \"V8BindingState.h\"\n\n" . "#undef LOG\n\n"); push(@implFixedHeader, "\n#if ${conditionalString}\n\n") if $conditionalString; @@ -1157,14 +1484,12 @@ sub GenerateImplementation $implIncludes{"${className}.h"} = 1; AddIncludesForType($interfaceName); - $implIncludes{"V8Proxy.h"} = 1; push(@implContentDecls, "namespace WebCore {\n"); push(@implContentDecls, "namespace ${interfaceName}Internal {\n\n"); push(@implContentDecls, "template <typename T> void V8_USE(T) { }\n\n"); my $hasConstructors = 0; - # Generate property accessors for attributes. for ($index = 0; $index < @{$dataNode->attributes}; $index++) { $attribute = @{$dataNode->attributes}[$index]; @@ -1173,7 +1498,8 @@ sub GenerateImplementation # Generate special code for the constructor attributes. if ($attrType =~ /Constructor$/) { - if ($attribute->signature->extendedAttributes->{"CustomGetter"}) { + if ($attribute->signature->extendedAttributes->{"CustomGetter"} || + $attribute->signature->extendedAttributes->{"V8CustomGetter"}) { $implIncludes{"V8CustomBinding.h"} = 1; } else { $hasConstructors = 1; @@ -1195,7 +1521,8 @@ sub GenerateImplementation } # Generate the accessor. - if ($attribute->signature->extendedAttributes->{"CustomGetter"}) { + if ($attribute->signature->extendedAttributes->{"CustomGetter"} || + $attribute->signature->extendedAttributes->{"V8CustomGetter"}) { $implIncludes{"V8CustomBinding.h"} = 1; } else { GenerateNormalAttrGetter($attribute, $dataNode, $classIndex, $implClassName, $interfaceName); @@ -1214,7 +1541,9 @@ sub GenerateImplementation if ($hasConstructors) { GenerateConstructorGetter($implClassName, $classIndex); } - + + my $indexer; + my $namedPropertyGetter; # Generate methods for functions. foreach my $function (@{$dataNode->functions}) { # hack for addEventListener/RemoveEventListener @@ -1225,6 +1554,14 @@ sub GenerateImplementation GenerateFunctionCallback($function, $dataNode, $classIndex, $implClassName); } + if ($function->signature->name eq "item") { + $indexer = $function->signature; + } + + if ($function->signature->name eq "namedItem") { + $namedPropertyGetter = $function->signature; + } + # If the function does not need domain security check, we need to # generate an access getter that returns different function objects # for different calling context. @@ -1243,6 +1580,7 @@ sub GenerateImplementation my @enabledAtRuntime; my @normal; foreach my $attribute (@$attributes) { + if ($interfaceName eq "DOMWindow" && $attribute->signature->extendedAttributes->{"V8DisallowShadowing"}) { push(@disallowsShadowing, $attribute); } elsif ($attribute->signature->extendedAttributes->{"EnabledAtRuntime"}) { @@ -1321,9 +1659,20 @@ END push(@implContentDecls, "} // namespace ${interfaceName}Internal\n\n"); + # In namespace WebCore, add generated implementation for 'CanBeConstructed'. + if ($dataNode->extendedAttributes->{"CanBeConstructed"} && !$dataNode->extendedAttributes->{"CustomConstructor"}) { + push(@implContent, <<END); + v8::Handle<v8::Value> ${className}::constructorCallback(const v8::Arguments& args) + { + INC_STATS("DOM.${interfaceName}.Contructor"); + return V8Proxy::constructDOMObject<V8ClassIndex::${classIndex}, $interfaceName>(args); + } +END + } + my $access_check = ""; if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !($interfaceName eq "DOMWindow")) { - $access_check = "instance->SetAccessCheckCallbacks(V8Custom::v8${interfaceName}NamedSecurityCheck, V8Custom::v8${interfaceName}IndexedSecurityCheck, v8::Integer::New(V8ClassIndex::ToInt(V8ClassIndex::${classIndex})));"; + $access_check = "instance->SetAccessCheckCallbacks(V8${interfaceName}::namedSecurityCheck, V8${interfaceName}::indexedSecurityCheck, v8::Integer::New(V8ClassIndex::ToInt(V8ClassIndex::${classIndex})));"; } # For the DOMWindow interface, generate the shadow object template @@ -1335,6 +1684,10 @@ static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Pers v8::Handle<v8::ObjectTemplate>(), shadow_attrs, sizeof(shadow_attrs)/sizeof(*shadow_attrs)); + + // Install a security handler with V8. + templ->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::Integer::New(V8ClassIndex::DOMWINDOW)); + templ->SetInternalFieldCount(V8DOMWindow::internalFieldCount); return templ; } END @@ -1349,20 +1702,13 @@ END $parentClassIndex = uc($codeGenerator->StripModule($parent)); last; } - - # find the field count - my $fieldCount = "V8Custom::kDefaultWrapperInternalFieldCount"; - if (IsNodeSubType($dataNode)) { - $fieldCount = "V8Custom::kNodeMinimumInternalFieldCount"; - } # Generate the template configuration method push(@implContent, <<END); static v8::Persistent<v8::FunctionTemplate> Configure${className}Template(v8::Persistent<v8::FunctionTemplate> desc) { v8::Local<v8::Signature> default_signature = configureTemplate(desc, \"${interfaceName}\", - V8ClassIndex::$parentClassIndex, $fieldCount, + V8ClassIndex::$parentClassIndex, V8${interfaceName}::internalFieldCount, END - # Set up our attributes if we have them if ($has_attributes) { push(@implContent, <<END); @@ -1384,6 +1730,12 @@ END END } + if ($dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"CanBeConstructed"}) { + push(@implContent, <<END); + desc->SetCallHandler(V8${interfaceName}::constructorCallback); +END + } + if ($access_check or @enabledAtRuntime or @{$dataNode->functions} or $has_constants) { push(@implContent, <<END); v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate(); @@ -1395,10 +1747,10 @@ END # Setup the enable-at-runtime attrs if we have them foreach my $runtime_attr (@enabledAtRuntime) { - $enable_function = $interfaceName . $codeGenerator->WK_ucfirst($runtime_attr->signature->name); + $enable_function = $interfaceName . "::" . $codeGenerator->WK_ucfirst($runtime_attr->signature->name); my $conditionalString = GenerateConditionalString($runtime_attr->signature); push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString; - push(@implContent, " if (V8Custom::v8${enable_function}Enabled()) {\n"); + push(@implContent, " if (V8${enable_function}Enabled()) {\n"); push(@implContent, " static const BatchedAttribute attrData =\\\n"); GenerateSingleBatchedAttribute($interfaceName, $runtime_attr, ";", " "); push(@implContent, <<END); @@ -1408,6 +1760,11 @@ END push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; } + GenerateImplementationIndexer($dataNode, $indexer); + GenerateImplementationNamedPropertyGetter($dataNode, $namedPropertyGetter); + GenerateImplementationCustomCall($dataNode); + GenerateImplementationMasqueradesAsUndefined($dataNode); + # Define our functions with Set() or SetAccessor() $total_functions = 0; foreach my $function (@{$dataNode->functions}) { @@ -1433,8 +1790,8 @@ END my $conditional = ""; if ($attrExt->{"EnabledAtRuntime"}) { # Only call Set()/SetAccessor() if this method should be enabled - $enable_function = $interfaceName . $codeGenerator->WK_ucfirst($function->signature->name); - $conditional = "if (V8Custom::v8${enable_function}Enabled())\n"; + $enable_function = $interfaceName . "::" . $codeGenerator->WK_ucfirst($function->signature->name); + $conditional = "if (V8${enable_function}Enabled())\n"; } if ($attrExt->{"DoNotCheckDomainSecurity"} && @@ -1494,7 +1851,7 @@ END } push(@implContent, <<END); - ${conditional}createCallback($template, "$name", $callback, ${signature}$property_attributes); + ${conditional}$template->Set(v8::String::New("$name"), v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), ${signature})$property_attributes); END $num_callbacks++; } @@ -1506,8 +1863,36 @@ END batchConfigureConstants(desc, proto, ${interfaceName}_consts, sizeof(${interfaceName}_consts)/sizeof(*${interfaceName}_consts)); END } + + # Special cases + if ($interfaceName eq "DOMWindow") { + push(@implContent, <<END); + + proto->SetInternalFieldCount(V8DOMWindow::internalFieldCount); + desc->SetHiddenPrototype(true); + instance->SetInternalFieldCount(V8DOMWindow::internalFieldCount); + // Set access check callbacks, but turned off initially. + // When a context is detached from a frame, turn on the access check. + // Turning on checks also invalidates inline caches of the object. + instance->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::Integer::New(V8ClassIndex::DOMWINDOW), false); +END + } + if ($interfaceName eq "Location") { + push(@implContent, <<END); + + // For security reasons, these functions are on the instance instead + // of on the prototype object to insure that they cannot be overwritten. + instance->SetAccessor(v8::String::New("reload"), V8Location::reloadAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly)); + instance->SetAccessor(v8::String::New("replace"), V8Location::replaceAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly)); + instance->SetAccessor(v8::String::New("assign"), V8Location::assignAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly)); +END + } + $toNativeReturnType = GetReturnTypeForToNative($interfaceName); push(@implContent, <<END); + + // Custom toString template + desc->Set(getToStringName(), getToStringTemplate()); return desc; } @@ -1521,6 +1906,10 @@ v8::Persistent<v8::FunctionTemplate> ${className}::GetTemplate() { return ${className}_cache_; } +${toNativeReturnType}* ${className}::toNative(v8::Handle<v8::Object> object) { + return reinterpret_cast<${toNativeReturnType}*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex)); +} + bool ${className}::HasInstance(v8::Handle<v8::Value> value) { return GetRawTemplate()->HasInstance(value); } @@ -1547,6 +1936,15 @@ END push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; } +sub GetReturnTypeForToNative +{ + my $type = shift; + return "FloatRect" if $type eq "SVGRect"; + return "FloatPoint" if $type eq "SVGPoint"; + return "TransformationMatrix" if $type eq "SVGMatrix"; + return "float" if $type eq "SVGNumber"; + return $type; +} sub GenerateFunctionCallString() { @@ -1757,101 +2155,20 @@ sub GetNativeTypeFromSignature sub IsRefPtrType { my $type = shift; - return 1 if $type eq "Attr"; - return 1 if $type eq "CanvasBooleanArray"; - return 1 if $type eq "CanvasGradient"; - return 1 if $type eq "CanvasObject"; - return 1 if $type eq "ClientRect"; - return 1 if $type eq "ClientRectList"; - return 1 if $type eq "CDATASection"; - return 1 if $type eq "Comment"; - return 1 if $type eq "CSSRule"; - return 1 if $type eq "CSSStyleRule"; - return 1 if $type eq "CSSCharsetRule"; - return 1 if $type eq "CSSImportRule"; - return 1 if $type eq "CSSMediaRule"; - return 1 if $type eq "CSSFontFaceRule"; - return 1 if $type eq "CSSPageRule"; - return 1 if $type eq "CSSPrimitiveValue"; - return 1 if $type eq "CSSStyleSheet"; - return 1 if $type eq "CSSStyleDeclaration"; - return 1 if $type eq "CSSValue"; - return 1 if $type eq "CSSRuleList"; - return 1 if $type eq "Database"; - return 1 if $type eq "Document"; - return 1 if $type eq "DocumentFragment"; - return 1 if $type eq "DocumentType"; - return 1 if $type eq "Element"; - return 1 if $type eq "EntityReference"; - return 1 if $type eq "Event"; - return 1 if $type eq "EventListener"; - return 1 if $type eq "FileList"; - return 1 if $type eq "HTMLCollection"; - return 1 if $type eq "HTMLAllCollection"; - return 1 if $type eq "HTMLDocument"; - return 1 if $type eq "HTMLElement"; - return 1 if $type eq "HTMLOptionsCollection"; - return 1 if $type eq "ImageData"; - return 1 if $type eq "Media"; - return 1 if $type eq "MediaError"; - return 1 if $type eq "MimeType"; - return 1 if $type eq "Node"; - return 1 if $type eq "NodeList"; - return 1 if $type eq "NodeFilter"; - return 1 if $type eq "NodeIterator"; - return 1 if $type eq "NSResolver"; - return 1 if $type eq "Plugin"; - return 1 if $type eq "ProcessingInstruction"; - return 1 if $type eq "Range"; - return 1 if $type eq "RGBColor"; - return 1 if $type eq "Text"; - return 1 if $type eq "TextMetrics"; - return 1 if $type eq "TimeRanges"; - return 1 if $type eq "TreeWalker"; - return 1 if $type eq "WebGLActiveInfo"; - return 1 if $type eq "WebGLArray"; - return 1 if $type eq "WebGLArrayBuffer"; - return 1 if $type eq "WebGLByteArray"; - return 1 if $type eq "WebGLBuffer"; - return 1 if $type eq "WebGLFloatArray"; - return 1 if $type eq "WebGLFramebuffer"; - return 1 if $type eq "WebGLIntArray"; - return 1 if $type eq "WebGLProgram"; - return 1 if $type eq "WebGLRenderbuffer"; - return 1 if $type eq "WebGLShader"; - return 1 if $type eq "WebGLShortArray"; - return 1 if $type eq "WebGLTexture"; - return 1 if $type eq "WebGLUniformLocation"; - return 1 if $type eq "WebGLUnsignedByteArray"; - return 1 if $type eq "WebGLUnsignedIntArray"; - return 1 if $type eq "WebGLUnsignedShortArray"; - return 1 if $type eq "WebKitCSSMatrix"; - return 1 if $type eq "WebKitPoint"; - return 1 if $type eq "XPathExpression"; - return 1 if $type eq "XPathNSResolver"; - return 1 if $type eq "XPathResult"; - - return 1 if $type eq "SVGAngle"; - return 1 if $type eq "SVGElementInstance"; - return 1 if $type eq "SVGElementInstanceList"; - return 1 if $type =~ /^SVGPathSeg/; - - return 1 if $type =~ /^SVGAnimated/; - - return 0; -} -sub IsVideoClassName -{ - my $class = shift; - return 1 if $class eq "V8HTMLAudioElement"; - return 1 if $class eq "V8HTMLMediaElement"; - return 1 if $class eq "V8HTMLSourceElement"; - return 1 if $class eq "V8HTMLVideoElement"; - return 1 if $class eq "V8MediaError"; - return 1 if $class eq "V8TimeRanges"; - - return 0; + 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; } sub IsWorkerClassName @@ -1879,6 +2196,7 @@ sub GetNativeType 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 "String" if $type eq "DOMString"; @@ -1888,11 +2206,14 @@ sub GetNativeType return "TransformationMatrix" if $type eq "SVGMatrix"; return "SVGTransform" if $type eq "SVGTransform"; return "SVGLength" if $type eq "SVGLength"; + return "SVGAngle" if $type eq "SVGAngle"; return "double" if $type eq "SVGNumber"; + return "SVGPreserveAspectRatio" if $type eq "SVGPreserveAspectRatio"; return "SVGPaint::SVGPaintType" if $type eq "SVGPaintType"; return "DOMTimeStamp" if $type eq "DOMTimeStamp"; return "unsigned" if $type eq "unsigned int"; return "Node*" if $type eq "EventTarget" and $isParameter; + return "double" if $type eq "Date"; return "String" if $type eq "DOMUserData"; # FIXME: Temporary hack? @@ -1914,6 +2235,8 @@ my %typeCanFailConversion = ( "WebGLArray" => 0, "WebGLBuffer" => 0, "WebGLByteArray" => 0, + "WebGLUnsignedByteArray" => 0, + "WebGLContextAttributes" => 0, "WebGLFloatArray" => 0, "WebGLFramebuffer" => 0, "CanvasGradient" => 0, @@ -1946,7 +2269,7 @@ my %typeCanFailConversion = ( "Range" => 0, "SQLResultSet" => 0, "Storage" => 0, - "SVGAngle" => 0, + "SVGAngle" => 1, "SVGElement" => 0, "SVGLength" => 1, "SVGMatrix" => 1, @@ -1954,6 +2277,7 @@ my %typeCanFailConversion = ( "SVGPaintType" => 0, "SVGPathSeg" => 0, "SVGPoint" => 1, + "SVGPreserveAspectRatio" => 1, "SVGRect" => 1, "SVGTransform" => 1, "TouchList" => 0, @@ -1969,6 +2293,8 @@ my %typeCanFailConversion = ( "long" => 0, "unsigned long" => 0, "unsigned short" => 0, + "long long" => 0, + "unsigned long long" => 0 ); @@ -1987,9 +2313,11 @@ sub BasicTypeCanFailConversion my $signature = shift; my $type = GetTypeFromSignature($signature); + return 1 if $type eq "SVGAngle"; return 1 if $type eq "SVGLength"; return 1 if $type eq "SVGMatrix"; return 1 if $type eq "SVGPoint"; + return 1 if $type eq "SVGPreserveAspectRatio"; return 1 if $type eq "SVGRect"; return 1 if $type eq "SVGTransform"; return 0; @@ -2023,8 +2351,10 @@ sub JSValueToNative return "$value->NumberValue()" if $type eq "SVGNumber"; return "toInt32($value${maybeOkParam})" if $type eq "unsigned long" or $type eq "unsigned short" or $type eq "long"; + return "toInt64($value)" if $type eq "unsigned long long" or $type eq "long long"; return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "CompareHow"; return "static_cast<SVGPaint::SVGPaintType>($value->ToInt32()->Int32Value())" if $type eq "SVGPaintType"; + return "toWebCoreDate($value)" if $type eq "Date"; if ($type eq "DOMString" or $type eq "DOMUserData") { return $value; @@ -2048,12 +2378,11 @@ sub JSValueToNative } # Default, assume autogenerated type conversion routines - $implIncludes{"V8Proxy.h"} = 1; if ($type eq "EventTarget") { $implIncludes{"V8Node.h"} = 1; # EventTarget is not in DOM hierarchy, but all Nodes are EventTarget. - return "V8Node::HasInstance($value) ? v8DOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast($value)) : 0"; + return "V8Node::HasInstance($value) ? V8Node::toNative(v8::Handle<v8::Object>::Cast($value)) : 0"; } if ($type eq "XPathNSResolver") { @@ -2061,14 +2390,13 @@ sub JSValueToNative } AddIncludesForType($type); - # $implIncludes{"$type.h"} = 1 unless AvoidInclusionOfType($type); if (IsDOMNodeType($type)) { $implIncludes{"V8${type}.h"} = 1; # Perform type checks on the parameter, if it is expected Node type, # return NULL. - return "V8${type}::HasInstance($value) ? v8DOMWrapperToNode<${type}>(v8::Handle<v8::Object>::Cast($value)) : 0"; + return "V8${type}::HasInstance($value) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0"; } else { # TODO: Temporary to avoid Window name conflict. my $classIndex = uc($type); @@ -2087,7 +2415,7 @@ sub JSValueToNative # Perform type checks on the parameter, if it is expected Node type, # return NULL. - return "V8${type}::HasInstance($value) ? v8DOMWrapperTo<${implClassName}>(V8ClassIndex::${classIndex}, v8::Handle<v8::Object>::Cast($value)) : 0"; + return "V8${type}::HasInstance($value) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0"; } } @@ -2157,10 +2485,14 @@ my %non_wrapper_types = ( 'long' => 1, 'unsigned long' => 1, 'boolean' => 1, + 'long long' => 1, + 'unsigned long long' => 1, 'DOMString' => 1, 'CompareHow' => 1, + 'SVGAngle' => 1, 'SVGRect' => 1, 'SVGPoint' => 1, + 'SVGPreserveAspectRatio' => 1, 'SVGMatrix' => 1, 'SVGTransform' => 1, 'SVGLength' => 1, @@ -2228,6 +2560,7 @@ sub ReturnNativeToJSValue return "return v8::Integer::New($value)" if $nativeType eq "int"; return "return v8::Integer::NewFromUnsigned($value)" if $nativeType eq "unsigned"; + return "return v8DateOrNull($value);" if $type eq "Date"; return "return v8::Number::New($value)" if $codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType"; if ($codeGenerator->IsStringType($type)) { @@ -2245,7 +2578,6 @@ sub ReturnNativeToJSValue # V8 specific. my $implClassName = $type; AddIncludesForType($type); - # $implIncludes{GetImplementationFileName($type)} = 1 unless AvoidInclusionOfType($type); # special case for non-DOM node interfaces if (IsDOMNodeType($type)) { @@ -2270,7 +2602,7 @@ sub ReturnNativeToJSValue if ($type eq "SerializedScriptValue") { $implIncludes{"$type.h"} = 1; - return "return v8String($value->toString())"; + return "return $value->deserialize()"; } if ($type eq "DedicatedWorkerContext" or $type eq "WorkerContext" or $type eq "SharedWorkerContext") { diff --git a/WebCore/bindings/scripts/IDLParser.pm b/WebCore/bindings/scripts/IDLParser.pm index 5affe94..b2577d2 100644 --- a/WebCore/bindings/scripts/IDLParser.pm +++ b/WebCore/bindings/scripts/IDLParser.pm @@ -158,6 +158,7 @@ sub parseExtendedAttributes # Attributes with no value are set to be true $value = 1 unless defined $value; $attrs{$name} = $value; + die("Invalid extended attribute name: '$name'\n") if $name =~ /\s/; } return \%attrs; @@ -370,7 +371,9 @@ sub DetermineParseMode $mode = MODE_INTERFACE; } elsif ($_ =~ /exception/) { $mode = MODE_EXCEPTION; - } elsif ($_ =~ /alias/) { + } elsif ($_ =~ /(\A|\b)alias/) { + # The (\A|\b) above is needed so we don't match attributes + # whose names contain the substring "alias". $mode = MODE_ALIAS; } diff --git a/WebCore/bindings/scripts/generate-bindings.pl b/WebCore/bindings/scripts/generate-bindings.pl index c7adeb3..ad29dc5 100755 --- a/WebCore/bindings/scripts/generate-bindings.pl +++ b/WebCore/bindings/scripts/generate-bindings.pl @@ -56,7 +56,6 @@ my $idlFile = $ARGV[0]; die('Must specify input file.') unless defined($idlFile); die('Must specify IDL search path.') unless @idlDirectories; die('Must specify generator') unless defined($generator); -die('Must specify input file.') unless defined($idlFile); die('Must specify output directory.') unless defined($outputDirectory); die('Must specify defines') unless defined($defines); |