diff options
Diffstat (limited to 'WebCore/bindings/scripts/CodeGeneratorV8.pm')
-rw-r--r-- | WebCore/bindings/scripts/CodeGeneratorV8.pm | 3251 |
1 files changed, 0 insertions, 3251 deletions
diff --git a/WebCore/bindings/scripts/CodeGeneratorV8.pm b/WebCore/bindings/scripts/CodeGeneratorV8.pm deleted file mode 100644 index f50e74a..0000000 --- a/WebCore/bindings/scripts/CodeGeneratorV8.pm +++ /dev/null @@ -1,3251 +0,0 @@ -# Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org> -# Copyright (C) 2006 Anders Carlsson <andersca@mac.com> -# Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> -# Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org> -# Copyright (C) 2006 Apple Computer, Inc. -# Copyright (C) 2007, 2008, 2009 Google Inc. -# Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au> -# Copyright (C) Research In Motion Limited 2010. All rights reserved. -# Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Library General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Library General Public License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; see the file COPYING.LIB. If not, write to -# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. -# - -package CodeGeneratorV8; - -use Digest::MD5; - -my $module = ""; -my $outputDir = ""; -my $outputHeadersDir = ""; - -my @headerContent = (); -my @implContentHeader = (); -my @implFixedHeader = (); -my @implContent = (); -my @implContentDecls = (); -my %implIncludes = (); -my %headerIncludes = (); - -my @allParents = (); - -# Default .h template -my $headerTemplate = << "EOF"; -/* - This file is part of the WebKit open source project. - This file has been generated by generate-bindings.pl. DO NOT MODIFY! - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ -EOF - -# Default constructor -sub new -{ - my $object = shift; - my $reference = { }; - - $codeGenerator = shift; - $outputDir = shift; - $outputHeadersDir = shift; - - bless($reference, $object); - return $reference; -} - -sub finish -{ - my $object = shift; - - # Commit changes! - $object->WriteData(); -} - -# Params: 'domClass' struct -sub GenerateInterface -{ - my $object = shift; - my $dataNode = shift; - my $defines = shift; - - # Start actual generation - if ($dataNode->extendedAttributes->{"Callback"}) { - $object->GenerateCallbackHeader($dataNode); - $object->GenerateCallbackImplementation($dataNode); - } else { - $object->GenerateHeader($dataNode); - $object->GenerateImplementation($dataNode); - } - - my $name = $dataNode->name; - - # Open files for writing - my $headerFileName = "$outputHeadersDir/V8$name.h"; - my $implFileName = "$outputDir/V8$name.cpp"; - - open($IMPL, ">$implFileName") || die "Couldn't open file $implFileName"; - open($HEADER, ">$headerFileName") || die "Couldn't open file $headerFileName"; -} - -# Params: 'idlDocument' struct -sub GenerateModule -{ - my $object = shift; - my $dataNode = shift; - - $module = $dataNode->module; -} - -sub AddIncludesForType -{ - my $type = $codeGenerator->StripModule(shift); - - # When we're finished with the one-file-per-class - # reorganization, we won't need these special cases. - if (!$codeGenerator->IsPrimitiveType($type) and !$codeGenerator->AvoidInclusionOfType($type) and $type ne "Date") { - # default, include the same named file - $implIncludes{GetV8HeaderName(${type})} = 1; - - if ($type =~ /SVGPathSeg/) { - $joinedName = $type; - $joinedName =~ s/Abs|Rel//; - $implIncludes{"${joinedName}.h"} = 1; - } - } - - # additional includes (things needed to compile the bindings but not the header) - - if ($type eq "CanvasRenderingContext2D") { - $implIncludes{"CanvasGradient.h"} = 1; - $implIncludes{"CanvasPattern.h"} = 1; - $implIncludes{"CanvasStyle.h"} = 1; - } - - if ($type eq "CanvasGradient" or $type eq "XPathNSResolver") { - $implIncludes{"PlatformString.h"} = 1; - } - - if ($type eq "CSSStyleDeclaration") { - $implIncludes{"CSSMutableStyleDeclaration.h"} = 1; - } - - if ($type eq "Plugin" or $type eq "PluginArray" or $type eq "MimeTypeArray") { - # So we can get String -> AtomicString conversion for namedItem(). - $implIncludes{"wtf/text/AtomicString.h"} = 1; - } -} - -# If the node has a [Conditional=XXX] attribute, returns an "ENABLE(XXX)" string for use in an #if. -sub GenerateConditionalString -{ - my $node = shift; - my $conditional = $node->extendedAttributes->{"Conditional"}; - if ($conditional) { - if ($conditional =~ /&/) { - return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; - } elsif ($conditional =~ /\|/) { - return "ENABLE(" . join(") || ENABLE(", split(/\|/, $conditional)) . ")"; - } else { - return "ENABLE(" . $conditional . ")"; - } - } else { - return ""; - } -} - -sub GetSVGPropertyTypes -{ - my $implType = shift; - - my $svgPropertyType; - my $svgListPropertyType; - my $svgNativeType; - - return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $implType =~ /SVG/; - - $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implType); - return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $svgNativeType; - - # Append space to avoid compilation errors when using PassRefPtr<$svgNativeType> - $svgNativeType = "$svgNativeType "; - - my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implType); - if ($svgNativeType =~ /SVGPropertyTearOff/) { - $svgPropertyType = $svgWrappedNativeType; - $implIncludes{"SVGAnimatedPropertyTearOff.h"} = 1; - } elsif ($svgNativeType =~ /SVGListPropertyTearOff/ or $svgNativeType =~ /SVGStaticListPropertyTearOff/) { - $svgListPropertyType = $svgWrappedNativeType; - $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1; - $headerIncludes{"SVGStaticListPropertyTearOff.h"} = 1; - } elsif ($svgNativeType =~ /SVGTransformListPropertyTearOff/) { - $svgListPropertyType = $svgWrappedNativeType; - $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1; - $headerIncludes{"SVGTransformListPropertyTearOff.h"} = 1; - } elsif ($svgNativeType =~ /SVGPathSegListPropertyTearOff/) { - $svgListPropertyType = $svgWrappedNativeType; - $headerIncludes{"SVGPathSegListPropertyTearOff.h"} = 1; - } - - if ($svgPropertyType) { - $svgPropertyType = "SVGPoint" if $svgPropertyType eq "FloatPoint"; - } - - return ($svgPropertyType, $svgListPropertyType, $svgNativeType); -} - -sub GenerateHeader -{ - my $object = shift; - my $dataNode = shift; - - my $interfaceName = $dataNode->name; - my $className = "V8$interfaceName"; - my $implClassName = $interfaceName; - - # Copy contents of parent classes except the first parent or if it is - # EventTarget. - $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@allParents, 1); - - my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"}; - - # - Add default header template - push(@headerContent, GenerateHeaderContentHeader($dataNode)); - - $headerIncludes{"wtf/text/StringHash.h"} = 1; - $headerIncludes{"WrapperTypeInfo.h"} = 1; - $headerIncludes{"V8DOMWrapper.h"} = 1; - - my $headerClassInclude = GetHeaderClassInclude($implClassName); - $headerIncludes{$headerClassInclude} = 1 if $headerClassInclude ne ""; - - my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implClassName); - - foreach my $headerInclude (sort keys(%headerIncludes)) { - push(@headerContent, "#include \"${headerInclude}\"\n"); - } - - push(@headerContent, "#include <v8.h>\n"); - push(@headerContent, "#include <wtf/HashMap.h>\n"); - - push(@headerContent, "\nnamespace WebCore {\n"); - push(@headerContent, "\ntemplate<typename PropertyType> class SVGPropertyTearOff;\n") if $svgPropertyType; - if ($svgNativeType) { - if ($svgNativeType =~ /SVGStaticListPropertyTearOff/) { - push(@headerContent, "\ntemplate<typename PropertyType> class SVGStaticListPropertyTearOff;\n"); - } else { - push(@headerContent, "\ntemplate<typename PropertyType> class SVGListPropertyTearOff;\n"); - } - } - push(@headerContent, "\nclass FloatRect;\n") if $svgPropertyType && $svgPropertyType eq "FloatRect"; - push(@headerContent, "\nclass $className {\n"); - - my $nativeType = GetNativeTypeForConversions($dataNode, $interfaceName); - my $domMapFunction = GetDomMapFunction($dataNode, $interfaceName); - my $forceNewObjectParameter = IsDOMNodeType($interfaceName) ? ", bool forceNewObject = false" : ""; - my $forceNewObjectInput = IsDOMNodeType($interfaceName) ? ", bool forceNewObject" : ""; - my $forceNewObjectCall = IsDOMNodeType($interfaceName) ? ", forceNewObject" : ""; - - push(@headerContent, <<END); - -public: - static bool HasInstance(v8::Handle<v8::Value> value); - static v8::Persistent<v8::FunctionTemplate> GetRawTemplate(); - static v8::Persistent<v8::FunctionTemplate> GetTemplate(); - static ${nativeType}* toNative(v8::Handle<v8::Object> object) - { - return reinterpret_cast<${nativeType}*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex)); - } - inline static v8::Handle<v8::Object> wrap(${nativeType}*${forceNewObjectParameter}); - static void derefObject(void*); - static WrapperTypeInfo info; -END - if (IsActiveDomType($implClassName)) { - push(@headerContent, " static ActiveDOMObject* toActiveDOMObject(v8::Handle<v8::Object>);\n"); - } - - if ($implClassName eq "DOMWindow") { - push(@headerContent, <<END); - static v8::Persistent<v8::ObjectTemplate> GetShadowObjectTemplate(); -END - } - - if ($implClassName eq "HTMLDocument") { - push(@headerContent, <<END); - static v8::Local<v8::Object> WrapInShadowObject(v8::Local<v8::Object> wrapper, Node* impl); - static v8::Handle<v8::Value> GetNamedProperty(HTMLDocument* htmlDocument, const AtomicString& key); -END - } - - my @enabledAtRuntime; - foreach my $function (@{$dataNode->functions}) { - my $name = $function->signature->name; - my $attrExt = $function->signature->extendedAttributes; - - if ($attrExt->{"Custom"} || $attrExt->{"V8Custom"}) { - 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->{"V8CustomConstructor"} || $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); - } - } - - 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: - static v8::Handle<v8::Object> wrapSlow(${nativeType}*); -}; - -END - - push(@headerContent, <<END); - -v8::Handle<v8::Object> ${className}::wrap(${nativeType}* impl${forceNewObjectInput}) -{ -END - if ($domMapFunction) { - push(@headerContent, " if (!forceNewObject) {\n") if IsDOMNodeType($interfaceName); - my $getWrapper = IsNodeSubType($dataNode) ? "V8DOMWrapper::getWrapper(impl)" : "${domMapFunction}.get(impl)"; - push(@headerContent, <<END); - v8::Handle<v8::Object> wrapper = ${getWrapper}; - if (!wrapper.IsEmpty()) - return wrapper; -END - push(@headerContent, " }\n") if IsDOMNodeType($interfaceName); - } - push(@headerContent, <<END); - return ${className}::wrapSlow(impl); -} -END - - if (!HasCustomToV8Implementation($dataNode, $interfaceName)) { - push(@headerContent, <<END); - -inline v8::Handle<v8::Value> toV8(${nativeType}* impl${forceNewObjectParameter}) -{ - if (!impl) - return v8::Null(); - return ${className}::wrap(impl${forceNewObjectCall}); -} -END - } elsif ($interfaceName ne 'Node') { - push(@headerContent, <<END); - -v8::Handle<v8::Value> toV8(${nativeType}*${forceNewObjectParameter}); -END - } else { - push(@headerContent, <<END); - -v8::Handle<v8::Value> toV8Slow(Node*, bool); - -inline v8::Handle<v8::Value> toV8(Node* impl, bool forceNewObject = false) -{ - if (!impl) - return v8::Null(); - if (!forceNewObject) { - v8::Handle<v8::Value> wrapper = V8DOMWrapper::getWrapper(impl); - if (!wrapper.IsEmpty()) - return wrapper; - } - return toV8Slow(impl, forceNewObject); -} -END - } - - if (IsRefPtrType($implClassName)) { - push(@headerContent, <<END); -inline v8::Handle<v8::Value> toV8(PassRefPtr< ${nativeType} > impl${forceNewObjectParameter}) -{ - return toV8(impl.get()${forceNewObjectCall}); -} -END - } - - push(@headerContent, "}\n\n"); - push(@headerContent, "#endif // $className" . "_h\n"); - - my $conditionalString = GenerateConditionalString($dataNode); - push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString; -} - -sub GetInternalFields -{ - my $dataNode = shift; - my $name = $dataNode->name; - - my @customInternalFields = (); - - # We can't ask whether a parent type has a given extendedAttribute, so special-case Node, AbstractWorker and WorkerContext to include all sub-types. - # FIXME: SVGElementInstance should probably have the EventTarget extended attribute, but doesn't. - if ($dataNode->extendedAttributes->{"EventTarget"} || IsNodeSubType($dataNode) || IsSubType($dataNode, "AbstractWorker") || IsSubType($dataNode, "WorkerContext") - || $name eq "SVGElementInstance") { - push(@customInternalFields, "eventListenerCacheIndex"); - } - - if (IsSubType($dataNode, "Document")) { - push(@customInternalFields, "implementationIndex"); - } elsif ($name eq "DOMWindow") { - push(@customInternalFields, "enteredIsolatedWorldIndex"); - } - return @customInternalFields; -} - -sub GetHeaderClassInclude -{ - my $className = shift; - if ($className =~ /SVGPathSeg/) { - $className =~ s/Abs|Rel//; - } - return "" if ($codeGenerator->AvoidInclusionOfType($className)); - return "${className}.h"; -} - -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 -} - -my %indexerSpecialCases = ( - "Storage" => 1, - "HTMLAppletElement" => 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 "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") { - $hasCustomNamedGetter = 1; - } - if ($interfaceName eq "HTMLDocument") { - $hasCustomNamedGetter = 0; - $hasCustomIndexedGetter = 0; - } - my $isIndexerSpecialCase = exists $indexerSpecialCases{$interfaceName}; - - if ($hasCustomIndexedGetter || $isIndexerSpecialCase) { - push(@headerContent, <<END); - static v8::Handle<v8::Value> indexedPropertyGetter(uint32_t, const v8::AccessorInfo&); -END - } - - if ($isIndexerSpecialCase || $hasCustomIndexedSetter) { - push(@headerContent, <<END); - static v8::Handle<v8::Value> indexedPropertySetter(uint32_t, v8::Local<v8::Value>, const v8::AccessorInfo&); -END - } - if ($hasCustomDeleters) { - push(@headerContent, <<END); - static v8::Handle<v8::Boolean> indexedPropertyDeleter(uint32_t, const v8::AccessorInfo&); -END - } - if ($hasCustomNamedGetter) { - push(@headerContent, <<END); - static v8::Handle<v8::Value> namedPropertyGetter(v8::Local<v8::String>, const v8::AccessorInfo&); -END - } - if ($hasCustomNamedSetter) { - push(@headerContent, <<END); - static v8::Handle<v8::Value> namedPropertySetter(v8::Local<v8::String>, v8::Local<v8::Value>, const v8::AccessorInfo&); -END - } - if ($hasCustomDeleters) { - push(@headerContent, <<END); - static v8::Handle<v8::Boolean> namedPropertyDeleter(v8::Local<v8::String>, const v8::AccessorInfo&); -END - } - if ($hasCustomEnumerator) { - push(@headerContent, <<END); - static v8::Handle<v8::Array> namedPropertyEnumerator(const v8::AccessorInfo&); - static v8::Handle<v8::Integer> namedPropertyQuery(v8::Local<v8::String>, const v8::AccessorInfo&); -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 -{ - my $indent = shift; - my $result = ""; - - $result .= $indent . "if (UNLIKELY(ec)) {\n"; - $result .= $indent . " V8Proxy::setDOMException(ec);\n"; - $result .= $indent . " return v8::Handle<v8::Value>();\n"; - $result .= $indent . "}\n"; - - return $result; -} - -sub IsSubType -{ - my $dataNode = shift; - my $parentType = shift; - return 1 if ($dataNode->name eq $parentType); - foreach (@allParents) { - my $parent = $codeGenerator->StripModule($_); - return 1 if $parent eq $parentType; - } - return 0; -} - -sub IsNodeSubType -{ - my $dataNode = shift; - return IsSubType($dataNode, "Node"); -} - -sub GenerateDomainSafeFunctionGetter -{ - my $function = shift; - my $implClassName = shift; - - my $className = "V8" . $implClassName; - my $funcName = $function->signature->name; - - my $signature = "v8::Signature::New(" . $className . "::GetRawTemplate())"; - if ($function->signature->extendedAttributes->{"V8DoNotCheckSignature"}) { - $signature = "v8::Local<v8::Signature>()"; - } - - my $newTemplateString = GenerateNewFunctionTemplate($function, $implClassName, $signature); - - 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\"); - static v8::Persistent<v8::FunctionTemplate> privateTemplate = v8::Persistent<v8::FunctionTemplate>::New($newTemplateString); - v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(${className}::GetTemplate(), info.This()); - if (holder.IsEmpty()) { - // can only reach here by 'object.__proto__.func', and it should passed - // domain security check already - return privateTemplate->GetFunction(); - } - ${implClassName}* imp = ${className}::toNative(holder); - if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false)) { - static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New($newTemplateString); - return sharedTemplate->GetFunction(); - } - return privateTemplate->GetFunction(); -} - -END -} - -sub GenerateConstructorGetter -{ - my $implClassName = shift; - - push(@implContentDecls, <<END); -static v8::Handle<v8::Value> ${implClassName}ConstructorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) -{ - INC_STATS(\"DOM.$implClassName.constructors._get\"); - v8::Handle<v8::Value> data = info.Data(); - ASSERT(data->IsExternal() || data->IsNumber()); - WrapperTypeInfo* type = WrapperTypeInfo::unwrap(data); -END - - if ($implClassName eq "DOMWindow") { - push(@implContentDecls, <<END); - // 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, V8DOMWindow::toNative(info.Holder())); -END - } elsif ($implClassName eq "DedicatedWorkerContext" or $implClassName eq "WorkerContext" or $implClassName eq "SharedWorkerContext") { - push(@implContentDecls, <<END); - return V8DOMWrapper::getConstructor(type, V8WorkerContext::toNative(info.Holder())); -END - } else { - push(@implContentDecls, " return v8::Handle<v8::Value>();"); - } - - push(@implContentDecls, <<END); -} - -END -} - -sub GenerateNormalAttrGetter -{ - my $attribute = shift; - my $dataNode = shift; - my $implClassName = shift; - my $interfaceName = shift; - - my $attrExt = $attribute->signature->extendedAttributes; - my $attrName = $attribute->signature->name; - my $attrType = GetTypeFromSignature($attribute->signature); - my $nativeType = GetNativeTypeFromSignature($attribute->signature, -1); - - my $getterStringUsesImp = $implClassName ne "SVGNumber"; - my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implClassName); - - # Getter - my $conditionalString = GenerateConditionalString($attribute->signature); - push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString; - - push(@implContentDecls, <<END); -static v8::Handle<v8::Value> ${attrName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) -{ - INC_STATS(\"DOM.$implClassName.$attrName._get\"); -END - - if ($svgNativeType) { - my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implClassName); - if ($svgWrappedNativeType =~ /List/) { - push(@implContentDecls, <<END); - $svgNativeType* imp = V8${implClassName}::toNative(info.Holder()); -END - } else { - push(@implContentDecls, <<END); - $svgNativeType* wrapper = V8${implClassName}::toNative(info.Holder()); - $svgWrappedNativeType& impInstance = wrapper->propertyReference(); -END - if ($getterStringUsesImp) { - push(@implContentDecls, <<END); - $svgWrappedNativeType* imp = &impInstance; -END - } - } - } elsif ($attrExt->{"v8OnProto"} || $attrExt->{"V8DisallowShadowing"}) { - if ($interfaceName eq "DOMWindow") { - push(@implContentDecls, <<END); - v8::Handle<v8::Object> holder = info.Holder(); -END - } else { - # perform lookup first - push(@implContentDecls, <<END); - v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8${interfaceName}::GetTemplate(), info.This()); - if (holder.IsEmpty()) - return v8::Handle<v8::Value>(); -END - } - push(@implContentDecls, <<END); - ${implClassName}* imp = V8${implClassName}::toNative(holder); -END - } else { - my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; - my $url = $attribute->signature->extendedAttributes->{"URL"}; - if ($getterStringUsesImp && $reflect && !$url && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) { - # Generate super-compact call for regular attribute getter: - my $contentAttributeName = $reflect eq "1" ? lc $attrName : $reflect; - my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName); - $implIncludes{"${namespace}.h"} = 1; - push(@implContentDecls, " return getElementStringAttr(info, ${namespace}::${contentAttributeName}Attr);\n"); - push(@implContentDecls, "}\n\n"); - push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString; - return; - # Skip the rest of the function! - } - push(@implContentDecls, <<END); - ${implClassName}* imp = V8${implClassName}::toNative(info.Holder()); -END - } - - # Generate security checks if necessary - if ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) { - push(@implContentDecls, " if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->$attrName()))\n return v8::Handle<v8::Value>();\n\n"); - } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) { - push(@implContentDecls, " if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->contentDocument()))\n return v8::Handle<v8::Value>();\n\n"); - } - - my $useExceptions = 1 if @{$attribute->getterExceptions}; - if ($useExceptions) { - $implIncludes{"ExceptionCode.h"} = 1; - push(@implContentDecls, " ExceptionCode ec = 0;\n"); - } - - if ($attribute->signature->extendedAttributes->{"v8referenceattr"}) { - $attrName = $attribute->signature->extendedAttributes->{"v8referenceattr"}; - } - - my $returnType = GetTypeFromSignature($attribute->signature); - - my $getterString; - if ($getterStringUsesImp) { - $getterString = "imp->" . $codeGenerator->GetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute); - $getterString .= "ec" if $useExceptions; - $getterString .= ")"; - } else { - $getterString = "impInstance"; - } - - my $result; - my $wrapper; - - if ($attribute->signature->type eq "EventListener" && $dataNode->name eq "DOMWindow") { - push(@implContentDecls, " if (!imp->document())\n"); - push(@implContentDecls, " return v8::Handle<v8::Value>();\n"); - } - - if ($useExceptions) { - if ($nativeType =~ /^V8Parameter/) { - push(@implContentDecls, " " . ConvertToV8Parameter($attribute->signature, $nativeType, "v", $getterString) . ";\n"); - } else { - push(@implContentDecls, " $nativeType v = $getterString;\n"); - } - push(@implContentDecls, GenerateSetDOMException(" ")); - $result = "v"; - $result .= ".release()" if (IsRefPtrType($returnType)); - } else { - # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary - $result = $getterString; - } - - # Special case for readonly or Replaceable attributes (with a few exceptions). This attempts to ensure that JS wrappers don't get - # garbage-collected prematurely when their lifetime is strongly tied to their owner. We accomplish this by inserting a reference to - # the newly created wrapper into an internal field of the holder object. - if (!IsNodeSubType($dataNode) && $attrName ne "self" && (IsWrapperType($returnType) && ($attribute->type =~ /^readonly/ || $attribute->signature->extendedAttributes->{"Replaceable"}) - && $returnType ne "EventTarget" && $returnType ne "SerializedScriptValue" && $returnType ne "DOMWindow" - && $returnType !~ /SVG/ && $returnType !~ /HTML/ && !IsDOMNodeType($returnType))) { - AddIncludesForType($returnType); - my $domMapFunction = GetDomMapFunction(0, $returnType); - # Check for a wrapper in the wrapper cache. If there is one, we know that a hidden reference has already - # been created. If we don't find a wrapper, we create both a wrapper and a hidden reference. - push(@implContentDecls, " RefPtr<$returnType> result = ${getterString};\n"); - push(@implContentDecls, " v8::Handle<v8::Value> wrapper = result.get() ? ${domMapFunction}.get(result.get()) : v8::Handle<v8::Value>();\n"); - push(@implContentDecls, " if (wrapper.IsEmpty()) {\n"); - push(@implContentDecls, " wrapper = toV8(result.get());\n"); - push(@implContentDecls, " if (!wrapper.IsEmpty())\n"); - if ($dataNode->name eq "DOMWindow") { - push(@implContentDecls, " V8DOMWrapper::setHiddenWindowReference(imp->frame(), wrapper);\n"); - } else { - push(@implContentDecls, " V8DOMWrapper::setHiddenReference(info.Holder(), wrapper);\n"); - } - push(@implContentDecls, " }\n"); - push(@implContentDecls, " return wrapper;\n"); - push(@implContentDecls, "}\n\n"); - push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString; - return; - } - - if ($codeGenerator->IsSVGAnimatedType($implClassName) and $codeGenerator->IsSVGTypeNeedingTearOff($attrType)) { - $implIncludes{"V8$attrType.h"} = 1; - my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($attrType); - # Convert from abstract SVGProperty to real type, so the right toJS() method can be invoked. - push(@implContentDecls, " return toV8(static_cast<$svgNativeType*>($result));\n"); - } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($attrType) and not $implClassName =~ /List$/) { - $implIncludes{"V8$attrType.h"} = 1; - $implIncludes{"SVGPropertyTearOff.h"} = 1; - my $tearOffType = $codeGenerator->GetSVGTypeNeedingTearOff($attrType); - if ($codeGenerator->IsSVGTypeWithWritablePropertiesNeedingTearOff($attrType) and not defined $attribute->signature->extendedAttributes->{"Immutable"}) { - my $getter = $result; - $getter =~ s/imp->//; - $getter =~ s/\(\)//; - - my $updateMethod = "&${implClassName}::update" . $codeGenerator->WK_ucfirst($getter); - - my $selfIsTearOffType = $codeGenerator->IsSVGTypeNeedingTearOff($implClassName); - if ($selfIsTearOffType) { - $implIncludes{"SVGStaticPropertyWithParentTearOff.h"} = 1; - $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyWithParentTearOff<$implClassName, /; - - if ($result =~ /matrix/ and $implClassName eq "SVGTransform") { - # SVGTransform offers a matrix() method for internal usage that returns an AffineTransform - # and a svgMatrix() method returning a SVGMatrix, used for the bindings. - $result =~ s/matrix/svgMatrix/; - } - - push(@implContentDecls, " return toV8(WTF::getPtr(${tearOffType}::create(wrapper, $result, $updateMethod)));\n"); - } else { - $implIncludes{"SVGStaticPropertyTearOff.h"} = 1; - $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyTearOff<$implClassName, /; - - push(@implContentDecls, " return toV8(WTF::getPtr(${tearOffType}::create(imp, $result, $updateMethod)));\n"); - } - } elsif ($tearOffType =~ /SVGStaticListPropertyTearOff/) { - my $extraImp = "GetOwnerElementForType<$implClassName, IsDerivedFromSVGElement<$implClassName>::value>::ownerElement(imp), "; - push(@implContentDecls, " return toV8(WTF::getPtr(${tearOffType}::create($extraImp$result)));\n"); - } elsif ($tearOffType =~ /SVG(Point|PathSeg)List/) { - push(@implContentDecls, " return toV8(WTF::getPtr($result));\n"); - } else { - push(@implContentDecls, " return toV8(WTF::getPtr(${tearOffType}::create($result)));\n"); - } - } else { - push(@implContentDecls, " " . ReturnNativeToJSValue($attribute->signature, $result, " ").";\n"); - } - - push(@implContentDecls, "}\n\n"); # end of getter - push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString; -} - -sub GenerateNormalAttrSetter -{ - my $attribute = shift; - my $dataNode = shift; - my $implClassName = shift; - my $interfaceName = shift; - - $implIncludes{"V8BindingMacros.h"} = 1; - - my $attrExt = $attribute->signature->extendedAttributes; - - my $conditionalString = GenerateConditionalString($attribute->signature); - push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString; - - push(@implContentDecls, "static void ${attrName}AttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)\n{\n"); - push(@implContentDecls, " INC_STATS(\"DOM.$implClassName.$attrName._set\");\n"); - - # If the "StrictTypeChecking" extended attribute is present, and the attribute's type is an - # interface type, then if the incoming value does not implement that interface, a TypeError is - # thrown rather than silently passing NULL to the C++ code. - # Per the Web IDL and ECMAScript specifications, incoming values can always be converted to both - # strings and numbers, so do not throw TypeError if the attribute is of these types. - if ($attribute->signature->extendedAttributes->{"StrictTypeChecking"}) { - my $argType = GetTypeFromSignature($attribute->signature); - if (IsWrapperType($argType)) { - push(@implContentDecls, " if (!isUndefinedOrNull(value) && !V8${argType}::HasInstance(value)) {\n"); - push(@implContentDecls, " V8Proxy::throwTypeError();\n"); - push(@implContentDecls, " return;\n"); - push(@implContentDecls, " }\n"); - } - } - - my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implClassName); - if ($svgNativeType) { - my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implClassName); - if ($svgWrappedNativeType =~ /List$/) { - push(@implContentDecls, <<END); - $svgNativeType* imp = V8${implClassName}::toNative(info.Holder()); -END - } else { - push(@implContentDecls, " $svgNativeType* wrapper = V8${implClassName}::toNative(info.Holder());\n"); - push(@implContentDecls, " if (wrapper->role() == AnimValRole) {\n"); - push(@implContentDecls, " V8Proxy::setDOMException(NO_MODIFICATION_ALLOWED_ERR);\n"); - push(@implContentDecls, " return;\n"); - push(@implContentDecls, " }\n"); - push(@implContentDecls, " $svgWrappedNativeType& impInstance = wrapper->propertyReference();\n"); - push(@implContentDecls, " $svgWrappedNativeType* imp = &impInstance;\n"); - } - } elsif ($attrExt->{"v8OnProto"}) { - if ($interfaceName eq "DOMWindow") { - push(@implContentDecls, <<END); - v8::Handle<v8::Object> holder = info.Holder(); -END - } else { - # perform lookup first - push(@implContentDecls, <<END); - v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8${interfaceName}::GetTemplate(), info.This()); - if (holder.IsEmpty()) - return; -END - } - push(@implContentDecls, <<END); - ${implClassName}* imp = V8${implClassName}::toNative(holder); -END - } else { - my $attrType = GetTypeFromSignature($attribute->signature); - my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; - if ($reflect && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) { - # Generate super-compact call for regular attribute setter: - my $contentAttributeName = $reflect eq "1" ? lc $attrName : $reflect; - my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName); - $implIncludes{"${namespace}.h"} = 1; - push(@implContentDecls, " setElementStringAttr(info, ${namespace}::${contentAttributeName}Attr, value);\n"); - push(@implContentDecls, "}\n\n"); - push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString; - return; - # Skip the rest of the function! - } - - push(@implContentDecls, <<END); - ${implClassName}* imp = V8${implClassName}::toNative(info.Holder()); -END - } - - my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0); - if ($attribute->signature->type eq "EventListener") { - if ($dataNode->name eq "DOMWindow") { - push(@implContentDecls, " if (!imp->document())\n"); - push(@implContentDecls, " return;\n"); - } - } else { - my $value = JSValueToNative($attribute->signature, "value"); - if ($nativeType =~ /^V8Parameter/) { - push(@implContentDecls, " " . ConvertToV8Parameter($attribute->signature, $nativeType, "v", $value, "VOID") . "\n"); - } else { - push(@implContentDecls, " $nativeType v = $value;\n"); - } - } - - my $result = "v"; - my $returnType = GetTypeFromSignature($attribute->signature); - if (IsRefPtrType($returnType)) { - $result = "WTF::getPtr(" . $result . ")"; - } - - my $useExceptions = 1 if @{$attribute->setterExceptions}; - - if ($useExceptions) { - $implIncludes{"ExceptionCode.h"} = 1; - push(@implContentDecls, " ExceptionCode ec = 0;\n"); - } - - if ($implClassName eq "SVGNumber") { - push(@implContentDecls, " *imp = $result;\n"); - } else { - if ($attribute->signature->type eq "EventListener") { - my $implSetterFunctionName = $codeGenerator->WK_ucfirst($attrName); - $implIncludes{"V8AbstractEventListener.h"} = 1; - push(@implContentDecls, " transferHiddenDependency(info.Holder(), imp->$attrName(), value, V8${interfaceName}::eventListenerCacheIndex);\n"); - if ($interfaceName eq "WorkerContext" and $attribute->signature->name eq "onerror") { - $implIncludes{"V8EventListenerList.h"} = 1; - $implIncludes{"V8WorkerContextErrorHandler.h"} = 1; - push(@implContentDecls, " imp->set$implSetterFunctionName(V8EventListenerList::findOrCreateWrapper<V8WorkerContextErrorHandler>(value, true)"); - } else { - push(@implContentDecls, " imp->set$implSetterFunctionName(V8DOMWrapper::getEventListener(value, true, ListenerFindOrCreate)"); - } - } else { - my $setterExpressionPrefix = $codeGenerator->SetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute); - push(@implContentDecls, " imp->$setterExpressionPrefix$result"); - } - push(@implContentDecls, ", ec") if $useExceptions; - push(@implContentDecls, ");\n"); - } - - if ($useExceptions) { - push(@implContentDecls, " if (UNLIKELY(ec))\n"); - push(@implContentDecls, " V8Proxy::setDOMException(ec);\n"); - } - - if ($svgNativeType) { - if ($useExceptions) { - push(@implContentDecls, " if (!ec)\n"); - push(@implContentDecls, " wrapper->commitChange();\n"); - } else { - push(@implContentDecls, " wrapper->commitChange();\n"); - } - } - - push(@implContentDecls, " return;\n"); - push(@implContentDecls, "}\n\n"); # end of setter - push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString; -} - -sub GetFunctionTemplateCallbackName -{ - $function = shift; - $interfaceName = shift; - - my $name = $function->signature->name; - - if ($function->signature->extendedAttributes->{"Custom"} || - $function->signature->extendedAttributes->{"V8Custom"}) { - if ($function->signature->extendedAttributes->{"Custom"} && - $function->signature->extendedAttributes->{"V8Custom"}) { - die "Custom and V8Custom should be mutually exclusive!" - } - return "V8${interfaceName}::${name}Callback"; - } else { - return "${interfaceName}Internal::${name}Callback"; - } -} - -sub GenerateNewFunctionTemplate -{ - $function = shift; - $interfaceName = shift; - $signature = shift; - - my $callback = GetFunctionTemplateCallbackName($function, $interfaceName); - return "v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), $signature)"; -} - -sub GenerateEventListenerCallback -{ - my $implClassName = shift; - my $functionName = shift; - my $lookupType = ($functionName eq "add") ? "OrCreate" : "Only"; - my $passRefPtrHandling = ($functionName eq "add") ? "" : ".get()"; - my $hiddenDependencyAction = ($functionName eq "add") ? "create" : "remove"; - - push(@implContentDecls, <<END); -static v8::Handle<v8::Value> ${functionName}EventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.${implClassName}.${functionName}EventListener()"); - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(args[1], false, ListenerFind${lookupType}); - if (listener) { - V8${implClassName}::toNative(args.Holder())->${functionName}EventListener(v8ValueToAtomicWebCoreString(args[0]), listener${passRefPtrHandling}, args[2]->BooleanValue()); - ${hiddenDependencyAction}HiddenDependency(args.Holder(), args[1], V8${implClassName}::eventListenerCacheIndex); - } - return v8::Undefined(); -} - -END -} - -sub GenerateParametersCheckExpression -{ - my $numParameters = shift; - my $function = shift; - - my @andExpression = (); - push(@andExpression, "args.Length() == $numParameters"); - my $parameterIndex = 0; - foreach $parameter (@{$function->parameters}) { - last if $parameterIndex >= $numParameters; - my $value = "args[$parameterIndex]"; - my $type = GetTypeFromSignature($parameter); - - # Only DOMString or wrapper types are checked. - # For DOMString, Null, Undefined and any Object are accepted too, as - # these are acceptable values for a DOMString argument (any Object can - # be converted to a string via .toString). - if ($codeGenerator->IsStringType($type)) { - push(@andExpression, "(${value}->IsNull() || ${value}->IsUndefined() || ${value}->IsString() || ${value}->IsObject())"); - } elsif ($parameter->extendedAttributes->{"Callback"}) { - # For Callbacks only checks if the value is null or object. - push(@andExpression, "(${value}->IsNull() || ${value}->IsObject())"); - } elsif (IsWrapperType($type)) { - push(@andExpression, "(${value}->IsNull() || V8${type}::HasInstance($value))"); - } - - $parameterIndex++; - } - my $res = join(" && ", @andExpression); - $res = "($res)" if @andExpression > 1; - return $res; -} - -sub GenerateFunctionParametersCheck -{ - my $function = shift; - - my @orExpression = (); - my $numParameters = 0; - foreach $parameter (@{$function->parameters}) { - if ($parameter->extendedAttributes->{"Optional"}) { - push(@orExpression, GenerateParametersCheckExpression($numParameters, $function)); - } - $numParameters++; - } - push(@orExpression, GenerateParametersCheckExpression($numParameters, $function)); - return join(" || ", @orExpression); -} - -sub GenerateOverloadedFunctionCallback -{ - my $function = shift; - my $dataNode = shift; - my $implClassName = shift; - - # Generate code for choosing the correct overload to call. Overloads are - # chosen based on the total number of arguments passed and the type of - # values passed in non-primitive argument slots. When more than a single - # overload is applicable, precedence is given according to the order of - # declaration in the IDL. - - my $name = $function->signature->name; - push(@implContentDecls, <<END); -static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args) -{ - INC_STATS(\"DOM.$implClassName.$name\"); -END - - foreach my $overload (@{$function->{overloads}}) { - my $parametersCheck = GenerateFunctionParametersCheck($overload); - push(@implContentDecls, " if ($parametersCheck)\n"); - push(@implContentDecls, " return ${name}$overload->{overloadIndex}Callback(args);\n"); - } - push(@implContentDecls, <<END); - V8Proxy::throwTypeError(); - return notHandledByInterceptor(); -END - push(@implContentDecls, "}\n\n"); -} - -sub GenerateFunctionCallback -{ - my $function = shift; - my $dataNode = shift; - my $implClassName = shift; - - my $interfaceName = $dataNode->name; - my $name = $function->signature->name; - - if (@{$function->{overloads}} > 1) { - # Append a number to an overloaded method's name to make it unique: - $name = $name . $function->{overloadIndex}; - } - - # Adding and removing event listeners are not standard callback behavior, - # but they are extremely consistent across the various classes that take event listeners, - # so we can generate them as a "special case". - if ($name eq "addEventListener") { - GenerateEventListenerCallback($implClassName, "add"); - return; - } elsif ($name eq "removeEventListener") { - GenerateEventListenerCallback($implClassName, "remove"); - return; - } - - push(@implContentDecls, <<END); -static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args) -{ - INC_STATS(\"DOM.$implClassName.$name\"); -END - - my $numParameters = @{$function->parameters}; - - my $requiresAllArguments = $function->signature->extendedAttributes->{"RequiresAllArguments"}; - if ($requiresAllArguments) { - my $numMandatoryParams = @{$function->parameters}; - foreach my $param (reverse(@{$function->parameters})) { - if ($param->extendedAttributes->{"Optional"}) { - $numMandatoryParams--; - } else { - last; - } - } - push(@implContentDecls, " if (args.Length() < $numMandatoryParams)\n"); - if ($requiresAllArguments eq "Raise") { - push(@implContentDecls, " return throwError(\"Not enough arguments\", V8Proxy::SyntaxError);\n"); - } else { - push(@implContentDecls, " return v8::Handle<v8::Value>();\n"); - } - } - - my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implClassName); - - if ($svgNativeType) { - my $nativeClassName = GetNativeType($implClassName); - if ($implClassName =~ /List$/) { - push(@implContentDecls, " $nativeClassName imp = V8${implClassName}::toNative(args.Holder());\n"); - } else { - push(@implContentDecls, " $nativeClassName wrapper = V8${implClassName}::toNative(args.Holder());\n"); - push(@implContentDecls, " if (wrapper->role() == AnimValRole) {\n"); - push(@implContentDecls, " V8Proxy::setDOMException(NO_MODIFICATION_ALLOWED_ERR);\n"); - push(@implContentDecls, " return v8::Handle<v8::Value>();\n"); - push(@implContentDecls, " }\n"); - my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implClassName); - push(@implContentDecls, " $svgWrappedNativeType& impInstance = wrapper->propertyReference();\n"); - push(@implContentDecls, " $svgWrappedNativeType* imp = &impInstance;\n"); - } - } elsif (!$function->signature->extendedAttributes->{"ClassMethod"}) { - push(@implContentDecls, <<END); - ${implClassName}* imp = V8${implClassName}::toNative(args.Holder()); -END - } - - # Check domain security if needed - if (($dataNode->extendedAttributes->{"CheckDomainSecurity"} - || $interfaceName eq "DOMWindow") - && !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) { - # We have not find real use cases yet. - push(@implContentDecls, <<END); - if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) - return v8::Handle<v8::Value>(); -END - } - - my $raisesExceptions = @{$function->raisesExceptions}; - if (!$raisesExceptions) { - foreach my $parameter (@{$function->parameters}) { - if ((!$parameter->extendedAttributes->{"Callback"} and TypeCanFailConversion($parameter)) or $parameter->extendedAttributes->{"IsIndex"}) { - $raisesExceptions = 1; - } - } - } - - if ($raisesExceptions) { - $implIncludes{"ExceptionCode.h"} = 1; - push(@implContentDecls, " ExceptionCode ec = 0;\n"); - push(@implContentDecls, " {\n"); - # The brace here is needed to prevent the ensuing 'goto fail's from jumping past constructors - # of objects (like Strings) declared later, causing compile errors. The block scope ends - # right before the label 'fail:'. - } - - if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) { - push(@implContentDecls, <<END); - RefPtr<ScriptArguments> scriptArguments(createScriptArguments(args, $numParameters)); - size_t maxStackSize = imp->shouldCaptureFullStackTrace() ? ScriptCallStack::maxCallStackSizeToCapture : 1; - RefPtr<ScriptCallStack> callStack(createScriptCallStack(maxStackSize)); - if (!callStack) - return v8::Undefined(); -END - $implIncludes{"ScriptArguments.h"} = 1; - $implIncludes{"ScriptCallStack.h"} = 1; - $implIncludes{"ScriptCallStackFactory.h"} = 1; - } - if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) { - push(@implContentDecls, <<END); - if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->getSVGDocument(ec))) - return v8::Handle<v8::Value>(); -END - } - - my $paramIndex = 0; - foreach my $parameter (@{$function->parameters}) { - TranslateParameter($parameter); - - my $parameterName = $parameter->name; - - # Optional callbacks should be treated differently, because they always have a default value (0), - # and we can reduce the number of overloaded functions that take a different number of parameters. - if ($parameter->extendedAttributes->{"Optional"} && !$parameter->extendedAttributes->{"Callback"}) { - # Generate early call if there are not enough parameters. - push(@implContentDecls, " if (args.Length() <= $paramIndex) {\n"); - my $functionCall = GenerateFunctionCallString($function, $paramIndex, " " x 2, $implClassName); - push(@implContentDecls, $functionCall); - push(@implContentDecls, " }\n"); - } - - $implIncludes{"ExceptionCode.h"} = 1; - my $nativeType = GetNativeTypeFromSignature($parameter, $paramIndex); - if ($parameter->extendedAttributes->{"Callback"}) { - my $className = GetCallbackClassName($parameter->type); - $implIncludes{"$className.h"} = 1; - if ($parameter->extendedAttributes->{"Optional"}) { - push(@implContentDecls, " RefPtr<" . $parameter->type . "> $parameterName;\n"); - push(@implContentDecls, " if (args.Length() > $paramIndex && !args[$paramIndex]->IsNull() && !args[$paramIndex]->IsUndefined()) {\n"); - push(@implContentDecls, " if (!args[$paramIndex]->IsObject())\n"); - push(@implContentDecls, " return throwError(TYPE_MISMATCH_ERR);\n"); - push(@implContentDecls, " $parameterName = ${className}::create(args[$paramIndex], getScriptExecutionContext());\n"); - push(@implContentDecls, " }\n"); - } else { - push(@implContentDecls, " if (args.Length() <= $paramIndex || !args[$paramIndex]->IsObject())\n"); - push(@implContentDecls, " return throwError(TYPE_MISMATCH_ERR);\n"); - push(@implContentDecls, " RefPtr<" . $parameter->type . "> $parameterName = ${className}::create(args[$paramIndex], getScriptExecutionContext());\n"); - } - } elsif ($parameter->type eq "SerializedScriptValue") { - $implIncludes{"SerializedScriptValue.h"} = 1; - push(@implContentDecls, " bool ${parameterName}DidThrow = false;\n"); - push(@implContentDecls, " $nativeType $parameterName = SerializedScriptValue::create(args[$paramIndex], ${parameterName}DidThrow);\n"); - push(@implContentDecls, " if (${parameterName}DidThrow)\n"); - push(@implContentDecls, " return v8::Undefined();\n"); - } elsif (TypeCanFailConversion($parameter)) { - push(@implContentDecls, " $nativeType $parameterName = " . - JSValueToNative($parameter, "args[$paramIndex]") . ";\n"); - push(@implContentDecls, " if (UNLIKELY(!$parameterName)) {\n"); - push(@implContentDecls, " ec = TYPE_MISMATCH_ERR;\n"); - push(@implContentDecls, " goto fail;\n"); - push(@implContentDecls, " }\n"); - } elsif ($nativeType =~ /^V8Parameter/) { - my $value = JSValueToNative($parameter, "args[$paramIndex]"); - push(@implContentDecls, " " . ConvertToV8Parameter($parameter, $nativeType, $parameterName, $value) . "\n"); - } else { - $implIncludes{"V8BindingMacros.h"} = 1; - # If the "StrictTypeChecking" extended attribute is present, and the argument's type is an - # interface type, then if the incoming value does not implement that interface, a TypeError - # is thrown rather than silently passing NULL to the C++ code. - # Per the Web IDL and ECMAScript specifications, incoming values can always be converted - # to both strings and numbers, so do not throw TypeError if the argument is of these - # types. - if ($function->signature->extendedAttributes->{"StrictTypeChecking"}) { - my $argValue = "args[$paramIndex]"; - my $argType = GetTypeFromSignature($parameter); - if (IsWrapperType($argType)) { - push(@implContentDecls, " if (args.Length() > $paramIndex && !isUndefinedOrNull($argValue) && !V8${argType}::HasInstance($argValue)) {\n"); - push(@implContentDecls, " V8Proxy::throwTypeError();\n"); - push(@implContentDecls, " return notHandledByInterceptor();\n"); - push(@implContentDecls, " }\n"); - } - } - push(@implContentDecls, " EXCEPTION_BLOCK($nativeType, $parameterName, " . - JSValueToNative($parameter, "args[$paramIndex]") . ");\n"); - } - - if ($parameter->extendedAttributes->{"IsIndex"}) { - push(@implContentDecls, " if (UNLIKELY($parameterName < 0)) {\n"); - push(@implContentDecls, " ec = INDEX_SIZE_ERR;\n"); - push(@implContentDecls, " goto fail;\n"); - push(@implContentDecls, " }\n"); - } - - $paramIndex++; - } - - # Build the function call string. - my $callString = GenerateFunctionCallString($function, $paramIndex, " ", $implClassName); - push(@implContentDecls, "$callString"); - - if ($raisesExceptions) { - push(@implContentDecls, " }\n"); - push(@implContentDecls, " fail:\n"); - push(@implContentDecls, " V8Proxy::setDOMException(ec);\n"); - push(@implContentDecls, " return v8::Handle<v8::Value>();\n"); - } - - push(@implContentDecls, "}\n\n"); -} - -sub GenerateBatchedAttributeData -{ - my $dataNode = shift; - my $interfaceName = $dataNode->name; - my $attributes = shift; - - foreach my $attribute (@$attributes) { - my $conditionalString = GenerateConditionalString($attribute->signature); - push(@implContent, "#if ${conditionalString}\n") if $conditionalString; - GenerateSingleBatchedAttribute($interfaceName, $attribute, ",", ""); - push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString; - } -} - -sub GenerateSingleBatchedAttribute -{ - my $interfaceName = shift; - my $attribute = shift; - my $delimiter = shift; - my $indent = shift; - my $attrName = $attribute->signature->name; - my $attrExt = $attribute->signature->extendedAttributes; - - # Attributes of type SerializedScriptValue are set in the - # constructor and don't require callbacks. - return if ($attribute->signature->type eq "SerializedScriptValue"); - - my $accessControl = "v8::DEFAULT"; - if ($attrExt->{"DoNotCheckDomainSecurityOnGet"}) { - $accessControl = "v8::ALL_CAN_READ"; - } elsif ($attrExt->{"DoNotCheckDomainSecurityOnSet"}) { - $accessControl = "v8::ALL_CAN_WRITE"; - } elsif ($attrExt->{"DoNotCheckDomainSecurity"}) { - $accessControl = "v8::ALL_CAN_READ"; - if (!($attribute->type =~ /^readonly/) && !($attrExt->{"V8ReadOnly"})) { - $accessControl .= " | v8::ALL_CAN_WRITE"; - } - } - if ($attrExt->{"V8DisallowShadowing"}) { - $accessControl .= " | v8::PROHIBITS_OVERWRITING"; - } - $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")"; - - my $customAccessor = - $attrExt->{"Custom"} || - $attrExt->{"CustomSetter"} || - $attrExt->{"CustomGetter"} || - $attrExt->{"V8Custom"} || - $attrExt->{"V8CustomSetter"} || - $attrExt->{"V8CustomGetter"} || - ""; - if ($customAccessor eq 1) { - # use the naming convension, interface + (capitalize) attr name - $customAccessor = $interfaceName . "::" . $attrName; - } - - my $getter; - my $setter; - my $propAttr = "v8::None"; - my $hasCustomSetter = 0; - - # Check attributes. - if ($attrExt->{"DontEnum"}) { - $propAttr .= " | v8::DontEnum"; - } - if ($attrExt->{"V8DisallowShadowing"}) { - $propAttr .= " | v8::DontDelete"; - } - - my $on_proto = "0 /* on instance */"; - my $data = "0 /* no data */"; - - # Constructor - if ($attribute->signature->type =~ /Constructor$/) { - my $constructorType = $codeGenerator->StripModule($attribute->signature->type); - $constructorType =~ s/Constructor$//; - $implIncludes{"V8${constructorType}.h"} = 1; - if ($customAccessor) { - $getter = "V8${customAccessor}AccessorGetter"; - } else { - $data = "&V8${constructorType}::info"; - $getter = "${interfaceName}Internal::${interfaceName}ConstructorGetter"; - } - $setter = "0"; - $propAttr = "v8::ReadOnly"; - - } else { - # Default Getter and Setter - $getter = "${interfaceName}Internal::${attrName}AttrGetter"; - $setter = "${interfaceName}Internal::${attrName}AttrSetter"; - - # Custom Setter - if ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) { - $hasCustomSetter = 1; - $setter = "V8${customAccessor}AccessorSetter"; - } - - # Custom Getter - if ($attrExt->{"CustomGetter"} || $attrExt->{"V8CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) { - $getter = "V8${customAccessor}AccessorGetter"; - } - } - - # Replaceable - if ($attrExt->{"Replaceable"} && !$hasCustomSetter) { - $setter = "0"; - # Handle the special case of window.top being marked as Replaceable. - # FIXME: Investigate whether we could treat window.top as replaceable - # and allow shadowing without it being a security hole. - if (!($interfaceName eq "DOMWindow" and $attrName eq "top")) { - $propAttr .= " | v8::ReadOnly"; - } - } - - # Read only attributes - if ($attribute->type =~ /^readonly/ || $attrExt->{"V8ReadOnly"}) { - $setter = "0"; - } - - # An accessor can be installed on the proto - if ($attrExt->{"v8OnProto"}) { - $on_proto = "1 /* on proto */"; - } - - my $commentInfo = "Attribute '$attrName' (Type: '" . $attribute->type . - "' ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')"; - - push(@implContent, $indent . " \/\/ $commentInfo\n"); - push(@implContent, $indent . " {\"$attrName\", $getter, $setter, $data, $accessControl, static_cast<v8::PropertyAttribute>($propAttr), $on_proto}" . $delimiter . "\n"); -} - -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: 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"; - } - - # FIXME: The item() getter is not inherited from CSSValueList, seemingly due to the way - # the CodeGenerator->AddMethodsConstantsAndAttributesFromParentClasses() method works, - # so we need to set the indexerType manually in this case. - if ($interfaceName eq "WebKitCSSTransformValue") { - $indexerType = "CSSValue"; - } - - 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 { - push(@implContent, <<END); - setCollectionIndexedGetter<${interfaceName}, ${indexerType}>(desc); -END - # Include the header for this indexer type, because setCollectionIndexedGetter() requires toV8() for this type. - $implIncludes{"V8${indexerType}.h"} = 1; - } - - 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}>") 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; - } - - if ($interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") { - $hasCustomGetter = 1; - } - - if ($interfaceName eq "HTMLDocument") { - $hasCustomGetter = 0; - } - - my $hasGetter = $dataNode->extendedAttributes->{"HasNameGetter"} || $hasCustomGetter; - if (!$hasGetter) { - return; - } - - if ($namedPropertyGetter && $namedPropertyGetter->type ne "Node" && !$namedPropertyGetter->extendedAttributes->{"Custom"} && !$hasCustomGetter) { - $implIncludes{"V8Collection.h"} = 1; - my $type = $namedPropertyGetter->type; - push(@implContent, <<END); - setCollectionNamedGetter<${interfaceName}, ${type}>(desc); -END - return; - } - - my $hasSetter = $dataNode->extendedAttributes->{"DelegatingPutFunction"}; - my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"}; - 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, "); - # If there is a custom enumerator, there MUST be custom query to properly communicate property attributes. - push(@implContent, $hasEnumerator ? "V8${interfaceName}::namedPropertyQuery, " : "0, "); - 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; - my $dataNode = shift; - my $interfaceName = $dataNode->name; - my $visibleInterfaceName = GetVisibleInterfaceName($interfaceName); - my $className = "V8$interfaceName"; - my $implClassName = $interfaceName; - my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"}; - - # - Add default header template - push(@implFixedHeader, GenerateImplementationContentHeader($dataNode)); - - $implIncludes{"RuntimeEnabledFeatures.h"} = 1; - $implIncludes{"V8Proxy.h"} = 1; - $implIncludes{"V8Binding.h"} = 1; - $implIncludes{"V8BindingState.h"} = 1; - $implIncludes{"V8DOMWrapper.h"} = 1; - $implIncludes{"V8IsolatedContext.h"} = 1; - - AddIncludesForType($interfaceName); - - my $toActive = IsActiveDomType($interfaceName) ? "${className}::toActiveDOMObject" : "0"; - - push(@implContentDecls, "namespace WebCore {\n\n"); - push(@implContentDecls, "WrapperTypeInfo ${className}::info = { ${className}::GetTemplate, ${className}::derefObject, ${toActive} };\n\n"); - push(@implContentDecls, "namespace ${interfaceName}Internal {\n\n"); - push(@implContentDecls, "template <typename T> void V8_USE(T) { }\n\n"); - - my $hasConstructors = 0; - my $serializedAttribute; - # Generate property accessors for attributes. - for ($index = 0; $index < @{$dataNode->attributes}; $index++) { - $attribute = @{$dataNode->attributes}[$index]; - $attrName = $attribute->signature->name; - $attrType = $attribute->signature->type; - - # Generate special code for the constructor attributes. - if ($attrType =~ /Constructor$/) { - if (!($attribute->signature->extendedAttributes->{"CustomGetter"} || - $attribute->signature->extendedAttributes->{"V8CustomGetter"})) { - $hasConstructors = 1; - } - next; - } - - if ($attrType eq "EventListener" && $interfaceName eq "DOMWindow") { - $attribute->signature->extendedAttributes->{"v8OnProto"} = 1; - } - - # Attributes of type SerializedScriptValue are set in the - # constructor and don't require callbacks. - if ($attrType eq "SerializedScriptValue") { - die "Only one attribute of type SerializedScriptValue supported" if $serializedAttribute; - $implIncludes{"SerializedScriptValue.h"} = 1; - $serializedAttribute = $attribute; - next; - } - - # Do not generate accessor if this is a custom attribute. The - # call will be forwarded to a hand-written accessor - # implementation. - if ($attribute->signature->extendedAttributes->{"Custom"} || - $attribute->signature->extendedAttributes->{"V8Custom"}) { - next; - } - - # Generate the accessor. - if (!($attribute->signature->extendedAttributes->{"CustomGetter"} || - $attribute->signature->extendedAttributes->{"V8CustomGetter"})) { - GenerateNormalAttrGetter($attribute, $dataNode, $implClassName, $interfaceName); - } - if (!$attribute->signature->extendedAttributes->{"CustomSetter"} && - !$attribute->signature->extendedAttributes->{"V8CustomSetter"} && - !$attribute->signature->extendedAttributes->{"Replaceable"} && - $attribute->type !~ /^readonly/ && - !$attribute->signature->extendedAttributes->{"V8ReadOnly"}) { - GenerateNormalAttrSetter($attribute, $dataNode, $implClassName, $interfaceName); - } - } - - if ($hasConstructors) { - GenerateConstructorGetter($implClassName); - } - - $codeGenerator->LinkOverloadedFunctions($dataNode); - - my $indexer; - my $namedPropertyGetter; - # Generate methods for functions. - foreach my $function (@{$dataNode->functions}) { - if (!($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"V8Custom"})) { - GenerateFunctionCallback($function, $dataNode, $implClassName); - if ($function->{overloadIndex} > 1 && $function->{overloadIndex} == @{$function->{overloads}}) { - GenerateOverloadedFunctionCallback($function, $dataNode, $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. - if (($dataNode->extendedAttributes->{"CheckDomainSecurity"} || ($interfaceName eq "DOMWindow")) && $function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) { - GenerateDomainSafeFunctionGetter($function, $implClassName); - } - } - - # Attributes - my $attributes = $dataNode->attributes; - - # For the DOMWindow interface we partition the attributes into the - # ones that disallows shadowing and the rest. - my @disallowsShadowing; - # Also separate out attributes that are enabled at runtime so we can process them specially. - my @enabledAtRuntime; - my @normal; - foreach my $attribute (@$attributes) { - - if ($interfaceName eq "DOMWindow" && $attribute->signature->extendedAttributes->{"V8DisallowShadowing"}) { - push(@disallowsShadowing, $attribute); - } elsif ($attribute->signature->extendedAttributes->{"EnabledAtRuntime"}) { - push(@enabledAtRuntime, $attribute); - } else { - push(@normal, $attribute); - } - } - $attributes = \@normal; - # Put the attributes that disallow shadowing on the shadow object. - if (@disallowsShadowing) { - push(@implContent, "static const BatchedAttribute shadowAttrs[] = {\n"); - GenerateBatchedAttributeData($dataNode, \@disallowsShadowing); - push(@implContent, "};\n"); - } - - my $has_attributes = 0; - if (@$attributes) { - $has_attributes = 1; - push(@implContent, "static const BatchedAttribute ${interfaceName}Attrs[] = {\n"); - GenerateBatchedAttributeData($dataNode, $attributes); - push(@implContent, "};\n"); - } - - # Setup table of standard callback functions - $num_callbacks = 0; - $has_callbacks = 0; - foreach my $function (@{$dataNode->functions}) { - # Only one table entry is needed for overloaded methods: - next if $function->{overloadIndex} > 1; - - my $attrExt = $function->signature->extendedAttributes; - # Don't put any nonstandard functions into this table: - if ($attrExt->{"V8OnInstance"}) { - next; - } - if ($attrExt->{"ClassMethod"}) { - next; - } - if ($attrExt->{"EnabledAtRuntime"} || RequiresCustomSignature($function) || $attrExt->{"V8DoNotCheckSignature"}) { - next; - } - if ($attrExt->{"DoNotCheckDomainSecurity"} && - ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) { - next; - } - if ($attrExt->{"DontEnum"} || $attrExt->{"V8ReadOnly"}) { - next; - } - if (!$has_callbacks) { - $has_callbacks = 1; - push(@implContent, "static const BatchedCallback ${interfaceName}Callbacks[] = {\n"); - } - my $name = $function->signature->name; - my $callback = GetFunctionTemplateCallbackName($function, $interfaceName); - push(@implContent, <<END); - {"$name", $callback}, -END - $num_callbacks++; - } - push(@implContent, "};\n") if $has_callbacks; - - # Setup constants - my $has_constants = 0; - if (@{$dataNode->constants}) { - $has_constants = 1; - push(@implContent, "static const BatchedConstant ${interfaceName}Consts[] = {\n"); - } - foreach my $constant (@{$dataNode->constants}) { - my $name = $constant->name; - my $value = $constant->value; - # FIXME: we need the static_cast here only because of one constant, NodeFilter.idl - # defines "const unsigned long SHOW_ALL = 0xFFFFFFFF". It would be better if we - # handled this here, and converted it to a -1 constant in the c++ output. - push(@implContent, <<END); - {"${name}", static_cast<signed int>($value)}, -END - } - if ($has_constants) { - push(@implContent, "};\n"); - push(@implContent, $codeGenerator->GenerateCompileTimeCheckForEnumsIfNeeded($dataNode)); - } - - push(@implContentDecls, "} // namespace ${interfaceName}Internal\n\n"); - - # In namespace WebCore, add generated implementation for 'CanBeConstructed'. - if ($dataNode->extendedAttributes->{"CanBeConstructed"} && !$dataNode->extendedAttributes->{"CustomConstructor"} && !$dataNode->extendedAttributes->{"V8CustomConstructor"}) { - my $v8ConstructFunction; - my $callWith = $dataNode->extendedAttributes->{"CallWith"}; - if ($callWith and $callWith eq "ScriptExecutionContext") { - $v8ConstructFunction = "constructDOMObjectWithScriptExecutionContext"; - } else { - $v8ConstructFunction = "constructDOMObject"; - } - push(@implContent, <<END); -v8::Handle<v8::Value> ${className}::constructorCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.${interfaceName}.Contructor"); - return V8Proxy::${v8ConstructFunction}<$interfaceName>(args, &info); -} -END - } - - my $access_check = ""; - if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !($interfaceName eq "DOMWindow")) { - $access_check = "instance->SetAccessCheckCallbacks(V8${interfaceName}::namedSecurityCheck, V8${interfaceName}::indexedSecurityCheck, v8::External::Wrap(&V8${interfaceName}::info));"; - } - - # For the DOMWindow interface, generate the shadow object template - # configuration method. - if ($implClassName eq "DOMWindow") { - push(@implContent, <<END); -static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Persistent<v8::ObjectTemplate> templ) -{ - batchConfigureAttributes(templ, v8::Handle<v8::ObjectTemplate>(), shadowAttrs, WTF_ARRAY_LENGTH(shadowAttrs)); - - // Install a security handler with V8. - templ->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::External::Wrap(&V8DOMWindow::info)); - templ->SetInternalFieldCount(V8DOMWindow::internalFieldCount); - return templ; -} -END - } - - # find the super descriptor - my $parentClassTemplate = ""; - foreach (@{$dataNode->parents}) { - my $parent = $codeGenerator->StripModule($_); - if ($parent eq "EventTarget") { next; } - $implIncludes{"V8${parent}.h"} = 1; - $parentClassTemplate = "V8" . $parent . "::GetTemplate()"; - last; - } - if (!$parentClassTemplate) { - $parentClassTemplate = "v8::Persistent<v8::FunctionTemplate>()"; - } - - # 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> defaultSignature = configureTemplate(desc, \"${visibleInterfaceName}\", $parentClassTemplate, V8${interfaceName}::internalFieldCount, -END - # Set up our attributes if we have them - if ($has_attributes) { - push(@implContent, <<END); - ${interfaceName}Attrs, WTF_ARRAY_LENGTH(${interfaceName}Attrs), -END - } else { - push(@implContent, <<END); - 0, 0, -END - } - - if ($has_callbacks) { - push(@implContent, <<END); - ${interfaceName}Callbacks, WTF_ARRAY_LENGTH(${interfaceName}Callbacks)); -END - } else { - push(@implContent, <<END); - 0, 0); -END - } - - if ($dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"V8CustomConstructor"} || $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(); - v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate(); -END - } - - push(@implContent, " $access_check\n"); - - # Setup the enable-at-runtime attrs if we have them - foreach my $runtime_attr (@enabledAtRuntime) { - my $enable_function = GetRuntimeEnableFunctionName($runtime_attr->signature); - my $conditionalString = GenerateConditionalString($runtime_attr->signature); - push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString; - push(@implContent, " if (${enable_function}()) {\n"); - push(@implContent, " static const BatchedAttribute attrData =\\\n"); - GenerateSingleBatchedAttribute($interfaceName, $runtime_attr, ";", " "); - push(@implContent, <<END); - configureAttribute(instance, proto, attrData); - } -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}) { - # Only one accessor is needed for overloaded methods: - next if $function->{overloadIndex} > 1; - - $total_functions++; - my $attrExt = $function->signature->extendedAttributes; - my $name = $function->signature->name; - - my $property_attributes = "v8::DontDelete"; - if ($attrExt->{"DontEnum"}) { - $property_attributes .= " | v8::DontEnum"; - } - if ($attrExt->{"V8ReadOnly"}) { - $property_attributes .= " | v8::ReadOnly"; - } - - my $commentInfo = "Function '$name' (ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')"; - - my $template = "proto"; - if ($attrExt->{"V8OnInstance"}) { - $template = "instance"; - } - if ($attrExt->{"ClassMethod"}) { - $template = "desc"; - } - - my $conditional = ""; - if ($attrExt->{"EnabledAtRuntime"}) { - # Only call Set()/SetAccessor() if this method should be enabled - $enable_function = GetRuntimeEnableFunctionName($function->signature); - $conditional = "if (${enable_function}())\n "; - } - - if ($attrExt->{"DoNotCheckDomainSecurity"} && - ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) { - # Mark the accessor as ReadOnly and set it on the proto object so - # it can be shadowed. This is really a hack to make it work. - # There are several sceneria to call into the accessor: - # 1) from the same domain: "window.open": - # the accessor finds the DOM wrapper in the proto chain; - # 2) from the same domain: "window.__proto__.open": - # the accessor will NOT find a DOM wrapper in the prototype chain - # 3) from another domain: "window.open": - # the access find the DOM wrapper in the prototype chain - # "window.__proto__.open" from another domain will fail when - # accessing '__proto__' - # - # The solution is very hacky and fragile, it really needs to be replaced - # by a better solution. - $property_attributes .= " | v8::ReadOnly"; - push(@implContent, <<END); - - // $commentInfo - ${conditional}$template->SetAccessor(v8::String::New("$name"), ${interfaceName}Internal::${name}AttrGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>($property_attributes)); -END - $num_callbacks++; - next; - } - - my $signature = "defaultSignature"; - if ($attrExt->{"V8DoNotCheckSignature"} || $attrExt->{"ClassMethod"}) { - $signature = "v8::Local<v8::Signature>()"; - } - - if (RequiresCustomSignature($function)) { - $signature = "${name}Signature"; - push(@implContent, "\n // Custom Signature '$name'\n", CreateCustomSignature($function)); - } - - # Normal function call is a template - my $callback = GetFunctionTemplateCallbackName($function, $interfaceName); - - if ($property_attributes eq "v8::DontDelete") { - $property_attributes = ""; - } else { - $property_attributes = ", static_cast<v8::PropertyAttribute>($property_attributes)"; - } - - if ($template eq "proto" && $conditional eq "" && $signature eq "defaultSignature" && $property_attributes eq "") { - # Standard type of callback, already created in the batch, so skip it here. - next; - } - - push(@implContent, <<END); - ${conditional}$template->Set(v8::String::New("$name"), v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), ${signature})$property_attributes); -END - $num_callbacks++; - } - - die "Wrong number of callbacks generated for $interfaceName ($num_callbacks, should be $total_functions)" if $num_callbacks != $total_functions; - - if ($has_constants) { - push(@implContent, <<END); - batchConfigureConstants(desc, proto, ${interfaceName}Consts, WTF_ARRAY_LENGTH(${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::External::Wrap(&V8DOMWindow::info), false); -END - } - if ($interfaceName eq "HTMLDocument") { - push(@implContent, <<END); - desc->SetHiddenPrototype(true); -END - } - if ($interfaceName eq "Location") { - push(@implContent, <<END); - - // For security reasons, these functions are on the instance instead - // of on the prototype object to ensure 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 - } - - my $nativeType = GetNativeTypeForConversions($dataNode, $interfaceName); - push(@implContent, <<END); - - // Custom toString template - desc->Set(getToStringName(), getToStringTemplate()); - return desc; -} - -v8::Persistent<v8::FunctionTemplate> ${className}::GetRawTemplate() -{ - static v8::Persistent<v8::FunctionTemplate> ${className}RawCache = createRawTemplate(); - return ${className}RawCache; -} - -v8::Persistent<v8::FunctionTemplate> ${className}::GetTemplate()\ -{ - static v8::Persistent<v8::FunctionTemplate> ${className}Cache = Configure${className}Template(GetRawTemplate()); - return ${className}Cache; -} - -bool ${className}::HasInstance(v8::Handle<v8::Value> value) -{ - return GetRawTemplate()->HasInstance(value); -} - -END - - if (IsActiveDomType($interfaceName)) { - # MessagePort is handled like an active dom object even though it doesn't inherit - # from ActiveDOMObject, so don't try to cast it to ActiveDOMObject. - my $returnValue = $interfaceName eq "MessagePort" ? "0" : "toNative(object)"; - push(@implContent, <<END); -ActiveDOMObject* ${className}::toActiveDOMObject(v8::Handle<v8::Object> object) -{ - return ${returnValue}; -} -END - } - - if ($implClassName eq "DOMWindow") { - push(@implContent, <<END); -v8::Persistent<v8::ObjectTemplate> V8DOMWindow::GetShadowObjectTemplate() -{ - static v8::Persistent<v8::ObjectTemplate> V8DOMWindowShadowObjectCache; - if (V8DOMWindowShadowObjectCache.IsEmpty()) { - V8DOMWindowShadowObjectCache = v8::Persistent<v8::ObjectTemplate>::New(v8::ObjectTemplate::New()); - ConfigureShadowObjectTemplate(V8DOMWindowShadowObjectCache); - } - return V8DOMWindowShadowObjectCache; -} -END - } - - GenerateToV8Converters($dataNode, $interfaceName, $className, $nativeType, $serializedAttribute); - - push(@implContent, <<END); - -void ${className}::derefObject(void* object) -{ -END - - if (IsRefPtrType($interfaceName)) { - push(@implContent, <<END); - static_cast<${nativeType}*>(object)->deref(); -END - } - - push(@implContent, <<END); -} - -} // namespace WebCore -END - - my $conditionalString = GenerateConditionalString($dataNode); - push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; - - # We've already added the header for this file in implFixedHeader, so remove - # it from implIncludes to ensure we don't #include it twice. - delete $implIncludes{"${className}.h"}; -} - -sub GenerateHeaderContentHeader -{ - my $dataNode = shift; - my $className = "V8" . $dataNode->name; - my $conditionalString = GenerateConditionalString($dataNode); - - my @headerContentHeader = split("\r", $headerTemplate); - - push(@headerContentHeader, "\n#if ${conditionalString}\n") if $conditionalString; - push(@headerContentHeader, "\n#ifndef ${className}" . "_h"); - push(@headerContentHeader, "\n#define ${className}" . "_h\n\n"); - return @headerContentHeader; -} - -sub GenerateImplementationContentHeader -{ - my $dataNode = shift; - my $className = "V8" . $dataNode->name; - my $conditionalString = GenerateConditionalString($dataNode); - - my @implContentHeader = split("\r", $headerTemplate); - - push(@implContentHeader, "\n#include \"config.h\"\n"); - push(@implContentHeader, "#include \"${className}.h\"\n\n"); - push(@implContentHeader, "#if ${conditionalString}\n\n") if $conditionalString; - return @implContentHeader; -} - -sub GenerateCallbackHeader -{ - my $object = shift; - my $dataNode = shift; - - my $interfaceName = $dataNode->name; - my $className = "V8$interfaceName"; - - - # - Add default header template - push(@headerContent, GenerateHeaderContentHeader($dataNode)); - - my @unsortedIncludes = (); - push(@unsortedIncludes, "#include \"ActiveDOMCallback.h\""); - push(@unsortedIncludes, "#include \"$interfaceName.h\""); - push(@unsortedIncludes, "#include \"WorldContextHandle.h\""); - push(@unsortedIncludes, "#include <v8.h>"); - push(@unsortedIncludes, "#include <wtf/Forward.h>"); - push(@headerContent, join("\n", sort @unsortedIncludes)); - - push(@headerContent, "\n\nnamespace WebCore {\n\n"); - push(@headerContent, "class ScriptExecutionContext;\n\n"); - push(@headerContent, "class $className : public $interfaceName, public ActiveDOMCallback {\n"); - - push(@headerContent, <<END); -public: - static PassRefPtr<${className}> create(v8::Local<v8::Value> value, ScriptExecutionContext* context) - { - ASSERT(value->IsObject()); - ASSERT(context); - return adoptRef(new ${className}(value->ToObject(), context)); - } - - virtual ~${className}(); - -END - - # Functions - my $numFunctions = @{$dataNode->functions}; - if ($numFunctions > 0) { - push(@headerContent, " // Functions\n"); - foreach my $function (@{$dataNode->functions}) { - my @params = @{$function->parameters}; - if (!$function->signature->extendedAttributes->{"Custom"} && - !(GetNativeType($function->signature->type) eq "bool")) { - push(@headerContent, " COMPILE_ASSERT(false)"); - } - - push(@headerContent, " virtual " . GetNativeTypeForCallbacks($function->signature->type) . " " . $function->signature->name . "("); - - my @args = (); - foreach my $param (@params) { - push(@args, GetNativeTypeForCallbacks($param->type) . " " . $param->name); - } - push(@headerContent, join(", ", @args)); - push(@headerContent, ");\n"); - } - } - - push(@headerContent, <<END); - -private: - ${className}(v8::Local<v8::Object>, ScriptExecutionContext*); - - v8::Persistent<v8::Object> m_callback; - WorldContextHandle m_worldContext; -}; - -END - - push(@headerContent, "}\n\n"); - push(@headerContent, "#endif // $className" . "_h\n\n"); - - my $conditionalString = GenerateConditionalString($dataNode); - push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString; -} - -sub GenerateCallbackImplementation -{ - my $object = shift; - my $dataNode = shift; - my $interfaceName = $dataNode->name; - my $className = "V8$interfaceName"; - - # - Add default header template - push(@implFixedHeader, GenerateImplementationContentHeader($dataNode)); - - $implIncludes{"ScriptExecutionContext.h"} = 1; - $implIncludes{"V8CustomVoidCallback.h"} = 1; - $implIncludes{"V8Proxy.h"} = 1; - - push(@implContent, "#include <wtf/Assertions.h>\n\n"); - push(@implContent, "namespace WebCore {\n\n"); - push(@implContent, <<END); -${className}::${className}(v8::Local<v8::Object> callback, ScriptExecutionContext* context) - : ActiveDOMCallback(context) - , m_callback(v8::Persistent<v8::Object>::New(callback)) - , m_worldContext(UseCurrentWorld) -{ -} - -${className}::~${className}() -{ - m_callback.Dispose(); -} - -END - - # Functions - my $numFunctions = @{$dataNode->functions}; - if ($numFunctions > 0) { - push(@implContent, "// Functions\n"); - foreach my $function (@{$dataNode->functions}) { - my @params = @{$function->parameters}; - if ($function->signature->extendedAttributes->{"Custom"} || - !(GetNativeTypeForCallbacks($function->signature->type) eq "bool")) { - next; - } - - AddIncludesForType($function->signature->type); - push(@implContent, "\n" . GetNativeTypeForCallbacks($function->signature->type) . " ${className}::" . $function->signature->name . "("); - - my @args = (); - foreach my $param (@params) { - AddIncludesForType($param->type); - push(@args, GetNativeTypeForCallbacks($param->type) . " " . $param->name); - } - push(@implContent, join(", ", @args)); - - push(@implContent, ")\n"); - push(@implContent, "{\n"); - push(@implContent, " if (!canInvokeCallback())\n"); - push(@implContent, " return true;\n\n"); - push(@implContent, " v8::HandleScope handleScope;\n\n"); - push(@implContent, " v8::Handle<v8::Context> v8Context = toV8Context(scriptExecutionContext(), m_worldContext);\n"); - push(@implContent, " if (v8Context.IsEmpty())\n"); - push(@implContent, " return true;\n\n"); - push(@implContent, " v8::Context::Scope scope(v8Context);\n\n"); - - @args = (); - foreach my $param (@params) { - my $paramName = $param->name; - push(@implContent, " v8::Handle<v8::Value> ${paramName}Handle = toV8(${paramName});\n"); - push(@implContent, " if (${paramName}Handle.IsEmpty()) {\n"); - push(@implContent, " CRASH();\n"); - push(@implContent, " return true;\n"); - push(@implContent, " }\n"); - push(@args, " ${paramName}Handle"); - } - - push(@implContent, "\n v8::Handle<v8::Value> argv[] = {\n"); - push(@implContent, join(",\n", @args)); - push(@implContent, "\n };\n\n"); - push(@implContent, " bool callbackReturnValue = false;\n"); - push(@implContent, " return !invokeCallback(m_callback, " . scalar(@params) . ", argv, callbackReturnValue, scriptExecutionContext());\n"); - push(@implContent, "}\n"); - } - } - - push(@implContent, "\n} // namespace WebCore\n\n"); - - my $conditionalString = GenerateConditionalString($dataNode); - push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString; -} - -sub GenerateToV8Converters -{ - my $dataNode = shift; - my $interfaceName = shift; - my $className = shift; - my $nativeType = shift; - my $serializedAttribute = shift; - - my $domMapFunction = GetDomMapFunction($dataNode, $interfaceName); - my $forceNewObjectInput = IsDOMNodeType($interfaceName) ? ", bool forceNewObject" : ""; - my $forceNewObjectCall = IsDOMNodeType($interfaceName) ? ", forceNewObject" : ""; - - push(@implContent, <<END); - -v8::Handle<v8::Object> ${className}::wrapSlow(${nativeType}* impl) -{ - v8::Handle<v8::Object> wrapper; - V8Proxy* proxy = 0; -END - - if (IsNodeSubType($dataNode)) { - push(@implContent, <<END); - if (impl->document()) { - proxy = V8Proxy::retrieve(impl->document()->frame()); - if (proxy && static_cast<Node*>(impl->document()) == static_cast<Node*>(impl)) { - if (proxy->windowShell()->initContextIfNeeded()) { - // initContextIfNeeded may have created a wrapper for the object, retry from the start. - return ${className}::wrap(impl); - } - } - } - -END - } - - if (IsNodeSubType($dataNode)) { - push(@implContent, <<END); - - v8::Handle<v8::Context> context; - if (proxy) - context = proxy->context(); - - // Enter the node's context and create the wrapper in that context. - if (!context.IsEmpty()) - context->Enter(); -END - } - - push(@implContent, <<END); - wrapper = V8DOMWrapper::instantiateV8Object(proxy, &info, impl); -END - if (IsNodeSubType($dataNode)) { - push(@implContent, <<END); - // Exit the node's context if it was entered. - if (!context.IsEmpty()) - context->Exit(); -END - } - - push(@implContent, <<END); - if (wrapper.IsEmpty()) - return wrapper; -END - push(@implContent, "\n impl->ref();\n") if IsRefPtrType($interfaceName); - - # Eagerly deserialize attributes of type SerializedScriptValue - # while we're in the right context. - if ($serializedAttribute) { - die "Attribute of type SerializedScriptValue expected" if $serializedAttribute->signature->type ne "SerializedScriptValue"; - my $attrName = $serializedAttribute->signature->name; - my $attrAttr = "v8::DontDelete"; - if ($serializedAttribute->type =~ /^readonly/) { - $attrAttr .= " | v8::ReadOnly"; - } - $attrAttr = "static_cast<v8::PropertyAttribute>($attrAttr)"; - my $getterFunc = $codeGenerator->WK_lcfirst($attrName); - push(@implContent, <<END); - SerializedScriptValue::deserializeAndSetProperty(wrapper, "${attrName}", ${attrAttr}, impl->${getterFunc}()); -END - } - - if ($domMapFunction) { - push(@implContent, <<END); - ${domMapFunction}.set(impl, v8::Persistent<v8::Object>::New(wrapper)); -END - } - - push(@implContent, <<END); - return wrapper; -} -END -} - -sub HasCustomToV8Implementation { - # FIXME: This subroutine is lame. Probably should be an .idl attribute (CustomToV8)? - $dataNode = shift; - $interfaceName = shift; - - # We generate a custom converter (but JSC doesn't) for the following: - return 1 if $interfaceName eq "CSSStyleSheet"; - return 1 if $interfaceName eq "CanvasPixelArray"; - return 1 if $interfaceName eq "DOMStringMap"; - return 1 if $interfaceName eq "DOMWindow"; - return 1 if $interfaceName eq "DOMTokenList"; - return 1 if $interfaceName eq "Element"; - return 1 if $interfaceName eq "HTMLDocument"; - return 1 if $interfaceName eq "HTMLElement"; - return 1 if $interfaceName eq "Location"; - return 1 if $interfaceName eq "NamedNodeMap"; - return 1 if $interfaceName eq "SVGDocument"; - return 1 if $interfaceName eq "SVGElement"; - return 1 if $interfaceName eq "ScriptProfile"; - return 1 if $interfaceName eq "ScriptProfileNode"; - return 1 if $interfaceName eq "WorkerContext"; - # We don't generate a custom converter (but JSC does) for the following: - return 0 if $interfaceName eq "AbstractWorker"; - return 0 if $interfaceName eq "CanvasRenderingContext"; - return 0 if $interfaceName eq "SVGElementInstance"; - - # For everything else, do what JSC does. - return $dataNode->extendedAttributes->{"CustomToJS"}; -} - -sub GetDomMapFunction -{ - my $dataNode = shift; - my $type = shift; - return "getDOMSVGElementInstanceMap()" if $type eq "SVGElementInstance"; - return "getDOMNodeMap()" if ($dataNode && IsNodeSubType($dataNode)); - return "" if $type eq "DOMImplementation"; - return "getActiveDOMObjectMap()" if IsActiveDomType($type); - return "getDOMObjectMap()"; -} - -sub IsActiveDomType -{ - # FIXME: Consider making this an .idl attribute. - my $type = shift; - return 1 if $type eq "EventSource"; - return 1 if $type eq "MessagePort"; - return 1 if $type eq "XMLHttpRequest"; - return 1 if $type eq "WebSocket"; - return 1 if $type eq "Worker"; - return 1 if $type eq "SharedWorker"; - return 1 if $type eq "IDBRequest"; - return 1 if $type eq "FileReader"; - return 1 if $type eq "FileWriter"; - return 0; -} - -sub GetNativeTypeForConversions -{ - my $dataNode = shift; - my $type = shift; - - $type = $codeGenerator->GetSVGTypeNeedingTearOff($type) if $codeGenerator->IsSVGTypeNeedingTearOff($type); - return $type; -} - -sub GenerateFunctionCallString() -{ - my $function = shift; - my $numberOfParameters = shift; - my $indent = shift; - my $implClassName = shift; - - my $name = $function->signature->name; - my $returnType = GetTypeFromSignature($function->signature); - my $nativeReturnType = GetNativeType($returnType, 0); - my $result = ""; - - my $isSVGTearOffType = ($codeGenerator->IsSVGTypeNeedingTearOff($returnType) and not $implClassName =~ /List$/); - $nativeReturnType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($returnType) if $isSVGTearOffType; - - if ($function->signature->extendedAttributes->{"v8implname"}) { - $name = $function->signature->extendedAttributes->{"v8implname"}; - } - - if ($function->signature->extendedAttributes->{"ImplementationFunction"}) { - $name = $function->signature->extendedAttributes->{"ImplementationFunction"}; - } - - my $functionString = "imp->${name}("; - if ($function->signature->extendedAttributes->{"ClassMethod"}) { - $functionString = "${implClassName}::${name}("; - } - - my $index = 0; - my $hasScriptState = 0; - - my $callWith = $function->signature->extendedAttributes->{"CallWith"}; - if ($callWith) { - my $callWithArg = "COMPILE_ASSERT(false)"; - if ($callWith eq "DynamicFrame") { - $result .= $indent . "Frame* enteredFrame = V8Proxy::retrieveFrameForEnteredContext();\n"; - $result .= $indent . "if (!enteredFrame)\n"; - $result .= $indent . " return v8::Undefined();\n"; - $callWithArg = "enteredFrame"; - } elsif ($callWith eq "ScriptState") { - $result .= $indent . "EmptyScriptState state;\n"; - $callWithArg = "&state"; - $hasScriptState = 1; - } elsif ($callWith eq "ScriptExecutionContext") { - $result .= $indent . "ScriptExecutionContext* scriptContext = getScriptExecutionContext();\n"; - $result .= $indent . "if (!scriptContext)\n"; - $result .= $indent . " return v8::Undefined();\n"; - $callWithArg = "scriptContext"; - } - $functionString .= ", " if $index; - $functionString .= $callWithArg; - $index++; - $numberOfParameters++ - } - - foreach my $parameter (@{$function->parameters}) { - if ($index eq $numberOfParameters) { - last; - } - $functionString .= ", " if $index; - my $paramName = $parameter->name; - my $paramType = $parameter->type; - - if ($parameter->type eq "NodeFilter" || $parameter->type eq "XPathNSResolver") { - $functionString .= "$paramName.get()"; - } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($parameter->type) and not $implClassName =~ /List$/) { - $functionString .= "$paramName->propertyReference()"; - $result .= $indent . "if (!$paramName) {\n"; - $result .= $indent . " V8Proxy::setDOMException(WebCore::TYPE_MISMATCH_ERR);\n"; - $result .= $indent . " return v8::Handle<v8::Value>();\n"; - $result .= $indent . "}\n"; - } elsif ($parameter->type eq "SVGMatrix" and $implClassName eq "SVGTransformList") { - $functionString .= "$paramName.get()"; - } else { - $functionString .= $paramName; - } - $index++; - } - - if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) { - $functionString .= ", " if $index; - $functionString .= "scriptArguments, callStack"; - $index += 2; - } - - if ($function->signature->extendedAttributes->{"NeedsUserGestureCheck"}) { - $functionString .= ", " if $index; - # FIXME: We need to pass DOMWrapperWorld as a parameter. - # See http://trac.webkit.org/changeset/54182 - $functionString .= "processingUserGesture()"; - $index++; - } - - if (@{$function->raisesExceptions}) { - $functionString .= ", " if $index; - $functionString .= "ec"; - $index++; - } - $functionString .= ")"; - - my $return = "result"; - my $returnIsRef = IsRefPtrType($returnType); - - if ($returnType eq "void") { - $result .= $indent . "$functionString;\n"; - } elsif ($hasScriptState or @{$function->raisesExceptions}) { - $result .= $indent . $nativeReturnType . " result = $functionString;\n"; - } else { - # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary - $return = $functionString; - $returnIsRef = 0; - - if ($implClassName eq "SVGTransformList" and IsRefPtrType($returnType)) { - $return = "WTF::getPtr(" . $return . ")"; - } - } - - if (@{$function->raisesExceptions}) { - $result .= $indent . "if (UNLIKELY(ec))\n"; - $result .= $indent . " goto fail;\n"; - } - - if ($hasScriptState) { - $result .= $indent . "if (state.hadException())\n"; - $result .= $indent . " return throwError(state.exception());\n" - } - - if ($isSVGTearOffType) { - $implIncludes{"V8$returnType.h"} = 1; - $implIncludes{"SVGPropertyTearOff.h"} = 1; - my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($returnType); - $result .= $indent . "return toV8(WTF::getPtr(${svgNativeType}::create($return)));\n"; - return $result; - } - - # If the implementing class is a POD type, commit changes - if ($codeGenerator->IsSVGTypeNeedingTearOff($implClassName) and not $implClassName =~ /List$/) { - $result .= $indent . "wrapper->commitChange();\n"; - } - - $return .= ".release()" if ($returnIsRef); - $result .= $indent . ReturnNativeToJSValue($function->signature, $return, $indent) . ";\n"; - - return $result; -} - - -sub GetTypeFromSignature -{ - my $signature = shift; - - return $codeGenerator->StripModule($signature->type); -} - - -sub GetNativeTypeFromSignature -{ - my $signature = shift; - my $parameterIndex = shift; - - my $type = GetTypeFromSignature($signature); - - if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) { - # Special-case index arguments because we need to check that they aren't < 0. - return "int"; - } - - $type = GetNativeType($type, $parameterIndex >= 0 ? 1 : 0); - - if ($parameterIndex >= 0 && $type eq "V8Parameter") { - my $mode = ""; - if ($signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"}) { - $mode = "WithUndefinedOrNullCheck"; - } elsif ($signature->extendedAttributes->{"ConvertNullToNullString"} || $signature->extendedAttributes->{"Reflect"}) { - $mode = "WithNullCheck"; - } - $type .= "<$mode>"; - } - - return $type; -} - -sub IsRefPtrType -{ - my $type = shift; - - 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 GetNativeType -{ - my $type = shift; - my $isParameter = shift; - - my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($type); - if ($svgNativeType) { - if ($svgNativeType =~ /List$/) { - return "${svgNativeType}*"; - } else { - return "RefPtr<${svgNativeType} >"; - } - } - - if ($type eq "float" or $type eq "double") { - return $type; - } - - return "V8Parameter" if ($type eq "DOMString" or $type eq "DOMUserData") and $isParameter; - return "int" if $type eq "int"; - return "int" if $type eq "short" or $type eq "unsigned short"; - return "unsigned" if $type eq "unsigned long"; - return "int" if $type eq "long"; - return "long long" if $type eq "long long"; - return "unsigned long long" if $type eq "unsigned long long"; - return "bool" if $type eq "boolean"; - return "String" if $type eq "DOMString"; - return "Range::CompareHow" if $type eq "CompareHow"; - 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 "ScriptValue" if $type eq "DOMObject"; - return "OptionsObject" if $type eq "OptionsObject"; - - return "String" if $type eq "DOMUserData"; # FIXME: Temporary hack? - - # temporary hack - return "RefPtr<NodeFilter>" if $type eq "NodeFilter"; - - return "RefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValue"; - - return "RefPtr<IDBKey>" if $type eq "IDBKey"; - - # necessary as resolvers could be constructed on fly. - return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver"; - - return "RefPtr<${type}>" if IsRefPtrType($type) and not $isParameter; - - return "RefPtr<MediaQueryListListener>" if $type eq "MediaQueryListListener"; - - # Default, assume native type is a pointer with same type name as idl type - return "${type}*"; -} - -sub GetNativeTypeForCallbacks -{ - my $type = shift; - return "const String&" if $type eq "DOMString"; - - # Callbacks use raw pointers, so pass isParameter = 1 - return GetNativeType($type, 1); -} - -sub TranslateParameter -{ - my $signature = shift; - - # The IDL uses some pseudo-types which don't really exist. - if ($signature->type eq "TimeoutHandler") { - $signature->type("DOMString"); - } -} - -sub TypeCanFailConversion -{ - my $signature = shift; - - my $type = GetTypeFromSignature($signature); - - $implIncludes{"ExceptionCode.h"} = 1 if $type eq "Attr"; - return 1 if $type eq "Attr"; - return 1 if $type eq "VoidCallback"; - return 1 if $type eq "IDBKey"; - return 0; -} - -sub JSValueToNative -{ - my $signature = shift; - my $value = shift; - - my $type = GetTypeFromSignature($signature); - - return "$value" if $type eq "JSObject"; - return "$value->BooleanValue()" if $type eq "boolean"; - return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $type eq "double"; - - return "toInt32($value)" if $type eq "long" or $type eq "short"; - return "toUInt32($value)" if $type eq "unsigned long" or $type eq "unsigned short"; - 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; - } - - die "Unexpected SerializedScriptValue" if $type eq "SerializedScriptValue"; - - if ($type eq "IDBKey") { - $implIncludes{"IDBBindingUtilities.h"} = 1; - $implIncludes{"IDBKey.h"} = 1; - return "createIDBKeyFromValue($value)"; - } - - if ($type eq "OptionsObject") { - $implIncludes{"OptionsObject.h"} = 1; - return $value; - } - - if ($type eq "DOMObject") { - $implIncludes{"ScriptValue.h"} = 1; - return "ScriptValue($value)"; - } - - if ($type eq "NodeFilter") { - return "V8DOMWrapper::wrapNativeNodeFilter($value)"; - } - - if ($type eq "MediaQueryListListener") { - $implIncludes{"MediaQueryListListener.h"} = 1; - return "MediaQueryListListener::create(" . $value . ")"; - } - - # Default, assume autogenerated type conversion routines - if ($type eq "EventTarget") { - $implIncludes{"V8Node.h"} = 1; - - # EventTarget is not in DOM hierarchy, but all Nodes are EventTarget. - return "V8Node::HasInstance($value) ? V8Node::toNative(v8::Handle<v8::Object>::Cast($value)) : 0"; - } - - if ($type eq "XPathNSResolver") { - return "V8DOMWrapper::getXPathNSResolver($value)"; - } - - AddIncludesForType($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) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0"; - } else { - $implIncludes{"V8$type.h"} = 1; - - # Perform type checks on the parameter, if it is expected Node type, - # return NULL. - return "V8${type}::HasInstance($value) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0"; - } -} - -sub GetV8HeaderName -{ - my $type = shift; - return "V8Event.h" if $type eq "DOMTimeStamp"; - return "EventListener.h" if $type eq "EventListener"; - return "EventTarget.h" if $type eq "EventTarget"; - return "SerializedScriptValue.h" if $type eq "SerializedScriptValue"; - return "ScriptValue.h" if $type eq "DOMObject"; - return "V8${type}.h"; -} - -sub CreateCustomSignature -{ - my $function = shift; - my $count = @{$function->parameters}; - my $name = $function->signature->name; - my $result = " const int ${name}Argc = ${count};\n" . - " v8::Handle<v8::FunctionTemplate> ${name}Argv[${name}Argc] = { "; - my $first = 1; - foreach my $parameter (@{$function->parameters}) { - if ($first) { $first = 0; } - else { $result .= ", "; } - if (IsWrapperType($parameter->type)) { - if ($parameter->type eq "XPathNSResolver") { - # Special case for XPathNSResolver. All other browsers accepts a callable, - # so, even though it's against IDL, accept objects here. - $result .= "v8::Handle<v8::FunctionTemplate>()"; - } else { - my $type = $parameter->type; - my $header = GetV8HeaderName($type); - $implIncludes{$header} = 1; - $result .= "V8${type}::GetRawTemplate()"; - } - } else { - $result .= "v8::Handle<v8::FunctionTemplate>()"; - } - } - $result .= " };\n"; - $result .= " v8::Handle<v8::Signature> ${name}Signature = v8::Signature::New(desc, ${name}Argc, ${name}Argv);\n"; - return $result; -} - - -sub RequiresCustomSignature -{ - my $function = shift; - # No signature needed for Custom function - if ($function->signature->extendedAttributes->{"Custom"} || - $function->signature->extendedAttributes->{"V8Custom"}) { - return 0; - } - # No signature needed for overloaded function - if (@{$function->{overloads}} > 1) { - return 0; - } - # Type checking is performed in the generated code - if ($function->signature->extendedAttributes->{"StrictTypeChecking"}) { - return 0; - } - foreach my $parameter (@{$function->parameters}) { - if ($parameter->extendedAttributes->{"Optional"} || $parameter->extendedAttributes->{"Callback"}) { - return 0; - } - } - - foreach my $parameter (@{$function->parameters}) { - if (IsWrapperType($parameter->type)) { - return 1; - } - } - return 0; -} - - -# FIXME: Sort this array. -my %non_wrapper_types = ( - 'float' => 1, - 'double' => 1, - 'int' => 1, - 'unsigned int' => 1, - 'short' => 1, - 'unsigned short' => 1, - 'long' => 1, - 'unsigned long' => 1, - 'boolean' => 1, - 'long long' => 1, - 'unsigned long long' => 1, - 'DOMString' => 1, - 'CompareHow' => 1, - 'SerializedScriptValue' => 1, - 'SVGPaintType' => 1, - 'DOMTimeStamp' => 1, - 'JSObject' => 1, - 'DOMObject' => 1, - 'EventTarget' => 1, - 'NodeFilter' => 1, - 'EventListener' => 1, - 'IDBKey' => 1, - 'OptionsObject' => 1, - 'Date' => 1, - 'MediaQueryListListener' => 1 -); - - -sub IsWrapperType -{ - my $type = $codeGenerator->StripModule(shift); - return !($non_wrapper_types{$type}); -} - -sub IsDOMNodeType -{ - my $type = shift; - - return 1 if $type eq 'Attr'; - return 1 if $type eq 'CDATASection'; - return 1 if $type eq 'Comment'; - 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 'HTMLCanvasElement'; - return 1 if $type eq 'HTMLDocument'; - return 1 if $type eq 'HTMLElement'; - return 1 if $type eq 'HTMLFormElement'; - return 1 if $type eq 'HTMLTableCaptionElement'; - return 1 if $type eq 'HTMLTableSectionElement'; - return 1 if $type eq 'Node'; - return 1 if $type eq 'ProcessingInstruction'; - return 1 if $type eq 'SVGElement'; - return 1 if $type eq 'SVGDocument'; - return 1 if $type eq 'SVGSVGElement'; - return 1 if $type eq 'SVGUseElement'; - return 1 if $type eq 'Text'; - - return 0; -} - - -sub ReturnNativeToJSValue -{ - my $signature = shift; - my $value = shift; - my $indent = shift; - my $type = GetTypeFromSignature($signature); - - return "return v8Boolean($value)" if $type eq "boolean"; - return "return v8::Handle<v8::Value>()" if $type eq "void"; # equivalent to v8::Undefined() - - # HTML5 says that unsigned reflected attributes should be in the range - # [0, 2^31). When a value isn't in this range, a default value (or 0) - # should be returned instead. - if ($signature->extendedAttributes->{"Reflect"} and ($type eq "unsigned long" or $type eq "unsigned short")) { - $value =~ s/getUnsignedIntegralAttribute/getIntegralAttribute/g; - return "return v8::Integer::NewFromUnsigned(std::max(0, " . $value . "))"; - } - - # For all the types where we use 'int' as the representation type, - # we use Integer::New which has a fast Smi conversion check. - my $nativeType = GetNativeType($type); - 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"; - # long long and unsigned long long are not representable in ECMAScript. - return "return v8::Number::New(static_cast<double>($value))" if $type eq "long long" or $type eq "unsigned long long" or $type eq "DOMTimeStamp"; - return "return v8::Number::New($value)" if $codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType"; - return "return $value.v8Value()" if $nativeType eq "ScriptValue"; - - if ($codeGenerator->IsStringType($type)) { - my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"}; - if (defined $conv) { - return "return v8StringOrNull($value)" if $conv eq "Null"; - return "return v8StringOrUndefined($value)" if $conv eq "Undefined"; - return "return v8StringOrFalse($value)" if $conv eq "False"; - - die "Unknown value for ConvertNullStringTo extended attribute"; - } - $conv = $signature->extendedAttributes->{"ConvertScriptString"}; - return "return v8StringOrNull($value)" if $conv; - return "return v8String($value)"; - } - - AddIncludesForType($type); - - # special case for non-DOM node interfaces - if (IsDOMNodeType($type)) { - return "return toV8(${value}" . ($signature->extendedAttributes->{"ReturnsNew"} ? ", true)" : ")"); - } - - if ($type eq "EventTarget") { - return "return V8DOMWrapper::convertEventTargetToV8Object($value)"; - } - - if ($type eq "EventListener") { - $implIncludes{"V8AbstractEventListener.h"} = 1; - return "return ${value} ? v8::Handle<v8::Value>(static_cast<V8AbstractEventListener*>(${value})->getListenerObject(imp->scriptExecutionContext())) : v8::Handle<v8::Value>(v8::Null())"; - } - - if ($type eq "SerializedScriptValue") { - $implIncludes{"$type.h"} = 1; - return "return $value->deserialize()"; - } - - $implIncludes{"wtf/RefCounted.h"} = 1; - $implIncludes{"wtf/RefPtr.h"} = 1; - $implIncludes{"wtf/GetPtr.h"} = 1; - - return "return toV8($value)"; -} - -# Internal helper -sub WriteData -{ - if (defined($IMPL)) { - # Write content to file. - print $IMPL @implContentHeader; - - print $IMPL @implFixedHeader; - - foreach my $implInclude (sort keys(%implIncludes)) { - my $checkType = $implInclude; - $checkType =~ s/\.h//; - - if ($implInclude =~ /wtf/) { - print $IMPL "#include \<$implInclude\>\n"; - } else { - print $IMPL "#include \"$implInclude\"\n" unless $codeGenerator->IsSVGAnimatedType($checkType); - } - } - - print $IMPL "\n"; - print $IMPL @implContentDecls; - print $IMPL @implContent; - close($IMPL); - undef($IMPL); - - %implIncludes = (); - @implFixedHeader = (); - @implHeaderContent = (); - @implContentDecls = (); - @implContent = (); - } - - if (defined($HEADER)) { - # Write content to file. - print $HEADER @headerContent; - close($HEADER); - undef($HEADER); - - @headerContent = (); - } -} - -sub GetVisibleInterfaceName -{ - my $interfaceName = shift; - - return "DOMException" if $interfaceName eq "DOMCoreException"; - return "FormData" if $interfaceName eq "DOMFormData"; - return $interfaceName; -} - -sub GetCallbackClassName -{ - my $interfaceName = shift; - - return "V8CustomVoidCallback" if $interfaceName eq "VoidCallback"; - return "V8$interfaceName"; -} - -sub ConvertToV8Parameter -{ - my $signature = shift; - my $nativeType = shift; - my $variableName = shift; - my $value = shift; - my $suffix = shift; - - die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8Parameter/; - if ($signature->type eq "DOMString") { - $implIncludes{"V8BindingMacros.h"} = 1; - my $macro = "STRING_TO_V8PARAMETER_EXCEPTION_BLOCK"; - $macro .= "_$suffix" if $suffix; - return "$macro($nativeType, $variableName, $value);" - } else { - # Don't know how to properly check for conversion exceptions when $parameter->type is "DOMUserData" - return "$nativeType $variableName($value, true);"; - } -} - -# Returns the RuntimeEnabledFeatures function name that is hooked up to check if a method/attribute is enabled. -sub GetRuntimeEnableFunctionName -{ - my $signature = shift; - - # If a parameter is given (e.g. "EnabledAtRuntime=FeatureName") return the RuntimeEnabledFeatures::{FeatureName}Enabled() method. - return "RuntimeEnabledFeatures::" . $codeGenerator->WK_lcfirst($signature->extendedAttributes->{"EnabledAtRuntime"}) . "Enabled" if ($signature->extendedAttributes->{"EnabledAtRuntime"} && $signature->extendedAttributes->{"EnabledAtRuntime"} ne "1"); - - # Otherwise return a function named RuntimeEnabledFeatures::{methodName}Enabled(). - return "RuntimeEnabledFeatures::" . $codeGenerator->WK_lcfirst($signature->name) . "Enabled"; -} - -sub DebugPrint -{ - my $output = shift; - - print $output; - print "\n"; -} |