Index: Source/bindings/scripts/CodeGeneratorV8.pm |
diff --git a/Source/bindings/scripts/CodeGeneratorV8.pm b/Source/bindings/scripts/CodeGeneratorV8.pm |
deleted file mode 100644 |
index a10985f8c2887ea61b27fedf8b0bb16dab36aab6..0000000000000000000000000000000000000000 |
--- a/Source/bindings/scripts/CodeGeneratorV8.pm |
+++ /dev/null |
@@ -1,6049 +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, 2012 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) |
-# Copyright (C) 2012 Ericsson AB. All rights reserved. |
-# Copyright (C) 2013 Samsung Electronics. All rights reserved. |
-# |
-# This library is free software; you can redistribute it and/or |
-# modify it under the terms of the GNU Library General Public |
-# License as published by the Free Software Foundation; either |
-# version 2 of the License, or (at your option) any later version. |
-# |
-# This library is distributed in the hope that it will be useful, |
-# but WITHOUT ANY WARRANTY; without even the implied warranty of |
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
-# Library General Public License for more details. |
-# |
-# You should have received a copy of the GNU Library General Public License |
-# along with this library; see the file COPYING.LIB. If not, write to |
-# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
-# Boston, MA 02111-1307, USA. |
-# |
- |
-package Block; |
- |
-# Sample code: |
-# my $outer = new Block("Free Name 1", "namespace Foo {", "} // namespace Foo"); |
-# $outer->add(" void foo() {}"); |
-# my $inner = new Block("Free Name 2", "namespace Bar {", "} // namespace Bar"); |
-# $inner->add(" void bar() {}"); |
-# $outer->add($inner); |
-# print $outer->toString(); |
-# |
-# Output code: |
-# namespace Foo { |
-# void foo() {} |
-# namespace Bar { |
-# void bar() {} |
-# } // namespace Bar |
-# } // namespace Foo |
- |
-sub new |
-{ |
- my $package = shift; |
- my $name = shift || "Anonymous block"; |
- my $header = shift || ""; |
- my $footer = shift || ""; |
- |
- my $object = { |
- "name" => $name, |
- "header" => [$header], |
- "footer" => [$footer], |
- "contents" => [], |
- }; |
- bless $object, $package; |
- return $object; |
-} |
- |
-sub addHeader |
-{ |
- my $object = shift; |
- my $header = shift || ""; |
- |
- push(@{$object->{header}}, $header); |
-} |
- |
-sub addFooter |
-{ |
- my $object = shift; |
- my $footer = shift || ""; |
- |
- push(@{$object->{footer}}, $footer); |
-} |
- |
-sub add |
-{ |
- my $object = shift; |
- my $content = shift || ""; |
- |
- push(@{$object->{contents}}, $content); |
-} |
- |
-sub toString |
-{ |
- my $object = shift; |
- |
- my $header = join "", @{$object->{header}}; |
- my $footer = join "", @{$object->{footer}}; |
- my $code = ""; |
- $code .= "/* BEGIN " . $object->{name} . " */\n" if $verbose; |
- $code .= $header . "\n" if $header; |
- for my $content (@{$object->{contents}}) { |
- if (ref($content) eq "Block") { |
- $code .= $content->toString(); |
- } else { |
- $code .= $content; |
- } |
- } |
- $code .= $footer . "\n" if $footer; |
- $code .= "/* END " . $object->{name} . " */\n" if $verbose; |
- return $code; |
-} |
- |
- |
-package CodeGeneratorV8; |
- |
-use strict; |
-use Cwd; |
-use File::Basename; |
-use File::Find; |
-use File::Spec; |
- |
-my $idlDocument; |
-my $idlDirectories; |
-my $preprocessor; |
-my $defines; |
-my $verbose; |
-my $interfaceIdlFiles; |
-my $writeFileOnlyIfChanged; |
-my $sourceRoot; |
- |
-# Cache of IDL file pathnames. |
-my $idlFiles; |
-my $cachedInterfaces = {}; |
- |
-my %implIncludes = (); |
-my %headerIncludes = (); |
- |
-# Header code structure: |
-# Root ... Copyright, include duplication check |
-# Conditional ... #if FEATURE ... #endif (to be removed soon) |
-# Includes |
-# NameSpaceWebCore |
-# Class |
-# ClassPublic |
-# ClassPrivate |
-my %header; |
- |
-# Implementation code structure: |
-# Root ... Copyright |
-# Conditional ... #if FEATURE ... #endif (to be removed soon) |
-# Includes |
-# NameSpaceWebCore |
-# NameSpaceInternal ... namespace ${implClassName}V8Internal in case of non-callback |
-my %implementation; |
- |
-my %primitiveTypeHash = ("boolean" => 1, |
- "void" => 1, |
- "Date" => 1, |
- "byte" => 1, |
- "octet" => 1, |
- "short" => 1, |
- "long" => 1, |
- "long long" => 1, |
- "unsigned short" => 1, |
- "unsigned long" => 1, |
- "unsigned long long" => 1, |
- "float" => 1, |
- "double" => 1, |
- ); |
- |
-my %nonWrapperTypes = ("CompareHow" => 1, |
- "DOMTimeStamp" => 1, |
- "Dictionary" => 1, |
- "EventListener" => 1, |
- # FIXME: When EventTarget is an interface and not a mixin, fix this so that |
- # EventTarget is treated as a wrapper type. |
- "EventTarget" => 1, |
- "MediaQueryListListener" => 1, |
- "NodeFilter" => 1, |
- "SerializedScriptValue" => 1, |
- "any" => 1, |
- ); |
- |
-my %typedArrayHash = ("ArrayBuffer" => [], |
- "ArrayBufferView" => [], |
- "Uint8Array" => ["unsigned char", "v8::kExternalUnsignedByteArray"], |
- "Uint8ClampedArray" => ["unsigned char", "v8::kExternalPixelArray"], |
- "Uint16Array" => ["unsigned short", "v8::kExternalUnsignedShortArray"], |
- "Uint32Array" => ["unsigned int", "v8::kExternalUnsignedIntArray"], |
- "Int8Array" => ["signed char", "v8::kExternalByteArray"], |
- "Int16Array" => ["short", "v8::kExternalShortArray"], |
- "Int32Array" => ["int", "v8::kExternalIntArray"], |
- "Float32Array" => ["float", "v8::kExternalFloatArray"], |
- "Float64Array" => ["double", "v8::kExternalDoubleArray"], |
- ); |
- |
-my %callbackFunctionTypeHash = (); |
- |
-my %enumTypeHash = (); |
- |
-my %svgAnimatedTypeHash = ("SVGAnimatedAngle" => 1, "SVGAnimatedBoolean" => 1, |
- "SVGAnimatedEnumeration" => 1, "SVGAnimatedInteger" => 1, |
- "SVGAnimatedLength" => 1, "SVGAnimatedLengthList" => 1, |
- "SVGAnimatedNumber" => 1, "SVGAnimatedNumberList" => 1, |
- "SVGAnimatedPreserveAspectRatio" => 1, |
- "SVGAnimatedRect" => 1, "SVGAnimatedString" => 1, |
- "SVGAnimatedTransformList" => 1); |
- |
-my %svgAttributesInHTMLHash = ("class" => 1, "id" => 1, "onabort" => 1, "onclick" => 1, |
- "onerror" => 1, "onload" => 1, "onmousedown" => 1, |
- "onmousemove" => 1, "onmouseout" => 1, "onmouseover" => 1, |
- "onmouseup" => 1, "onresize" => 1, "onscroll" => 1, |
- "onunload" => 1); |
- |
-my %svgTypeNeedingTearOff = ( |
- "SVGAngle" => "SVGPropertyTearOff<SVGAngle>", |
- "SVGLength" => "SVGPropertyTearOff<SVGLength>", |
- "SVGLengthList" => "SVGListPropertyTearOff<SVGLengthList>", |
- "SVGMatrix" => "SVGPropertyTearOff<SVGMatrix>", |
- "SVGNumber" => "SVGPropertyTearOff<float>", |
- "SVGNumberList" => "SVGListPropertyTearOff<SVGNumberList>", |
- "SVGPathSegList" => "SVGPathSegListPropertyTearOff", |
- "SVGPoint" => "SVGPropertyTearOff<FloatPoint>", |
- "SVGPointList" => "SVGListPropertyTearOff<SVGPointList>", |
- "SVGPreserveAspectRatio" => "SVGPropertyTearOff<SVGPreserveAspectRatio>", |
- "SVGRect" => "SVGPropertyTearOff<FloatRect>", |
- "SVGStringList" => "SVGStaticListPropertyTearOff<SVGStringList>", |
- "SVGTransform" => "SVGPropertyTearOff<SVGTransform>", |
- "SVGTransformList" => "SVGTransformListPropertyTearOff" |
-); |
- |
-my %svgTypeWithWritablePropertiesNeedingTearOff = ( |
- "SVGPoint" => 1, |
- "SVGMatrix" => 1 |
-); |
- |
-# Default .h template |
-my $headerTemplate = <<EOF; |
-/* |
- This file is part of the Blink open source project. |
- This file has been auto-generated by CodeGeneratorV8.pm. 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 |
- |
-sub new |
-{ |
- my $object = shift; |
- my $reference = { }; |
- |
- $idlDocument = shift; |
- $idlDirectories = shift; |
- $preprocessor = shift; |
- $defines = shift; |
- $verbose = shift; |
- $interfaceIdlFiles = shift; |
- $writeFileOnlyIfChanged = shift; |
- |
- $sourceRoot = getcwd(); |
- |
- bless($reference, $object); |
- return $reference; |
-} |
- |
- |
-sub IDLFileForInterface |
-{ |
- my $interfaceName = shift; |
- |
- unless ($idlFiles) { |
- my @directories = map { $_ = "$sourceRoot/$_" if -d "$sourceRoot/$_"; $_ } @$idlDirectories; |
- push(@directories, "."); |
- |
- $idlFiles = { }; |
- foreach my $idlFile (@$interfaceIdlFiles) { |
- $idlFiles->{fileparse(basename($idlFile), ".idl")} = $idlFile; |
- } |
- |
- my $wanted = sub { |
- $idlFiles->{$1} = $File::Find::name if /^([A-Z].*)\.idl$/; |
- $File::Find::prune = 1 if /^\../; |
- }; |
- find($wanted, @directories); |
- } |
- |
- return $idlFiles->{$interfaceName}; |
-} |
- |
-sub ParseInterface |
-{ |
- my $interfaceName = shift; |
- |
- if (exists $cachedInterfaces->{$interfaceName}) { |
- return $cachedInterfaces->{$interfaceName}; |
- } |
- |
- # Step #1: Find the IDL file associated with 'interface' |
- my $filename = IDLFileForInterface($interfaceName) |
- or die("Could NOT find IDL file for interface \"$interfaceName\" $!\n"); |
- |
- print " | |> Parsing parent IDL \"$filename\" for interface \"$interfaceName\"\n" if $verbose; |
- |
- # Step #2: Parse the found IDL file (in quiet mode). |
- my $parser = IDLParser->new(1); |
- my $document = $parser->Parse($filename, $defines, $preprocessor); |
- |
- foreach my $interface (@{$document->interfaces}) { |
- if ($interface->name eq $interfaceName or $interface->isPartial) { |
- $cachedInterfaces->{$interfaceName} = $interface; |
- return $interface; |
- } |
- } |
- |
- die("Could NOT find interface definition for $interfaceName in $filename"); |
-} |
- |
-sub GenerateInterface |
-{ |
- my $object = shift; |
- my $interface = shift; |
- |
- %callbackFunctionTypeHash = map { $_->name => $_ } @{$idlDocument->callbackFunctions}; |
- %enumTypeHash = map { $_->name => $_->values } @{$idlDocument->enumerations}; |
- my $v8ClassName = GetV8ClassName($interface); |
- my $defineName = $v8ClassName . "_h"; |
- my $internalNamespace = GetImplName($interface) . "V8Internal"; |
- |
- my $conditionalString = GenerateConditionalString($interface); |
- my $conditionalIf = ""; |
- my $conditionalEndif = ""; |
- if ($conditionalString) { |
- $conditionalIf = "#if ${conditionalString}"; |
- $conditionalEndif = "#endif // ${conditionalString}"; |
- } |
- |
- $header{root} = new Block("ROOT", "", ""); |
- # FIXME: newlines should be generated by Block::toString(). |
- $header{conditional} = new Block("Conditional", "$conditionalIf", $conditionalEndif ? "$conditionalEndif\n" : ""); |
- $header{includes} = new Block("Includes", "", ""); |
- $header{nameSpaceWebCore} = new Block("Namespace WebCore", "\nnamespace WebCore {\n", "}\n"); |
- $header{class} = new Block("Class definition", "", ""); |
- $header{classPublic} = new Block("Class public:", "public:", ""); |
- $header{classPrivate} = new Block("Class private:", "private:", ""); |
- |
- $header{root}->add($header{conditional}); |
- $header{conditional}->add($header{includes}); |
- $header{conditional}->add($header{nameSpaceWebCore}); |
- $header{nameSpaceWebCore}->add($header{class}); |
- $header{class}->add($header{classPublic}); |
- $header{class}->add($header{classPrivate}); |
- |
- # - Add default header template |
- $header{root}->addHeader($headerTemplate . "\n"); |
- $header{root}->addHeader("#ifndef $defineName\n#define $defineName\n"); |
- $header{root}->addFooter("#endif // $defineName"); |
- |
- $implementation{root} = new Block("ROOT", "", ""); |
- $conditionalEndif = "\n$conditionalEndif" if !$interface->isCallback and $conditionalEndif; |
- $implementation{conditional} = new Block("Conditional", $conditionalIf, $conditionalEndif); |
- $implementation{includes} = new Block("Includes", "", ""); |
- |
- # FIXME: newlines should be generated by Block::toString(). |
- my $nameSpaceWebCoreBegin = "namespace WebCore {\n"; |
- my $nameSpaceWebCoreEnd = "} // namespace WebCore"; |
- $nameSpaceWebCoreBegin = "$nameSpaceWebCoreBegin\n" if !$interface->isCallback; |
- $nameSpaceWebCoreEnd = "\n$nameSpaceWebCoreEnd\n" if $interface->isCallback; |
- $implementation{nameSpaceWebCore} = new Block("Namespace WebCore", $nameSpaceWebCoreBegin, $nameSpaceWebCoreEnd); |
- $implementation{nameSpaceInternal} = new Block("Internal namespace", "namespace $internalNamespace {\n", "} // namespace $internalNamespace\n"); |
- |
- $implementation{root}->add($implementation{conditional}); |
- $implementation{conditional}->add($implementation{includes}); |
- $implementation{conditional}->add($implementation{nameSpaceWebCore}); |
- if (!$interface->isCallback) { |
- $implementation{nameSpaceWebCore}->add($implementation{nameSpaceInternal}); |
- } |
- |
- # - Add default header template |
- $implementation{root}->addHeader($headerTemplate); |
- $implementation{root}->addHeader("\n#include \"config.h\""); |
- $implementation{includes}->add("#include \"${v8ClassName}.h\"\n\n"); |
- |
- # Start actual generation |
- if ($interface->isCallback) { |
- $object->GenerateCallbackHeader($interface); |
- $object->GenerateCallbackImplementation($interface); |
- } else { |
- $object->GenerateHeader($interface); |
- $object->GenerateImplementation($interface); |
- } |
-} |
- |
-sub AddToImplIncludes |
-{ |
- my $header = shift; |
- $implIncludes{$header} = 1; |
-} |
- |
-sub AddToHeaderIncludes |
-{ |
- my @includes = @_; |
- |
- for my $include (@includes) { |
- $headerIncludes{$include} = 1; |
- } |
-} |
- |
-sub SkipIncludeHeader |
-{ |
- my $type = shift; |
- |
- return 1 if IsPrimitiveType($type); |
- return 1 if IsEnumType($type); |
- return 1 if IsCallbackFunctionType($type); |
- return 1 if $type eq "DOMString"; |
- |
- # Special case: SVGPoint.h / SVGNumber.h do not exist. |
- return 1 if $type eq "SVGPoint" or $type eq "SVGNumber"; |
- return 0; |
-} |
- |
-sub AddIncludesForType |
-{ |
- my $type = shift; |
- |
- return if SkipIncludeHeader($type); |
- |
- # Default includes |
- if ($type eq "EventListener") { |
- AddToImplIncludes("core/dom/EventListener.h"); |
- } elsif ($type eq "SerializedScriptValue") { |
- AddToImplIncludes("bindings/v8/SerializedScriptValue.h"); |
- } elsif ($type eq "any" || IsCallbackFunctionType($type)) { |
- AddToImplIncludes("bindings/v8/ScriptValue.h"); |
- } elsif ($type eq "ArrayBuffer") { |
- AddToImplIncludes("bindings/v8/custom/V8ArrayBufferCustom.h"); |
- } else { |
- AddToImplIncludes("V8${type}.h"); |
- } |
- |
- # Additional includes |
- if ($type eq "CSSStyleSheet") { |
- AddToImplIncludes("core/css/CSSImportRule.h"); |
- } |
-} |
- |
-sub HeaderFilesForInterface |
-{ |
- my $interfaceName = shift; |
- my $implClassName = shift; |
- |
- my @includes = (); |
- if (IsTypedArrayType($interfaceName) or $interfaceName eq "ArrayBuffer") { |
- push(@includes, "wtf/${interfaceName}.h"); |
- } elsif ($interfaceName =~ /SVGPathSeg/) { |
- $interfaceName =~ s/Abs|Rel//; |
- push(@includes, "core/svg/${interfaceName}.h"); |
- } elsif (!SkipIncludeHeader($interfaceName)) { |
- my $idlFilename = IDLFileForInterface($interfaceName) or die("Could NOT find IDL file for interface \"$interfaceName\" $!\n"); |
- my $idlRelPath= "bindings/" . File::Spec->abs2rel($idlFilename, $sourceRoot); |
- push(@includes, dirname($idlRelPath) . "/" . $implClassName . ".h"); |
- } |
- return @includes; |
-} |
- |
-sub NeedsOpaqueRootForGC |
-{ |
- my $interface = shift; |
- return $interface->extendedAttributes->{"GenerateIsReachable"} || $interface->extendedAttributes->{"CustomIsReachable"}; |
-} |
- |
-sub GenerateOpaqueRootForGC |
-{ |
- my $interface = shift; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- |
- if ($interface->extendedAttributes->{"CustomIsReachable"}) { |
- return; |
- } |
- |
- my $code = <<END; |
-void* ${v8ClassName}::opaqueRootForGC(void* object, v8::Isolate* isolate) |
-{ |
- ${implClassName}* impl = static_cast<${implClassName}*>(object); |
-END |
- my $isReachableMethod = $interface->extendedAttributes->{"GenerateIsReachable"}; |
- if ($isReachableMethod) { |
- AddToImplIncludes("bindings/v8/V8GCController.h"); |
- AddToImplIncludes("core/dom/Element.h"); |
- $code .= <<END; |
- if (Node* owner = impl->${isReachableMethod}()) |
- return V8GCController::opaqueRootForGC(owner, isolate); |
-END |
- } |
- |
- $code .= <<END; |
- return object; |
-} |
- |
-END |
- $implementation{nameSpaceWebCore}->add($code); |
-} |
- |
-sub GetSVGPropertyTypes |
-{ |
- my $implType = shift; |
- |
- my $svgPropertyType; |
- my $svgListPropertyType; |
- my $svgNativeType; |
- |
- return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $implType =~ /SVG/; |
- |
- $svgNativeType = GetSVGTypeNeedingTearOff($implType); |
- return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $svgNativeType; |
- |
- # Append space to avoid compilation errors when using PassRefPtr<$svgNativeType> |
- $svgNativeType = "$svgNativeType "; |
- |
- my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($implType); |
- if ($svgNativeType =~ /SVGPropertyTearOff/) { |
- $svgPropertyType = $svgWrappedNativeType; |
- AddToImplIncludes("core/svg/properties/SVGAnimatedPropertyTearOff.h"); |
- } elsif ($svgNativeType =~ /SVGListPropertyTearOff/ or $svgNativeType =~ /SVGStaticListPropertyTearOff/ or $svgNativeType =~ /SVGTransformListPropertyTearOff/) { |
- $svgListPropertyType = $svgWrappedNativeType; |
- AddToHeaderIncludes("core/svg/properties/SVGAnimatedListPropertyTearOff.h"); |
- } elsif ($svgNativeType =~ /SVGPathSegListPropertyTearOff/) { |
- $svgListPropertyType = $svgWrappedNativeType; |
- AddToHeaderIncludes("core/svg/properties/SVGPathSegListPropertyTearOff.h"); |
- } |
- |
- if ($svgPropertyType) { |
- $svgPropertyType = "SVGPoint" if $svgPropertyType eq "FloatPoint"; |
- } |
- |
- return ($svgPropertyType, $svgListPropertyType, $svgNativeType); |
-} |
- |
-sub GetIndexedGetterFunction |
-{ |
- my $interface = shift; |
- |
- # FIXME: Expose indexed getter of CSSMixFunctionValue by removing this special case |
- # because CSSValueList(which is parent of CSSMixFunctionValue) has indexed property getter. |
- if ($interface->name eq "CSSMixFunctionValue") { |
- return 0; |
- } |
- |
- return GetSpecialAccessorFunctionForType($interface, "getter", "unsigned long", 1); |
-} |
- |
-sub GetIndexedSetterFunction |
-{ |
- my $interface = shift; |
- |
- return GetSpecialAccessorFunctionForType($interface, "setter", "unsigned long", 2); |
-} |
- |
-sub GetIndexedDeleterFunction |
-{ |
- my $interface = shift; |
- |
- return GetSpecialAccessorFunctionForType($interface, "deleter", "unsigned long", 1); |
-} |
- |
-sub GetNamedGetterFunction |
-{ |
- my $interface = shift; |
- return GetSpecialAccessorFunctionForType($interface, "getter", "DOMString", 1); |
-} |
- |
-sub GetNamedSetterFunction |
-{ |
- my $interface = shift; |
- return GetSpecialAccessorFunctionForType($interface, "setter", "DOMString", 2); |
-} |
- |
-sub GetNamedDeleterFunction |
-{ |
- my $interface = shift; |
- return GetSpecialAccessorFunctionForType($interface, "deleter", "DOMString", 1); |
-} |
- |
-sub GetSpecialAccessorFunctionForType |
-{ |
- my $interface = shift; |
- my $special = shift; |
- my $firstParameterType = shift; |
- my $numberOfParameters = shift; |
- |
- foreach my $function (@{$interface->functions}) { |
- my $specials = $function->specials; |
- my $specialExists = grep { $_ eq $special } @$specials; |
- my $parameters = $function->parameters; |
- if ($specialExists and scalar(@$parameters) == $numberOfParameters and $parameters->[0]->type eq $firstParameterType) { |
- return $function; |
- } |
- } |
- |
- return 0; |
-} |
- |
-sub GenerateHeader |
-{ |
- my $object = shift; |
- my $interface = shift; |
- |
- my $interfaceName = $interface->name; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- |
- LinkOverloadedFunctions($interface); |
- |
- # Ensure the IsDOMNodeType function is in sync. |
- die("IsDOMNodeType is out of date with respect to $interfaceName") if IsDOMNodeType($interfaceName) != InheritsInterface($interface, "Node"); |
- |
- my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($interfaceName); |
- |
- my $parentInterface = $interface->parent; |
- AddToHeaderIncludes("V8${parentInterface}.h") if $parentInterface; |
- AddToHeaderIncludes("bindings/v8/WrapperTypeInfo.h"); |
- AddToHeaderIncludes("bindings/v8/V8Binding.h"); |
- AddToHeaderIncludes("bindings/v8/V8DOMWrapper.h"); |
- AddToHeaderIncludes(HeaderFilesForInterface($interfaceName, $implClassName)); |
- foreach my $headerInclude (sort keys(%headerIncludes)) { |
- $header{includes}->add("#include \"${headerInclude}\"\n"); |
- } |
- |
- $header{nameSpaceWebCore}->addHeader("\ntemplate<typename PropertyType> class SVGPropertyTearOff;\n") if $svgPropertyType; |
- if ($svgNativeType) { |
- if ($svgNativeType =~ /SVGStaticListPropertyTearOff/) { |
- $header{nameSpaceWebCore}->addHeader("\ntemplate<typename PropertyType> class SVGStaticListPropertyTearOff;\n"); |
- } else { |
- $header{nameSpaceWebCore}->addHeader("\ntemplate<typename PropertyType> class SVGListPropertyTearOff;\n"); |
- } |
- } |
- |
- $header{nameSpaceWebCore}->addHeader("class FloatRect;\n") if $svgPropertyType && $svgPropertyType eq "FloatRect"; |
- $header{nameSpaceWebCore}->addHeader("\nclass Dictionary;") if IsConstructorTemplate($interface, "Event"); |
- |
- my $nativeType = GetNativeTypeForConversions($interface); |
- if ($interface->extendedAttributes->{"NamedConstructor"}) { |
- $header{nameSpaceWebCore}->addHeader(<<END); |
- |
-class V8${nativeType}Constructor { |
-public: |
- static v8::Handle<v8::FunctionTemplate> GetTemplate(v8::Isolate*, WrapperWorldType); |
- static WrapperTypeInfo info; |
-}; |
-END |
- } |
- |
- $header{class}->addHeader("class $v8ClassName {"); |
- $header{class}->addFooter("};"); |
- |
- $header{classPublic}->add(<<END); |
- static bool HasInstance(v8::Handle<v8::Value>, v8::Isolate*, WrapperWorldType); |
- static bool HasInstanceInAnyWorld(v8::Handle<v8::Value>, v8::Isolate*); |
- static v8::Handle<v8::FunctionTemplate> GetTemplate(v8::Isolate*, WrapperWorldType); |
- static ${nativeType}* toNative(v8::Handle<v8::Object> object) |
- { |
- return reinterpret_cast<${nativeType}*>(object->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex)); |
- } |
- static void derefObject(void*); |
- static WrapperTypeInfo info; |
-END |
- |
- if (NeedsOpaqueRootForGC($interface)) { |
- $header{classPublic}->add(" static void* opaqueRootForGC(void*, v8::Isolate*);\n"); |
- } |
- |
- if (InheritsExtendedAttribute($interface, "ActiveDOMObject")) { |
- $header{classPublic}->add(" static ActiveDOMObject* toActiveDOMObject(v8::Handle<v8::Object>);\n"); |
- } |
- |
- if (InheritsExtendedAttribute($interface, "EventTarget")) { |
- $header{classPublic}->add(" static EventTarget* toEventTarget(v8::Handle<v8::Object>);\n"); |
- } |
- |
- if ($interfaceName eq "Window") { |
- $header{classPublic}->add(<<END); |
- static v8::Handle<v8::ObjectTemplate> GetShadowObjectTemplate(v8::Isolate*, WrapperWorldType); |
-END |
- } |
- |
- my @enabledPerContextFunctions; |
- foreach my $function (@{$interface->functions}) { |
- my $name = $function->name; |
- next if $name eq ""; |
- my $attrExt = $function->extendedAttributes; |
- |
- if (HasCustomMethod($attrExt) && $function->{overloadIndex} == 1) { |
- my $conditionalString = GenerateConditionalString($function); |
- $header{classPublic}->add("#if ${conditionalString}\n") if $conditionalString; |
- $header{classPublic}->add(<<END); |
- static void ${name}MethodCustom(const v8::FunctionCallbackInfo<v8::Value>&); |
-END |
- $header{classPublic}->add("#endif // ${conditionalString}\n") if $conditionalString; |
- } |
- if ($attrExt->{"EnabledPerContext"}) { |
- push(@enabledPerContextFunctions, $function); |
- } |
- } |
- |
- if (IsConstructable($interface)) { |
- $header{classPublic}->add(" static void constructorCallback(const v8::FunctionCallbackInfo<v8::Value>&);\n"); |
-END |
- } |
- if (HasCustomConstructor($interface)) { |
- $header{classPublic}->add(" static void constructorCustom(const v8::FunctionCallbackInfo<v8::Value>&);\n"); |
- } |
- |
- my @enabledPerContextAttributes; |
- foreach my $attribute (@{$interface->attributes}) { |
- my $name = $attribute->name; |
- my $attrExt = $attribute->extendedAttributes; |
- my $conditionalString = GenerateConditionalString($attribute); |
- if (HasCustomGetter($attrExt) && !$attrExt->{"ImplementedBy"}) { |
- $header{classPublic}->add("#if ${conditionalString}\n") if $conditionalString; |
- $header{classPublic}->add(<<END); |
- static void ${name}AttrGetterCustom(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>&); |
-END |
- $header{classPublic}->add("#endif // ${conditionalString}\n") if $conditionalString; |
- } |
- if (HasCustomSetter($attrExt) && !$attrExt->{"ImplementedBy"}) { |
- $header{classPublic}->add("#if ${conditionalString}\n") if $conditionalString; |
- $header{classPublic}->add(<<END); |
- static void ${name}AttrSetterCustom(v8::Local<v8::String> name, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<void>&); |
-END |
- $header{classPublic}->add("#endif // ${conditionalString}\n") if $conditionalString; |
- } |
- if ($attrExt->{"EnabledPerContext"}) { |
- push(@enabledPerContextAttributes, $attribute); |
- } |
- } |
- |
- GenerateHeaderNamedAndIndexedPropertyAccessors($interface); |
- GenerateHeaderLegacyCall($interface); |
- GenerateHeaderCustomInternalFieldIndices($interface); |
- |
- if ($interface->name eq "Window") { |
- $header{classPublic}->add(<<END); |
- static bool namedSecurityCheckCustom(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType, v8::Local<v8::Value> data); |
- static bool indexedSecurityCheckCustom(v8::Local<v8::Object> host, uint32_t index, v8::AccessType, v8::Local<v8::Value> data); |
-END |
- } |
- |
- if (@enabledPerContextAttributes) { |
- $header{classPublic}->add(<<END); |
- static void installPerContextProperties(v8::Handle<v8::Object>, ${nativeType}*, v8::Isolate*); |
-END |
- } else { |
- $header{classPublic}->add(<<END); |
- static void installPerContextProperties(v8::Handle<v8::Object>, ${nativeType}*, v8::Isolate*) { } |
-END |
- } |
- |
- if (@enabledPerContextFunctions) { |
- $header{classPublic}->add(<<END); |
- static void installPerContextPrototypeProperties(v8::Handle<v8::Object>, v8::Isolate*); |
-END |
- } else { |
- $header{classPublic}->add(<<END); |
- static void installPerContextPrototypeProperties(v8::Handle<v8::Object>, v8::Isolate*) { } |
-END |
- } |
- |
- if ($interfaceName eq "HTMLElement") { |
- $header{classPublic}->add(<<END); |
- friend v8::Handle<v8::Object> createV8HTMLWrapper(HTMLElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*); |
- friend v8::Handle<v8::Object> createV8HTMLDirectWrapper(HTMLElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*); |
-END |
- } elsif ($interfaceName eq "SVGElement") { |
- $header{classPublic}->add(<<END); |
- friend v8::Handle<v8::Object> createV8SVGWrapper(SVGElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*); |
- friend v8::Handle<v8::Object> createV8SVGDirectWrapper(SVGElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*); |
- friend v8::Handle<v8::Object> createV8SVGFallbackWrapper(SVGElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*); |
-END |
- } elsif ($interfaceName eq "HTMLUnknownElement") { |
- $header{classPublic}->add(<<END); |
- friend v8::Handle<v8::Object> createV8HTMLFallbackWrapper(HTMLUnknownElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*); |
-END |
- } elsif ($interfaceName eq "Element") { |
- $header{classPublic}->add(<<END); |
- // This is a performance optimization hack. See V8Element::wrap. |
- friend v8::Handle<v8::Object> wrap(Node*, v8::Handle<v8::Object> creationContext, v8::Isolate*); |
-END |
- } |
- |
- my $noToV8 = $interface->extendedAttributes->{"DoNotGenerateToV8"}; |
- my $noWrap = $interface->extendedAttributes->{"DoNotGenerateWrap"} || $noToV8; |
- if (!$noWrap) { |
- my $createWrapperArgumentType = GetPassRefPtrType($nativeType); |
- $header{classPrivate}->add(<<END); |
- friend v8::Handle<v8::Object> wrap(${nativeType}*, v8::Handle<v8::Object> creationContext, v8::Isolate*); |
- static v8::Handle<v8::Object> createWrapper(${createWrapperArgumentType}, v8::Handle<v8::Object> creationContext, v8::Isolate*); |
-END |
- } |
- |
- $header{nameSpaceWebCore}->add(<<END); |
- |
-template<> |
-class WrapperTypeTraits<${nativeType} > { |
-public: |
- static WrapperTypeInfo* info() { return &${v8ClassName}::info; } |
-}; |
- |
-END |
- |
- my $customWrap = $interface->extendedAttributes->{"CustomToV8"}; |
- if ($noToV8) { |
- die "Can't suppress toV8 for subclass\n" if $interface->parent; |
- } elsif ($noWrap) { |
- die "Must have custom toV8\n" if !$customWrap; |
- $header{nameSpaceWebCore}->add(<<END); |
-class ${nativeType}; |
-v8::Handle<v8::Value> toV8(${nativeType}*, v8::Handle<v8::Object> creationContext, v8::Isolate*); |
-v8::Handle<v8::Value> toV8ForMainWorld(${nativeType}*, v8::Handle<v8::Object> creationContext, v8::Isolate*); |
- |
-template<class HolderContainer, class Wrappable> |
-inline v8::Handle<v8::Value> toV8Fast(${nativeType}* impl, const HolderContainer& container, Wrappable*) |
-{ |
- return toV8(impl, container.Holder(), container.GetIsolate()); |
-} |
- |
-template<class HolderContainer, class Wrappable> |
-inline v8::Handle<v8::Value> toV8FastForMainWorld(${nativeType}* impl, const HolderContainer& container, Wrappable*) |
-{ |
- return toV8ForMainWorld(impl, container.Holder(), container.GetIsolate()); |
-} |
-END |
- } else { |
- |
- my $createWrapperCall = $customWrap ? "${v8ClassName}::wrap" : "${v8ClassName}::createWrapper"; |
- |
- if ($customWrap) { |
- $header{nameSpaceWebCore}->add(<<END); |
- |
-v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate*); |
-END |
- } else { |
- $header{nameSpaceWebCore}->add(<<END); |
- |
-inline v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) |
-{ |
- ASSERT(impl); |
- ASSERT(DOMDataStore::getWrapper(impl, isolate).IsEmpty()); |
- if (ScriptWrappable::wrapperCanBeStoredInObject(impl)) { |
- const WrapperTypeInfo* actualInfo = ScriptWrappable::getTypeInfoFromObject(impl); |
- // Might be a XXXConstructor::info instead of an XXX::info. These will both have |
- // the same object de-ref functions, though, so use that as the basis of the check. |
- RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(actualInfo->derefObjectFunction == ${v8ClassName}::info.derefObjectFunction); |
- } |
- return $createWrapperCall(impl, creationContext, isolate); |
-} |
-END |
- } |
- |
- $header{nameSpaceWebCore}->add(<<END); |
- |
-inline v8::Handle<v8::Value> toV8(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) |
-{ |
- if (UNLIKELY(!impl)) |
- return v8NullWithCheck(isolate); |
- v8::Handle<v8::Value> wrapper = DOMDataStore::getWrapper(impl, isolate); |
- if (!wrapper.IsEmpty()) |
- return wrapper; |
- return wrap(impl, creationContext, isolate); |
-} |
- |
-inline v8::Handle<v8::Value> toV8ForMainWorld(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) |
-{ |
- ASSERT(worldType(isolate) == MainWorld); |
- if (UNLIKELY(!impl)) |
- return v8NullWithCheck(isolate); |
- v8::Handle<v8::Value> wrapper = DOMDataStore::getWrapperForMainWorld(impl); |
- if (!wrapper.IsEmpty()) |
- return wrapper; |
- return wrap(impl, creationContext, isolate); |
-} |
- |
-template<class HolderContainer, class Wrappable> |
-inline v8::Handle<v8::Value> toV8Fast(${nativeType}* impl, const HolderContainer& container, Wrappable* wrappable) |
-{ |
- if (UNLIKELY(!impl)) |
- return v8::Null(container.GetIsolate()); |
- v8::Handle<v8::Object> wrapper = DOMDataStore::getWrapperFast(impl, container, wrappable); |
- if (!wrapper.IsEmpty()) |
- return wrapper; |
- return wrap(impl, container.Holder(), container.GetIsolate()); |
-} |
- |
-template<class HolderContainer, class Wrappable> |
-inline v8::Handle<v8::Value> toV8FastForMainWorld(${nativeType}* impl, const HolderContainer& container, Wrappable* wrappable) |
-{ |
- ASSERT(worldType(container.GetIsolate()) == MainWorld); |
- if (UNLIKELY(!impl)) |
- return v8::Null(container.GetIsolate()); |
- v8::Handle<v8::Object> wrapper = DOMDataStore::getWrapperForMainWorld(impl); |
- if (!wrapper.IsEmpty()) |
- return wrapper; |
- return wrap(impl, container.Holder(), container.GetIsolate()); |
-} |
- |
-template<class HolderContainer, class Wrappable> |
-inline v8::Handle<v8::Value> toV8FastForMainWorld(PassRefPtr< ${nativeType} > impl, const HolderContainer& container, Wrappable* wrappable) |
-{ |
- return toV8FastForMainWorld(impl.get(), container, wrappable); |
-} |
- |
-END |
- } |
- |
- $header{nameSpaceWebCore}->add(<<END); |
- |
-template<class HolderContainer, class Wrappable> |
-inline v8::Handle<v8::Value> toV8Fast(PassRefPtr< ${nativeType} > impl, const HolderContainer& container, Wrappable* wrappable) |
-{ |
- return toV8Fast(impl.get(), container, wrappable); |
-} |
- |
-inline v8::Handle<v8::Value> toV8(PassRefPtr< ${nativeType} > impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) |
-{ |
- return toV8(impl.get(), creationContext, isolate); |
-} |
- |
-END |
- |
- if (IsConstructorTemplate($interface, "Event")) { |
- $header{nameSpaceWebCore}->add("bool fill${implClassName}Init(${implClassName}Init&, const Dictionary&);\n\n"); |
- } |
-} |
- |
-sub GetInternalFields |
-{ |
- my $interface = shift; |
- |
- my @customInternalFields = (); |
- # Event listeners on DOM nodes are explicitly supported in the GC controller. |
- if (!InheritsInterface($interface, "Node") && |
- InheritsExtendedAttribute($interface, "EventTarget")) { |
- push(@customInternalFields, "eventListenerCacheIndex"); |
- } |
- return @customInternalFields; |
-} |
- |
-sub GenerateHeaderCustomInternalFieldIndices |
-{ |
- my $interface = shift; |
- my @customInternalFields = GetInternalFields($interface); |
- my $customFieldCounter = 0; |
- foreach my $customInternalField (@customInternalFields) { |
- $header{classPublic}->add(<<END); |
- static const int ${customInternalField} = v8DefaultWrapperInternalFieldCount + ${customFieldCounter}; |
-END |
- $customFieldCounter++; |
- } |
- $header{classPublic}->add(<<END); |
- static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + ${customFieldCounter}; |
-END |
-} |
- |
-sub GenerateHeaderNamedAndIndexedPropertyAccessors |
-{ |
- my $interface = shift; |
- |
- my $indexedGetterFunction = GetIndexedGetterFunction($interface); |
- my $hasCustomIndexedGetter = $indexedGetterFunction && $indexedGetterFunction->extendedAttributes->{"Custom"}; |
- |
- my $indexedSetterFunction = GetIndexedSetterFunction($interface); |
- my $hasCustomIndexedSetter = $indexedSetterFunction && $indexedSetterFunction->extendedAttributes->{"Custom"}; |
- |
- my $indexedDeleterFunction = GetIndexedDeleterFunction($interface); |
- my $hasCustomIndexedDeleters = $indexedDeleterFunction && $indexedDeleterFunction->extendedAttributes->{"Custom"}; |
- |
- my $namedGetterFunction = GetNamedGetterFunction($interface); |
- my $hasCustomNamedGetter = $namedGetterFunction && $namedGetterFunction->extendedAttributes->{"Custom"}; |
- |
- my $namedSetterFunction = GetNamedSetterFunction($interface); |
- my $hasCustomNamedSetter = $namedSetterFunction && $namedSetterFunction->extendedAttributes->{"Custom"}; |
- |
- my $namedDeleterFunction = GetNamedDeleterFunction($interface); |
- my $hasCustomNamedDeleter = $namedDeleterFunction && $namedDeleterFunction->extendedAttributes->{"Custom"}; |
- |
- my $namedEnumeratorFunction = $namedGetterFunction && !$namedGetterFunction->extendedAttributes->{"NotEnumerable"}; |
- my $hasCustomNamedEnumerator = $namedGetterFunction && $namedGetterFunction->extendedAttributes->{"CustomEnumerateProperty"}; |
- |
- if ($hasCustomIndexedGetter) { |
- $header{classPublic}->add(" static void indexedPropertyGetterCustom(uint32_t, const v8::PropertyCallbackInfo<v8::Value>&);\n"); |
- } |
- |
- if ($hasCustomIndexedSetter) { |
- $header{classPublic}->add(" static void indexedPropertySetterCustom(uint32_t, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&);\n"); |
- } |
- |
- if ($hasCustomIndexedDeleters) { |
- $header{classPublic}->add(" static void indexedPropertyDeleterCustom(uint32_t, const v8::PropertyCallbackInfo<v8::Boolean>&);\n"); |
- } |
- |
- if ($hasCustomNamedGetter) { |
- $header{classPublic}->add(" static void namedPropertyGetterCustom(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>&);\n"); |
- } |
- |
- if ($hasCustomNamedSetter) { |
- $header{classPublic}->add(" static void namedPropertySetterCustom(v8::Local<v8::String>, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&);\n"); |
- } |
- |
- if ($hasCustomNamedDeleter) { |
- $header{classPublic}->add(" static void namedPropertyDeleterCustom(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Boolean>&);\n"); |
- } |
- |
- if ($hasCustomNamedEnumerator) { |
- $header{classPublic}->add(" static void namedPropertyEnumeratorCustom(const v8::PropertyCallbackInfo<v8::Array>&);\n"); |
- $header{classPublic}->add(" static void namedPropertyQueryCustom(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Integer>&);\n"); |
- } |
-} |
- |
-sub GenerateHeaderLegacyCall |
-{ |
- my $interface = shift; |
- |
- if ($interface->extendedAttributes->{"CustomLegacyCall"}) { |
- $header{classPublic}->add(" static void legacyCallCustom(const v8::FunctionCallbackInfo<v8::Value>&);\n"); |
- } |
-} |
- |
-sub HasActivityLogging |
-{ |
- my $forMainWorldSuffix = shift; |
- my $attrExt = shift; |
- my $access = shift; |
- |
- if (!$attrExt->{"ActivityLog"}) { |
- return 0; |
- } |
- my $logAllAccess = ($attrExt->{"ActivityLog"} =~ /^Access/); |
- my $logGetter = ($attrExt->{"ActivityLog"} =~ /^Getter/); |
- my $logSetter = ($attrExt->{"ActivityLog"} =~ /^Setter/); |
- my $logOnlyIsolatedWorlds = ($attrExt->{"ActivityLog"} =~ /ForIsolatedWorlds$/); |
- |
- if ($logOnlyIsolatedWorlds && $forMainWorldSuffix eq "ForMainWorld") { |
- return 0; |
- } |
- return $logAllAccess || ($logGetter && $access eq "Getter") || ($logSetter && $access eq "Setter"); |
-} |
- |
-sub IsConstructable |
-{ |
- my $interface = shift; |
- |
- return $interface->extendedAttributes->{"CustomConstructor"} || $interface->extendedAttributes->{"Constructor"} || $interface->extendedAttributes->{"ConstructorTemplate"}; |
-} |
- |
-sub HasCustomConstructor |
-{ |
- my $interface = shift; |
- |
- return $interface->extendedAttributes->{"CustomConstructor"}; |
-} |
- |
-sub HasCustomGetter |
-{ |
- my $attrExt = shift; |
- return $attrExt->{"Custom"} || $attrExt->{"CustomGetter"}; |
-} |
- |
-sub HasCustomSetter |
-{ |
- my $attrExt = shift; |
- return $attrExt->{"Custom"} || $attrExt->{"CustomSetter"}; |
-} |
- |
-sub HasCustomMethod |
-{ |
- my $attrExt = shift; |
- return $attrExt->{"Custom"}; |
-} |
- |
-sub IsReadonly |
-{ |
- my $attribute = shift; |
- my $attrExt = $attribute->extendedAttributes; |
- return $attribute->isReadOnly && !$attrExt->{"Replaceable"}; |
-} |
- |
-sub GetV8ClassName |
-{ |
- my $interface = shift; |
- return "V8" . $interface->name; |
-} |
- |
-sub GetImplName |
-{ |
- my $interfaceOrAttributeOrFunction = shift; |
- return $interfaceOrAttributeOrFunction->extendedAttributes->{"ImplementedAs"} || $interfaceOrAttributeOrFunction->name; |
-} |
- |
-sub GetImplNameFromImplementedBy |
-{ |
- my $implementedBy = shift; |
- |
- my $interface = ParseInterface($implementedBy); |
- return $interface->extendedAttributes->{"ImplementedAs"} || $implementedBy; |
-} |
- |
-sub GenerateDomainSafeFunctionGetter |
-{ |
- my $function = shift; |
- my $interface = shift; |
- |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- my $funcName = $function->name; |
- |
- my $functionLength = GetFunctionLength($function); |
- my $signature = "v8::Signature::New(V8PerIsolateData::from(info.GetIsolate())->rawTemplate(&" . $v8ClassName . "::info, currentWorldType))"; |
- if ($function->extendedAttributes->{"DoNotCheckSignature"}) { |
- $signature = "v8::Local<v8::Signature>()"; |
- } |
- |
- my $newTemplateParams = "${implClassName}V8Internal::${funcName}MethodCallback, v8Undefined(), $signature"; |
- |
- AddToImplIncludes("core/page/Frame.h"); |
- AddToImplIncludes("bindings/v8/BindingSecurity.h"); |
- $implementation{nameSpaceInternal}->add(<<END); |
-static void ${funcName}AttrGetter(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info) |
-{ |
- // This is only for getting a unique pointer which we can pass to privateTemplate. |
- static const char* privateTemplateUniqueKey = "${funcName}PrivateTemplate"; |
- WrapperWorldType currentWorldType = worldType(info.GetIsolate()); |
- V8PerIsolateData* data = V8PerIsolateData::from(info.GetIsolate()); |
- v8::Handle<v8::FunctionTemplate> privateTemplate = data->privateTemplate(currentWorldType, &privateTemplateUniqueKey, $newTemplateParams, $functionLength); |
- |
- v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(${v8ClassName}::GetTemplate(info.GetIsolate(), currentWorldType)); |
- if (holder.IsEmpty()) { |
- // can only reach here by 'object.__proto__.func', and it should passed |
- // domain security check already |
- v8SetReturnValue(info, privateTemplate->GetFunction()); |
- return; |
- } |
- ${implClassName}* imp = ${v8ClassName}::toNative(holder); |
- if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame(), DoNotReportSecurityError)) { |
- static const char* sharedTemplateUniqueKey = "${funcName}SharedTemplate"; |
- v8::Handle<v8::FunctionTemplate> sharedTemplate = data->privateTemplate(currentWorldType, &sharedTemplateUniqueKey, $newTemplateParams, $functionLength); |
- v8SetReturnValue(info, sharedTemplate->GetFunction()); |
- return; |
- } |
- |
- v8::Local<v8::Value> hiddenValue = info.This()->GetHiddenValue(name); |
- if (!hiddenValue.IsEmpty()) { |
- v8SetReturnValue(info, hiddenValue); |
- return; |
- } |
- |
- v8SetReturnValue(info, privateTemplate->GetFunction()); |
-} |
- |
-END |
- $implementation{nameSpaceInternal}->add(<<END); |
-static void ${funcName}AttrGetterCallback(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info) |
-{ |
- TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMGetter"); |
- ${implClassName}V8Internal::${funcName}AttrGetter(name, info); |
- TRACE_EVENT_SET_SAMPLING_STATE("V8", "Execution"); |
-} |
- |
-END |
-} |
- |
-sub GenerateDomainSafeFunctionSetter |
-{ |
- my $interface = shift; |
- |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- |
- AddToImplIncludes("bindings/v8/BindingSecurity.h"); |
- $implementation{nameSpaceInternal}->add(<<END); |
-static void ${implClassName}DomainSafeFunctionSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) |
-{ |
- v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(${v8ClassName}::GetTemplate(info.GetIsolate(), worldType(info.GetIsolate()))); |
- if (holder.IsEmpty()) |
- return; |
- ${implClassName}* imp = ${v8ClassName}::toNative(holder); |
- if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame())) |
- return; |
- |
- info.This()->SetHiddenValue(name, value); |
-} |
- |
-END |
-} |
- |
-sub GenerateConstructorGetter |
-{ |
- my $interface = shift; |
- my $implClassName = GetImplName($interface); |
- |
- $implementation{nameSpaceInternal}->add(<<END); |
-static void ${implClassName}ConstructorGetter(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info) |
-{ |
- v8::Handle<v8::Value> data = info.Data(); |
- ASSERT(data->IsExternal()); |
- V8PerContextData* perContextData = V8PerContextData::from(info.Holder()->CreationContext()); |
- if (!perContextData) |
- return; |
- v8SetReturnValue(info, perContextData->constructorForType(WrapperTypeInfo::unwrap(data))); |
-} |
-END |
-} |
- |
-sub GenerateFeatureObservation |
-{ |
- my $measureAs = shift; |
- |
- if ($measureAs) { |
- AddToImplIncludes("core/page/UseCounter.h"); |
- return " UseCounter::count(activeDOMWindow(), UseCounter::${measureAs});\n"; |
- } |
- |
- return ""; |
-} |
- |
-sub GenerateDeprecationNotification |
-{ |
- my $deprecateAs = shift; |
- if ($deprecateAs) { |
- AddToImplIncludes("core/page/PageConsole.h"); |
- AddToImplIncludes("core/page/UseCounter.h"); |
- return " UseCounter::countDeprecation(activeDOMWindow(), UseCounter::${deprecateAs});\n"; |
- } |
- return ""; |
-} |
- |
-sub GenerateActivityLogging |
-{ |
- my $accessType = shift; |
- my $interface = shift; |
- my $propertyName = shift; |
- |
- my $interfaceName = $interface->name; |
- |
- AddToImplIncludes("bindings/v8/V8Binding.h"); |
- AddToImplIncludes("bindings/v8/V8DOMActivityLogger.h"); |
- AddToImplIncludes("wtf/Vector.h"); |
- |
- my $code = ""; |
- if ($accessType eq "Method") { |
- $code .= <<END; |
- V8PerContextData* contextData = V8PerContextData::from(args.GetIsolate()->GetCurrentContext()); |
- if (contextData && contextData->activityLogger()) { |
- Vector<v8::Handle<v8::Value> > loggerArgs = toVectorOfArguments(args); |
- contextData->activityLogger()->log("${interfaceName}.${propertyName}", args.Length(), loggerArgs.data(), "${accessType}"); |
- } |
-END |
- } elsif ($accessType eq "Setter") { |
- $code .= <<END; |
- V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->GetCurrentContext()); |
- if (contextData && contextData->activityLogger()) { |
- v8::Handle<v8::Value> loggerArg[] = { value }; |
- contextData->activityLogger()->log("${interfaceName}.${propertyName}", 1, &loggerArg[0], "${accessType}"); |
- } |
-END |
- } elsif ($accessType eq "Getter") { |
- $code .= <<END; |
- V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->GetCurrentContext()); |
- if (contextData && contextData->activityLogger()) |
- contextData->activityLogger()->log("${interfaceName}.${propertyName}", 0, 0, "${accessType}"); |
-END |
- } else { |
- die "Unrecognized activity logging access type"; |
- } |
- |
- return $code; |
-} |
- |
-sub GenerateNormalAttrGetterCallback |
-{ |
- my $attribute = shift; |
- my $interface = shift; |
- my $forMainWorldSuffix = shift; |
- |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- my $attrExt = $attribute->extendedAttributes; |
- my $attrName = $attribute->name; |
- |
- my $conditionalString = GenerateConditionalString($attribute); |
- my $code = ""; |
- $code .= "#if ${conditionalString}\n\n" if $conditionalString; |
- |
- $code .= "static void ${attrName}AttrGetterCallback${forMainWorldSuffix}(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; |
- $code .= "{\n"; |
- $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMGetter\");\n"; |
- $code .= GenerateFeatureObservation($attrExt->{"MeasureAs"}); |
- $code .= GenerateDeprecationNotification($attrExt->{"DeprecateAs"}); |
- if (HasActivityLogging($forMainWorldSuffix, $attrExt, "Getter")) { |
- $code .= GenerateActivityLogging("Getter", $interface, "${attrName}"); |
- } |
- if (HasCustomGetter($attrExt)) { |
- $code .= " ${v8ClassName}::${attrName}AttrGetterCustom(name, info);\n"; |
- } else { |
- $code .= " ${implClassName}V8Internal::${attrName}AttrGetter${forMainWorldSuffix}(name, info);\n"; |
- } |
- $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; |
- $code .= "}\n\n"; |
- $code .= "#endif // ${conditionalString}\n\n" if $conditionalString; |
- |
- $implementation{nameSpaceInternal}->add($code); |
-} |
- |
-sub GenerateNormalAttrGetter |
-{ |
- my $attribute = shift; |
- my $interface = shift; |
- my $forMainWorldSuffix = shift; |
- |
- my $interfaceName = $interface->name; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- my $attrExt = $attribute->extendedAttributes; |
- my $attrName = $attribute->name; |
- my $attrType = $attribute->type; |
- |
- if (HasCustomGetter($attrExt)) { |
- return; |
- } |
- |
- AssertNotSequenceType($attrType); |
- my $getterStringUsesImp = $interfaceName ne "SVGNumber"; |
- my $nativeType = GetNativeType($attribute->type, $attribute->extendedAttributes, ""); |
- my $svgNativeType = GetSVGTypeNeedingTearOff($interfaceName); |
- |
- my $conditionalString = GenerateConditionalString($attribute); |
- my $code = ""; |
- $code .= "#if ${conditionalString}\n\n" if $conditionalString; |
- $code .= <<END; |
-static void ${attrName}AttrGetter${forMainWorldSuffix}(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info) |
-{ |
-END |
- if ($svgNativeType) { |
- my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($interfaceName); |
- if ($svgWrappedNativeType =~ /List/) { |
- $code .= <<END; |
- $svgNativeType* imp = ${v8ClassName}::toNative(info.Holder()); |
-END |
- } else { |
- $code .= <<END; |
- $svgNativeType* wrapper = ${v8ClassName}::toNative(info.Holder()); |
- $svgWrappedNativeType& impInstance = wrapper->propertyReference(); |
-END |
- if ($getterStringUsesImp) { |
- $code .= <<END; |
- $svgWrappedNativeType* imp = &impInstance; |
-END |
- } |
- } |
- } elsif ($attrExt->{"OnProto"} || $attrExt->{"Unforgeable"}) { |
- if ($interfaceName eq "Window") { |
- $code .= <<END; |
- v8::Handle<v8::Object> holder = info.Holder(); |
-END |
- } else { |
- # perform lookup first |
- $code .= <<END; |
- v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(${v8ClassName}::GetTemplate(info.GetIsolate(), worldType(info.GetIsolate()))); |
- if (holder.IsEmpty()) |
- return; |
-END |
- } |
- $code .= <<END; |
- ${implClassName}* imp = ${v8ClassName}::toNative(holder); |
-END |
- } else { |
- my $reflect = $attribute->extendedAttributes->{"Reflect"}; |
- my $url = $attribute->extendedAttributes->{"URL"}; |
- if ($getterStringUsesImp && $reflect && !$url && InheritsInterface($interface, "Node") && $attrType eq "DOMString") { |
- # Generate super-compact call for regular attribute getter: |
- my ($functionName, @arguments) = GetterExpression($interfaceName, $attribute); |
- $code .= " Element* imp = V8Element::toNative(info.Holder());\n"; |
- $code .= " v8SetReturnValue(info, v8String(imp->${functionName}(" . join(", ", @arguments) . "), info.GetIsolate(), ReturnUnsafeHandle));\n"; |
- $code .= " return;\n"; |
- $code .= "}\n\n"; |
- $code .= "#endif // ${conditionalString}\n\n" if $conditionalString; |
- $implementation{nameSpaceInternal}->add($code); |
- return; |
- # Skip the rest of the function! |
- } |
- if ($attribute->type eq "SerializedScriptValue" && $attrExt->{"CachedAttribute"}) { |
- $code .= <<END; |
- v8::Handle<v8::String> propertyName = v8::String::NewSymbol("${attrName}"); |
- v8::Handle<v8::Value> value = info.Holder()->GetHiddenValue(propertyName); |
- if (!value.IsEmpty()) { |
- v8SetReturnValue(info, value); |
- return; |
- } |
-END |
- } |
- if (!$attribute->isStatic) { |
- $code .= <<END; |
- ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()); |
-END |
- } |
- } |
- |
- # Generate security checks if necessary |
- if ($attribute->extendedAttributes->{"CheckSecurityForNode"}) { |
- AddToImplIncludes("bindings/v8/BindingSecurity.h"); |
- $code .= " if (!BindingSecurity::shouldAllowAccessToNode(imp->" . GetImplName($attribute) . "())) {\n"; |
- $code .= " v8SetReturnValueNull(info);\n"; |
- $code .= " return;\n"; |
- $code .= " }\n"; |
- } |
- |
- my $useExceptions = 1 if $attribute->extendedAttributes->{"GetterRaisesException"} || $attribute->extendedAttributes->{"RaisesException"}; |
- my $isNullable = $attribute->isNullable; |
- if ($useExceptions) { |
- AddToImplIncludes("core/dom/ExceptionCode.h"); |
- $code .= " ExceptionCode ec = 0;\n"; |
- } |
- |
- if ($isNullable) { |
- $code .= " bool isNull = false;\n"; |
- } |
- |
- my $returnType = $attribute->type; |
- my $getterString; |
- |
- if ($getterStringUsesImp) { |
- my ($functionName, @arguments) = GetterExpression($interfaceName, $attribute); |
- push(@arguments, "isNull") if $isNullable; |
- push(@arguments, "ec") if $useExceptions; |
- if ($attribute->extendedAttributes->{"ImplementedBy"}) { |
- my $implementedBy = $attribute->extendedAttributes->{"ImplementedBy"}; |
- my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy); |
- AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implementedByImplName)); |
- unshift(@arguments, "imp") if !$attribute->isStatic; |
- $functionName = "${implementedByImplName}::${functionName}"; |
- } elsif ($attribute->isStatic) { |
- $functionName = "${implClassName}::${functionName}"; |
- } else { |
- $functionName = "imp->${functionName}"; |
- } |
- my ($arg, $subCode) = GenerateCallWith($attribute->extendedAttributes->{"CallWith"}, " ", 0); |
- $code .= $subCode; |
- unshift(@arguments, @$arg); |
- $getterString = "${functionName}(" . join(", ", @arguments) . ")"; |
- } else { |
- $getterString = "impInstance"; |
- } |
- |
- my $expression; |
- if ($attribute->type eq "EventListener" && $interface->name eq "Window") { |
- $code .= " if (!imp->document())\n"; |
- $code .= " return;\n"; |
- } |
- |
- if ($useExceptions || $isNullable) { |
- if ($nativeType =~ /^V8StringResource/) { |
- $code .= " " . ConvertToV8StringResource($attribute, $nativeType, "v", $getterString) . ";\n"; |
- } else { |
- $code .= " $nativeType v = $getterString;\n"; |
- } |
- |
- if ($isNullable) { |
- $code .= " if (isNull) {\n"; |
- $code .= " v8SetReturnValueNull(info);\n"; |
- $code .= " return;\n"; |
- $code .= " }\n"; |
- } |
- |
- if ($useExceptions) { |
- $code .= " if (UNLIKELY(ec)) {\n"; |
- $code .= " setDOMException(ec, info.GetIsolate());\n"; |
- $code .= " return;\n"; |
- $code .= " };\n"; |
- |
- if (ExtendedAttributeContains($attribute->extendedAttributes->{"CallWith"}, "ScriptState")) { |
- $code .= " if (state.hadException()) {\n"; |
- $code .= " throwError(state.exception(), info.GetIsolate());\n"; |
- $code .= " return;\n"; |
- $code .= " }\n"; |
- } |
- } |
- |
- $expression = "v"; |
- $expression .= ".release()" if (IsRefPtrType($returnType)); |
- } else { |
- # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary |
- $expression = $getterString; |
- # Fix amigious conversion problem, by casting to the base type first ($getterString returns a type that inherits from SVGAnimatedEnumeration, not the base class directly). |
- $expression = "static_pointer_cast<SVGAnimatedEnumeration>($expression)" if $returnType eq "SVGAnimatedEnumeration"; |
- } |
- |
- if (ShouldKeepAttributeAlive($interface, $attribute, $returnType)) { |
- my $arrayType = GetArrayType($returnType); |
- if ($arrayType) { |
- AddIncludeForType("V8$arrayType.h"); |
- $code .= " v8SetReturnValue(info, v8Array(${getterString}, info.GetIsolate()));\n"; |
- $code .= " return;\n"; |
- $code .= "}\n\n"; |
- $implementation{nameSpaceInternal}->add($code); |
- return; |
- } |
- |
- AddIncludesForType($returnType); |
- AddToImplIncludes("bindings/v8/V8HiddenPropertyName.h"); |
- # 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. |
- my $nativeReturnType = GetNativeType($returnType); |
- $code .= " $nativeReturnType result = ${getterString};\n"; |
- if ($forMainWorldSuffix) { |
- $code .= " v8::Handle<v8::Value> wrapper = result.get() ? v8::Handle<v8::Value>(DOMDataStore::getWrapper${forMainWorldSuffix}(result.get())) : v8Undefined();\n"; |
- } else { |
- $code .= " v8::Handle<v8::Value> wrapper = result.get() ? v8::Handle<v8::Value>(DOMDataStore::getWrapper(result.get(), info.GetIsolate())) : v8Undefined();\n"; |
- } |
- $code .= " if (wrapper.IsEmpty()) {\n"; |
- $code .= " wrapper = toV8(result.get(), info.Holder(), info.GetIsolate());\n"; # FIXME: Could use wrap here since the wrapper is empty. |
- $code .= " if (!wrapper.IsEmpty())\n"; |
- $code .= " V8HiddenPropertyName::setNamedHiddenReference(info.Holder(), \"${attrName}\", wrapper);\n"; |
- $code .= " }\n"; |
- $code .= " v8SetReturnValue(info, wrapper);\n"; |
- $code .= " return;\n"; |
- $code .= "}\n\n"; |
- $code .= "#endif // ${conditionalString}\n\n" if $conditionalString; |
- $implementation{nameSpaceInternal}->add($code); |
- return; |
- } |
- |
- if ((IsSVGAnimatedType($interfaceName) or $interfaceName eq "SVGViewSpec") and IsSVGTypeNeedingTearOff($attrType)) { |
- AddToImplIncludes("V8$attrType.h"); |
- my $svgNativeType = GetSVGTypeNeedingTearOff($attrType); |
- # Convert from abstract SVGProperty to real type, so the right toJS() method can be invoked. |
- $code .= " v8SetReturnValue(info, toV8Fast$forMainWorldSuffix(static_cast<$svgNativeType*>($expression), info, imp));\n"; |
- $code .= " return;\n"; |
- } elsif (IsSVGTypeNeedingTearOff($attrType) and not $interfaceName =~ /List$/) { |
- AddToImplIncludes("V8$attrType.h"); |
- AddToImplIncludes("core/svg/properties/SVGPropertyTearOff.h"); |
- my $tearOffType = GetSVGTypeNeedingTearOff($attrType); |
- my $wrappedValue; |
- if (IsSVGTypeWithWritablePropertiesNeedingTearOff($attrType) and not defined $attribute->extendedAttributes->{"Immutable"}) { |
- my $getter = $expression; |
- $getter =~ s/imp->//; |
- $getter =~ s/\(\)//; |
- |
- my $updateMethod = "&${implClassName}::update" . FirstLetterToUpperCase($getter); |
- |
- my $selfIsTearOffType = IsSVGTypeNeedingTearOff($interfaceName); |
- if ($selfIsTearOffType) { |
- AddToImplIncludes("core/svg/properties/SVGStaticPropertyWithParentTearOff.h"); |
- $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyWithParentTearOff<$implClassName, /; |
- |
- if ($expression =~ /matrix/ and $interfaceName 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. |
- $expression =~ s/matrix/svgMatrix/; |
- } |
- |
- $wrappedValue = "WTF::getPtr(${tearOffType}::create(wrapper, $expression, $updateMethod))"; |
- } else { |
- AddToImplIncludes("core/svg/properties/SVGStaticPropertyTearOff.h"); |
- $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyTearOff<$implClassName, /; |
- |
- $wrappedValue = "WTF::getPtr(${tearOffType}::create(imp, $expression, $updateMethod))"; |
- } |
- } elsif ($tearOffType =~ /SVGStaticListPropertyTearOff/) { |
- $wrappedValue = "WTF::getPtr(${tearOffType}::create(imp, $expression))"; |
- } elsif ($tearOffType =~ /SVG(Point|PathSeg)List/) { |
- $wrappedValue = "WTF::getPtr($expression)"; |
- } else { |
- $wrappedValue = "WTF::getPtr(${tearOffType}::create($expression))"; |
- } |
- $code .= " v8SetReturnValue(info, toV8Fast$forMainWorldSuffix($wrappedValue, info, imp));\n"; |
- $code .= " return;\n"; |
- } elsif ($attribute->type eq "SerializedScriptValue" && $attrExt->{"CachedAttribute"}) { |
- my $getterFunc = ToMethodName($attribute->name); |
- $code .= <<END; |
- RefPtr<SerializedScriptValue> serialized = imp->${getterFunc}(); |
- value = serialized ? serialized->deserialize() : v8::Handle<v8::Value>(v8::Null(info.GetIsolate())); |
- info.Holder()->SetHiddenValue(propertyName, value); |
- v8SetReturnValue(info, value); |
- return; |
-END |
- } elsif ($attribute->type eq "EventListener") { |
- AddToImplIncludes("bindings/v8/V8AbstractEventListener.h"); |
- my $getterFunc = ToMethodName($attribute->name); |
- # FIXME: Pass the main world ID for main-world-only getters. |
- $code .= " EventListener* listener = imp->${getterFunc}(isolatedWorldForIsolate(info.GetIsolate()));\n"; |
- $code .= " v8SetReturnValue(info, listener ? v8::Handle<v8::Value>(V8AbstractEventListener::cast(listener)->getListenerObject(imp->scriptExecutionContext())) : v8::Handle<v8::Value>(v8::Null(info.GetIsolate())));\n"; |
- $code .= " return;\n"; |
- } else { |
- my $nativeValue = NativeToJSValue($attribute->type, $attribute->extendedAttributes, $expression, " ", "", "info.Holder()", "info.GetIsolate()", "info", "imp", "ReturnUnsafeHandle", $forMainWorldSuffix, "return"); |
- $code .= "${nativeValue}\n"; |
- $code .= " return;\n"; |
- } |
- |
- $code .= "}\n\n"; # end of getter |
- $code .= "#endif // ${conditionalString}\n\n" if $conditionalString; |
- $implementation{nameSpaceInternal}->add($code); |
-} |
- |
-sub ShouldKeepAttributeAlive |
-{ |
- my ($interface, $attribute, $returnType) = @_; |
- my $attrName = $attribute->name; |
- |
- return 1 if $attribute->extendedAttributes->{"KeepAttributeAliveForGC"}; |
- |
- # Basically, for readonly or replaceable attributes, we have to guarantee |
- # that JS wrappers don't get garbage-collected prematually when their |
- # lifetime is strongly tied to their owner. |
- return 0 if !IsWrapperType($returnType); |
- return 0 if !IsReadonly($attribute) && !$attribute->extendedAttributes->{"Replaceable"}; |
- |
- # However, there are a couple of exceptions. |
- |
- # Node lifetime is managed by object grouping. |
- return 0 if InheritsInterface($interface, "Node"); |
- return 0 if IsDOMNodeType($returnType); |
- |
- # To avoid adding a reference to itself. |
- # FIXME: Introduce [DoNotKeepAttributeAliveForGC] and remove this hack |
- # depending on the attribute name. |
- return 0 if $attrName eq "self"; |
- |
- # FIXME: Remove these hard-coded hacks. |
- return 0 if $returnType eq "EventTarget"; |
- return 0 if $returnType eq "SerializedScriptValue"; |
- return 0 if $returnType eq "Window"; |
- return 0 if $returnType =~ /SVG/; |
- return 0 if $returnType =~ /HTML/; |
- |
- return 1; |
-} |
- |
-sub GenerateReplaceableAttrSetterCallback |
-{ |
- my $interface = shift; |
- my $implClassName = GetImplName($interface); |
- |
- my $code = ""; |
- $code .= "static void ${implClassName}ReplaceableAttrSetterCallback(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)\n"; |
- $code .= "{\n"; |
- $code .= GenerateFeatureObservation($interface->extendedAttributes->{"MeasureAs"}); |
- $code .= GenerateDeprecationNotification($interface->extendedAttributes->{"DeprecateAs"}); |
- $code .= GenerateCustomElementInvocationScopeIfNeeded($interface->extendedAttributes); |
- if (HasActivityLogging("", $interface->extendedAttributes, "Setter")) { |
- die "IDL error: ActivityLog attribute cannot exist on a ReplacableAttrSetterCallback"; |
- } |
- $code .= " ${implClassName}V8Internal::${implClassName}ReplaceableAttrSetter(name, value, info);\n"; |
- $code .= "}\n\n"; |
- $implementation{nameSpaceInternal}->add($code); |
-} |
- |
-sub GenerateReplaceableAttrSetter |
-{ |
- my $interface = shift; |
- |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- |
- my $code = ""; |
- $code .= <<END; |
-static void ${implClassName}ReplaceableAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) |
-{ |
-END |
- if ($interface->extendedAttributes->{"CheckSecurity"}) { |
- AddToImplIncludes("core/page/Frame.h"); |
- AddToImplIncludes("bindings/v8/BindingSecurity.h"); |
- $code .= <<END; |
- ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()); |
- if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame())) |
- return; |
-END |
- } |
- |
- $code .= <<END; |
- info.This()->ForceSet(name, value); |
-} |
- |
-END |
- $implementation{nameSpaceInternal}->add($code); |
-} |
- |
-sub GenerateCustomElementInvocationScopeIfNeeded |
-{ |
- my $code = ""; |
- my $ext = shift; |
- |
- if ($ext->{"DeliverCustomElementCallbacks"} or $ext->{"Reflect"}) { |
- AddToImplIncludes("core/dom/CustomElementCallbackDispatcher.h"); |
- $code .= <<END; |
- CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope; |
-END |
- } |
- return $code; |
-} |
- |
-sub GenerateNormalAttrSetterCallback |
-{ |
- my $attribute = shift; |
- my $interface = shift; |
- my $forMainWorldSuffix = shift; |
- |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- my $attrExt = $attribute->extendedAttributes; |
- my $attrName = $attribute->name; |
- |
- my $conditionalString = GenerateConditionalString($attribute); |
- my $code = ""; |
- $code .= "#if ${conditionalString}\n\n" if $conditionalString; |
- |
- $code .= "static void ${attrName}AttrSetterCallback${forMainWorldSuffix}(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)\n"; |
- $code .= "{\n"; |
- $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMSetter\");\n"; |
- $code .= GenerateFeatureObservation($attrExt->{"MeasureAs"}); |
- $code .= GenerateDeprecationNotification($attrExt->{"DeprecateAs"}); |
- if (HasActivityLogging($forMainWorldSuffix, $attrExt, "Setter")) { |
- $code .= GenerateActivityLogging("Setter", $interface, "${attrName}"); |
- } |
- $code .= GenerateCustomElementInvocationScopeIfNeeded($attrExt); |
- if (HasCustomSetter($attrExt)) { |
- $code .= " ${v8ClassName}::${attrName}AttrSetterCustom(name, value, info);\n"; |
- } else { |
- $code .= " ${implClassName}V8Internal::${attrName}AttrSetter${forMainWorldSuffix}(name, value, info);\n"; |
- } |
- $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; |
- $code .= "}\n\n"; |
- $code .= "#endif // ${conditionalString}\n\n" if $conditionalString; |
- $implementation{nameSpaceInternal}->add($code); |
-} |
- |
-sub GenerateNormalAttrSetter |
-{ |
- my $attribute = shift; |
- my $interface = shift; |
- my $forMainWorldSuffix = shift; |
- |
- my $interfaceName = $interface->name; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- my $attrName = $attribute->name; |
- my $attrExt = $attribute->extendedAttributes; |
- my $attrType = $attribute->type; |
- |
- if (HasCustomSetter($attrExt)) { |
- return; |
- } |
- |
- my $conditionalString = GenerateConditionalString($attribute); |
- my $code = ""; |
- $code .= "#if ${conditionalString}\n\n" if $conditionalString; |
- $code .= "static void ${attrName}AttrSetter${forMainWorldSuffix}(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)\n"; |
- $code .= "{\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->extendedAttributes->{"StrictTypeChecking"}) { |
- my $argType = $attribute->type; |
- if (IsWrapperType($argType)) { |
- $code .= " if (!isUndefinedOrNull(value) && !V8${argType}::HasInstance(value, info.GetIsolate(), worldType(info.GetIsolate()))) {\n"; |
- $code .= " throwTypeError(0, info.GetIsolate());\n"; |
- $code .= " return;\n"; |
- $code .= " }\n"; |
- } |
- } |
- |
- my $svgNativeType = GetSVGTypeNeedingTearOff($interfaceName); |
- if ($svgNativeType) { |
- my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($interfaceName); |
- if ($svgWrappedNativeType =~ /List$/) { |
- $code .= <<END; |
- $svgNativeType* imp = ${v8ClassName}::toNative(info.Holder()); |
-END |
- } else { |
- AddToImplIncludes("core/dom/ExceptionCode.h"); |
- $code .= " $svgNativeType* wrapper = ${v8ClassName}::toNative(info.Holder());\n"; |
- $code .= " if (wrapper->isReadOnly()) {\n"; |
- $code .= " setDOMException(NoModificationAllowedError, info.GetIsolate());\n"; |
- $code .= " return;\n"; |
- $code .= " }\n"; |
- $code .= " $svgWrappedNativeType& impInstance = wrapper->propertyReference();\n"; |
- $code .= " $svgWrappedNativeType* imp = &impInstance;\n"; |
- } |
- } elsif ($attrExt->{"OnProto"}) { |
- $code .= <<END; |
- ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()); |
-END |
- } else { |
- my $reflect = $attribute->extendedAttributes->{"Reflect"}; |
- if ($reflect && InheritsInterface($interface, "Node") && $attrType eq "DOMString") { |
- # Generate super-compact call for regular attribute setter: |
- my $contentAttributeName = $reflect eq "VALUE_IS_MISSING" ? lc $attrName : $reflect; |
- my $namespace = NamespaceForAttributeName($interfaceName, $contentAttributeName); |
- AddToImplIncludes("${namespace}.h"); |
- $code .= " Element* imp = V8Element::toNative(info.Holder());\n"; |
- $code .= " V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, stringResource, value);\n"; |
- $code .= " imp->setAttribute(${namespace}::${contentAttributeName}Attr, stringResource);\n"; |
- $code .= "}\n\n"; |
- $code .= "#endif // ${conditionalString}\n\n" if $conditionalString; |
- $implementation{nameSpaceInternal}->add($code); |
- return; |
- # Skip the rest of the function! |
- } |
- |
- if (!$attribute->isStatic) { |
- $code .= <<END; |
- ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()); |
-END |
- } |
- } |
- |
- my $nativeType = GetNativeType($attribute->type, $attribute->extendedAttributes, "parameter"); |
- if ($attribute->type eq "EventListener") { |
- if ($interface->name eq "Window") { |
- $code .= " if (!imp->document())\n"; |
- $code .= " return;\n"; |
- } |
- } else { |
- $code .= JSValueToNativeStatement($attribute->type, $attribute->extendedAttributes, "value", "v", " ", "info.GetIsolate()"); |
- } |
- |
- if (IsEnumType($attrType)) { |
- # setter ignores invalid enumeration values |
- my @enumValues = ValidEnumValues($attrType); |
- my @validEqualities = (); |
- foreach my $enumValue (@enumValues) { |
- push(@validEqualities, "string == \"$enumValue\""); |
- } |
- my $enumValidationExpression = join(" || ", @validEqualities); |
- $code .= <<END; |
- String string = v; |
- if (!($enumValidationExpression)) |
- return; |
-END |
- } |
- |
- my $expression = "v"; |
- my $returnType = $attribute->type; |
- if (IsRefPtrType($returnType) && !GetArrayType($returnType)) { |
- $expression = "WTF::getPtr(" . $expression . ")"; |
- } |
- |
- $code .= GenerateCustomElementInvocationScopeIfNeeded($attribute->extendedAttributes); |
- |
- my $useExceptions = 1 if $attribute->extendedAttributes->{"SetterRaisesException"} || $attribute->extendedAttributes->{"RaisesException"}; |
- |
- if ($useExceptions) { |
- AddToImplIncludes("core/dom/ExceptionCode.h"); |
- $code .= " ExceptionCode ec = 0;\n"; |
- } |
- |
- if ($interfaceName eq "SVGNumber") { |
- $code .= " *imp = $expression;\n"; |
- } else { |
- if ($attribute->type eq "EventListener") { |
- my $implSetterFunctionName = FirstLetterToUpperCase($attrName); |
- AddToImplIncludes("bindings/v8/V8AbstractEventListener.h"); |
- if (!InheritsInterface($interface, "Node")) { |
- my $attrImplName = GetImplName($attribute); |
- $code .= " transferHiddenDependency(info.Holder(), imp->${attrImplName}(isolatedWorldForIsolate(info.GetIsolate())), value, ${v8ClassName}::eventListenerCacheIndex, info.GetIsolate());\n"; |
- } |
- AddToImplIncludes("bindings/v8/V8EventListenerList.h"); |
- if (($interfaceName eq "Window" or $interfaceName eq "WorkerGlobalScope") and $attribute->name eq "onerror") { |
- AddToImplIncludes("bindings/v8/V8ErrorHandler.h"); |
- $code .= " imp->set$implSetterFunctionName(V8EventListenerList::findOrCreateWrapper<V8ErrorHandler>(value, true), isolatedWorldForIsolate(info.GetIsolate()));\n"; |
- } else { |
- $code .= " imp->set$implSetterFunctionName(V8EventListenerList::getEventListener(value, true, ListenerFindOrCreate), isolatedWorldForIsolate(info.GetIsolate()));\n"; |
- } |
- } else { |
- my ($functionName, @arguments) = SetterExpression($interfaceName, $attribute); |
- push(@arguments, $expression); |
- push(@arguments, "ec") if $useExceptions; |
- if ($attribute->extendedAttributes->{"ImplementedBy"}) { |
- my $implementedBy = $attribute->extendedAttributes->{"ImplementedBy"}; |
- my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy); |
- AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implementedByImplName)); |
- unshift(@arguments, "imp") if !$attribute->isStatic; |
- $functionName = "${implementedByImplName}::${functionName}"; |
- } elsif ($attribute->isStatic) { |
- $functionName = "${implClassName}::${functionName}"; |
- } else { |
- $functionName = "imp->${functionName}"; |
- } |
- my ($arg, $subCode) = GenerateCallWith($attribute->extendedAttributes->{"SetterCallWith"} || $attribute->extendedAttributes->{"CallWith"}, " ", 1); |
- $code .= $subCode; |
- unshift(@arguments, @$arg); |
- $code .= " ${functionName}(" . join(", ", @arguments) . ");\n"; |
- } |
- } |
- |
- if ($useExceptions) { |
- $code .= " if (UNLIKELY(ec))\n"; |
- $code .= " setDOMException(ec, info.GetIsolate());\n"; |
- } |
- |
- if (ExtendedAttributeContains($attribute->extendedAttributes->{"CallWith"}, "ScriptState")) { |
- $code .= " if (state.hadException())\n"; |
- $code .= " throwError(state.exception(), info.GetIsolate());\n"; |
- } |
- |
- if ($svgNativeType) { |
- if ($useExceptions) { |
- $code .= " if (!ec)\n"; |
- $code .= " wrapper->commitChange();\n"; |
- } else { |
- $code .= " wrapper->commitChange();\n"; |
- } |
- } |
- |
- if ($attribute->type eq "SerializedScriptValue" && $attribute->extendedAttributes->{"CachedAttribute"}) { |
- $code .= <<END; |
- info.Holder()->DeleteHiddenValue(v8::String::NewSymbol("${attrName}")); // Invalidate the cached value. |
-END |
- } |
- |
- $code .= " return;\n"; |
- $code .= "}\n\n"; # end of setter |
- $code .= "#endif // ${conditionalString}\n\n" if $conditionalString; |
- $implementation{nameSpaceInternal}->add($code); |
-} |
- |
-sub GenerateParametersCheckExpression |
-{ |
- my $numParameters = shift; |
- my $function = shift; |
- |
- my @andExpression = (); |
- push(@andExpression, "args.Length() == $numParameters"); |
- my $parameterIndex = 0; |
- foreach my $parameter (@{$function->parameters}) { |
- last if $parameterIndex >= $numParameters; |
- my $value = "args[$parameterIndex]"; |
- my $type = $parameter->type; |
- |
- # Only DOMString or wrapper types are checked. |
- # For DOMString with StrictTypeChecking only Null, Undefined and Object |
- # are accepted for compatibility. Otherwise, no restrictions are made to |
- # match the non-overloaded behavior. |
- # FIXME: Implement WebIDL overload resolution algorithm. |
- if ($type eq "DOMString") { |
- if ($parameter->extendedAttributes->{"StrictTypeChecking"}) { |
- push(@andExpression, "(${value}->IsNull() || ${value}->IsUndefined() || ${value}->IsString() || ${value}->IsObject())"); |
- } |
- } elsif (IsCallbackInterface($parameter->type)) { |
- # For Callbacks only checks if the value is null or object. |
- push(@andExpression, "(${value}->IsNull() || ${value}->IsFunction())"); |
- } elsif (GetArrayOrSequenceType($type)) { |
- if ($parameter->isNullable) { |
- push(@andExpression, "(${value}->IsNull() || ${value}->IsArray())"); |
- } else { |
- push(@andExpression, "(${value}->IsArray())"); |
- } |
- } elsif (IsWrapperType($type)) { |
- if ($parameter->isNullable) { |
- push(@andExpression, "(${value}->IsNull() || V8${type}::HasInstance($value, args.GetIsolate(), worldType(args.GetIsolate())))"); |
- } else { |
- push(@andExpression, "(V8${type}::HasInstance($value, args.GetIsolate(), worldType(args.GetIsolate())))"); |
- } |
- } |
- |
- $parameterIndex++; |
- } |
- my $res = join(" && ", @andExpression); |
- $res = "($res)" if @andExpression > 1; |
- return $res; |
-} |
- |
-# As per Web IDL specification, the length of a function Object is |
-# its number of mandatory parameters. |
-sub GetFunctionLength |
-{ |
- my $function = shift; |
- |
- my $numMandatoryParams = 0; |
- foreach my $parameter (@{$function->parameters}) { |
- # Abort as soon as we find the first optional parameter as no mandatory |
- # parameter can follow an optional one. |
- last if $parameter->isOptional; |
- $numMandatoryParams++; |
- } |
- return $numMandatoryParams; |
-} |
- |
-sub GenerateFunctionParametersCheck |
-{ |
- my $function = shift; |
- |
- my @orExpression = (); |
- my $numParameters = 0; |
- my $hasVariadic = 0; |
- my $numMandatoryParams = @{$function->parameters}; |
- foreach my $parameter (@{$function->parameters}) { |
- if ($parameter->isOptional) { |
- push(@orExpression, GenerateParametersCheckExpression($numParameters, $function)); |
- $numMandatoryParams--; |
- } |
- if ($parameter->isVariadic) { |
- $hasVariadic = 1; |
- last; |
- } |
- $numParameters++; |
- } |
- if (!$hasVariadic) { |
- push(@orExpression, GenerateParametersCheckExpression($numParameters, $function)); |
- } |
- return ($numMandatoryParams, join(" || ", @orExpression)); |
-} |
- |
-sub GenerateOverloadedFunction |
-{ |
- my $function = shift; |
- my $interface = shift; |
- my $forMainWorldSuffix = 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->name; |
- |
- my $conditionalString = GenerateConditionalString($function); |
- my $leastNumMandatoryParams = 255; |
- my $code = ""; |
- $code .= "#if ${conditionalString}\n\n" if $conditionalString; |
- $code .= <<END; |
-static void ${name}Method${forMainWorldSuffix}(const v8::FunctionCallbackInfo<v8::Value>& args) |
-{ |
-END |
- $code .= GenerateFeatureObservation($function->extendedAttributes->{"MeasureAs"}); |
- $code .= GenerateDeprecationNotification($function->extendedAttributes->{"DeprecateAs"}); |
- |
- foreach my $overload (@{$function->{overloads}}) { |
- my ($numMandatoryParams, $parametersCheck) = GenerateFunctionParametersCheck($overload); |
- $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams < $leastNumMandatoryParams); |
- $code .= " if ($parametersCheck) {\n"; |
- my $overloadedIndexString = $overload->{overloadIndex}; |
- $code .= " ${name}${overloadedIndexString}Method${forMainWorldSuffix}(args);\n"; |
- $code .= " return;\n"; |
- $code .= " }\n"; |
- } |
- if ($leastNumMandatoryParams >= 1) { |
- $code .= " if (args.Length() < $leastNumMandatoryParams) {\n"; |
- $code .= " throwNotEnoughArgumentsError(args.GetIsolate());\n"; |
- $code .= " return;\n"; |
- $code .= " }\n"; |
- } |
- $code .= <<END; |
- throwTypeError(0, args.GetIsolate()); |
-END |
- $code .= "}\n\n"; |
- $code .= "#endif // ${conditionalString}\n\n" if $conditionalString; |
- $implementation{nameSpaceInternal}->add($code); |
-} |
- |
-sub GenerateFunctionCallback |
-{ |
- my $function = shift; |
- my $interface = shift; |
- my $forMainWorldSuffix = shift; |
- |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- my $name = $function->name; |
- |
- if ($name eq "") { |
- return; |
- } |
- |
- my $conditionalString = GenerateConditionalString($function); |
- my $code = ""; |
- $code .= "#if ${conditionalString}\n\n" if $conditionalString; |
- $code .= <<END; |
-static void ${name}MethodCallback${forMainWorldSuffix}(const v8::FunctionCallbackInfo<v8::Value>& args) |
-{ |
-END |
- $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMMethod\");\n"; |
- $code .= GenerateFeatureObservation($function->extendedAttributes->{"MeasureAs"}); |
- $code .= GenerateDeprecationNotification($function->extendedAttributes->{"DeprecateAs"}); |
- if (HasActivityLogging($forMainWorldSuffix, $function->extendedAttributes, "Access")) { |
- $code .= GenerateActivityLogging("Method", $interface, "${name}"); |
- } |
- if (HasCustomMethod($function->extendedAttributes)) { |
- $code .= " ${v8ClassName}::${name}MethodCustom(args);\n"; |
- } else { |
- $code .= " ${implClassName}V8Internal::${name}Method${forMainWorldSuffix}(args);\n"; |
- } |
- $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; |
- $code .= "}\n\n"; |
- $code .= "#endif // ${conditionalString}\n\n" if $conditionalString; |
- $implementation{nameSpaceInternal}->add($code); |
-} |
- |
-sub GenerateFunction |
-{ |
- my $function = shift; |
- my $interface = shift; |
- my $forMainWorldSuffix = shift; |
- |
- my $interfaceName = $interface->name; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- my $name = $function->name; |
- my $implName = GetImplName($function); |
- my $funcExt = $function->extendedAttributes; |
- |
- if (HasCustomMethod($funcExt) || $name eq "") { |
- return; |
- } |
- |
- if (@{$function->{overloads}} > 1) { |
- # Append a number to an overloaded method's name to make it unique: |
- $name = $name . $function->{overloadIndex}; |
- } |
- |
- my $conditionalString = GenerateConditionalString($function); |
- my $code = ""; |
- $code .= "#if ${conditionalString}\n\n" if $conditionalString; |
- $code .= "static void ${name}Method${forMainWorldSuffix}(const v8::FunctionCallbackInfo<v8::Value>& args)\n"; |
- $code .= "{\n"; |
- |
- if ($name eq "addEventListener" || $name eq "removeEventListener") { |
- my $lookupType = ($name eq "addEventListener") ? "OrCreate" : "Only"; |
- my $passRefPtrHandling = ($name eq "addEventListener") ? "" : ".get()"; |
- my $hiddenDependencyAction = ($name eq "addEventListener") ? "create" : "remove"; |
- |
- AddToImplIncludes("bindings/v8/V8EventListenerList.h"); |
- $code .= <<END; |
- RefPtr<EventListener> listener = V8EventListenerList::getEventListener(args[1], false, ListenerFind${lookupType}); |
- if (listener) { |
- V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, stringResource, args[0]); |
- ${v8ClassName}::toNative(args.Holder())->${implName}(stringResource, listener${passRefPtrHandling}, args[2]->BooleanValue()); |
-END |
- if (!InheritsInterface($interface, "Node")) { |
- $code .= <<END; |
- ${hiddenDependencyAction}HiddenDependency(args.Holder(), args[1], ${v8ClassName}::eventListenerCacheIndex, args.GetIsolate()); |
-END |
- } |
- $code .= <<END; |
- } |
-} |
- |
-END |
- $code .= "#endif // ${conditionalString}\n\n" if $conditionalString; |
- $implementation{nameSpaceInternal}->add($code); |
- return; |
- } |
- |
- $code .= GenerateArgumentsCountCheck($function, $interface); |
- |
- if ($name eq "set" and IsConstructorTemplate($interface, "TypedArray")) { |
- AddToImplIncludes("bindings/v8/custom/V8ArrayBufferViewCustom.h"); |
- $code .= <<END; |
- setWebGLArrayHelper<$implClassName, ${v8ClassName}>(args); |
-} |
- |
-END |
- $implementation{nameSpaceInternal}->add($code); |
- return; |
- } |
- |
- my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($interfaceName); |
- |
- if ($svgNativeType) { |
- my $nativeClassName = GetNativeType($interfaceName); |
- if ($interfaceName =~ /List$/) { |
- $code .= " $nativeClassName imp = ${v8ClassName}::toNative(args.Holder());\n"; |
- } else { |
- AddToImplIncludes("core/dom/ExceptionCode.h"); |
- $code .= " $nativeClassName wrapper = ${v8ClassName}::toNative(args.Holder());\n"; |
- $code .= " if (wrapper->isReadOnly()) {\n"; |
- $code .= " setDOMException(NoModificationAllowedError, args.GetIsolate());\n"; |
- $code .= " return;\n"; |
- $code .= " }\n"; |
- my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($interfaceName); |
- $code .= " $svgWrappedNativeType& impInstance = wrapper->propertyReference();\n"; |
- $code .= " $svgWrappedNativeType* imp = &impInstance;\n"; |
- } |
- } elsif (!$function->isStatic) { |
- $code .= <<END; |
- ${implClassName}* imp = ${v8ClassName}::toNative(args.Holder()); |
-END |
- } |
- |
- $code .= GenerateCustomElementInvocationScopeIfNeeded($funcExt); |
- |
- # Check domain security if needed |
- if ($interface->extendedAttributes->{"CheckSecurity"} && !$function->extendedAttributes->{"DoNotCheckSecurity"}) { |
- # We have not find real use cases yet. |
- AddToImplIncludes("core/page/Frame.h"); |
- AddToImplIncludes("bindings/v8/BindingSecurity.h"); |
- $code .= <<END; |
- if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame())) |
- return; |
-END |
- } |
- |
- my $raisesExceptions = $function->extendedAttributes->{"RaisesException"}; |
- if (!$raisesExceptions) { |
- foreach my $parameter (@{$function->parameters}) { |
- if ($parameter->extendedAttributes->{"IsIndex"}) { |
- $raisesExceptions = 1; |
- } |
- } |
- } |
- |
- if ($raisesExceptions) { |
- AddToImplIncludes("core/dom/ExceptionCode.h"); |
- $code .= " ExceptionCode ec = 0;\n"; |
- } |
- |
- if ($function->extendedAttributes->{"CheckSecurityForNode"}) { |
- AddToImplIncludes("bindings/v8/BindingSecurity.h"); |
- $code .= " if (!BindingSecurity::shouldAllowAccessToNode(imp->" . GetImplName($function) . "(ec))) {\n"; |
- $code .= " v8SetReturnValueNull(args);\n"; |
- $code .= " return;\n"; |
- $code .= " }\n"; |
-END |
- } |
- |
- my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersCheck($function, $interface, $forMainWorldSuffix); |
- $code .= $parameterCheckString; |
- |
- # Build the function call string. |
- $code .= GenerateFunctionCallString($function, $paramIndex, " ", $interface, $forMainWorldSuffix, %replacements); |
- $code .= "}\n\n"; |
- $code .= "#endif // ${conditionalString}\n\n" if $conditionalString; |
- $implementation{nameSpaceInternal}->add($code); |
-} |
- |
-sub GenerateCallWith |
-{ |
- my $callWith = shift; |
- return ([], "") unless $callWith; |
- my $indent = shift; |
- my $returnVoid = shift; |
- my $function = shift; |
- my $code = ""; |
- |
- my @callWithArgs; |
- if (ExtendedAttributeContains($callWith, "ScriptState")) { |
- $code .= $indent . "ScriptState* currentState = ScriptState::current();\n"; |
- $code .= $indent . "if (!currentState)\n"; |
- $code .= $indent . " return" . ($returnVoid ? "" : " v8Undefined()") . ";\n"; |
- $code .= $indent . "ScriptState& state = *currentState;\n"; |
- push(@callWithArgs, "&state"); |
- } |
- if (ExtendedAttributeContains($callWith, "ScriptExecutionContext")) { |
- $code .= $indent . "ScriptExecutionContext* scriptContext = getScriptExecutionContext();\n"; |
- push(@callWithArgs, "scriptContext"); |
- } |
- if ($function and ExtendedAttributeContains($callWith, "ScriptArguments")) { |
- $code .= $indent . "RefPtr<ScriptArguments> scriptArguments(createScriptArguments(args, " . @{$function->parameters} . "));\n"; |
- push(@callWithArgs, "scriptArguments.release()"); |
- AddToImplIncludes("bindings/v8/ScriptCallStackFactory.h"); |
- AddToImplIncludes("core/inspector/ScriptArguments.h"); |
- } |
- if (ExtendedAttributeContains($callWith, "ActiveWindow")) { |
- push(@callWithArgs, "activeDOMWindow()"); |
- } |
- if (ExtendedAttributeContains($callWith, "FirstWindow")) { |
- push(@callWithArgs, "firstDOMWindow()"); |
- } |
- return ([@callWithArgs], $code); |
-} |
- |
-sub GenerateArgumentsCountCheck |
-{ |
- my $function = shift; |
- my $interface = shift; |
- |
- my $numMandatoryParams = 0; |
- my $allowNonOptional = 1; |
- foreach my $param (@{$function->parameters}) { |
- if ($param->isOptional or $param->isVariadic) { |
- $allowNonOptional = 0; |
- } else { |
- die "An argument must not be declared to be optional unless all subsequent arguments to the operation are also optional." if !$allowNonOptional; |
- $numMandatoryParams++; |
- } |
- } |
- |
- my $argumentsCountCheckString = ""; |
- if ($numMandatoryParams >= 1) { |
- $argumentsCountCheckString .= " if (args.Length() < $numMandatoryParams) {\n"; |
- $argumentsCountCheckString .= " throwNotEnoughArgumentsError(args.GetIsolate());\n"; |
- $argumentsCountCheckString .= " return;\n"; |
- $argumentsCountCheckString .= " }\n"; |
- } |
- return $argumentsCountCheckString; |
-} |
- |
-sub GenerateParametersCheck |
-{ |
- my $function = shift; |
- my $interface = shift; |
- my $forMainWorldSuffix = shift; |
- my $style = shift || "new"; |
- |
- my $parameterCheckString = ""; |
- my $paramIndex = 0; |
- my %replacements = (); |
- |
- foreach my $parameter (@{$function->parameters}) { |
- my $nativeType = GetNativeType($parameter->type, $parameter->extendedAttributes, "parameter"); |
- |
- # Optional arguments without [Default=...] should generate an early call with fewer arguments. |
- # Optional arguments with [Optional=...] should not generate the early call. |
- # Optional Dictionary arguments always considered to have default of empty dictionary. |
- if ($parameter->isOptional && !$parameter->extendedAttributes->{"Default"} && $nativeType ne "Dictionary" && !IsCallbackInterface($parameter->type)) { |
- $parameterCheckString .= " if (args.Length() <= $paramIndex)"; |
- my $functionCall = GenerateFunctionCallString($function, $paramIndex, " " x 2, $interface, $forMainWorldSuffix, %replacements); |
- my $multiLine = ($functionCall =~ tr/\n//) > 1; |
- $parameterCheckString .= $multiLine ? " {\n" : "\n"; |
- $parameterCheckString .= $functionCall; |
- $parameterCheckString .= $multiLine ? " }\n" : "\n"; |
- } |
- |
- my $parameterDefaultPolicy = "DefaultIsUndefined"; |
- my $default = defined $parameter->extendedAttributes->{"Default"} ? $parameter->extendedAttributes->{"Default"} : ""; |
- if ($parameter->isOptional and $default eq "NullString") { |
- $parameterDefaultPolicy = "DefaultIsNullString"; |
- } |
- |
- my $parameterName = $parameter->name; |
- AddToImplIncludes("core/dom/ExceptionCode.h"); |
- if (IsCallbackInterface($parameter->type)) { |
- my $v8ClassName = "V8" . $parameter->type; |
- AddToImplIncludes("$v8ClassName.h"); |
- if ($parameter->isOptional) { |
- $parameterCheckString .= " RefPtr<" . $parameter->type . "> $parameterName;\n"; |
- $parameterCheckString .= " if (args.Length() > $paramIndex && !args[$paramIndex]->IsNull() && !args[$paramIndex]->IsUndefined()) {\n"; |
- $parameterCheckString .= " if (!args[$paramIndex]->IsFunction()) {\n"; |
- $parameterCheckString .= " throwTypeError(0, args.GetIsolate());\n"; |
- $parameterCheckString .= " return;\n"; |
- $parameterCheckString .= " }\n"; |
- $parameterCheckString .= " $parameterName = ${v8ClassName}::create(args[$paramIndex], getScriptExecutionContext());\n"; |
- $parameterCheckString .= " }\n"; |
- } else { |
- $parameterCheckString .= " if (args.Length() <= $paramIndex || !args[$paramIndex]->IsFunction()) {\n"; |
- $parameterCheckString .= " throwTypeError(0, args.GetIsolate());\n"; |
- $parameterCheckString .= " return;\n"; |
- $parameterCheckString .= " }\n"; |
- $parameterCheckString .= " RefPtr<" . $parameter->type . "> $parameterName = ${v8ClassName}::create(args[$paramIndex], getScriptExecutionContext());\n"; |
- } |
- } elsif ($parameter->extendedAttributes->{"Clamp"}) { |
- my $nativeValue = "${parameterName}NativeValue"; |
- my $paramType = $parameter->type; |
- $parameterCheckString .= " $paramType $parameterName = 0;\n"; |
- $parameterCheckString .= " V8TRYCATCH_VOID(double, $nativeValue, args[$paramIndex]->NumberValue());\n"; |
- $parameterCheckString .= " if (!std::isnan($nativeValue))\n"; |
- $parameterCheckString .= " $parameterName = clampTo<$paramType>($nativeValue);\n"; |
- } elsif ($parameter->type eq "SerializedScriptValue") { |
- AddToImplIncludes("bindings/v8/SerializedScriptValue.h"); |
- $parameterCheckString .= " bool ${parameterName}DidThrow = false;\n"; |
- $parameterCheckString .= " $nativeType $parameterName = SerializedScriptValue::create(args[$paramIndex], 0, 0, ${parameterName}DidThrow, args.GetIsolate());\n"; |
- $parameterCheckString .= " if (${parameterName}DidThrow)\n"; |
- $parameterCheckString .= " return;\n"; |
- } elsif ($parameter->isVariadic) { |
- my $nativeElementType = GetNativeType($parameter->type); |
- if ($nativeElementType =~ />$/) { |
- $nativeElementType .= " "; |
- } |
- |
- my $argType = $parameter->type; |
- if (IsWrapperType($argType)) { |
- $parameterCheckString .= " Vector<$nativeElementType> $parameterName;\n"; |
- $parameterCheckString .= " for (int i = $paramIndex; i < args.Length(); ++i) {\n"; |
- $parameterCheckString .= " if (!V8${argType}::HasInstance(args[i], args.GetIsolate(), worldType(args.GetIsolate()))) {\n"; |
- $parameterCheckString .= " throwTypeError(0, args.GetIsolate());\n"; |
- $parameterCheckString .= " return;\n"; |
- $parameterCheckString .= " }\n"; |
- $parameterCheckString .= " $parameterName.append(V8${argType}::toNative(v8::Handle<v8::Object>::Cast(args[i])));\n"; |
- $parameterCheckString .= " }\n"; |
- } else { |
- $parameterCheckString .= " V8TRYCATCH_VOID(Vector<$nativeElementType>, $parameterName, toNativeArguments<$nativeElementType>(args, $paramIndex));\n"; |
- } |
- } elsif ($nativeType =~ /^V8StringResource/) { |
- my $default = defined $parameter->extendedAttributes->{"Default"} ? $parameter->extendedAttributes->{"Default"} : ""; |
- my $jsValue = $parameter->isOptional && $default eq "NullString" ? "argumentOrNull(args, $paramIndex)" : "args[$paramIndex]"; |
- $parameterCheckString .= JSValueToNativeStatement($parameter->type, $parameter->extendedAttributes, $jsValue, $parameterName, " ", "args.GetIsolate()"); |
- if (IsEnumType($parameter->type)) { |
- my @enumValues = ValidEnumValues($parameter->type); |
- my @validEqualities = (); |
- foreach my $enumValue (@enumValues) { |
- push(@validEqualities, "string == \"$enumValue\""); |
- } |
- my $enumValidationExpression = join(" || ", @validEqualities); |
- $parameterCheckString .= " String string = $parameterName;\n"; |
- $parameterCheckString .= " if (!($enumValidationExpression)) {\n"; |
- $parameterCheckString .= " throwTypeError(0, args.GetIsolate());\n"; |
- $parameterCheckString .= " return;\n"; |
- $parameterCheckString .= " }\n"; |
- } |
- } else { |
- # 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->extendedAttributes->{"StrictTypeChecking"}) { |
- my $argValue = "args[$paramIndex]"; |
- my $argType = $parameter->type; |
- if (IsWrapperType($argType)) { |
- $parameterCheckString .= " if (args.Length() > $paramIndex && !isUndefinedOrNull($argValue) && !V8${argType}::HasInstance($argValue, args.GetIsolate(), worldType(args.GetIsolate()))) {\n"; |
- $parameterCheckString .= " throwTypeError(0, args.GetIsolate());\n"; |
- $parameterCheckString .= " return;\n"; |
- $parameterCheckString .= " }\n"; |
- } |
- } |
- my $default = defined $parameter->extendedAttributes->{"Default"} ? $parameter->extendedAttributes->{"Default"} : ""; |
- my $jsValue = $parameter->isOptional && $default eq "NullString" ? "argumentOrNull(args, $paramIndex)" : "args[$paramIndex]"; |
- $parameterCheckString .= JSValueToNativeStatement($parameter->type, $parameter->extendedAttributes, $jsValue, $parameterName, " ", "args.GetIsolate()"); |
- if ($nativeType eq 'Dictionary') { |
- $parameterCheckString .= " if (!$parameterName.isUndefinedOrNull() && !$parameterName.isObject()) {\n"; |
- $parameterCheckString .= " throwTypeError(\"Not an object.\", args.GetIsolate());\n"; |
- $parameterCheckString .= " return;\n"; |
- $parameterCheckString .= " }\n"; |
- } |
- } |
- |
- if ($parameter->extendedAttributes->{"IsIndex"}) { |
- $parameterCheckString .= " if (UNLIKELY($parameterName < 0)) {\n"; |
- $parameterCheckString .= " setDOMException(IndexSizeError, args.GetIsolate());\n"; |
- $parameterCheckString .= " return;\n"; |
- $parameterCheckString .= " }\n"; |
- } |
- |
- $paramIndex++; |
- } |
- return ($parameterCheckString, $paramIndex, %replacements); |
-} |
- |
-sub GenerateOverloadedConstructorCallback |
-{ |
- my $interface = shift; |
- my $implClassName = GetImplName($interface); |
- |
- my $code = ""; |
- $code .= <<END; |
-static void constructor(const v8::FunctionCallbackInfo<v8::Value>& args) |
-{ |
-END |
- my $leastNumMandatoryParams = 255; |
- foreach my $constructor (@{$interface->constructors}) { |
- my $name = "constructor" . $constructor->overloadedIndex; |
- my ($numMandatoryParams, $parametersCheck) = GenerateFunctionParametersCheck($constructor); |
- $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams < $leastNumMandatoryParams); |
- $code .= " if ($parametersCheck) {\n"; |
- $code .= " ${implClassName}V8Internal::${name}(args);\n"; |
- $code .= " return;\n"; |
- $code .= " }\n"; |
- } |
- if ($leastNumMandatoryParams >= 1) { |
- $code .= " if (args.Length() < $leastNumMandatoryParams) {\n"; |
- $code .= " throwNotEnoughArgumentsError(args.GetIsolate());\n"; |
- $code .= " return;\n"; |
- $code .= " }\n"; |
- } |
- $code .= <<END; |
- throwTypeError(0, args.GetIsolate()); |
- return; |
-END |
- $code .= "}\n\n"; |
- $implementation{nameSpaceInternal}->add($code); |
-} |
- |
-sub GenerateSingleConstructorCallback |
-{ |
- my $interface = shift; |
- my $function = shift; |
- |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- my $overloadedIndexString = ""; |
- if ($function->overloadedIndex > 0) { |
- $overloadedIndexString .= $function->overloadedIndex; |
- } |
- |
- my $raisesExceptions = $function->extendedAttributes->{"RaisesException"}; |
- if ($interface->extendedAttributes->{"ConstructorRaisesException"}) { |
- $raisesExceptions = 1; |
- } |
- if (!$raisesExceptions) { |
- foreach my $parameter (@{$function->parameters}) { |
- if ($parameter->extendedAttributes->{"IsIndex"}) { |
- $raisesExceptions = 1; |
- } |
- } |
- } |
- |
- my @beforeArgumentList; |
- my @afterArgumentList; |
- my $code = ""; |
- $code .= <<END; |
-static void constructor${overloadedIndexString}(const v8::FunctionCallbackInfo<v8::Value>& args) |
-{ |
-END |
- |
- if ($function->overloadedIndex == 0) { |
- $code .= GenerateArgumentsCountCheck($function, $interface); |
- } |
- |
- if ($raisesExceptions) { |
- AddToImplIncludes("core/dom/ExceptionCode.h"); |
- $code .= " ExceptionCode ec = 0;\n"; |
- } |
- |
- # FIXME: Currently [Constructor(...)] does not yet support optional arguments without [Default=...] |
- my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersCheck($function, $interface, ""); |
- $code .= $parameterCheckString; |
- |
- if ($interface->extendedAttributes->{"ConstructorCallWith"} && $interface->extendedAttributes->{"ConstructorCallWith"} eq "ScriptExecutionContext") { |
- push(@beforeArgumentList, "context"); |
- $code .= <<END; |
- |
- ScriptExecutionContext* context = getScriptExecutionContext(); |
-END |
- } |
- |
- if ($interface->extendedAttributes->{"ConstructorRaisesException"}) { |
- push(@afterArgumentList, "ec"); |
- } |
- |
- my @argumentList; |
- my $index = 0; |
- foreach my $parameter (@{$function->parameters}) { |
- last if $index eq $paramIndex; |
- if ($replacements{$parameter->name}) { |
- push(@argumentList, $replacements{$parameter->name}); |
- } else { |
- push(@argumentList, $parameter->name); |
- } |
- $index++; |
- } |
- |
- my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterArgumentList); |
- $code .= "\n"; |
- $code .= " RefPtr<${implClassName}> impl = ${implClassName}::create(${argumentString});\n"; |
- $code .= " v8::Handle<v8::Object> wrapper = args.Holder();\n"; |
- |
- if ($interface->extendedAttributes->{"ConstructorRaisesException"}) { |
- $code .= " if (ec) {\n"; |
- $code .= " setDOMException(ec, args.GetIsolate());\n"; |
- $code .= " return;\n"; |
- $code .= " }\n"; |
- } |
- |
- $code .= <<END; |
- |
- V8DOMWrapper::associateObjectWithWrapper(impl.release(), &${v8ClassName}::info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent); |
- args.GetReturnValue().Set(wrapper); |
-} |
- |
-END |
- $implementation{nameSpaceInternal}->add($code); |
-} |
- |
-# The Web IDL specification states that Interface objects for interfaces MUST have a property named |
-# "length" that returns the length of the shortest argument list of the entries in the effective |
-# overload set for constructors. In other words, use the lowest number of mandatory arguments among |
-# all constructors. |
-sub GetInterfaceLength |
-{ |
- my $interface = shift; |
- |
- my $leastConstructorLength = 0; |
- if (IsConstructorTemplate($interface, "Event") || IsConstructorTemplate($interface, "TypedArray")) { |
- $leastConstructorLength = 1; |
- } elsif ($interface->extendedAttributes->{"Constructor"} || $interface->extendedAttributes->{"CustomConstructor"}) { |
- my @constructors = @{$interface->constructors}; |
- my @customConstructors = @{$interface->customConstructors}; |
- $leastConstructorLength = 255; |
- foreach my $constructor (@constructors, @customConstructors) { |
- my $constructorLength = GetFunctionLength($constructor); |
- $leastConstructorLength = $constructorLength if ($constructorLength < $leastConstructorLength); |
- } |
- } |
- |
- return $leastConstructorLength; |
-} |
- |
-sub GenerateConstructorCallback |
-{ |
- my $interface = shift; |
- |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- my $code = ""; |
- $code .= "void ${v8ClassName}::constructorCallback(const v8::FunctionCallbackInfo<v8::Value>& args)\n"; |
- $code .= "{\n"; |
- $code .= " TRACE_EVENT_SCOPED_SAMPLING_STATE(\"Blink\", \"DOMConstructor\");\n"; |
- $code .= GenerateFeatureObservation($interface->extendedAttributes->{"MeasureAs"}); |
- $code .= GenerateDeprecationNotification($interface->extendedAttributes->{"DeprecateAs"}); |
- $code .= GenerateConstructorHeader(); |
- if (HasCustomConstructor($interface)) { |
- $code .= " ${v8ClassName}::constructorCustom(args);\n"; |
- } else { |
- $code .= " ${implClassName}V8Internal::constructor(args);\n"; |
- } |
- $code .= "}\n\n"; |
- $implementation{nameSpaceWebCore}->add($code); |
-} |
- |
-sub GenerateConstructor |
-{ |
- my $interface = shift; |
- |
- if (@{$interface->constructors} == 1) { |
- GenerateSingleConstructorCallback($interface, @{$interface->constructors}[0]); |
- } else { |
- foreach my $constructor (@{$interface->constructors}) { |
- GenerateSingleConstructorCallback($interface, $constructor); |
- } |
- GenerateOverloadedConstructorCallback($interface); |
- } |
-} |
- |
-sub GenerateEventConstructor |
-{ |
- my $interface = shift; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- |
- AddToImplIncludes("bindings/v8/Dictionary.h"); |
- $implementation{nameSpaceInternal}->add(<<END); |
-static void constructor(const v8::FunctionCallbackInfo<v8::Value>& args) |
-{ |
- if (args.Length() < 1) { |
- throwNotEnoughArgumentsError(args.GetIsolate()); |
- return; |
- } |
- |
- V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, type, args[0]); |
- ${implClassName}Init eventInit; |
- if (args.Length() >= 2) { |
- V8TRYCATCH_VOID(Dictionary, options, Dictionary(args[1], args.GetIsolate())); |
- if (!fill${implClassName}Init(eventInit, options)) |
- return; |
-END |
- for (my $index = 0; $index < @{$interface->attributes}; $index++) { |
- my $attribute = @{$interface->attributes}[$index]; |
- if ($attribute->type eq "any") { |
- my $attributeName = $attribute->name; |
- $implementation{nameSpaceInternal}->add(<<END); |
- v8::Local<v8::Value> ${attributeName}; |
- options.get("${attributeName}", ${attributeName}); |
- if (!${attributeName}.IsEmpty()) |
- args.Holder()->SetHiddenValue(V8HiddenPropertyName::${attributeName}(), ${attributeName}); |
-END |
- } |
- } |
- $implementation{nameSpaceInternal}->add(<<END); |
- } |
- |
- RefPtr<${implClassName}> event = ${implClassName}::create(type, eventInit); |
- |
- v8::Handle<v8::Object> wrapper = args.Holder(); |
- V8DOMWrapper::associateObjectWithWrapper(event.release(), &${v8ClassName}::info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent); |
- v8SetReturnValue(args, wrapper); |
-} |
-END |
- |
- my $code = ""; |
- $code .= <<END; |
-bool fill${implClassName}Init(${implClassName}Init& eventInit, const Dictionary& options) |
-{ |
-END |
- |
- if ($interface->parent) { |
- my $interfaceBase = $interface->parent; |
- $code .= <<END; |
- if (!fill${interfaceBase}Init(eventInit, options)) |
- return false; |
- |
-END |
- } |
- |
- for (my $index = 0; $index < @{$interface->attributes}; $index++) { |
- my $attribute = @{$interface->attributes}[$index]; |
- if ($attribute->extendedAttributes->{"InitializedByEventConstructor"}) { |
- my $attributeName = $attribute->name; |
- my $attributeType = $attribute->type; |
- if (not ($attribute->type eq "any")) { |
- $code .= " options.get(\"$attributeName\", eventInit.$attributeName);\n"; |
- } |
- } |
- } |
- |
- $code .= <<END; |
- return true; |
-} |
- |
-END |
- $implementation{nameSpaceWebCore}->add($code); |
-} |
- |
-sub GenerateTypedArrayConstructor |
-{ |
- my $interface = shift; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- |
- my ($nativeType, $arrayType) = GetNativeTypeOfTypedArray($interface); |
- AddToImplIncludes("bindings/v8/custom/V8ArrayBufferViewCustom.h"); |
- |
- $implementation{nameSpaceInternal}->add(<<END); |
-static void constructor(const v8::FunctionCallbackInfo<v8::Value>& args) |
-{ |
- return constructWebGLArray<$implClassName, ${v8ClassName}, $nativeType>(args, &${v8ClassName}::info, $arrayType); |
-} |
- |
-END |
-} |
- |
-sub GenerateNamedConstructor |
-{ |
- my $function = shift; |
- my $interface = shift; |
- |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- my $raisesExceptions = $function->extendedAttributes->{"RaisesException"}; |
- if ($interface->extendedAttributes->{"ConstructorRaisesException"}) { |
- $raisesExceptions = 1; |
- } |
- if (!$raisesExceptions) { |
- foreach my $parameter (@{$function->parameters}) { |
- if ($parameter->extendedAttributes->{"IsIndex"}) { |
- $raisesExceptions = 1; |
- } |
- } |
- } |
- |
- my $maybeObserveFeature = GenerateFeatureObservation($function->extendedAttributes->{"MeasureAs"}); |
- my $maybeDeprecateFeature = GenerateDeprecationNotification($function->extendedAttributes->{"DeprecateAs"}); |
- |
- my @beforeArgumentList; |
- my @afterArgumentList; |
- |
- my $toActiveDOMObject = "0"; |
- if (InheritsExtendedAttribute($interface, "ActiveDOMObject")) { |
- $toActiveDOMObject = "${v8ClassName}::toActiveDOMObject"; |
- } |
- |
- my $toEventTarget = "0"; |
- if (InheritsExtendedAttribute($interface, "EventTarget")) { |
- $toEventTarget = "${v8ClassName}::toEventTarget"; |
- } |
- |
- AddToImplIncludes("core/page/Frame.h"); |
- $implementation{nameSpaceWebCore}->add(<<END); |
-WrapperTypeInfo ${v8ClassName}Constructor::info = { ${v8ClassName}Constructor::GetTemplate, ${v8ClassName}::derefObject, $toActiveDOMObject, $toEventTarget, 0, ${v8ClassName}::installPerContextPrototypeProperties, 0, WrapperTypeObjectPrototype }; |
- |
-END |
- |
- my $code = ""; |
- $code .= <<END; |
-static void ${v8ClassName}ConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& args) |
-{ |
-END |
- $code .= $maybeObserveFeature if $maybeObserveFeature; |
- $code .= $maybeDeprecateFeature if $maybeDeprecateFeature; |
- $code .= GenerateConstructorHeader(); |
- AddToImplIncludes("V8Document.h"); |
- $code .= <<END; |
- Document* document = currentDocument(); |
- |
- // Make sure the document is added to the DOM Node map. Otherwise, the ${implClassName} instance |
- // may end up being the only node in the map and get garbage-collected prematurely. |
- toV8(document, args.Holder(), args.GetIsolate()); |
- |
-END |
- |
- $code .= GenerateArgumentsCountCheck($function, $interface); |
- |
- if ($raisesExceptions) { |
- AddToImplIncludes("core/dom/ExceptionCode.h"); |
- $code .= " ExceptionCode ec = 0;\n"; |
- } |
- |
- my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersCheck($function, $interface); |
- $code .= $parameterCheckString; |
- |
- push(@beforeArgumentList, "document"); |
- |
- if ($interface->extendedAttributes->{"ConstructorRaisesException"}) { |
- push(@afterArgumentList, "ec"); |
- } |
- |
- my @argumentList; |
- my $index = 0; |
- foreach my $parameter (@{$function->parameters}) { |
- last if $index eq $paramIndex; |
- if ($replacements{$parameter->name}) { |
- push(@argumentList, $replacements{$parameter->name}); |
- } else { |
- push(@argumentList, $parameter->name); |
- } |
- $index++; |
- } |
- |
- my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterArgumentList); |
- $code .= "\n"; |
- $code .= " RefPtr<${implClassName}> impl = ${implClassName}::createForJSConstructor(${argumentString});\n"; |
- $code .= " v8::Handle<v8::Object> wrapper = args.Holder();\n"; |
- |
- if ($interface->extendedAttributes->{"ConstructorRaisesException"}) { |
- $code .= " if (ec) {\n"; |
- $code .= " setDOMException(ec, args.GetIsolate());\n"; |
- $code .= " return;\n"; |
- $code .= " }\n"; |
- } |
- |
- $code .= <<END; |
- |
- V8DOMWrapper::associateObjectWithWrapper(impl.release(), &${v8ClassName}Constructor::info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent); |
- args.GetReturnValue().Set(wrapper); |
-} |
- |
-END |
- $implementation{nameSpaceWebCore}->add($code); |
- |
- $code = <<END; |
-v8::Handle<v8::FunctionTemplate> ${v8ClassName}Constructor::GetTemplate(v8::Isolate* isolate, WrapperWorldType currentWorldType) |
-{ |
- static v8::Persistent<v8::FunctionTemplate> cachedTemplate; |
- if (!cachedTemplate.IsEmpty()) |
- return v8::Local<v8::FunctionTemplate>::New(isolate, cachedTemplate); |
- |
- TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink\", \"BuildDOMTemplate"); |
- v8::HandleScope scope(isolate); |
- v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(${v8ClassName}ConstructorCallback); |
- |
- v8::Local<v8::ObjectTemplate> instance = result->InstanceTemplate(); |
- instance->SetInternalFieldCount(${v8ClassName}::internalFieldCount); |
- result->SetClassName(v8::String::NewSymbol("${implClassName}")); |
- result->Inherit(${v8ClassName}::GetTemplate(isolate, currentWorldType)); |
- |
- cachedTemplate.Reset(isolate, result); |
- return scope.Close(v8::Local<v8::FunctionTemplate>::New(isolate, cachedTemplate)); |
-} |
- |
-END |
- $implementation{nameSpaceWebCore}->add($code); |
-} |
- |
-sub GenerateConstructorHeader |
-{ |
- AddToImplIncludes("bindings/v8/V8ObjectConstructor.h"); |
- my $content = <<END; |
- if (!args.IsConstructCall()) { |
- throwTypeError("DOM object constructor cannot be called as a function.", args.GetIsolate()); |
- return; |
- } |
- |
- if (ConstructorMode::current() == ConstructorMode::WrapExistingObject) { |
- args.GetReturnValue().Set(args.Holder()); |
- return; |
- } |
- |
-END |
- return $content; |
-} |
- |
-sub GenerateBatchedAttributeData |
-{ |
- my $interface = shift; |
- my $attributes = shift; |
- my $code = ""; |
- |
- foreach my $attribute (@$attributes) { |
- my $conditionalString = GenerateConditionalString($attribute); |
- my $subCode = ""; |
- $subCode .= "#if ${conditionalString}\n" if $conditionalString; |
- $subCode .= GenerateSingleBatchedAttribute($interface, $attribute, ",", ""); |
- $subCode .= "#endif // ${conditionalString}\n" if $conditionalString; |
- $code .= $subCode; |
- } |
- return $code; |
-} |
- |
-sub GenerateSingleBatchedAttribute |
-{ |
- my $interface = shift; |
- my $attribute = shift; |
- my $delimiter = shift; |
- my $indent = shift; |
- my $code = ""; |
- my $attrName = $attribute->name; |
- my $attrExt = $attribute->extendedAttributes; |
- my $implClassName = GetImplName($interface); |
- |
- my $accessControl = "v8::DEFAULT"; |
- if ($attrExt->{"DoNotCheckSecurityOnGetter"}) { |
- $accessControl = "v8::ALL_CAN_READ"; |
- } elsif ($attrExt->{"DoNotCheckSecurityOnSetter"}) { |
- $accessControl = "v8::ALL_CAN_WRITE"; |
- } elsif ($attrExt->{"DoNotCheckSecurity"}) { |
- $accessControl = "v8::ALL_CAN_READ"; |
- if (!IsReadonly($attribute)) { |
- $accessControl .= " | v8::ALL_CAN_WRITE"; |
- } |
- } |
- if ($attrExt->{"Unforgeable"}) { |
- $accessControl .= " | v8::PROHIBITS_OVERWRITING"; |
- } |
- $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")"; |
- |
- my $customAccessor = HasCustomGetter($attrExt) || HasCustomSetter($attrExt) || ""; |
- if ($customAccessor eq "VALUE_IS_MISSING") { |
- # use the naming convension, interface + (capitalize) attr name |
- $customAccessor = $implClassName . "::" . $attrName; |
- } |
- |
- my $getter; |
- my $setter; |
- my $getterForMainWorld; |
- my $setterForMainWorld; |
- my $propAttr = "v8::None"; |
- |
- my $isConstructor = ($attribute->type =~ /Constructor$/); |
- |
- # Check attributes. |
- # As per Web IDL specification, constructor properties on the ECMAScript global object should be |
- # configurable and should not be enumerable. |
- if ($attrExt->{"NotEnumerable"} || $isConstructor) { |
- $propAttr .= " | v8::DontEnum"; |
- } |
- if ($attrExt->{"Unforgeable"} && !$isConstructor) { |
- $propAttr .= " | v8::DontDelete"; |
- } |
- |
- my $on_proto = "0 /* on instance */"; |
- my $data = "0 /* no data */"; |
- |
- # Constructor |
- if ($isConstructor) { |
- my $constructorType = $attribute->type; |
- $constructorType =~ s/Constructor$//; |
- # $constructorType ~= /Constructor$/ indicates that it is NamedConstructor. |
- # We do not generate the header file for NamedConstructor of class XXXX, |
- # since we generate the NamedConstructor declaration into the header file of class XXXX. |
- if ($constructorType !~ /Constructor$/ || $attribute->extendedAttributes->{"CustomConstructor"}) { |
- AddToImplIncludes("V8${constructorType}.h"); |
- } |
- $data = "&V8${constructorType}::info"; |
- $getter = "${implClassName}V8Internal::${implClassName}ConstructorGetter"; |
- $setter = "${implClassName}V8Internal::${implClassName}ReplaceableAttrSetterCallback"; |
- $getterForMainWorld = "0"; |
- $setterForMainWorld = "0"; |
- } else { |
- # Default Getter and Setter |
- $getter = "${implClassName}V8Internal::${attrName}AttrGetterCallback"; |
- $setter = "${implClassName}V8Internal::${attrName}AttrSetterCallback"; |
- $getterForMainWorld = "${getter}ForMainWorld"; |
- $setterForMainWorld = "${setter}ForMainWorld"; |
- |
- if (!HasCustomSetter($attrExt) && $attrExt->{"Replaceable"}) { |
- $setter = "${implClassName}V8Internal::${implClassName}ReplaceableAttrSetterCallback"; |
- $setterForMainWorld = "0"; |
- } |
- } |
- |
- # Read only attributes |
- if (IsReadonly($attribute)) { |
- $setter = "0"; |
- $setterForMainWorld = "0"; |
- } |
- |
- # An accessor can be installed on the proto |
- if ($attrExt->{"OnProto"}) { |
- $on_proto = "1 /* on proto */"; |
- } |
- |
- if (!$attrExt->{"PerWorldBindings"}) { |
- $getterForMainWorld = "0"; |
- $setterForMainWorld = "0"; |
- } |
- |
- my $commentInfo = "Attribute '$attrName'"; |
- |
- $code .= $indent . " \/\/ $commentInfo\n"; |
- $code .= $indent . " {\"$attrName\", $getter, $setter, $getterForMainWorld, $setterForMainWorld, $data, $accessControl, static_cast<v8::PropertyAttribute>($propAttr), $on_proto}" . $delimiter . "\n"; |
- return $code; |
-} |
- |
-sub IsStandardFunction |
-{ |
- my $interface = shift; |
- my $function = shift; |
- |
- my $interfaceName = $interface->name; |
- my $attrExt = $function->extendedAttributes; |
- return 0 if $attrExt->{"Unforgeable"}; |
- return 0 if $function->isStatic; |
- return 0 if $attrExt->{"EnabledAtRuntime"}; |
- return 0 if $attrExt->{"EnabledPerContext"}; |
- return 0 if RequiresCustomSignature($function); |
- return 0 if $attrExt->{"DoNotCheckSignature"}; |
- return 0 if ($attrExt->{"DoNotCheckSecurity"} && ($interface->extendedAttributes->{"CheckSecurity"} || $interfaceName eq "Window")); |
- return 0 if $attrExt->{"NotEnumerable"}; |
- return 0 if $attrExt->{"ReadOnly"}; |
- return 1; |
-} |
- |
-sub GenerateNonStandardFunction |
-{ |
- my $interface = shift; |
- my $function = shift; |
- my $code = ""; |
- |
- my $implClassName = GetImplName($interface); |
- my $attrExt = $function->extendedAttributes; |
- my $name = $function->name; |
- |
- my $property_attributes = "v8::DontDelete"; |
- if ($attrExt->{"NotEnumerable"}) { |
- $property_attributes .= " | v8::DontEnum"; |
- } |
- if ($attrExt->{"ReadOnly"}) { |
- $property_attributes .= " | v8::ReadOnly"; |
- } |
- |
- my $commentInfo = "Function '$name' (ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')"; |
- |
- my $template = "proto"; |
- if ($attrExt->{"Unforgeable"}) { |
- $template = "instance"; |
- } |
- if ($function->isStatic) { |
- $template = "desc"; |
- } |
- |
- my $conditional = ""; |
- if ($attrExt->{"EnabledAtRuntime"}) { |
- # Only call Set()/SetAccessor() if this method should be enabled |
- my $enable_function = GetRuntimeEnableFunctionName($function); |
- $conditional = "if (${enable_function}())\n "; |
- } |
- if ($attrExt->{"EnabledPerContext"}) { |
- # Only call Set()/SetAccessor() if this method should be enabled |
- my $enable_function = GetContextEnableFunction($function); |
- $conditional = "if (${enable_function}(impl->document()))\n "; |
- } |
- |
- if ($interface->extendedAttributes->{"CheckSecurity"} && $attrExt->{"DoNotCheckSecurity"}) { |
- my $setter = $attrExt->{"ReadOnly"} ? "0" : "${implClassName}V8Internal::${implClassName}DomainSafeFunctionSetter"; |
- # Functions that are marked DoNotCheckSecurity are always readable but if they are changed |
- # and then accessed on a different domain we do not return the underlying value but instead |
- # return a new copy of the original function. This is achieved by storing the changed value |
- # as hidden property. |
- $code .= <<END; |
- |
- // $commentInfo |
- ${conditional}$template->SetAccessor(v8::String::NewSymbol("$name"), ${implClassName}V8Internal::${name}AttrGetterCallback, ${setter}, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>($property_attributes)); |
-END |
- return $code; |
- } |
- |
- my $signature = "defaultSignature"; |
- if ($attrExt->{"DoNotCheckSignature"} || $function->isStatic) { |
- $signature = "v8::Local<v8::Signature>()"; |
- } |
- |
- my $conditionalString = GenerateConditionalString($function); |
- $code .= "#if ${conditionalString}\n" if $conditionalString; |
- if (RequiresCustomSignature($function)) { |
- $signature = "${name}Signature"; |
- $code .= "\n // Custom Signature '$name'\n" . CreateCustomSignature($function); |
- } |
- |
- 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 "") { |
- die "This shouldn't happen: Class '$implClassName' $commentInfo\n"; |
- } |
- |
- my $functionLength = GetFunctionLength($function); |
- |
- if ($function->extendedAttributes->{"PerWorldBindings"}) { |
- $code .= " if (currentWorldType == MainWorld) {\n"; |
- $code .= " ${conditional}$template->Set(v8::String::NewSymbol(\"$name\"), v8::FunctionTemplate::New(${implClassName}V8Internal::${name}MethodCallbackForMainWorld, v8Undefined(), ${signature}, $functionLength)$property_attributes);\n"; |
- $code .= " } else {\n"; |
- $code .= " ${conditional}$template->Set(v8::String::NewSymbol(\"$name\"), v8::FunctionTemplate::New(${implClassName}V8Internal::${name}MethodCallback, v8Undefined(), ${signature}, $functionLength)$property_attributes);\n"; |
- $code .= " }\n"; |
- } else { |
- $code .= " ${conditional}$template->Set(v8::String::NewSymbol(\"$name\"), v8::FunctionTemplate::New(${implClassName}V8Internal::${name}MethodCallback, v8Undefined(), ${signature}, $functionLength)$property_attributes);\n"; |
- } |
- $code .= "#endif // ${conditionalString}\n" if $conditionalString; |
- return $code; |
-} |
- |
-sub GenerateIsNullExpression |
-{ |
- my $type = shift; |
- my $variableName = shift; |
- if (IsUnionType($type)) { |
- my $types = $type->unionMemberTypes; |
- my @expression = (); |
- for my $i (0 .. scalar(@$types)-1) { |
- my $unionMemberType = $types->[$i]; |
- my $unionMemberVariable = $variableName . $i; |
- my $isNull = GenerateIsNullExpression($unionMemberType, $unionMemberVariable); |
- push @expression, $isNull; |
- } |
- return join " && ", @expression; |
- } |
- if (IsRefPtrType($type)) { |
- return "!${variableName}"; |
- } elsif ($type eq "DOMString") { |
- return "${variableName}.isNull()"; |
- } else { |
- return ""; |
- } |
-} |
- |
-sub GenerateIfElseStatement |
-{ |
- my $type = shift; |
- my $outputVariableName = shift; |
- my $conditions = shift; |
- my $statements = shift; |
- |
- my $code = ""; |
- if (@$conditions == 1) { |
- $code .= " ${type} ${outputVariableName} = " . $statements->[0] . "\n"; |
- } else { |
- $code .= " ${type} ${outputVariableName};\n"; |
- for my $i (0 .. @$conditions - 1) { |
- my $token = "else if"; |
- $token = "if" if $i == 0; |
- $token = "else" if $i == @$conditions - 1; |
- $code .= " ${token}"; |
- $code .= " (" . $conditions->[$i] . ")" if $conditions->[$i]; |
- $code .= "\n"; |
- $code .= " ${outputVariableName} = " . $statements->[$i] . "\n"; |
- } |
- } |
- return $code; |
-} |
- |
-sub GenerateImplementationIndexedPropertyAccessors |
-{ |
- my $interface = shift; |
- my $interfaceName = $interface->name; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- |
- my $indexedGetterFunction = GetIndexedGetterFunction($interface); |
- if ($indexedGetterFunction) { |
- my $hasCustomIndexedGetter = $indexedGetterFunction->extendedAttributes->{"Custom"}; |
- if (!$hasCustomIndexedGetter) { |
- GenerateImplementationIndexedPropertyGetter($interface, $indexedGetterFunction); |
- } |
- GenerateImplementationIndexedPropertyGetterCallback($interface, $hasCustomIndexedGetter); |
- } |
- |
- my $indexedSetterFunction = GetIndexedSetterFunction($interface); |
- if ($indexedSetterFunction) { |
- my $hasCustomIndexedSetter = $indexedSetterFunction->extendedAttributes->{"Custom"}; |
- if (!$hasCustomIndexedSetter) { |
- GenerateImplementationIndexedPropertySetter($interface, $indexedSetterFunction); |
- } |
- GenerateImplementationIndexedPropertySetterCallback($interface, $hasCustomIndexedSetter); |
- } |
- |
- my $indexedDeleterFunction = GetIndexedDeleterFunction($interface); |
- if ($indexedDeleterFunction) { |
- my $hasCustomIndexedDeleter = $indexedDeleterFunction->extendedAttributes->{"Custom"}; |
- if (!$hasCustomIndexedDeleter) { |
- GenerateImplementationIndexedPropertyDeleter($interface, $indexedDeleterFunction); |
- } |
- GenerateImplementationIndexedPropertyDeleterCallback($interface, $hasCustomIndexedDeleter); |
- } |
- |
- my $indexedEnumeratorFunction = $indexedGetterFunction; |
- $indexedEnumeratorFunction = 0 if $indexedGetterFunction && $indexedGetterFunction->extendedAttributes->{"NotEnumerable"}; |
- |
- my $indexedQueryFunction = 0; |
- # If there is an enumerator, there MUST be a query method to properly communicate property attributes. |
- my $hasQuery = $indexedQueryFunction || $indexedEnumeratorFunction; |
- |
- my $setOn = "Instance"; |
- |
- # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on Window |
- # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to |
- # get implementation straight out of the Window prototype regardless of what prototype is actually set |
- # on the object. |
- if ($interfaceName eq "Window") { |
- $setOn = "Prototype"; |
- } |
- |
- my $code = ""; |
- if ($indexedGetterFunction || $indexedSetterFunction || $indexedDeleterFunction || $indexedEnumeratorFunction || $hasQuery) { |
- $code .= " desc->${setOn}Template()->SetIndexedPropertyHandler(${implClassName}V8Internal::indexedPropertyGetterCallback"; |
- $code .= $indexedSetterFunction ? ", ${implClassName}V8Internal::indexedPropertySetterCallback" : ", 0"; |
- $code .= ", 0"; # IndexedPropertyQuery -- not being used at the moment. |
- $code .= $indexedDeleterFunction ? ", ${implClassName}V8Internal::indexedPropertyDeleterCallback" : ", 0"; |
- $code .= ", indexedPropertyEnumerator<${implClassName}>" if $indexedEnumeratorFunction; |
- $code .= ");\n"; |
- } |
- |
- return $code; |
-} |
- |
-sub GenerateImplementationIndexedPropertyGetter |
-{ |
- my $interface = shift; |
- my $indexedGetterFunction = shift; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- my $methodName = GetImplName($indexedGetterFunction); |
- |
- my $returnType = $indexedGetterFunction->type; |
- my $nativeType = GetNativeType($returnType); |
- my $nativeValue = "element"; |
- $nativeValue .= ".release()" if (IsRefPtrType($returnType)); |
- my $isNull = GenerateIsNullExpression($returnType, "element"); |
- my $returnJSValueCode = NativeToJSValue($indexedGetterFunction->type, $indexedGetterFunction->extendedAttributes, $nativeValue, " ", "", "info.Holder()", "info.GetIsolate()", "info", "collection", "", "", "return"); |
- my $raisesExceptions = $indexedGetterFunction->extendedAttributes->{"RaisesException"}; |
- my $methodCallCode = GenerateMethodCall($returnType, "element", "collection->${methodName}", "index", $raisesExceptions); |
- my $getterCode = "static void indexedPropertyGetter(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; |
- $getterCode .= "{\n"; |
- $getterCode .= " ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder()));\n"; |
- $getterCode .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder());\n"; |
- if ($raisesExceptions) { |
- $getterCode .= " ExceptionCode ec = 0;\n"; |
- } |
- $getterCode .= $methodCallCode . "\n"; |
- if ($raisesExceptions) { |
- $getterCode .= " if (ec) {\n"; |
- $getterCode .= " setDOMException(ec, info.GetIsolate());\n"; |
- $getterCode .= " return;\n"; |
- $getterCode .= " }\n"; |
- } |
- if (IsUnionType($returnType)) { |
- $getterCode .= "${returnJSValueCode}\n"; |
- $getterCode .= " return;\n"; |
- } else { |
- $getterCode .= " if (${isNull})\n"; |
- $getterCode .= " return;\n"; |
- $getterCode .= $returnJSValueCode . "\n"; |
- } |
- $getterCode .= "}\n\n"; |
- $implementation{nameSpaceInternal}->add($getterCode); |
-} |
- |
-sub GenerateImplementationIndexedPropertyGetterCallback |
-{ |
- my $interface = shift; |
- my $hasCustom = shift; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- |
- my $code = "static void indexedPropertyGetterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; |
- $code .= "{\n"; |
- $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMIndexedProperty\");\n"; |
- if ($hasCustom) { |
- $code .= " ${v8ClassName}::indexedPropertyGetterCustom(index, info);\n"; |
- } else { |
- $code .= " ${implClassName}V8Internal::indexedPropertyGetter(index, info);\n"; |
- } |
- $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; |
- $code .= "}\n\n"; |
- $implementation{nameSpaceInternal}->add($code); |
-} |
- |
-sub GenerateImplementationIndexedPropertySetterCallback |
-{ |
- my $interface = shift; |
- my $hasCustom = shift; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- |
- my $code = "static void indexedPropertySetterCallback(uint32_t index, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; |
- $code .= "{\n"; |
- $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMIndexedProperty\");\n"; |
- if ($hasCustom) { |
- $code .= " ${v8ClassName}::indexedPropertySetterCustom(index, value, info);\n"; |
- } else { |
- $code .= " ${implClassName}V8Internal::indexedPropertySetter(index, value, info);\n"; |
- } |
- $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; |
- $code .= "}\n\n"; |
- $implementation{nameSpaceInternal}->add($code); |
-} |
- |
-sub GenerateImplementationIndexedPropertyDeleterCallback |
-{ |
- my $interface = shift; |
- my $hasCustom = shift; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- |
- my $code = "static void indexedPropertyDeleterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info)\n"; |
- $code .= "{\n"; |
- $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMIndexedProperty\");\n"; |
- if ($hasCustom) { |
- $code .= " ${v8ClassName}::indexedPropertyDeleterCustom(index, info);\n"; |
- } else { |
- $code .= " ${implClassName}V8Internal::indexedPropertyDeleter(index, info);\n"; |
- } |
- $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; |
- $code .= "}\n\n"; |
- $implementation{nameSpaceInternal}->add($code); |
-} |
- |
-sub GenerateImplementationIndexedPropertySetter |
-{ |
- my $interface = shift; |
- my $indexedSetterFunction = shift; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- my $methodName = GetImplName($indexedSetterFunction); |
- |
- my $type = $indexedSetterFunction->parameters->[1]->type; |
- my $raisesExceptions = $indexedSetterFunction->extendedAttributes->{"RaisesException"}; |
- my $treatNullAs = $indexedSetterFunction->parameters->[1]->extendedAttributes->{"TreatNullAs"}; |
- my $treatUndefinedAs = $indexedSetterFunction->parameters->[1]->extendedAttributes->{"TreatUndefinedAs"}; |
- my $code = "static void indexedPropertySetter(uint32_t index, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; |
- $code .= "{\n"; |
- $code .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder());\n"; |
- $code .= JSValueToNativeStatement($indexedSetterFunction->parameters->[1]->type, $indexedSetterFunction->extendedAttributes, "value", "propertyValue", " ", "info.GetIsolate()"); |
- |
- my $extraArguments = ""; |
- if ($raisesExceptions) { |
- $code .= " ExceptionCode ec = 0;\n"; |
- $extraArguments = ", ec"; |
- } |
- my @conditions = (); |
- my @statements = (); |
- if ($treatNullAs && $treatNullAs ne "NullString") { |
- push @conditions, "value->IsNull()"; |
- push @statements, "collection->${treatNullAs}(index$extraArguments);"; |
- } |
- if ($treatUndefinedAs && $treatUndefinedAs ne "NullString") { |
- push @conditions, "value->IsUndefined()"; |
- push @statements, "collection->${treatUndefinedAs}(index$extraArguments);"; |
- } |
- push @conditions, ""; |
- push @statements, "collection->${methodName}(index, propertyValue$extraArguments);"; |
- $code .= GenerateIfElseStatement("bool", "result", \@conditions, \@statements); |
- |
- $code .= " if (!result)\n"; |
- $code .= " return;\n"; |
- if ($raisesExceptions) { |
- $code .= " if (ec) {\n"; |
- $code .= " setDOMException(ec, info.GetIsolate());\n"; |
- $code .= " return;\n"; |
- $code .= " }\n"; |
- } |
- $code .= " v8SetReturnValue(info, value);\n"; |
- $code .= "}\n\n"; |
- $implementation{nameSpaceInternal}->add($code); |
-} |
- |
-sub GenerateImplementationNamedPropertyAccessors |
-{ |
- my $interface = shift; |
- |
- my $interfaceName = $interface->name; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- |
- my $namedGetterFunction = GetNamedGetterFunction($interface); |
- if ($namedGetterFunction) { |
- my $hasCustomNamedGetter = $namedGetterFunction->extendedAttributes->{"Custom"}; |
- if (!$hasCustomNamedGetter) { |
- GenerateImplementationNamedPropertyGetter($interface, $namedGetterFunction); |
- } |
- GenerateImplementationNamedPropertyGetterCallback($interface, $hasCustomNamedGetter); |
- } |
- |
- my $namedSetterFunction = GetNamedSetterFunction($interface); |
- if ($namedSetterFunction) { |
- my $hasCustomNamedSetter = $namedSetterFunction->extendedAttributes->{"Custom"}; |
- if (!$hasCustomNamedSetter) { |
- GenerateImplementationNamedPropertySetter($interface, $namedSetterFunction); |
- } |
- GenerateImplementationNamedPropertySetterCallback($interface, $hasCustomNamedSetter); |
- } |
- |
- my $namedDeleterFunction = GetNamedDeleterFunction($interface); |
- if ($namedDeleterFunction) { |
- my $hasCustomNamedDeleter = $namedDeleterFunction->extendedAttributes->{"Custom"}; |
- if (!$hasCustomNamedDeleter) { |
- GenerateImplementationNamedPropertyDeleter($interface, $namedDeleterFunction); |
- } |
- GenerateImplementationNamedPropertyDeleterCallback($interface, $hasCustomNamedDeleter); |
- } |
- |
- my $namedEnumeratorFunction = $namedGetterFunction && !$namedGetterFunction->extendedAttributes->{"NotEnumerable"}; |
- if ($namedEnumeratorFunction) { |
- my $hasCustomNamedEnumerator = $namedGetterFunction->extendedAttributes->{"CustomEnumerateProperty"}; |
- if (!$hasCustomNamedEnumerator) { |
- GenerateImplementationNamedPropertyEnumerator($interface); |
- GenerateImplementationNamedPropertyQuery($interface); |
- } |
- GenerateImplementationNamedPropertyEnumeratorCallback($interface, $hasCustomNamedEnumerator); |
- GenerateImplementationNamedPropertyQueryCallback($interface, $hasCustomNamedEnumerator); |
- } |
- |
- my $subCode = ""; |
- if ($namedGetterFunction || $namedSetterFunction || $namedDeleterFunction || $namedEnumeratorFunction) { |
- my $setOn = "Instance"; |
- |
- # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on Window |
- # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to |
- # get implementation straight out of the Window prototype regardless of what prototype is actually set |
- # on the object. |
- if ($interfaceName eq "Window") { |
- $setOn = "Prototype"; |
- } |
- |
- $subCode .= " desc->${setOn}Template()->SetNamedPropertyHandler("; |
- $subCode .= $namedGetterFunction ? "${implClassName}V8Internal::namedPropertyGetterCallback, " : "0, "; |
- $subCode .= $namedSetterFunction ? "${implClassName}V8Internal::namedPropertySetterCallback, " : "0, "; |
- $subCode .= $namedEnumeratorFunction ? "${implClassName}V8Internal::namedPropertyQueryCallback, " : "0, "; |
- $subCode .= $namedDeleterFunction ? "${implClassName}V8Internal::namedPropertyDeleterCallback, " : "0, "; |
- $subCode .= $namedEnumeratorFunction ? "${implClassName}V8Internal::namedPropertyEnumeratorCallback" : "0"; |
- $subCode .= ");\n"; |
- } |
- |
- return $subCode; |
-} |
- |
-sub GenerateImplementationNamedPropertyGetterCallback |
-{ |
- my $interface = shift; |
- my $hasCustom = shift; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- |
- my $code = "static void namedPropertyGetterCallback(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; |
- $code .= "{\n"; |
- $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\");\n"; |
- if ($hasCustom) { |
- $code .= " ${v8ClassName}::namedPropertyGetterCustom(name, info);\n"; |
- } else { |
- $code .= " ${implClassName}V8Internal::namedPropertyGetter(name, info);\n"; |
- } |
- $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; |
- $code .= "}\n\n"; |
- $implementation{nameSpaceInternal}->add($code); |
-} |
- |
-sub GenerateImplementationNamedPropertySetterCallback |
-{ |
- my $interface = shift; |
- my $hasCustom = shift; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- |
- my $code = "static void namedPropertySetterCallback(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; |
- $code .= "{\n"; |
- $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\");\n"; |
- if ($hasCustom) { |
- $code .= " ${v8ClassName}::namedPropertySetterCustom(name, value, info);\n"; |
- } else { |
- $code .= " ${implClassName}V8Internal::namedPropertySetter(name, value, info);\n"; |
- } |
- $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; |
- $code .= "}\n\n"; |
- $implementation{nameSpaceInternal}->add($code); |
-} |
- |
-sub GenerateImplementationNamedPropertyDeleterCallback |
-{ |
- my $interface = shift; |
- my $hasCustom = shift; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- |
- my $code = "static void namedPropertyDeleterCallback(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Boolean>& info)\n"; |
- $code .= "{\n"; |
- $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\");\n"; |
- if ($hasCustom) { |
- $code .= " ${v8ClassName}::namedPropertyDeleterCustom(name, info);\n"; |
- } else { |
- $code .= " ${implClassName}V8Internal::namedPropertyDeleter(name, info);\n"; |
- } |
- $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; |
- $code .= "}\n\n"; |
- $implementation{nameSpaceInternal}->add($code); |
-} |
- |
-sub GenerateImplementationNamedPropertyEnumeratorCallback |
-{ |
- my $interface = shift; |
- my $hasCustom = shift; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- |
- my $code = "static void namedPropertyEnumeratorCallback(const v8::PropertyCallbackInfo<v8::Array>& info)\n"; |
- $code .= "{\n"; |
- $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\");\n"; |
- if ($hasCustom) { |
- $code .= " ${v8ClassName}::namedPropertyEnumeratorCustom(info);\n"; |
- } else { |
- $code .= " ${implClassName}V8Internal::namedPropertyEnumerator(info);\n"; |
- } |
- $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; |
- $code .= "}\n\n"; |
- $implementation{nameSpaceInternal}->add($code); |
-} |
- |
-sub GenerateImplementationNamedPropertyQueryCallback |
-{ |
- my $interface = shift; |
- my $hasCustom = shift; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- |
- my $code = "static void namedPropertyQueryCallback(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Integer>& info)\n"; |
- $code .= "{\n"; |
- $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\");\n"; |
- if ($hasCustom) { |
- $code .= " ${v8ClassName}::namedPropertyQueryCustom(name, info);\n"; |
- } else { |
- $code .= " ${implClassName}V8Internal::namedPropertyQuery(name, info);\n"; |
- } |
- $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; |
- $code .= "}\n\n"; |
- $implementation{nameSpaceInternal}->add($code); |
-} |
- |
-sub GenerateMethodCall |
-{ |
- my $returnType = shift; # string or UnionType |
- my $returnName = shift; |
- my $functionExpression = shift; |
- my $firstArgument = shift; |
- my $raisesExceptions = shift; |
- |
- my @arguments = (); |
- push @arguments, $firstArgument; |
- if ($raisesExceptions) { |
- push @arguments, "ec"; |
- } |
- |
- if (IsUnionType($returnType)) { |
- my $code = ""; |
- my @extraArguments = (); |
- for my $i (0..scalar(@{$returnType->unionMemberTypes})-1) { |
- my $unionMemberType = $returnType->unionMemberTypes->[$i]; |
- my $nativeType = GetNativeType($unionMemberType); |
- my $unionMemberVariable = $returnName . $i; |
- my $unionMemberEnabledVariable = $returnName . $i . "Enabled"; |
- $code .= " bool ${unionMemberEnabledVariable} = false;\n"; |
- $code .= " ${nativeType} ${unionMemberVariable};\n"; |
- push @extraArguments, $unionMemberEnabledVariable; |
- push @extraArguments, $unionMemberVariable; |
- } |
- push @arguments, @extraArguments; |
- $code .= " ${functionExpression}(" . (join ", ", @arguments) . ");"; |
- return $code; |
- } else { |
- my $nativeType = GetNativeType($returnType); |
- return " ${nativeType} element = ${functionExpression}(" . (join ", ", @arguments) . ");" |
- } |
-} |
- |
-sub GenerateImplementationNamedPropertyGetter |
-{ |
- my $interface = shift; |
- my $namedGetterFunction = shift; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- my $methodName = GetImplName($namedGetterFunction); |
- |
- my $returnType = $namedGetterFunction->type; |
- my $isNull = GenerateIsNullExpression($returnType, "element"); |
- my $nativeValue = "element"; |
- $nativeValue .= ".release()" if (IsRefPtrType($returnType)); |
- my $returnJSValueCode = NativeToJSValue($namedGetterFunction->type, $namedGetterFunction->extendedAttributes, $nativeValue, " ", "", "info.Holder()", "info.GetIsolate()", "info", "collection", "", "", "return"); |
- my $raisesExceptions = $namedGetterFunction->extendedAttributes->{"RaisesException"}; |
- my $methodCallCode = GenerateMethodCall($returnType, "element", "collection->${methodName}", "propertyName", $raisesExceptions); |
- |
- my $code = "static void namedPropertyGetter(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; |
- $code .= "{\n"; |
- if (!$namedGetterFunction->extendedAttributes->{"OverrideBuiltins"}) { |
- $code .= " if (!info.Holder()->GetRealNamedPropertyInPrototypeChain(name).IsEmpty())\n"; |
- $code .= " return;\n"; |
- $code .= " if (info.Holder()->HasRealNamedCallbackProperty(name))\n"; |
- $code .= " return;\n"; |
- $code .= " if (info.Holder()->HasRealNamedProperty(name))\n"; |
- $code .= " return;\n"; |
- } |
- $code .= "\n"; |
- $code .= " ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder()));\n"; |
- $code .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder());\n"; |
- $code .= " AtomicString propertyName = toWebCoreAtomicString(name);\n"; |
- if ($raisesExceptions) { |
- $code .= " ExceptionCode ec = 0;\n"; |
- } |
- $code .= $methodCallCode . "\n"; |
- if ($raisesExceptions) { |
- $code .= " if (ec) {\n"; |
- $code .= " setDOMException(ec, info.GetIsolate());\n"; |
- $code .= " return;\n"; |
- $code .= " }\n"; |
- } |
- if (IsUnionType($returnType)) { |
- $code .= "${returnJSValueCode}\n"; |
- $code .= " return;\n"; |
- } else { |
- $code .= " if (${isNull})\n"; |
- $code .= " return;\n"; |
- $code .= $returnJSValueCode . "\n"; |
- } |
- $code .= "}\n\n"; |
- $implementation{nameSpaceInternal}->add($code); |
-} |
- |
-sub GenerateImplementationNamedPropertySetter |
-{ |
- my $interface = shift; |
- my $namedSetterFunction = shift; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- my $methodName = GetImplName($namedSetterFunction); |
- |
- my $raisesExceptions = $namedSetterFunction->extendedAttributes->{"RaisesException"}; |
- my $treatNullAs = $namedSetterFunction->parameters->[1]->extendedAttributes->{"TreatNullAs"}; |
- my $treatUndefinedAs = $namedSetterFunction->parameters->[1]->extendedAttributes->{"TreatUndefinedAs"}; |
- |
- my $code = "static void namedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; |
- $code .= "{\n"; |
- if (!$namedSetterFunction->extendedAttributes->{"OverrideBuiltins"}) { |
- $code .= " if (!info.Holder()->GetRealNamedPropertyInPrototypeChain(name).IsEmpty())\n"; |
- $code .= " return;\n"; |
- $code .= " if (info.Holder()->HasRealNamedCallbackProperty(name))\n"; |
- $code .= " return;\n"; |
- $code .= " if (info.Holder()->HasRealNamedProperty(name))\n"; |
- $code .= " return;\n"; |
- } |
- $code .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder());\n"; |
- $code .= JSValueToNativeStatement($namedSetterFunction->parameters->[0]->type, $namedSetterFunction->extendedAttributes, "name", "propertyName", " ", "info.GetIsolate()"); |
- $code .= JSValueToNativeStatement($namedSetterFunction->parameters->[1]->type, $namedSetterFunction->extendedAttributes, "value", "propertyValue", " ", "info.GetIsolate()"); |
- my $extraArguments = ""; |
- if ($raisesExceptions) { |
- $code .= " ExceptionCode ec = 0;\n"; |
- $extraArguments = ", ec"; |
- } |
- |
- my @conditions = (); |
- my @statements = (); |
- if ($treatNullAs && $treatNullAs ne "NullString") { |
- push @conditions, "value->IsNull()"; |
- push @statements, "collection->${treatNullAs}(propertyName$extraArguments);"; |
- } |
- if ($treatUndefinedAs && $treatUndefinedAs ne "NullString") { |
- push @conditions, "value->IsUndefined()"; |
- push @statements, "collection->${treatUndefinedAs}(propertyName$extraArguments);"; |
- } |
- push @conditions, ""; |
- push @statements, "collection->${methodName}(propertyName, propertyValue$extraArguments);"; |
- $code .= GenerateIfElseStatement("bool", "result", \@conditions, \@statements); |
- |
- $code .= " if (!result)\n"; |
- $code .= " return;\n"; |
- if ($raisesExceptions) { |
- $code .= " if (ec) {\n"; |
- $code .= " setDOMException(ec, info.GetIsolate());\n"; |
- $code .= " return;\n"; |
- $code .= " }\n"; |
- } |
- $code .= " v8SetReturnValue(info, value);\n"; |
- $code .= "}\n\n"; |
- $implementation{nameSpaceInternal}->add($code); |
-} |
- |
-sub GenerateImplementationIndexedPropertyDeleter |
-{ |
- my $interface = shift; |
- my $indexedDeleterFunction = shift; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- my $methodName = GetImplName($indexedDeleterFunction); |
- |
- my $raisesExceptions = $indexedDeleterFunction->extendedAttributes->{"RaisesException"}; |
- |
- my $code = "static void indexedPropertyDeleter(unsigned index, const v8::PropertyCallbackInfo<v8::Boolean>& info)\n"; |
- $code .= "{\n"; |
- $code .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder());\n"; |
- my $extraArguments = ""; |
- if ($raisesExceptions) { |
- $code .= " ExceptionCode ec = 0;\n"; |
- $extraArguments = ", ec"; |
- } |
- $code .= " bool result = collection->${methodName}(index$extraArguments);\n"; |
- if ($raisesExceptions) { |
- $code .= " if (ec) {\n"; |
- $code .= " setDOMException(ec, info.GetIsolate());\n"; |
- $code .= " return;\n"; |
- $code .= " }\n"; |
- } |
- $code .= " return v8SetReturnValueBool(info, result);\n"; |
- $code .= "}\n\n"; |
- $implementation{nameSpaceInternal}->add($code); |
-} |
- |
-sub GenerateImplementationNamedPropertyDeleter |
-{ |
- my $interface = shift; |
- my $namedDeleterFunction = shift; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- my $methodName = GetImplName($namedDeleterFunction); |
- |
- my $raisesExceptions = $namedDeleterFunction->extendedAttributes->{"RaisesException"}; |
- |
- my $code = "static void namedPropertyDeleter(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Boolean>& info)\n"; |
- $code .= "{\n"; |
- $code .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder());\n"; |
- $code .= " AtomicString propertyName = toWebCoreAtomicString(name);\n"; |
- my $extraArguments = ""; |
- if ($raisesExceptions) { |
- $code .= " ExceptionCode ec = 0;\n"; |
- $extraArguments = ", ec"; |
- } |
- $code .= " bool result = collection->${methodName}(propertyName$extraArguments);\n"; |
- if ($raisesExceptions) { |
- $code .= " if (ec) {\n"; |
- $code .= " setDOMException(ec, info.GetIsolate());\n"; |
- $code .= " return;\n"; |
- $code .= " }\n"; |
- } |
- $code .= " return v8SetReturnValueBool(info, result);\n"; |
- $code .= "}\n\n"; |
- $implementation{nameSpaceInternal}->add($code); |
-} |
- |
-sub GenerateImplementationNamedPropertyEnumerator |
-{ |
- my $interface = shift; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- |
- $implementation{nameSpaceInternal}->add(<<END); |
-static void namedPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) |
-{ |
- ExceptionCode ec = 0; |
- ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder()); |
- Vector<String> names; |
- collection->namedPropertyEnumerator(names, ec); |
- if (ec) { |
- setDOMException(ec, info.GetIsolate()); |
- return; |
- } |
- v8::Handle<v8::Array> v8names = v8::Array::New(names.size()); |
- for (size_t i = 0; i < names.size(); ++i) |
- v8names->Set(v8::Integer::New(i, info.GetIsolate()), v8String(names[i], info.GetIsolate())); |
- v8SetReturnValue(info, v8names); |
-} |
- |
-END |
-} |
- |
-sub GenerateImplementationNamedPropertyQuery |
-{ |
- my $interface = shift; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- |
- $implementation{nameSpaceInternal}->add(<<END); |
-static void namedPropertyQuery(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Integer>& info) |
-{ |
- ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder()); |
- AtomicString propertyName = toWebCoreAtomicString(name); |
- ExceptionCode ec = 0; |
- bool result = collection->namedPropertyQuery(propertyName, ec); |
- if (ec) { |
- setDOMException(ec, info.GetIsolate()); |
- return; |
- } |
- if (!result) |
- return; |
- v8SetReturnValueInt(info, v8::None); |
-} |
- |
-END |
-} |
- |
-sub GenerateImplementationLegacyCall |
-{ |
- my $interface = shift; |
- my $code = ""; |
- |
- my $v8ClassName = GetV8ClassName($interface); |
- |
- if ($interface->extendedAttributes->{"CustomLegacyCall"}) { |
- $code .= " desc->InstanceTemplate()->SetCallAsFunctionHandler(${v8ClassName}::legacyCallCustom);\n"; |
- } |
- return $code; |
-} |
- |
-sub GenerateImplementationMasqueradesAsUndefined |
-{ |
- my $interface = shift; |
- my $code = ""; |
- |
- if ($interface->extendedAttributes->{"MasqueradesAsUndefined"}) |
- { |
- $code .= " desc->InstanceTemplate()->MarkAsUndetectable();\n"; |
- } |
- return $code; |
-} |
- |
-sub GenerateImplementation |
-{ |
- my $object = shift; |
- my $interface = shift; |
- my $interfaceName = $interface->name; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- my $nativeType = GetNativeTypeForConversions($interface); |
- |
- AddToImplIncludes("bindings/v8/V8Binding.h"); |
- AddToImplIncludes("bindings/v8/V8DOMWrapper.h"); |
- AddToImplIncludes("core/dom/ContextFeatures.h"); |
- AddToImplIncludes("core/dom/Document.h"); |
- AddToImplIncludes("RuntimeEnabledFeatures.h"); |
- AddToImplIncludes("core/platform/chromium/TraceEvent.h"); |
- |
- AddIncludesForType($interfaceName); |
- |
- my $toActiveDOMObject = InheritsExtendedAttribute($interface, "ActiveDOMObject") ? "${v8ClassName}::toActiveDOMObject" : "0"; |
- my $toEventTarget = InheritsExtendedAttribute($interface, "EventTarget") ? "${v8ClassName}::toEventTarget" : "0"; |
- my $rootForGC = NeedsOpaqueRootForGC($interface) ? "${v8ClassName}::opaqueRootForGC" : "0"; |
- |
- # Find the super descriptor. |
- my $parentClass = ""; |
- my $parentClassTemplate = ""; |
- if ($interface->parent) { |
- my $parent = $interface->parent; |
- AddToImplIncludes("V8${parent}.h"); |
- $parentClass = "V8" . $parent; |
- $parentClassTemplate = $parentClass . "::GetTemplate(isolate, currentWorldType)"; |
- } |
- |
- my $parentClassInfo = $parentClass ? "&${parentClass}::info" : "0"; |
- my $WrapperTypePrototype = $interface->isException ? "WrapperTypeErrorPrototype" : "WrapperTypeObjectPrototype"; |
- |
- if (!IsSVGTypeNeedingTearOff($interfaceName)) { |
- my $code = <<END; |
-static void initializeScriptWrappableForInterface(${implClassName}* object) |
-{ |
- if (ScriptWrappable::wrapperCanBeStoredInObject(object)) |
- ScriptWrappable::setTypeInfoInObject(object, &${v8ClassName}::info); |
- else |
- ASSERT_NOT_REACHED(); |
-} |
- |
-} // namespace WebCore |
- |
-// In ScriptWrappable::init, the use of a local function declaration has an issue on Windows: |
-// the local declaration does not pick up the surrounding namespace. Therefore, we provide this function |
-// in the global namespace. |
-// (More info on the MSVC bug here: http://connect.microsoft.com/VisualStudio/feedback/details/664619/the-namespace-of-local-function-declarations-in-c) |
-END |
- |
- if (GetNamespaceForInterface($interface) eq "WebCore") { |
- $code .= "void webCoreInitializeScriptWrappableForInterface(WebCore::${implClassName}* object)\n"; |
- } else { |
- $code .= "void webCoreInitializeScriptWrappableForInterface(${implClassName}* object)\n"; |
- } |
- |
- $code .= <<END; |
-{ |
- WebCore::initializeScriptWrappableForInterface(object); |
-} |
- |
-namespace WebCore { |
-END |
- $implementation{nameSpaceWebCore}->addHeader($code); |
- } |
- |
- my $code = "WrapperTypeInfo ${v8ClassName}::info = { ${v8ClassName}::GetTemplate, ${v8ClassName}::derefObject, $toActiveDOMObject, $toEventTarget, "; |
- $code .= "$rootForGC, ${v8ClassName}::installPerContextPrototypeProperties, $parentClassInfo, $WrapperTypePrototype };\n"; |
- $implementation{nameSpaceWebCore}->addHeader($code); |
- |
- $implementation{nameSpaceInternal}->add("template <typename T> void V8_USE(T) { }\n\n"); |
- |
- my $hasConstructors = 0; |
- my $hasReplaceable = 0; |
- |
- # Generate property accessors for attributes. |
- for (my $index = 0; $index < @{$interface->attributes}; $index++) { |
- my $attribute = @{$interface->attributes}[$index]; |
- my $attrType = $attribute->type; |
- my $attrExt = $attribute->extendedAttributes; |
- |
- # Generate special code for the constructor attributes. |
- if ($attrType =~ /Constructor$/) { |
- if (!HasCustomGetter($attrExt)) { |
- $hasConstructors = 1; |
- } |
- next; |
- } |
- |
- if ($attrType eq "EventListener" && $interfaceName eq "Window") { |
- $attrExt->{"OnProto"} = 1; |
- } |
- |
- if ($attrType eq "SerializedScriptValue") { |
- AddToImplIncludes("bindings/v8/SerializedScriptValue.h"); |
- } |
- |
- GenerateNormalAttrGetter($attribute, $interface, ""); |
- GenerateNormalAttrGetterCallback($attribute, $interface, ""); |
- if ($attrExt->{"PerWorldBindings"}) { |
- GenerateNormalAttrGetter($attribute, $interface, "ForMainWorld"); |
- GenerateNormalAttrGetterCallback($attribute, $interface, "ForMainWorld"); |
- } |
- if (!HasCustomSetter($attrExt) && $attrExt->{"Replaceable"}) { |
- $hasReplaceable = 1; |
- } elsif (!IsReadonly($attribute)) { |
- GenerateNormalAttrSetter($attribute, $interface, ""); |
- GenerateNormalAttrSetterCallback($attribute, $interface, ""); |
- if ($attrExt->{"PerWorldBindings"}) { |
- GenerateNormalAttrSetter($attribute, $interface, "ForMainWorld"); |
- GenerateNormalAttrSetterCallback($attribute, $interface, "ForMainWorld"); |
- } |
- } |
- } |
- |
- if ($hasConstructors) { |
- GenerateConstructorGetter($interface); |
- } |
- |
- if ($hasConstructors || $hasReplaceable) { |
- GenerateReplaceableAttrSetter($interface); |
- GenerateReplaceableAttrSetterCallback($interface); |
- } |
- |
- if (NeedsOpaqueRootForGC($interface)) { |
- GenerateOpaqueRootForGC($interface); |
- } |
- |
- if ($interface->extendedAttributes->{"CheckSecurity"} && $interface->name ne "Window") { |
- GenerateSecurityCheckFunctions($interface); |
- } |
- |
- if (IsConstructorTemplate($interface, "TypedArray")) { |
- my ($nativeType, $arrayType) = GetNativeTypeOfTypedArray($interface); |
- $implementation{nameSpaceWebCore}->add(<<END); |
-v8::Handle<v8::Object> wrap($implClassName* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) |
-{ |
- ASSERT(impl); |
- v8::Handle<v8::Object> wrapper = ${v8ClassName}::createWrapper(impl, creationContext, isolate); |
- if (!wrapper.IsEmpty()) |
- wrapper->SetIndexedPropertiesToExternalArrayData(impl->baseAddress(), $arrayType, impl->length()); |
- return wrapper; |
-} |
- |
-END |
- } |
- |
- my @enabledPerContextFunctions; |
- my @normalFunctions; |
- my $needsDomainSafeFunctionSetter = 0; |
- # Generate methods for functions. |
- foreach my $function (@{$interface->functions}) { |
- next if $function->name eq ""; |
- GenerateFunction($function, $interface, ""); |
- if ($function->extendedAttributes->{"PerWorldBindings"}) { |
- GenerateFunction($function, $interface, "ForMainWorld"); |
- } |
- if ($function->{overloadIndex} == @{$function->{overloads}}) { |
- if ($function->{overloadIndex} > 1) { |
- GenerateOverloadedFunction($function, $interface, ""); |
- if ($function->extendedAttributes->{"PerWorldBindings"}) { |
- GenerateOverloadedFunction($function, $interface, "ForMainWorld"); |
- } |
- } |
- GenerateFunctionCallback($function, $interface, ""); |
- if ($function->extendedAttributes->{"PerWorldBindings"}) { |
- GenerateFunctionCallback($function, $interface, "ForMainWorld"); |
- } |
- } |
- |
- # 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 ($interface->extendedAttributes->{"CheckSecurity"} && $function->extendedAttributes->{"DoNotCheckSecurity"}) { |
- if (!HasCustomMethod($function->extendedAttributes) || $function->{overloadIndex} == 1) { |
- GenerateDomainSafeFunctionGetter($function, $interface); |
- if (!$function->extendedAttributes->{"ReadOnly"}) { |
- $needsDomainSafeFunctionSetter = 1; |
- } |
- } |
- } |
- |
- # Separate out functions that are enabled per context so we can process them specially. |
- if ($function->extendedAttributes->{"EnabledPerContext"}) { |
- push(@enabledPerContextFunctions, $function); |
- } else { |
- push(@normalFunctions, $function); |
- } |
- } |
- |
- if ($needsDomainSafeFunctionSetter) { |
- GenerateDomainSafeFunctionSetter($interface); |
- } |
- |
- # Attributes |
- my $attributes = $interface->attributes; |
- |
- # For the Window 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 @enabledAtRuntimeAttributes; |
- my @enabledPerContextAttributes; |
- my @normalAttributes; |
- foreach my $attribute (@$attributes) { |
- |
- if ($interfaceName eq "Window" && $attribute->extendedAttributes->{"Unforgeable"}) { |
- push(@disallowsShadowing, $attribute); |
- } elsif ($attribute->extendedAttributes->{"EnabledAtRuntime"} || $attribute->extendedAttributes->{"EnabledPerContext"}) { |
- if ($attribute->extendedAttributes->{"EnabledPerContext"}) { |
- push(@enabledPerContextAttributes, $attribute); |
- } |
- if ($attribute->extendedAttributes->{"EnabledAtRuntime"}) { |
- push(@enabledAtRuntimeAttributes, $attribute); |
- } |
- } else { |
- push(@normalAttributes, $attribute); |
- } |
- } |
- AddToImplIncludes("bindings/v8/V8DOMConfiguration.h"); |
- $attributes = \@normalAttributes; |
- # Put the attributes that disallow shadowing on the shadow object. |
- if (@disallowsShadowing) { |
- my $code = ""; |
- $code .= "static const V8DOMConfiguration::BatchedAttribute shadowAttrs[] = {\n"; |
- $code .= GenerateBatchedAttributeData($interface, \@disallowsShadowing); |
- $code .= "};\n\n"; |
- $implementation{nameSpaceWebCore}->add($code); |
- } |
- |
- my $has_attributes = 0; |
- if (@$attributes) { |
- $has_attributes = 1; |
- my $code = ""; |
- $code .= "static const V8DOMConfiguration::BatchedAttribute ${v8ClassName}Attrs[] = {\n"; |
- $code .= GenerateBatchedAttributeData($interface, $attributes); |
- $code .= "};\n\n"; |
- $implementation{nameSpaceWebCore}->add($code); |
- } |
- |
- # Setup table of standard callback functions |
- my $num_callbacks = 0; |
- my $has_callbacks = 0; |
- $code = ""; |
- foreach my $function (@normalFunctions) { |
- # Only one table entry is needed for overloaded methods: |
- next if $function->{overloadIndex} > 1; |
- # Don't put any nonstandard functions into this table: |
- next if !IsStandardFunction($interface, $function); |
- next if $function->name eq ""; |
- if (!$has_callbacks) { |
- $has_callbacks = 1; |
- $code .= "static const V8DOMConfiguration::BatchedMethod ${v8ClassName}Methods[] = {\n"; |
- } |
- my $name = $function->name; |
- my $methodForMainWorld = "0"; |
- if ($function->extendedAttributes->{"PerWorldBindings"}) { |
- $methodForMainWorld = "${implClassName}V8Internal::${name}MethodCallbackForMainWorld"; |
- } |
- my $functionLength = GetFunctionLength($function); |
- my $conditionalString = GenerateConditionalString($function); |
- $code .= "#if ${conditionalString}\n" if $conditionalString; |
- $code .= <<END; |
- {"$name", ${implClassName}V8Internal::${name}MethodCallback, ${methodForMainWorld}, ${functionLength}}, |
-END |
- $code .= "#endif\n" if $conditionalString; |
- $num_callbacks++; |
- } |
- $code .= "};\n\n" if $has_callbacks; |
- $implementation{nameSpaceWebCore}->add($code); |
- |
- # Setup constants |
- my $has_constants = 0; |
- my @constantsEnabledAtRuntime; |
- $code = ""; |
- if (@{$interface->constants}) { |
- $has_constants = 1; |
- $code .= "static const V8DOMConfiguration::BatchedConstant ${v8ClassName}Consts[] = {\n"; |
- } |
- foreach my $constant (@{$interface->constants}) { |
- my $name = $constant->name; |
- my $value = $constant->value; |
- my $attrExt = $constant->extendedAttributes; |
- my $implementedBy = $attrExt->{"ImplementedBy"}; |
- if ($implementedBy) { |
- my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy); |
- AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implementedByImplName)); |
- } |
- if ($attrExt->{"EnabledAtRuntime"}) { |
- push(@constantsEnabledAtRuntime, $constant); |
- } else { |
- my $conditionalString = GenerateConditionalString($constant); |
- $code .= "#if ${conditionalString}\n" if $conditionalString; |
- # If the value we're dealing with is a hex number, preprocess it into a signed integer |
- # here, rather than running static_cast<signed int> in the generated code. |
- if (substr($value, 0, 2) eq "0x") { |
- $value = unpack('i', pack('I', hex($value))); |
- } |
- $code .= <<END; |
- {"${name}", $value}, |
-END |
- $code .= "#endif\n" if $conditionalString; |
- } |
- } |
- if ($has_constants) { |
- $code .= "};\n\n"; |
- $code .= join "", GenerateCompileTimeCheckForEnumsIfNeeded($interface); |
- $implementation{nameSpaceWebCore}->add($code); |
- } |
- |
- if (!HasCustomConstructor($interface)) { |
- if ($interface->extendedAttributes->{"NamedConstructor"}) { |
- GenerateNamedConstructor(@{$interface->constructors}[0], $interface); |
- } elsif ($interface->extendedAttributes->{"Constructor"}) { |
- GenerateConstructor($interface); |
- } elsif (IsConstructorTemplate($interface, "Event")) { |
- GenerateEventConstructor($interface); |
- } elsif (IsConstructorTemplate($interface, "TypedArray")) { |
- GenerateTypedArrayConstructor($interface); |
- } |
- } |
- if (IsConstructable($interface)) { |
- GenerateConstructorCallback($interface); |
- } |
- |
- my $access_check = ""; |
- if ($interface->extendedAttributes->{"CheckSecurity"} && $interfaceName ne "Window") { |
- $access_check = "instance->SetAccessCheckCallbacks(${implClassName}V8Internal::namedSecurityCheck, ${implClassName}V8Internal::indexedSecurityCheck, v8::External::New(&${v8ClassName}::info));"; |
- } |
- |
- # For the Window interface, generate the shadow object template |
- # configuration method. |
- if ($interfaceName eq "Window") { |
- $implementation{nameSpaceWebCore}->add(<<END); |
-static void ConfigureShadowObjectTemplate(v8::Handle<v8::ObjectTemplate> templ, v8::Isolate* isolate, WrapperWorldType currentWorldType) |
-{ |
- V8DOMConfiguration::batchConfigureAttributes(templ, v8::Handle<v8::ObjectTemplate>(), shadowAttrs, WTF_ARRAY_LENGTH(shadowAttrs), isolate, currentWorldType); |
- |
- // Install a security handler with V8. |
- templ->SetAccessCheckCallbacks(V8Window::namedSecurityCheckCustom, V8Window::indexedSecurityCheckCustom, v8::External::New(&V8Window::info)); |
- templ->SetInternalFieldCount(V8Window::internalFieldCount); |
-} |
-END |
- } |
- |
- if (!$parentClassTemplate) { |
- $parentClassTemplate = "v8::Local<v8::FunctionTemplate>()"; |
- } |
- |
- # Generate the template configuration method |
- $code = <<END; |
-static v8::Handle<v8::FunctionTemplate> Configure${v8ClassName}Template(v8::Handle<v8::FunctionTemplate> desc, v8::Isolate* isolate, WrapperWorldType currentWorldType) |
-{ |
- desc->ReadOnlyPrototype(); |
- |
- v8::Local<v8::Signature> defaultSignature; |
-END |
- if ($interface->extendedAttributes->{"EnabledAtRuntime"}) { |
- my $enable_function = GetRuntimeEnableFunctionName($interface); |
- $code .= <<END; |
- if (!${enable_function}()) |
- defaultSignature = V8DOMConfiguration::configureTemplate(desc, \"\", $parentClassTemplate, ${v8ClassName}::internalFieldCount, 0, 0, 0, 0, isolate, currentWorldType); |
- else |
-END |
- } |
- $code .= <<END; |
- defaultSignature = V8DOMConfiguration::configureTemplate(desc, \"${interfaceName}\", $parentClassTemplate, ${v8ClassName}::internalFieldCount, |
-END |
- # Set up our attributes if we have them |
- if ($has_attributes) { |
- $code .= <<END; |
- ${v8ClassName}Attrs, WTF_ARRAY_LENGTH(${v8ClassName}Attrs), |
-END |
- } else { |
- $code .= <<END; |
- 0, 0, |
-END |
- } |
- |
- if ($has_callbacks) { |
- $code .= <<END; |
- ${v8ClassName}Methods, WTF_ARRAY_LENGTH(${v8ClassName}Methods), isolate, currentWorldType); |
-END |
- } else { |
- $code .= <<END; |
- 0, 0, isolate, currentWorldType); |
-END |
- } |
- |
- AddToImplIncludes("wtf/UnusedParam.h"); |
- $code .= <<END; |
- UNUSED_PARAM(defaultSignature); // In some cases, it will not be used. |
-END |
- |
- if (IsConstructable($interface)) { |
- $code .= " desc->SetCallHandler(${v8ClassName}::constructorCallback);\n"; |
- my $interfaceLength = GetInterfaceLength($interface); |
- $code .= " desc->SetLength(${interfaceLength});\n"; |
- } |
- |
- if ($access_check or @enabledAtRuntimeAttributes or @normalFunctions or $has_constants) { |
- $code .= <<END; |
- v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate(); |
- v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate(); |
- UNUSED_PARAM(instance); // In some cases, it will not be used. |
- UNUSED_PARAM(proto); // In some cases, it will not be used. |
-END |
- } |
- |
- if ($access_check) { |
- $code .= " $access_check\n"; |
- } |
- |
- # Setup the enable-at-runtime attrs if we have them |
- foreach my $runtime_attr (@enabledAtRuntimeAttributes) { |
- next if grep { $_ eq $runtime_attr } @enabledPerContextAttributes; |
- my $enable_function = GetRuntimeEnableFunctionName($runtime_attr); |
- my $conditionalString = GenerateConditionalString($runtime_attr); |
- $code .= "\n#if ${conditionalString}\n" if $conditionalString; |
- $code .= " if (${enable_function}()) {\n"; |
- $code .= " static const V8DOMConfiguration::BatchedAttribute attrData =\\\n"; |
- $code .= GenerateSingleBatchedAttribute($interface, $runtime_attr, ";", " "); |
- $code .= <<END; |
- V8DOMConfiguration::configureAttribute(instance, proto, attrData, isolate, currentWorldType); |
- } |
-END |
- $code .= "\n#endif // ${conditionalString}\n" if $conditionalString; |
- } |
- |
- # Setup the enable-at-runtime constants if we have them |
- foreach my $runtime_const (@constantsEnabledAtRuntime) { |
- my $enable_function = GetRuntimeEnableFunctionName($runtime_const); |
- my $conditionalString = GenerateConditionalString($runtime_const); |
- my $name = $runtime_const->name; |
- my $value = $runtime_const->value; |
- $code .= "\n#if ${conditionalString}\n" if $conditionalString; |
- $code .= " if (${enable_function}()) {\n"; |
- $code .= <<END; |
- static const V8DOMConfiguration::BatchedConstant constData = {"${name}", static_cast<signed int>(${value})}; |
- V8DOMConfiguration::batchConfigureConstants(desc, proto, &constData, 1, isolate); |
-END |
- $code .= " }\n"; |
- $code .= "\n#endif // ${conditionalString}\n" if $conditionalString; |
- } |
- |
- $code .= GenerateImplementationIndexedPropertyAccessors($interface); |
- $code .= GenerateImplementationNamedPropertyAccessors($interface); |
- $code .= GenerateImplementationLegacyCall($interface); |
- $code .= GenerateImplementationMasqueradesAsUndefined($interface); |
- |
- # Define our functions with Set() or SetAccessor() |
- my $total_functions = 0; |
- foreach my $function (@normalFunctions) { |
- # Only one accessor is needed for overloaded methods: |
- next if $function->{overloadIndex} > 1; |
- next if $function->name eq ""; |
- |
- $total_functions++; |
- next if IsStandardFunction($interface, $function); |
- $code .= GenerateNonStandardFunction($interface, $function); |
- $num_callbacks++; |
- } |
- |
- die "Wrong number of callbacks generated for $interfaceName ($num_callbacks, should be $total_functions)" if $num_callbacks != $total_functions; |
- |
- if ($has_constants) { |
- $code .= <<END; |
- V8DOMConfiguration::batchConfigureConstants(desc, proto, ${v8ClassName}Consts, WTF_ARRAY_LENGTH(${v8ClassName}Consts), isolate); |
-END |
- } |
- |
- # Special cases |
- if ($interfaceName eq "Window") { |
- $code .= <<END; |
- |
- proto->SetInternalFieldCount(V8Window::internalFieldCount); |
- desc->SetHiddenPrototype(true); |
- instance->SetInternalFieldCount(V8Window::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(V8Window::namedSecurityCheckCustom, V8Window::indexedSecurityCheckCustom, v8::External::New(&V8Window::info), false); |
-END |
- } |
- if ($interfaceName eq "HTMLDocument" or $interfaceName eq "DedicatedWorkerGlobalScope" or $interfaceName eq "SharedWorkerGlobalScope") { |
- $code .= <<END; |
- desc->SetHiddenPrototype(true); |
-END |
- } |
- |
- $code .= <<END; |
- |
- // Custom toString template |
- desc->Set(v8::String::NewSymbol("toString"), V8PerIsolateData::current()->toStringTemplate()); |
- return desc; |
-} |
- |
-END |
- $implementation{nameSpaceWebCore}->add($code); |
- |
- $implementation{nameSpaceWebCore}->add(<<END); |
-v8::Handle<v8::FunctionTemplate> ${v8ClassName}::GetTemplate(v8::Isolate* isolate, WrapperWorldType currentWorldType) |
-{ |
- V8PerIsolateData* data = V8PerIsolateData::from(isolate); |
- V8PerIsolateData::TemplateMap::iterator result = data->templateMap(currentWorldType).find(&info); |
- if (result != data->templateMap(currentWorldType).end()) |
- return result->value.newLocal(isolate); |
- |
- TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate"); |
- v8::HandleScope handleScope(isolate); |
- v8::Handle<v8::FunctionTemplate> templ = |
- Configure${v8ClassName}Template(data->rawTemplate(&info, currentWorldType), isolate, currentWorldType); |
- data->templateMap(currentWorldType).add(&info, UnsafePersistent<v8::FunctionTemplate>(isolate, templ)); |
- return handleScope.Close(templ); |
-} |
- |
-END |
- $implementation{nameSpaceWebCore}->add(<<END); |
-bool ${v8ClassName}::HasInstance(v8::Handle<v8::Value> value, v8::Isolate* isolate, WrapperWorldType currentWorldType) |
-{ |
- return V8PerIsolateData::from(isolate)->hasInstance(&info, value, currentWorldType); |
-} |
- |
-END |
- $implementation{nameSpaceWebCore}->add(<<END); |
-bool ${v8ClassName}::HasInstanceInAnyWorld(v8::Handle<v8::Value> value, v8::Isolate* isolate) |
-{ |
- return V8PerIsolateData::from(isolate)->hasInstance(&info, value, MainWorld) |
- || V8PerIsolateData::from(isolate)->hasInstance(&info, value, IsolatedWorld) |
- || V8PerIsolateData::from(isolate)->hasInstance(&info, value, WorkerWorld); |
-} |
- |
-END |
- |
- if (@enabledPerContextAttributes) { |
- my $code = ""; |
- $code .= <<END; |
-void ${v8ClassName}::installPerContextProperties(v8::Handle<v8::Object> instance, ${nativeType}* impl, v8::Isolate* isolate) |
-{ |
- v8::Local<v8::Object> proto = v8::Local<v8::Object>::Cast(instance->GetPrototype()); |
-END |
- |
- # Setup the enable-by-settings attrs if we have them |
- foreach my $runtimeAttr (@enabledPerContextAttributes) { |
- my $enableFunction = GetContextEnableFunction($runtimeAttr); |
- my $conditionalString = GenerateConditionalString($runtimeAttr); |
- $code .= "\n#if ${conditionalString}\n" if $conditionalString; |
- if (grep { $_ eq $runtimeAttr } @enabledAtRuntimeAttributes) { |
- my $runtimeEnableFunction = GetRuntimeEnableFunctionName($runtimeAttr); |
- $code .= " if (${enableFunction}(impl->document()) && ${runtimeEnableFunction}()) {\n"; |
- } else { |
- $code .= " if (${enableFunction}(impl->document())) {\n"; |
- } |
- |
- $code .= " static const V8DOMConfiguration::BatchedAttribute attrData =\\\n"; |
- $code .= GenerateSingleBatchedAttribute($interface, $runtimeAttr, ";", " "); |
- $code .= <<END; |
- V8DOMConfiguration::configureAttribute(instance, proto, attrData, isolate); |
-END |
- $code .= " }\n"; |
- $code .= "#endif // ${conditionalString}\n" if $conditionalString; |
- } |
- $code .= <<END; |
-} |
- |
-END |
- $implementation{nameSpaceWebCore}->add($code); |
- } |
- |
- if (@enabledPerContextFunctions) { |
- my $code = ""; |
- $code .= <<END; |
-void ${v8ClassName}::installPerContextPrototypeProperties(v8::Handle<v8::Object> proto, v8::Isolate* isolate) |
-{ |
- UNUSED_PARAM(proto); |
-END |
- # Setup the enable-by-settings functions if we have them |
- $code .= <<END; |
- v8::Local<v8::Signature> defaultSignature = v8::Signature::New(GetTemplate(isolate, worldType(isolate))); |
- UNUSED_PARAM(defaultSignature); // In some cases, it will not be used. |
- |
- ScriptExecutionContext* context = toScriptExecutionContext(proto->CreationContext()); |
-END |
- |
- foreach my $runtimeFunc (@enabledPerContextFunctions) { |
- my $enableFunction = GetContextEnableFunction($runtimeFunc); |
- my $functionLength = GetFunctionLength($runtimeFunc); |
- my $conditionalString = GenerateConditionalString($runtimeFunc); |
- $code .= "\n#if ${conditionalString}\n" if $conditionalString; |
- $code .= " if (context && context->isDocument() && ${enableFunction}(toDocument(context)))\n"; |
- my $name = $runtimeFunc->name; |
- $code .= <<END; |
- proto->Set(v8::String::NewSymbol("${name}"), v8::FunctionTemplate::New(${implClassName}V8Internal::${name}MethodCallback, v8Undefined(), defaultSignature, $functionLength)->GetFunction()); |
-END |
- $code .= "#endif // ${conditionalString}\n" if $conditionalString; |
- } |
- |
- $code .= <<END; |
-} |
- |
-END |
- $implementation{nameSpaceWebCore}->add($code); |
- } |
- |
- if (InheritsExtendedAttribute($interface, "ActiveDOMObject")) { |
- # 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)"; |
- $implementation{nameSpaceWebCore}->add(<<END); |
-ActiveDOMObject* ${v8ClassName}::toActiveDOMObject(v8::Handle<v8::Object> object) |
-{ |
- return $returnValue; |
-} |
- |
-END |
- } |
- |
- if (InheritsExtendedAttribute($interface, "EventTarget")) { |
- $implementation{nameSpaceWebCore}->add(<<END); |
-EventTarget* ${v8ClassName}::toEventTarget(v8::Handle<v8::Object> object) |
-{ |
- return toNative(object); |
-} |
- |
-END |
- } |
- |
- if ($interfaceName eq "Window") { |
- $implementation{nameSpaceWebCore}->add(<<END); |
-v8::Handle<v8::ObjectTemplate> V8Window::GetShadowObjectTemplate(v8::Isolate* isolate, WrapperWorldType currentWorldType) |
-{ |
- if (currentWorldType == MainWorld) { |
- static v8::Persistent<v8::ObjectTemplate> V8WindowShadowObjectCacheForMainWorld; |
- if (V8WindowShadowObjectCacheForMainWorld.IsEmpty()) { |
- TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate"); |
- v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(); |
- ConfigureShadowObjectTemplate(templ, isolate, currentWorldType); |
- V8WindowShadowObjectCacheForMainWorld.Reset(isolate, templ); |
- return templ; |
- } |
- return v8::Local<v8::ObjectTemplate>::New(isolate, V8WindowShadowObjectCacheForMainWorld); |
- } else { |
- static v8::Persistent<v8::ObjectTemplate> V8WindowShadowObjectCacheForNonMainWorld; |
- if (V8WindowShadowObjectCacheForNonMainWorld.IsEmpty()) { |
- TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate"); |
- v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(); |
- ConfigureShadowObjectTemplate(templ, isolate, currentWorldType); |
- V8WindowShadowObjectCacheForNonMainWorld.Reset(isolate, templ); |
- return templ; |
- } |
- return v8::Local<v8::ObjectTemplate>::New(isolate, V8WindowShadowObjectCacheForNonMainWorld); |
- } |
-} |
- |
-END |
- } |
- |
- GenerateToV8Converters($interface, $v8ClassName, $nativeType); |
- |
- $implementation{nameSpaceWebCore}->add(<<END); |
-void ${v8ClassName}::derefObject(void* object) |
-{ |
- static_cast<${nativeType}*>(object)->deref(); |
-} |
- |
-END |
-} |
- |
-sub GenerateHeaderContentHeader |
-{ |
- my $interface = shift; |
- my $v8ClassName = GetV8ClassName($interface); |
- my $conditionalString = GenerateConditionalString($interface); |
- |
- my @headerContentHeader = split("\r", $headerTemplate); |
- |
- push(@headerContentHeader, "\n#ifndef ${v8ClassName}" . "_h\n"); |
- push(@headerContentHeader, "#define ${v8ClassName}" . "_h\n\n"); |
- push(@headerContentHeader, "#if ${conditionalString}\n") if $conditionalString; |
- return join "", @headerContentHeader; |
-} |
- |
-sub GenerateCallbackHeader |
-{ |
- my $object = shift; |
- my $interface = shift; |
- |
- my $interfaceName = $interface->name; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- |
- $header{root}->addFooter("\n"); |
- |
- my @includes = (); |
- push(@includes, "bindings/v8/ActiveDOMCallback.h"); |
- push(@includes, "bindings/v8/DOMWrapperWorld.h"); |
- push(@includes, "bindings/v8/ScopedPersistent.h"); |
- push(@includes, HeaderFilesForInterface($interfaceName, $implClassName)); |
- for my $include (sort @includes) { |
- $header{includes}->add("#include \"$include\"\n"); |
- } |
- $header{nameSpaceWebCore}->addHeader("\nclass ScriptExecutionContext;\n\n"); |
- $header{class}->addHeader("class $v8ClassName : public $implClassName, public ActiveDOMCallback {"); |
- $header{class}->addFooter("};\n"); |
- |
- $header{classPublic}->add(<<END); |
- static PassRefPtr<${v8ClassName}> create(v8::Handle<v8::Value> value, ScriptExecutionContext* context) |
- { |
- ASSERT(value->IsObject()); |
- ASSERT(context); |
- return adoptRef(new ${v8ClassName}(v8::Handle<v8::Object>::Cast(value), context)); |
- } |
- |
- virtual ~${v8ClassName}(); |
- |
-END |
- |
- # Functions |
- my $numFunctions = @{$interface->functions}; |
- if ($numFunctions > 0) { |
- $header{classPublic}->add(" // Functions\n"); |
- foreach my $function (@{$interface->functions}) { |
- my $code = " virtual " . GetNativeTypeForCallbacks($function->type) . " " . $function->name . "("; |
- |
- my @args = (); |
- if (ExtendedAttributeContains($function->extendedAttributes->{"CallWith"}, "ThisValue")) { |
- push(@args, GetNativeType("any") . " thisValue"); |
- } |
- my @params = @{$function->parameters}; |
- foreach my $param (@params) { |
- push(@args, GetNativeTypeForCallbacks($param->type) . " " . $param->name); |
- } |
- $code .= join(", ", @args); |
- $code .= ");\n"; |
- $header{classPublic}->add($code); |
- } |
- } |
- |
- $header{classPublic}->add(<<END); |
- |
- virtual ScriptExecutionContext* scriptExecutionContext() const { return ContextLifecycleObserver::scriptExecutionContext(); } |
- |
-END |
- $header{classPrivate}->add(<<END); |
- ${v8ClassName}(v8::Handle<v8::Object>, ScriptExecutionContext*); |
- |
- ScopedPersistent<v8::Object> m_callback; |
- RefPtr<DOMWrapperWorld> m_world; |
-END |
-} |
- |
-sub GenerateCallbackImplementation |
-{ |
- my $object = shift; |
- my $interface = shift; |
- my $v8ClassName = GetV8ClassName($interface); |
- |
- AddToImplIncludes("core/dom/ScriptExecutionContext.h"); |
- AddToImplIncludes("bindings/v8/V8Binding.h"); |
- AddToImplIncludes("bindings/v8/V8Callback.h"); |
- AddToImplIncludes("wtf/Assertions.h"); |
- |
- $implementation{nameSpaceWebCore}->add(<<END); |
-${v8ClassName}::${v8ClassName}(v8::Handle<v8::Object> callback, ScriptExecutionContext* context) |
- : ActiveDOMCallback(context) |
- , m_callback(callback) |
- , m_world(DOMWrapperWorld::current()) |
-{ |
-} |
- |
-END |
- |
- $implementation{nameSpaceWebCore}->add(<<END); |
-${v8ClassName}::~${v8ClassName}() |
-{ |
-} |
- |
-END |
- |
- # Functions |
- my $numFunctions = @{$interface->functions}; |
- if ($numFunctions > 0) { |
- $implementation{nameSpaceWebCore}->add("// Functions\n"); |
- foreach my $function (@{$interface->functions}) { |
- my $code = ""; |
- my @params = @{$function->parameters}; |
- next if $function->extendedAttributes->{"Custom"}; |
- |
- AddIncludesForType($function->type); |
- die "We don't yet support callbacks that return non-boolean values.\n" if $function->type ne "boolean"; |
- $code .= "\n" . GetNativeTypeForCallbacks($function->type) . " ${v8ClassName}::" . $function->name . "("; |
- my $callWithThisValue = ExtendedAttributeContains($function->extendedAttributes->{"CallWith"}, "ThisValue"); |
- |
- my @args = (); |
- if ($callWithThisValue) { |
- push(@args, GetNativeTypeForCallbacks("any") . " thisValue"); |
- } |
- foreach my $param (@params) { |
- my $paramName = $param->name; |
- my $type = $param->type; |
- my $arrayOrSequenceType = GetArrayOrSequenceType($type); |
- |
- if ($arrayOrSequenceType) { |
- if (IsRefPtrType($arrayOrSequenceType)) { |
- AddIncludesForType($arrayOrSequenceType); |
- } |
- } else { |
- AddIncludesForType($type); |
- } |
- |
- push(@args, GetNativeTypeForCallbacks($type) . " " . $paramName); |
- } |
- $code .= join(", ", @args); |
- |
- $code .= ")\n"; |
- $code .= "{\n"; |
- $code .= " if (!canInvokeCallback())\n"; |
- $code .= " return true;\n\n"; |
- $code .= " v8::Isolate* isolate = v8::Isolate::GetCurrent();\n"; |
- $code .= " v8::HandleScope handleScope(isolate);\n\n"; |
- $code .= " v8::Handle<v8::Context> v8Context = toV8Context(scriptExecutionContext(), m_world.get());\n"; |
- $code .= " if (v8Context.IsEmpty())\n"; |
- $code .= " return true;\n\n"; |
- $code .= " v8::Context::Scope scope(v8Context);\n\n"; |
- |
- my $thisObjectHandle = ""; |
- if ($callWithThisValue) { |
- $code .= " v8::Handle<v8::Value> thisHandle = thisValue.v8Value();\n"; |
- $code .= " if (thisHandle.IsEmpty()) {\n"; |
- $code .= " if (!isScriptControllerTerminating())\n"; |
- $code .= " CRASH();\n"; |
- $code .= " return true;\n"; |
- $code .= " }\n"; |
- $code .= " ASSERT(thisHandle->isObject());\n"; |
- $thisObjectHandle = "v8::Handle<v8::Object>::Cast(thisHandle), "; |
- } |
- @args = (); |
- foreach my $param (@params) { |
- my $paramName = $param->name; |
- $code .= NativeToJSValue($param->type, $param->extendedAttributes, $paramName, " ", "v8::Handle<v8::Value> ${paramName}Handle =", "v8::Handle<v8::Object>()", "isolate", "") . "\n"; |
- $code .= " if (${paramName}Handle.IsEmpty()) {\n"; |
- $code .= " if (!isScriptControllerTerminating())\n"; |
- $code .= " CRASH();\n"; |
- $code .= " return true;\n"; |
- $code .= " }\n"; |
- push(@args, " ${paramName}Handle"); |
- } |
- |
- if (scalar(@args) > 0) { |
- $code .= "\n v8::Handle<v8::Value> argv[] = {\n"; |
- $code .= join(",\n", @args); |
- $code .= "\n };\n\n"; |
- } else { |
- $code .= "\n v8::Handle<v8::Value> *argv = 0;\n\n"; |
- } |
- $code .= " bool callbackReturnValue = false;\n"; |
- $code .= " return !invokeCallback(m_callback.newLocal(isolate), ${thisObjectHandle}" . scalar(@args) . ", argv, callbackReturnValue, scriptExecutionContext());\n"; |
- $code .= "}\n"; |
- $implementation{nameSpaceWebCore}->add($code); |
- } |
- } |
-} |
- |
-sub BaseInterfaceName |
-{ |
- my $interface = shift; |
- |
- while ($interface->parent) { |
- $interface = ParseInterface($interface->parent); |
- } |
- |
- return $interface->name; |
-} |
- |
-sub GenerateToV8Converters |
-{ |
- my $interface = shift; |
- my $v8ClassName = shift; |
- my $nativeType = shift; |
- my $interfaceName = $interface->name; |
- |
- if ($interface->extendedAttributes->{"DoNotGenerateWrap"} || $interface->extendedAttributes->{"DoNotGenerateToV8"}) { |
- return; |
- } |
- |
- AddToImplIncludes("bindings/v8/ScriptController.h"); |
- AddToImplIncludes("core/page/Frame.h"); |
- |
- my $createWrapperArgumentType = GetPassRefPtrType($nativeType); |
- my $baseType = BaseInterfaceName($interface); |
- |
- # FIXME: Do we really need to treat "GenerateIsReachable", "CustomIsReachable" and /SVG/ |
- # as dependent DOM objects? |
- my $wrapperConfiguration = "WrapperConfiguration::Independent"; |
- if (InheritsExtendedAttribute($interface, "ActiveDOMObject") |
- || InheritsExtendedAttribute($interface, "DependentLifetime") |
- || InheritsExtendedAttribute($interface, "GenerateIsReachable") |
- || InheritsExtendedAttribute($interface, "CustomIsReachable") |
- || $v8ClassName =~ /SVG/) { |
- $wrapperConfiguration = "WrapperConfiguration::Dependent"; |
- } |
- |
- my $code = ""; |
- $code .= <<END; |
- |
-v8::Handle<v8::Object> ${v8ClassName}::createWrapper(${createWrapperArgumentType} impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) |
-{ |
- ASSERT(impl.get()); |
- ASSERT(DOMDataStore::getWrapper(impl.get(), isolate).IsEmpty()); |
-END |
- |
- $code .= <<END if ($baseType ne $interfaceName); |
- ASSERT(static_cast<void*>(static_cast<${baseType}*>(impl.get())) == static_cast<void*>(impl.get())); |
-END |
- |
- if (InheritsInterface($interface, "Document")) { |
- $code .= <<END; |
- if (Frame* frame = impl->frame()) { |
- if (frame->script()->initializeMainWorld()) { |
- // initializeMainWorld may have created a wrapper for the object, retry from the start. |
- v8::Handle<v8::Object> wrapper = DOMDataStore::getWrapper(impl.get(), isolate); |
- if (!wrapper.IsEmpty()) |
- return wrapper; |
- } |
- } |
-END |
- } |
- |
- $code .= <<END; |
- |
- v8::Handle<v8::Object> wrapper = V8DOMWrapper::createWrapper(creationContext, &info, impl.get(), isolate); |
- if (UNLIKELY(wrapper.IsEmpty())) |
- return wrapper; |
-END |
- if (IsTypedArrayType($interface->name)) { |
- AddToImplIncludes("bindings/v8/custom/V8ArrayBufferCustom.h"); |
- $code .= <<END; |
- if (!impl->buffer()->hasDeallocationObserver()) { |
- v8::V8::AdjustAmountOfExternalAllocatedMemory(impl->buffer()->byteLength()); |
- impl->buffer()->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instance()); |
- } |
-END |
- } |
- |
- $code .= <<END; |
- installPerContextProperties(wrapper, impl.get(), isolate); |
- V8DOMWrapper::associateObjectWithWrapper(impl, &info, wrapper, isolate, $wrapperConfiguration); |
- return wrapper; |
-} |
-END |
- $implementation{nameSpaceWebCore}->add($code); |
-} |
- |
-sub GenerateSecurityCheckFunctions |
-{ |
- my $interface = shift; |
- my $implClassName = GetImplName($interface); |
- my $v8ClassName = GetV8ClassName($interface); |
- |
- AddToImplIncludes("bindings/v8/BindingSecurity.h"); |
- $implementation{nameSpaceInternal}->add(<<END); |
-bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value>) |
-{ |
- $implClassName* imp = ${v8ClassName}::toNative(host); |
- return BindingSecurity::shouldAllowAccessToFrame(imp->frame(), DoNotReportSecurityError); |
-} |
- |
-END |
- $implementation{nameSpaceInternal}->add(<<END); |
-bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value>) |
-{ |
- $implClassName* imp = ${v8ClassName}::toNative(host); |
- return BindingSecurity::shouldAllowAccessToFrame(imp->frame(), DoNotReportSecurityError); |
-} |
- |
-END |
-} |
- |
-sub GetNativeTypeForConversions |
-{ |
- my $interface = shift; |
- my $implClassName = GetImplName($interface); |
- $implClassName = GetSVGTypeNeedingTearOff($interface->name) if IsSVGTypeNeedingTearOff($interface->name); |
- return $implClassName; |
-} |
- |
-sub GetNamespaceForInterface |
-{ |
- my $interface = shift; |
- return "WTF" if IsTypedArrayType($interface->name); |
- return "WebCore"; |
-} |
- |
-sub GenerateFunctionCallString |
-{ |
- my $function = shift; |
- my $numberOfParameters = shift; |
- my $indent = shift; |
- my $interface = shift; |
- my $forMainWorldSuffix = shift; |
- my %replacements = @_; |
- |
- my $interfaceName = $interface->name; |
- my $implClassName = GetImplName($interface); |
- my $name = GetImplName($function); |
- my $returnType = $function->type; |
- my $nativeReturnType = GetNativeType($returnType, {}, ""); |
- my $code = ""; |
- |
- my $isSVGTearOffType = (IsSVGTypeNeedingTearOff($returnType) and not $interfaceName =~ /List$/); |
- $nativeReturnType = GetSVGWrappedTypeNeedingTearOff($returnType) if $isSVGTearOffType; |
- |
- my $index = 0; |
- |
- my @arguments; |
- my $functionName; |
- my $implementedBy = $function->extendedAttributes->{"ImplementedBy"}; |
- if ($implementedBy) { |
- my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy); |
- AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implementedByImplName)); |
- unshift(@arguments, "imp") if !$function->isStatic; |
- $functionName = "${implementedByImplName}::${name}"; |
- } elsif ($function->isStatic) { |
- $functionName = "${implClassName}::${name}"; |
- } else { |
- $functionName = "imp->${name}"; |
- } |
- |
- my $callWith = $function->extendedAttributes->{"CallWith"}; |
- my ($callWithArgs, $subCode) = GenerateCallWith($callWith, $indent, 1, $function); |
- $code .= $subCode; |
- unshift(@arguments, @$callWithArgs); |
- $index += @$callWithArgs; |
- $numberOfParameters += @$callWithArgs; |
- |
- foreach my $parameter (@{$function->parameters}) { |
- if ($index eq $numberOfParameters) { |
- last; |
- } |
- my $paramName = $parameter->name; |
- my $paramType = $parameter->type; |
- |
- if ($replacements{$paramName}) { |
- push @arguments, $replacements{$paramName}; |
- } elsif ($parameter->type eq "NodeFilter" || $parameter->type eq "XPathNSResolver") { |
- push @arguments, "$paramName.get()"; |
- } elsif (IsSVGTypeNeedingTearOff($parameter->type) and not $interfaceName =~ /List$/) { |
- push @arguments, "$paramName->propertyReference()"; |
- $code .= $indent . "if (!$paramName) {\n"; |
- $code .= $indent . " setDOMException(WebCore::TypeMismatchError, args.GetIsolate());\n"; |
- $code .= $indent . " return;\n"; |
- $code .= $indent . "}\n"; |
- } elsif ($parameter->type eq "SVGMatrix" and $interfaceName eq "SVGTransformList") { |
- push @arguments, "$paramName.get()"; |
- } else { |
- push @arguments, $paramName; |
- } |
- $index++; |
- } |
- |
- if ($function->extendedAttributes->{"RaisesException"}) { |
- push @arguments, "ec"; |
- } |
- |
- my $functionString = "$functionName(" . join(", ", @arguments) . ")"; |
- |
- my $return = "result"; |
- my $returnIsRef = IsRefPtrType($returnType); |
- |
- if ($returnType eq "void") { |
- $code .= $indent . "$functionString;\n"; |
- } elsif (ExtendedAttributeContains($callWith, "ScriptState") or $function->extendedAttributes->{"RaisesException"}) { |
- $code .= $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 ($interfaceName eq "SVGTransformList" and IsRefPtrType($returnType)) { |
- $return = "WTF::getPtr(" . $return . ")"; |
- } |
- } |
- |
- if ($function->extendedAttributes->{"RaisesException"}) { |
- $code .= $indent . "if (UNLIKELY(ec)) {\n"; |
- $code .= $indent . " setDOMException(ec, args.GetIsolate());\n"; |
- $code .= $indent . " return;\n"; |
- $code .= $indent . "}\n"; |
- } |
- |
- if (ExtendedAttributeContains($callWith, "ScriptState")) { |
- $code .= $indent . "if (state.hadException()) {\n"; |
- $code .= $indent . " v8::Local<v8::Value> exception = state.exception();\n"; |
- $code .= $indent . " state.clearException();\n"; |
- $code .= $indent . " throwError(exception, args.GetIsolate());\n"; |
- $code .= $indent . " return;\n"; |
- $code .= $indent . "}\n"; |
- } |
- |
- if ($isSVGTearOffType) { |
- AddToImplIncludes("V8$returnType.h"); |
- AddToImplIncludes("core/svg/properties/SVGPropertyTearOff.h"); |
- my $svgNativeType = GetSVGTypeNeedingTearOff($returnType); |
- # FIXME: Update for all ScriptWrappables. |
- if (IsDOMNodeType($interfaceName)) { |
- $code .= $indent . "v8SetReturnValue(args, toV8Fast${forMainWorldSuffix}(WTF::getPtr(${svgNativeType}::create($return)), args, imp));\n"; |
- } else { |
- $code .= $indent . "v8SetReturnValue(args, toV8${forMainWorldSuffix}(WTF::getPtr(${svgNativeType}::create($return)), args.Holder(), args.GetIsolate()));\n"; |
- } |
- $code .= $indent . "return;\n"; |
- return $code; |
- } |
- |
- # If the implementing class is a POD type, commit changes |
- if (IsSVGTypeNeedingTearOff($interfaceName) and not $interfaceName =~ /List$/) { |
- $code .= $indent . "wrapper->commitChange();\n"; |
- } |
- |
- $return .= ".release()" if ($returnIsRef); |
- |
- my $nativeValue; |
- # FIXME: Update for all ScriptWrappables. |
- if (IsDOMNodeType($interfaceName)) { |
- $nativeValue = NativeToJSValue($function->type, $function->extendedAttributes, $return, $indent, "", "args.Holder()", "args.GetIsolate()", "args", "imp", "ReturnUnsafeHandle", $forMainWorldSuffix, "return"); |
- } else { |
- $nativeValue = NativeToJSValue($function->type, $function->extendedAttributes, $return, $indent, "", "args.Holder()", "args.GetIsolate()", "args", 0, "ReturnUnsafeHandle", $forMainWorldSuffix, "return"); |
- } |
- |
- $code .= $nativeValue . "\n"; |
- $code .= $indent . "return;\n"; |
- |
- return $code; |
-} |
- |
-sub GetNativeType |
-{ |
- my $type = shift; |
- my $extendedAttributes = shift; |
- my $isParameter = shift; |
- |
- my $svgNativeType = GetSVGTypeNeedingTearOff($type); |
- if ($svgNativeType) { |
- if ($svgNativeType =~ /List$/) { |
- return "${svgNativeType}*"; |
- } else { |
- return "RefPtr<${svgNativeType} >"; |
- } |
- } |
- |
- return "float" if $type eq "float"; |
- return "double" if $type eq "double"; |
- return "int" if $type eq "long" or $type eq "int" or $type eq "short" or $type eq "byte"; |
- if ($type eq "unsigned long" or $type eq "unsigned int" or $type eq "unsigned short" or $type eq "octet") { |
- if ($extendedAttributes->{"IsIndex"}) { |
- # Special-case index arguments because we need to check that they aren't < 0. |
- return "int"; |
- } |
- return "unsigned"; |
- } |
- return "long long" if $type eq "long long"; |
- return "unsigned long long" if $type eq "unsigned long long"; |
- return "bool" if $type eq "boolean"; |
- |
- if (($type eq "DOMString" || IsEnumType($type)) and $isParameter) { |
- # FIXME: This implements [TreatNullAs=NullString] and [TreatUndefinedAs=NullString], |
- # but the Web IDL spec requires [TreatNullAs=EmptyString] and [TreatUndefinedAs=EmptyString]. |
- my $mode = ""; |
- if (($extendedAttributes->{"TreatNullAs"} and $extendedAttributes->{"TreatNullAs"} eq "NullString") and ($extendedAttributes->{"TreatUndefinedAs"} and $extendedAttributes->{"TreatUndefinedAs"} eq "NullString")) { |
- $mode = "WithUndefinedOrNullCheck"; |
- } elsif (($extendedAttributes->{"TreatNullAs"} and $extendedAttributes->{"TreatNullAs"} eq "NullString") or $extendedAttributes->{"Reflect"}) { |
- $mode = "WithNullCheck"; |
- } |
- # FIXME: Add the case for 'elsif ($attributeOrParameter->extendedAttributes->{"TreatUndefinedAs"} and $attributeOrParameter->extendedAttributes->{"TreatUndefinedAs"} eq "NullString"))'. |
- return "V8StringResource<$mode>"; |
- } |
- |
- return "String" if $type eq "DOMString" or IsEnumType($type); |
- |
- return "Range::CompareHow" if $type eq "CompareHow"; |
- return "DOMTimeStamp" if $type eq "DOMTimeStamp"; |
- return "double" if $type eq "Date"; |
- return "ScriptValue" if $type eq "any" or IsCallbackFunctionType($type); |
- return "Dictionary" if $type eq "Dictionary"; |
- |
- return "RefPtr<DOMStringList>" if $type eq "DOMStringList"; |
- return "RefPtr<MediaQueryListListener>" if $type eq "MediaQueryListListener"; |
- return "RefPtr<NodeFilter>" if $type eq "NodeFilter"; |
- return "RefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValue"; |
- return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver"; |
- |
- die "UnionType is not supported" if IsUnionType($type); |
- |
- if ($type eq "ArrayBuffer") { |
- return $isParameter ? "ArrayBuffer*" : "RefPtr<ArrayBuffer>"; |
- } |
- |
- # We need to check [ImplementedAs] extended attribute for wrapper types. |
- if (IsWrapperType($type)) { |
- my $interface = ParseInterface($type); |
- my $implClassName = GetImplName($interface); |
- return $isParameter ? "${implClassName}*" : "RefPtr<${implClassName}>"; |
- } |
- return "RefPtr<${type}>" if IsRefPtrType($type) and not $isParameter; |
- |
- my $arrayOrSequenceType = GetArrayOrSequenceType($type); |
- |
- if ($arrayOrSequenceType) { |
- my $nativeType = GetNativeType($arrayOrSequenceType); |
- $nativeType .= " " if ($nativeType =~ />$/); |
- return "Vector<${nativeType}>"; |
- } |
- |
- # 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"; |
- return "PassRefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValue"; |
- |
- # Callbacks use raw pointers, so pass isParameter = 1 |
- return GetNativeType($type, {}, "parameter"); |
-} |
- |
-sub JSValueToNativeStatement |
-{ |
- my $type = shift; |
- my $extendedAttributes = shift; |
- my $jsValue = shift; |
- my $variableName = shift; |
- my $indent = shift; |
- my $getIsolate = shift; |
- |
- my $nativeType = GetNativeType($type, $extendedAttributes, "parameter"); |
- if ($type eq "unsigned long" and $extendedAttributes->{"IsIndex"}) { |
- # Special-case index arguments because we need to check that they aren't < 0. |
- $nativeType = "int"; |
- } |
- my $native_value = JSValueToNative($type, $extendedAttributes, $jsValue, $getIsolate); |
- my $code = ""; |
- if ($type eq "DOMString" || IsEnumType($type)) { |
- die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8StringResource/; |
- if ($type eq "DOMString" or IsEnumType($type)) { |
- $code .= $indent . "V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID($nativeType, $variableName, $native_value);\n" |
- } else { |
- $code .= $indent . "$nativeType $variableName($native_value, true);\n"; |
- } |
- } elsif ($extendedAttributes->{"EnforceRange"}) { |
- $code .= $indent . "V8TRYCATCH_WITH_TYPECHECK_VOID($nativeType, $variableName, $native_value, $getIsolate);\n"; |
- } else { |
- $code .= $indent . "V8TRYCATCH_VOID($nativeType, $variableName, $native_value);\n"; |
- } |
- return $code; |
-} |
- |
- |
-sub JSValueToNative |
-{ |
- my $type = shift; |
- my $extendedAttributes = shift; |
- my $value = shift; |
- my $getIsolate = shift; |
- |
- my $intConversion = $extendedAttributes->{"EnforceRange"} ? "EnforceRange" : "NormalConversion"; |
- |
- return "$value->BooleanValue()" if $type eq "boolean"; |
- return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $type eq "double"; |
- |
- if ($intConversion ne "NormalConversion") { |
- return "toInt8($value, $intConversion, ok)" if $type eq "byte"; |
- return "toUInt8($value, $intConversion, ok)" if $type eq "octet"; |
- return "toInt32($value, $intConversion, ok)" if $type eq "long" or $type eq "short"; |
- return "toUInt32($value, $intConversion, ok)" if $type eq "unsigned long" or $type eq "unsigned short"; |
- return "toInt64($value, $intConversion, ok)" if $type eq "long long"; |
- return "toUInt64($value, $intConversion, ok)" if $type eq "unsigned long long"; |
- } else { |
- return "toInt8($value)" if $type eq "byte"; |
- return "toUInt8($value)" if $type eq "octet"; |
- 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 "long long"; |
- return "toUInt64($value)" if $type eq "unsigned long long"; |
- } |
- return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "CompareHow"; |
- return "toWebCoreDate($value)" if $type eq "Date"; |
- return "toDOMStringList($value, $getIsolate)" if $type eq "DOMStringList"; |
- |
- if ($type eq "DOMString" or IsEnumType($type)) { |
- return $value; |
- } |
- |
- if ($type eq "SerializedScriptValue") { |
- AddToImplIncludes("bindings/v8/SerializedScriptValue.h"); |
- return "SerializedScriptValue::create($value, $getIsolate)"; |
- } |
- |
- if ($type eq "Dictionary") { |
- AddToImplIncludes("bindings/v8/Dictionary.h"); |
- return "Dictionary($value, $getIsolate)"; |
- } |
- |
- if ($type eq "any" || IsCallbackFunctionType($type)) { |
- AddToImplIncludes("bindings/v8/ScriptValue.h"); |
- return "ScriptValue($value)"; |
- } |
- |
- if ($type eq "NodeFilter") { |
- return "toNodeFilter($value)"; |
- } |
- |
- if ($type eq "MediaQueryListListener") { |
- AddToImplIncludes("core/css/MediaQueryListListener.h"); |
- return "MediaQueryListListener::create(" . $value . ")"; |
- } |
- |
- if ($type eq "EventTarget") { |
- return "V8DOMWrapper::isDOMWrapper($value) ? toWrapperTypeInfo(v8::Handle<v8::Object>::Cast($value))->toEventTarget(v8::Handle<v8::Object>::Cast($value)) : 0"; |
- } |
- |
- if ($type eq "ArrayBuffer") { |
- AddIncludesForType($type); |
- return "$value->IsArrayBuffer() ? V8ArrayBuffer::toNative(v8::Handle<v8::ArrayBuffer>::Cast($value)) : 0" |
- } |
- |
- if ($type eq "XPathNSResolver") { |
- return "toXPathNSResolver($value, $getIsolate)"; |
- } |
- |
- my $arrayOrSequenceType = GetArrayOrSequenceType($type); |
- |
- if ($arrayOrSequenceType) { |
- if (IsRefPtrType($arrayOrSequenceType)) { |
- AddToImplIncludes("V8${arrayOrSequenceType}.h"); |
- return "(toRefPtrNativeArray<${arrayOrSequenceType}, V8${arrayOrSequenceType}>($value, $getIsolate))"; |
- } |
- return "toNativeArray<" . GetNativeType($arrayOrSequenceType) . ">($value)"; |
- } |
- |
- AddIncludesForType($type); |
- |
- AddToImplIncludes("V8${type}.h"); |
- return "V8${type}::HasInstance($value, $getIsolate, worldType($getIsolate)) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0"; |
-} |
- |
-sub CreateCustomSignature |
-{ |
- my $function = shift; |
- my $count = @{$function->parameters}; |
- my $name = $function->name; |
- my $code = " 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 { $code .= ", "; } |
- if (IsWrapperType($parameter->type) && $parameter->type ne "ArrayBuffer") { |
- 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. |
- $code .= "v8::Handle<v8::FunctionTemplate>()"; |
- } else { |
- my $type = $parameter->type; |
- my $arrayOrSequenceType = GetArrayOrSequenceType($type); |
- |
- if ($arrayOrSequenceType) { |
- if (IsRefPtrType($arrayOrSequenceType)) { |
- AddIncludesForType($arrayOrSequenceType); |
- } else { |
- $code .= "v8::Handle<v8::FunctionTemplate>()"; |
- next; |
- } |
- } else { |
- AddIncludesForType($type); |
- } |
- $code .= "V8PerIsolateData::from(isolate)->rawTemplate(&V8${type}::info, currentWorldType)"; |
- } |
- } else { |
- $code .= "v8::Handle<v8::FunctionTemplate>()"; |
- } |
- } |
- $code .= " };\n"; |
- $code .= " v8::Handle<v8::Signature> ${name}Signature = v8::Signature::New(desc, ${name}Argc, ${name}Argv);\n"; |
- return $code; |
-} |
- |
- |
-sub RequiresCustomSignature |
-{ |
- my $function = shift; |
- # No signature needed for Custom function |
- if (HasCustomMethod($function->extendedAttributes)) { |
- return 0; |
- } |
- # No signature needed for overloaded function |
- if (@{$function->{overloads}} > 1) { |
- return 0; |
- } |
- if ($function->isStatic) { |
- return 0; |
- } |
- # Type checking is performed in the generated code |
- if ($function->extendedAttributes->{"StrictTypeChecking"}) { |
- return 0; |
- } |
- foreach my $parameter (@{$function->parameters}) { |
- if (($parameter->isOptional && !$parameter->extendedAttributes->{"Default"}) || IsCallbackInterface($parameter->type)) { |
- return 0; |
- } |
- } |
- |
- foreach my $parameter (@{$function->parameters}) { |
- if (IsWrapperType($parameter->type)) { |
- return 1; |
- } |
- } |
- return 0; |
-} |
- |
-sub IsUnionType |
-{ |
- my $type = shift; # string or UnionType |
- if(ref($type) eq "UnionType") { |
- die "Currently only 2 values of non-union type is supported as union type.\n" unless @{$type->unionMemberTypes} == 2; |
- return 1; |
- } |
- return 0; |
-} |
- |
-sub IsWrapperType |
-{ |
- my $type = shift; |
- return 0 if GetArrayType($type); |
- return 0 if GetSequenceType($type); |
- return 0 if IsCallbackFunctionType($type); |
- return 0 if IsEnumType($type); |
- return 0 if IsPrimitiveType($type); |
- return 0 if $type eq "DOMString"; |
- return !$nonWrapperTypes{$type}; |
-} |
- |
-sub IsCallbackInterface |
-{ |
- my $type = shift; |
- return 0 unless IsWrapperType($type); |
- return 0 if $type eq "ArrayBuffer"; |
- |
- my $idlFile = IDLFileForInterface($type) |
- or die("Could NOT find IDL file for interface \"$type\"!\n"); |
- |
- open FILE, "<", $idlFile; |
- my @lines = <FILE>; |
- close FILE; |
- |
- my $fileContents = join('', @lines); |
- return ($fileContents =~ /callback\s+interface\s+(\w+)/gs); |
-} |
- |
-sub GetNativeTypeOfTypedArray |
-{ |
- my $interface = shift; |
- my $interfaceName = $interface->name; |
- die "TypedArray of unknown type is found" unless $typedArrayHash{$interface->name}; |
- return @{$typedArrayHash{$interface->name}}; |
-} |
- |
-sub IsDOMNodeType |
-{ |
- my $type = shift; |
- |
- return 1 if $type eq 'Attr'; |
- return 1 if $type eq 'CDATASection'; |
- return 1 if $type eq 'CharacterData'; |
- 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 'Entity'; |
- return 1 if $type eq 'HTMLDocument'; |
- return 1 if $type eq 'Node'; |
- return 1 if $type eq 'Notation'; |
- return 1 if $type eq 'ProcessingInstruction'; |
- return 1 if $type eq 'ShadowRoot'; |
- return 1 if $type eq 'SVGDocument'; |
- return 1 if $type eq 'Text'; |
- |
- return 1 if $type =~ /^HTML.*Element$/; |
- return 1 if $type =~ /^SVG.*Element$/; |
- |
- return 1 if $type eq 'TestNode'; |
- |
- return 0; |
-} |
- |
- |
-sub NativeToJSValue |
-{ |
- my $type = shift; |
- my $extendedAttributes = shift; |
- my $nativeValue = shift; |
- my $indent = shift; # added before every line |
- my $receiver = shift; # "return" or "<variableName> =" |
- my $getCreationContext = shift; |
- my $getIsolate = shift; |
- die "An Isolate is mandatory for native value => JS value conversion." unless $getIsolate; |
- my $getHolderContainer = shift || ""; |
- my $getHolderContainerArg = $getHolderContainer ? ", $getHolderContainer" : ""; |
- my $getScriptWrappable = shift || ""; |
- my $getScriptWrappableArg = $getScriptWrappable ? ", $getScriptWrappable" : ""; |
- my $returnHandleType = shift || ""; |
- my $returnHandleTypeArg = $returnHandleType ? ", $returnHandleType" : ""; |
- my $forMainWorldSuffix = shift || ""; |
- my $returnValueArg = shift || 0; |
- my $isReturnValue = $returnValueArg eq "return"; |
- |
- if (IsUnionType($type)) { |
- my $types = $type->unionMemberTypes; |
- my @codes = (); |
- for my $i (0 .. scalar(@$types)-1) { |
- my $unionMemberType = $types->[$i]; |
- my $unionMemberNumber = $i + 1; |
- my $unionMemberVariable = $nativeValue . $i; |
- my $unionMemberEnabledVariable = $nativeValue . $i . "Enabled"; |
- my $unionMemberNativeValue = $unionMemberVariable; |
- $unionMemberNativeValue .= ".release()" if (IsRefPtrType($unionMemberType)); |
- my $returnJSValueCode = NativeToJSValue($unionMemberType, $extendedAttributes, $unionMemberNativeValue, $indent . " ", $receiver, $getCreationContext, $getIsolate, $getHolderContainer, $getScriptWrappable, $returnHandleType, $forMainWorldSuffix, $returnValueArg); |
- my $code = ""; |
- if ($isReturnValue) { |
- $code .= "${indent}if (${unionMemberEnabledVariable}) {\n"; |
- $code .= "${returnJSValueCode}\n"; |
- $code .= "${indent} return;\n"; |
- $code .= "${indent}}\n"; |
- } else { |
- $code .= "${indent}if (${unionMemberEnabledVariable})\n"; |
- $code .= "${returnJSValueCode}"; |
- } |
- push @codes, $code; |
- } |
- return join "\n", @codes; |
- } |
- |
- if ($type eq "boolean") { |
- return "${indent}v8SetReturnValueBool(${getHolderContainer}, ${nativeValue});" if $isReturnValue; |
- return "$indent$receiver v8Boolean($nativeValue, $getIsolate);"; |
- } |
- |
- if ($type eq "void") { # equivalent to v8Undefined() |
- return "" if $isReturnValue; |
- return "$indent$receiver v8Undefined();" |
- } |
- |
- # 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 ($extendedAttributes->{"Reflect"} and ($type eq "unsigned long" or $type eq "unsigned short")) { |
- $nativeValue =~ s/getUnsignedIntegralAttribute/getIntegralAttribute/g; |
- return "${indent}v8SetReturnValueUnsigned(${getHolderContainer}, std::max(0, ${nativeValue}));" if $isReturnValue; |
- return "$indent$receiver v8::Integer::NewFromUnsigned(std::max(0, " . $nativeValue . "), $getIsolate);"; |
- } |
- |
- my $nativeType = GetNativeType($type); |
- if ($nativeType eq "int") { |
- return "${indent}v8SetReturnValueInt(${getHolderContainer}, ${nativeValue});" if $isReturnValue; |
- return "$indent$receiver v8::Integer::New($nativeValue, $getIsolate);"; |
- } |
- |
- if ($nativeType eq "unsigned") { |
- return "${indent}v8SetReturnValueUnsigned(${getHolderContainer}, ${nativeValue});" if $isReturnValue; |
- return "$indent$receiver v8::Integer::NewFromUnsigned($nativeValue, $getIsolate);"; |
- } |
- |
- if ($type eq "Date") { |
- return "${indent}v8SetReturnValue(${getHolderContainer}, v8DateOrNull($nativeValue, $getIsolate));" if $isReturnValue; |
- return "$indent$receiver v8DateOrNull($nativeValue, $getIsolate);" |
- } |
- |
- # long long and unsigned long long are not representable in ECMAScript. |
- if ($type eq "long long" or $type eq "unsigned long long" or $type eq "DOMTimeStamp") { |
- return "${indent}v8SetReturnValue(${getHolderContainer}, static_cast<double>($nativeValue));" if $isReturnValue; |
- return "$indent$receiver v8::Number::New(static_cast<double>($nativeValue));"; |
- } |
- |
- if (IsPrimitiveType($type)) { |
- die "unexpected type $type" if not ($type eq "float" or $type eq "double"); |
- return "${indent}v8SetReturnValue(${getHolderContainer}, ${nativeValue});" if $isReturnValue; |
- return "$indent$receiver v8::Number::New($nativeValue);"; |
- } |
- |
- if ($nativeType eq "ScriptValue") { |
- return "${indent}v8SetReturnValue(${getHolderContainer}, ${nativeValue}.v8Value());" if $isReturnValue; |
- return "$indent$receiver $nativeValue.v8Value();"; |
- } |
- |
- my $conv = $extendedAttributes->{"TreatReturnedNullStringAs"}; |
- if (($type eq "DOMString" || IsEnumType($type)) && $isReturnValue) { |
- my $nullAs = "NullStringAsEmpty"; |
- if (defined $conv) { |
- if ($conv eq "Null") { |
- $nullAs = "NullStringAsNull"; |
- } elsif ($conv eq "Undefined") { |
- $nullAs = "NullStringAsUndefined"; |
- } else { |
- die "Unknown value for TreatReturnedNullStringAs extended attribute"; |
- } |
- } |
- return "${indent}v8SetReturnValueString(${getHolderContainer}, $nativeValue, $getIsolate, $nullAs);"; |
- } |
- |
- if ($type eq "DOMString" or IsEnumType($type)) { |
- my $returnValue = ""; |
- if (defined $conv) { |
- if ($conv eq "Null") { |
- $returnValue = "v8StringOrNull($nativeValue, $getIsolate$returnHandleTypeArg)"; |
- } elsif ($conv eq "Undefined") { |
- $returnValue = "v8StringOrUndefined($nativeValue, $getIsolate$returnHandleTypeArg)"; |
- } else { |
- die "Unknown value for TreatReturnedNullStringAs extended attribute"; |
- } |
- } else { |
- $returnValue = "v8String($nativeValue, $getIsolate$returnHandleTypeArg)"; |
- } |
- return "$indent$receiver $returnValue;"; |
- } |
- |
- my $arrayOrSequenceType = GetArrayOrSequenceType($type); |
- |
- if ($arrayOrSequenceType) { |
- if (IsRefPtrType($arrayOrSequenceType)) { |
- AddIncludesForType($arrayOrSequenceType); |
- } |
- return "${indent}v8SetReturnValue(${getHolderContainer}, v8Array($nativeValue, $getIsolate));" if $isReturnValue; |
- return "$indent$receiver v8Array($nativeValue, $getIsolate);"; |
- } |
- |
- AddIncludesForType($type); |
- |
- if (IsDOMNodeType($type) || $type eq "EventTarget") { |
- if ($getScriptWrappable) { |
- # FIXME: Use safe handles |
- return "${indent}v8SetReturnValue(${getHolderContainer}, toV8Fast${forMainWorldSuffix}($nativeValue$getHolderContainerArg$getScriptWrappableArg));" if $isReturnValue; |
- return "$indent$receiver toV8Fast${forMainWorldSuffix}($nativeValue$getHolderContainerArg$getScriptWrappableArg);"; |
- } |
- # FIXME: Use safe handles |
- return "${indent}v8SetReturnValue(${getHolderContainer}, toV8($nativeValue, $getCreationContext, $getIsolate));" if $isReturnValue; |
- return "$indent$receiver toV8($nativeValue, $getCreationContext, $getIsolate);"; |
- } |
- |
- if ($type eq "SerializedScriptValue") { |
- AddToImplIncludes("$type.h"); |
- my $returnValue = "$nativeValue ? $nativeValue->deserialize() : v8::Handle<v8::Value>(v8::Null($getIsolate))"; |
- return "${indent}v8SetReturnValue(${getHolderContainer}, $returnValue);" if $isReturnValue; |
- return "$indent$receiver $returnValue;"; |
- } |
- |
- AddToImplIncludes("wtf/RefCounted.h"); |
- AddToImplIncludes("wtf/RefPtr.h"); |
- AddToImplIncludes("wtf/GetPtr.h"); |
- |
- if ($getScriptWrappable) { |
- # FIXME: Use safe handles |
- return "${indent}v8SetReturnValue(${getHolderContainer}, toV8Fast${forMainWorldSuffix}($nativeValue$getHolderContainerArg$getScriptWrappableArg));" if $isReturnValue; |
- return "$indent$receiver toV8Fast${forMainWorldSuffix}($nativeValue$getHolderContainerArg$getScriptWrappableArg);"; |
- } |
- # FIXME: Use safe handles |
- return "${indent}v8SetReturnValue(${getHolderContainer}, toV8($nativeValue, $getCreationContext, $getIsolate));" if $isReturnValue; |
- return "$indent$receiver toV8($nativeValue, $getCreationContext, $getIsolate);"; |
-} |
- |
-sub WriteData |
-{ |
- my $object = shift; |
- my $interface = shift; |
- my $outputDirectory = shift; |
- |
- my $name = $interface->name; |
- my $headerFileName = "$outputDirectory/V8$name.h"; |
- my $implFileName = "$outputDirectory/V8$name.cpp"; |
- |
- my @includes = (); |
- foreach my $include (keys %implIncludes) { |
- push @includes, "\"$include\""; |
- } |
- |
- #FIXME: do not treat main header special |
- my $mainInclude = "\"V8$name.h\""; |
- foreach my $include (sort @includes) { |
- $implementation{includes}->add("#include $include\n") unless $include eq $mainInclude; |
- } |
- $implementation{includes}->add("\n") unless $interface->isCallback; |
- WriteFileIfChanged($implFileName, $implementation{root}->toString()); |
- |
- %implIncludes = (); |
- |
- WriteFileIfChanged($headerFileName, $header{root}->toString()); |
-} |
- |
-sub ConvertToV8StringResource |
-{ |
- my $attributeOrParameter = shift; |
- my $nativeType = shift; |
- my $variableName = shift; |
- my $value = shift; |
- |
- die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8StringResource/; |
- if ($attributeOrParameter->type eq "DOMString" or IsEnumType($attributeOrParameter->type)) { |
- return "V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID($nativeType, $variableName, $value);" |
- } else { |
- 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::" . ToMethodName($signature->extendedAttributes->{"EnabledAtRuntime"}) . "Enabled" if ($signature->extendedAttributes->{"EnabledAtRuntime"} && $signature->extendedAttributes->{"EnabledAtRuntime"} ne "VALUE_IS_MISSING"); |
- |
- # Otherwise return a function named RuntimeEnabledFeatures::{methodName}Enabled(). |
- return "RuntimeEnabledFeatures::" . ToMethodName($signature->name) . "Enabled"; |
-} |
- |
-sub GetContextEnableFunction |
-{ |
- my $signature = shift; |
- |
- # If a parameter is given (e.g. "EnabledPerContext=FeatureName") return the {FeatureName}Allowed() method. |
- if ($signature->extendedAttributes->{"EnabledPerContext"} && $signature->extendedAttributes->{"EnabledPerContext"} ne "VALUE_IS_MISSING") { |
- return "ContextFeatures::" . ToMethodName($signature->extendedAttributes->{"EnabledPerContext"}) . "Enabled"; |
- } |
- |
- # Or it fallbacks to the attribute name if the parameter value is missing. |
- return "ContextFeatures::" . ToMethodName($signature->name) . "Enabled"; |
-} |
- |
-sub GetPassRefPtrType |
-{ |
- my $v8ClassName = shift; |
- |
- my $angleBracketSpace = $v8ClassName =~ />$/ ? " " : ""; |
- return "PassRefPtr<${v8ClassName}${angleBracketSpace}>"; |
-} |
- |
-sub WriteFileIfChanged |
-{ |
- my $fileName = shift; |
- my $contents = shift; |
- |
- if (-f $fileName && $writeFileOnlyIfChanged) { |
- open FH, "<", $fileName or die "Couldn't open $fileName: $!\n"; |
- my @lines = <FH>; |
- my $oldContents = join "", @lines; |
- close FH; |
- return if $contents eq $oldContents; |
- } |
- open FH, ">", $fileName or die "Couldn't open $fileName: $!\n"; |
- print FH $contents; |
- close FH; |
-} |
- |
-sub ForAllParents |
-{ |
- my $interface = shift; |
- my $beforeRecursion = shift; |
- my $afterRecursion = shift; |
- |
- my $recurse; |
- $recurse = sub { |
- my $currentInterface = shift; |
- |
- if ($currentInterface->parent) { |
- my $parentInterface = ParseInterface($currentInterface->parent); |
- if ($beforeRecursion) { |
- &$beforeRecursion($parentInterface) eq 'prune' and return; |
- } |
- &$recurse($parentInterface); |
- &$afterRecursion($parentInterface) if $afterRecursion; |
- } |
- }; |
- |
- &$recurse($interface); |
-} |
- |
-sub FindSuperMethod |
-{ |
- my ($interface, $functionName) = @_; |
- my $indexer; |
- ForAllParents($interface, undef, sub { |
- my $currentInterface = shift; |
- foreach my $function (@{$currentInterface->functions}) { |
- if ($function->name eq $functionName) { |
- $indexer = $function; |
- return 'prune'; |
- } |
- } |
- }); |
- return $indexer; |
-} |
- |
-sub IsConstructorTemplate |
-{ |
- my $interface = shift; |
- my $template = shift; |
- |
- return $interface->extendedAttributes->{"ConstructorTemplate"} && $interface->extendedAttributes->{"ConstructorTemplate"} eq $template; |
-} |
- |
-sub IsPrimitiveType |
-{ |
- my $type = shift; |
- |
- return 1 if $primitiveTypeHash{$type}; |
- return 0; |
-} |
- |
-sub IsCallbackFunctionType |
-{ |
- my $type = shift; |
- |
- return 1 if $callbackFunctionTypeHash{$type}; |
- return 0; |
-} |
- |
-sub IsEnumType |
-{ |
- my $type = shift; |
- |
- return 1 if $enumTypeHash{$type}; |
- return 0; |
-} |
- |
-sub ValidEnumValues |
-{ |
- my $type = shift; |
- |
- return @{$enumTypeHash{$type}}; |
-} |
- |
-sub IsSVGTypeNeedingTearOff |
-{ |
- my $type = shift; |
- |
- return 1 if $svgTypeNeedingTearOff{$type}; |
- return 0; |
-} |
- |
-sub IsSVGTypeWithWritablePropertiesNeedingTearOff |
-{ |
- my $type = shift; |
- |
- return 1 if $svgTypeWithWritablePropertiesNeedingTearOff{$type}; |
- return 0; |
-} |
- |
-sub IsTypedArrayType |
-{ |
- my $type = shift; |
- return 1 if $typedArrayHash{$type}; |
- return 0; |
-} |
- |
-sub IsRefPtrType |
-{ |
- my $type = shift; |
- |
- return 0 if $type eq "any"; |
- return 0 if IsPrimitiveType($type); |
- return 0 if GetArrayType($type); |
- return 0 if GetSequenceType($type); |
- return 0 if $type eq "DOMString"; |
- return 0 if IsCallbackFunctionType($type); |
- return 0 if IsEnumType($type); |
- return 0 if IsUnionType($type); |
- |
- return 1; |
-} |
- |
-sub GetSVGTypeNeedingTearOff |
-{ |
- my $type = shift; |
- |
- return $svgTypeNeedingTearOff{$type} if exists $svgTypeNeedingTearOff{$type}; |
- return undef; |
-} |
- |
-sub GetSVGWrappedTypeNeedingTearOff |
-{ |
- my $type = shift; |
- |
- my $svgTypeNeedingTearOff = GetSVGTypeNeedingTearOff($type); |
- return $svgTypeNeedingTearOff if not $svgTypeNeedingTearOff; |
- |
- if ($svgTypeNeedingTearOff =~ /SVGPropertyTearOff/) { |
- $svgTypeNeedingTearOff =~ s/SVGPropertyTearOff<//; |
- } elsif ($svgTypeNeedingTearOff =~ /SVGListPropertyTearOff/) { |
- $svgTypeNeedingTearOff =~ s/SVGListPropertyTearOff<//; |
- } elsif ($svgTypeNeedingTearOff =~ /SVGStaticListPropertyTearOff/) { |
- $svgTypeNeedingTearOff =~ s/SVGStaticListPropertyTearOff<//; |
- } elsif ($svgTypeNeedingTearOff =~ /SVGTransformListPropertyTearOff/) { |
- $svgTypeNeedingTearOff =~ s/SVGTransformListPropertyTearOff<//; |
- } |
- |
- $svgTypeNeedingTearOff =~ s/>//; |
- return $svgTypeNeedingTearOff; |
-} |
- |
-sub IsSVGAnimatedType |
-{ |
- my $type = shift; |
- |
- return 1 if $svgAnimatedTypeHash{$type}; |
- return 0; |
-} |
- |
-sub GetSequenceType |
-{ |
- my $type = shift; |
- |
- return $1 if $type =~ /^sequence<([\w\d_\s]+)>.*/; |
- return ""; |
-} |
- |
-sub GetArrayType |
-{ |
- my $type = shift; |
- |
- return $1 if $type =~ /^([\w\d_\s]+)\[\]/; |
- return ""; |
-} |
- |
-sub GetArrayOrSequenceType |
-{ |
- my $type = shift; |
- |
- return GetArrayType($type) || GetSequenceType($type); |
-} |
- |
-sub AssertNotSequenceType |
-{ |
- my $type = shift; |
- die "Sequences must not be used as the type of an attribute, constant or exception field." if GetSequenceType($type); |
-} |
- |
-sub FirstLetterToUpperCase |
-{ |
- my $param = shift; |
- my $ret = ucfirst($param); |
- # xmlEncoding becomes XMLEncoding, but xmlllang becomes Xmllang. |
- $ret =~ s/Xml/XML/ if $ret =~ /^Xml[^a-z]/; |
- $ret =~ s/Css/CSS/ if $ret =~ /^Css[^T]/; # css -> setCSS, except setCssText. |
- $ret =~ s/Ime/IME/ if $ret =~ /^Ime/; # ime -> setIME |
- return $ret; |
-} |
- |
-# URL becomes url, but SetURL becomes setURL. |
-sub ToMethodName |
-{ |
- my $param = shift; |
- my $ret = lcfirst($param); |
- $ret =~ s/hTML/html/ if $ret =~ /^hTML/; |
- $ret =~ s/uRL/url/ if $ret =~ /^uRL/; |
- $ret =~ s/jS/js/ if $ret =~ /^jS/; |
- $ret =~ s/xML/xml/ if $ret =~ /^xML/; |
- $ret =~ s/xSLT/xslt/ if $ret =~ /^xSLT/; |
- $ret =~ s/cSS/css/ if $ret =~ /^cSS/; |
- |
- # For HTML5 FileSystem API Flags attributes. |
- # (create is widely used to instantiate an object and must be avoided.) |
- $ret =~ s/^create/isCreate/ if $ret =~ /^create$/; |
- $ret =~ s/^exclusive/isExclusive/ if $ret =~ /^exclusive$/; |
- |
- return $ret; |
-} |
- |
-sub NamespaceForAttributeName |
-{ |
- my ($interfaceName, $attributeName) = @_; |
- return "SVGNames" if $interfaceName =~ /^SVG/ && !$svgAttributesInHTMLHash{$attributeName}; |
- return "HTMLNames"; |
-} |
- |
-# Identifies overloaded functions and for each function adds an array with |
-# links to its respective overloads (including itself). |
-sub LinkOverloadedFunctions |
-{ |
- my $interface = shift; |
- |
- my %nameToFunctionsMap = (); |
- foreach my $function (@{$interface->functions}) { |
- my $name = $function->name; |
- $nameToFunctionsMap{$name} = [] if !exists $nameToFunctionsMap{$name} or !$name; # Nameless functions cannot be overloaded |
- push(@{$nameToFunctionsMap{$name}}, $function); |
- $function->{overloads} = $nameToFunctionsMap{$name}; |
- $function->{overloadIndex} = @{$nameToFunctionsMap{$name}}; |
- } |
-} |
- |
-sub AttributeNameForGetterAndSetter |
-{ |
- my $attribute = shift; |
- |
- my $attributeName = GetImplName($attribute); |
- if ($attribute->extendedAttributes->{"ImplementedAs"}) { |
- $attributeName = $attribute->extendedAttributes->{"ImplementedAs"}; |
- } |
- my $attributeType = $attribute->type; |
- |
- # Avoid clash with C++ keyword. |
- $attributeName = "_operator" if $attributeName eq "operator"; |
- |
- # SVGAElement defines a non-virtual "String& target() const" method which clashes with "virtual String target() const" in Element. |
- # To solve this issue the SVGAElement method was renamed to "svgTarget", take care of that when calling this method. |
- $attributeName = "svgTarget" if $attributeName eq "target" and $attributeType eq "SVGAnimatedString"; |
- |
- # SVG animated types need to use a special attribute name. |
- # The rest of the special casing for SVG animated types is handled in the language-specific code generators. |
- $attributeName .= "Animated" if IsSVGAnimatedType($attributeType); |
- |
- return $attributeName; |
-} |
- |
-sub ContentAttributeName |
-{ |
- my ($interfaceName, $attribute) = @_; |
- |
- my $contentAttributeName = $attribute->extendedAttributes->{"Reflect"}; |
- return undef if !$contentAttributeName; |
- |
- $contentAttributeName = lc AttributeNameForGetterAndSetter($attribute) if $contentAttributeName eq "VALUE_IS_MISSING"; |
- |
- my $namespace = NamespaceForAttributeName($interfaceName, $contentAttributeName); |
- |
- AddToImplIncludes("${namespace}.h"); |
- return "WebCore::${namespace}::${contentAttributeName}Attr"; |
-} |
- |
-sub CanUseFastAttribute |
-{ |
- my $attribute = shift; |
- return !IsSVGAnimatedType($attribute->type); |
-} |
- |
-sub GetterExpression |
-{ |
- my ($interfaceName, $attribute) = @_; |
- |
- my $contentAttributeName = ContentAttributeName($interfaceName, $attribute); |
- |
- if (!$contentAttributeName) { |
- return (ToMethodName(AttributeNameForGetterAndSetter($attribute))); |
- } |
- |
- my $functionName; |
- if ($attribute->extendedAttributes->{"URL"}) { |
- $functionName = "getURLAttribute"; |
- } elsif ($attribute->type eq "boolean") { |
- if (CanUseFastAttribute($attribute)) { |
- $functionName = "fastHasAttribute"; |
- } else { |
- $functionName = "hasAttribute"; |
- } |
- } elsif ($attribute->type eq "long") { |
- $functionName = "getIntegralAttribute"; |
- } elsif ($attribute->type eq "unsigned long") { |
- $functionName = "getUnsignedIntegralAttribute"; |
- } else { |
- if ($contentAttributeName eq "WebCore::HTMLNames::idAttr") { |
- $functionName = "getIdAttribute"; |
- $contentAttributeName = ""; |
- } elsif ($contentAttributeName eq "WebCore::HTMLNames::nameAttr") { |
- $functionName = "getNameAttribute"; |
- $contentAttributeName = ""; |
- } elsif ($contentAttributeName eq "WebCore::HTMLNames::classAttr") { |
- $functionName = "getClassAttribute"; |
- $contentAttributeName = ""; |
- } elsif (CanUseFastAttribute($attribute)) { |
- $functionName = "fastGetAttribute"; |
- } else { |
- $functionName = "getAttribute"; |
- } |
- } |
- |
- return ($functionName, $contentAttributeName); |
-} |
- |
-sub SetterExpression |
-{ |
- my ($interfaceName, $attribute) = @_; |
- |
- my $contentAttributeName = ContentAttributeName($interfaceName, $attribute); |
- |
- if (!$contentAttributeName) { |
- return ("set" . FirstLetterToUpperCase(AttributeNameForGetterAndSetter($attribute))); |
- } |
- |
- my $functionName; |
- if ($attribute->type eq "boolean") { |
- $functionName = "setBooleanAttribute"; |
- } elsif ($attribute->type eq "long") { |
- $functionName = "setIntegralAttribute"; |
- } elsif ($attribute->type eq "unsigned long") { |
- $functionName = "setUnsignedIntegralAttribute"; |
- } else { |
- $functionName = "setAttribute"; |
- } |
- |
- return ($functionName, $contentAttributeName); |
-} |
- |
-sub GenerateConditionalString |
-{ |
- my $node = shift; |
- |
- my $conditional = $node->extendedAttributes->{"Conditional"}; |
- if ($conditional) { |
- return GenerateConditionalStringFromAttributeValue($conditional); |
- } else { |
- return ""; |
- } |
-} |
- |
-sub GenerateConditionalStringFromAttributeValue |
-{ |
- my $conditional = shift; |
- |
- my $operator = ($conditional =~ /&/ ? '&' : ($conditional =~ /\|/ ? '|' : '')); |
- if ($operator) { |
- # Avoid duplicated conditions. |
- my %conditions; |
- map { $conditions{$_} = 1 } split('\\' . $operator, $conditional); |
- return "ENABLE(" . join(") $operator$operator ENABLE(", sort keys %conditions) . ")"; |
- } else { |
- return "ENABLE(" . $conditional . ")"; |
- } |
-} |
- |
-sub GenerateCompileTimeCheckForEnumsIfNeeded |
-{ |
- my $interface = shift; |
- my $implClassName = GetImplName($interface); |
- my @checks = (); |
- # If necessary, check that all constants are available as enums with the same value. |
- if (!$interface->extendedAttributes->{"DoNotCheckConstants"} && @{$interface->constants}) { |
- push(@checks, "\n"); |
- foreach my $constant (@{$interface->constants}) { |
- my $reflect = $constant->extendedAttributes->{"Reflect"}; |
- my $name = $reflect ? $reflect : $constant->name; |
- my $value = $constant->value; |
- my $conditionalString = GenerateConditionalString($constant); |
- push(@checks, "#if ${conditionalString}\n") if $conditionalString; |
- |
- if ($constant->extendedAttributes->{"ImplementedBy"}) { |
- my $implementedByImplName = GetImplNameFromImplementedBy($constant->extendedAttributes->{"ImplementedBy"}); |
- push(@checks, "COMPILE_ASSERT($value == " . $implementedByImplName . "::$name, ${implClassName}Enum${name}IsWrongUseDoNotCheckConstants);\n"); |
- } else { |
- push(@checks, "COMPILE_ASSERT($value == ${implClassName}::$name, ${implClassName}Enum${name}IsWrongUseDoNotCheckConstants);\n"); |
- } |
- |
- push(@checks, "#endif\n") if $conditionalString; |
- } |
- push(@checks, "\n"); |
- } |
- return @checks; |
-} |
- |
-sub ExtendedAttributeContains |
-{ |
- my $callWith = shift; |
- return 0 unless $callWith; |
- my $keyword = shift; |
- |
- my @callWithKeywords = split /\s*\&\s*/, $callWith; |
- return grep { $_ eq $keyword } @callWithKeywords; |
-} |
- |
-sub InheritsInterface |
-{ |
- my $interface = shift; |
- my $interfaceName = shift; |
- my $found = 0; |
- |
- return 1 if $interfaceName eq $interface->name; |
- ForAllParents($interface, sub { |
- my $currentInterface = shift; |
- if ($currentInterface->name eq $interfaceName) { |
- $found = 1; |
- } |
- return 1 if $found; |
- }, 0); |
- |
- return $found; |
-} |
- |
-sub InheritsExtendedAttribute |
-{ |
- my $interface = shift; |
- my $extendedAttribute = shift; |
- my $found = 0; |
- |
- return 1 if $interface->extendedAttributes->{$extendedAttribute}; |
- ForAllParents($interface, sub { |
- my $currentInterface = shift; |
- if ($currentInterface->extendedAttributes->{$extendedAttribute}) { |
- $found = 1; |
- } |
- return 1 if $found; |
- }, 0); |
- |
- return $found; |
-} |
- |
-1; |