| OLD | NEW |
| (Empty) |
| 1 # Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org> | |
| 2 # Copyright (C) 2006 Anders Carlsson <andersca@mac.com> | |
| 3 # Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> | |
| 4 # Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org> | |
| 5 # Copyright (C) 2006 Apple Computer, Inc. | |
| 6 # Copyright (C) 2007, 2008, 2009, 2012 Google Inc. | |
| 7 # Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au> | |
| 8 # Copyright (C) Research In Motion Limited 2010. All rights reserved. | |
| 9 # Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) | |
| 10 # Copyright (C) 2012 Ericsson AB. All rights reserved. | |
| 11 # Copyright (C) 2013 Samsung Electronics. All rights reserved. | |
| 12 # | |
| 13 # This library is free software; you can redistribute it and/or | |
| 14 # modify it under the terms of the GNU Library General Public | |
| 15 # License as published by the Free Software Foundation; either | |
| 16 # version 2 of the License, or (at your option) any later version. | |
| 17 # | |
| 18 # This library is distributed in the hope that it will be useful, | |
| 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 21 # Library General Public License for more details. | |
| 22 # | |
| 23 # You should have received a copy of the GNU Library General Public License | |
| 24 # along with this library; see the file COPYING.LIB. If not, write to | |
| 25 # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
| 26 # Boston, MA 02111-1307, USA. | |
| 27 # | |
| 28 | |
| 29 package Block; | |
| 30 | |
| 31 # Sample code: | |
| 32 # my $outer = new Block("Free Name 1", "namespace Foo {", "} // namespace Foo"
); | |
| 33 # $outer->add(" void foo() {}"); | |
| 34 # my $inner = new Block("Free Name 2", "namespace Bar {", "} // namespace Bar"
); | |
| 35 # $inner->add(" void bar() {}"); | |
| 36 # $outer->add($inner); | |
| 37 # print $outer->toString(); | |
| 38 # | |
| 39 # Output code: | |
| 40 # namespace Foo { | |
| 41 # void foo() {} | |
| 42 # namespace Bar { | |
| 43 # void bar() {} | |
| 44 # } // namespace Bar | |
| 45 # } // namespace Foo | |
| 46 | |
| 47 sub new | |
| 48 { | |
| 49 my $package = shift; | |
| 50 my $name = shift || "Anonymous block"; | |
| 51 my $header = shift || ""; | |
| 52 my $footer = shift || ""; | |
| 53 | |
| 54 my $object = { | |
| 55 "name" => $name, | |
| 56 "header" => [$header], | |
| 57 "footer" => [$footer], | |
| 58 "contents" => [], | |
| 59 }; | |
| 60 bless $object, $package; | |
| 61 return $object; | |
| 62 } | |
| 63 | |
| 64 sub addHeader | |
| 65 { | |
| 66 my $object = shift; | |
| 67 my $header = shift || ""; | |
| 68 | |
| 69 push(@{$object->{header}}, $header); | |
| 70 } | |
| 71 | |
| 72 sub addFooter | |
| 73 { | |
| 74 my $object = shift; | |
| 75 my $footer = shift || ""; | |
| 76 | |
| 77 push(@{$object->{footer}}, $footer); | |
| 78 } | |
| 79 | |
| 80 sub add | |
| 81 { | |
| 82 my $object = shift; | |
| 83 my $content = shift || ""; | |
| 84 | |
| 85 push(@{$object->{contents}}, $content); | |
| 86 } | |
| 87 | |
| 88 sub toString | |
| 89 { | |
| 90 my $object = shift; | |
| 91 | |
| 92 my $header = join "", @{$object->{header}}; | |
| 93 my $footer = join "", @{$object->{footer}}; | |
| 94 my $code = ""; | |
| 95 $code .= "/* BEGIN " . $object->{name} . " */\n" if $verbose; | |
| 96 $code .= $header . "\n" if $header; | |
| 97 for my $content (@{$object->{contents}}) { | |
| 98 if (ref($content) eq "Block") { | |
| 99 $code .= $content->toString(); | |
| 100 } else { | |
| 101 $code .= $content; | |
| 102 } | |
| 103 } | |
| 104 $code .= $footer . "\n" if $footer; | |
| 105 $code .= "/* END " . $object->{name} . " */\n" if $verbose; | |
| 106 return $code; | |
| 107 } | |
| 108 | |
| 109 | |
| 110 package CodeGeneratorV8; | |
| 111 | |
| 112 use strict; | |
| 113 use Cwd; | |
| 114 use File::Basename; | |
| 115 use File::Find; | |
| 116 use File::Spec; | |
| 117 | |
| 118 my $idlDocument; | |
| 119 my $idlDirectories; | |
| 120 my $preprocessor; | |
| 121 my $defines; | |
| 122 my $verbose; | |
| 123 my $dependentIdlFiles; | |
| 124 my $writeFileOnlyIfChanged; | |
| 125 my $sourceRoot; | |
| 126 | |
| 127 # Cache of IDL file pathnames. | |
| 128 my $idlFiles; | |
| 129 my $cachedInterfaces = {}; | |
| 130 | |
| 131 my %implIncludes = (); | |
| 132 my %headerIncludes = (); | |
| 133 | |
| 134 # Header code structure: | |
| 135 # Root ... Copyright, include duplication check | |
| 136 # Conditional ... #if FEATURE ... #endif (to be removed soon) | |
| 137 # Includes | |
| 138 # NameSpaceWebCore | |
| 139 # Class | |
| 140 # ClassPublic | |
| 141 # ClassPrivate | |
| 142 my %header; | |
| 143 | |
| 144 # Implementation code structure: | |
| 145 # Root ... Copyright | |
| 146 # Conditional ... #if FEATURE ... #endif (to be removed soon) | |
| 147 # Includes | |
| 148 # NameSpaceWebCore | |
| 149 # NameSpaceInternal ... namespace ${implClassName}V8Internal in case of no
n-callback | |
| 150 my %implementation; | |
| 151 | |
| 152 my %primitiveTypeHash = ("boolean" => 1, | |
| 153 "void" => 1, | |
| 154 "Date" => 1, | |
| 155 "byte" => 1, | |
| 156 "octet" => 1, | |
| 157 "short" => 1, | |
| 158 "long" => 1, | |
| 159 "long long" => 1, | |
| 160 "unsigned short" => 1, | |
| 161 "unsigned long" => 1, | |
| 162 "unsigned long long" => 1, | |
| 163 "float" => 1, | |
| 164 "double" => 1, | |
| 165 ); | |
| 166 | |
| 167 my %nonWrapperTypes = ("CompareHow" => 1, | |
| 168 "DOMTimeStamp" => 1, | |
| 169 "Dictionary" => 1, | |
| 170 "EventListener" => 1, | |
| 171 # FIXME: When EventTarget is an interface and not a mixin
, fix this so that | |
| 172 # EventTarget is treated as a wrapper type. | |
| 173 "EventTarget" => 1, | |
| 174 "MediaQueryListListener" => 1, | |
| 175 "NodeFilter" => 1, | |
| 176 "SerializedScriptValue" => 1, | |
| 177 "any" => 1, | |
| 178 ); | |
| 179 | |
| 180 my %typedArrayHash = ("ArrayBuffer" => [], | |
| 181 "ArrayBufferView" => [], | |
| 182 "Uint8Array" => ["unsigned char", "v8::kExternalUnsignedBy
teArray"], | |
| 183 "Uint8ClampedArray" => ["unsigned char", "v8::kExternalPix
elArray"], | |
| 184 "Uint16Array" => ["unsigned short", "v8::kExternalUnsigned
ShortArray"], | |
| 185 "Uint32Array" => ["unsigned int", "v8::kExternalUnsignedIn
tArray"], | |
| 186 "Int8Array" => ["signed char", "v8::kExternalByteArray"], | |
| 187 "Int16Array" => ["short", "v8::kExternalShortArray"], | |
| 188 "Int32Array" => ["int", "v8::kExternalIntArray"], | |
| 189 "Float32Array" => ["float", "v8::kExternalFloatArray"], | |
| 190 "Float64Array" => ["double", "v8::kExternalDoubleArray"], | |
| 191 ); | |
| 192 | |
| 193 my %callbackFunctionTypeHash = (); | |
| 194 | |
| 195 my %enumTypeHash = (); | |
| 196 | |
| 197 my %svgAnimatedTypeHash = ("SVGAnimatedAngle" => 1, "SVGAnimatedBoolean" => 1, | |
| 198 "SVGAnimatedEnumeration" => 1, "SVGAnimatedInteger" =
> 1, | |
| 199 "SVGAnimatedLength" => 1, "SVGAnimatedLengthList" =>
1, | |
| 200 "SVGAnimatedNumber" => 1, "SVGAnimatedNumberList" =>
1, | |
| 201 "SVGAnimatedPreserveAspectRatio" => 1, | |
| 202 "SVGAnimatedRect" => 1, "SVGAnimatedString" => 1, | |
| 203 "SVGAnimatedTransformList" => 1); | |
| 204 | |
| 205 my %svgAttributesInHTMLHash = ("class" => 1, "id" => 1, "onabort" => 1, "onclick
" => 1, | |
| 206 "onerror" => 1, "onload" => 1, "onmousedown" => 1
, | |
| 207 "onmousemove" => 1, "onmouseout" => 1, "onmouseov
er" => 1, | |
| 208 "onmouseup" => 1, "onresize" => 1, "onscroll" =>
1, | |
| 209 "onunload" => 1); | |
| 210 | |
| 211 my %svgTypeNeedingTearOff = ( | |
| 212 "SVGAngle" => "SVGPropertyTearOff<SVGAngle>", | |
| 213 "SVGLength" => "SVGPropertyTearOff<SVGLength>", | |
| 214 "SVGLengthList" => "SVGListPropertyTearOff<SVGLengthList>", | |
| 215 "SVGMatrix" => "SVGPropertyTearOff<SVGMatrix>", | |
| 216 "SVGNumber" => "SVGPropertyTearOff<float>", | |
| 217 "SVGNumberList" => "SVGListPropertyTearOff<SVGNumberList>", | |
| 218 "SVGPathSegList" => "SVGPathSegListPropertyTearOff", | |
| 219 "SVGPoint" => "SVGPropertyTearOff<FloatPoint>", | |
| 220 "SVGPointList" => "SVGListPropertyTearOff<SVGPointList>", | |
| 221 "SVGPreserveAspectRatio" => "SVGPropertyTearOff<SVGPreserveAspectRatio>", | |
| 222 "SVGRect" => "SVGPropertyTearOff<FloatRect>", | |
| 223 "SVGStringList" => "SVGStaticListPropertyTearOff<SVGStringList>", | |
| 224 "SVGTransform" => "SVGPropertyTearOff<SVGTransform>", | |
| 225 "SVGTransformList" => "SVGTransformListPropertyTearOff" | |
| 226 ); | |
| 227 | |
| 228 my %svgTypeWithWritablePropertiesNeedingTearOff = ( | |
| 229 "SVGPoint" => 1, | |
| 230 "SVGMatrix" => 1 | |
| 231 ); | |
| 232 | |
| 233 # Default .h template | |
| 234 my $headerTemplate = <<EOF; | |
| 235 /* | |
| 236 This file is part of the Blink open source project. | |
| 237 This file has been auto-generated by CodeGeneratorV8.pm. DO NOT MODIFY! | |
| 238 | |
| 239 This library is free software; you can redistribute it and/or | |
| 240 modify it under the terms of the GNU Library General Public | |
| 241 License as published by the Free Software Foundation; either | |
| 242 version 2 of the License, or (at your option) any later version. | |
| 243 | |
| 244 This library is distributed in the hope that it will be useful, | |
| 245 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 246 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 247 Library General Public License for more details. | |
| 248 | |
| 249 You should have received a copy of the GNU Library General Public License | |
| 250 along with this library; see the file COPYING.LIB. If not, write to | |
| 251 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
| 252 Boston, MA 02111-1307, USA. | |
| 253 */ | |
| 254 EOF | |
| 255 | |
| 256 sub new | |
| 257 { | |
| 258 my $object = shift; | |
| 259 my $reference = { }; | |
| 260 | |
| 261 $idlDocument = shift; | |
| 262 $idlDirectories = shift; | |
| 263 $preprocessor = shift; | |
| 264 $defines = shift; | |
| 265 $verbose = shift; | |
| 266 $dependentIdlFiles = shift; | |
| 267 $writeFileOnlyIfChanged = shift; | |
| 268 | |
| 269 $sourceRoot = getcwd(); | |
| 270 | |
| 271 bless($reference, $object); | |
| 272 return $reference; | |
| 273 } | |
| 274 | |
| 275 | |
| 276 sub IDLFileForInterface | |
| 277 { | |
| 278 my $interfaceName = shift; | |
| 279 | |
| 280 unless ($idlFiles) { | |
| 281 my @directories = map { $_ = "$sourceRoot/$_" if -d "$sourceRoot/$_"; $_
} @$idlDirectories; | |
| 282 push(@directories, "."); | |
| 283 | |
| 284 $idlFiles = { }; | |
| 285 foreach my $idlFile (@$dependentIdlFiles) { | |
| 286 $idlFiles->{fileparse(basename($idlFile), ".idl")} = $idlFile; | |
| 287 } | |
| 288 | |
| 289 my $wanted = sub { | |
| 290 $idlFiles->{$1} = $File::Find::name if /^([A-Z].*)\.idl$/; | |
| 291 $File::Find::prune = 1 if /^\../; | |
| 292 }; | |
| 293 find($wanted, @directories); | |
| 294 } | |
| 295 | |
| 296 return $idlFiles->{$interfaceName}; | |
| 297 } | |
| 298 | |
| 299 sub ParseInterface | |
| 300 { | |
| 301 my $interfaceName = shift; | |
| 302 | |
| 303 if (exists $cachedInterfaces->{$interfaceName}) { | |
| 304 return $cachedInterfaces->{$interfaceName}; | |
| 305 } | |
| 306 | |
| 307 # Step #1: Find the IDL file associated with 'interface' | |
| 308 my $filename = IDLFileForInterface($interfaceName) | |
| 309 or die("Could NOT find IDL file for interface \"$interfaceName\" $!\n"); | |
| 310 | |
| 311 print " | |> Parsing parent IDL \"$filename\" for interface \"$interfaceN
ame\"\n" if $verbose; | |
| 312 | |
| 313 # Step #2: Parse the found IDL file (in quiet mode). | |
| 314 my $parser = IDLParser->new(1); | |
| 315 my $document = $parser->Parse($filename, $defines, $preprocessor); | |
| 316 | |
| 317 foreach my $interface (@{$document->interfaces}) { | |
| 318 if ($interface->name eq $interfaceName or $interface->isPartial) { | |
| 319 $cachedInterfaces->{$interfaceName} = $interface; | |
| 320 return $interface; | |
| 321 } | |
| 322 } | |
| 323 | |
| 324 die("Could NOT find interface definition for $interfaceName in $filename"); | |
| 325 } | |
| 326 | |
| 327 sub GenerateInterface | |
| 328 { | |
| 329 my $object = shift; | |
| 330 my $interface = shift; | |
| 331 | |
| 332 %callbackFunctionTypeHash = map { $_->name => $_ } @{$idlDocument->callbackF
unctions}; | |
| 333 %enumTypeHash = map { $_->name => $_->values } @{$idlDocument->enumerations}
; | |
| 334 my $v8ClassName = GetV8ClassName($interface); | |
| 335 my $defineName = $v8ClassName . "_h"; | |
| 336 my $internalNamespace = GetImplName($interface) . "V8Internal"; | |
| 337 | |
| 338 my $conditionalString = GenerateConditionalString($interface); | |
| 339 my $conditionalIf = ""; | |
| 340 my $conditionalEndif = ""; | |
| 341 if ($conditionalString) { | |
| 342 $conditionalIf = "#if ${conditionalString}"; | |
| 343 $conditionalEndif = "#endif // ${conditionalString}"; | |
| 344 } | |
| 345 | |
| 346 $header{root} = new Block("ROOT", "", ""); | |
| 347 # FIXME: newlines should be generated by Block::toString(). | |
| 348 $header{conditional} = new Block("Conditional", "$conditionalIf", $condition
alEndif ? "$conditionalEndif\n" : ""); | |
| 349 $header{includes} = new Block("Includes", "", ""); | |
| 350 $header{nameSpaceWebCore} = new Block("Namespace WebCore", "\nnamespace WebC
ore {\n", "}\n"); | |
| 351 $header{class} = new Block("Class definition", "", ""); | |
| 352 $header{classPublic} = new Block("Class public:", "public:", ""); | |
| 353 $header{classPrivate} = new Block("Class private:", "private:", ""); | |
| 354 | |
| 355 $header{root}->add($header{conditional}); | |
| 356 $header{conditional}->add($header{includes}); | |
| 357 $header{conditional}->add($header{nameSpaceWebCore}); | |
| 358 $header{nameSpaceWebCore}->add($header{class}); | |
| 359 $header{class}->add($header{classPublic}); | |
| 360 $header{class}->add($header{classPrivate}); | |
| 361 | |
| 362 # - Add default header template | |
| 363 $header{root}->addHeader($headerTemplate . "\n"); | |
| 364 $header{root}->addHeader("#ifndef $defineName\n#define $defineName\n"); | |
| 365 $header{root}->addFooter("#endif // $defineName"); | |
| 366 | |
| 367 $implementation{root} = new Block("ROOT", "", ""); | |
| 368 $conditionalEndif = "\n$conditionalEndif" if !$interface->isCallback and $co
nditionalEndif; | |
| 369 $implementation{conditional} = new Block("Conditional", $conditionalIf, $con
ditionalEndif); | |
| 370 $implementation{includes} = new Block("Includes", "", ""); | |
| 371 | |
| 372 # FIXME: newlines should be generated by Block::toString(). | |
| 373 my $nameSpaceWebCoreBegin = "namespace WebCore {\n"; | |
| 374 my $nameSpaceWebCoreEnd = "} // namespace WebCore"; | |
| 375 $nameSpaceWebCoreBegin = "$nameSpaceWebCoreBegin\n" if !$interface->isCallba
ck; | |
| 376 $nameSpaceWebCoreEnd = "\n$nameSpaceWebCoreEnd\n" if $interface->isCallback; | |
| 377 $implementation{nameSpaceWebCore} = new Block("Namespace WebCore", $nameSpac
eWebCoreBegin, $nameSpaceWebCoreEnd); | |
| 378 $implementation{nameSpaceInternal} = new Block("Internal namespace", "namesp
ace $internalNamespace {\n", "} // namespace $internalNamespace\n"); | |
| 379 | |
| 380 $implementation{root}->add($implementation{conditional}); | |
| 381 $implementation{conditional}->add($implementation{includes}); | |
| 382 $implementation{conditional}->add($implementation{nameSpaceWebCore}); | |
| 383 if (!$interface->isCallback) { | |
| 384 $implementation{nameSpaceWebCore}->add($implementation{nameSpaceInternal
}); | |
| 385 } | |
| 386 | |
| 387 # - Add default header template | |
| 388 $implementation{root}->addHeader($headerTemplate); | |
| 389 $implementation{root}->addHeader("\n#include \"config.h\""); | |
| 390 $implementation{includes}->add("#include \"${v8ClassName}.h\"\n\n"); | |
| 391 | |
| 392 # Start actual generation | |
| 393 if ($interface->isCallback) { | |
| 394 $object->GenerateCallbackHeader($interface); | |
| 395 $object->GenerateCallbackImplementation($interface); | |
| 396 } else { | |
| 397 $object->GenerateHeader($interface); | |
| 398 $object->GenerateImplementation($interface); | |
| 399 } | |
| 400 } | |
| 401 | |
| 402 sub AddToImplIncludes | |
| 403 { | |
| 404 my $header = shift; | |
| 405 $implIncludes{$header} = 1; | |
| 406 } | |
| 407 | |
| 408 sub AddToHeaderIncludes | |
| 409 { | |
| 410 my @includes = @_; | |
| 411 | |
| 412 for my $include (@includes) { | |
| 413 $headerIncludes{$include} = 1; | |
| 414 } | |
| 415 } | |
| 416 | |
| 417 sub SkipIncludeHeader | |
| 418 { | |
| 419 my $type = shift; | |
| 420 | |
| 421 return 1 if IsPrimitiveType($type); | |
| 422 return 1 if IsEnumType($type); | |
| 423 return 1 if IsCallbackFunctionType($type); | |
| 424 return 1 if $type eq "DOMString"; | |
| 425 | |
| 426 # Special case: SVGPoint.h / SVGNumber.h do not exist. | |
| 427 return 1 if $type eq "SVGPoint" or $type eq "SVGNumber"; | |
| 428 return 0; | |
| 429 } | |
| 430 | |
| 431 sub AddIncludesForType | |
| 432 { | |
| 433 my $type = shift; | |
| 434 | |
| 435 return if SkipIncludeHeader($type); | |
| 436 | |
| 437 # Default includes | |
| 438 if ($type eq "EventListener") { | |
| 439 AddToImplIncludes("core/dom/EventListener.h"); | |
| 440 } elsif ($type eq "SerializedScriptValue") { | |
| 441 AddToImplIncludes("bindings/v8/SerializedScriptValue.h"); | |
| 442 } elsif ($type eq "any" || IsCallbackFunctionType($type)) { | |
| 443 AddToImplIncludes("bindings/v8/ScriptValue.h"); | |
| 444 } elsif ($type eq "ArrayBuffer") { | |
| 445 AddToImplIncludes("bindings/v8/custom/V8ArrayBufferCustom.h"); | |
| 446 } else { | |
| 447 AddToImplIncludes("V8${type}.h"); | |
| 448 } | |
| 449 | |
| 450 # Additional includes | |
| 451 if ($type eq "CSSStyleSheet") { | |
| 452 AddToImplIncludes("core/css/CSSImportRule.h"); | |
| 453 } | |
| 454 } | |
| 455 | |
| 456 sub HeaderFilesForInterface | |
| 457 { | |
| 458 my $interfaceName = shift; | |
| 459 my $implClassName = shift; | |
| 460 | |
| 461 my @includes = (); | |
| 462 if (IsTypedArrayType($interfaceName) or $interfaceName eq "ArrayBuffer") { | |
| 463 push(@includes, "wtf/${interfaceName}.h"); | |
| 464 } elsif ($interfaceName =~ /SVGPathSeg/) { | |
| 465 $interfaceName =~ s/Abs|Rel//; | |
| 466 push(@includes, "core/svg/${interfaceName}.h"); | |
| 467 } elsif (!SkipIncludeHeader($interfaceName)) { | |
| 468 my $idlFilename = IDLFileForInterface($interfaceName) or die("Could NOT
find IDL file for interface \"$interfaceName\" $!\n"); | |
| 469 my $idlRelPath= "bindings/" . File::Spec->abs2rel($idlFilename, $sourceR
oot); | |
| 470 push(@includes, dirname($idlRelPath) . "/" . $implClassName . ".h"); | |
| 471 } | |
| 472 return @includes; | |
| 473 } | |
| 474 | |
| 475 sub NeedsOpaqueRootForGC | |
| 476 { | |
| 477 my $interface = shift; | |
| 478 return $interface->extendedAttributes->{"GenerateIsReachable"} || $interface
->extendedAttributes->{"CustomIsReachable"}; | |
| 479 } | |
| 480 | |
| 481 sub GenerateOpaqueRootForGC | |
| 482 { | |
| 483 my $interface = shift; | |
| 484 my $implClassName = GetImplName($interface); | |
| 485 my $v8ClassName = GetV8ClassName($interface); | |
| 486 | |
| 487 if ($interface->extendedAttributes->{"CustomIsReachable"}) { | |
| 488 return; | |
| 489 } | |
| 490 | |
| 491 my $code = <<END; | |
| 492 void* ${v8ClassName}::opaqueRootForGC(void* object, v8::Isolate* isolate) | |
| 493 { | |
| 494 ${implClassName}* impl = static_cast<${implClassName}*>(object); | |
| 495 END | |
| 496 my $isReachableMethod = $interface->extendedAttributes->{"GenerateIsReachabl
e"}; | |
| 497 if ($isReachableMethod) { | |
| 498 AddToImplIncludes("bindings/v8/V8GCController.h"); | |
| 499 AddToImplIncludes("core/dom/Element.h"); | |
| 500 $code .= <<END; | |
| 501 if (Node* owner = impl->${isReachableMethod}()) | |
| 502 return V8GCController::opaqueRootForGC(owner, isolate); | |
| 503 END | |
| 504 } | |
| 505 | |
| 506 $code .= <<END; | |
| 507 return object; | |
| 508 } | |
| 509 | |
| 510 END | |
| 511 $implementation{nameSpaceWebCore}->add($code); | |
| 512 } | |
| 513 | |
| 514 sub GetSVGPropertyTypes | |
| 515 { | |
| 516 my $implType = shift; | |
| 517 | |
| 518 my $svgPropertyType; | |
| 519 my $svgListPropertyType; | |
| 520 my $svgNativeType; | |
| 521 | |
| 522 return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $impl
Type =~ /SVG/; | |
| 523 | |
| 524 $svgNativeType = GetSVGTypeNeedingTearOff($implType); | |
| 525 return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $svgN
ativeType; | |
| 526 | |
| 527 # Append space to avoid compilation errors when using PassRefPtr<$svgNative
Type> | |
| 528 $svgNativeType = "$svgNativeType "; | |
| 529 | |
| 530 my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($implType); | |
| 531 if ($svgNativeType =~ /SVGPropertyTearOff/) { | |
| 532 $svgPropertyType = $svgWrappedNativeType; | |
| 533 AddToImplIncludes("core/svg/properties/SVGAnimatedPropertyTearOff.h"); | |
| 534 } elsif ($svgNativeType =~ /SVGListPropertyTearOff/ or $svgNativeType =~ /SV
GStaticListPropertyTearOff/ or $svgNativeType =~ /SVGTransformListPropertyTearOf
f/) { | |
| 535 $svgListPropertyType = $svgWrappedNativeType; | |
| 536 AddToHeaderIncludes("core/svg/properties/SVGAnimatedListPropertyTearOff.
h"); | |
| 537 } elsif ($svgNativeType =~ /SVGPathSegListPropertyTearOff/) { | |
| 538 $svgListPropertyType = $svgWrappedNativeType; | |
| 539 AddToHeaderIncludes("core/svg/properties/SVGPathSegListPropertyTearOff.h
"); | |
| 540 } | |
| 541 | |
| 542 if ($svgPropertyType) { | |
| 543 $svgPropertyType = "SVGPoint" if $svgPropertyType eq "FloatPoint"; | |
| 544 } | |
| 545 | |
| 546 return ($svgPropertyType, $svgListPropertyType, $svgNativeType); | |
| 547 } | |
| 548 | |
| 549 sub GetIndexedGetterFunction | |
| 550 { | |
| 551 my $interface = shift; | |
| 552 | |
| 553 # FIXME: Expose indexed getter of CSSMixFunctionValue by removing this speci
al case | |
| 554 # because CSSValueList(which is parent of CSSMixFunctionValue) has indexed p
roperty getter. | |
| 555 if ($interface->name eq "CSSMixFunctionValue") { | |
| 556 return 0; | |
| 557 } | |
| 558 | |
| 559 return GetSpecialAccessorFunctionForType($interface, "getter", "unsigned lon
g", 1); | |
| 560 } | |
| 561 | |
| 562 sub GetIndexedSetterFunction | |
| 563 { | |
| 564 my $interface = shift; | |
| 565 | |
| 566 return GetSpecialAccessorFunctionForType($interface, "setter", "unsigned lon
g", 2); | |
| 567 } | |
| 568 | |
| 569 sub GetIndexedDeleterFunction | |
| 570 { | |
| 571 my $interface = shift; | |
| 572 | |
| 573 return GetSpecialAccessorFunctionForType($interface, "deleter", "unsigned lo
ng", 1); | |
| 574 } | |
| 575 | |
| 576 sub GetNamedGetterFunction | |
| 577 { | |
| 578 my $interface = shift; | |
| 579 return GetSpecialAccessorFunctionForType($interface, "getter", "DOMString",
1); | |
| 580 } | |
| 581 | |
| 582 sub GetNamedSetterFunction | |
| 583 { | |
| 584 my $interface = shift; | |
| 585 return GetSpecialAccessorFunctionForType($interface, "setter", "DOMString",
2); | |
| 586 } | |
| 587 | |
| 588 sub GetNamedDeleterFunction | |
| 589 { | |
| 590 my $interface = shift; | |
| 591 return GetSpecialAccessorFunctionForType($interface, "deleter", "DOMString",
1); | |
| 592 } | |
| 593 | |
| 594 sub GetSpecialAccessorFunctionForType | |
| 595 { | |
| 596 my $interface = shift; | |
| 597 my $special = shift; | |
| 598 my $firstParameterType = shift; | |
| 599 my $numberOfParameters = shift; | |
| 600 | |
| 601 foreach my $function (@{$interface->functions}) { | |
| 602 my $specials = $function->specials; | |
| 603 my $specialExists = grep { $_ eq $special } @$specials; | |
| 604 my $parameters = $function->parameters; | |
| 605 if ($specialExists and scalar(@$parameters) == $numberOfParameters and $
parameters->[0]->type eq $firstParameterType) { | |
| 606 return $function; | |
| 607 } | |
| 608 } | |
| 609 | |
| 610 return 0; | |
| 611 } | |
| 612 | |
| 613 sub GenerateHeader | |
| 614 { | |
| 615 my $object = shift; | |
| 616 my $interface = shift; | |
| 617 | |
| 618 my $interfaceName = $interface->name; | |
| 619 my $implClassName = GetImplName($interface); | |
| 620 my $v8ClassName = GetV8ClassName($interface); | |
| 621 | |
| 622 LinkOverloadedFunctions($interface); | |
| 623 | |
| 624 # Ensure the IsDOMNodeType function is in sync. | |
| 625 die("IsDOMNodeType is out of date with respect to $interfaceName") if IsDOMN
odeType($interfaceName) != InheritsInterface($interface, "Node"); | |
| 626 | |
| 627 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGProperty
Types($interfaceName); | |
| 628 | |
| 629 my $parentInterface = $interface->parent; | |
| 630 AddToHeaderIncludes("V8${parentInterface}.h") if $parentInterface; | |
| 631 AddToHeaderIncludes("bindings/v8/WrapperTypeInfo.h"); | |
| 632 AddToHeaderIncludes("bindings/v8/V8Binding.h"); | |
| 633 AddToHeaderIncludes("bindings/v8/V8DOMWrapper.h"); | |
| 634 AddToHeaderIncludes(HeaderFilesForInterface($interfaceName, $implClassName))
; | |
| 635 foreach my $headerInclude (sort keys(%headerIncludes)) { | |
| 636 $header{includes}->add("#include \"${headerInclude}\"\n"); | |
| 637 } | |
| 638 | |
| 639 $header{nameSpaceWebCore}->addHeader("\ntemplate<typename PropertyType> clas
s SVGPropertyTearOff;\n") if $svgPropertyType; | |
| 640 if ($svgNativeType) { | |
| 641 if ($svgNativeType =~ /SVGStaticListPropertyTearOff/) { | |
| 642 $header{nameSpaceWebCore}->addHeader("\ntemplate<typename PropertyTy
pe> class SVGStaticListPropertyTearOff;\n"); | |
| 643 } else { | |
| 644 $header{nameSpaceWebCore}->addHeader("\ntemplate<typename PropertyTy
pe> class SVGListPropertyTearOff;\n"); | |
| 645 } | |
| 646 } | |
| 647 | |
| 648 $header{nameSpaceWebCore}->addHeader("class FloatRect;\n") if $svgPropertyTy
pe && $svgPropertyType eq "FloatRect"; | |
| 649 $header{nameSpaceWebCore}->addHeader("\nclass Dictionary;") if IsConstructor
Template($interface, "Event"); | |
| 650 | |
| 651 my $nativeType = GetNativeTypeForConversions($interface); | |
| 652 if ($interface->extendedAttributes->{"NamedConstructor"}) { | |
| 653 $header{nameSpaceWebCore}->addHeader(<<END); | |
| 654 | |
| 655 class V8${nativeType}Constructor { | |
| 656 public: | |
| 657 static v8::Handle<v8::FunctionTemplate> GetTemplate(v8::Isolate*, WrapperWor
ldType); | |
| 658 static WrapperTypeInfo info; | |
| 659 }; | |
| 660 END | |
| 661 } | |
| 662 | |
| 663 $header{class}->addHeader("class $v8ClassName {"); | |
| 664 $header{class}->addFooter("};"); | |
| 665 | |
| 666 $header{classPublic}->add(<<END); | |
| 667 static bool HasInstance(v8::Handle<v8::Value>, v8::Isolate*, WrapperWorldTyp
e); | |
| 668 static bool HasInstanceInAnyWorld(v8::Handle<v8::Value>, v8::Isolate*); | |
| 669 static v8::Handle<v8::FunctionTemplate> GetTemplate(v8::Isolate*, WrapperWor
ldType); | |
| 670 static ${nativeType}* toNative(v8::Handle<v8::Object> object) | |
| 671 { | |
| 672 return reinterpret_cast<${nativeType}*>(object->GetAlignedPointerFromInt
ernalField(v8DOMWrapperObjectIndex)); | |
| 673 } | |
| 674 static void derefObject(void*); | |
| 675 static WrapperTypeInfo info; | |
| 676 END | |
| 677 | |
| 678 if (NeedsOpaqueRootForGC($interface)) { | |
| 679 $header{classPublic}->add(" static void* opaqueRootForGC(void*, v8::I
solate*);\n"); | |
| 680 } | |
| 681 | |
| 682 if (InheritsExtendedAttribute($interface, "ActiveDOMObject")) { | |
| 683 $header{classPublic}->add(" static ActiveDOMObject* toActiveDOMObject
(v8::Handle<v8::Object>);\n"); | |
| 684 } | |
| 685 | |
| 686 if (InheritsExtendedAttribute($interface, "EventTarget")) { | |
| 687 $header{classPublic}->add(" static EventTarget* toEventTarget(v8::Han
dle<v8::Object>);\n"); | |
| 688 } | |
| 689 | |
| 690 if ($interfaceName eq "Window") { | |
| 691 $header{classPublic}->add(<<END); | |
| 692 static v8::Handle<v8::ObjectTemplate> GetShadowObjectTemplate(v8::Isolate*,
WrapperWorldType); | |
| 693 END | |
| 694 } | |
| 695 | |
| 696 my @enabledPerContextFunctions; | |
| 697 foreach my $function (@{$interface->functions}) { | |
| 698 my $name = $function->name; | |
| 699 next if $name eq ""; | |
| 700 my $attrExt = $function->extendedAttributes; | |
| 701 | |
| 702 if (HasCustomMethod($attrExt) && !$attrExt->{"ImplementedBy"} && $functi
on->{overloadIndex} == 1) { | |
| 703 my $conditionalString = GenerateConditionalString($function); | |
| 704 $header{classPublic}->add("#if ${conditionalString}\n") if $conditio
nalString; | |
| 705 $header{classPublic}->add(<<END); | |
| 706 static void ${name}MethodCustom(const v8::FunctionCallbackInfo<v8::Value>&); | |
| 707 END | |
| 708 $header{classPublic}->add("#endif // ${conditionalString}\n") if $co
nditionalString; | |
| 709 } | |
| 710 if ($attrExt->{"EnabledPerContext"}) { | |
| 711 push(@enabledPerContextFunctions, $function); | |
| 712 } | |
| 713 } | |
| 714 | |
| 715 if (IsConstructable($interface)) { | |
| 716 $header{classPublic}->add(" static void constructorCallback(const v8:
:FunctionCallbackInfo<v8::Value>&);\n"); | |
| 717 END | |
| 718 } | |
| 719 if (HasCustomConstructor($interface)) { | |
| 720 $header{classPublic}->add(" static void constructorCustom(const v8::F
unctionCallbackInfo<v8::Value>&);\n"); | |
| 721 } | |
| 722 | |
| 723 my @enabledPerContextAttributes; | |
| 724 foreach my $attribute (@{$interface->attributes}) { | |
| 725 my $name = $attribute->name; | |
| 726 my $attrExt = $attribute->extendedAttributes; | |
| 727 my $conditionalString = GenerateConditionalString($attribute); | |
| 728 if (HasCustomGetter($attrExt) && !$attrExt->{"ImplementedBy"}) { | |
| 729 $header{classPublic}->add("#if ${conditionalString}\n") if $conditio
nalString; | |
| 730 $header{classPublic}->add(<<END); | |
| 731 static void ${name}AttrGetterCustom(v8::Local<v8::String> name, const v8::Pr
opertyCallbackInfo<v8::Value>&); | |
| 732 END | |
| 733 $header{classPublic}->add("#endif // ${conditionalString}\n") if $co
nditionalString; | |
| 734 } | |
| 735 if (HasCustomSetter($attrExt) && !$attrExt->{"ImplementedBy"}) { | |
| 736 $header{classPublic}->add("#if ${conditionalString}\n") if $conditio
nalString; | |
| 737 $header{classPublic}->add(<<END); | |
| 738 static void ${name}AttrSetterCustom(v8::Local<v8::String> name, v8::Local<v8
::Value>, const v8::PropertyCallbackInfo<void>&); | |
| 739 END | |
| 740 $header{classPublic}->add("#endif // ${conditionalString}\n") if $co
nditionalString; | |
| 741 } | |
| 742 if ($attrExt->{"EnabledPerContext"}) { | |
| 743 push(@enabledPerContextAttributes, $attribute); | |
| 744 } | |
| 745 } | |
| 746 | |
| 747 GenerateHeaderNamedAndIndexedPropertyAccessors($interface); | |
| 748 GenerateHeaderLegacyCall($interface); | |
| 749 GenerateHeaderCustomInternalFieldIndices($interface); | |
| 750 | |
| 751 if ($interface->name eq "Window") { | |
| 752 $header{classPublic}->add(<<END); | |
| 753 static bool namedSecurityCheckCustom(v8::Local<v8::Object> host, v8::Local<v
8::Value> key, v8::AccessType, v8::Local<v8::Value> data); | |
| 754 static bool indexedSecurityCheckCustom(v8::Local<v8::Object> host, uint32_t
index, v8::AccessType, v8::Local<v8::Value> data); | |
| 755 END | |
| 756 } | |
| 757 | |
| 758 if (@enabledPerContextAttributes) { | |
| 759 $header{classPublic}->add(<<END); | |
| 760 static void installPerContextProperties(v8::Handle<v8::Object>, ${nativeType
}*, v8::Isolate*); | |
| 761 END | |
| 762 } else { | |
| 763 $header{classPublic}->add(<<END); | |
| 764 static void installPerContextProperties(v8::Handle<v8::Object>, ${nativeType
}*, v8::Isolate*) { } | |
| 765 END | |
| 766 } | |
| 767 | |
| 768 if (@enabledPerContextFunctions) { | |
| 769 $header{classPublic}->add(<<END); | |
| 770 static void installPerContextPrototypeProperties(v8::Handle<v8::Object>, v8:
:Isolate*); | |
| 771 END | |
| 772 } else { | |
| 773 $header{classPublic}->add(<<END); | |
| 774 static void installPerContextPrototypeProperties(v8::Handle<v8::Object>, v8:
:Isolate*) { } | |
| 775 END | |
| 776 } | |
| 777 | |
| 778 if ($interfaceName eq "HTMLElement") { | |
| 779 $header{classPublic}->add(<<END); | |
| 780 friend v8::Handle<v8::Object> createV8HTMLWrapper(HTMLElement*, v8::Handle<v
8::Object> creationContext, v8::Isolate*); | |
| 781 friend v8::Handle<v8::Object> createV8HTMLDirectWrapper(HTMLElement*, v8::Ha
ndle<v8::Object> creationContext, v8::Isolate*); | |
| 782 END | |
| 783 } elsif ($interfaceName eq "SVGElement") { | |
| 784 $header{classPublic}->add(<<END); | |
| 785 friend v8::Handle<v8::Object> createV8SVGWrapper(SVGElement*, v8::Handle<v8:
:Object> creationContext, v8::Isolate*); | |
| 786 friend v8::Handle<v8::Object> createV8SVGDirectWrapper(SVGElement*, v8::Hand
le<v8::Object> creationContext, v8::Isolate*); | |
| 787 friend v8::Handle<v8::Object> createV8SVGFallbackWrapper(SVGElement*, v8::Ha
ndle<v8::Object> creationContext, v8::Isolate*); | |
| 788 END | |
| 789 } elsif ($interfaceName eq "HTMLUnknownElement") { | |
| 790 $header{classPublic}->add(<<END); | |
| 791 friend v8::Handle<v8::Object> createV8HTMLFallbackWrapper(HTMLUnknownElement
*, v8::Handle<v8::Object> creationContext, v8::Isolate*); | |
| 792 END | |
| 793 } elsif ($interfaceName eq "Element") { | |
| 794 $header{classPublic}->add(<<END); | |
| 795 // This is a performance optimization hack. See V8Element::wrap. | |
| 796 friend v8::Handle<v8::Object> wrap(Node*, v8::Handle<v8::Object> creationCon
text, v8::Isolate*); | |
| 797 END | |
| 798 } | |
| 799 | |
| 800 my $noToV8 = $interface->extendedAttributes->{"DoNotGenerateToV8"}; | |
| 801 my $noWrap = $interface->extendedAttributes->{"DoNotGenerateWrap"} || $noToV
8; | |
| 802 if (!$noWrap) { | |
| 803 my $createWrapperArgumentType = GetPassRefPtrType($nativeType); | |
| 804 $header{classPrivate}->add(<<END); | |
| 805 friend v8::Handle<v8::Object> wrap(${nativeType}*, v8::Handle<v8::Object> cr
eationContext, v8::Isolate*); | |
| 806 static v8::Handle<v8::Object> createWrapper(${createWrapperArgumentType}, v8
::Handle<v8::Object> creationContext, v8::Isolate*); | |
| 807 END | |
| 808 } | |
| 809 | |
| 810 $header{nameSpaceWebCore}->add(<<END); | |
| 811 | |
| 812 template<> | |
| 813 class WrapperTypeTraits<${nativeType} > { | |
| 814 public: | |
| 815 static WrapperTypeInfo* info() { return &${v8ClassName}::info; } | |
| 816 }; | |
| 817 | |
| 818 END | |
| 819 | |
| 820 my $customWrap = $interface->extendedAttributes->{"CustomToV8"}; | |
| 821 if ($noToV8) { | |
| 822 die "Can't suppress toV8 for subclass\n" if $interface->parent; | |
| 823 } elsif ($noWrap) { | |
| 824 die "Must have custom toV8\n" if !$customWrap; | |
| 825 $header{nameSpaceWebCore}->add(<<END); | |
| 826 class ${nativeType}; | |
| 827 v8::Handle<v8::Value> toV8(${nativeType}*, v8::Handle<v8::Object> creationContex
t, v8::Isolate*); | |
| 828 v8::Handle<v8::Value> toV8ForMainWorld(${nativeType}*, v8::Handle<v8::Object> cr
eationContext, v8::Isolate*); | |
| 829 | |
| 830 template<class HolderContainer, class Wrappable> | |
| 831 inline v8::Handle<v8::Value> toV8Fast(${nativeType}* impl, const HolderContainer
& container, Wrappable*) | |
| 832 { | |
| 833 return toV8(impl, container.Holder(), container.GetIsolate()); | |
| 834 } | |
| 835 | |
| 836 template<class HolderContainer, class Wrappable> | |
| 837 inline v8::Handle<v8::Value> toV8FastForMainWorld(${nativeType}* impl, const Hol
derContainer& container, Wrappable*) | |
| 838 { | |
| 839 return toV8ForMainWorld(impl, container.Holder(), container.GetIsolate()); | |
| 840 } | |
| 841 END | |
| 842 } else { | |
| 843 | |
| 844 my $createWrapperCall = $customWrap ? "${v8ClassName}::wrap" : "${v8Clas
sName}::createWrapper"; | |
| 845 | |
| 846 if ($customWrap) { | |
| 847 $header{nameSpaceWebCore}->add(<<END); | |
| 848 | |
| 849 v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> creation
Context, v8::Isolate*); | |
| 850 END | |
| 851 } else { | |
| 852 $header{nameSpaceWebCore}->add(<<END); | |
| 853 | |
| 854 inline v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> c
reationContext, v8::Isolate* isolate) | |
| 855 { | |
| 856 ASSERT(impl); | |
| 857 ASSERT(DOMDataStore::getWrapper(impl, isolate).IsEmpty()); | |
| 858 if (ScriptWrappable::wrapperCanBeStoredInObject(impl)) { | |
| 859 const WrapperTypeInfo* actualInfo = ScriptWrappable::getTypeInfoFromObje
ct(impl); | |
| 860 // Might be a XXXConstructor::info instead of an XXX::info. These will b
oth have | |
| 861 // the same object de-ref functions, though, so use that as the basis of
the check. | |
| 862 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(actualInfo->derefObjectFunction
== ${v8ClassName}::info.derefObjectFunction); | |
| 863 } | |
| 864 return $createWrapperCall(impl, creationContext, isolate); | |
| 865 } | |
| 866 END | |
| 867 } | |
| 868 | |
| 869 $header{nameSpaceWebCore}->add(<<END); | |
| 870 | |
| 871 inline v8::Handle<v8::Value> toV8(${nativeType}* impl, v8::Handle<v8::Object> cr
eationContext, v8::Isolate* isolate) | |
| 872 { | |
| 873 if (UNLIKELY(!impl)) | |
| 874 return v8NullWithCheck(isolate); | |
| 875 v8::Handle<v8::Value> wrapper = DOMDataStore::getWrapper(impl, isolate); | |
| 876 if (!wrapper.IsEmpty()) | |
| 877 return wrapper; | |
| 878 return wrap(impl, creationContext, isolate); | |
| 879 } | |
| 880 | |
| 881 inline v8::Handle<v8::Value> toV8ForMainWorld(${nativeType}* impl, v8::Handle<v8
::Object> creationContext, v8::Isolate* isolate) | |
| 882 { | |
| 883 ASSERT(worldType(isolate) == MainWorld); | |
| 884 if (UNLIKELY(!impl)) | |
| 885 return v8NullWithCheck(isolate); | |
| 886 v8::Handle<v8::Value> wrapper = DOMDataStore::getWrapperForMainWorld(impl); | |
| 887 if (!wrapper.IsEmpty()) | |
| 888 return wrapper; | |
| 889 return wrap(impl, creationContext, isolate); | |
| 890 } | |
| 891 | |
| 892 template<class HolderContainer, class Wrappable> | |
| 893 inline v8::Handle<v8::Value> toV8Fast(${nativeType}* impl, const HolderContainer
& container, Wrappable* wrappable) | |
| 894 { | |
| 895 if (UNLIKELY(!impl)) | |
| 896 return v8::Null(container.GetIsolate()); | |
| 897 v8::Handle<v8::Object> wrapper = DOMDataStore::getWrapperFast(impl, containe
r, wrappable); | |
| 898 if (!wrapper.IsEmpty()) | |
| 899 return wrapper; | |
| 900 return wrap(impl, container.Holder(), container.GetIsolate()); | |
| 901 } | |
| 902 | |
| 903 template<class HolderContainer, class Wrappable> | |
| 904 inline v8::Handle<v8::Value> toV8FastForMainWorld(${nativeType}* impl, const Hol
derContainer& container, Wrappable* wrappable) | |
| 905 { | |
| 906 ASSERT(worldType(container.GetIsolate()) == MainWorld); | |
| 907 if (UNLIKELY(!impl)) | |
| 908 return v8::Null(container.GetIsolate()); | |
| 909 v8::Handle<v8::Object> wrapper = DOMDataStore::getWrapperForMainWorld(impl); | |
| 910 if (!wrapper.IsEmpty()) | |
| 911 return wrapper; | |
| 912 return wrap(impl, container.Holder(), container.GetIsolate()); | |
| 913 } | |
| 914 | |
| 915 template<class HolderContainer, class Wrappable> | |
| 916 inline v8::Handle<v8::Value> toV8FastForMainWorld(PassRefPtr< ${nativeType} > im
pl, const HolderContainer& container, Wrappable* wrappable) | |
| 917 { | |
| 918 return toV8FastForMainWorld(impl.get(), container, wrappable); | |
| 919 } | |
| 920 | |
| 921 END | |
| 922 } | |
| 923 | |
| 924 $header{nameSpaceWebCore}->add(<<END); | |
| 925 | |
| 926 template<class HolderContainer, class Wrappable> | |
| 927 inline v8::Handle<v8::Value> toV8Fast(PassRefPtr< ${nativeType} > impl, const Ho
lderContainer& container, Wrappable* wrappable) | |
| 928 { | |
| 929 return toV8Fast(impl.get(), container, wrappable); | |
| 930 } | |
| 931 | |
| 932 inline v8::Handle<v8::Value> toV8(PassRefPtr< ${nativeType} > impl, v8::Handle<v
8::Object> creationContext, v8::Isolate* isolate) | |
| 933 { | |
| 934 return toV8(impl.get(), creationContext, isolate); | |
| 935 } | |
| 936 | |
| 937 END | |
| 938 | |
| 939 if (IsConstructorTemplate($interface, "Event")) { | |
| 940 $header{nameSpaceWebCore}->add("bool fill${implClassName}Init(${implClas
sName}Init&, const Dictionary&);\n\n"); | |
| 941 } | |
| 942 } | |
| 943 | |
| 944 sub GetInternalFields | |
| 945 { | |
| 946 my $interface = shift; | |
| 947 | |
| 948 my @customInternalFields = (); | |
| 949 # Event listeners on DOM nodes are explicitly supported in the GC controller
. | |
| 950 if (!InheritsInterface($interface, "Node") && | |
| 951 InheritsExtendedAttribute($interface, "EventTarget")) { | |
| 952 push(@customInternalFields, "eventListenerCacheIndex"); | |
| 953 } | |
| 954 return @customInternalFields; | |
| 955 } | |
| 956 | |
| 957 sub GenerateHeaderCustomInternalFieldIndices | |
| 958 { | |
| 959 my $interface = shift; | |
| 960 my @customInternalFields = GetInternalFields($interface); | |
| 961 my $customFieldCounter = 0; | |
| 962 foreach my $customInternalField (@customInternalFields) { | |
| 963 $header{classPublic}->add(<<END); | |
| 964 static const int ${customInternalField} = v8DefaultWrapperInternalFieldCount
+ ${customFieldCounter}; | |
| 965 END | |
| 966 $customFieldCounter++; | |
| 967 } | |
| 968 $header{classPublic}->add(<<END); | |
| 969 static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + $
{customFieldCounter}; | |
| 970 END | |
| 971 } | |
| 972 | |
| 973 sub GenerateHeaderNamedAndIndexedPropertyAccessors | |
| 974 { | |
| 975 my $interface = shift; | |
| 976 | |
| 977 my $indexedGetterFunction = GetIndexedGetterFunction($interface); | |
| 978 my $hasCustomIndexedGetter = $indexedGetterFunction && $indexedGetterFunctio
n->extendedAttributes->{"Custom"}; | |
| 979 | |
| 980 my $indexedSetterFunction = GetIndexedSetterFunction($interface); | |
| 981 my $hasCustomIndexedSetter = $indexedSetterFunction && $indexedSetterFunctio
n->extendedAttributes->{"Custom"}; | |
| 982 | |
| 983 my $indexedDeleterFunction = GetIndexedDeleterFunction($interface); | |
| 984 my $hasCustomIndexedDeleters = $indexedDeleterFunction && $indexedDeleterFun
ction->extendedAttributes->{"Custom"}; | |
| 985 | |
| 986 my $namedGetterFunction = GetNamedGetterFunction($interface); | |
| 987 my $hasCustomNamedGetter = $namedGetterFunction && $namedGetterFunction->ext
endedAttributes->{"Custom"}; | |
| 988 | |
| 989 my $namedSetterFunction = GetNamedSetterFunction($interface); | |
| 990 my $hasCustomNamedSetter = $namedSetterFunction && $namedSetterFunction->ext
endedAttributes->{"Custom"}; | |
| 991 | |
| 992 my $namedDeleterFunction = GetNamedDeleterFunction($interface); | |
| 993 my $hasCustomNamedDeleter = $namedDeleterFunction && $namedDeleterFunction->
extendedAttributes->{"Custom"}; | |
| 994 | |
| 995 my $namedEnumeratorFunction = $namedGetterFunction && !$namedGetterFunction-
>extendedAttributes->{"NotEnumerable"}; | |
| 996 my $hasCustomNamedEnumerator = $namedGetterFunction && $namedGetterFunction-
>extendedAttributes->{"CustomEnumerateProperty"}; | |
| 997 | |
| 998 if ($hasCustomIndexedGetter) { | |
| 999 $header{classPublic}->add(" static void indexedPropertyGetterCustom(u
int32_t, const v8::PropertyCallbackInfo<v8::Value>&);\n"); | |
| 1000 } | |
| 1001 | |
| 1002 if ($hasCustomIndexedSetter) { | |
| 1003 $header{classPublic}->add(" static void indexedPropertySetterCustom(u
int32_t, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&);\n"); | |
| 1004 } | |
| 1005 | |
| 1006 if ($hasCustomIndexedDeleters) { | |
| 1007 $header{classPublic}->add(" static void indexedPropertyDeleterCustom(
uint32_t, const v8::PropertyCallbackInfo<v8::Boolean>&);\n"); | |
| 1008 } | |
| 1009 | |
| 1010 if ($hasCustomNamedGetter) { | |
| 1011 $header{classPublic}->add(" static void namedPropertyGetterCustom(v8:
:Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>&);\n"); | |
| 1012 } | |
| 1013 | |
| 1014 if ($hasCustomNamedSetter) { | |
| 1015 $header{classPublic}->add(" static void namedPropertySetterCustom(v8:
:Local<v8::String>, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Val
ue>&);\n"); | |
| 1016 } | |
| 1017 | |
| 1018 if ($hasCustomNamedDeleter) { | |
| 1019 $header{classPublic}->add(" static void namedPropertyDeleterCustom(v8
::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Boolean>&);\n"); | |
| 1020 } | |
| 1021 | |
| 1022 if ($hasCustomNamedEnumerator) { | |
| 1023 $header{classPublic}->add(" static void namedPropertyEnumeratorCustom
(const v8::PropertyCallbackInfo<v8::Array>&);\n"); | |
| 1024 $header{classPublic}->add(" static void namedPropertyQueryCustom(v8::
Local<v8::String>, const v8::PropertyCallbackInfo<v8::Integer>&);\n"); | |
| 1025 } | |
| 1026 } | |
| 1027 | |
| 1028 sub GenerateHeaderLegacyCall | |
| 1029 { | |
| 1030 my $interface = shift; | |
| 1031 | |
| 1032 if ($interface->extendedAttributes->{"CustomLegacyCall"}) { | |
| 1033 $header{classPublic}->add(" static void legacyCallCustom(const v8::Fu
nctionCallbackInfo<v8::Value>&);\n"); | |
| 1034 } | |
| 1035 } | |
| 1036 | |
| 1037 sub HasActivityLogging | |
| 1038 { | |
| 1039 my $forMainWorldSuffix = shift; | |
| 1040 my $attrExt = shift; | |
| 1041 my $access = shift; | |
| 1042 | |
| 1043 if (!$attrExt->{"ActivityLog"}) { | |
| 1044 return 0; | |
| 1045 } | |
| 1046 my $logAllAccess = ($attrExt->{"ActivityLog"} =~ /^Access/); | |
| 1047 my $logGetter = ($attrExt->{"ActivityLog"} =~ /^Getter/); | |
| 1048 my $logSetter = ($attrExt->{"ActivityLog"} =~ /^Setter/); | |
| 1049 my $logOnlyIsolatedWorlds = ($attrExt->{"ActivityLog"} =~ /ForIsolatedWorlds
$/); | |
| 1050 | |
| 1051 if ($logOnlyIsolatedWorlds && $forMainWorldSuffix eq "ForMainWorld") { | |
| 1052 return 0; | |
| 1053 } | |
| 1054 return $logAllAccess || ($logGetter && $access eq "Getter") || ($logSetter &
& $access eq "Setter"); | |
| 1055 } | |
| 1056 | |
| 1057 sub IsConstructable | |
| 1058 { | |
| 1059 my $interface = shift; | |
| 1060 | |
| 1061 return $interface->extendedAttributes->{"CustomConstructor"} || $interface->
extendedAttributes->{"Constructor"} || $interface->extendedAttributes->{"Constru
ctorTemplate"}; | |
| 1062 } | |
| 1063 | |
| 1064 sub HasCustomConstructor | |
| 1065 { | |
| 1066 my $interface = shift; | |
| 1067 | |
| 1068 return $interface->extendedAttributes->{"CustomConstructor"}; | |
| 1069 } | |
| 1070 | |
| 1071 sub HasCustomGetter | |
| 1072 { | |
| 1073 my $attrExt = shift; | |
| 1074 return $attrExt->{"Custom"} || $attrExt->{"CustomGetter"}; | |
| 1075 } | |
| 1076 | |
| 1077 sub HasCustomSetter | |
| 1078 { | |
| 1079 my $attrExt = shift; | |
| 1080 return $attrExt->{"Custom"} || $attrExt->{"CustomSetter"}; | |
| 1081 } | |
| 1082 | |
| 1083 sub HasCustomMethod | |
| 1084 { | |
| 1085 my $attrExt = shift; | |
| 1086 return $attrExt->{"Custom"}; | |
| 1087 } | |
| 1088 | |
| 1089 sub IsReadonly | |
| 1090 { | |
| 1091 my $attribute = shift; | |
| 1092 my $attrExt = $attribute->extendedAttributes; | |
| 1093 return $attribute->isReadOnly && !$attrExt->{"Replaceable"}; | |
| 1094 } | |
| 1095 | |
| 1096 sub GetV8ClassName | |
| 1097 { | |
| 1098 my $interface = shift; | |
| 1099 return "V8" . $interface->name; | |
| 1100 } | |
| 1101 | |
| 1102 sub GetImplName | |
| 1103 { | |
| 1104 my $interfaceOrAttributeOrFunction = shift; | |
| 1105 return $interfaceOrAttributeOrFunction->extendedAttributes->{"ImplementedAs"
} || $interfaceOrAttributeOrFunction->name; | |
| 1106 } | |
| 1107 | |
| 1108 sub GetImplNameFromImplementedBy | |
| 1109 { | |
| 1110 my $implementedBy = shift; | |
| 1111 | |
| 1112 my $interface = ParseInterface($implementedBy); | |
| 1113 return $interface->extendedAttributes->{"ImplementedAs"} || $implementedBy; | |
| 1114 } | |
| 1115 | |
| 1116 sub GenerateDomainSafeFunctionGetter | |
| 1117 { | |
| 1118 my $function = shift; | |
| 1119 my $interface = shift; | |
| 1120 | |
| 1121 my $implClassName = GetImplName($interface); | |
| 1122 my $v8ClassName = GetV8ClassName($interface); | |
| 1123 my $funcName = $function->name; | |
| 1124 | |
| 1125 my $functionLength = GetFunctionLength($function); | |
| 1126 my $signature = "v8::Signature::New(V8PerIsolateData::from(info.GetIsolate()
)->rawTemplate(&" . $v8ClassName . "::info, currentWorldType))"; | |
| 1127 if ($function->extendedAttributes->{"DoNotCheckSignature"}) { | |
| 1128 $signature = "v8::Local<v8::Signature>()"; | |
| 1129 } | |
| 1130 | |
| 1131 my $newTemplateParams = "${implClassName}V8Internal::${funcName}MethodCallba
ck, v8Undefined(), $signature"; | |
| 1132 | |
| 1133 AddToImplIncludes("core/page/Frame.h"); | |
| 1134 AddToImplIncludes("bindings/v8/BindingSecurity.h"); | |
| 1135 $implementation{nameSpaceInternal}->add(<<END); | |
| 1136 static void ${funcName}AttrGetter(v8::Local<v8::String> name, const v8::Property
CallbackInfo<v8::Value>& info) | |
| 1137 { | |
| 1138 // This is only for getting a unique pointer which we can pass to privateTem
plate. | |
| 1139 static const char* privateTemplateUniqueKey = "${funcName}PrivateTemplate"; | |
| 1140 WrapperWorldType currentWorldType = worldType(info.GetIsolate()); | |
| 1141 V8PerIsolateData* data = V8PerIsolateData::from(info.GetIsolate()); | |
| 1142 v8::Handle<v8::FunctionTemplate> privateTemplate = data->privateTemplate(cur
rentWorldType, &privateTemplateUniqueKey, $newTemplateParams, $functionLength); | |
| 1143 | |
| 1144 v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(${
v8ClassName}::GetTemplate(info.GetIsolate(), currentWorldType)); | |
| 1145 if (holder.IsEmpty()) { | |
| 1146 // can only reach here by 'object.__proto__.func', and it should passed | |
| 1147 // domain security check already | |
| 1148 v8SetReturnValue(info, privateTemplate->GetFunction()); | |
| 1149 return; | |
| 1150 } | |
| 1151 ${implClassName}* imp = ${v8ClassName}::toNative(holder); | |
| 1152 if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame(), DoNotReportSecu
rityError)) { | |
| 1153 static const char* sharedTemplateUniqueKey = "${funcName}SharedTemplate"
; | |
| 1154 v8::Handle<v8::FunctionTemplate> sharedTemplate = data->privateTemplate(
currentWorldType, &sharedTemplateUniqueKey, $newTemplateParams, $functionLength)
; | |
| 1155 v8SetReturnValue(info, sharedTemplate->GetFunction()); | |
| 1156 return; | |
| 1157 } | |
| 1158 | |
| 1159 v8::Local<v8::Value> hiddenValue = info.This()->GetHiddenValue(name); | |
| 1160 if (!hiddenValue.IsEmpty()) { | |
| 1161 v8SetReturnValue(info, hiddenValue); | |
| 1162 return; | |
| 1163 } | |
| 1164 | |
| 1165 v8SetReturnValue(info, privateTemplate->GetFunction()); | |
| 1166 } | |
| 1167 | |
| 1168 END | |
| 1169 $implementation{nameSpaceInternal}->add(<<END); | |
| 1170 static void ${funcName}AttrGetterCallback(v8::Local<v8::String> name, const v8::
PropertyCallbackInfo<v8::Value>& info) | |
| 1171 { | |
| 1172 ${implClassName}V8Internal::${funcName}AttrGetter(name, info); | |
| 1173 } | |
| 1174 | |
| 1175 END | |
| 1176 } | |
| 1177 | |
| 1178 sub GenerateDomainSafeFunctionSetter | |
| 1179 { | |
| 1180 my $interface = shift; | |
| 1181 | |
| 1182 my $implClassName = GetImplName($interface); | |
| 1183 my $v8ClassName = GetV8ClassName($interface); | |
| 1184 | |
| 1185 AddToImplIncludes("bindings/v8/BindingSecurity.h"); | |
| 1186 $implementation{nameSpaceInternal}->add(<<END); | |
| 1187 static void ${implClassName}DomainSafeFunctionSetter(v8::Local<v8::String> name,
v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) | |
| 1188 { | |
| 1189 v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(${
v8ClassName}::GetTemplate(info.GetIsolate(), worldType(info.GetIsolate()))); | |
| 1190 if (holder.IsEmpty()) | |
| 1191 return; | |
| 1192 ${implClassName}* imp = ${v8ClassName}::toNative(holder); | |
| 1193 if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame())) | |
| 1194 return; | |
| 1195 | |
| 1196 info.This()->SetHiddenValue(name, value); | |
| 1197 } | |
| 1198 | |
| 1199 END | |
| 1200 } | |
| 1201 | |
| 1202 sub GenerateConstructorGetter | |
| 1203 { | |
| 1204 my $interface = shift; | |
| 1205 my $implClassName = GetImplName($interface); | |
| 1206 | |
| 1207 $implementation{nameSpaceInternal}->add(<<END); | |
| 1208 static void ${implClassName}ConstructorGetter(v8::Local<v8::String> name, const
v8::PropertyCallbackInfo<v8::Value>& info) | |
| 1209 { | |
| 1210 v8::Handle<v8::Value> data = info.Data(); | |
| 1211 ASSERT(data->IsExternal()); | |
| 1212 V8PerContextData* perContextData = V8PerContextData::from(info.Holder()->Cre
ationContext()); | |
| 1213 if (!perContextData) | |
| 1214 return; | |
| 1215 v8SetReturnValue(info, perContextData->constructorForType(WrapperTypeInfo::u
nwrap(data))); | |
| 1216 } | |
| 1217 END | |
| 1218 } | |
| 1219 | |
| 1220 sub GenerateFeatureObservation | |
| 1221 { | |
| 1222 my $measureAs = shift; | |
| 1223 | |
| 1224 if ($measureAs) { | |
| 1225 AddToImplIncludes("core/page/UseCounter.h"); | |
| 1226 return " UseCounter::count(activeDOMWindow(), UseCounter::${measureAs
});\n"; | |
| 1227 } | |
| 1228 | |
| 1229 return ""; | |
| 1230 } | |
| 1231 | |
| 1232 sub GenerateDeprecationNotification | |
| 1233 { | |
| 1234 my $deprecateAs = shift; | |
| 1235 if ($deprecateAs) { | |
| 1236 AddToImplIncludes("core/page/PageConsole.h"); | |
| 1237 AddToImplIncludes("core/page/UseCounter.h"); | |
| 1238 return " UseCounter::countDeprecation(activeDOMWindow(), UseCounter::
${deprecateAs});\n"; | |
| 1239 } | |
| 1240 return ""; | |
| 1241 } | |
| 1242 | |
| 1243 sub GenerateActivityLogging | |
| 1244 { | |
| 1245 my $accessType = shift; | |
| 1246 my $interface = shift; | |
| 1247 my $propertyName = shift; | |
| 1248 | |
| 1249 my $interfaceName = $interface->name; | |
| 1250 | |
| 1251 AddToImplIncludes("bindings/v8/V8Binding.h"); | |
| 1252 AddToImplIncludes("bindings/v8/V8DOMActivityLogger.h"); | |
| 1253 AddToImplIncludes("wtf/Vector.h"); | |
| 1254 | |
| 1255 my $code = ""; | |
| 1256 if ($accessType eq "Method") { | |
| 1257 $code .= <<END; | |
| 1258 V8PerContextData* contextData = V8PerContextData::from(args.GetIsolate()->Ge
tCurrentContext()); | |
| 1259 if (contextData && contextData->activityLogger()) { | |
| 1260 Vector<v8::Handle<v8::Value> > loggerArgs = toVectorOfArguments(args); | |
| 1261 contextData->activityLogger()->log("${interfaceName}.${propertyName}", a
rgs.Length(), loggerArgs.data(), "${accessType}"); | |
| 1262 } | |
| 1263 END | |
| 1264 } elsif ($accessType eq "Setter") { | |
| 1265 $code .= <<END; | |
| 1266 V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->Ge
tCurrentContext()); | |
| 1267 if (contextData && contextData->activityLogger()) { | |
| 1268 v8::Handle<v8::Value> loggerArg[] = { value }; | |
| 1269 contextData->activityLogger()->log("${interfaceName}.${propertyName}", 1
, &loggerArg[0], "${accessType}"); | |
| 1270 } | |
| 1271 END | |
| 1272 } elsif ($accessType eq "Getter") { | |
| 1273 $code .= <<END; | |
| 1274 V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->Ge
tCurrentContext()); | |
| 1275 if (contextData && contextData->activityLogger()) | |
| 1276 contextData->activityLogger()->log("${interfaceName}.${propertyName}", 0
, 0, "${accessType}"); | |
| 1277 END | |
| 1278 } else { | |
| 1279 die "Unrecognized activity logging access type"; | |
| 1280 } | |
| 1281 | |
| 1282 return $code; | |
| 1283 } | |
| 1284 | |
| 1285 sub GenerateNormalAttrGetterCallback | |
| 1286 { | |
| 1287 my $attribute = shift; | |
| 1288 my $interface = shift; | |
| 1289 my $forMainWorldSuffix = shift; | |
| 1290 | |
| 1291 my $implClassName = GetImplName($interface); | |
| 1292 my $v8ClassName = GetV8ClassName($interface); | |
| 1293 my $attrExt = $attribute->extendedAttributes; | |
| 1294 my $attrName = $attribute->name; | |
| 1295 | |
| 1296 my $conditionalString = GenerateConditionalString($attribute); | |
| 1297 my $code = ""; | |
| 1298 $code .= "#if ${conditionalString}\n\n" if $conditionalString; | |
| 1299 | |
| 1300 $code .= "static void ${attrName}AttrGetterCallback${forMainWorldSuffix}(v8:
:Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; | |
| 1301 $code .= "{\n"; | |
| 1302 $code .= GenerateFeatureObservation($attrExt->{"MeasureAs"}); | |
| 1303 $code .= GenerateDeprecationNotification($attrExt->{"DeprecateAs"}); | |
| 1304 if (HasActivityLogging($forMainWorldSuffix, $attrExt, "Getter")) { | |
| 1305 $code .= GenerateActivityLogging("Getter", $interface, "${attrName}"); | |
| 1306 } | |
| 1307 if (HasCustomGetter($attrExt)) { | |
| 1308 $code .= " ${v8ClassName}::${attrName}AttrGetterCustom(name, info);\n
"; | |
| 1309 } else { | |
| 1310 $code .= " ${implClassName}V8Internal::${attrName}AttrGetter${forMain
WorldSuffix}(name, info);\n"; | |
| 1311 } | |
| 1312 $code .= "}\n\n"; | |
| 1313 $code .= "#endif // ${conditionalString}\n\n" if $conditionalString; | |
| 1314 | |
| 1315 $implementation{nameSpaceInternal}->add($code); | |
| 1316 } | |
| 1317 | |
| 1318 sub GenerateNormalAttrGetter | |
| 1319 { | |
| 1320 my $attribute = shift; | |
| 1321 my $interface = shift; | |
| 1322 my $forMainWorldSuffix = shift; | |
| 1323 | |
| 1324 my $interfaceName = $interface->name; | |
| 1325 my $implClassName = GetImplName($interface); | |
| 1326 my $v8ClassName = GetV8ClassName($interface); | |
| 1327 my $attrExt = $attribute->extendedAttributes; | |
| 1328 my $attrName = $attribute->name; | |
| 1329 my $attrType = $attribute->type; | |
| 1330 | |
| 1331 if (HasCustomGetter($attrExt)) { | |
| 1332 return; | |
| 1333 } | |
| 1334 | |
| 1335 AssertNotSequenceType($attrType); | |
| 1336 my $getterStringUsesImp = $interfaceName ne "SVGNumber"; | |
| 1337 my $nativeType = GetNativeType($attribute->type, $attribute->extendedAttribu
tes, ""); | |
| 1338 my $svgNativeType = GetSVGTypeNeedingTearOff($interfaceName); | |
| 1339 | |
| 1340 my $conditionalString = GenerateConditionalString($attribute); | |
| 1341 my $code = ""; | |
| 1342 $code .= "#if ${conditionalString}\n\n" if $conditionalString; | |
| 1343 $code .= <<END; | |
| 1344 static void ${attrName}AttrGetter${forMainWorldSuffix}(v8::Local<v8::String> nam
e, const v8::PropertyCallbackInfo<v8::Value>& info) | |
| 1345 { | |
| 1346 END | |
| 1347 if ($svgNativeType) { | |
| 1348 my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($interfaceNam
e); | |
| 1349 if ($svgWrappedNativeType =~ /List/) { | |
| 1350 $code .= <<END; | |
| 1351 $svgNativeType* imp = ${v8ClassName}::toNative(info.Holder()); | |
| 1352 END | |
| 1353 } else { | |
| 1354 $code .= <<END; | |
| 1355 $svgNativeType* wrapper = ${v8ClassName}::toNative(info.Holder()); | |
| 1356 $svgWrappedNativeType& impInstance = wrapper->propertyReference(); | |
| 1357 END | |
| 1358 if ($getterStringUsesImp) { | |
| 1359 $code .= <<END; | |
| 1360 $svgWrappedNativeType* imp = &impInstance; | |
| 1361 END | |
| 1362 } | |
| 1363 } | |
| 1364 } elsif ($attrExt->{"OnProto"} || $attrExt->{"Unforgeable"}) { | |
| 1365 if ($interfaceName eq "Window") { | |
| 1366 $code .= <<END; | |
| 1367 v8::Handle<v8::Object> holder = info.Holder(); | |
| 1368 END | |
| 1369 } else { | |
| 1370 # perform lookup first | |
| 1371 $code .= <<END; | |
| 1372 v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(${
v8ClassName}::GetTemplate(info.GetIsolate(), worldType(info.GetIsolate()))); | |
| 1373 if (holder.IsEmpty()) | |
| 1374 return; | |
| 1375 END | |
| 1376 } | |
| 1377 $code .= <<END; | |
| 1378 ${implClassName}* imp = ${v8ClassName}::toNative(holder); | |
| 1379 END | |
| 1380 } else { | |
| 1381 my $reflect = $attribute->extendedAttributes->{"Reflect"}; | |
| 1382 my $url = $attribute->extendedAttributes->{"URL"}; | |
| 1383 if ($getterStringUsesImp && $reflect && !$url && InheritsInterface($inte
rface, "Node") && $attrType eq "DOMString") { | |
| 1384 # Generate super-compact call for regular attribute getter: | |
| 1385 my ($functionName, @arguments) = GetterExpression($interfaceName, $a
ttribute); | |
| 1386 $code .= " Element* imp = V8Element::toNative(info.Holder());\n"; | |
| 1387 $code .= " v8SetReturnValue(info, v8String(imp->${functionName}("
. join(", ", @arguments) . "), info.GetIsolate(), ReturnUnsafeHandle));\n"; | |
| 1388 $code .= " return;\n"; | |
| 1389 $code .= "}\n\n"; | |
| 1390 $code .= "#endif // ${conditionalString}\n\n" if $conditionalString; | |
| 1391 $implementation{nameSpaceInternal}->add($code); | |
| 1392 return; | |
| 1393 # Skip the rest of the function! | |
| 1394 } | |
| 1395 if ($attribute->type eq "SerializedScriptValue" && $attrExt->{"CachedAtt
ribute"}) { | |
| 1396 $code .= <<END; | |
| 1397 v8::Handle<v8::String> propertyName = v8::String::NewSymbol("${attrName}"); | |
| 1398 v8::Handle<v8::Value> value = info.Holder()->GetHiddenValue(propertyName); | |
| 1399 if (!value.IsEmpty()) { | |
| 1400 v8SetReturnValue(info, value); | |
| 1401 return; | |
| 1402 } | |
| 1403 END | |
| 1404 } | |
| 1405 if (!$attribute->isStatic) { | |
| 1406 $code .= <<END; | |
| 1407 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()); | |
| 1408 END | |
| 1409 } | |
| 1410 } | |
| 1411 | |
| 1412 # Generate security checks if necessary | |
| 1413 if ($attribute->extendedAttributes->{"CheckSecurityForNode"}) { | |
| 1414 AddToImplIncludes("bindings/v8/BindingSecurity.h"); | |
| 1415 $code .= " if (!BindingSecurity::shouldAllowAccessToNode(imp->" . Get
ImplName($attribute) . "())) {\n"; | |
| 1416 $code .= " v8SetReturnValueNull(info);\n"; | |
| 1417 $code .= " return;\n"; | |
| 1418 $code .= " }\n"; | |
| 1419 } | |
| 1420 | |
| 1421 my $useExceptions = 1 if $attribute->extendedAttributes->{"GetterRaisesExcep
tion"} || $attribute->extendedAttributes->{"RaisesException"}; | |
| 1422 my $isNullable = $attribute->isNullable; | |
| 1423 if ($useExceptions) { | |
| 1424 AddToImplIncludes("core/dom/ExceptionCode.h"); | |
| 1425 $code .= " ExceptionCode ec = 0;\n"; | |
| 1426 } | |
| 1427 | |
| 1428 if ($isNullable) { | |
| 1429 $code .= " bool isNull = false;\n"; | |
| 1430 } | |
| 1431 | |
| 1432 my $returnType = $attribute->type; | |
| 1433 my $getterString; | |
| 1434 | |
| 1435 if ($getterStringUsesImp) { | |
| 1436 my ($functionName, @arguments) = GetterExpression($interfaceName, $attri
bute); | |
| 1437 push(@arguments, "isNull") if $isNullable; | |
| 1438 push(@arguments, "ec") if $useExceptions; | |
| 1439 if ($attribute->extendedAttributes->{"ImplementedBy"}) { | |
| 1440 my $implementedBy = $attribute->extendedAttributes->{"ImplementedBy"
}; | |
| 1441 my $implementedByImplName = GetImplNameFromImplementedBy($implemente
dBy); | |
| 1442 AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implement
edByImplName)); | |
| 1443 unshift(@arguments, "imp") if !$attribute->isStatic; | |
| 1444 $functionName = "${implementedByImplName}::${functionName}"; | |
| 1445 } elsif ($attribute->isStatic) { | |
| 1446 $functionName = "${implClassName}::${functionName}"; | |
| 1447 } else { | |
| 1448 $functionName = "imp->${functionName}"; | |
| 1449 } | |
| 1450 my ($arg, $subCode) = GenerateCallWith($attribute->extendedAttributes->{
"CallWith"}, " ", 0); | |
| 1451 $code .= $subCode; | |
| 1452 unshift(@arguments, @$arg); | |
| 1453 $getterString = "${functionName}(" . join(", ", @arguments) . ")"; | |
| 1454 } else { | |
| 1455 $getterString = "impInstance"; | |
| 1456 } | |
| 1457 | |
| 1458 my $expression; | |
| 1459 if ($attribute->type eq "EventListener" && $interface->name eq "Window") { | |
| 1460 $code .= " if (!imp->document())\n"; | |
| 1461 $code .= " return;\n"; | |
| 1462 } | |
| 1463 | |
| 1464 if ($useExceptions || $isNullable) { | |
| 1465 if ($nativeType =~ /^V8StringResource/) { | |
| 1466 $code .= " " . ConvertToV8StringResource($attribute, $nativeType,
"v", $getterString) . ";\n"; | |
| 1467 } else { | |
| 1468 $code .= " $nativeType v = $getterString;\n"; | |
| 1469 } | |
| 1470 | |
| 1471 if ($isNullable) { | |
| 1472 $code .= " if (isNull) {\n"; | |
| 1473 $code .= " v8SetReturnValueNull(info);\n"; | |
| 1474 $code .= " return;\n"; | |
| 1475 $code .= " }\n"; | |
| 1476 } | |
| 1477 | |
| 1478 if ($useExceptions) { | |
| 1479 $code .= " if (UNLIKELY(ec)) {\n"; | |
| 1480 $code .= " setDOMException(ec, info.GetIsolate());\n"; | |
| 1481 $code .= " return;\n"; | |
| 1482 $code .= " };\n"; | |
| 1483 | |
| 1484 if (ExtendedAttributeContains($attribute->extendedAttributes->{"Call
With"}, "ScriptState")) { | |
| 1485 $code .= " if (state.hadException()) {\n"; | |
| 1486 $code .= " throwError(state.exception(), info.GetIsolate(
));\n"; | |
| 1487 $code .= " return;\n"; | |
| 1488 $code .= " }\n"; | |
| 1489 } | |
| 1490 } | |
| 1491 | |
| 1492 $expression = "v"; | |
| 1493 $expression .= ".release()" if (IsRefPtrType($returnType)); | |
| 1494 } else { | |
| 1495 # Can inline the function call into the return statement to avoid overhe
ad of using a Ref<> temporary | |
| 1496 $expression = $getterString; | |
| 1497 # Fix amigious conversion problem, by casting to the base type first ($g
etterString returns a type that inherits from SVGAnimatedEnumeration, not the ba
se class directly). | |
| 1498 $expression = "static_pointer_cast<SVGAnimatedEnumeration>($expression)"
if $returnType eq "SVGAnimatedEnumeration"; | |
| 1499 } | |
| 1500 | |
| 1501 if (ShouldKeepAttributeAlive($interface, $attribute, $returnType)) { | |
| 1502 my $arrayType = GetArrayType($returnType); | |
| 1503 if ($arrayType) { | |
| 1504 AddIncludeForType("V8$arrayType.h"); | |
| 1505 $code .= " v8SetReturnValue(info, v8Array(${getterString}, info.G
etIsolate()));\n"; | |
| 1506 $code .= " return;\n"; | |
| 1507 $code .= "}\n\n"; | |
| 1508 $implementation{nameSpaceInternal}->add($code); | |
| 1509 return; | |
| 1510 } | |
| 1511 | |
| 1512 AddIncludesForType($returnType); | |
| 1513 AddToImplIncludes("bindings/v8/V8HiddenPropertyName.h"); | |
| 1514 # Check for a wrapper in the wrapper cache. If there is one, we know tha
t a hidden reference has already | |
| 1515 # been created. If we don't find a wrapper, we create both a wrapper and
a hidden reference. | |
| 1516 my $nativeReturnType = GetNativeType($returnType); | |
| 1517 $code .= " $nativeReturnType result = ${getterString};\n"; | |
| 1518 if ($forMainWorldSuffix) { | |
| 1519 $code .= " v8::Handle<v8::Value> wrapper = result.get() ? v8::Handl
e<v8::Value>(DOMDataStore::getWrapper${forMainWorldSuffix}(result.get())) : v8Un
defined();\n"; | |
| 1520 } else { | |
| 1521 $code .= " v8::Handle<v8::Value> wrapper = result.get() ? v8::Handl
e<v8::Value>(DOMDataStore::getWrapper(result.get(), info.GetIsolate())) : v8Unde
fined();\n"; | |
| 1522 } | |
| 1523 $code .= " if (wrapper.IsEmpty()) {\n"; | |
| 1524 $code .= " wrapper = toV8(result.get(), info.Holder(), info.GetIs
olate());\n"; # FIXME: Could use wrap here since the wrapper is empty. | |
| 1525 $code .= " if (!wrapper.IsEmpty())\n"; | |
| 1526 $code .= " V8HiddenPropertyName::setNamedHiddenReference(info
.Holder(), \"${attrName}\", wrapper);\n"; | |
| 1527 $code .= " }\n"; | |
| 1528 $code .= " v8SetReturnValue(info, wrapper);\n"; | |
| 1529 $code .= " return;\n"; | |
| 1530 $code .= "}\n\n"; | |
| 1531 $code .= "#endif // ${conditionalString}\n\n" if $conditionalString; | |
| 1532 $implementation{nameSpaceInternal}->add($code); | |
| 1533 return; | |
| 1534 } | |
| 1535 | |
| 1536 if ((IsSVGAnimatedType($interfaceName) or $interfaceName eq "SVGViewSpec") a
nd IsSVGTypeNeedingTearOff($attrType)) { | |
| 1537 AddToImplIncludes("V8$attrType.h"); | |
| 1538 my $svgNativeType = GetSVGTypeNeedingTearOff($attrType); | |
| 1539 # Convert from abstract SVGProperty to real type, so the right toJS() me
thod can be invoked. | |
| 1540 $code .= " v8SetReturnValue(info, toV8Fast$forMainWorldSuffix(static_
cast<$svgNativeType*>($expression), info, imp));\n"; | |
| 1541 $code .= " return;\n"; | |
| 1542 } elsif (IsSVGTypeNeedingTearOff($attrType) and not $interfaceName =~ /List$
/) { | |
| 1543 AddToImplIncludes("V8$attrType.h"); | |
| 1544 AddToImplIncludes("core/svg/properties/SVGPropertyTearOff.h"); | |
| 1545 my $tearOffType = GetSVGTypeNeedingTearOff($attrType); | |
| 1546 my $wrappedValue; | |
| 1547 if (IsSVGTypeWithWritablePropertiesNeedingTearOff($attrType) and not def
ined $attribute->extendedAttributes->{"Immutable"}) { | |
| 1548 my $getter = $expression; | |
| 1549 $getter =~ s/imp->//; | |
| 1550 $getter =~ s/\(\)//; | |
| 1551 | |
| 1552 my $updateMethod = "&${implClassName}::update" . FirstLetterToUpperC
ase($getter); | |
| 1553 | |
| 1554 my $selfIsTearOffType = IsSVGTypeNeedingTearOff($interfaceName); | |
| 1555 if ($selfIsTearOffType) { | |
| 1556 AddToImplIncludes("core/svg/properties/SVGStaticPropertyWithPare
ntTearOff.h"); | |
| 1557 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyWithParen
tTearOff<$implClassName, /; | |
| 1558 | |
| 1559 if ($expression =~ /matrix/ and $interfaceName eq "SVGTransform"
) { | |
| 1560 # SVGTransform offers a matrix() method for internal usage t
hat returns an AffineTransform | |
| 1561 # and a svgMatrix() method returning a SVGMatrix, used for t
he bindings. | |
| 1562 $expression =~ s/matrix/svgMatrix/; | |
| 1563 } | |
| 1564 | |
| 1565 $wrappedValue = "WTF::getPtr(${tearOffType}::create(wrapper, $ex
pression, $updateMethod))"; | |
| 1566 } else { | |
| 1567 AddToImplIncludes("core/svg/properties/SVGStaticPropertyTearOff.
h"); | |
| 1568 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyTearOff<$
implClassName, /; | |
| 1569 | |
| 1570 $wrappedValue = "WTF::getPtr(${tearOffType}::create(imp, $expres
sion, $updateMethod))"; | |
| 1571 } | |
| 1572 } elsif ($tearOffType =~ /SVGStaticListPropertyTearOff/) { | |
| 1573 $wrappedValue = "WTF::getPtr(${tearOffType}::create(imp, $expres
sion))"; | |
| 1574 } elsif ($tearOffType =~ /SVG(Point|PathSeg)List/) { | |
| 1575 $wrappedValue = "WTF::getPtr($expression)"; | |
| 1576 } else { | |
| 1577 $wrappedValue = "WTF::getPtr(${tearOffType}::create($expression)
)"; | |
| 1578 } | |
| 1579 $code .= " v8SetReturnValue(info, toV8Fast$forMainWorldSuffix($wrappe
dValue, info, imp));\n"; | |
| 1580 $code .= " return;\n"; | |
| 1581 } elsif ($attribute->type eq "SerializedScriptValue" && $attrExt->{"CachedAt
tribute"}) { | |
| 1582 my $getterFunc = ToMethodName($attribute->name); | |
| 1583 $code .= <<END; | |
| 1584 RefPtr<SerializedScriptValue> serialized = imp->${getterFunc}(); | |
| 1585 value = serialized ? serialized->deserialize() : v8::Handle<v8::Value>(v8::N
ull(info.GetIsolate())); | |
| 1586 info.Holder()->SetHiddenValue(propertyName, value); | |
| 1587 v8SetReturnValue(info, value); | |
| 1588 return; | |
| 1589 END | |
| 1590 } elsif ($attribute->type eq "EventListener") { | |
| 1591 AddToImplIncludes("bindings/v8/V8AbstractEventListener.h"); | |
| 1592 my $getterFunc = ToMethodName($attribute->name); | |
| 1593 # FIXME: Pass the main world ID for main-world-only getters. | |
| 1594 $code .= " EventListener* listener = imp->${getterFunc}(isolatedWorld
ForIsolate(info.GetIsolate()));\n"; | |
| 1595 $code .= " v8SetReturnValue(info, listener ? v8::Handle<v8::Value>(V8
AbstractEventListener::cast(listener)->getListenerObject(imp->scriptExecutionCon
text())) : v8::Handle<v8::Value>(v8::Null(info.GetIsolate())));\n"; | |
| 1596 $code .= " return;\n"; | |
| 1597 } else { | |
| 1598 my $nativeValue = NativeToJSValue($attribute->type, $attribute->extended
Attributes, $expression, " ", "", "info.Holder()", "info.GetIsolate()", "info
", "imp", "ReturnUnsafeHandle", $forMainWorldSuffix, "return"); | |
| 1599 $code .= "${nativeValue}\n"; | |
| 1600 $code .= " return;\n"; | |
| 1601 } | |
| 1602 | |
| 1603 $code .= "}\n\n"; # end of getter | |
| 1604 $code .= "#endif // ${conditionalString}\n\n" if $conditionalString; | |
| 1605 $implementation{nameSpaceInternal}->add($code); | |
| 1606 } | |
| 1607 | |
| 1608 sub ShouldKeepAttributeAlive | |
| 1609 { | |
| 1610 my ($interface, $attribute, $returnType) = @_; | |
| 1611 my $attrName = $attribute->name; | |
| 1612 | |
| 1613 return 1 if $attribute->extendedAttributes->{"KeepAttributeAliveForGC"}; | |
| 1614 | |
| 1615 # Basically, for readonly or replaceable attributes, we have to guarantee | |
| 1616 # that JS wrappers don't get garbage-collected prematually when their | |
| 1617 # lifetime is strongly tied to their owner. | |
| 1618 return 0 if !IsWrapperType($returnType); | |
| 1619 return 0 if !IsReadonly($attribute) && !$attribute->extendedAttributes->{"Re
placeable"}; | |
| 1620 | |
| 1621 # However, there are a couple of exceptions. | |
| 1622 | |
| 1623 # Node lifetime is managed by object grouping. | |
| 1624 return 0 if InheritsInterface($interface, "Node"); | |
| 1625 return 0 if IsDOMNodeType($returnType); | |
| 1626 | |
| 1627 # To avoid adding a reference to itself. | |
| 1628 # FIXME: Introduce [DoNotKeepAttributeAliveForGC] and remove this hack | |
| 1629 # depending on the attribute name. | |
| 1630 return 0 if $attrName eq "self"; | |
| 1631 | |
| 1632 # FIXME: Remove these hard-coded hacks. | |
| 1633 return 0 if $returnType eq "EventTarget"; | |
| 1634 return 0 if $returnType eq "SerializedScriptValue"; | |
| 1635 return 0 if $returnType eq "Window"; | |
| 1636 return 0 if $returnType =~ /SVG/; | |
| 1637 return 0 if $returnType =~ /HTML/; | |
| 1638 | |
| 1639 return 1; | |
| 1640 } | |
| 1641 | |
| 1642 sub GenerateReplaceableAttrSetterCallback | |
| 1643 { | |
| 1644 my $interface = shift; | |
| 1645 my $implClassName = GetImplName($interface); | |
| 1646 | |
| 1647 my $code = ""; | |
| 1648 $code .= "static void ${implClassName}ReplaceableAttrSetterCallback(v8::Loca
l<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v
oid>& info)\n"; | |
| 1649 $code .= "{\n"; | |
| 1650 $code .= GenerateFeatureObservation($interface->extendedAttributes->{"Measur
eAs"}); | |
| 1651 $code .= GenerateDeprecationNotification($interface->extendedAttributes->{"D
eprecateAs"}); | |
| 1652 $code .= GenerateCustomElementInvocationScopeIfNeeded($interface->extendedAt
tributes); | |
| 1653 if (HasActivityLogging("", $interface->extendedAttributes, "Setter")) { | |
| 1654 die "IDL error: ActivityLog attribute cannot exist on a ReplacableAttrS
etterCallback"; | |
| 1655 } | |
| 1656 $code .= " ${implClassName}V8Internal::${implClassName}ReplaceableAttrSet
ter(name, value, info);\n"; | |
| 1657 $code .= "}\n\n"; | |
| 1658 $implementation{nameSpaceInternal}->add($code); | |
| 1659 } | |
| 1660 | |
| 1661 sub GenerateReplaceableAttrSetter | |
| 1662 { | |
| 1663 my $interface = shift; | |
| 1664 | |
| 1665 my $implClassName = GetImplName($interface); | |
| 1666 my $v8ClassName = GetV8ClassName($interface); | |
| 1667 | |
| 1668 my $code = ""; | |
| 1669 $code .= <<END; | |
| 1670 static void ${implClassName}ReplaceableAttrSetter(v8::Local<v8::String> name, v8
::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) | |
| 1671 { | |
| 1672 END | |
| 1673 if ($interface->extendedAttributes->{"CheckSecurity"}) { | |
| 1674 AddToImplIncludes("core/page/Frame.h"); | |
| 1675 AddToImplIncludes("bindings/v8/BindingSecurity.h"); | |
| 1676 $code .= <<END; | |
| 1677 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()); | |
| 1678 if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame())) | |
| 1679 return; | |
| 1680 END | |
| 1681 } | |
| 1682 | |
| 1683 $code .= <<END; | |
| 1684 info.This()->ForceSet(name, value); | |
| 1685 } | |
| 1686 | |
| 1687 END | |
| 1688 $implementation{nameSpaceInternal}->add($code); | |
| 1689 } | |
| 1690 | |
| 1691 sub GenerateCustomElementInvocationScopeIfNeeded | |
| 1692 { | |
| 1693 my $code = ""; | |
| 1694 my $ext = shift; | |
| 1695 | |
| 1696 if ($ext->{"DeliverCustomElementCallbacks"} or $ext->{"Reflect"}) { | |
| 1697 AddToImplIncludes("core/dom/CustomElementCallbackDispatcher.h"); | |
| 1698 $code .= <<END; | |
| 1699 CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope; | |
| 1700 END | |
| 1701 } | |
| 1702 return $code; | |
| 1703 } | |
| 1704 | |
| 1705 sub GenerateNormalAttrSetterCallback | |
| 1706 { | |
| 1707 my $attribute = shift; | |
| 1708 my $interface = shift; | |
| 1709 my $forMainWorldSuffix = shift; | |
| 1710 | |
| 1711 my $implClassName = GetImplName($interface); | |
| 1712 my $v8ClassName = GetV8ClassName($interface); | |
| 1713 my $attrExt = $attribute->extendedAttributes; | |
| 1714 my $attrName = $attribute->name; | |
| 1715 | |
| 1716 my $conditionalString = GenerateConditionalString($attribute); | |
| 1717 my $code = ""; | |
| 1718 $code .= "#if ${conditionalString}\n\n" if $conditionalString; | |
| 1719 | |
| 1720 $code .= "static void ${attrName}AttrSetterCallback${forMainWorldSuffix}(v8:
:Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackI
nfo<void>& info)\n"; | |
| 1721 $code .= "{\n"; | |
| 1722 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMMethod\");\n"; | |
| 1723 $code .= GenerateFeatureObservation($attrExt->{"MeasureAs"}); | |
| 1724 $code .= GenerateDeprecationNotification($attrExt->{"DeprecateAs"}); | |
| 1725 if (HasActivityLogging($forMainWorldSuffix, $attrExt, "Setter")) { | |
| 1726 $code .= GenerateActivityLogging("Setter", $interface, "${attrName}"); | |
| 1727 } | |
| 1728 $code .= GenerateCustomElementInvocationScopeIfNeeded($attrExt); | |
| 1729 if (HasCustomSetter($attrExt)) { | |
| 1730 $code .= " ${v8ClassName}::${attrName}AttrSetterCustom(name, value, i
nfo);\n"; | |
| 1731 } else { | |
| 1732 $code .= " ${implClassName}V8Internal::${attrName}AttrSetter${forMain
WorldSuffix}(name, value, info);\n"; | |
| 1733 } | |
| 1734 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; | |
| 1735 $code .= "}\n\n"; | |
| 1736 $code .= "#endif // ${conditionalString}\n\n" if $conditionalString; | |
| 1737 $implementation{nameSpaceInternal}->add($code); | |
| 1738 } | |
| 1739 | |
| 1740 sub GenerateNormalAttrSetter | |
| 1741 { | |
| 1742 my $attribute = shift; | |
| 1743 my $interface = shift; | |
| 1744 my $forMainWorldSuffix = shift; | |
| 1745 | |
| 1746 my $interfaceName = $interface->name; | |
| 1747 my $implClassName = GetImplName($interface); | |
| 1748 my $v8ClassName = GetV8ClassName($interface); | |
| 1749 my $attrName = $attribute->name; | |
| 1750 my $attrExt = $attribute->extendedAttributes; | |
| 1751 my $attrType = $attribute->type; | |
| 1752 | |
| 1753 if (HasCustomSetter($attrExt)) { | |
| 1754 return; | |
| 1755 } | |
| 1756 | |
| 1757 my $conditionalString = GenerateConditionalString($attribute); | |
| 1758 my $code = ""; | |
| 1759 $code .= "#if ${conditionalString}\n\n" if $conditionalString; | |
| 1760 $code .= "static void ${attrName}AttrSetter${forMainWorldSuffix}(v8::Local<v
8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void
>& info)\n"; | |
| 1761 $code .= "{\n"; | |
| 1762 | |
| 1763 # If the "StrictTypeChecking" extended attribute is present, and the attribu
te's type is an | |
| 1764 # interface type, then if the incoming value does not implement that interfa
ce, a TypeError is | |
| 1765 # thrown rather than silently passing NULL to the C++ code. | |
| 1766 # Per the Web IDL and ECMAScript specifications, incoming values can always
be converted to both | |
| 1767 # strings and numbers, so do not throw TypeError if the attribute is of thes
e types. | |
| 1768 if ($attribute->extendedAttributes->{"StrictTypeChecking"}) { | |
| 1769 my $argType = $attribute->type; | |
| 1770 if (IsWrapperType($argType)) { | |
| 1771 $code .= " if (!isUndefinedOrNull(value) && !V8${argType}::HasIns
tance(value, info.GetIsolate(), worldType(info.GetIsolate()))) {\n"; | |
| 1772 $code .= " throwTypeError(0, info.GetIsolate());\n"; | |
| 1773 $code .= " return;\n"; | |
| 1774 $code .= " }\n"; | |
| 1775 } | |
| 1776 } | |
| 1777 | |
| 1778 my $svgNativeType = GetSVGTypeNeedingTearOff($interfaceName); | |
| 1779 if ($svgNativeType) { | |
| 1780 my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($interfaceNam
e); | |
| 1781 if ($svgWrappedNativeType =~ /List$/) { | |
| 1782 $code .= <<END; | |
| 1783 $svgNativeType* imp = ${v8ClassName}::toNative(info.Holder()); | |
| 1784 END | |
| 1785 } else { | |
| 1786 AddToImplIncludes("core/dom/ExceptionCode.h"); | |
| 1787 $code .= " $svgNativeType* wrapper = ${v8ClassName}::toNative(inf
o.Holder());\n"; | |
| 1788 $code .= " if (wrapper->isReadOnly()) {\n"; | |
| 1789 $code .= " setDOMException(NoModificationAllowedError, info.G
etIsolate());\n"; | |
| 1790 $code .= " return;\n"; | |
| 1791 $code .= " }\n"; | |
| 1792 $code .= " $svgWrappedNativeType& impInstance = wrapper->property
Reference();\n"; | |
| 1793 $code .= " $svgWrappedNativeType* imp = &impInstance;\n"; | |
| 1794 } | |
| 1795 } elsif ($attrExt->{"OnProto"}) { | |
| 1796 $code .= <<END; | |
| 1797 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()); | |
| 1798 END | |
| 1799 } else { | |
| 1800 my $reflect = $attribute->extendedAttributes->{"Reflect"}; | |
| 1801 if ($reflect && InheritsInterface($interface, "Node") && $attrType eq "D
OMString") { | |
| 1802 # Generate super-compact call for regular attribute setter: | |
| 1803 my $contentAttributeName = $reflect eq "VALUE_IS_MISSING" ? lc $attr
Name : $reflect; | |
| 1804 my $namespace = NamespaceForAttributeName($interfaceName, $contentAt
tributeName); | |
| 1805 AddToImplIncludes("${namespace}.h"); | |
| 1806 $code .= " Element* imp = V8Element::toNative(info.Holder());\n"; | |
| 1807 $code .= " V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<
WithNullCheck>, stringResource, value);\n"; | |
| 1808 $code .= " imp->setAttribute(${namespace}::${contentAttributeName
}Attr, stringResource);\n"; | |
| 1809 $code .= "}\n\n"; | |
| 1810 $code .= "#endif // ${conditionalString}\n\n" if $conditionalString; | |
| 1811 $implementation{nameSpaceInternal}->add($code); | |
| 1812 return; | |
| 1813 # Skip the rest of the function! | |
| 1814 } | |
| 1815 | |
| 1816 if (!$attribute->isStatic) { | |
| 1817 $code .= <<END; | |
| 1818 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()); | |
| 1819 END | |
| 1820 } | |
| 1821 } | |
| 1822 | |
| 1823 my $nativeType = GetNativeType($attribute->type, $attribute->extendedAttribu
tes, "parameter"); | |
| 1824 if ($attribute->type eq "EventListener") { | |
| 1825 if ($interface->name eq "Window") { | |
| 1826 $code .= " if (!imp->document())\n"; | |
| 1827 $code .= " return;\n"; | |
| 1828 } | |
| 1829 } else { | |
| 1830 $code .= JSValueToNativeStatement($attribute->type, $attribute->extended
Attributes, "value", "v", " ", "info.GetIsolate()"); | |
| 1831 } | |
| 1832 | |
| 1833 if (IsEnumType($attrType)) { | |
| 1834 # setter ignores invalid enumeration values | |
| 1835 my @enumValues = ValidEnumValues($attrType); | |
| 1836 my @validEqualities = (); | |
| 1837 foreach my $enumValue (@enumValues) { | |
| 1838 push(@validEqualities, "string == \"$enumValue\""); | |
| 1839 } | |
| 1840 my $enumValidationExpression = join(" || ", @validEqualities); | |
| 1841 $code .= <<END; | |
| 1842 String string = v; | |
| 1843 if (!($enumValidationExpression)) | |
| 1844 return; | |
| 1845 END | |
| 1846 } | |
| 1847 | |
| 1848 my $expression = "v"; | |
| 1849 my $returnType = $attribute->type; | |
| 1850 if (IsRefPtrType($returnType) && !GetArrayType($returnType)) { | |
| 1851 $expression = "WTF::getPtr(" . $expression . ")"; | |
| 1852 } | |
| 1853 | |
| 1854 $code .= GenerateCustomElementInvocationScopeIfNeeded($attribute->extendedAt
tributes); | |
| 1855 | |
| 1856 my $useExceptions = 1 if $attribute->extendedAttributes->{"SetterRaisesExcep
tion"} || $attribute->extendedAttributes->{"RaisesException"}; | |
| 1857 | |
| 1858 if ($useExceptions) { | |
| 1859 AddToImplIncludes("core/dom/ExceptionCode.h"); | |
| 1860 $code .= " ExceptionCode ec = 0;\n"; | |
| 1861 } | |
| 1862 | |
| 1863 if ($interfaceName eq "SVGNumber") { | |
| 1864 $code .= " *imp = $expression;\n"; | |
| 1865 } else { | |
| 1866 if ($attribute->type eq "EventListener") { | |
| 1867 my $implSetterFunctionName = FirstLetterToUpperCase($attrName); | |
| 1868 AddToImplIncludes("bindings/v8/V8AbstractEventListener.h"); | |
| 1869 if (!InheritsInterface($interface, "Node")) { | |
| 1870 my $attrImplName = GetImplName($attribute); | |
| 1871 $code .= " transferHiddenDependency(info.Holder(), imp->${att
rImplName}(isolatedWorldForIsolate(info.GetIsolate())), value, ${v8ClassName}::e
ventListenerCacheIndex, info.GetIsolate());\n"; | |
| 1872 } | |
| 1873 AddToImplIncludes("bindings/v8/V8EventListenerList.h"); | |
| 1874 if (($interfaceName eq "Window" or $interfaceName eq "WorkerGlobalSc
ope") and $attribute->name eq "onerror") { | |
| 1875 AddToImplIncludes("bindings/v8/V8ErrorHandler.h"); | |
| 1876 $code .= " imp->set$implSetterFunctionName(V8EventListenerLis
t::findOrCreateWrapper<V8ErrorHandler>(value, true), isolatedWorldForIsolate(inf
o.GetIsolate()));\n"; | |
| 1877 } else { | |
| 1878 $code .= " imp->set$implSetterFunctionName(V8EventListenerLis
t::getEventListener(value, true, ListenerFindOrCreate), isolatedWorldForIsolate(
info.GetIsolate()));\n"; | |
| 1879 } | |
| 1880 } else { | |
| 1881 my ($functionName, @arguments) = SetterExpression($interfaceName, $a
ttribute); | |
| 1882 push(@arguments, $expression); | |
| 1883 push(@arguments, "ec") if $useExceptions; | |
| 1884 if ($attribute->extendedAttributes->{"ImplementedBy"}) { | |
| 1885 my $implementedBy = $attribute->extendedAttributes->{"Implemente
dBy"}; | |
| 1886 my $implementedByImplName = GetImplNameFromImplementedBy($implem
entedBy); | |
| 1887 AddToImplIncludes(HeaderFilesForInterface($implementedBy, $imple
mentedByImplName)); | |
| 1888 unshift(@arguments, "imp") if !$attribute->isStatic; | |
| 1889 $functionName = "${implementedByImplName}::${functionName}"; | |
| 1890 } elsif ($attribute->isStatic) { | |
| 1891 $functionName = "${implClassName}::${functionName}"; | |
| 1892 } else { | |
| 1893 $functionName = "imp->${functionName}"; | |
| 1894 } | |
| 1895 my ($arg, $subCode) = GenerateCallWith($attribute->extendedAttribute
s->{"SetterCallWith"} || $attribute->extendedAttributes->{"CallWith"}, " ", 1
); | |
| 1896 $code .= $subCode; | |
| 1897 unshift(@arguments, @$arg); | |
| 1898 $code .= " ${functionName}(" . join(", ", @arguments) . ");\n"; | |
| 1899 } | |
| 1900 } | |
| 1901 | |
| 1902 if ($useExceptions) { | |
| 1903 $code .= " if (UNLIKELY(ec))\n"; | |
| 1904 $code .= " setDOMException(ec, info.GetIsolate());\n"; | |
| 1905 } | |
| 1906 | |
| 1907 if (ExtendedAttributeContains($attribute->extendedAttributes->{"CallWith"},
"ScriptState")) { | |
| 1908 $code .= " if (state.hadException())\n"; | |
| 1909 $code .= " throwError(state.exception(), info.GetIsolate());\n"; | |
| 1910 } | |
| 1911 | |
| 1912 if ($svgNativeType) { | |
| 1913 if ($useExceptions) { | |
| 1914 $code .= " if (!ec)\n"; | |
| 1915 $code .= " wrapper->commitChange();\n"; | |
| 1916 } else { | |
| 1917 $code .= " wrapper->commitChange();\n"; | |
| 1918 } | |
| 1919 } | |
| 1920 | |
| 1921 if ($attribute->type eq "SerializedScriptValue" && $attribute->extendedAttri
butes->{"CachedAttribute"}) { | |
| 1922 $code .= <<END; | |
| 1923 info.Holder()->DeleteHiddenValue(v8::String::NewSymbol("${attrName}")); // I
nvalidate the cached value. | |
| 1924 END | |
| 1925 } | |
| 1926 | |
| 1927 $code .= " return;\n"; | |
| 1928 $code .= "}\n\n"; # end of setter | |
| 1929 $code .= "#endif // ${conditionalString}\n\n" if $conditionalString; | |
| 1930 $implementation{nameSpaceInternal}->add($code); | |
| 1931 } | |
| 1932 | |
| 1933 sub GenerateParametersCheckExpression | |
| 1934 { | |
| 1935 my $numParameters = shift; | |
| 1936 my $function = shift; | |
| 1937 | |
| 1938 my @andExpression = (); | |
| 1939 push(@andExpression, "args.Length() == $numParameters"); | |
| 1940 my $parameterIndex = 0; | |
| 1941 foreach my $parameter (@{$function->parameters}) { | |
| 1942 last if $parameterIndex >= $numParameters; | |
| 1943 my $value = "args[$parameterIndex]"; | |
| 1944 my $type = $parameter->type; | |
| 1945 | |
| 1946 # Only DOMString or wrapper types are checked. | |
| 1947 # For DOMString with StrictTypeChecking only Null, Undefined and Object | |
| 1948 # are accepted for compatibility. Otherwise, no restrictions are made to | |
| 1949 # match the non-overloaded behavior. | |
| 1950 # FIXME: Implement WebIDL overload resolution algorithm. | |
| 1951 if ($type eq "DOMString") { | |
| 1952 if ($parameter->extendedAttributes->{"StrictTypeChecking"}) { | |
| 1953 push(@andExpression, "(${value}->IsNull() || ${value}->IsUndefin
ed() || ${value}->IsString() || ${value}->IsObject())"); | |
| 1954 } | |
| 1955 } elsif (IsCallbackInterface($parameter->type)) { | |
| 1956 # For Callbacks only checks if the value is null or object. | |
| 1957 push(@andExpression, "(${value}->IsNull() || ${value}->IsFunction())
"); | |
| 1958 } elsif (GetArrayOrSequenceType($type)) { | |
| 1959 if ($parameter->isNullable) { | |
| 1960 push(@andExpression, "(${value}->IsNull() || ${value}->IsArray()
)"); | |
| 1961 } else { | |
| 1962 push(@andExpression, "(${value}->IsArray())"); | |
| 1963 } | |
| 1964 } elsif (IsWrapperType($type)) { | |
| 1965 if ($parameter->isNullable) { | |
| 1966 push(@andExpression, "(${value}->IsNull() || V8${type}::HasInsta
nce($value, args.GetIsolate(), worldType(args.GetIsolate())))"); | |
| 1967 } else { | |
| 1968 push(@andExpression, "(V8${type}::HasInstance($value, args.GetIs
olate(), worldType(args.GetIsolate())))"); | |
| 1969 } | |
| 1970 } | |
| 1971 | |
| 1972 $parameterIndex++; | |
| 1973 } | |
| 1974 my $res = join(" && ", @andExpression); | |
| 1975 $res = "($res)" if @andExpression > 1; | |
| 1976 return $res; | |
| 1977 } | |
| 1978 | |
| 1979 # As per Web IDL specification, the length of a function Object is | |
| 1980 # its number of mandatory parameters. | |
| 1981 sub GetFunctionLength | |
| 1982 { | |
| 1983 my $function = shift; | |
| 1984 | |
| 1985 my $numMandatoryParams = 0; | |
| 1986 foreach my $parameter (@{$function->parameters}) { | |
| 1987 # Abort as soon as we find the first optional parameter as no mandatory | |
| 1988 # parameter can follow an optional one. | |
| 1989 last if $parameter->isOptional; | |
| 1990 $numMandatoryParams++; | |
| 1991 } | |
| 1992 return $numMandatoryParams; | |
| 1993 } | |
| 1994 | |
| 1995 sub GenerateFunctionParametersCheck | |
| 1996 { | |
| 1997 my $function = shift; | |
| 1998 | |
| 1999 my @orExpression = (); | |
| 2000 my $numParameters = 0; | |
| 2001 my $hasVariadic = 0; | |
| 2002 my $numMandatoryParams = @{$function->parameters}; | |
| 2003 foreach my $parameter (@{$function->parameters}) { | |
| 2004 if ($parameter->isOptional) { | |
| 2005 push(@orExpression, GenerateParametersCheckExpression($numParameters
, $function)); | |
| 2006 $numMandatoryParams--; | |
| 2007 } | |
| 2008 if ($parameter->isVariadic) { | |
| 2009 $hasVariadic = 1; | |
| 2010 last; | |
| 2011 } | |
| 2012 $numParameters++; | |
| 2013 } | |
| 2014 if (!$hasVariadic) { | |
| 2015 push(@orExpression, GenerateParametersCheckExpression($numParameters, $f
unction)); | |
| 2016 } | |
| 2017 return ($numMandatoryParams, join(" || ", @orExpression)); | |
| 2018 } | |
| 2019 | |
| 2020 sub GenerateOverloadedFunction | |
| 2021 { | |
| 2022 my $function = shift; | |
| 2023 my $interface = shift; | |
| 2024 my $forMainWorldSuffix = shift; | |
| 2025 | |
| 2026 # Generate code for choosing the correct overload to call. Overloads are | |
| 2027 # chosen based on the total number of arguments passed and the type of | |
| 2028 # values passed in non-primitive argument slots. When more than a single | |
| 2029 # overload is applicable, precedence is given according to the order of | |
| 2030 # declaration in the IDL. | |
| 2031 | |
| 2032 my $name = $function->name; | |
| 2033 | |
| 2034 my $conditionalString = GenerateConditionalString($function); | |
| 2035 my $leastNumMandatoryParams = 255; | |
| 2036 my $code = ""; | |
| 2037 $code .= "#if ${conditionalString}\n\n" if $conditionalString; | |
| 2038 $code .= <<END; | |
| 2039 static void ${name}Method${forMainWorldSuffix}(const v8::FunctionCallbackInfo<v8
::Value>& args) | |
| 2040 { | |
| 2041 END | |
| 2042 $code .= GenerateFeatureObservation($function->extendedAttributes->{"Measure
As"}); | |
| 2043 $code .= GenerateDeprecationNotification($function->extendedAttributes->{"De
precateAs"}); | |
| 2044 | |
| 2045 foreach my $overload (@{$function->{overloads}}) { | |
| 2046 my ($numMandatoryParams, $parametersCheck) = GenerateFunctionParametersC
heck($overload); | |
| 2047 $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams <
$leastNumMandatoryParams); | |
| 2048 $code .= " if ($parametersCheck) {\n"; | |
| 2049 my $overloadedIndexString = $overload->{overloadIndex}; | |
| 2050 $code .= " ${name}${overloadedIndexString}Method${forMainWorldSuf
fix}(args);\n"; | |
| 2051 $code .= " return;\n"; | |
| 2052 $code .= " }\n"; | |
| 2053 } | |
| 2054 if ($leastNumMandatoryParams >= 1) { | |
| 2055 $code .= " if (args.Length() < $leastNumMandatoryParams) {\n"; | |
| 2056 $code .= " throwNotEnoughArgumentsError(args.GetIsolate());\n"; | |
| 2057 $code .= " return;\n"; | |
| 2058 $code .= " }\n"; | |
| 2059 } | |
| 2060 $code .= <<END; | |
| 2061 throwTypeError(0, args.GetIsolate()); | |
| 2062 END | |
| 2063 $code .= "}\n\n"; | |
| 2064 $code .= "#endif // ${conditionalString}\n\n" if $conditionalString; | |
| 2065 $implementation{nameSpaceInternal}->add($code); | |
| 2066 } | |
| 2067 | |
| 2068 sub GenerateFunctionCallback | |
| 2069 { | |
| 2070 my $function = shift; | |
| 2071 my $interface = shift; | |
| 2072 my $forMainWorldSuffix = shift; | |
| 2073 | |
| 2074 my $implClassName = GetImplName($interface); | |
| 2075 my $v8ClassName = GetV8ClassName($interface); | |
| 2076 my $name = $function->name; | |
| 2077 | |
| 2078 if ($name eq "") { | |
| 2079 return; | |
| 2080 } | |
| 2081 | |
| 2082 my $conditionalString = GenerateConditionalString($function); | |
| 2083 my $code = ""; | |
| 2084 $code .= "#if ${conditionalString}\n\n" if $conditionalString; | |
| 2085 $code .= <<END; | |
| 2086 static void ${name}MethodCallback${forMainWorldSuffix}(const v8::FunctionCallbac
kInfo<v8::Value>& args) | |
| 2087 { | |
| 2088 END | |
| 2089 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMMethod\");\n"; | |
| 2090 $code .= GenerateFeatureObservation($function->extendedAttributes->{"Measure
As"}); | |
| 2091 $code .= GenerateDeprecationNotification($function->extendedAttributes->{"De
precateAs"}); | |
| 2092 if (HasActivityLogging($forMainWorldSuffix, $function->extendedAttributes, "
Access")) { | |
| 2093 $code .= GenerateActivityLogging("Method", $interface, "${name}"); | |
| 2094 } | |
| 2095 if (HasCustomMethod($function->extendedAttributes)) { | |
| 2096 $code .= " ${v8ClassName}::${name}MethodCustom(args);\n"; | |
| 2097 } else { | |
| 2098 $code .= " ${implClassName}V8Internal::${name}Method${forMainWorldSuf
fix}(args);\n"; | |
| 2099 } | |
| 2100 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; | |
| 2101 $code .= "}\n\n"; | |
| 2102 $code .= "#endif // ${conditionalString}\n\n" if $conditionalString; | |
| 2103 $implementation{nameSpaceInternal}->add($code); | |
| 2104 } | |
| 2105 | |
| 2106 sub GenerateFunction | |
| 2107 { | |
| 2108 my $function = shift; | |
| 2109 my $interface = shift; | |
| 2110 my $forMainWorldSuffix = shift; | |
| 2111 | |
| 2112 my $interfaceName = $interface->name; | |
| 2113 my $implClassName = GetImplName($interface); | |
| 2114 my $v8ClassName = GetV8ClassName($interface); | |
| 2115 my $name = $function->name; | |
| 2116 my $implName = GetImplName($function); | |
| 2117 my $funcExt = $function->extendedAttributes; | |
| 2118 | |
| 2119 if (HasCustomMethod($funcExt) || $name eq "") { | |
| 2120 return; | |
| 2121 } | |
| 2122 | |
| 2123 if (@{$function->{overloads}} > 1) { | |
| 2124 # Append a number to an overloaded method's name to make it unique: | |
| 2125 $name = $name . $function->{overloadIndex}; | |
| 2126 } | |
| 2127 | |
| 2128 my $conditionalString = GenerateConditionalString($function); | |
| 2129 my $code = ""; | |
| 2130 $code .= "#if ${conditionalString}\n\n" if $conditionalString; | |
| 2131 $code .= "static void ${name}Method${forMainWorldSuffix}(const v8::FunctionC
allbackInfo<v8::Value>& args)\n"; | |
| 2132 $code .= "{\n"; | |
| 2133 | |
| 2134 if ($name eq "addEventListener" || $name eq "removeEventListener") { | |
| 2135 my $lookupType = ($name eq "addEventListener") ? "OrCreate" : "Only"; | |
| 2136 my $passRefPtrHandling = ($name eq "addEventListener") ? "" : ".get()"; | |
| 2137 my $hiddenDependencyAction = ($name eq "addEventListener") ? "create" :
"remove"; | |
| 2138 | |
| 2139 AddToImplIncludes("bindings/v8/V8EventListenerList.h"); | |
| 2140 $code .= <<END; | |
| 2141 RefPtr<EventListener> listener = V8EventListenerList::getEventListener(args[
1], false, ListenerFind${lookupType}); | |
| 2142 if (listener) { | |
| 2143 V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, st
ringResource, args[0]); | |
| 2144 ${v8ClassName}::toNative(args.Holder())->${implName}(stringResource, lis
tener${passRefPtrHandling}, args[2]->BooleanValue()); | |
| 2145 END | |
| 2146 if (!InheritsInterface($interface, "Node")) { | |
| 2147 $code .= <<END; | |
| 2148 ${hiddenDependencyAction}HiddenDependency(args.Holder(), args[1], ${v8Cl
assName}::eventListenerCacheIndex, args.GetIsolate()); | |
| 2149 END | |
| 2150 } | |
| 2151 $code .= <<END; | |
| 2152 } | |
| 2153 } | |
| 2154 | |
| 2155 END | |
| 2156 $code .= "#endif // ${conditionalString}\n\n" if $conditionalString; | |
| 2157 $implementation{nameSpaceInternal}->add($code); | |
| 2158 return; | |
| 2159 } | |
| 2160 | |
| 2161 $code .= GenerateArgumentsCountCheck($function, $interface); | |
| 2162 | |
| 2163 if ($name eq "set" and IsConstructorTemplate($interface, "TypedArray")) { | |
| 2164 AddToImplIncludes("bindings/v8/custom/V8ArrayBufferViewCustom.h"); | |
| 2165 $code .= <<END; | |
| 2166 setWebGLArrayHelper<$implClassName, ${v8ClassName}>(args); | |
| 2167 } | |
| 2168 | |
| 2169 END | |
| 2170 $implementation{nameSpaceInternal}->add($code); | |
| 2171 return; | |
| 2172 } | |
| 2173 | |
| 2174 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGProperty
Types($interfaceName); | |
| 2175 | |
| 2176 if ($svgNativeType) { | |
| 2177 my $nativeClassName = GetNativeType($interfaceName); | |
| 2178 if ($interfaceName =~ /List$/) { | |
| 2179 $code .= " $nativeClassName imp = ${v8ClassName}::toNative(args.H
older());\n"; | |
| 2180 } else { | |
| 2181 AddToImplIncludes("core/dom/ExceptionCode.h"); | |
| 2182 $code .= " $nativeClassName wrapper = ${v8ClassName}::toNative(ar
gs.Holder());\n"; | |
| 2183 $code .= " if (wrapper->isReadOnly()) {\n"; | |
| 2184 $code .= " setDOMException(NoModificationAllowedError, args.G
etIsolate());\n"; | |
| 2185 $code .= " return;\n"; | |
| 2186 $code .= " }\n"; | |
| 2187 my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($interfac
eName); | |
| 2188 $code .= " $svgWrappedNativeType& impInstance = wrapper->property
Reference();\n"; | |
| 2189 $code .= " $svgWrappedNativeType* imp = &impInstance;\n"; | |
| 2190 } | |
| 2191 } elsif (!$function->isStatic) { | |
| 2192 $code .= <<END; | |
| 2193 ${implClassName}* imp = ${v8ClassName}::toNative(args.Holder()); | |
| 2194 END | |
| 2195 } | |
| 2196 | |
| 2197 $code .= GenerateCustomElementInvocationScopeIfNeeded($funcExt); | |
| 2198 | |
| 2199 # Check domain security if needed | |
| 2200 if ($interface->extendedAttributes->{"CheckSecurity"} && !$function->extende
dAttributes->{"DoNotCheckSecurity"}) { | |
| 2201 # We have not find real use cases yet. | |
| 2202 AddToImplIncludes("core/page/Frame.h"); | |
| 2203 AddToImplIncludes("bindings/v8/BindingSecurity.h"); | |
| 2204 $code .= <<END; | |
| 2205 if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame())) | |
| 2206 return; | |
| 2207 END | |
| 2208 } | |
| 2209 | |
| 2210 my $raisesExceptions = $function->extendedAttributes->{"RaisesException"}; | |
| 2211 if (!$raisesExceptions) { | |
| 2212 foreach my $parameter (@{$function->parameters}) { | |
| 2213 if ($parameter->extendedAttributes->{"IsIndex"}) { | |
| 2214 $raisesExceptions = 1; | |
| 2215 } | |
| 2216 } | |
| 2217 } | |
| 2218 | |
| 2219 if ($raisesExceptions) { | |
| 2220 AddToImplIncludes("core/dom/ExceptionCode.h"); | |
| 2221 $code .= " ExceptionCode ec = 0;\n"; | |
| 2222 } | |
| 2223 | |
| 2224 if ($function->extendedAttributes->{"CheckSecurityForNode"}) { | |
| 2225 AddToImplIncludes("bindings/v8/BindingSecurity.h"); | |
| 2226 $code .= " if (!BindingSecurity::shouldAllowAccessToNode(imp->" . Get
ImplName($function) . "(ec))) {\n"; | |
| 2227 $code .= " v8SetReturnValueNull(args);\n"; | |
| 2228 $code .= " return;\n"; | |
| 2229 $code .= " }\n"; | |
| 2230 END | |
| 2231 } | |
| 2232 | |
| 2233 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersC
heck($function, $interface, $forMainWorldSuffix); | |
| 2234 $code .= $parameterCheckString; | |
| 2235 | |
| 2236 # Build the function call string. | |
| 2237 $code .= GenerateFunctionCallString($function, $paramIndex, " ", $interfa
ce, $forMainWorldSuffix, %replacements); | |
| 2238 $code .= "}\n\n"; | |
| 2239 $code .= "#endif // ${conditionalString}\n\n" if $conditionalString; | |
| 2240 $implementation{nameSpaceInternal}->add($code); | |
| 2241 } | |
| 2242 | |
| 2243 sub GenerateCallWith | |
| 2244 { | |
| 2245 my $callWith = shift; | |
| 2246 return ([], "") unless $callWith; | |
| 2247 my $indent = shift; | |
| 2248 my $returnVoid = shift; | |
| 2249 my $function = shift; | |
| 2250 my $code = ""; | |
| 2251 | |
| 2252 my @callWithArgs; | |
| 2253 if (ExtendedAttributeContains($callWith, "ScriptState")) { | |
| 2254 $code .= $indent . "ScriptState* currentState = ScriptState::current();\
n"; | |
| 2255 $code .= $indent . "if (!currentState)\n"; | |
| 2256 $code .= $indent . " return" . ($returnVoid ? "" : " v8Undefined()")
. ";\n"; | |
| 2257 $code .= $indent . "ScriptState& state = *currentState;\n"; | |
| 2258 push(@callWithArgs, "&state"); | |
| 2259 } | |
| 2260 if (ExtendedAttributeContains($callWith, "ScriptExecutionContext")) { | |
| 2261 $code .= $indent . "ScriptExecutionContext* scriptContext = getScriptExe
cutionContext();\n"; | |
| 2262 push(@callWithArgs, "scriptContext"); | |
| 2263 } | |
| 2264 if ($function and ExtendedAttributeContains($callWith, "ScriptArguments")) { | |
| 2265 $code .= $indent . "RefPtr<ScriptArguments> scriptArguments(createScript
Arguments(args, " . @{$function->parameters} . "));\n"; | |
| 2266 push(@callWithArgs, "scriptArguments.release()"); | |
| 2267 AddToImplIncludes("bindings/v8/ScriptCallStackFactory.h"); | |
| 2268 AddToImplIncludes("core/inspector/ScriptArguments.h"); | |
| 2269 } | |
| 2270 if (ExtendedAttributeContains($callWith, "ActiveWindow")) { | |
| 2271 push(@callWithArgs, "activeDOMWindow()"); | |
| 2272 } | |
| 2273 if (ExtendedAttributeContains($callWith, "FirstWindow")) { | |
| 2274 push(@callWithArgs, "firstDOMWindow()"); | |
| 2275 } | |
| 2276 return ([@callWithArgs], $code); | |
| 2277 } | |
| 2278 | |
| 2279 sub GenerateArgumentsCountCheck | |
| 2280 { | |
| 2281 my $function = shift; | |
| 2282 my $interface = shift; | |
| 2283 | |
| 2284 my $numMandatoryParams = 0; | |
| 2285 my $allowNonOptional = 1; | |
| 2286 foreach my $param (@{$function->parameters}) { | |
| 2287 if ($param->isOptional or $param->isVariadic) { | |
| 2288 $allowNonOptional = 0; | |
| 2289 } else { | |
| 2290 die "An argument must not be declared to be optional unless all subs
equent arguments to the operation are also optional." if !$allowNonOptional; | |
| 2291 $numMandatoryParams++; | |
| 2292 } | |
| 2293 } | |
| 2294 | |
| 2295 my $argumentsCountCheckString = ""; | |
| 2296 if ($numMandatoryParams >= 1) { | |
| 2297 $argumentsCountCheckString .= " if (args.Length() < $numMandatoryPara
ms) {\n"; | |
| 2298 $argumentsCountCheckString .= " throwNotEnoughArgumentsError(args
.GetIsolate());\n"; | |
| 2299 $argumentsCountCheckString .= " return;\n"; | |
| 2300 $argumentsCountCheckString .= " }\n"; | |
| 2301 } | |
| 2302 return $argumentsCountCheckString; | |
| 2303 } | |
| 2304 | |
| 2305 sub GenerateParametersCheck | |
| 2306 { | |
| 2307 my $function = shift; | |
| 2308 my $interface = shift; | |
| 2309 my $forMainWorldSuffix = shift; | |
| 2310 my $style = shift || "new"; | |
| 2311 | |
| 2312 my $parameterCheckString = ""; | |
| 2313 my $paramIndex = 0; | |
| 2314 my %replacements = (); | |
| 2315 | |
| 2316 foreach my $parameter (@{$function->parameters}) { | |
| 2317 my $nativeType = GetNativeType($parameter->type, $parameter->extendedAtt
ributes, "parameter"); | |
| 2318 | |
| 2319 # Optional arguments without [Default=...] should generate an early call
with fewer arguments. | |
| 2320 # Optional arguments with [Optional=...] should not generate the early c
all. | |
| 2321 # Optional Dictionary arguments always considered to have default of emp
ty dictionary. | |
| 2322 if ($parameter->isOptional && !$parameter->extendedAttributes->{"Default
"} && $nativeType ne "Dictionary" && !IsCallbackInterface($parameter->type)) { | |
| 2323 $parameterCheckString .= " if (args.Length() <= $paramIndex)"; | |
| 2324 my $functionCall = GenerateFunctionCallString($function, $paramIndex
, " " x 2, $interface, $forMainWorldSuffix, %replacements); | |
| 2325 my $multiLine = ($functionCall =~ tr/\n//) > 1; | |
| 2326 $parameterCheckString .= $multiLine ? " {\n" : "\n"; | |
| 2327 $parameterCheckString .= $functionCall; | |
| 2328 $parameterCheckString .= $multiLine ? " }\n" : "\n"; | |
| 2329 } | |
| 2330 | |
| 2331 my $parameterDefaultPolicy = "DefaultIsUndefined"; | |
| 2332 my $default = defined $parameter->extendedAttributes->{"Default"} ? $par
ameter->extendedAttributes->{"Default"} : ""; | |
| 2333 if ($parameter->isOptional and $default eq "NullString") { | |
| 2334 $parameterDefaultPolicy = "DefaultIsNullString"; | |
| 2335 } | |
| 2336 | |
| 2337 my $parameterName = $parameter->name; | |
| 2338 AddToImplIncludes("core/dom/ExceptionCode.h"); | |
| 2339 if (IsCallbackInterface($parameter->type)) { | |
| 2340 my $v8ClassName = "V8" . $parameter->type; | |
| 2341 AddToImplIncludes("$v8ClassName.h"); | |
| 2342 if ($parameter->isOptional) { | |
| 2343 $parameterCheckString .= " RefPtr<" . $parameter->type . "> $
parameterName;\n"; | |
| 2344 $parameterCheckString .= " if (args.Length() > $paramIndex &&
!args[$paramIndex]->IsNull() && !args[$paramIndex]->IsUndefined()) {\n"; | |
| 2345 $parameterCheckString .= " if (!args[$paramIndex]->IsFunc
tion()) {\n"; | |
| 2346 $parameterCheckString .= " throwTypeError(0, args.Get
Isolate());\n"; | |
| 2347 $parameterCheckString .= " return;\n"; | |
| 2348 $parameterCheckString .= " }\n"; | |
| 2349 $parameterCheckString .= " $parameterName = ${v8ClassName
}::create(args[$paramIndex], getScriptExecutionContext());\n"; | |
| 2350 $parameterCheckString .= " }\n"; | |
| 2351 } else { | |
| 2352 $parameterCheckString .= " if (args.Length() <= $paramIndex |
| !args[$paramIndex]->IsFunction()) {\n"; | |
| 2353 $parameterCheckString .= " throwTypeError(0, args.GetIsol
ate());\n"; | |
| 2354 $parameterCheckString .= " return;\n"; | |
| 2355 $parameterCheckString .= " }\n"; | |
| 2356 $parameterCheckString .= " RefPtr<" . $parameter->type . "> $
parameterName = ${v8ClassName}::create(args[$paramIndex], getScriptExecutionCont
ext());\n"; | |
| 2357 } | |
| 2358 } elsif ($parameter->extendedAttributes->{"Clamp"}) { | |
| 2359 my $nativeValue = "${parameterName}NativeValue"; | |
| 2360 my $paramType = $parameter->type; | |
| 2361 $parameterCheckString .= " $paramType $parameterName = 0;\n"; | |
| 2362 $parameterCheckString .= " V8TRYCATCH_VOID(double, $nativeVal
ue, args[$paramIndex]->NumberValue());\n"; | |
| 2363 $parameterCheckString .= " if (!std::isnan($nativeValue))\n"; | |
| 2364 $parameterCheckString .= " $parameterName = clampTo<$para
mType>($nativeValue);\n"; | |
| 2365 } elsif ($parameter->type eq "SerializedScriptValue") { | |
| 2366 AddToImplIncludes("bindings/v8/SerializedScriptValue.h"); | |
| 2367 $parameterCheckString .= " bool ${parameterName}DidThrow = false;
\n"; | |
| 2368 $parameterCheckString .= " $nativeType $parameterName = Serialize
dScriptValue::create(args[$paramIndex], 0, 0, ${parameterName}DidThrow, args.Get
Isolate());\n"; | |
| 2369 $parameterCheckString .= " if (${parameterName}DidThrow)\n"; | |
| 2370 $parameterCheckString .= " return;\n"; | |
| 2371 } elsif ($parameter->isVariadic) { | |
| 2372 my $nativeElementType = GetNativeType($parameter->type); | |
| 2373 if ($nativeElementType =~ />$/) { | |
| 2374 $nativeElementType .= " "; | |
| 2375 } | |
| 2376 | |
| 2377 my $argType = $parameter->type; | |
| 2378 if (IsWrapperType($argType)) { | |
| 2379 $parameterCheckString .= " Vector<$nativeElementType> $parame
terName;\n"; | |
| 2380 $parameterCheckString .= " for (int i = $paramIndex; i < args
.Length(); ++i) {\n"; | |
| 2381 $parameterCheckString .= " if (!V8${argType}::HasInstance
(args[i], args.GetIsolate(), worldType(args.GetIsolate()))) {\n"; | |
| 2382 $parameterCheckString .= " throwTypeError(0, args.Get
Isolate());\n"; | |
| 2383 $parameterCheckString .= " return;\n"; | |
| 2384 $parameterCheckString .= " }\n"; | |
| 2385 $parameterCheckString .= " $parameterName.append(V8${argT
ype}::toNative(v8::Handle<v8::Object>::Cast(args[i])));\n"; | |
| 2386 $parameterCheckString .= " }\n"; | |
| 2387 } else { | |
| 2388 $parameterCheckString .= " V8TRYCATCH_VOID(Vector<$nativeElem
entType>, $parameterName, toNativeArguments<$nativeElementType>(args, $paramInde
x));\n"; | |
| 2389 } | |
| 2390 } elsif ($nativeType =~ /^V8StringResource/) { | |
| 2391 my $default = defined $parameter->extendedAttributes->{"Default"} ?
$parameter->extendedAttributes->{"Default"} : ""; | |
| 2392 my $jsValue = $parameter->isOptional && $default eq "NullString" ? "
argumentOrNull(args, $paramIndex)" : "args[$paramIndex]"; | |
| 2393 $parameterCheckString .= JSValueToNativeStatement($parameter->type,
$parameter->extendedAttributes, $jsValue, $parameterName, " ", "args.GetIsola
te()"); | |
| 2394 if (IsEnumType($parameter->type)) { | |
| 2395 my @enumValues = ValidEnumValues($parameter->type); | |
| 2396 my @validEqualities = (); | |
| 2397 foreach my $enumValue (@enumValues) { | |
| 2398 push(@validEqualities, "string == \"$enumValue\""); | |
| 2399 } | |
| 2400 my $enumValidationExpression = join(" || ", @validEqualities); | |
| 2401 $parameterCheckString .= " String string = $parameterName;\n
"; | |
| 2402 $parameterCheckString .= " if (!($enumValidationExpression))
{\n"; | |
| 2403 $parameterCheckString .= " throwTypeError(0, args.GetIsol
ate());\n"; | |
| 2404 $parameterCheckString .= " return;\n"; | |
| 2405 $parameterCheckString .= " }\n"; | |
| 2406 } | |
| 2407 } else { | |
| 2408 # If the "StrictTypeChecking" extended attribute is present, and the
argument's type is an | |
| 2409 # interface type, then if the incoming value does not implement that
interface, a TypeError | |
| 2410 # is thrown rather than silently passing NULL to the C++ code. | |
| 2411 # Per the Web IDL and ECMAScript specifications, incoming values can
always be converted | |
| 2412 # to both strings and numbers, so do not throw TypeError if the argu
ment is of these | |
| 2413 # types. | |
| 2414 if ($function->extendedAttributes->{"StrictTypeChecking"}) { | |
| 2415 my $argValue = "args[$paramIndex]"; | |
| 2416 my $argType = $parameter->type; | |
| 2417 if (IsWrapperType($argType)) { | |
| 2418 $parameterCheckString .= " if (args.Length() > $paramInde
x && !isUndefinedOrNull($argValue) && !V8${argType}::HasInstance($argValue, args
.GetIsolate(), worldType(args.GetIsolate()))) {\n"; | |
| 2419 $parameterCheckString .= " throwTypeError(0, args.Get
Isolate());\n"; | |
| 2420 $parameterCheckString .= " return;\n"; | |
| 2421 $parameterCheckString .= " }\n"; | |
| 2422 } | |
| 2423 } | |
| 2424 my $default = defined $parameter->extendedAttributes->{"Default"} ?
$parameter->extendedAttributes->{"Default"} : ""; | |
| 2425 my $jsValue = $parameter->isOptional && $default eq "NullString" ? "
argumentOrNull(args, $paramIndex)" : "args[$paramIndex]"; | |
| 2426 $parameterCheckString .= JSValueToNativeStatement($parameter->type,
$parameter->extendedAttributes, $jsValue, $parameterName, " ", "args.GetIsola
te()"); | |
| 2427 if ($nativeType eq 'Dictionary') { | |
| 2428 $parameterCheckString .= " if (!$parameterName.isUndefinedOrN
ull() && !$parameterName.isObject()) {\n"; | |
| 2429 $parameterCheckString .= " throwTypeError(\"Not an object
.\", args.GetIsolate());\n"; | |
| 2430 $parameterCheckString .= " return;\n"; | |
| 2431 $parameterCheckString .= " }\n"; | |
| 2432 } | |
| 2433 } | |
| 2434 | |
| 2435 if ($parameter->extendedAttributes->{"IsIndex"}) { | |
| 2436 $parameterCheckString .= " if (UNLIKELY($parameterName < 0)) {\n"
; | |
| 2437 $parameterCheckString .= " setDOMException(IndexSizeError, ar
gs.GetIsolate());\n"; | |
| 2438 $parameterCheckString .= " return;\n"; | |
| 2439 $parameterCheckString .= " }\n"; | |
| 2440 } | |
| 2441 | |
| 2442 $paramIndex++; | |
| 2443 } | |
| 2444 return ($parameterCheckString, $paramIndex, %replacements); | |
| 2445 } | |
| 2446 | |
| 2447 sub GenerateOverloadedConstructorCallback | |
| 2448 { | |
| 2449 my $interface = shift; | |
| 2450 my $implClassName = GetImplName($interface); | |
| 2451 | |
| 2452 my $code = ""; | |
| 2453 $code .= <<END; | |
| 2454 static void constructor(const v8::FunctionCallbackInfo<v8::Value>& args) | |
| 2455 { | |
| 2456 END | |
| 2457 my $leastNumMandatoryParams = 255; | |
| 2458 foreach my $constructor (@{$interface->constructors}) { | |
| 2459 my $name = "constructor" . $constructor->overloadedIndex; | |
| 2460 my ($numMandatoryParams, $parametersCheck) = GenerateFunctionParametersC
heck($constructor); | |
| 2461 $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams <
$leastNumMandatoryParams); | |
| 2462 $code .= " if ($parametersCheck) {\n"; | |
| 2463 $code .= " ${implClassName}V8Internal::${name}(args);\n"; | |
| 2464 $code .= " return;\n"; | |
| 2465 $code .= " }\n"; | |
| 2466 } | |
| 2467 if ($leastNumMandatoryParams >= 1) { | |
| 2468 $code .= " if (args.Length() < $leastNumMandatoryParams) {\n"; | |
| 2469 $code .= " throwNotEnoughArgumentsError(args.GetIsolate());\n"; | |
| 2470 $code .= " return;\n"; | |
| 2471 $code .= " }\n"; | |
| 2472 } | |
| 2473 $code .= <<END; | |
| 2474 throwTypeError(0, args.GetIsolate()); | |
| 2475 return; | |
| 2476 END | |
| 2477 $code .= "}\n\n"; | |
| 2478 $implementation{nameSpaceInternal}->add($code); | |
| 2479 } | |
| 2480 | |
| 2481 sub GenerateSingleConstructorCallback | |
| 2482 { | |
| 2483 my $interface = shift; | |
| 2484 my $function = shift; | |
| 2485 | |
| 2486 my $implClassName = GetImplName($interface); | |
| 2487 my $v8ClassName = GetV8ClassName($interface); | |
| 2488 my $overloadedIndexString = ""; | |
| 2489 if ($function->overloadedIndex > 0) { | |
| 2490 $overloadedIndexString .= $function->overloadedIndex; | |
| 2491 } | |
| 2492 | |
| 2493 my $raisesExceptions = $function->extendedAttributes->{"RaisesException"}; | |
| 2494 if ($interface->extendedAttributes->{"ConstructorRaisesException"}) { | |
| 2495 $raisesExceptions = 1; | |
| 2496 } | |
| 2497 if (!$raisesExceptions) { | |
| 2498 foreach my $parameter (@{$function->parameters}) { | |
| 2499 if ($parameter->extendedAttributes->{"IsIndex"}) { | |
| 2500 $raisesExceptions = 1; | |
| 2501 } | |
| 2502 } | |
| 2503 } | |
| 2504 | |
| 2505 my @beforeArgumentList; | |
| 2506 my @afterArgumentList; | |
| 2507 my $code = ""; | |
| 2508 $code .= <<END; | |
| 2509 static void constructor${overloadedIndexString}(const v8::FunctionCallbackInfo<v
8::Value>& args) | |
| 2510 { | |
| 2511 END | |
| 2512 | |
| 2513 if ($function->overloadedIndex == 0) { | |
| 2514 $code .= GenerateArgumentsCountCheck($function, $interface); | |
| 2515 } | |
| 2516 | |
| 2517 if ($raisesExceptions) { | |
| 2518 AddToImplIncludes("core/dom/ExceptionCode.h"); | |
| 2519 $code .= " ExceptionCode ec = 0;\n"; | |
| 2520 } | |
| 2521 | |
| 2522 # FIXME: Currently [Constructor(...)] does not yet support optional argument
s without [Default=...] | |
| 2523 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersC
heck($function, $interface, ""); | |
| 2524 $code .= $parameterCheckString; | |
| 2525 | |
| 2526 if ($interface->extendedAttributes->{"ConstructorCallWith"} && $interface->e
xtendedAttributes->{"ConstructorCallWith"} eq "ScriptExecutionContext") { | |
| 2527 push(@beforeArgumentList, "context"); | |
| 2528 $code .= <<END; | |
| 2529 | |
| 2530 ScriptExecutionContext* context = getScriptExecutionContext(); | |
| 2531 END | |
| 2532 } | |
| 2533 | |
| 2534 if ($interface->extendedAttributes->{"ConstructorRaisesException"}) { | |
| 2535 push(@afterArgumentList, "ec"); | |
| 2536 } | |
| 2537 | |
| 2538 my @argumentList; | |
| 2539 my $index = 0; | |
| 2540 foreach my $parameter (@{$function->parameters}) { | |
| 2541 last if $index eq $paramIndex; | |
| 2542 if ($replacements{$parameter->name}) { | |
| 2543 push(@argumentList, $replacements{$parameter->name}); | |
| 2544 } else { | |
| 2545 push(@argumentList, $parameter->name); | |
| 2546 } | |
| 2547 $index++; | |
| 2548 } | |
| 2549 | |
| 2550 my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterAr
gumentList); | |
| 2551 $code .= "\n"; | |
| 2552 $code .= " RefPtr<${implClassName}> impl = ${implClassName}::create(${arg
umentString});\n"; | |
| 2553 $code .= " v8::Handle<v8::Object> wrapper = args.Holder();\n"; | |
| 2554 | |
| 2555 if ($interface->extendedAttributes->{"ConstructorRaisesException"}) { | |
| 2556 $code .= " if (ec) {\n"; | |
| 2557 $code .= " setDOMException(ec, args.GetIsolate());\n"; | |
| 2558 $code .= " return;\n"; | |
| 2559 $code .= " }\n"; | |
| 2560 } | |
| 2561 | |
| 2562 $code .= <<END; | |
| 2563 | |
| 2564 V8DOMWrapper::associateObjectWithWrapper(impl.release(), &${v8ClassName}::in
fo, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent); | |
| 2565 args.GetReturnValue().Set(wrapper); | |
| 2566 } | |
| 2567 | |
| 2568 END | |
| 2569 $implementation{nameSpaceInternal}->add($code); | |
| 2570 } | |
| 2571 | |
| 2572 # The Web IDL specification states that Interface objects for interfaces MUST ha
ve a property named | |
| 2573 # "length" that returns the length of the shortest argument list of the entries
in the effective | |
| 2574 # overload set for constructors. In other words, use the lowest number of mandat
ory arguments among | |
| 2575 # all constructors. | |
| 2576 sub GetInterfaceLength | |
| 2577 { | |
| 2578 my $interface = shift; | |
| 2579 | |
| 2580 my $leastConstructorLength = 0; | |
| 2581 if (IsConstructorTemplate($interface, "Event") || IsConstructorTemplate($int
erface, "TypedArray")) { | |
| 2582 $leastConstructorLength = 1; | |
| 2583 } elsif ($interface->extendedAttributes->{"Constructor"} || $interface->exte
ndedAttributes->{"CustomConstructor"}) { | |
| 2584 my @constructors = @{$interface->constructors}; | |
| 2585 my @customConstructors = @{$interface->customConstructors}; | |
| 2586 $leastConstructorLength = 255; | |
| 2587 foreach my $constructor (@constructors, @customConstructors) { | |
| 2588 my $constructorLength = GetFunctionLength($constructor); | |
| 2589 $leastConstructorLength = $constructorLength if ($constructorLength
< $leastConstructorLength); | |
| 2590 } | |
| 2591 } | |
| 2592 | |
| 2593 return $leastConstructorLength; | |
| 2594 } | |
| 2595 | |
| 2596 sub GenerateConstructorCallback | |
| 2597 { | |
| 2598 my $interface = shift; | |
| 2599 | |
| 2600 my $implClassName = GetImplName($interface); | |
| 2601 my $v8ClassName = GetV8ClassName($interface); | |
| 2602 my $code = ""; | |
| 2603 $code .= "void ${v8ClassName}::constructorCallback(const v8::FunctionCallbac
kInfo<v8::Value>& args)\n"; | |
| 2604 $code .= "{\n"; | |
| 2605 $code .= " TRACE_EVENT_SCOPED_SAMPLING_STATE(\"Blink\", \"DOMConstructor\
");\n"; | |
| 2606 $code .= GenerateFeatureObservation($interface->extendedAttributes->{"Measur
eAs"}); | |
| 2607 $code .= GenerateDeprecationNotification($interface->extendedAttributes->{"D
eprecateAs"}); | |
| 2608 $code .= GenerateConstructorHeader(); | |
| 2609 if (HasCustomConstructor($interface)) { | |
| 2610 $code .= " ${v8ClassName}::constructorCustom(args);\n"; | |
| 2611 } else { | |
| 2612 $code .= " ${implClassName}V8Internal::constructor(args);\n"; | |
| 2613 } | |
| 2614 $code .= "}\n\n"; | |
| 2615 $implementation{nameSpaceWebCore}->add($code); | |
| 2616 } | |
| 2617 | |
| 2618 sub GenerateConstructor | |
| 2619 { | |
| 2620 my $interface = shift; | |
| 2621 | |
| 2622 if (@{$interface->constructors} == 1) { | |
| 2623 GenerateSingleConstructorCallback($interface, @{$interface->constructors
}[0]); | |
| 2624 } else { | |
| 2625 foreach my $constructor (@{$interface->constructors}) { | |
| 2626 GenerateSingleConstructorCallback($interface, $constructor); | |
| 2627 } | |
| 2628 GenerateOverloadedConstructorCallback($interface); | |
| 2629 } | |
| 2630 } | |
| 2631 | |
| 2632 sub GenerateEventConstructor | |
| 2633 { | |
| 2634 my $interface = shift; | |
| 2635 my $implClassName = GetImplName($interface); | |
| 2636 my $v8ClassName = GetV8ClassName($interface); | |
| 2637 | |
| 2638 AddToImplIncludes("bindings/v8/Dictionary.h"); | |
| 2639 $implementation{nameSpaceInternal}->add(<<END); | |
| 2640 static void constructor(const v8::FunctionCallbackInfo<v8::Value>& args) | |
| 2641 { | |
| 2642 if (args.Length() < 1) { | |
| 2643 throwNotEnoughArgumentsError(args.GetIsolate()); | |
| 2644 return; | |
| 2645 } | |
| 2646 | |
| 2647 V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, type, args[0]); | |
| 2648 ${implClassName}Init eventInit; | |
| 2649 if (args.Length() >= 2) { | |
| 2650 V8TRYCATCH_VOID(Dictionary, options, Dictionary(args[1], args.GetIsolate
())); | |
| 2651 if (!fill${implClassName}Init(eventInit, options)) | |
| 2652 return; | |
| 2653 END | |
| 2654 for (my $index = 0; $index < @{$interface->attributes}; $index++) { | |
| 2655 my $attribute = @{$interface->attributes}[$index]; | |
| 2656 if ($attribute->type eq "any") { | |
| 2657 my $attributeName = $attribute->name; | |
| 2658 $implementation{nameSpaceInternal}->add(<<END); | |
| 2659 v8::Local<v8::Value> ${attributeName}; | |
| 2660 options.get("${attributeName}", ${attributeName}); | |
| 2661 if (!${attributeName}.IsEmpty()) | |
| 2662 args.Holder()->SetHiddenValue(V8HiddenPropertyName::${attributeName}
(), ${attributeName}); | |
| 2663 END | |
| 2664 } | |
| 2665 } | |
| 2666 $implementation{nameSpaceInternal}->add(<<END); | |
| 2667 } | |
| 2668 | |
| 2669 RefPtr<${implClassName}> event = ${implClassName}::create(type, eventInit); | |
| 2670 | |
| 2671 v8::Handle<v8::Object> wrapper = args.Holder(); | |
| 2672 V8DOMWrapper::associateObjectWithWrapper(event.release(), &${v8ClassName}::i
nfo, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent); | |
| 2673 v8SetReturnValue(args, wrapper); | |
| 2674 } | |
| 2675 END | |
| 2676 | |
| 2677 my $code = ""; | |
| 2678 $code .= <<END; | |
| 2679 bool fill${implClassName}Init(${implClassName}Init& eventInit, const Dictionary&
options) | |
| 2680 { | |
| 2681 END | |
| 2682 | |
| 2683 if ($interface->parent) { | |
| 2684 my $interfaceBase = $interface->parent; | |
| 2685 $code .= <<END; | |
| 2686 if (!fill${interfaceBase}Init(eventInit, options)) | |
| 2687 return false; | |
| 2688 | |
| 2689 END | |
| 2690 } | |
| 2691 | |
| 2692 for (my $index = 0; $index < @{$interface->attributes}; $index++) { | |
| 2693 my $attribute = @{$interface->attributes}[$index]; | |
| 2694 if ($attribute->extendedAttributes->{"InitializedByEventConstructor"}) { | |
| 2695 my $attributeName = $attribute->name; | |
| 2696 my $attributeType = $attribute->type; | |
| 2697 if (not ($attribute->type eq "any")) { | |
| 2698 $code .= " options.get(\"$attributeName\", eventInit.$attribu
teName);\n"; | |
| 2699 } | |
| 2700 } | |
| 2701 } | |
| 2702 | |
| 2703 $code .= <<END; | |
| 2704 return true; | |
| 2705 } | |
| 2706 | |
| 2707 END | |
| 2708 $implementation{nameSpaceWebCore}->add($code); | |
| 2709 } | |
| 2710 | |
| 2711 sub GenerateTypedArrayConstructor | |
| 2712 { | |
| 2713 my $interface = shift; | |
| 2714 my $implClassName = GetImplName($interface); | |
| 2715 my $v8ClassName = GetV8ClassName($interface); | |
| 2716 | |
| 2717 my ($nativeType, $arrayType) = GetNativeTypeOfTypedArray($interface); | |
| 2718 AddToImplIncludes("bindings/v8/custom/V8ArrayBufferViewCustom.h"); | |
| 2719 | |
| 2720 $implementation{nameSpaceInternal}->add(<<END); | |
| 2721 static void constructor(const v8::FunctionCallbackInfo<v8::Value>& args) | |
| 2722 { | |
| 2723 return constructWebGLArray<$implClassName, ${v8ClassName}, $nativeType>(args
, &${v8ClassName}::info, $arrayType); | |
| 2724 } | |
| 2725 | |
| 2726 END | |
| 2727 } | |
| 2728 | |
| 2729 sub GenerateNamedConstructor | |
| 2730 { | |
| 2731 my $function = shift; | |
| 2732 my $interface = shift; | |
| 2733 | |
| 2734 my $implClassName = GetImplName($interface); | |
| 2735 my $v8ClassName = GetV8ClassName($interface); | |
| 2736 my $raisesExceptions = $function->extendedAttributes->{"RaisesException"}; | |
| 2737 if ($interface->extendedAttributes->{"ConstructorRaisesException"}) { | |
| 2738 $raisesExceptions = 1; | |
| 2739 } | |
| 2740 if (!$raisesExceptions) { | |
| 2741 foreach my $parameter (@{$function->parameters}) { | |
| 2742 if ($parameter->extendedAttributes->{"IsIndex"}) { | |
| 2743 $raisesExceptions = 1; | |
| 2744 } | |
| 2745 } | |
| 2746 } | |
| 2747 | |
| 2748 my $maybeObserveFeature = GenerateFeatureObservation($function->extendedAttr
ibutes->{"MeasureAs"}); | |
| 2749 my $maybeDeprecateFeature = GenerateDeprecationNotification($function->exten
dedAttributes->{"DeprecateAs"}); | |
| 2750 | |
| 2751 my @beforeArgumentList; | |
| 2752 my @afterArgumentList; | |
| 2753 | |
| 2754 my $toActiveDOMObject = "0"; | |
| 2755 if (InheritsExtendedAttribute($interface, "ActiveDOMObject")) { | |
| 2756 $toActiveDOMObject = "${v8ClassName}::toActiveDOMObject"; | |
| 2757 } | |
| 2758 | |
| 2759 my $toEventTarget = "0"; | |
| 2760 if (InheritsExtendedAttribute($interface, "EventTarget")) { | |
| 2761 $toEventTarget = "${v8ClassName}::toEventTarget"; | |
| 2762 } | |
| 2763 | |
| 2764 AddToImplIncludes("core/page/Frame.h"); | |
| 2765 $implementation{nameSpaceWebCore}->add(<<END); | |
| 2766 WrapperTypeInfo ${v8ClassName}Constructor::info = { ${v8ClassName}Constructor::G
etTemplate, ${v8ClassName}::derefObject, $toActiveDOMObject, $toEventTarget, 0,
${v8ClassName}::installPerContextPrototypeProperties, 0, WrapperTypeObjectProtot
ype }; | |
| 2767 | |
| 2768 END | |
| 2769 | |
| 2770 my $code = ""; | |
| 2771 $code .= <<END; | |
| 2772 static void ${v8ClassName}ConstructorCallback(const v8::FunctionCallbackInfo<v8:
:Value>& args) | |
| 2773 { | |
| 2774 END | |
| 2775 $code .= $maybeObserveFeature if $maybeObserveFeature; | |
| 2776 $code .= $maybeDeprecateFeature if $maybeDeprecateFeature; | |
| 2777 $code .= GenerateConstructorHeader(); | |
| 2778 AddToImplIncludes("V8Document.h"); | |
| 2779 $code .= <<END; | |
| 2780 Document* document = currentDocument(); | |
| 2781 | |
| 2782 // Make sure the document is added to the DOM Node map. Otherwise, the ${imp
lClassName} instance | |
| 2783 // may end up being the only node in the map and get garbage-collected prema
turely. | |
| 2784 toV8(document, args.Holder(), args.GetIsolate()); | |
| 2785 | |
| 2786 END | |
| 2787 | |
| 2788 $code .= GenerateArgumentsCountCheck($function, $interface); | |
| 2789 | |
| 2790 if ($raisesExceptions) { | |
| 2791 AddToImplIncludes("core/dom/ExceptionCode.h"); | |
| 2792 $code .= " ExceptionCode ec = 0;\n"; | |
| 2793 } | |
| 2794 | |
| 2795 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersC
heck($function, $interface); | |
| 2796 $code .= $parameterCheckString; | |
| 2797 | |
| 2798 push(@beforeArgumentList, "document"); | |
| 2799 | |
| 2800 if ($interface->extendedAttributes->{"ConstructorRaisesException"}) { | |
| 2801 push(@afterArgumentList, "ec"); | |
| 2802 } | |
| 2803 | |
| 2804 my @argumentList; | |
| 2805 my $index = 0; | |
| 2806 foreach my $parameter (@{$function->parameters}) { | |
| 2807 last if $index eq $paramIndex; | |
| 2808 if ($replacements{$parameter->name}) { | |
| 2809 push(@argumentList, $replacements{$parameter->name}); | |
| 2810 } else { | |
| 2811 push(@argumentList, $parameter->name); | |
| 2812 } | |
| 2813 $index++; | |
| 2814 } | |
| 2815 | |
| 2816 my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterAr
gumentList); | |
| 2817 $code .= "\n"; | |
| 2818 $code .= " RefPtr<${implClassName}> impl = ${implClassName}::createForJSC
onstructor(${argumentString});\n"; | |
| 2819 $code .= " v8::Handle<v8::Object> wrapper = args.Holder();\n"; | |
| 2820 | |
| 2821 if ($interface->extendedAttributes->{"ConstructorRaisesException"}) { | |
| 2822 $code .= " if (ec) {\n"; | |
| 2823 $code .= " setDOMException(ec, args.GetIsolate());\n"; | |
| 2824 $code .= " return;\n"; | |
| 2825 $code .= " }\n"; | |
| 2826 } | |
| 2827 | |
| 2828 $code .= <<END; | |
| 2829 | |
| 2830 V8DOMWrapper::associateObjectWithWrapper(impl.release(), &${v8ClassName}Cons
tructor::info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent); | |
| 2831 args.GetReturnValue().Set(wrapper); | |
| 2832 } | |
| 2833 | |
| 2834 END | |
| 2835 $implementation{nameSpaceWebCore}->add($code); | |
| 2836 | |
| 2837 $code = <<END; | |
| 2838 v8::Handle<v8::FunctionTemplate> ${v8ClassName}Constructor::GetTemplate(v8::Isol
ate* isolate, WrapperWorldType currentWorldType) | |
| 2839 { | |
| 2840 static v8::Persistent<v8::FunctionTemplate> cachedTemplate; | |
| 2841 if (!cachedTemplate.IsEmpty()) | |
| 2842 return v8::Local<v8::FunctionTemplate>::New(isolate, cachedTemplate); | |
| 2843 | |
| 2844 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink\", \"BuildDOMTemplate"); | |
| 2845 v8::HandleScope scope(isolate); | |
| 2846 v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(${v8Class
Name}ConstructorCallback); | |
| 2847 | |
| 2848 v8::Local<v8::ObjectTemplate> instance = result->InstanceTemplate(); | |
| 2849 instance->SetInternalFieldCount(${v8ClassName}::internalFieldCount); | |
| 2850 result->SetClassName(v8::String::NewSymbol("${implClassName}")); | |
| 2851 result->Inherit(${v8ClassName}::GetTemplate(isolate, currentWorldType)); | |
| 2852 | |
| 2853 cachedTemplate.Reset(isolate, result); | |
| 2854 return scope.Close(v8::Local<v8::FunctionTemplate>::New(isolate, cachedTempl
ate)); | |
| 2855 } | |
| 2856 | |
| 2857 END | |
| 2858 $implementation{nameSpaceWebCore}->add($code); | |
| 2859 } | |
| 2860 | |
| 2861 sub GenerateConstructorHeader | |
| 2862 { | |
| 2863 AddToImplIncludes("bindings/v8/V8ObjectConstructor.h"); | |
| 2864 my $content = <<END; | |
| 2865 if (!args.IsConstructCall()) { | |
| 2866 throwTypeError("DOM object constructor cannot be called as a function.",
args.GetIsolate()); | |
| 2867 return; | |
| 2868 } | |
| 2869 | |
| 2870 if (ConstructorMode::current() == ConstructorMode::WrapExistingObject) { | |
| 2871 args.GetReturnValue().Set(args.Holder()); | |
| 2872 return; | |
| 2873 } | |
| 2874 | |
| 2875 END | |
| 2876 return $content; | |
| 2877 } | |
| 2878 | |
| 2879 sub GenerateBatchedAttributeData | |
| 2880 { | |
| 2881 my $interface = shift; | |
| 2882 my $attributes = shift; | |
| 2883 my $code = ""; | |
| 2884 | |
| 2885 foreach my $attribute (@$attributes) { | |
| 2886 my $conditionalString = GenerateConditionalString($attribute); | |
| 2887 my $subCode = ""; | |
| 2888 $subCode .= "#if ${conditionalString}\n" if $conditionalString; | |
| 2889 $subCode .= GenerateSingleBatchedAttribute($interface, $attribute, ",",
""); | |
| 2890 $subCode .= "#endif // ${conditionalString}\n" if $conditionalString; | |
| 2891 $code .= $subCode; | |
| 2892 } | |
| 2893 return $code; | |
| 2894 } | |
| 2895 | |
| 2896 sub GenerateSingleBatchedAttribute | |
| 2897 { | |
| 2898 my $interface = shift; | |
| 2899 my $attribute = shift; | |
| 2900 my $delimiter = shift; | |
| 2901 my $indent = shift; | |
| 2902 my $code = ""; | |
| 2903 my $attrName = $attribute->name; | |
| 2904 my $attrExt = $attribute->extendedAttributes; | |
| 2905 my $implClassName = GetImplName($interface); | |
| 2906 | |
| 2907 my $accessControl = "v8::DEFAULT"; | |
| 2908 if ($attrExt->{"DoNotCheckSecurityOnGetter"}) { | |
| 2909 $accessControl = "v8::ALL_CAN_READ"; | |
| 2910 } elsif ($attrExt->{"DoNotCheckSecurityOnSetter"}) { | |
| 2911 $accessControl = "v8::ALL_CAN_WRITE"; | |
| 2912 } elsif ($attrExt->{"DoNotCheckSecurity"}) { | |
| 2913 $accessControl = "v8::ALL_CAN_READ"; | |
| 2914 if (!IsReadonly($attribute)) { | |
| 2915 $accessControl .= " | v8::ALL_CAN_WRITE"; | |
| 2916 } | |
| 2917 } | |
| 2918 if ($attrExt->{"Unforgeable"}) { | |
| 2919 $accessControl .= " | v8::PROHIBITS_OVERWRITING"; | |
| 2920 } | |
| 2921 $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")"; | |
| 2922 | |
| 2923 my $customAccessor = HasCustomGetter($attrExt) || HasCustomSetter($attrExt)
|| ""; | |
| 2924 if ($customAccessor eq "VALUE_IS_MISSING") { | |
| 2925 # use the naming convension, interface + (capitalize) attr name | |
| 2926 $customAccessor = $implClassName . "::" . $attrName; | |
| 2927 } | |
| 2928 | |
| 2929 my $getter; | |
| 2930 my $setter; | |
| 2931 my $getterForMainWorld; | |
| 2932 my $setterForMainWorld; | |
| 2933 my $propAttr = "v8::None"; | |
| 2934 | |
| 2935 my $isConstructor = ($attribute->type =~ /Constructor$/); | |
| 2936 | |
| 2937 # Check attributes. | |
| 2938 # As per Web IDL specification, constructor properties on the ECMAScript glo
bal object should be | |
| 2939 # configurable and should not be enumerable. | |
| 2940 if ($attrExt->{"NotEnumerable"} || $isConstructor) { | |
| 2941 $propAttr .= " | v8::DontEnum"; | |
| 2942 } | |
| 2943 if ($attrExt->{"Unforgeable"} && !$isConstructor) { | |
| 2944 $propAttr .= " | v8::DontDelete"; | |
| 2945 } | |
| 2946 | |
| 2947 my $on_proto = "0 /* on instance */"; | |
| 2948 my $data = "0 /* no data */"; | |
| 2949 | |
| 2950 # Constructor | |
| 2951 if ($isConstructor) { | |
| 2952 my $constructorType = $attribute->type; | |
| 2953 $constructorType =~ s/Constructor$//; | |
| 2954 # $constructorType ~= /Constructor$/ indicates that it is NamedConstruct
or. | |
| 2955 # We do not generate the header file for NamedConstructor of class XXXX, | |
| 2956 # since we generate the NamedConstructor declaration into the header fil
e of class XXXX. | |
| 2957 if ($constructorType !~ /Constructor$/ || $attribute->extendedAttributes
->{"CustomConstructor"}) { | |
| 2958 AddToImplIncludes("V8${constructorType}.h"); | |
| 2959 } | |
| 2960 $data = "&V8${constructorType}::info"; | |
| 2961 $getter = "${implClassName}V8Internal::${implClassName}ConstructorGetter
"; | |
| 2962 $setter = "${implClassName}V8Internal::${implClassName}ReplaceableAttrSe
tterCallback"; | |
| 2963 $getterForMainWorld = "0"; | |
| 2964 $setterForMainWorld = "0"; | |
| 2965 } else { | |
| 2966 # Default Getter and Setter | |
| 2967 $getter = "${implClassName}V8Internal::${attrName}AttrGetterCallback"; | |
| 2968 $setter = "${implClassName}V8Internal::${attrName}AttrSetterCallback"; | |
| 2969 $getterForMainWorld = "${getter}ForMainWorld"; | |
| 2970 $setterForMainWorld = "${setter}ForMainWorld"; | |
| 2971 | |
| 2972 if (!HasCustomSetter($attrExt) && $attrExt->{"Replaceable"}) { | |
| 2973 $setter = "${implClassName}V8Internal::${implClassName}ReplaceableAt
trSetterCallback"; | |
| 2974 $setterForMainWorld = "0"; | |
| 2975 } | |
| 2976 } | |
| 2977 | |
| 2978 # Read only attributes | |
| 2979 if (IsReadonly($attribute)) { | |
| 2980 $setter = "0"; | |
| 2981 $setterForMainWorld = "0"; | |
| 2982 } | |
| 2983 | |
| 2984 # An accessor can be installed on the proto | |
| 2985 if ($attrExt->{"OnProto"}) { | |
| 2986 $on_proto = "1 /* on proto */"; | |
| 2987 } | |
| 2988 | |
| 2989 if (!$attrExt->{"PerWorldBindings"}) { | |
| 2990 $getterForMainWorld = "0"; | |
| 2991 $setterForMainWorld = "0"; | |
| 2992 } | |
| 2993 | |
| 2994 my $commentInfo = "Attribute '$attrName'"; | |
| 2995 | |
| 2996 $code .= $indent . " \/\/ $commentInfo\n"; | |
| 2997 $code .= $indent . " {\"$attrName\", $getter, $setter, $getterForMainWorl
d, $setterForMainWorld, $data, $accessControl, static_cast<v8::PropertyAttribute
>($propAttr), $on_proto}" . $delimiter . "\n"; | |
| 2998 return $code; | |
| 2999 } | |
| 3000 | |
| 3001 sub IsStandardFunction | |
| 3002 { | |
| 3003 my $interface = shift; | |
| 3004 my $function = shift; | |
| 3005 | |
| 3006 my $interfaceName = $interface->name; | |
| 3007 my $attrExt = $function->extendedAttributes; | |
| 3008 return 0 if $attrExt->{"Unforgeable"}; | |
| 3009 return 0 if $function->isStatic; | |
| 3010 return 0 if $attrExt->{"EnabledAtRuntime"}; | |
| 3011 return 0 if $attrExt->{"EnabledPerContext"}; | |
| 3012 return 0 if RequiresCustomSignature($function); | |
| 3013 return 0 if $attrExt->{"DoNotCheckSignature"}; | |
| 3014 return 0 if ($attrExt->{"DoNotCheckSecurity"} && ($interface->extendedAttrib
utes->{"CheckSecurity"} || $interfaceName eq "Window")); | |
| 3015 return 0 if $attrExt->{"NotEnumerable"}; | |
| 3016 return 0 if $attrExt->{"ReadOnly"}; | |
| 3017 return 1; | |
| 3018 } | |
| 3019 | |
| 3020 sub GenerateNonStandardFunction | |
| 3021 { | |
| 3022 my $interface = shift; | |
| 3023 my $function = shift; | |
| 3024 my $code = ""; | |
| 3025 | |
| 3026 my $implClassName = GetImplName($interface); | |
| 3027 my $attrExt = $function->extendedAttributes; | |
| 3028 my $name = $function->name; | |
| 3029 | |
| 3030 my $property_attributes = "v8::DontDelete"; | |
| 3031 if ($attrExt->{"NotEnumerable"}) { | |
| 3032 $property_attributes .= " | v8::DontEnum"; | |
| 3033 } | |
| 3034 if ($attrExt->{"ReadOnly"}) { | |
| 3035 $property_attributes .= " | v8::ReadOnly"; | |
| 3036 } | |
| 3037 | |
| 3038 my $commentInfo = "Function '$name' (ExtAttr: '" . join(' ', keys(%{$attrExt
})) . "')"; | |
| 3039 | |
| 3040 my $template = "proto"; | |
| 3041 if ($attrExt->{"Unforgeable"}) { | |
| 3042 $template = "instance"; | |
| 3043 } | |
| 3044 if ($function->isStatic) { | |
| 3045 $template = "desc"; | |
| 3046 } | |
| 3047 | |
| 3048 my $conditional = ""; | |
| 3049 if ($attrExt->{"EnabledAtRuntime"}) { | |
| 3050 # Only call Set()/SetAccessor() if this method should be enabled | |
| 3051 my $enable_function = GetRuntimeEnableFunctionName($function); | |
| 3052 $conditional = "if (${enable_function}())\n "; | |
| 3053 } | |
| 3054 if ($attrExt->{"EnabledPerContext"}) { | |
| 3055 # Only call Set()/SetAccessor() if this method should be enabled | |
| 3056 my $enable_function = GetContextEnableFunction($function); | |
| 3057 $conditional = "if (${enable_function}(impl->document()))\n "; | |
| 3058 } | |
| 3059 | |
| 3060 if ($interface->extendedAttributes->{"CheckSecurity"} && $attrExt->{"DoNotCh
eckSecurity"}) { | |
| 3061 my $setter = $attrExt->{"ReadOnly"} ? "0" : "${implClassName}V8Internal:
:${implClassName}DomainSafeFunctionSetter"; | |
| 3062 # Functions that are marked DoNotCheckSecurity are always readable but i
f they are changed | |
| 3063 # and then accessed on a different domain we do not return the underlyin
g value but instead | |
| 3064 # return a new copy of the original function. This is achieved by storin
g the changed value | |
| 3065 # as hidden property. | |
| 3066 $code .= <<END; | |
| 3067 | |
| 3068 // $commentInfo | |
| 3069 ${conditional}$template->SetAccessor(v8::String::NewSymbol("$name"), ${implC
lassName}V8Internal::${name}AttrGetterCallback, ${setter}, v8Undefined(), v8::AL
L_CAN_READ, static_cast<v8::PropertyAttribute>($property_attributes)); | |
| 3070 END | |
| 3071 return $code; | |
| 3072 } | |
| 3073 | |
| 3074 my $signature = "defaultSignature"; | |
| 3075 if ($attrExt->{"DoNotCheckSignature"} || $function->isStatic) { | |
| 3076 $signature = "v8::Local<v8::Signature>()"; | |
| 3077 } | |
| 3078 | |
| 3079 my $conditionalString = GenerateConditionalString($function); | |
| 3080 $code .= "#if ${conditionalString}\n" if $conditionalString; | |
| 3081 if (RequiresCustomSignature($function)) { | |
| 3082 $signature = "${name}Signature"; | |
| 3083 $code .= "\n // Custom Signature '$name'\n" . CreateCustomSignature($
function); | |
| 3084 } | |
| 3085 | |
| 3086 if ($property_attributes eq "v8::DontDelete") { | |
| 3087 $property_attributes = ""; | |
| 3088 } else { | |
| 3089 $property_attributes = ", static_cast<v8::PropertyAttribute>($property_a
ttributes)"; | |
| 3090 } | |
| 3091 | |
| 3092 if ($template eq "proto" && $conditional eq "" && $signature eq "defaultSign
ature" && $property_attributes eq "") { | |
| 3093 die "This shouldn't happen: Class '$implClassName' $commentInfo\n"; | |
| 3094 } | |
| 3095 | |
| 3096 my $functionLength = GetFunctionLength($function); | |
| 3097 | |
| 3098 if ($function->extendedAttributes->{"PerWorldBindings"}) { | |
| 3099 $code .= " if (currentWorldType == MainWorld) {\n"; | |
| 3100 $code .= " ${conditional}$template->Set(v8::String::NewSymbol(\"$
name\"), v8::FunctionTemplate::New(${implClassName}V8Internal::${name}MethodCall
backForMainWorld, v8Undefined(), ${signature}, $functionLength)$property_attribu
tes);\n"; | |
| 3101 $code .= " } else {\n"; | |
| 3102 $code .= " ${conditional}$template->Set(v8::String::NewSymbol(\"$
name\"), v8::FunctionTemplate::New(${implClassName}V8Internal::${name}MethodCall
back, v8Undefined(), ${signature}, $functionLength)$property_attributes);\n"; | |
| 3103 $code .= " }\n"; | |
| 3104 } else { | |
| 3105 $code .= " ${conditional}$template->Set(v8::String::NewSymbol(\"$name
\"), v8::FunctionTemplate::New(${implClassName}V8Internal::${name}MethodCallback
, v8Undefined(), ${signature}, $functionLength)$property_attributes);\n"; | |
| 3106 } | |
| 3107 $code .= "#endif // ${conditionalString}\n" if $conditionalString; | |
| 3108 return $code; | |
| 3109 } | |
| 3110 | |
| 3111 sub GenerateIsNullExpression | |
| 3112 { | |
| 3113 my $type = shift; | |
| 3114 my $variableName = shift; | |
| 3115 if (IsUnionType($type)) { | |
| 3116 my $types = $type->unionMemberTypes; | |
| 3117 my @expression = (); | |
| 3118 for my $i (0 .. scalar(@$types)-1) { | |
| 3119 my $unionMemberType = $types->[$i]; | |
| 3120 my $unionMemberVariable = $variableName . $i; | |
| 3121 my $isNull = GenerateIsNullExpression($unionMemberType, $unionMember
Variable); | |
| 3122 push @expression, $isNull; | |
| 3123 } | |
| 3124 return join " && ", @expression; | |
| 3125 } | |
| 3126 if (IsRefPtrType($type)) { | |
| 3127 return "!${variableName}"; | |
| 3128 } elsif ($type eq "DOMString") { | |
| 3129 return "${variableName}.isNull()"; | |
| 3130 } else { | |
| 3131 return ""; | |
| 3132 } | |
| 3133 } | |
| 3134 | |
| 3135 sub GenerateIfElseStatement | |
| 3136 { | |
| 3137 my $type = shift; | |
| 3138 my $outputVariableName = shift; | |
| 3139 my $conditions = shift; | |
| 3140 my $statements = shift; | |
| 3141 | |
| 3142 my $code = ""; | |
| 3143 if (@$conditions == 1) { | |
| 3144 $code .= " ${type} ${outputVariableName} = " . $statements->[0] . "\n
"; | |
| 3145 } else { | |
| 3146 $code .= " ${type} ${outputVariableName};\n"; | |
| 3147 for my $i (0 .. @$conditions - 1) { | |
| 3148 my $token = "else if"; | |
| 3149 $token = "if" if $i == 0; | |
| 3150 $token = "else" if $i == @$conditions - 1; | |
| 3151 $code .= " ${token}"; | |
| 3152 $code .= " (" . $conditions->[$i] . ")" if $conditions->[$i]; | |
| 3153 $code .= "\n"; | |
| 3154 $code .= " ${outputVariableName} = " . $statements->[$i] . "\
n"; | |
| 3155 } | |
| 3156 } | |
| 3157 return $code; | |
| 3158 } | |
| 3159 | |
| 3160 sub GenerateImplementationIndexedPropertyAccessors | |
| 3161 { | |
| 3162 my $interface = shift; | |
| 3163 my $interfaceName = $interface->name; | |
| 3164 my $implClassName = GetImplName($interface); | |
| 3165 my $v8ClassName = GetV8ClassName($interface); | |
| 3166 | |
| 3167 my $indexedGetterFunction = GetIndexedGetterFunction($interface); | |
| 3168 if ($indexedGetterFunction) { | |
| 3169 my $hasCustomIndexedGetter = $indexedGetterFunction->extendedAttributes-
>{"Custom"}; | |
| 3170 if (!$hasCustomIndexedGetter) { | |
| 3171 GenerateImplementationIndexedPropertyGetter($interface, $indexedGett
erFunction); | |
| 3172 } | |
| 3173 GenerateImplementationIndexedPropertyGetterCallback($interface, $hasCust
omIndexedGetter); | |
| 3174 } | |
| 3175 | |
| 3176 my $indexedSetterFunction = GetIndexedSetterFunction($interface); | |
| 3177 if ($indexedSetterFunction) { | |
| 3178 my $hasCustomIndexedSetter = $indexedSetterFunction->extendedAttributes-
>{"Custom"}; | |
| 3179 if (!$hasCustomIndexedSetter) { | |
| 3180 GenerateImplementationIndexedPropertySetter($interface, $indexedSett
erFunction); | |
| 3181 } | |
| 3182 GenerateImplementationIndexedPropertySetterCallback($interface, $hasCust
omIndexedSetter); | |
| 3183 } | |
| 3184 | |
| 3185 my $indexedDeleterFunction = GetIndexedDeleterFunction($interface); | |
| 3186 if ($indexedDeleterFunction) { | |
| 3187 my $hasCustomIndexedDeleter = $indexedDeleterFunction->extendedAttribute
s->{"Custom"}; | |
| 3188 if (!$hasCustomIndexedDeleter) { | |
| 3189 GenerateImplementationIndexedPropertyDeleter($interface, $indexedDel
eterFunction); | |
| 3190 } | |
| 3191 GenerateImplementationIndexedPropertyDeleterCallback($interface, $hasCus
tomIndexedDeleter); | |
| 3192 } | |
| 3193 | |
| 3194 my $indexedEnumeratorFunction = $indexedGetterFunction; | |
| 3195 $indexedEnumeratorFunction = 0 if $indexedGetterFunction && $indexedGetterFu
nction->extendedAttributes->{"NotEnumerable"}; | |
| 3196 | |
| 3197 my $indexedQueryFunction = 0; | |
| 3198 # If there is an enumerator, there MUST be a query method to properly commun
icate property attributes. | |
| 3199 my $hasQuery = $indexedQueryFunction || $indexedEnumeratorFunction; | |
| 3200 | |
| 3201 my $setOn = "Instance"; | |
| 3202 | |
| 3203 # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallba
cks) and it's used on Window | |
| 3204 # instead of deleters or enumerators. In addition, the getter should be set
on prototype template, to | |
| 3205 # get implementation straight out of the Window prototype regardless of what
prototype is actually set | |
| 3206 # on the object. | |
| 3207 if ($interfaceName eq "Window") { | |
| 3208 $setOn = "Prototype"; | |
| 3209 } | |
| 3210 | |
| 3211 my $code = ""; | |
| 3212 if ($indexedGetterFunction || $indexedSetterFunction || $indexedDeleterFunct
ion || $indexedEnumeratorFunction || $hasQuery) { | |
| 3213 $code .= " desc->${setOn}Template()->SetIndexedPropertyHandler(${impl
ClassName}V8Internal::indexedPropertyGetterCallback"; | |
| 3214 $code .= $indexedSetterFunction ? ", ${implClassName}V8Internal::indexed
PropertySetterCallback" : ", 0"; | |
| 3215 $code .= ", 0"; # IndexedPropertyQuery -- not being used at the moment. | |
| 3216 $code .= $indexedDeleterFunction ? ", ${implClassName}V8Internal::indexe
dPropertyDeleterCallback" : ", 0"; | |
| 3217 $code .= ", indexedPropertyEnumerator<${implClassName}>" if $indexedEnum
eratorFunction; | |
| 3218 $code .= ");\n"; | |
| 3219 } | |
| 3220 | |
| 3221 return $code; | |
| 3222 } | |
| 3223 | |
| 3224 sub GenerateImplementationIndexedPropertyGetter | |
| 3225 { | |
| 3226 my $interface = shift; | |
| 3227 my $indexedGetterFunction = shift; | |
| 3228 my $implClassName = GetImplName($interface); | |
| 3229 my $v8ClassName = GetV8ClassName($interface); | |
| 3230 my $methodName = GetImplName($indexedGetterFunction); | |
| 3231 | |
| 3232 my $returnType = $indexedGetterFunction->type; | |
| 3233 my $nativeType = GetNativeType($returnType); | |
| 3234 my $nativeValue = "element"; | |
| 3235 $nativeValue .= ".release()" if (IsRefPtrType($returnType)); | |
| 3236 my $isNull = GenerateIsNullExpression($returnType, "element"); | |
| 3237 my $returnJSValueCode = NativeToJSValue($indexedGetterFunction->type, $index
edGetterFunction->extendedAttributes, $nativeValue, " ", "", "info.Holder()",
"info.GetIsolate()", "info", "collection", "", "", "return"); | |
| 3238 my $raisesExceptions = $indexedGetterFunction->extendedAttributes->{"RaisesE
xception"}; | |
| 3239 my $methodCallCode = GenerateMethodCall($returnType, "element", "collection-
>${methodName}", "index", $raisesExceptions); | |
| 3240 my $getterCode = "static void indexedPropertyGetter(uint32_t index, const v8
::PropertyCallbackInfo<v8::Value>& info)\n"; | |
| 3241 $getterCode .= "{\n"; | |
| 3242 $getterCode .= " ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder()));\n"
; | |
| 3243 $getterCode .= " ${implClassName}* collection = ${v8ClassName}::toNative(
info.Holder());\n"; | |
| 3244 if ($raisesExceptions) { | |
| 3245 $getterCode .= " ExceptionCode ec = 0;\n"; | |
| 3246 } | |
| 3247 $getterCode .= $methodCallCode . "\n"; | |
| 3248 if ($raisesExceptions) { | |
| 3249 $getterCode .= " if (ec) {\n"; | |
| 3250 $getterCode .= " setDOMException(ec, info.GetIsolate());\n"; | |
| 3251 $getterCode .= " return;\n"; | |
| 3252 $getterCode .= " }\n"; | |
| 3253 } | |
| 3254 if (IsUnionType($returnType)) { | |
| 3255 $getterCode .= "${returnJSValueCode}\n"; | |
| 3256 $getterCode .= " return;\n"; | |
| 3257 } else { | |
| 3258 $getterCode .= " if (${isNull})\n"; | |
| 3259 $getterCode .= " return;\n"; | |
| 3260 $getterCode .= $returnJSValueCode . "\n"; | |
| 3261 } | |
| 3262 $getterCode .= "}\n\n"; | |
| 3263 $implementation{nameSpaceInternal}->add($getterCode); | |
| 3264 } | |
| 3265 | |
| 3266 sub GenerateImplementationIndexedPropertyGetterCallback | |
| 3267 { | |
| 3268 my $interface = shift; | |
| 3269 my $hasCustom = shift; | |
| 3270 my $implClassName = GetImplName($interface); | |
| 3271 my $v8ClassName = GetV8ClassName($interface); | |
| 3272 | |
| 3273 my $code = "static void indexedPropertyGetterCallback(uint32_t index, const
v8::PropertyCallbackInfo<v8::Value>& info)\n"; | |
| 3274 $code .= "{\n"; | |
| 3275 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMIndexedProperty
\");\n"; | |
| 3276 if ($hasCustom) { | |
| 3277 $code .= " ${v8ClassName}::indexedPropertyGetterCustom(index, info);\
n"; | |
| 3278 } else { | |
| 3279 $code .= " ${implClassName}V8Internal::indexedPropertyGetter(index, i
nfo);\n"; | |
| 3280 } | |
| 3281 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; | |
| 3282 $code .= "}\n\n"; | |
| 3283 $implementation{nameSpaceInternal}->add($code); | |
| 3284 } | |
| 3285 | |
| 3286 sub GenerateImplementationIndexedPropertySetterCallback | |
| 3287 { | |
| 3288 my $interface = shift; | |
| 3289 my $hasCustom = shift; | |
| 3290 my $implClassName = GetImplName($interface); | |
| 3291 my $v8ClassName = GetV8ClassName($interface); | |
| 3292 | |
| 3293 my $code = "static void indexedPropertySetterCallback(uint32_t index, v8::Lo
cal<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; | |
| 3294 $code .= "{\n"; | |
| 3295 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMIndexedProperty
\");\n"; | |
| 3296 if ($hasCustom) { | |
| 3297 $code .= " ${v8ClassName}::indexedPropertySetterCustom(index, value,
info);\n"; | |
| 3298 } else { | |
| 3299 $code .= " ${implClassName}V8Internal::indexedPropertySetter(index, v
alue, info);\n"; | |
| 3300 } | |
| 3301 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; | |
| 3302 $code .= "}\n\n"; | |
| 3303 $implementation{nameSpaceInternal}->add($code); | |
| 3304 } | |
| 3305 | |
| 3306 sub GenerateImplementationIndexedPropertyDeleterCallback | |
| 3307 { | |
| 3308 my $interface = shift; | |
| 3309 my $hasCustom = shift; | |
| 3310 my $implClassName = GetImplName($interface); | |
| 3311 my $v8ClassName = GetV8ClassName($interface); | |
| 3312 | |
| 3313 my $code = "static void indexedPropertyDeleterCallback(uint32_t index, const
v8::PropertyCallbackInfo<v8::Boolean>& info)\n"; | |
| 3314 $code .= "{\n"; | |
| 3315 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMIndexedProperty
\");\n"; | |
| 3316 if ($hasCustom) { | |
| 3317 $code .= " ${v8ClassName}::indexedPropertyDeleterCustom(index, info);
\n"; | |
| 3318 } else { | |
| 3319 $code .= " ${implClassName}V8Internal::indexedPropertyDeleter(index,
info);\n"; | |
| 3320 } | |
| 3321 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; | |
| 3322 $code .= "}\n\n"; | |
| 3323 $implementation{nameSpaceInternal}->add($code); | |
| 3324 } | |
| 3325 | |
| 3326 sub GenerateImplementationIndexedPropertySetter | |
| 3327 { | |
| 3328 my $interface = shift; | |
| 3329 my $indexedSetterFunction = shift; | |
| 3330 my $implClassName = GetImplName($interface); | |
| 3331 my $v8ClassName = GetV8ClassName($interface); | |
| 3332 my $methodName = GetImplName($indexedSetterFunction); | |
| 3333 | |
| 3334 my $type = $indexedSetterFunction->parameters->[1]->type; | |
| 3335 my $raisesExceptions = $indexedSetterFunction->extendedAttributes->{"RaisesE
xception"}; | |
| 3336 my $treatNullAs = $indexedSetterFunction->parameters->[1]->extendedAttribute
s->{"TreatNullAs"}; | |
| 3337 my $treatUndefinedAs = $indexedSetterFunction->parameters->[1]->extendedAttr
ibutes->{"TreatUndefinedAs"}; | |
| 3338 my $code = "static void indexedPropertySetter(uint32_t index, v8::Local<v8::
Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; | |
| 3339 $code .= "{\n"; | |
| 3340 $code .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.H
older());\n"; | |
| 3341 $code .= JSValueToNativeStatement($indexedSetterFunction->parameters->[1]->t
ype, $indexedSetterFunction->extendedAttributes, "value", "propertyValue", "
", "info.GetIsolate()"); | |
| 3342 | |
| 3343 my $extraArguments = ""; | |
| 3344 if ($raisesExceptions) { | |
| 3345 $code .= " ExceptionCode ec = 0;\n"; | |
| 3346 $extraArguments = ", ec"; | |
| 3347 } | |
| 3348 my @conditions = (); | |
| 3349 my @statements = (); | |
| 3350 if ($treatNullAs && $treatNullAs ne "NullString") { | |
| 3351 push @conditions, "value->IsNull()"; | |
| 3352 push @statements, "collection->${treatNullAs}(index$extraArguments);"; | |
| 3353 } | |
| 3354 if ($treatUndefinedAs && $treatUndefinedAs ne "NullString") { | |
| 3355 push @conditions, "value->IsUndefined()"; | |
| 3356 push @statements, "collection->${treatUndefinedAs}(index$extraArguments)
;"; | |
| 3357 } | |
| 3358 push @conditions, ""; | |
| 3359 push @statements, "collection->${methodName}(index, propertyValue$extraArgum
ents);"; | |
| 3360 $code .= GenerateIfElseStatement("bool", "result", \@conditions, \@statement
s); | |
| 3361 | |
| 3362 $code .= " if (!result)\n"; | |
| 3363 $code .= " return;\n"; | |
| 3364 if ($raisesExceptions) { | |
| 3365 $code .= " if (ec) {\n"; | |
| 3366 $code .= " setDOMException(ec, info.GetIsolate());\n"; | |
| 3367 $code .= " return;\n"; | |
| 3368 $code .= " }\n"; | |
| 3369 } | |
| 3370 $code .= " v8SetReturnValue(info, value);\n"; | |
| 3371 $code .= "}\n\n"; | |
| 3372 $implementation{nameSpaceInternal}->add($code); | |
| 3373 } | |
| 3374 | |
| 3375 sub GenerateImplementationNamedPropertyAccessors | |
| 3376 { | |
| 3377 my $interface = shift; | |
| 3378 | |
| 3379 my $interfaceName = $interface->name; | |
| 3380 my $implClassName = GetImplName($interface); | |
| 3381 my $v8ClassName = GetV8ClassName($interface); | |
| 3382 | |
| 3383 my $namedGetterFunction = GetNamedGetterFunction($interface); | |
| 3384 if ($namedGetterFunction) { | |
| 3385 my $hasCustomNamedGetter = $namedGetterFunction->extendedAttributes->{"C
ustom"}; | |
| 3386 if (!$hasCustomNamedGetter) { | |
| 3387 GenerateImplementationNamedPropertyGetter($interface, $namedGetterFu
nction); | |
| 3388 } | |
| 3389 GenerateImplementationNamedPropertyGetterCallback($interface, $hasCustom
NamedGetter); | |
| 3390 } | |
| 3391 | |
| 3392 my $namedSetterFunction = GetNamedSetterFunction($interface); | |
| 3393 if ($namedSetterFunction) { | |
| 3394 my $hasCustomNamedSetter = $namedSetterFunction->extendedAttributes->{"C
ustom"}; | |
| 3395 if (!$hasCustomNamedSetter) { | |
| 3396 GenerateImplementationNamedPropertySetter($interface, $namedSetterFu
nction); | |
| 3397 } | |
| 3398 GenerateImplementationNamedPropertySetterCallback($interface, $hasCustom
NamedSetter); | |
| 3399 } | |
| 3400 | |
| 3401 my $namedDeleterFunction = GetNamedDeleterFunction($interface); | |
| 3402 if ($namedDeleterFunction) { | |
| 3403 my $hasCustomNamedDeleter = $namedDeleterFunction->extendedAttributes->{
"Custom"}; | |
| 3404 if (!$hasCustomNamedDeleter) { | |
| 3405 GenerateImplementationNamedPropertyDeleter($interface, $namedDeleter
Function); | |
| 3406 } | |
| 3407 GenerateImplementationNamedPropertyDeleterCallback($interface, $hasCusto
mNamedDeleter); | |
| 3408 } | |
| 3409 | |
| 3410 my $namedEnumeratorFunction = $namedGetterFunction && !$namedGetterFunction-
>extendedAttributes->{"NotEnumerable"}; | |
| 3411 if ($namedEnumeratorFunction) { | |
| 3412 my $hasCustomNamedEnumerator = $namedGetterFunction->extendedAttributes-
>{"CustomEnumerateProperty"}; | |
| 3413 if (!$hasCustomNamedEnumerator) { | |
| 3414 GenerateImplementationNamedPropertyEnumerator($interface); | |
| 3415 GenerateImplementationNamedPropertyQuery($interface); | |
| 3416 } | |
| 3417 GenerateImplementationNamedPropertyEnumeratorCallback($interface, $hasCu
stomNamedEnumerator); | |
| 3418 GenerateImplementationNamedPropertyQueryCallback($interface, $hasCustomN
amedEnumerator); | |
| 3419 } | |
| 3420 | |
| 3421 my $subCode = ""; | |
| 3422 if ($namedGetterFunction || $namedSetterFunction || $namedDeleterFunction ||
$namedEnumeratorFunction) { | |
| 3423 my $setOn = "Instance"; | |
| 3424 | |
| 3425 # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCa
llbacks) and it's used on Window | |
| 3426 # instead of deleters or enumerators. In addition, the getter should be
set on prototype template, to | |
| 3427 # get implementation straight out of the Window prototype regardless of
what prototype is actually set | |
| 3428 # on the object. | |
| 3429 if ($interfaceName eq "Window") { | |
| 3430 $setOn = "Prototype"; | |
| 3431 } | |
| 3432 | |
| 3433 $subCode .= " desc->${setOn}Template()->SetNamedPropertyHandler("; | |
| 3434 $subCode .= $namedGetterFunction ? "${implClassName}V8Internal::namedPro
pertyGetterCallback, " : "0, "; | |
| 3435 $subCode .= $namedSetterFunction ? "${implClassName}V8Internal::namedPro
pertySetterCallback, " : "0, "; | |
| 3436 $subCode .= $namedEnumeratorFunction ? "${implClassName}V8Internal::name
dPropertyQueryCallback, " : "0, "; | |
| 3437 $subCode .= $namedDeleterFunction ? "${implClassName}V8Internal::namedPr
opertyDeleterCallback, " : "0, "; | |
| 3438 $subCode .= $namedEnumeratorFunction ? "${implClassName}V8Internal::name
dPropertyEnumeratorCallback" : "0"; | |
| 3439 $subCode .= ");\n"; | |
| 3440 } | |
| 3441 | |
| 3442 return $subCode; | |
| 3443 } | |
| 3444 | |
| 3445 sub GenerateImplementationNamedPropertyGetterCallback | |
| 3446 { | |
| 3447 my $interface = shift; | |
| 3448 my $hasCustom = shift; | |
| 3449 my $implClassName = GetImplName($interface); | |
| 3450 my $v8ClassName = GetV8ClassName($interface); | |
| 3451 | |
| 3452 my $code = "static void namedPropertyGetterCallback(v8::Local<v8::String> na
me, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; | |
| 3453 $code .= "{\n"; | |
| 3454 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\"
);\n"; | |
| 3455 if ($hasCustom) { | |
| 3456 $code .= " ${v8ClassName}::namedPropertyGetterCustom(name, info);\n"; | |
| 3457 } else { | |
| 3458 $code .= " ${implClassName}V8Internal::namedPropertyGetter(name, info
);\n"; | |
| 3459 } | |
| 3460 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; | |
| 3461 $code .= "}\n\n"; | |
| 3462 $implementation{nameSpaceInternal}->add($code); | |
| 3463 } | |
| 3464 | |
| 3465 sub GenerateImplementationNamedPropertySetterCallback | |
| 3466 { | |
| 3467 my $interface = shift; | |
| 3468 my $hasCustom = shift; | |
| 3469 my $implClassName = GetImplName($interface); | |
| 3470 my $v8ClassName = GetV8ClassName($interface); | |
| 3471 | |
| 3472 my $code = "static void namedPropertySetterCallback(v8::Local<v8::String> na
me, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
\n"; | |
| 3473 $code .= "{\n"; | |
| 3474 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\"
);\n"; | |
| 3475 if ($hasCustom) { | |
| 3476 $code .= " ${v8ClassName}::namedPropertySetterCustom(name, value, inf
o);\n"; | |
| 3477 } else { | |
| 3478 $code .= " ${implClassName}V8Internal::namedPropertySetter(name, valu
e, info);\n"; | |
| 3479 } | |
| 3480 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; | |
| 3481 $code .= "}\n\n"; | |
| 3482 $implementation{nameSpaceInternal}->add($code); | |
| 3483 } | |
| 3484 | |
| 3485 sub GenerateImplementationNamedPropertyDeleterCallback | |
| 3486 { | |
| 3487 my $interface = shift; | |
| 3488 my $hasCustom = shift; | |
| 3489 my $implClassName = GetImplName($interface); | |
| 3490 my $v8ClassName = GetV8ClassName($interface); | |
| 3491 | |
| 3492 my $code = "static void namedPropertyDeleterCallback(v8::Local<v8::String> n
ame, const v8::PropertyCallbackInfo<v8::Boolean>& info)\n"; | |
| 3493 $code .= "{\n"; | |
| 3494 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\"
);\n"; | |
| 3495 if ($hasCustom) { | |
| 3496 $code .= " ${v8ClassName}::namedPropertyDeleterCustom(name, info);\n"
; | |
| 3497 } else { | |
| 3498 $code .= " ${implClassName}V8Internal::namedPropertyDeleter(name, inf
o);\n"; | |
| 3499 } | |
| 3500 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; | |
| 3501 $code .= "}\n\n"; | |
| 3502 $implementation{nameSpaceInternal}->add($code); | |
| 3503 } | |
| 3504 | |
| 3505 sub GenerateImplementationNamedPropertyEnumeratorCallback | |
| 3506 { | |
| 3507 my $interface = shift; | |
| 3508 my $hasCustom = shift; | |
| 3509 my $implClassName = GetImplName($interface); | |
| 3510 my $v8ClassName = GetV8ClassName($interface); | |
| 3511 | |
| 3512 my $code = "static void namedPropertyEnumeratorCallback(const v8::PropertyCa
llbackInfo<v8::Array>& info)\n"; | |
| 3513 $code .= "{\n"; | |
| 3514 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\"
);\n"; | |
| 3515 if ($hasCustom) { | |
| 3516 $code .= " ${v8ClassName}::namedPropertyEnumeratorCustom(info);\n"; | |
| 3517 } else { | |
| 3518 $code .= " ${implClassName}V8Internal::namedPropertyEnumerator(info);
\n"; | |
| 3519 } | |
| 3520 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; | |
| 3521 $code .= "}\n\n"; | |
| 3522 $implementation{nameSpaceInternal}->add($code); | |
| 3523 } | |
| 3524 | |
| 3525 sub GenerateImplementationNamedPropertyQueryCallback | |
| 3526 { | |
| 3527 my $interface = shift; | |
| 3528 my $hasCustom = shift; | |
| 3529 my $implClassName = GetImplName($interface); | |
| 3530 my $v8ClassName = GetV8ClassName($interface); | |
| 3531 | |
| 3532 my $code = "static void namedPropertyQueryCallback(v8::Local<v8::String> nam
e, const v8::PropertyCallbackInfo<v8::Integer>& info)\n"; | |
| 3533 $code .= "{\n"; | |
| 3534 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\"
);\n"; | |
| 3535 if ($hasCustom) { | |
| 3536 $code .= " ${v8ClassName}::namedPropertyQueryCustom(name, info);\n"; | |
| 3537 } else { | |
| 3538 $code .= " ${implClassName}V8Internal::namedPropertyQuery(name, info)
;\n"; | |
| 3539 } | |
| 3540 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; | |
| 3541 $code .= "}\n\n"; | |
| 3542 $implementation{nameSpaceInternal}->add($code); | |
| 3543 } | |
| 3544 | |
| 3545 sub GenerateMethodCall | |
| 3546 { | |
| 3547 my $returnType = shift; # string or UnionType | |
| 3548 my $returnName = shift; | |
| 3549 my $functionExpression = shift; | |
| 3550 my $firstArgument = shift; | |
| 3551 my $raisesExceptions = shift; | |
| 3552 | |
| 3553 my @arguments = (); | |
| 3554 push @arguments, $firstArgument; | |
| 3555 if ($raisesExceptions) { | |
| 3556 push @arguments, "ec"; | |
| 3557 } | |
| 3558 | |
| 3559 if (IsUnionType($returnType)) { | |
| 3560 my $code = ""; | |
| 3561 my @extraArguments = (); | |
| 3562 for my $i (0..scalar(@{$returnType->unionMemberTypes})-1) { | |
| 3563 my $unionMemberType = $returnType->unionMemberTypes->[$i]; | |
| 3564 my $nativeType = GetNativeType($unionMemberType); | |
| 3565 my $unionMemberVariable = $returnName . $i; | |
| 3566 my $unionMemberEnabledVariable = $returnName . $i . "Enabled"; | |
| 3567 $code .= " bool ${unionMemberEnabledVariable} = false;\n"; | |
| 3568 $code .= " ${nativeType} ${unionMemberVariable};\n"; | |
| 3569 push @extraArguments, $unionMemberEnabledVariable; | |
| 3570 push @extraArguments, $unionMemberVariable; | |
| 3571 } | |
| 3572 push @arguments, @extraArguments; | |
| 3573 $code .= " ${functionExpression}(" . (join ", ", @arguments) . ");"; | |
| 3574 return $code; | |
| 3575 } else { | |
| 3576 my $nativeType = GetNativeType($returnType); | |
| 3577 return " ${nativeType} element = ${functionExpression}(" . (join ", "
, @arguments) . ");" | |
| 3578 } | |
| 3579 } | |
| 3580 | |
| 3581 sub GenerateImplementationNamedPropertyGetter | |
| 3582 { | |
| 3583 my $interface = shift; | |
| 3584 my $namedGetterFunction = shift; | |
| 3585 my $implClassName = GetImplName($interface); | |
| 3586 my $v8ClassName = GetV8ClassName($interface); | |
| 3587 my $methodName = GetImplName($namedGetterFunction); | |
| 3588 | |
| 3589 my $returnType = $namedGetterFunction->type; | |
| 3590 my $isNull = GenerateIsNullExpression($returnType, "element"); | |
| 3591 my $nativeValue = "element"; | |
| 3592 $nativeValue .= ".release()" if (IsRefPtrType($returnType)); | |
| 3593 my $returnJSValueCode = NativeToJSValue($namedGetterFunction->type, $namedGe
tterFunction->extendedAttributes, $nativeValue, " ", "", "info.Holder()", "in
fo.GetIsolate()", "info", "collection", "", "", "return"); | |
| 3594 my $raisesExceptions = $namedGetterFunction->extendedAttributes->{"RaisesExc
eption"}; | |
| 3595 my $methodCallCode = GenerateMethodCall($returnType, "element", "collection-
>${methodName}", "propertyName", $raisesExceptions); | |
| 3596 | |
| 3597 my $code = "static void namedPropertyGetter(v8::Local<v8::String> name, cons
t v8::PropertyCallbackInfo<v8::Value>& info)\n"; | |
| 3598 $code .= "{\n"; | |
| 3599 if (!$namedGetterFunction->extendedAttributes->{"OverrideBuiltins"}) { | |
| 3600 $code .= " if (!info.Holder()->GetRealNamedPropertyInPrototypeChain(n
ame).IsEmpty())\n"; | |
| 3601 $code .= " return;\n"; | |
| 3602 $code .= " if (info.Holder()->HasRealNamedCallbackProperty(name))\n"; | |
| 3603 $code .= " return;\n"; | |
| 3604 $code .= " if (info.Holder()->HasRealNamedProperty(name))\n"; | |
| 3605 $code .= " return;\n"; | |
| 3606 } | |
| 3607 $code .= "\n"; | |
| 3608 $code .= " ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder()));\n"; | |
| 3609 $code .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.H
older());\n"; | |
| 3610 $code .= " AtomicString propertyName = toWebCoreAtomicString(name);\n"; | |
| 3611 if ($raisesExceptions) { | |
| 3612 $code .= " ExceptionCode ec = 0;\n"; | |
| 3613 } | |
| 3614 $code .= $methodCallCode . "\n"; | |
| 3615 if ($raisesExceptions) { | |
| 3616 $code .= " if (ec) {\n"; | |
| 3617 $code .= " setDOMException(ec, info.GetIsolate());\n"; | |
| 3618 $code .= " return;\n"; | |
| 3619 $code .= " }\n"; | |
| 3620 } | |
| 3621 if (IsUnionType($returnType)) { | |
| 3622 $code .= "${returnJSValueCode}\n"; | |
| 3623 $code .= " return;\n"; | |
| 3624 } else { | |
| 3625 $code .= " if (${isNull})\n"; | |
| 3626 $code .= " return;\n"; | |
| 3627 $code .= $returnJSValueCode . "\n"; | |
| 3628 } | |
| 3629 $code .= "}\n\n"; | |
| 3630 $implementation{nameSpaceInternal}->add($code); | |
| 3631 } | |
| 3632 | |
| 3633 sub GenerateImplementationNamedPropertySetter | |
| 3634 { | |
| 3635 my $interface = shift; | |
| 3636 my $namedSetterFunction = shift; | |
| 3637 my $implClassName = GetImplName($interface); | |
| 3638 my $v8ClassName = GetV8ClassName($interface); | |
| 3639 my $methodName = GetImplName($namedSetterFunction); | |
| 3640 | |
| 3641 my $raisesExceptions = $namedSetterFunction->extendedAttributes->{"RaisesExc
eption"}; | |
| 3642 my $treatNullAs = $namedSetterFunction->parameters->[1]->extendedAttributes-
>{"TreatNullAs"}; | |
| 3643 my $treatUndefinedAs = $namedSetterFunction->parameters->[1]->extendedAttrib
utes->{"TreatUndefinedAs"}; | |
| 3644 | |
| 3645 my $code = "static void namedPropertySetter(v8::Local<v8::String> name, v8::
Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; | |
| 3646 $code .= "{\n"; | |
| 3647 if (!$namedSetterFunction->extendedAttributes->{"OverrideBuiltins"}) { | |
| 3648 $code .= " if (!info.Holder()->GetRealNamedPropertyInPrototypeChain(n
ame).IsEmpty())\n"; | |
| 3649 $code .= " return;\n"; | |
| 3650 $code .= " if (info.Holder()->HasRealNamedCallbackProperty(name))\n"; | |
| 3651 $code .= " return;\n"; | |
| 3652 $code .= " if (info.Holder()->HasRealNamedProperty(name))\n"; | |
| 3653 $code .= " return;\n"; | |
| 3654 } | |
| 3655 $code .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.H
older());\n"; | |
| 3656 $code .= JSValueToNativeStatement($namedSetterFunction->parameters->[0]->typ
e, $namedSetterFunction->extendedAttributes, "name", "propertyName", " ", "in
fo.GetIsolate()"); | |
| 3657 $code .= JSValueToNativeStatement($namedSetterFunction->parameters->[1]->typ
e, $namedSetterFunction->extendedAttributes, "value", "propertyValue", " ", "
info.GetIsolate()"); | |
| 3658 my $extraArguments = ""; | |
| 3659 if ($raisesExceptions) { | |
| 3660 $code .= " ExceptionCode ec = 0;\n"; | |
| 3661 $extraArguments = ", ec"; | |
| 3662 } | |
| 3663 | |
| 3664 my @conditions = (); | |
| 3665 my @statements = (); | |
| 3666 if ($treatNullAs && $treatNullAs ne "NullString") { | |
| 3667 push @conditions, "value->IsNull()"; | |
| 3668 push @statements, "collection->${treatNullAs}(propertyName$extraArgument
s);"; | |
| 3669 } | |
| 3670 if ($treatUndefinedAs && $treatUndefinedAs ne "NullString") { | |
| 3671 push @conditions, "value->IsUndefined()"; | |
| 3672 push @statements, "collection->${treatUndefinedAs}(propertyName$extraArg
uments);"; | |
| 3673 } | |
| 3674 push @conditions, ""; | |
| 3675 push @statements, "collection->${methodName}(propertyName, propertyValue$ext
raArguments);"; | |
| 3676 $code .= GenerateIfElseStatement("bool", "result", \@conditions, \@statement
s); | |
| 3677 | |
| 3678 $code .= " if (!result)\n"; | |
| 3679 $code .= " return;\n"; | |
| 3680 if ($raisesExceptions) { | |
| 3681 $code .= " if (ec) {\n"; | |
| 3682 $code .= " setDOMException(ec, info.GetIsolate());\n"; | |
| 3683 $code .= " return;\n"; | |
| 3684 $code .= " }\n"; | |
| 3685 } | |
| 3686 $code .= " v8SetReturnValue(info, value);\n"; | |
| 3687 $code .= "}\n\n"; | |
| 3688 $implementation{nameSpaceInternal}->add($code); | |
| 3689 } | |
| 3690 | |
| 3691 sub GenerateImplementationIndexedPropertyDeleter | |
| 3692 { | |
| 3693 my $interface = shift; | |
| 3694 my $indexedDeleterFunction = shift; | |
| 3695 my $implClassName = GetImplName($interface); | |
| 3696 my $v8ClassName = GetV8ClassName($interface); | |
| 3697 my $methodName = GetImplName($indexedDeleterFunction); | |
| 3698 | |
| 3699 my $raisesExceptions = $indexedDeleterFunction->extendedAttributes->{"Raises
Exception"}; | |
| 3700 | |
| 3701 my $code = "static void indexedPropertyDeleter(unsigned index, const v8::Pro
pertyCallbackInfo<v8::Boolean>& info)\n"; | |
| 3702 $code .= "{\n"; | |
| 3703 $code .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.H
older());\n"; | |
| 3704 my $extraArguments = ""; | |
| 3705 if ($raisesExceptions) { | |
| 3706 $code .= " ExceptionCode ec = 0;\n"; | |
| 3707 $extraArguments = ", ec"; | |
| 3708 } | |
| 3709 $code .= " bool result = collection->${methodName}(index$extraArguments);
\n"; | |
| 3710 if ($raisesExceptions) { | |
| 3711 $code .= " if (ec) {\n"; | |
| 3712 $code .= " setDOMException(ec, info.GetIsolate());\n"; | |
| 3713 $code .= " return;\n"; | |
| 3714 $code .= " }\n"; | |
| 3715 } | |
| 3716 $code .= " return v8SetReturnValueBool(info, result);\n"; | |
| 3717 $code .= "}\n\n"; | |
| 3718 $implementation{nameSpaceInternal}->add($code); | |
| 3719 } | |
| 3720 | |
| 3721 sub GenerateImplementationNamedPropertyDeleter | |
| 3722 { | |
| 3723 my $interface = shift; | |
| 3724 my $namedDeleterFunction = shift; | |
| 3725 my $implClassName = GetImplName($interface); | |
| 3726 my $v8ClassName = GetV8ClassName($interface); | |
| 3727 my $methodName = GetImplName($namedDeleterFunction); | |
| 3728 | |
| 3729 my $raisesExceptions = $namedDeleterFunction->extendedAttributes->{"RaisesEx
ception"}; | |
| 3730 | |
| 3731 my $code = "static void namedPropertyDeleter(v8::Local<v8::String> name, con
st v8::PropertyCallbackInfo<v8::Boolean>& info)\n"; | |
| 3732 $code .= "{\n"; | |
| 3733 $code .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.H
older());\n"; | |
| 3734 $code .= " AtomicString propertyName = toWebCoreAtomicString(name);\n"; | |
| 3735 my $extraArguments = ""; | |
| 3736 if ($raisesExceptions) { | |
| 3737 $code .= " ExceptionCode ec = 0;\n"; | |
| 3738 $extraArguments = ", ec"; | |
| 3739 } | |
| 3740 $code .= " bool result = collection->${methodName}(propertyName$extraArgu
ments);\n"; | |
| 3741 if ($raisesExceptions) { | |
| 3742 $code .= " if (ec) {\n"; | |
| 3743 $code .= " setDOMException(ec, info.GetIsolate());\n"; | |
| 3744 $code .= " return;\n"; | |
| 3745 $code .= " }\n"; | |
| 3746 } | |
| 3747 $code .= " return v8SetReturnValueBool(info, result);\n"; | |
| 3748 $code .= "}\n\n"; | |
| 3749 $implementation{nameSpaceInternal}->add($code); | |
| 3750 } | |
| 3751 | |
| 3752 sub GenerateImplementationNamedPropertyEnumerator | |
| 3753 { | |
| 3754 my $interface = shift; | |
| 3755 my $implClassName = GetImplName($interface); | |
| 3756 my $v8ClassName = GetV8ClassName($interface); | |
| 3757 | |
| 3758 $implementation{nameSpaceInternal}->add(<<END); | |
| 3759 static void namedPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& i
nfo) | |
| 3760 { | |
| 3761 ExceptionCode ec = 0; | |
| 3762 ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder()); | |
| 3763 Vector<String> names; | |
| 3764 collection->namedPropertyEnumerator(names, ec); | |
| 3765 if (ec) { | |
| 3766 setDOMException(ec, info.GetIsolate()); | |
| 3767 return; | |
| 3768 } | |
| 3769 v8::Handle<v8::Array> v8names = v8::Array::New(names.size()); | |
| 3770 for (size_t i = 0; i < names.size(); ++i) | |
| 3771 v8names->Set(v8::Integer::New(i, info.GetIsolate()), v8String(names[i],
info.GetIsolate())); | |
| 3772 v8SetReturnValue(info, v8names); | |
| 3773 } | |
| 3774 | |
| 3775 END | |
| 3776 } | |
| 3777 | |
| 3778 sub GenerateImplementationNamedPropertyQuery | |
| 3779 { | |
| 3780 my $interface = shift; | |
| 3781 my $implClassName = GetImplName($interface); | |
| 3782 my $v8ClassName = GetV8ClassName($interface); | |
| 3783 | |
| 3784 $implementation{nameSpaceInternal}->add(<<END); | |
| 3785 static void namedPropertyQuery(v8::Local<v8::String> name, const v8::PropertyCal
lbackInfo<v8::Integer>& info) | |
| 3786 { | |
| 3787 ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder()); | |
| 3788 AtomicString propertyName = toWebCoreAtomicString(name); | |
| 3789 ExceptionCode ec = 0; | |
| 3790 bool result = collection->namedPropertyQuery(propertyName, ec); | |
| 3791 if (ec) { | |
| 3792 setDOMException(ec, info.GetIsolate()); | |
| 3793 return; | |
| 3794 } | |
| 3795 if (!result) | |
| 3796 return; | |
| 3797 v8SetReturnValueInt(info, v8::None); | |
| 3798 } | |
| 3799 | |
| 3800 END | |
| 3801 } | |
| 3802 | |
| 3803 sub GenerateImplementationLegacyCall | |
| 3804 { | |
| 3805 my $interface = shift; | |
| 3806 my $code = ""; | |
| 3807 | |
| 3808 my $v8ClassName = GetV8ClassName($interface); | |
| 3809 | |
| 3810 if ($interface->extendedAttributes->{"CustomLegacyCall"}) { | |
| 3811 $code .= " desc->InstanceTemplate()->SetCallAsFunctionHandler(${v8Cla
ssName}::legacyCallCustom);\n"; | |
| 3812 } | |
| 3813 return $code; | |
| 3814 } | |
| 3815 | |
| 3816 sub GenerateImplementationMasqueradesAsUndefined | |
| 3817 { | |
| 3818 my $interface = shift; | |
| 3819 my $code = ""; | |
| 3820 | |
| 3821 if ($interface->extendedAttributes->{"MasqueradesAsUndefined"}) | |
| 3822 { | |
| 3823 $code .= " desc->InstanceTemplate()->MarkAsUndetectable();\n"; | |
| 3824 } | |
| 3825 return $code; | |
| 3826 } | |
| 3827 | |
| 3828 sub GenerateImplementation | |
| 3829 { | |
| 3830 my $object = shift; | |
| 3831 my $interface = shift; | |
| 3832 my $interfaceName = $interface->name; | |
| 3833 my $implClassName = GetImplName($interface); | |
| 3834 my $v8ClassName = GetV8ClassName($interface); | |
| 3835 my $nativeType = GetNativeTypeForConversions($interface); | |
| 3836 | |
| 3837 AddToImplIncludes("bindings/v8/V8Binding.h"); | |
| 3838 AddToImplIncludes("bindings/v8/V8DOMWrapper.h"); | |
| 3839 AddToImplIncludes("core/dom/ContextFeatures.h"); | |
| 3840 AddToImplIncludes("core/dom/Document.h"); | |
| 3841 AddToImplIncludes("RuntimeEnabledFeatures.h"); | |
| 3842 AddToImplIncludes("core/platform/chromium/TraceEvent.h"); | |
| 3843 | |
| 3844 AddIncludesForType($interfaceName); | |
| 3845 | |
| 3846 my $toActiveDOMObject = InheritsExtendedAttribute($interface, "ActiveDOMObje
ct") ? "${v8ClassName}::toActiveDOMObject" : "0"; | |
| 3847 my $toEventTarget = InheritsExtendedAttribute($interface, "EventTarget") ? "
${v8ClassName}::toEventTarget" : "0"; | |
| 3848 my $rootForGC = NeedsOpaqueRootForGC($interface) ? "${v8ClassName}::opaqueRo
otForGC" : "0"; | |
| 3849 | |
| 3850 # Find the super descriptor. | |
| 3851 my $parentClass = ""; | |
| 3852 my $parentClassTemplate = ""; | |
| 3853 if ($interface->parent) { | |
| 3854 my $parent = $interface->parent; | |
| 3855 AddToImplIncludes("V8${parent}.h"); | |
| 3856 $parentClass = "V8" . $parent; | |
| 3857 $parentClassTemplate = $parentClass . "::GetTemplate(isolate, currentWor
ldType)"; | |
| 3858 } | |
| 3859 | |
| 3860 my $parentClassInfo = $parentClass ? "&${parentClass}::info" : "0"; | |
| 3861 my $WrapperTypePrototype = $interface->isException ? "WrapperTypeErrorProtot
ype" : "WrapperTypeObjectPrototype"; | |
| 3862 | |
| 3863 if (!IsSVGTypeNeedingTearOff($interfaceName)) { | |
| 3864 my $code = <<END; | |
| 3865 static void initializeScriptWrappableForInterface(${implClassName}* object) | |
| 3866 { | |
| 3867 if (ScriptWrappable::wrapperCanBeStoredInObject(object)) | |
| 3868 ScriptWrappable::setTypeInfoInObject(object, &${v8ClassName}::info); | |
| 3869 else | |
| 3870 ASSERT_NOT_REACHED(); | |
| 3871 } | |
| 3872 | |
| 3873 } // namespace WebCore | |
| 3874 | |
| 3875 // In ScriptWrappable::init, the use of a local function declaration has an issu
e on Windows: | |
| 3876 // the local declaration does not pick up the surrounding namespace. Therefore,
we provide this function | |
| 3877 // in the global namespace. | |
| 3878 // (More info on the MSVC bug here: http://connect.microsoft.com/VisualStudio/fe
edback/details/664619/the-namespace-of-local-function-declarations-in-c) | |
| 3879 END | |
| 3880 | |
| 3881 if (GetNamespaceForInterface($interface) eq "WebCore") { | |
| 3882 $code .= "void webCoreInitializeScriptWrappableForInterface(WebCore::${i
mplClassName}* object)\n"; | |
| 3883 } else { | |
| 3884 $code .= "void webCoreInitializeScriptWrappableForInterface(${implClassN
ame}* object)\n"; | |
| 3885 } | |
| 3886 | |
| 3887 $code .= <<END; | |
| 3888 { | |
| 3889 WebCore::initializeScriptWrappableForInterface(object); | |
| 3890 } | |
| 3891 | |
| 3892 namespace WebCore { | |
| 3893 END | |
| 3894 $implementation{nameSpaceWebCore}->addHeader($code); | |
| 3895 } | |
| 3896 | |
| 3897 my $code = "WrapperTypeInfo ${v8ClassName}::info = { ${v8ClassName}::GetTemp
late, ${v8ClassName}::derefObject, $toActiveDOMObject, $toEventTarget, "; | |
| 3898 $code .= "$rootForGC, ${v8ClassName}::installPerContextPrototypeProperties,
$parentClassInfo, $WrapperTypePrototype };\n"; | |
| 3899 $implementation{nameSpaceWebCore}->addHeader($code); | |
| 3900 | |
| 3901 $implementation{nameSpaceInternal}->add("template <typename T> void V8_USE(T
) { }\n\n"); | |
| 3902 | |
| 3903 my $hasConstructors = 0; | |
| 3904 my $hasReplaceable = 0; | |
| 3905 | |
| 3906 # Generate property accessors for attributes. | |
| 3907 for (my $index = 0; $index < @{$interface->attributes}; $index++) { | |
| 3908 my $attribute = @{$interface->attributes}[$index]; | |
| 3909 my $attrType = $attribute->type; | |
| 3910 my $attrExt = $attribute->extendedAttributes; | |
| 3911 | |
| 3912 # Generate special code for the constructor attributes. | |
| 3913 if ($attrType =~ /Constructor$/) { | |
| 3914 if (!HasCustomGetter($attrExt)) { | |
| 3915 $hasConstructors = 1; | |
| 3916 } | |
| 3917 next; | |
| 3918 } | |
| 3919 | |
| 3920 if ($attrType eq "EventListener" && $interfaceName eq "Window") { | |
| 3921 $attrExt->{"OnProto"} = 1; | |
| 3922 } | |
| 3923 | |
| 3924 if ($attrType eq "SerializedScriptValue") { | |
| 3925 AddToImplIncludes("bindings/v8/SerializedScriptValue.h"); | |
| 3926 } | |
| 3927 | |
| 3928 GenerateNormalAttrGetter($attribute, $interface, ""); | |
| 3929 GenerateNormalAttrGetterCallback($attribute, $interface, ""); | |
| 3930 if ($attrExt->{"PerWorldBindings"}) { | |
| 3931 GenerateNormalAttrGetter($attribute, $interface, "ForMainWorld"); | |
| 3932 GenerateNormalAttrGetterCallback($attribute, $interface, "ForMainWor
ld"); | |
| 3933 } | |
| 3934 if (!HasCustomSetter($attrExt) && $attrExt->{"Replaceable"}) { | |
| 3935 $hasReplaceable = 1; | |
| 3936 } elsif (!IsReadonly($attribute)) { | |
| 3937 GenerateNormalAttrSetter($attribute, $interface, ""); | |
| 3938 GenerateNormalAttrSetterCallback($attribute, $interface, ""); | |
| 3939 if ($attrExt->{"PerWorldBindings"}) { | |
| 3940 GenerateNormalAttrSetter($attribute, $interface, "ForMainWorld"); | |
| 3941 GenerateNormalAttrSetterCallback($attribute, $interface, "ForMainW
orld"); | |
| 3942 } | |
| 3943 } | |
| 3944 } | |
| 3945 | |
| 3946 if ($hasConstructors) { | |
| 3947 GenerateConstructorGetter($interface); | |
| 3948 } | |
| 3949 | |
| 3950 if ($hasConstructors || $hasReplaceable) { | |
| 3951 GenerateReplaceableAttrSetter($interface); | |
| 3952 GenerateReplaceableAttrSetterCallback($interface); | |
| 3953 } | |
| 3954 | |
| 3955 if (NeedsOpaqueRootForGC($interface)) { | |
| 3956 GenerateOpaqueRootForGC($interface); | |
| 3957 } | |
| 3958 | |
| 3959 if ($interface->extendedAttributes->{"CheckSecurity"} && $interface->name ne
"Window") { | |
| 3960 GenerateSecurityCheckFunctions($interface); | |
| 3961 } | |
| 3962 | |
| 3963 if (IsConstructorTemplate($interface, "TypedArray")) { | |
| 3964 my ($nativeType, $arrayType) = GetNativeTypeOfTypedArray($interface); | |
| 3965 $implementation{nameSpaceWebCore}->add(<<END); | |
| 3966 v8::Handle<v8::Object> wrap($implClassName* impl, v8::Handle<v8::Object> creatio
nContext, v8::Isolate* isolate) | |
| 3967 { | |
| 3968 ASSERT(impl); | |
| 3969 v8::Handle<v8::Object> wrapper = ${v8ClassName}::createWrapper(impl, creatio
nContext, isolate); | |
| 3970 if (!wrapper.IsEmpty()) | |
| 3971 wrapper->SetIndexedPropertiesToExternalArrayData(impl->baseAddress(), $a
rrayType, impl->length()); | |
| 3972 return wrapper; | |
| 3973 } | |
| 3974 | |
| 3975 END | |
| 3976 } | |
| 3977 | |
| 3978 my @enabledPerContextFunctions; | |
| 3979 my @normalFunctions; | |
| 3980 my $needsDomainSafeFunctionSetter = 0; | |
| 3981 # Generate methods for functions. | |
| 3982 foreach my $function (@{$interface->functions}) { | |
| 3983 next if $function->name eq ""; | |
| 3984 GenerateFunction($function, $interface, ""); | |
| 3985 if ($function->extendedAttributes->{"PerWorldBindings"}) { | |
| 3986 GenerateFunction($function, $interface, "ForMainWorld"); | |
| 3987 } | |
| 3988 if ($function->{overloadIndex} == @{$function->{overloads}}) { | |
| 3989 if ($function->{overloadIndex} > 1) { | |
| 3990 GenerateOverloadedFunction($function, $interface, ""); | |
| 3991 if ($function->extendedAttributes->{"PerWorldBindings"}) { | |
| 3992 GenerateOverloadedFunction($function, $interface, "ForMainWo
rld"); | |
| 3993 } | |
| 3994 } | |
| 3995 GenerateFunctionCallback($function, $interface, ""); | |
| 3996 if ($function->extendedAttributes->{"PerWorldBindings"}) { | |
| 3997 GenerateFunctionCallback($function, $interface, "ForMainWorld"); | |
| 3998 } | |
| 3999 } | |
| 4000 | |
| 4001 # If the function does not need domain security check, we need to | |
| 4002 # generate an access getter that returns different function objects | |
| 4003 # for different calling context. | |
| 4004 if ($interface->extendedAttributes->{"CheckSecurity"} && $function->exte
ndedAttributes->{"DoNotCheckSecurity"}) { | |
| 4005 if (!HasCustomMethod($function->extendedAttributes) || $function->{o
verloadIndex} == 1) { | |
| 4006 GenerateDomainSafeFunctionGetter($function, $interface); | |
| 4007 if (!$function->extendedAttributes->{"ReadOnly"}) { | |
| 4008 $needsDomainSafeFunctionSetter = 1; | |
| 4009 } | |
| 4010 } | |
| 4011 } | |
| 4012 | |
| 4013 # Separate out functions that are enabled per context so we can process
them specially. | |
| 4014 if ($function->extendedAttributes->{"EnabledPerContext"}) { | |
| 4015 push(@enabledPerContextFunctions, $function); | |
| 4016 } else { | |
| 4017 push(@normalFunctions, $function); | |
| 4018 } | |
| 4019 } | |
| 4020 | |
| 4021 if ($needsDomainSafeFunctionSetter) { | |
| 4022 GenerateDomainSafeFunctionSetter($interface); | |
| 4023 } | |
| 4024 | |
| 4025 # Attributes | |
| 4026 my $attributes = $interface->attributes; | |
| 4027 | |
| 4028 # For the Window interface we partition the attributes into the | |
| 4029 # ones that disallows shadowing and the rest. | |
| 4030 my @disallowsShadowing; | |
| 4031 # Also separate out attributes that are enabled at runtime so we can process
them specially. | |
| 4032 my @enabledAtRuntimeAttributes; | |
| 4033 my @enabledPerContextAttributes; | |
| 4034 my @normalAttributes; | |
| 4035 foreach my $attribute (@$attributes) { | |
| 4036 | |
| 4037 if ($interfaceName eq "Window" && $attribute->extendedAttributes->{"Unfo
rgeable"}) { | |
| 4038 push(@disallowsShadowing, $attribute); | |
| 4039 } elsif ($attribute->extendedAttributes->{"EnabledAtRuntime"} || $attrib
ute->extendedAttributes->{"EnabledPerContext"}) { | |
| 4040 if ($attribute->extendedAttributes->{"EnabledPerContext"}) { | |
| 4041 push(@enabledPerContextAttributes, $attribute); | |
| 4042 } | |
| 4043 if ($attribute->extendedAttributes->{"EnabledAtRuntime"}) { | |
| 4044 push(@enabledAtRuntimeAttributes, $attribute); | |
| 4045 } | |
| 4046 } else { | |
| 4047 push(@normalAttributes, $attribute); | |
| 4048 } | |
| 4049 } | |
| 4050 AddToImplIncludes("bindings/v8/V8DOMConfiguration.h"); | |
| 4051 $attributes = \@normalAttributes; | |
| 4052 # Put the attributes that disallow shadowing on the shadow object. | |
| 4053 if (@disallowsShadowing) { | |
| 4054 my $code = ""; | |
| 4055 $code .= "static const V8DOMConfiguration::BatchedAttribute shadowAttrs[
] = {\n"; | |
| 4056 $code .= GenerateBatchedAttributeData($interface, \@disallowsShadowing); | |
| 4057 $code .= "};\n\n"; | |
| 4058 $implementation{nameSpaceWebCore}->add($code); | |
| 4059 } | |
| 4060 | |
| 4061 my $has_attributes = 0; | |
| 4062 if (@$attributes) { | |
| 4063 $has_attributes = 1; | |
| 4064 my $code = ""; | |
| 4065 $code .= "static const V8DOMConfiguration::BatchedAttribute ${v8ClassNam
e}Attrs[] = {\n"; | |
| 4066 $code .= GenerateBatchedAttributeData($interface, $attributes); | |
| 4067 $code .= "};\n\n"; | |
| 4068 $implementation{nameSpaceWebCore}->add($code); | |
| 4069 } | |
| 4070 | |
| 4071 # Setup table of standard callback functions | |
| 4072 my $num_callbacks = 0; | |
| 4073 my $has_callbacks = 0; | |
| 4074 $code = ""; | |
| 4075 foreach my $function (@normalFunctions) { | |
| 4076 # Only one table entry is needed for overloaded methods: | |
| 4077 next if $function->{overloadIndex} > 1; | |
| 4078 # Don't put any nonstandard functions into this table: | |
| 4079 next if !IsStandardFunction($interface, $function); | |
| 4080 next if $function->name eq ""; | |
| 4081 if (!$has_callbacks) { | |
| 4082 $has_callbacks = 1; | |
| 4083 $code .= "static const V8DOMConfiguration::BatchedMethod ${v8ClassNa
me}Methods[] = {\n"; | |
| 4084 } | |
| 4085 my $name = $function->name; | |
| 4086 my $methodForMainWorld = "0"; | |
| 4087 if ($function->extendedAttributes->{"PerWorldBindings"}) { | |
| 4088 $methodForMainWorld = "${implClassName}V8Internal::${name}MethodCall
backForMainWorld"; | |
| 4089 } | |
| 4090 my $functionLength = GetFunctionLength($function); | |
| 4091 my $conditionalString = GenerateConditionalString($function); | |
| 4092 $code .= "#if ${conditionalString}\n" if $conditionalString; | |
| 4093 $code .= <<END; | |
| 4094 {"$name", ${implClassName}V8Internal::${name}MethodCallback, ${methodForMain
World}, ${functionLength}}, | |
| 4095 END | |
| 4096 $code .= "#endif\n" if $conditionalString; | |
| 4097 $num_callbacks++; | |
| 4098 } | |
| 4099 $code .= "};\n\n" if $has_callbacks; | |
| 4100 $implementation{nameSpaceWebCore}->add($code); | |
| 4101 | |
| 4102 # Setup constants | |
| 4103 my $has_constants = 0; | |
| 4104 my @constantsEnabledAtRuntime; | |
| 4105 $code = ""; | |
| 4106 if (@{$interface->constants}) { | |
| 4107 $has_constants = 1; | |
| 4108 $code .= "static const V8DOMConfiguration::BatchedConstant ${v8ClassName
}Consts[] = {\n"; | |
| 4109 } | |
| 4110 foreach my $constant (@{$interface->constants}) { | |
| 4111 my $name = $constant->name; | |
| 4112 my $value = $constant->value; | |
| 4113 my $attrExt = $constant->extendedAttributes; | |
| 4114 my $implementedBy = $attrExt->{"ImplementedBy"}; | |
| 4115 if ($implementedBy) { | |
| 4116 my $implementedByImplName = GetImplNameFromImplementedBy($implemente
dBy); | |
| 4117 AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implement
edByImplName)); | |
| 4118 } | |
| 4119 if ($attrExt->{"EnabledAtRuntime"}) { | |
| 4120 push(@constantsEnabledAtRuntime, $constant); | |
| 4121 } else { | |
| 4122 my $conditionalString = GenerateConditionalString($constant); | |
| 4123 $code .= "#if ${conditionalString}\n" if $conditionalString; | |
| 4124 # If the value we're dealing with is a hex number, preprocess it int
o a signed integer | |
| 4125 # here, rather than running static_cast<signed int> in the generated
code. | |
| 4126 if (substr($value, 0, 2) eq "0x") { | |
| 4127 $value = unpack('i', pack('I', hex($value))); | |
| 4128 } | |
| 4129 $code .= <<END; | |
| 4130 {"${name}", $value}, | |
| 4131 END | |
| 4132 $code .= "#endif\n" if $conditionalString; | |
| 4133 } | |
| 4134 } | |
| 4135 if ($has_constants) { | |
| 4136 $code .= "};\n\n"; | |
| 4137 $code .= join "", GenerateCompileTimeCheckForEnumsIfNeeded($interface); | |
| 4138 $implementation{nameSpaceWebCore}->add($code); | |
| 4139 } | |
| 4140 | |
| 4141 if (!HasCustomConstructor($interface)) { | |
| 4142 if ($interface->extendedAttributes->{"NamedConstructor"}) { | |
| 4143 GenerateNamedConstructor(@{$interface->constructors}[0], $interface)
; | |
| 4144 } elsif ($interface->extendedAttributes->{"Constructor"}) { | |
| 4145 GenerateConstructor($interface); | |
| 4146 } elsif (IsConstructorTemplate($interface, "Event")) { | |
| 4147 GenerateEventConstructor($interface); | |
| 4148 } elsif (IsConstructorTemplate($interface, "TypedArray")) { | |
| 4149 GenerateTypedArrayConstructor($interface); | |
| 4150 } | |
| 4151 } | |
| 4152 if (IsConstructable($interface)) { | |
| 4153 GenerateConstructorCallback($interface); | |
| 4154 } | |
| 4155 | |
| 4156 my $access_check = ""; | |
| 4157 if ($interface->extendedAttributes->{"CheckSecurity"} && $interfaceName ne "
Window") { | |
| 4158 $access_check = "instance->SetAccessCheckCallbacks(${implClassName}V8Int
ernal::namedSecurityCheck, ${implClassName}V8Internal::indexedSecurityCheck, v8:
:External::New(&${v8ClassName}::info));"; | |
| 4159 } | |
| 4160 | |
| 4161 # For the Window interface, generate the shadow object template | |
| 4162 # configuration method. | |
| 4163 if ($interfaceName eq "Window") { | |
| 4164 $implementation{nameSpaceWebCore}->add(<<END); | |
| 4165 static void ConfigureShadowObjectTemplate(v8::Handle<v8::ObjectTemplate> templ,
v8::Isolate* isolate, WrapperWorldType currentWorldType) | |
| 4166 { | |
| 4167 V8DOMConfiguration::batchConfigureAttributes(templ, v8::Handle<v8::ObjectTem
plate>(), shadowAttrs, WTF_ARRAY_LENGTH(shadowAttrs), isolate, currentWorldType)
; | |
| 4168 | |
| 4169 // Install a security handler with V8. | |
| 4170 templ->SetAccessCheckCallbacks(V8Window::namedSecurityCheckCustom, V8Window:
:indexedSecurityCheckCustom, v8::External::New(&V8Window::info)); | |
| 4171 templ->SetInternalFieldCount(V8Window::internalFieldCount); | |
| 4172 } | |
| 4173 END | |
| 4174 } | |
| 4175 | |
| 4176 if (!$parentClassTemplate) { | |
| 4177 $parentClassTemplate = "v8::Local<v8::FunctionTemplate>()"; | |
| 4178 } | |
| 4179 | |
| 4180 # Generate the template configuration method | |
| 4181 $code = <<END; | |
| 4182 static v8::Handle<v8::FunctionTemplate> Configure${v8ClassName}Template(v8::Hand
le<v8::FunctionTemplate> desc, v8::Isolate* isolate, WrapperWorldType currentWor
ldType) | |
| 4183 { | |
| 4184 desc->ReadOnlyPrototype(); | |
| 4185 | |
| 4186 v8::Local<v8::Signature> defaultSignature; | |
| 4187 END | |
| 4188 if ($interface->extendedAttributes->{"EnabledAtRuntime"}) { | |
| 4189 my $enable_function = GetRuntimeEnableFunctionName($interface); | |
| 4190 $code .= <<END; | |
| 4191 if (!${enable_function}()) | |
| 4192 defaultSignature = V8DOMConfiguration::configureTemplate(desc, \"\", $pa
rentClassTemplate, ${v8ClassName}::internalFieldCount, 0, 0, 0, 0, isolate, curr
entWorldType); | |
| 4193 else | |
| 4194 END | |
| 4195 } | |
| 4196 $code .= <<END; | |
| 4197 defaultSignature = V8DOMConfiguration::configureTemplate(desc, \"${interface
Name}\", $parentClassTemplate, ${v8ClassName}::internalFieldCount, | |
| 4198 END | |
| 4199 # Set up our attributes if we have them | |
| 4200 if ($has_attributes) { | |
| 4201 $code .= <<END; | |
| 4202 ${v8ClassName}Attrs, WTF_ARRAY_LENGTH(${v8ClassName}Attrs), | |
| 4203 END | |
| 4204 } else { | |
| 4205 $code .= <<END; | |
| 4206 0, 0, | |
| 4207 END | |
| 4208 } | |
| 4209 | |
| 4210 if ($has_callbacks) { | |
| 4211 $code .= <<END; | |
| 4212 ${v8ClassName}Methods, WTF_ARRAY_LENGTH(${v8ClassName}Methods), isolate,
currentWorldType); | |
| 4213 END | |
| 4214 } else { | |
| 4215 $code .= <<END; | |
| 4216 0, 0, isolate, currentWorldType); | |
| 4217 END | |
| 4218 } | |
| 4219 | |
| 4220 AddToImplIncludes("wtf/UnusedParam.h"); | |
| 4221 $code .= <<END; | |
| 4222 UNUSED_PARAM(defaultSignature); // In some cases, it will not be used. | |
| 4223 END | |
| 4224 | |
| 4225 if (IsConstructable($interface)) { | |
| 4226 $code .= " desc->SetCallHandler(${v8ClassName}::constructorCallback);
\n"; | |
| 4227 my $interfaceLength = GetInterfaceLength($interface); | |
| 4228 $code .= " desc->SetLength(${interfaceLength});\n"; | |
| 4229 } | |
| 4230 | |
| 4231 if ($access_check or @enabledAtRuntimeAttributes or @normalFunctions or $has
_constants) { | |
| 4232 $code .= <<END; | |
| 4233 v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate(); | |
| 4234 v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate(); | |
| 4235 UNUSED_PARAM(instance); // In some cases, it will not be used. | |
| 4236 UNUSED_PARAM(proto); // In some cases, it will not be used. | |
| 4237 END | |
| 4238 } | |
| 4239 | |
| 4240 if ($access_check) { | |
| 4241 $code .= " $access_check\n"; | |
| 4242 } | |
| 4243 | |
| 4244 # Setup the enable-at-runtime attrs if we have them | |
| 4245 foreach my $runtime_attr (@enabledAtRuntimeAttributes) { | |
| 4246 next if grep { $_ eq $runtime_attr } @enabledPerContextAttributes; | |
| 4247 my $enable_function = GetRuntimeEnableFunctionName($runtime_attr); | |
| 4248 my $conditionalString = GenerateConditionalString($runtime_attr); | |
| 4249 $code .= "\n#if ${conditionalString}\n" if $conditionalString; | |
| 4250 $code .= " if (${enable_function}()) {\n"; | |
| 4251 $code .= " static const V8DOMConfiguration::BatchedAttribute attr
Data =\\\n"; | |
| 4252 $code .= GenerateSingleBatchedAttribute($interface, $runtime_attr, ";",
" "); | |
| 4253 $code .= <<END; | |
| 4254 V8DOMConfiguration::configureAttribute(instance, proto, attrData, isolat
e, currentWorldType); | |
| 4255 } | |
| 4256 END | |
| 4257 $code .= "\n#endif // ${conditionalString}\n" if $conditionalString; | |
| 4258 } | |
| 4259 | |
| 4260 # Setup the enable-at-runtime constants if we have them | |
| 4261 foreach my $runtime_const (@constantsEnabledAtRuntime) { | |
| 4262 my $enable_function = GetRuntimeEnableFunctionName($runtime_const); | |
| 4263 my $conditionalString = GenerateConditionalString($runtime_const); | |
| 4264 my $name = $runtime_const->name; | |
| 4265 my $value = $runtime_const->value; | |
| 4266 $code .= "\n#if ${conditionalString}\n" if $conditionalString; | |
| 4267 $code .= " if (${enable_function}()) {\n"; | |
| 4268 $code .= <<END; | |
| 4269 static const V8DOMConfiguration::BatchedConstant constData = {"${name}",
static_cast<signed int>(${value})}; | |
| 4270 V8DOMConfiguration::batchConfigureConstants(desc, proto, &constData, 1,
isolate); | |
| 4271 END | |
| 4272 $code .= " }\n"; | |
| 4273 $code .= "\n#endif // ${conditionalString}\n" if $conditionalString; | |
| 4274 } | |
| 4275 | |
| 4276 $code .= GenerateImplementationIndexedPropertyAccessors($interface); | |
| 4277 $code .= GenerateImplementationNamedPropertyAccessors($interface); | |
| 4278 $code .= GenerateImplementationLegacyCall($interface); | |
| 4279 $code .= GenerateImplementationMasqueradesAsUndefined($interface); | |
| 4280 | |
| 4281 # Define our functions with Set() or SetAccessor() | |
| 4282 my $total_functions = 0; | |
| 4283 foreach my $function (@normalFunctions) { | |
| 4284 # Only one accessor is needed for overloaded methods: | |
| 4285 next if $function->{overloadIndex} > 1; | |
| 4286 next if $function->name eq ""; | |
| 4287 | |
| 4288 $total_functions++; | |
| 4289 next if IsStandardFunction($interface, $function); | |
| 4290 $code .= GenerateNonStandardFunction($interface, $function); | |
| 4291 $num_callbacks++; | |
| 4292 } | |
| 4293 | |
| 4294 die "Wrong number of callbacks generated for $interfaceName ($num_callbacks,
should be $total_functions)" if $num_callbacks != $total_functions; | |
| 4295 | |
| 4296 if ($has_constants) { | |
| 4297 $code .= <<END; | |
| 4298 V8DOMConfiguration::batchConfigureConstants(desc, proto, ${v8ClassName}Const
s, WTF_ARRAY_LENGTH(${v8ClassName}Consts), isolate); | |
| 4299 END | |
| 4300 } | |
| 4301 | |
| 4302 # Special cases | |
| 4303 if ($interfaceName eq "Window") { | |
| 4304 $code .= <<END; | |
| 4305 | |
| 4306 proto->SetInternalFieldCount(V8Window::internalFieldCount); | |
| 4307 desc->SetHiddenPrototype(true); | |
| 4308 instance->SetInternalFieldCount(V8Window::internalFieldCount); | |
| 4309 // Set access check callbacks, but turned off initially. | |
| 4310 // When a context is detached from a frame, turn on the access check. | |
| 4311 // Turning on checks also invalidates inline caches of the object. | |
| 4312 instance->SetAccessCheckCallbacks(V8Window::namedSecurityCheckCustom, V8Wind
ow::indexedSecurityCheckCustom, v8::External::New(&V8Window::info), false); | |
| 4313 END | |
| 4314 } | |
| 4315 if ($interfaceName eq "HTMLDocument" or $interfaceName eq "DedicatedWorkerGl
obalScope" or $interfaceName eq "SharedWorkerGlobalScope") { | |
| 4316 $code .= <<END; | |
| 4317 desc->SetHiddenPrototype(true); | |
| 4318 END | |
| 4319 } | |
| 4320 | |
| 4321 $code .= <<END; | |
| 4322 | |
| 4323 // Custom toString template | |
| 4324 desc->Set(v8::String::NewSymbol("toString"), V8PerIsolateData::current()->to
StringTemplate()); | |
| 4325 return desc; | |
| 4326 } | |
| 4327 | |
| 4328 END | |
| 4329 $implementation{nameSpaceWebCore}->add($code); | |
| 4330 | |
| 4331 $implementation{nameSpaceWebCore}->add(<<END); | |
| 4332 v8::Handle<v8::FunctionTemplate> ${v8ClassName}::GetTemplate(v8::Isolate* isolat
e, WrapperWorldType currentWorldType) | |
| 4333 { | |
| 4334 V8PerIsolateData* data = V8PerIsolateData::from(isolate); | |
| 4335 V8PerIsolateData::TemplateMap::iterator result = data->templateMap(currentWo
rldType).find(&info); | |
| 4336 if (result != data->templateMap(currentWorldType).end()) | |
| 4337 return result->value.newLocal(isolate); | |
| 4338 | |
| 4339 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate"); | |
| 4340 v8::HandleScope handleScope(isolate); | |
| 4341 v8::Handle<v8::FunctionTemplate> templ = | |
| 4342 Configure${v8ClassName}Template(data->rawTemplate(&info, currentWorldTyp
e), isolate, currentWorldType); | |
| 4343 data->templateMap(currentWorldType).add(&info, UnsafePersistent<v8::Function
Template>(isolate, templ)); | |
| 4344 return handleScope.Close(templ); | |
| 4345 } | |
| 4346 | |
| 4347 END | |
| 4348 $implementation{nameSpaceWebCore}->add(<<END); | |
| 4349 bool ${v8ClassName}::HasInstance(v8::Handle<v8::Value> value, v8::Isolate* isola
te, WrapperWorldType currentWorldType) | |
| 4350 { | |
| 4351 return V8PerIsolateData::from(isolate)->hasInstance(&info, value, currentWor
ldType); | |
| 4352 } | |
| 4353 | |
| 4354 END | |
| 4355 $implementation{nameSpaceWebCore}->add(<<END); | |
| 4356 bool ${v8ClassName}::HasInstanceInAnyWorld(v8::Handle<v8::Value> value, v8::Isol
ate* isolate) | |
| 4357 { | |
| 4358 return V8PerIsolateData::from(isolate)->hasInstance(&info, value, MainWorld) | |
| 4359 || V8PerIsolateData::from(isolate)->hasInstance(&info, value, IsolatedWo
rld) | |
| 4360 || V8PerIsolateData::from(isolate)->hasInstance(&info, value, WorkerWorl
d); | |
| 4361 } | |
| 4362 | |
| 4363 END | |
| 4364 | |
| 4365 if (@enabledPerContextAttributes) { | |
| 4366 my $code = ""; | |
| 4367 $code .= <<END; | |
| 4368 void ${v8ClassName}::installPerContextProperties(v8::Handle<v8::Object> instance
, ${nativeType}* impl, v8::Isolate* isolate) | |
| 4369 { | |
| 4370 v8::Local<v8::Object> proto = v8::Local<v8::Object>::Cast(instance->GetProto
type()); | |
| 4371 END | |
| 4372 | |
| 4373 # Setup the enable-by-settings attrs if we have them | |
| 4374 foreach my $runtimeAttr (@enabledPerContextAttributes) { | |
| 4375 my $enableFunction = GetContextEnableFunction($runtimeAttr); | |
| 4376 my $conditionalString = GenerateConditionalString($runtimeAttr); | |
| 4377 $code .= "\n#if ${conditionalString}\n" if $conditionalString; | |
| 4378 if (grep { $_ eq $runtimeAttr } @enabledAtRuntimeAttributes) { | |
| 4379 my $runtimeEnableFunction = GetRuntimeEnableFunctionName($runtim
eAttr); | |
| 4380 $code .= " if (${enableFunction}(impl->document()) && ${runti
meEnableFunction}()) {\n"; | |
| 4381 } else { | |
| 4382 $code .= " if (${enableFunction}(impl->document())) {\n"; | |
| 4383 } | |
| 4384 | |
| 4385 $code .= " static const V8DOMConfiguration::BatchedAttribute
attrData =\\\n"; | |
| 4386 $code .= GenerateSingleBatchedAttribute($interface, $runtimeAttr, ";
", " "); | |
| 4387 $code .= <<END; | |
| 4388 V8DOMConfiguration::configureAttribute(instance, proto, attrData, isolat
e); | |
| 4389 END | |
| 4390 $code .= " }\n"; | |
| 4391 $code .= "#endif // ${conditionalString}\n" if $conditionalString; | |
| 4392 } | |
| 4393 $code .= <<END; | |
| 4394 } | |
| 4395 | |
| 4396 END | |
| 4397 $implementation{nameSpaceWebCore}->add($code); | |
| 4398 } | |
| 4399 | |
| 4400 if (@enabledPerContextFunctions) { | |
| 4401 my $code = ""; | |
| 4402 $code .= <<END; | |
| 4403 void ${v8ClassName}::installPerContextPrototypeProperties(v8::Handle<v8::Object>
proto, v8::Isolate* isolate) | |
| 4404 { | |
| 4405 UNUSED_PARAM(proto); | |
| 4406 END | |
| 4407 # Setup the enable-by-settings functions if we have them | |
| 4408 $code .= <<END; | |
| 4409 v8::Local<v8::Signature> defaultSignature = v8::Signature::New(GetTemplate(i
solate, worldType(isolate))); | |
| 4410 UNUSED_PARAM(defaultSignature); // In some cases, it will not be used. | |
| 4411 | |
| 4412 ScriptExecutionContext* context = toScriptExecutionContext(proto->CreationCo
ntext()); | |
| 4413 END | |
| 4414 | |
| 4415 foreach my $runtimeFunc (@enabledPerContextFunctions) { | |
| 4416 my $enableFunction = GetContextEnableFunction($runtimeFunc); | |
| 4417 my $functionLength = GetFunctionLength($runtimeFunc); | |
| 4418 my $conditionalString = GenerateConditionalString($runtimeFunc); | |
| 4419 $code .= "\n#if ${conditionalString}\n" if $conditionalString; | |
| 4420 $code .= " if (context && context->isDocument() && ${enableFuncti
on}(toDocument(context)))\n"; | |
| 4421 my $name = $runtimeFunc->name; | |
| 4422 $code .= <<END; | |
| 4423 proto->Set(v8::String::NewSymbol("${name}"), v8::FunctionTemplate::New($
{implClassName}V8Internal::${name}MethodCallback, v8Undefined(), defaultSignatur
e, $functionLength)->GetFunction()); | |
| 4424 END | |
| 4425 $code .= "#endif // ${conditionalString}\n" if $conditionalString; | |
| 4426 } | |
| 4427 | |
| 4428 $code .= <<END; | |
| 4429 } | |
| 4430 | |
| 4431 END | |
| 4432 $implementation{nameSpaceWebCore}->add($code); | |
| 4433 } | |
| 4434 | |
| 4435 if (InheritsExtendedAttribute($interface, "ActiveDOMObject")) { | |
| 4436 # MessagePort is handled like an active dom object even though it doesn'
t inherit | |
| 4437 # from ActiveDOMObject, so don't try to cast it to ActiveDOMObject. | |
| 4438 my $returnValue = $interfaceName eq "MessagePort" ? "0" : "toNative(obje
ct)"; | |
| 4439 $implementation{nameSpaceWebCore}->add(<<END); | |
| 4440 ActiveDOMObject* ${v8ClassName}::toActiveDOMObject(v8::Handle<v8::Object> object
) | |
| 4441 { | |
| 4442 return $returnValue; | |
| 4443 } | |
| 4444 | |
| 4445 END | |
| 4446 } | |
| 4447 | |
| 4448 if (InheritsExtendedAttribute($interface, "EventTarget")) { | |
| 4449 $implementation{nameSpaceWebCore}->add(<<END); | |
| 4450 EventTarget* ${v8ClassName}::toEventTarget(v8::Handle<v8::Object> object) | |
| 4451 { | |
| 4452 return toNative(object); | |
| 4453 } | |
| 4454 | |
| 4455 END | |
| 4456 } | |
| 4457 | |
| 4458 if ($interfaceName eq "Window") { | |
| 4459 $implementation{nameSpaceWebCore}->add(<<END); | |
| 4460 v8::Handle<v8::ObjectTemplate> V8Window::GetShadowObjectTemplate(v8::Isolate* is
olate, WrapperWorldType currentWorldType) | |
| 4461 { | |
| 4462 if (currentWorldType == MainWorld) { | |
| 4463 static v8::Persistent<v8::ObjectTemplate> V8WindowShadowObjectCacheForMa
inWorld; | |
| 4464 if (V8WindowShadowObjectCacheForMainWorld.IsEmpty()) { | |
| 4465 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate"); | |
| 4466 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(); | |
| 4467 ConfigureShadowObjectTemplate(templ, isolate, currentWorldType); | |
| 4468 V8WindowShadowObjectCacheForMainWorld.Reset(isolate, templ); | |
| 4469 return templ; | |
| 4470 } | |
| 4471 return v8::Local<v8::ObjectTemplate>::New(isolate, V8WindowShadowObjectC
acheForMainWorld); | |
| 4472 } else { | |
| 4473 static v8::Persistent<v8::ObjectTemplate> V8WindowShadowObjectCacheForNo
nMainWorld; | |
| 4474 if (V8WindowShadowObjectCacheForNonMainWorld.IsEmpty()) { | |
| 4475 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate"); | |
| 4476 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(); | |
| 4477 ConfigureShadowObjectTemplate(templ, isolate, currentWorldType); | |
| 4478 V8WindowShadowObjectCacheForNonMainWorld.Reset(isolate, templ); | |
| 4479 return templ; | |
| 4480 } | |
| 4481 return v8::Local<v8::ObjectTemplate>::New(isolate, V8WindowShadowObjectC
acheForNonMainWorld); | |
| 4482 } | |
| 4483 } | |
| 4484 | |
| 4485 END | |
| 4486 } | |
| 4487 | |
| 4488 GenerateToV8Converters($interface, $v8ClassName, $nativeType); | |
| 4489 | |
| 4490 $implementation{nameSpaceWebCore}->add(<<END); | |
| 4491 void ${v8ClassName}::derefObject(void* object) | |
| 4492 { | |
| 4493 static_cast<${nativeType}*>(object)->deref(); | |
| 4494 } | |
| 4495 | |
| 4496 END | |
| 4497 } | |
| 4498 | |
| 4499 sub GenerateHeaderContentHeader | |
| 4500 { | |
| 4501 my $interface = shift; | |
| 4502 my $v8ClassName = GetV8ClassName($interface); | |
| 4503 my $conditionalString = GenerateConditionalString($interface); | |
| 4504 | |
| 4505 my @headerContentHeader = split("\r", $headerTemplate); | |
| 4506 | |
| 4507 push(@headerContentHeader, "\n#ifndef ${v8ClassName}" . "_h\n"); | |
| 4508 push(@headerContentHeader, "#define ${v8ClassName}" . "_h\n\n"); | |
| 4509 push(@headerContentHeader, "#if ${conditionalString}\n") if $conditionalStri
ng; | |
| 4510 return join "", @headerContentHeader; | |
| 4511 } | |
| 4512 | |
| 4513 sub GenerateCallbackHeader | |
| 4514 { | |
| 4515 my $object = shift; | |
| 4516 my $interface = shift; | |
| 4517 | |
| 4518 my $interfaceName = $interface->name; | |
| 4519 my $implClassName = GetImplName($interface); | |
| 4520 my $v8ClassName = GetV8ClassName($interface); | |
| 4521 | |
| 4522 $header{root}->addFooter("\n"); | |
| 4523 | |
| 4524 my @includes = (); | |
| 4525 push(@includes, "bindings/v8/ActiveDOMCallback.h"); | |
| 4526 push(@includes, "bindings/v8/DOMWrapperWorld.h"); | |
| 4527 push(@includes, "bindings/v8/ScopedPersistent.h"); | |
| 4528 push(@includes, HeaderFilesForInterface($interfaceName, $implClassName)); | |
| 4529 for my $include (sort @includes) { | |
| 4530 $header{includes}->add("#include \"$include\"\n"); | |
| 4531 } | |
| 4532 $header{nameSpaceWebCore}->addHeader("\nclass ScriptExecutionContext;\n\n"); | |
| 4533 $header{class}->addHeader("class $v8ClassName : public $implClassName, publi
c ActiveDOMCallback {"); | |
| 4534 $header{class}->addFooter("};\n"); | |
| 4535 | |
| 4536 $header{classPublic}->add(<<END); | |
| 4537 static PassRefPtr<${v8ClassName}> create(v8::Handle<v8::Value> value, Script
ExecutionContext* context) | |
| 4538 { | |
| 4539 ASSERT(value->IsObject()); | |
| 4540 ASSERT(context); | |
| 4541 return adoptRef(new ${v8ClassName}(v8::Handle<v8::Object>::Cast(value),
context)); | |
| 4542 } | |
| 4543 | |
| 4544 virtual ~${v8ClassName}(); | |
| 4545 | |
| 4546 END | |
| 4547 | |
| 4548 # Functions | |
| 4549 my $numFunctions = @{$interface->functions}; | |
| 4550 if ($numFunctions > 0) { | |
| 4551 $header{classPublic}->add(" // Functions\n"); | |
| 4552 foreach my $function (@{$interface->functions}) { | |
| 4553 my $code = " virtual " . GetNativeTypeForCallbacks($function->typ
e) . " " . $function->name . "("; | |
| 4554 | |
| 4555 my @args = (); | |
| 4556 if (ExtendedAttributeContains($function->extendedAttributes->{"CallW
ith"}, "ThisValue")) { | |
| 4557 push(@args, GetNativeType("any") . " thisValue"); | |
| 4558 } | |
| 4559 my @params = @{$function->parameters}; | |
| 4560 foreach my $param (@params) { | |
| 4561 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $par
am->name); | |
| 4562 } | |
| 4563 $code .= join(", ", @args); | |
| 4564 $code .= ");\n"; | |
| 4565 $header{classPublic}->add($code); | |
| 4566 } | |
| 4567 } | |
| 4568 | |
| 4569 $header{classPublic}->add(<<END); | |
| 4570 | |
| 4571 virtual ScriptExecutionContext* scriptExecutionContext() const { return Cont
extLifecycleObserver::scriptExecutionContext(); } | |
| 4572 | |
| 4573 END | |
| 4574 $header{classPrivate}->add(<<END); | |
| 4575 ${v8ClassName}(v8::Handle<v8::Object>, ScriptExecutionContext*); | |
| 4576 | |
| 4577 ScopedPersistent<v8::Object> m_callback; | |
| 4578 RefPtr<DOMWrapperWorld> m_world; | |
| 4579 END | |
| 4580 } | |
| 4581 | |
| 4582 sub GenerateCallbackImplementation | |
| 4583 { | |
| 4584 my $object = shift; | |
| 4585 my $interface = shift; | |
| 4586 my $v8ClassName = GetV8ClassName($interface); | |
| 4587 | |
| 4588 AddToImplIncludes("core/dom/ScriptExecutionContext.h"); | |
| 4589 AddToImplIncludes("bindings/v8/V8Binding.h"); | |
| 4590 AddToImplIncludes("bindings/v8/V8Callback.h"); | |
| 4591 AddToImplIncludes("wtf/Assertions.h"); | |
| 4592 | |
| 4593 $implementation{nameSpaceWebCore}->add(<<END); | |
| 4594 ${v8ClassName}::${v8ClassName}(v8::Handle<v8::Object> callback, ScriptExecutionC
ontext* context) | |
| 4595 : ActiveDOMCallback(context) | |
| 4596 , m_callback(callback) | |
| 4597 , m_world(DOMWrapperWorld::current()) | |
| 4598 { | |
| 4599 } | |
| 4600 | |
| 4601 END | |
| 4602 | |
| 4603 $implementation{nameSpaceWebCore}->add(<<END); | |
| 4604 ${v8ClassName}::~${v8ClassName}() | |
| 4605 { | |
| 4606 } | |
| 4607 | |
| 4608 END | |
| 4609 | |
| 4610 # Functions | |
| 4611 my $numFunctions = @{$interface->functions}; | |
| 4612 if ($numFunctions > 0) { | |
| 4613 $implementation{nameSpaceWebCore}->add("// Functions\n"); | |
| 4614 foreach my $function (@{$interface->functions}) { | |
| 4615 my $code = ""; | |
| 4616 my @params = @{$function->parameters}; | |
| 4617 next if $function->extendedAttributes->{"Custom"}; | |
| 4618 | |
| 4619 AddIncludesForType($function->type); | |
| 4620 die "We don't yet support callbacks that return non-boolean values.\
n" if $function->type ne "boolean"; | |
| 4621 $code .= "\n" . GetNativeTypeForCallbacks($function->type) . " ${v8C
lassName}::" . $function->name . "("; | |
| 4622 my $callWithThisValue = ExtendedAttributeContains($function->extende
dAttributes->{"CallWith"}, "ThisValue"); | |
| 4623 | |
| 4624 my @args = (); | |
| 4625 if ($callWithThisValue) { | |
| 4626 push(@args, GetNativeTypeForCallbacks("any") . " thisValue"); | |
| 4627 } | |
| 4628 foreach my $param (@params) { | |
| 4629 my $paramName = $param->name; | |
| 4630 my $type = $param->type; | |
| 4631 my $arrayOrSequenceType = GetArrayOrSequenceType($type); | |
| 4632 | |
| 4633 if ($arrayOrSequenceType) { | |
| 4634 if (IsRefPtrType($arrayOrSequenceType)) { | |
| 4635 AddIncludesForType($arrayOrSequenceType); | |
| 4636 } | |
| 4637 } else { | |
| 4638 AddIncludesForType($type); | |
| 4639 } | |
| 4640 | |
| 4641 push(@args, GetNativeTypeForCallbacks($type) . " " . $paramName)
; | |
| 4642 } | |
| 4643 $code .= join(", ", @args); | |
| 4644 | |
| 4645 $code .= ")\n"; | |
| 4646 $code .= "{\n"; | |
| 4647 $code .= " if (!canInvokeCallback())\n"; | |
| 4648 $code .= " return true;\n\n"; | |
| 4649 $code .= " v8::Isolate* isolate = v8::Isolate::GetCurrent();\n"; | |
| 4650 $code .= " v8::HandleScope handleScope(isolate);\n\n"; | |
| 4651 $code .= " v8::Handle<v8::Context> v8Context = toV8Context(script
ExecutionContext(), m_world.get());\n"; | |
| 4652 $code .= " if (v8Context.IsEmpty())\n"; | |
| 4653 $code .= " return true;\n\n"; | |
| 4654 $code .= " v8::Context::Scope scope(v8Context);\n\n"; | |
| 4655 | |
| 4656 my $thisObjectHandle = ""; | |
| 4657 if ($callWithThisValue) { | |
| 4658 $code .= " v8::Handle<v8::Value> thisHandle = thisValue.v8Val
ue();\n"; | |
| 4659 $code .= " if (thisHandle.IsEmpty()) {\n"; | |
| 4660 $code .= " if (!isScriptControllerTerminating())\n"; | |
| 4661 $code .= " CRASH();\n"; | |
| 4662 $code .= " return true;\n"; | |
| 4663 $code .= " }\n"; | |
| 4664 $code .= " ASSERT(thisHandle->isObject());\n"; | |
| 4665 $thisObjectHandle = "v8::Handle<v8::Object>::Cast(thisHandle), "
; | |
| 4666 } | |
| 4667 @args = (); | |
| 4668 foreach my $param (@params) { | |
| 4669 my $paramName = $param->name; | |
| 4670 $code .= NativeToJSValue($param->type, $param->extendedAttribute
s, $paramName, " ", "v8::Handle<v8::Value> ${paramName}Handle =", "v8::Handle
<v8::Object>()", "isolate", "") . "\n"; | |
| 4671 $code .= " if (${paramName}Handle.IsEmpty()) {\n"; | |
| 4672 $code .= " if (!isScriptControllerTerminating())\n"; | |
| 4673 $code .= " CRASH();\n"; | |
| 4674 $code .= " return true;\n"; | |
| 4675 $code .= " }\n"; | |
| 4676 push(@args, " ${paramName}Handle"); | |
| 4677 } | |
| 4678 | |
| 4679 if (scalar(@args) > 0) { | |
| 4680 $code .= "\n v8::Handle<v8::Value> argv[] = {\n"; | |
| 4681 $code .= join(",\n", @args); | |
| 4682 $code .= "\n };\n\n"; | |
| 4683 } else { | |
| 4684 $code .= "\n v8::Handle<v8::Value> *argv = 0;\n\n"; | |
| 4685 } | |
| 4686 $code .= " bool callbackReturnValue = false;\n"; | |
| 4687 $code .= " return !invokeCallback(m_callback.newLocal(isolate), $
{thisObjectHandle}" . scalar(@args) . ", argv, callbackReturnValue, scriptExecut
ionContext());\n"; | |
| 4688 $code .= "}\n"; | |
| 4689 $implementation{nameSpaceWebCore}->add($code); | |
| 4690 } | |
| 4691 } | |
| 4692 } | |
| 4693 | |
| 4694 sub BaseInterfaceName | |
| 4695 { | |
| 4696 my $interface = shift; | |
| 4697 | |
| 4698 while ($interface->parent) { | |
| 4699 $interface = ParseInterface($interface->parent); | |
| 4700 } | |
| 4701 | |
| 4702 return $interface->name; | |
| 4703 } | |
| 4704 | |
| 4705 sub GenerateToV8Converters | |
| 4706 { | |
| 4707 my $interface = shift; | |
| 4708 my $v8ClassName = shift; | |
| 4709 my $nativeType = shift; | |
| 4710 my $interfaceName = $interface->name; | |
| 4711 | |
| 4712 if ($interface->extendedAttributes->{"DoNotGenerateWrap"} || $interface->ext
endedAttributes->{"DoNotGenerateToV8"}) { | |
| 4713 return; | |
| 4714 } | |
| 4715 | |
| 4716 AddToImplIncludes("bindings/v8/ScriptController.h"); | |
| 4717 AddToImplIncludes("core/page/Frame.h"); | |
| 4718 | |
| 4719 my $createWrapperArgumentType = GetPassRefPtrType($nativeType); | |
| 4720 my $baseType = BaseInterfaceName($interface); | |
| 4721 | |
| 4722 # FIXME: Do we really need to treat "GenerateIsReachable", "CustomIsReachabl
e" and /SVG/ | |
| 4723 # as dependent DOM objects? | |
| 4724 my $wrapperConfiguration = "WrapperConfiguration::Independent"; | |
| 4725 if (InheritsExtendedAttribute($interface, "ActiveDOMObject") | |
| 4726 || InheritsExtendedAttribute($interface, "DependentLifetime") | |
| 4727 || InheritsExtendedAttribute($interface, "GenerateIsReachable") | |
| 4728 || InheritsExtendedAttribute($interface, "CustomIsReachable") | |
| 4729 || $v8ClassName =~ /SVG/) { | |
| 4730 $wrapperConfiguration = "WrapperConfiguration::Dependent"; | |
| 4731 } | |
| 4732 | |
| 4733 my $code = ""; | |
| 4734 $code .= <<END; | |
| 4735 | |
| 4736 v8::Handle<v8::Object> ${v8ClassName}::createWrapper(${createWrapperArgumentType
} impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) | |
| 4737 { | |
| 4738 ASSERT(impl.get()); | |
| 4739 ASSERT(DOMDataStore::getWrapper(impl.get(), isolate).IsEmpty()); | |
| 4740 END | |
| 4741 | |
| 4742 $code .= <<END if ($baseType ne $interfaceName); | |
| 4743 ASSERT(static_cast<void*>(static_cast<${baseType}*>(impl.get())) == static_c
ast<void*>(impl.get())); | |
| 4744 END | |
| 4745 | |
| 4746 if (InheritsInterface($interface, "Document")) { | |
| 4747 $code .= <<END; | |
| 4748 if (Frame* frame = impl->frame()) { | |
| 4749 if (frame->script()->initializeMainWorld()) { | |
| 4750 // initializeMainWorld may have created a wrapper for the object, re
try from the start. | |
| 4751 v8::Handle<v8::Object> wrapper = DOMDataStore::getWrapper(impl.get()
, isolate); | |
| 4752 if (!wrapper.IsEmpty()) | |
| 4753 return wrapper; | |
| 4754 } | |
| 4755 } | |
| 4756 END | |
| 4757 } | |
| 4758 | |
| 4759 $code .= <<END; | |
| 4760 | |
| 4761 v8::Handle<v8::Object> wrapper = V8DOMWrapper::createWrapper(creationContext
, &info, impl.get(), isolate); | |
| 4762 if (UNLIKELY(wrapper.IsEmpty())) | |
| 4763 return wrapper; | |
| 4764 END | |
| 4765 if (IsTypedArrayType($interface->name)) { | |
| 4766 AddToImplIncludes("bindings/v8/custom/V8ArrayBufferCustom.h"); | |
| 4767 $code .= <<END; | |
| 4768 if (!impl->buffer()->hasDeallocationObserver()) { | |
| 4769 v8::V8::AdjustAmountOfExternalAllocatedMemory(impl->buffer()->byteLength
()); | |
| 4770 impl->buffer()->setDeallocationObserver(V8ArrayBufferDeallocationObserve
r::instance()); | |
| 4771 } | |
| 4772 END | |
| 4773 } | |
| 4774 | |
| 4775 $code .= <<END; | |
| 4776 installPerContextProperties(wrapper, impl.get(), isolate); | |
| 4777 V8DOMWrapper::associateObjectWithWrapper(impl, &info, wrapper, isolate, $wra
pperConfiguration); | |
| 4778 return wrapper; | |
| 4779 } | |
| 4780 END | |
| 4781 $implementation{nameSpaceWebCore}->add($code); | |
| 4782 } | |
| 4783 | |
| 4784 sub GenerateSecurityCheckFunctions | |
| 4785 { | |
| 4786 my $interface = shift; | |
| 4787 my $implClassName = GetImplName($interface); | |
| 4788 my $v8ClassName = GetV8ClassName($interface); | |
| 4789 | |
| 4790 AddToImplIncludes("bindings/v8/BindingSecurity.h"); | |
| 4791 $implementation{nameSpaceInternal}->add(<<END); | |
| 4792 bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::Access
Type type, v8::Local<v8::Value>) | |
| 4793 { | |
| 4794 $implClassName* imp = ${v8ClassName}::toNative(host); | |
| 4795 return BindingSecurity::shouldAllowAccessToFrame(imp->frame(), DoNotReportSe
curityError); | |
| 4796 } | |
| 4797 | |
| 4798 END | |
| 4799 $implementation{nameSpaceInternal}->add(<<END); | |
| 4800 bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8
::AccessType type, v8::Local<v8::Value>) | |
| 4801 { | |
| 4802 $implClassName* imp = ${v8ClassName}::toNative(host); | |
| 4803 return BindingSecurity::shouldAllowAccessToFrame(imp->frame(), DoNotReportSe
curityError); | |
| 4804 } | |
| 4805 | |
| 4806 END | |
| 4807 } | |
| 4808 | |
| 4809 sub GetNativeTypeForConversions | |
| 4810 { | |
| 4811 my $interface = shift; | |
| 4812 my $implClassName = GetImplName($interface); | |
| 4813 $implClassName = GetSVGTypeNeedingTearOff($interface->name) if IsSVGTypeNeed
ingTearOff($interface->name); | |
| 4814 return $implClassName; | |
| 4815 } | |
| 4816 | |
| 4817 sub GetNamespaceForInterface | |
| 4818 { | |
| 4819 my $interface = shift; | |
| 4820 return "WTF" if IsTypedArrayType($interface->name); | |
| 4821 return "WebCore"; | |
| 4822 } | |
| 4823 | |
| 4824 sub GenerateFunctionCallString | |
| 4825 { | |
| 4826 my $function = shift; | |
| 4827 my $numberOfParameters = shift; | |
| 4828 my $indent = shift; | |
| 4829 my $interface = shift; | |
| 4830 my $forMainWorldSuffix = shift; | |
| 4831 my %replacements = @_; | |
| 4832 | |
| 4833 my $interfaceName = $interface->name; | |
| 4834 my $implClassName = GetImplName($interface); | |
| 4835 my $name = GetImplName($function); | |
| 4836 my $returnType = $function->type; | |
| 4837 my $nativeReturnType = GetNativeType($returnType, {}, ""); | |
| 4838 my $code = ""; | |
| 4839 | |
| 4840 my $isSVGTearOffType = (IsSVGTypeNeedingTearOff($returnType) and not $interf
aceName =~ /List$/); | |
| 4841 $nativeReturnType = GetSVGWrappedTypeNeedingTearOff($returnType) if $isSVGTe
arOffType; | |
| 4842 | |
| 4843 my $index = 0; | |
| 4844 | |
| 4845 my @arguments; | |
| 4846 my $functionName; | |
| 4847 my $implementedBy = $function->extendedAttributes->{"ImplementedBy"}; | |
| 4848 if ($implementedBy) { | |
| 4849 my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy)
; | |
| 4850 AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implementedBy
ImplName)); | |
| 4851 unshift(@arguments, "imp") if !$function->isStatic; | |
| 4852 $functionName = "${implementedByImplName}::${name}"; | |
| 4853 } elsif ($function->isStatic) { | |
| 4854 $functionName = "${implClassName}::${name}"; | |
| 4855 } else { | |
| 4856 $functionName = "imp->${name}"; | |
| 4857 } | |
| 4858 | |
| 4859 my $callWith = $function->extendedAttributes->{"CallWith"}; | |
| 4860 my ($callWithArgs, $subCode) = GenerateCallWith($callWith, $indent, 1, $func
tion); | |
| 4861 $code .= $subCode; | |
| 4862 unshift(@arguments, @$callWithArgs); | |
| 4863 $index += @$callWithArgs; | |
| 4864 $numberOfParameters += @$callWithArgs; | |
| 4865 | |
| 4866 foreach my $parameter (@{$function->parameters}) { | |
| 4867 if ($index eq $numberOfParameters) { | |
| 4868 last; | |
| 4869 } | |
| 4870 my $paramName = $parameter->name; | |
| 4871 my $paramType = $parameter->type; | |
| 4872 | |
| 4873 if ($replacements{$paramName}) { | |
| 4874 push @arguments, $replacements{$paramName}; | |
| 4875 } elsif ($parameter->type eq "NodeFilter" || $parameter->type eq "XPathN
SResolver") { | |
| 4876 push @arguments, "$paramName.get()"; | |
| 4877 } elsif (IsSVGTypeNeedingTearOff($parameter->type) and not $interfaceNam
e =~ /List$/) { | |
| 4878 push @arguments, "$paramName->propertyReference()"; | |
| 4879 $code .= $indent . "if (!$paramName) {\n"; | |
| 4880 $code .= $indent . " setDOMException(WebCore::TypeMismatchError,
args.GetIsolate());\n"; | |
| 4881 $code .= $indent . " return;\n"; | |
| 4882 $code .= $indent . "}\n"; | |
| 4883 } elsif ($parameter->type eq "SVGMatrix" and $interfaceName eq "SVGTrans
formList") { | |
| 4884 push @arguments, "$paramName.get()"; | |
| 4885 } else { | |
| 4886 push @arguments, $paramName; | |
| 4887 } | |
| 4888 $index++; | |
| 4889 } | |
| 4890 | |
| 4891 if ($function->extendedAttributes->{"RaisesException"}) { | |
| 4892 push @arguments, "ec"; | |
| 4893 } | |
| 4894 | |
| 4895 my $functionString = "$functionName(" . join(", ", @arguments) . ")"; | |
| 4896 | |
| 4897 my $return = "result"; | |
| 4898 my $returnIsRef = IsRefPtrType($returnType); | |
| 4899 | |
| 4900 if ($returnType eq "void") { | |
| 4901 $code .= $indent . "$functionString;\n"; | |
| 4902 } elsif (ExtendedAttributeContains($callWith, "ScriptState") or $function->e
xtendedAttributes->{"RaisesException"}) { | |
| 4903 $code .= $indent . $nativeReturnType . " result = $functionString;\n"; | |
| 4904 } else { | |
| 4905 # Can inline the function call into the return statement to avoid overhe
ad of using a Ref<> temporary | |
| 4906 $return = $functionString; | |
| 4907 $returnIsRef = 0; | |
| 4908 | |
| 4909 if ($interfaceName eq "SVGTransformList" and IsRefPtrType($returnType))
{ | |
| 4910 $return = "WTF::getPtr(" . $return . ")"; | |
| 4911 } | |
| 4912 } | |
| 4913 | |
| 4914 if ($function->extendedAttributes->{"RaisesException"}) { | |
| 4915 $code .= $indent . "if (UNLIKELY(ec)) {\n"; | |
| 4916 $code .= $indent . " setDOMException(ec, args.GetIsolate());\n"; | |
| 4917 $code .= $indent . " return;\n"; | |
| 4918 $code .= $indent . "}\n"; | |
| 4919 } | |
| 4920 | |
| 4921 if (ExtendedAttributeContains($callWith, "ScriptState")) { | |
| 4922 $code .= $indent . "if (state.hadException()) {\n"; | |
| 4923 $code .= $indent . " v8::Local<v8::Value> exception = state.exception
();\n"; | |
| 4924 $code .= $indent . " state.clearException();\n"; | |
| 4925 $code .= $indent . " throwError(exception, args.GetIsolate());\n"; | |
| 4926 $code .= $indent . " return;\n"; | |
| 4927 $code .= $indent . "}\n"; | |
| 4928 } | |
| 4929 | |
| 4930 if ($isSVGTearOffType) { | |
| 4931 AddToImplIncludes("V8$returnType.h"); | |
| 4932 AddToImplIncludes("core/svg/properties/SVGPropertyTearOff.h"); | |
| 4933 my $svgNativeType = GetSVGTypeNeedingTearOff($returnType); | |
| 4934 # FIXME: Update for all ScriptWrappables. | |
| 4935 if (IsDOMNodeType($interfaceName)) { | |
| 4936 $code .= $indent . "v8SetReturnValue(args, toV8Fast${forMainWorldSuf
fix}(WTF::getPtr(${svgNativeType}::create($return)), args, imp));\n"; | |
| 4937 } else { | |
| 4938 $code .= $indent . "v8SetReturnValue(args, toV8${forMainWorldSuffix}
(WTF::getPtr(${svgNativeType}::create($return)), args.Holder(), args.GetIsolate(
)));\n"; | |
| 4939 } | |
| 4940 $code .= $indent . "return;\n"; | |
| 4941 return $code; | |
| 4942 } | |
| 4943 | |
| 4944 # If the implementing class is a POD type, commit changes | |
| 4945 if (IsSVGTypeNeedingTearOff($interfaceName) and not $interfaceName =~ /List$
/) { | |
| 4946 $code .= $indent . "wrapper->commitChange();\n"; | |
| 4947 } | |
| 4948 | |
| 4949 $return .= ".release()" if ($returnIsRef); | |
| 4950 | |
| 4951 my $nativeValue; | |
| 4952 # FIXME: Update for all ScriptWrappables. | |
| 4953 if (IsDOMNodeType($interfaceName)) { | |
| 4954 $nativeValue = NativeToJSValue($function->type, $function->extendedAttri
butes, $return, $indent, "", "args.Holder()", "args.GetIsolate()", "args", "imp"
, "ReturnUnsafeHandle", $forMainWorldSuffix, "return"); | |
| 4955 } else { | |
| 4956 $nativeValue = NativeToJSValue($function->type, $function->extendedAttri
butes, $return, $indent, "", "args.Holder()", "args.GetIsolate()", "args", 0, "R
eturnUnsafeHandle", $forMainWorldSuffix, "return"); | |
| 4957 } | |
| 4958 | |
| 4959 $code .= $nativeValue . "\n"; | |
| 4960 $code .= $indent . "return;\n"; | |
| 4961 | |
| 4962 return $code; | |
| 4963 } | |
| 4964 | |
| 4965 sub GetNativeType | |
| 4966 { | |
| 4967 my $type = shift; | |
| 4968 my $extendedAttributes = shift; | |
| 4969 my $isParameter = shift; | |
| 4970 | |
| 4971 my $svgNativeType = GetSVGTypeNeedingTearOff($type); | |
| 4972 if ($svgNativeType) { | |
| 4973 if ($svgNativeType =~ /List$/) { | |
| 4974 return "${svgNativeType}*"; | |
| 4975 } else { | |
| 4976 return "RefPtr<${svgNativeType} >"; | |
| 4977 } | |
| 4978 } | |
| 4979 | |
| 4980 return "float" if $type eq "float"; | |
| 4981 return "double" if $type eq "double"; | |
| 4982 return "int" if $type eq "long" or $type eq "int" or $type eq "short" or $ty
pe eq "byte"; | |
| 4983 if ($type eq "unsigned long" or $type eq "unsigned int" or $type eq "unsigne
d short" or $type eq "octet") { | |
| 4984 if ($extendedAttributes->{"IsIndex"}) { | |
| 4985 # Special-case index arguments because we need to check that they ar
en't < 0. | |
| 4986 return "int"; | |
| 4987 } | |
| 4988 return "unsigned"; | |
| 4989 } | |
| 4990 return "long long" if $type eq "long long"; | |
| 4991 return "unsigned long long" if $type eq "unsigned long long"; | |
| 4992 return "bool" if $type eq "boolean"; | |
| 4993 | |
| 4994 if (($type eq "DOMString" || IsEnumType($type)) and $isParameter) { | |
| 4995 # FIXME: This implements [TreatNullAs=NullString] and [TreatUndefinedAs=
NullString], | |
| 4996 # but the Web IDL spec requires [TreatNullAs=EmptyString] and [TreatUnde
finedAs=EmptyString]. | |
| 4997 my $mode = ""; | |
| 4998 if (($extendedAttributes->{"TreatNullAs"} and $extendedAttributes->{"Tre
atNullAs"} eq "NullString") and ($extendedAttributes->{"TreatUndefinedAs"} and $
extendedAttributes->{"TreatUndefinedAs"} eq "NullString")) { | |
| 4999 $mode = "WithUndefinedOrNullCheck"; | |
| 5000 } elsif (($extendedAttributes->{"TreatNullAs"} and $extendedAttributes->
{"TreatNullAs"} eq "NullString") or $extendedAttributes->{"Reflect"}) { | |
| 5001 $mode = "WithNullCheck"; | |
| 5002 } | |
| 5003 # FIXME: Add the case for 'elsif ($attributeOrParameter->extendedAttribu
tes->{"TreatUndefinedAs"} and $attributeOrParameter->extendedAttributes->{"Treat
UndefinedAs"} eq "NullString"))'. | |
| 5004 return "V8StringResource<$mode>"; | |
| 5005 } | |
| 5006 | |
| 5007 return "String" if $type eq "DOMString" or IsEnumType($type); | |
| 5008 | |
| 5009 return "Range::CompareHow" if $type eq "CompareHow"; | |
| 5010 return "DOMTimeStamp" if $type eq "DOMTimeStamp"; | |
| 5011 return "double" if $type eq "Date"; | |
| 5012 return "ScriptValue" if $type eq "any" or IsCallbackFunctionType($type); | |
| 5013 return "Dictionary" if $type eq "Dictionary"; | |
| 5014 | |
| 5015 return "RefPtr<DOMStringList>" if $type eq "DOMStringList"; | |
| 5016 return "RefPtr<MediaQueryListListener>" if $type eq "MediaQueryListListener"
; | |
| 5017 return "RefPtr<NodeFilter>" if $type eq "NodeFilter"; | |
| 5018 return "RefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValue"; | |
| 5019 return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver"; | |
| 5020 | |
| 5021 die "UnionType is not supported" if IsUnionType($type); | |
| 5022 | |
| 5023 if ($type eq "ArrayBuffer") { | |
| 5024 return $isParameter ? "ArrayBuffer*" : "RefPtr<ArrayBuffer>"; | |
| 5025 } | |
| 5026 | |
| 5027 # We need to check [ImplementedAs] extended attribute for wrapper types. | |
| 5028 if (IsWrapperType($type)) { | |
| 5029 my $interface = ParseInterface($type); | |
| 5030 my $implClassName = GetImplName($interface); | |
| 5031 return $isParameter ? "${implClassName}*" : "RefPtr<${implClassName}>"; | |
| 5032 } | |
| 5033 return "RefPtr<${type}>" if IsRefPtrType($type) and not $isParameter; | |
| 5034 | |
| 5035 my $arrayOrSequenceType = GetArrayOrSequenceType($type); | |
| 5036 | |
| 5037 if ($arrayOrSequenceType) { | |
| 5038 my $nativeType = GetNativeType($arrayOrSequenceType); | |
| 5039 $nativeType .= " " if ($nativeType =~ />$/); | |
| 5040 return "Vector<${nativeType}>"; | |
| 5041 } | |
| 5042 | |
| 5043 # Default, assume native type is a pointer with same type name as idl type | |
| 5044 return "${type}*"; | |
| 5045 } | |
| 5046 | |
| 5047 sub GetNativeTypeForCallbacks | |
| 5048 { | |
| 5049 my $type = shift; | |
| 5050 return "const String&" if $type eq "DOMString"; | |
| 5051 return "PassRefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValu
e"; | |
| 5052 | |
| 5053 # Callbacks use raw pointers, so pass isParameter = 1 | |
| 5054 return GetNativeType($type, {}, "parameter"); | |
| 5055 } | |
| 5056 | |
| 5057 sub JSValueToNativeStatement | |
| 5058 { | |
| 5059 my $type = shift; | |
| 5060 my $extendedAttributes = shift; | |
| 5061 my $jsValue = shift; | |
| 5062 my $variableName = shift; | |
| 5063 my $indent = shift; | |
| 5064 my $getIsolate = shift; | |
| 5065 | |
| 5066 my $nativeType = GetNativeType($type, $extendedAttributes, "parameter"); | |
| 5067 if ($type eq "unsigned long" and $extendedAttributes->{"IsIndex"}) { | |
| 5068 # Special-case index arguments because we need to check that they aren't
< 0. | |
| 5069 $nativeType = "int"; | |
| 5070 } | |
| 5071 my $native_value = JSValueToNative($type, $extendedAttributes, $jsValue, $ge
tIsolate); | |
| 5072 my $code = ""; | |
| 5073 if ($type eq "DOMString" || IsEnumType($type)) { | |
| 5074 die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8St
ringResource/; | |
| 5075 if ($type eq "DOMString" or IsEnumType($type)) { | |
| 5076 $code .= $indent . "V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID($nativeType
, $variableName, $native_value);\n" | |
| 5077 } else { | |
| 5078 $code .= $indent . "$nativeType $variableName($native_value, true);\
n"; | |
| 5079 } | |
| 5080 } elsif ($extendedAttributes->{"EnforceRange"}) { | |
| 5081 $code .= $indent . "V8TRYCATCH_WITH_TYPECHECK_VOID($nativeType, $variabl
eName, $native_value, $getIsolate);\n"; | |
| 5082 } else { | |
| 5083 $code .= $indent . "V8TRYCATCH_VOID($nativeType, $variableName, $native_
value);\n"; | |
| 5084 } | |
| 5085 return $code; | |
| 5086 } | |
| 5087 | |
| 5088 | |
| 5089 sub JSValueToNative | |
| 5090 { | |
| 5091 my $type = shift; | |
| 5092 my $extendedAttributes = shift; | |
| 5093 my $value = shift; | |
| 5094 my $getIsolate = shift; | |
| 5095 | |
| 5096 my $intConversion = $extendedAttributes->{"EnforceRange"} ? "EnforceRange" :
"NormalConversion"; | |
| 5097 | |
| 5098 return "$value->BooleanValue()" if $type eq "boolean"; | |
| 5099 return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $t
ype eq "double"; | |
| 5100 | |
| 5101 if ($intConversion ne "NormalConversion") { | |
| 5102 return "toInt8($value, $intConversion, ok)" if $type eq "byte"; | |
| 5103 return "toUInt8($value, $intConversion, ok)" if $type eq "octet"; | |
| 5104 return "toInt32($value, $intConversion, ok)" if $type eq "long" or $type
eq "short"; | |
| 5105 return "toUInt32($value, $intConversion, ok)" if $type eq "unsigned long
" or $type eq "unsigned short"; | |
| 5106 return "toInt64($value, $intConversion, ok)" if $type eq "long long"; | |
| 5107 return "toUInt64($value, $intConversion, ok)" if $type eq "unsigned long
long"; | |
| 5108 } else { | |
| 5109 return "toInt8($value)" if $type eq "byte"; | |
| 5110 return "toUInt8($value)" if $type eq "octet"; | |
| 5111 return "toInt32($value)" if $type eq "long" or $type eq "short"; | |
| 5112 return "toUInt32($value)" if $type eq "unsigned long" or $type eq "unsig
ned short"; | |
| 5113 return "toInt64($value)" if $type eq "long long"; | |
| 5114 return "toUInt64($value)" if $type eq "unsigned long long"; | |
| 5115 } | |
| 5116 return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "C
ompareHow"; | |
| 5117 return "toWebCoreDate($value)" if $type eq "Date"; | |
| 5118 return "toDOMStringList($value, $getIsolate)" if $type eq "DOMStringList"; | |
| 5119 | |
| 5120 if ($type eq "DOMString" or IsEnumType($type)) { | |
| 5121 return $value; | |
| 5122 } | |
| 5123 | |
| 5124 if ($type eq "SerializedScriptValue") { | |
| 5125 AddToImplIncludes("bindings/v8/SerializedScriptValue.h"); | |
| 5126 return "SerializedScriptValue::create($value, $getIsolate)"; | |
| 5127 } | |
| 5128 | |
| 5129 if ($type eq "Dictionary") { | |
| 5130 AddToImplIncludes("bindings/v8/Dictionary.h"); | |
| 5131 return "Dictionary($value, $getIsolate)"; | |
| 5132 } | |
| 5133 | |
| 5134 if ($type eq "any" || IsCallbackFunctionType($type)) { | |
| 5135 AddToImplIncludes("bindings/v8/ScriptValue.h"); | |
| 5136 return "ScriptValue($value)"; | |
| 5137 } | |
| 5138 | |
| 5139 if ($type eq "NodeFilter") { | |
| 5140 return "toNodeFilter($value)"; | |
| 5141 } | |
| 5142 | |
| 5143 if ($type eq "MediaQueryListListener") { | |
| 5144 AddToImplIncludes("core/css/MediaQueryListListener.h"); | |
| 5145 return "MediaQueryListListener::create(" . $value . ")"; | |
| 5146 } | |
| 5147 | |
| 5148 if ($type eq "EventTarget") { | |
| 5149 return "V8DOMWrapper::isDOMWrapper($value) ? toWrapperTypeInfo(v8::Handl
e<v8::Object>::Cast($value))->toEventTarget(v8::Handle<v8::Object>::Cast($value)
) : 0"; | |
| 5150 } | |
| 5151 | |
| 5152 if ($type eq "ArrayBuffer") { | |
| 5153 AddIncludesForType($type); | |
| 5154 return "$value->IsArrayBuffer() ? V8ArrayBuffer::toNative(v8::Handle<v8:
:ArrayBuffer>::Cast($value)) : 0" | |
| 5155 } | |
| 5156 | |
| 5157 if ($type eq "XPathNSResolver") { | |
| 5158 return "toXPathNSResolver($value, $getIsolate)"; | |
| 5159 } | |
| 5160 | |
| 5161 my $arrayOrSequenceType = GetArrayOrSequenceType($type); | |
| 5162 | |
| 5163 if ($arrayOrSequenceType) { | |
| 5164 if (IsRefPtrType($arrayOrSequenceType)) { | |
| 5165 AddToImplIncludes("V8${arrayOrSequenceType}.h"); | |
| 5166 return "(toRefPtrNativeArray<${arrayOrSequenceType}, V8${arrayOrSequ
enceType}>($value, $getIsolate))"; | |
| 5167 } | |
| 5168 return "toNativeArray<" . GetNativeType($arrayOrSequenceType) . ">($valu
e)"; | |
| 5169 } | |
| 5170 | |
| 5171 AddIncludesForType($type); | |
| 5172 | |
| 5173 AddToImplIncludes("V8${type}.h"); | |
| 5174 return "V8${type}::HasInstance($value, $getIsolate, worldType($getIsolate))
? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0"; | |
| 5175 } | |
| 5176 | |
| 5177 sub CreateCustomSignature | |
| 5178 { | |
| 5179 my $function = shift; | |
| 5180 my $count = @{$function->parameters}; | |
| 5181 my $name = $function->name; | |
| 5182 my $code = " const int ${name}Argc = ${count};\n" . | |
| 5183 " v8::Handle<v8::FunctionTemplate> ${name}Argv[${name}Argc] = { "; | |
| 5184 my $first = 1; | |
| 5185 foreach my $parameter (@{$function->parameters}) { | |
| 5186 if ($first) { $first = 0; } | |
| 5187 else { $code .= ", "; } | |
| 5188 if (IsWrapperType($parameter->type) && $parameter->type ne "ArrayBuffer"
) { | |
| 5189 if ($parameter->type eq "XPathNSResolver") { | |
| 5190 # Special case for XPathNSResolver. All other browsers accepts
a callable, | |
| 5191 # so, even though it's against IDL, accept objects here. | |
| 5192 $code .= "v8::Handle<v8::FunctionTemplate>()"; | |
| 5193 } else { | |
| 5194 my $type = $parameter->type; | |
| 5195 my $arrayOrSequenceType = GetArrayOrSequenceType($type); | |
| 5196 | |
| 5197 if ($arrayOrSequenceType) { | |
| 5198 if (IsRefPtrType($arrayOrSequenceType)) { | |
| 5199 AddIncludesForType($arrayOrSequenceType); | |
| 5200 } else { | |
| 5201 $code .= "v8::Handle<v8::FunctionTemplate>()"; | |
| 5202 next; | |
| 5203 } | |
| 5204 } else { | |
| 5205 AddIncludesForType($type); | |
| 5206 } | |
| 5207 $code .= "V8PerIsolateData::from(isolate)->rawTemplate(&V8${type
}::info, currentWorldType)"; | |
| 5208 } | |
| 5209 } else { | |
| 5210 $code .= "v8::Handle<v8::FunctionTemplate>()"; | |
| 5211 } | |
| 5212 } | |
| 5213 $code .= " };\n"; | |
| 5214 $code .= " v8::Handle<v8::Signature> ${name}Signature = v8::Signature::Ne
w(desc, ${name}Argc, ${name}Argv);\n"; | |
| 5215 return $code; | |
| 5216 } | |
| 5217 | |
| 5218 | |
| 5219 sub RequiresCustomSignature | |
| 5220 { | |
| 5221 my $function = shift; | |
| 5222 # No signature needed for Custom function | |
| 5223 if (HasCustomMethod($function->extendedAttributes)) { | |
| 5224 return 0; | |
| 5225 } | |
| 5226 # No signature needed for overloaded function | |
| 5227 if (@{$function->{overloads}} > 1) { | |
| 5228 return 0; | |
| 5229 } | |
| 5230 if ($function->isStatic) { | |
| 5231 return 0; | |
| 5232 } | |
| 5233 # Type checking is performed in the generated code | |
| 5234 if ($function->extendedAttributes->{"StrictTypeChecking"}) { | |
| 5235 return 0; | |
| 5236 } | |
| 5237 foreach my $parameter (@{$function->parameters}) { | |
| 5238 if (($parameter->isOptional && !$parameter->extendedAttributes->{"Defaul
t"}) || IsCallbackInterface($parameter->type)) { | |
| 5239 return 0; | |
| 5240 } | |
| 5241 } | |
| 5242 | |
| 5243 foreach my $parameter (@{$function->parameters}) { | |
| 5244 if (IsWrapperType($parameter->type)) { | |
| 5245 return 1; | |
| 5246 } | |
| 5247 } | |
| 5248 return 0; | |
| 5249 } | |
| 5250 | |
| 5251 sub IsUnionType | |
| 5252 { | |
| 5253 my $type = shift; # string or UnionType | |
| 5254 if(ref($type) eq "UnionType") { | |
| 5255 die "Currently only 2 values of non-union type is supported as union typ
e.\n" unless @{$type->unionMemberTypes} == 2; | |
| 5256 return 1; | |
| 5257 } | |
| 5258 return 0; | |
| 5259 } | |
| 5260 | |
| 5261 sub IsWrapperType | |
| 5262 { | |
| 5263 my $type = shift; | |
| 5264 return 0 if GetArrayType($type); | |
| 5265 return 0 if GetSequenceType($type); | |
| 5266 return 0 if IsCallbackFunctionType($type); | |
| 5267 return 0 if IsEnumType($type); | |
| 5268 return 0 if IsPrimitiveType($type); | |
| 5269 return 0 if $type eq "DOMString"; | |
| 5270 return !$nonWrapperTypes{$type}; | |
| 5271 } | |
| 5272 | |
| 5273 sub IsCallbackInterface | |
| 5274 { | |
| 5275 my $type = shift; | |
| 5276 return 0 unless IsWrapperType($type); | |
| 5277 return 0 if $type eq "ArrayBuffer"; | |
| 5278 | |
| 5279 my $idlFile = IDLFileForInterface($type) | |
| 5280 or die("Could NOT find IDL file for interface \"$type\"!\n"); | |
| 5281 | |
| 5282 open FILE, "<", $idlFile; | |
| 5283 my @lines = <FILE>; | |
| 5284 close FILE; | |
| 5285 | |
| 5286 my $fileContents = join('', @lines); | |
| 5287 return ($fileContents =~ /callback\s+interface\s+(\w+)/gs); | |
| 5288 } | |
| 5289 | |
| 5290 sub GetNativeTypeOfTypedArray | |
| 5291 { | |
| 5292 my $interface = shift; | |
| 5293 my $interfaceName = $interface->name; | |
| 5294 die "TypedArray of unknown type is found" unless $typedArrayHash{$interface-
>name}; | |
| 5295 return @{$typedArrayHash{$interface->name}}; | |
| 5296 } | |
| 5297 | |
| 5298 sub IsDOMNodeType | |
| 5299 { | |
| 5300 my $type = shift; | |
| 5301 | |
| 5302 return 1 if $type eq 'Attr'; | |
| 5303 return 1 if $type eq 'CDATASection'; | |
| 5304 return 1 if $type eq 'CharacterData'; | |
| 5305 return 1 if $type eq 'Comment'; | |
| 5306 return 1 if $type eq 'Document'; | |
| 5307 return 1 if $type eq 'DocumentFragment'; | |
| 5308 return 1 if $type eq 'DocumentType'; | |
| 5309 return 1 if $type eq 'Element'; | |
| 5310 return 1 if $type eq 'Entity'; | |
| 5311 return 1 if $type eq 'HTMLDocument'; | |
| 5312 return 1 if $type eq 'Node'; | |
| 5313 return 1 if $type eq 'Notation'; | |
| 5314 return 1 if $type eq 'ProcessingInstruction'; | |
| 5315 return 1 if $type eq 'ShadowRoot'; | |
| 5316 return 1 if $type eq 'SVGDocument'; | |
| 5317 return 1 if $type eq 'Text'; | |
| 5318 | |
| 5319 return 1 if $type =~ /^HTML.*Element$/; | |
| 5320 return 1 if $type =~ /^SVG.*Element$/; | |
| 5321 | |
| 5322 return 1 if $type eq 'TestNode'; | |
| 5323 | |
| 5324 return 0; | |
| 5325 } | |
| 5326 | |
| 5327 | |
| 5328 sub NativeToJSValue | |
| 5329 { | |
| 5330 my $type = shift; | |
| 5331 my $extendedAttributes = shift; | |
| 5332 my $nativeValue = shift; | |
| 5333 my $indent = shift; # added before every line | |
| 5334 my $receiver = shift; # "return" or "<variableName> =" | |
| 5335 my $getCreationContext = shift; | |
| 5336 my $getIsolate = shift; | |
| 5337 die "An Isolate is mandatory for native value => JS value conversion." unles
s $getIsolate; | |
| 5338 my $getHolderContainer = shift || ""; | |
| 5339 my $getHolderContainerArg = $getHolderContainer ? ", $getHolderContainer" :
""; | |
| 5340 my $getScriptWrappable = shift || ""; | |
| 5341 my $getScriptWrappableArg = $getScriptWrappable ? ", $getScriptWrappable" :
""; | |
| 5342 my $returnHandleType = shift || ""; | |
| 5343 my $returnHandleTypeArg = $returnHandleType ? ", $returnHandleType" : ""; | |
| 5344 my $forMainWorldSuffix = shift || ""; | |
| 5345 my $returnValueArg = shift || 0; | |
| 5346 my $isReturnValue = $returnValueArg eq "return"; | |
| 5347 | |
| 5348 if (IsUnionType($type)) { | |
| 5349 my $types = $type->unionMemberTypes; | |
| 5350 my @codes = (); | |
| 5351 for my $i (0 .. scalar(@$types)-1) { | |
| 5352 my $unionMemberType = $types->[$i]; | |
| 5353 my $unionMemberNumber = $i + 1; | |
| 5354 my $unionMemberVariable = $nativeValue . $i; | |
| 5355 my $unionMemberEnabledVariable = $nativeValue . $i . "Enabled"; | |
| 5356 my $unionMemberNativeValue = $unionMemberVariable; | |
| 5357 $unionMemberNativeValue .= ".release()" if (IsRefPtrType($unionMembe
rType)); | |
| 5358 my $returnJSValueCode = NativeToJSValue($unionMemberType, $extendedA
ttributes, $unionMemberNativeValue, $indent . " ", $receiver, $getCreationCon
text, $getIsolate, $getHolderContainer, $getScriptWrappable, $returnHandleType,
$forMainWorldSuffix, $returnValueArg); | |
| 5359 my $code = ""; | |
| 5360 if ($isReturnValue) { | |
| 5361 $code .= "${indent}if (${unionMemberEnabledVariable}) {\n"; | |
| 5362 $code .= "${returnJSValueCode}\n"; | |
| 5363 $code .= "${indent} return;\n"; | |
| 5364 $code .= "${indent}}\n"; | |
| 5365 } else { | |
| 5366 $code .= "${indent}if (${unionMemberEnabledVariable})\n"; | |
| 5367 $code .= "${returnJSValueCode}"; | |
| 5368 } | |
| 5369 push @codes, $code; | |
| 5370 } | |
| 5371 return join "\n", @codes; | |
| 5372 } | |
| 5373 | |
| 5374 if ($type eq "boolean") { | |
| 5375 return "${indent}v8SetReturnValueBool(${getHolderContainer}, ${nativeVal
ue});" if $isReturnValue; | |
| 5376 return "$indent$receiver v8Boolean($nativeValue, $getIsolate);"; | |
| 5377 } | |
| 5378 | |
| 5379 if ($type eq "void") { # equivalent to v8Undefined() | |
| 5380 return "" if $isReturnValue; | |
| 5381 return "$indent$receiver v8Undefined();" | |
| 5382 } | |
| 5383 | |
| 5384 # HTML5 says that unsigned reflected attributes should be in the range | |
| 5385 # [0, 2^31). When a value isn't in this range, a default value (or 0) | |
| 5386 # should be returned instead. | |
| 5387 if ($extendedAttributes->{"Reflect"} and ($type eq "unsigned long" or $type
eq "unsigned short")) { | |
| 5388 $nativeValue =~ s/getUnsignedIntegralAttribute/getIntegralAttribute/g; | |
| 5389 return "${indent}v8SetReturnValueUnsigned(${getHolderContainer}, std::ma
x(0, ${nativeValue}));" if $isReturnValue; | |
| 5390 return "$indent$receiver v8::Integer::NewFromUnsigned(std::max(0, " . $n
ativeValue . "), $getIsolate);"; | |
| 5391 } | |
| 5392 | |
| 5393 my $nativeType = GetNativeType($type); | |
| 5394 if ($nativeType eq "int") { | |
| 5395 return "${indent}v8SetReturnValueInt(${getHolderContainer}, ${nativeValu
e});" if $isReturnValue; | |
| 5396 return "$indent$receiver v8::Integer::New($nativeValue, $getIsolate);"; | |
| 5397 } | |
| 5398 | |
| 5399 if ($nativeType eq "unsigned") { | |
| 5400 return "${indent}v8SetReturnValueUnsigned(${getHolderContainer}, ${nativ
eValue});" if $isReturnValue; | |
| 5401 return "$indent$receiver v8::Integer::NewFromUnsigned($nativeValue, $get
Isolate);"; | |
| 5402 } | |
| 5403 | |
| 5404 if ($type eq "Date") { | |
| 5405 return "${indent}v8SetReturnValue(${getHolderContainer}, v8DateOrNull($n
ativeValue, $getIsolate));" if $isReturnValue; | |
| 5406 return "$indent$receiver v8DateOrNull($nativeValue, $getIsolate);" | |
| 5407 } | |
| 5408 | |
| 5409 # long long and unsigned long long are not representable in ECMAScript. | |
| 5410 if ($type eq "long long" or $type eq "unsigned long long" or $type eq "DOMTi
meStamp") { | |
| 5411 return "${indent}v8SetReturnValue(${getHolderContainer}, static_cast<dou
ble>($nativeValue));" if $isReturnValue; | |
| 5412 return "$indent$receiver v8::Number::New(static_cast<double>($nativeValu
e));"; | |
| 5413 } | |
| 5414 | |
| 5415 if (IsPrimitiveType($type)) { | |
| 5416 die "unexpected type $type" if not ($type eq "float" or $type eq "double
"); | |
| 5417 return "${indent}v8SetReturnValue(${getHolderContainer}, ${nativeValue})
;" if $isReturnValue; | |
| 5418 return "$indent$receiver v8::Number::New($nativeValue);"; | |
| 5419 } | |
| 5420 | |
| 5421 if ($nativeType eq "ScriptValue") { | |
| 5422 return "${indent}v8SetReturnValue(${getHolderContainer}, ${nativeValue}.
v8Value());" if $isReturnValue; | |
| 5423 return "$indent$receiver $nativeValue.v8Value();"; | |
| 5424 } | |
| 5425 | |
| 5426 my $conv = $extendedAttributes->{"TreatReturnedNullStringAs"}; | |
| 5427 if (($type eq "DOMString" || IsEnumType($type)) && $isReturnValue) { | |
| 5428 my $nullAs = "NullStringAsEmpty"; | |
| 5429 if (defined $conv) { | |
| 5430 if ($conv eq "Null") { | |
| 5431 $nullAs = "NullStringAsNull"; | |
| 5432 } elsif ($conv eq "Undefined") { | |
| 5433 $nullAs = "NullStringAsUndefined"; | |
| 5434 } else { | |
| 5435 die "Unknown value for TreatReturnedNullStringAs extended attrib
ute"; | |
| 5436 } | |
| 5437 } | |
| 5438 return "${indent}v8SetReturnValueString(${getHolderContainer}, $nativeVa
lue, $getIsolate, $nullAs);"; | |
| 5439 } | |
| 5440 | |
| 5441 if ($type eq "DOMString" or IsEnumType($type)) { | |
| 5442 my $returnValue = ""; | |
| 5443 if (defined $conv) { | |
| 5444 if ($conv eq "Null") { | |
| 5445 $returnValue = "v8StringOrNull($nativeValue, $getIsolate$returnH
andleTypeArg)"; | |
| 5446 } elsif ($conv eq "Undefined") { | |
| 5447 $returnValue = "v8StringOrUndefined($nativeValue, $getIsolate$re
turnHandleTypeArg)"; | |
| 5448 } else { | |
| 5449 die "Unknown value for TreatReturnedNullStringAs extended attrib
ute"; | |
| 5450 } | |
| 5451 } else { | |
| 5452 $returnValue = "v8String($nativeValue, $getIsolate$returnHandleTypeA
rg)"; | |
| 5453 } | |
| 5454 return "$indent$receiver $returnValue;"; | |
| 5455 } | |
| 5456 | |
| 5457 my $arrayOrSequenceType = GetArrayOrSequenceType($type); | |
| 5458 | |
| 5459 if ($arrayOrSequenceType) { | |
| 5460 if (IsRefPtrType($arrayOrSequenceType)) { | |
| 5461 AddIncludesForType($arrayOrSequenceType); | |
| 5462 } | |
| 5463 return "${indent}v8SetReturnValue(${getHolderContainer}, v8Array($native
Value, $getIsolate));" if $isReturnValue; | |
| 5464 return "$indent$receiver v8Array($nativeValue, $getIsolate);"; | |
| 5465 } | |
| 5466 | |
| 5467 AddIncludesForType($type); | |
| 5468 | |
| 5469 if (IsDOMNodeType($type) || $type eq "EventTarget") { | |
| 5470 if ($getScriptWrappable) { | |
| 5471 # FIXME: Use safe handles | |
| 5472 return "${indent}v8SetReturnValue(${getHolderContainer}, toV8Fast${for
MainWorldSuffix}($nativeValue$getHolderContainerArg$getScriptWrappableArg));" if
$isReturnValue; | |
| 5473 return "$indent$receiver toV8Fast${forMainWorldSuffix}($nativeValue$ge
tHolderContainerArg$getScriptWrappableArg);"; | |
| 5474 } | |
| 5475 # FIXME: Use safe handles | |
| 5476 return "${indent}v8SetReturnValue(${getHolderContainer}, toV8($nativeValue
, $getCreationContext, $getIsolate));" if $isReturnValue; | |
| 5477 return "$indent$receiver toV8($nativeValue, $getCreationContext, $getIsola
te);"; | |
| 5478 } | |
| 5479 | |
| 5480 if ($type eq "SerializedScriptValue") { | |
| 5481 AddToImplIncludes("$type.h"); | |
| 5482 my $returnValue = "$nativeValue ? $nativeValue->deserialize() : v8::Hand
le<v8::Value>(v8::Null($getIsolate))"; | |
| 5483 return "${indent}v8SetReturnValue(${getHolderContainer}, $returnValue);"
if $isReturnValue; | |
| 5484 return "$indent$receiver $returnValue;"; | |
| 5485 } | |
| 5486 | |
| 5487 AddToImplIncludes("wtf/RefCounted.h"); | |
| 5488 AddToImplIncludes("wtf/RefPtr.h"); | |
| 5489 AddToImplIncludes("wtf/GetPtr.h"); | |
| 5490 | |
| 5491 if ($getScriptWrappable) { | |
| 5492 # FIXME: Use safe handles | |
| 5493 return "${indent}v8SetReturnValue(${getHolderContainer}, toV8Fast${forMa
inWorldSuffix}($nativeValue$getHolderContainerArg$getScriptWrappableArg));" if $
isReturnValue; | |
| 5494 return "$indent$receiver toV8Fast${forMainWorldSuffix}($nativeValue$getH
olderContainerArg$getScriptWrappableArg);"; | |
| 5495 } | |
| 5496 # FIXME: Use safe handles | |
| 5497 return "${indent}v8SetReturnValue(${getHolderContainer}, toV8($nativeValue,
$getCreationContext, $getIsolate));" if $isReturnValue; | |
| 5498 return "$indent$receiver toV8($nativeValue, $getCreationContext, $getIsolate
);"; | |
| 5499 } | |
| 5500 | |
| 5501 sub WriteData | |
| 5502 { | |
| 5503 my $object = shift; | |
| 5504 my $interface = shift; | |
| 5505 my $outputDirectory = shift; | |
| 5506 | |
| 5507 my $name = $interface->name; | |
| 5508 my $headerFileName = "$outputDirectory/V8$name.h"; | |
| 5509 my $implFileName = "$outputDirectory/V8$name.cpp"; | |
| 5510 | |
| 5511 my @includes = (); | |
| 5512 foreach my $include (keys %implIncludes) { | |
| 5513 push @includes, "\"$include\""; | |
| 5514 } | |
| 5515 | |
| 5516 #FIXME: do not treat main header special | |
| 5517 my $mainInclude = "\"V8$name.h\""; | |
| 5518 foreach my $include (sort @includes) { | |
| 5519 $implementation{includes}->add("#include $include\n") unless $include eq
$mainInclude; | |
| 5520 } | |
| 5521 $implementation{includes}->add("\n") unless $interface->isCallback; | |
| 5522 WriteFileIfChanged($implFileName, $implementation{root}->toString()); | |
| 5523 | |
| 5524 %implIncludes = (); | |
| 5525 | |
| 5526 WriteFileIfChanged($headerFileName, $header{root}->toString()); | |
| 5527 } | |
| 5528 | |
| 5529 sub ConvertToV8StringResource | |
| 5530 { | |
| 5531 my $attributeOrParameter = shift; | |
| 5532 my $nativeType = shift; | |
| 5533 my $variableName = shift; | |
| 5534 my $value = shift; | |
| 5535 | |
| 5536 die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8String
Resource/; | |
| 5537 if ($attributeOrParameter->type eq "DOMString" or IsEnumType($attributeOrPar
ameter->type)) { | |
| 5538 return "V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID($nativeType, $variableName,
$value);" | |
| 5539 } else { | |
| 5540 return "$nativeType $variableName($value, true);"; | |
| 5541 } | |
| 5542 } | |
| 5543 | |
| 5544 # Returns the RuntimeEnabledFeatures function name that is hooked up to check if
a method/attribute is enabled. | |
| 5545 sub GetRuntimeEnableFunctionName | |
| 5546 { | |
| 5547 my $signature = shift; | |
| 5548 | |
| 5549 # If a parameter is given (e.g. "EnabledAtRuntime=FeatureName") return the R
untimeEnabledFeatures::{FeatureName}Enabled() method. | |
| 5550 return "RuntimeEnabledFeatures::" . ToMethodName($signature->extendedAttribu
tes->{"EnabledAtRuntime"}) . "Enabled" if ($signature->extendedAttributes->{"Ena
bledAtRuntime"} && $signature->extendedAttributes->{"EnabledAtRuntime"} ne "VALU
E_IS_MISSING"); | |
| 5551 | |
| 5552 # Otherwise return a function named RuntimeEnabledFeatures::{methodName}Enab
led(). | |
| 5553 return "RuntimeEnabledFeatures::" . ToMethodName($signature->name) . "Enable
d"; | |
| 5554 } | |
| 5555 | |
| 5556 sub GetContextEnableFunction | |
| 5557 { | |
| 5558 my $signature = shift; | |
| 5559 | |
| 5560 # If a parameter is given (e.g. "EnabledPerContext=FeatureName") return the
{FeatureName}Allowed() method. | |
| 5561 if ($signature->extendedAttributes->{"EnabledPerContext"} && $signature->ext
endedAttributes->{"EnabledPerContext"} ne "VALUE_IS_MISSING") { | |
| 5562 return "ContextFeatures::" . ToMethodName($signature->extendedAttributes
->{"EnabledPerContext"}) . "Enabled"; | |
| 5563 } | |
| 5564 | |
| 5565 # Or it fallbacks to the attribute name if the parameter value is missing. | |
| 5566 return "ContextFeatures::" . ToMethodName($signature->name) . "Enabled"; | |
| 5567 } | |
| 5568 | |
| 5569 sub GetPassRefPtrType | |
| 5570 { | |
| 5571 my $v8ClassName = shift; | |
| 5572 | |
| 5573 my $angleBracketSpace = $v8ClassName =~ />$/ ? " " : ""; | |
| 5574 return "PassRefPtr<${v8ClassName}${angleBracketSpace}>"; | |
| 5575 } | |
| 5576 | |
| 5577 sub WriteFileIfChanged | |
| 5578 { | |
| 5579 my $fileName = shift; | |
| 5580 my $contents = shift; | |
| 5581 | |
| 5582 if (-f $fileName && $writeFileOnlyIfChanged) { | |
| 5583 open FH, "<", $fileName or die "Couldn't open $fileName: $!\n"; | |
| 5584 my @lines = <FH>; | |
| 5585 my $oldContents = join "", @lines; | |
| 5586 close FH; | |
| 5587 return if $contents eq $oldContents; | |
| 5588 } | |
| 5589 open FH, ">", $fileName or die "Couldn't open $fileName: $!\n"; | |
| 5590 print FH $contents; | |
| 5591 close FH; | |
| 5592 } | |
| 5593 | |
| 5594 sub ForAllParents | |
| 5595 { | |
| 5596 my $interface = shift; | |
| 5597 my $beforeRecursion = shift; | |
| 5598 my $afterRecursion = shift; | |
| 5599 | |
| 5600 my $recurse; | |
| 5601 $recurse = sub { | |
| 5602 my $currentInterface = shift; | |
| 5603 | |
| 5604 if ($currentInterface->parent) { | |
| 5605 my $parentInterface = ParseInterface($currentInterface->parent); | |
| 5606 if ($beforeRecursion) { | |
| 5607 &$beforeRecursion($parentInterface) eq 'prune' and return; | |
| 5608 } | |
| 5609 &$recurse($parentInterface); | |
| 5610 &$afterRecursion($parentInterface) if $afterRecursion; | |
| 5611 } | |
| 5612 }; | |
| 5613 | |
| 5614 &$recurse($interface); | |
| 5615 } | |
| 5616 | |
| 5617 sub FindSuperMethod | |
| 5618 { | |
| 5619 my ($interface, $functionName) = @_; | |
| 5620 my $indexer; | |
| 5621 ForAllParents($interface, undef, sub { | |
| 5622 my $currentInterface = shift; | |
| 5623 foreach my $function (@{$currentInterface->functions}) { | |
| 5624 if ($function->name eq $functionName) { | |
| 5625 $indexer = $function; | |
| 5626 return 'prune'; | |
| 5627 } | |
| 5628 } | |
| 5629 }); | |
| 5630 return $indexer; | |
| 5631 } | |
| 5632 | |
| 5633 sub IsConstructorTemplate | |
| 5634 { | |
| 5635 my $interface = shift; | |
| 5636 my $template = shift; | |
| 5637 | |
| 5638 return $interface->extendedAttributes->{"ConstructorTemplate"} && $interface
->extendedAttributes->{"ConstructorTemplate"} eq $template; | |
| 5639 } | |
| 5640 | |
| 5641 sub IsPrimitiveType | |
| 5642 { | |
| 5643 my $type = shift; | |
| 5644 | |
| 5645 return 1 if $primitiveTypeHash{$type}; | |
| 5646 return 0; | |
| 5647 } | |
| 5648 | |
| 5649 sub IsCallbackFunctionType | |
| 5650 { | |
| 5651 my $type = shift; | |
| 5652 | |
| 5653 return 1 if $callbackFunctionTypeHash{$type}; | |
| 5654 return 0; | |
| 5655 } | |
| 5656 | |
| 5657 sub IsEnumType | |
| 5658 { | |
| 5659 my $type = shift; | |
| 5660 | |
| 5661 return 1 if $enumTypeHash{$type}; | |
| 5662 return 0; | |
| 5663 } | |
| 5664 | |
| 5665 sub ValidEnumValues | |
| 5666 { | |
| 5667 my $type = shift; | |
| 5668 | |
| 5669 return @{$enumTypeHash{$type}}; | |
| 5670 } | |
| 5671 | |
| 5672 sub IsSVGTypeNeedingTearOff | |
| 5673 { | |
| 5674 my $type = shift; | |
| 5675 | |
| 5676 return 1 if $svgTypeNeedingTearOff{$type}; | |
| 5677 return 0; | |
| 5678 } | |
| 5679 | |
| 5680 sub IsSVGTypeWithWritablePropertiesNeedingTearOff | |
| 5681 { | |
| 5682 my $type = shift; | |
| 5683 | |
| 5684 return 1 if $svgTypeWithWritablePropertiesNeedingTearOff{$type}; | |
| 5685 return 0; | |
| 5686 } | |
| 5687 | |
| 5688 sub IsTypedArrayType | |
| 5689 { | |
| 5690 my $type = shift; | |
| 5691 return 1 if $typedArrayHash{$type}; | |
| 5692 return 0; | |
| 5693 } | |
| 5694 | |
| 5695 sub IsRefPtrType | |
| 5696 { | |
| 5697 my $type = shift; | |
| 5698 | |
| 5699 return 0 if $type eq "any"; | |
| 5700 return 0 if IsPrimitiveType($type); | |
| 5701 return 0 if GetArrayType($type); | |
| 5702 return 0 if GetSequenceType($type); | |
| 5703 return 0 if $type eq "DOMString"; | |
| 5704 return 0 if IsCallbackFunctionType($type); | |
| 5705 return 0 if IsEnumType($type); | |
| 5706 return 0 if IsUnionType($type); | |
| 5707 | |
| 5708 return 1; | |
| 5709 } | |
| 5710 | |
| 5711 sub GetSVGTypeNeedingTearOff | |
| 5712 { | |
| 5713 my $type = shift; | |
| 5714 | |
| 5715 return $svgTypeNeedingTearOff{$type} if exists $svgTypeNeedingTearOff{$type}
; | |
| 5716 return undef; | |
| 5717 } | |
| 5718 | |
| 5719 sub GetSVGWrappedTypeNeedingTearOff | |
| 5720 { | |
| 5721 my $type = shift; | |
| 5722 | |
| 5723 my $svgTypeNeedingTearOff = GetSVGTypeNeedingTearOff($type); | |
| 5724 return $svgTypeNeedingTearOff if not $svgTypeNeedingTearOff; | |
| 5725 | |
| 5726 if ($svgTypeNeedingTearOff =~ /SVGPropertyTearOff/) { | |
| 5727 $svgTypeNeedingTearOff =~ s/SVGPropertyTearOff<//; | |
| 5728 } elsif ($svgTypeNeedingTearOff =~ /SVGListPropertyTearOff/) { | |
| 5729 $svgTypeNeedingTearOff =~ s/SVGListPropertyTearOff<//; | |
| 5730 } elsif ($svgTypeNeedingTearOff =~ /SVGStaticListPropertyTearOff/) { | |
| 5731 $svgTypeNeedingTearOff =~ s/SVGStaticListPropertyTearOff<//; | |
| 5732 } elsif ($svgTypeNeedingTearOff =~ /SVGTransformListPropertyTearOff/) { | |
| 5733 $svgTypeNeedingTearOff =~ s/SVGTransformListPropertyTearOff<//; | |
| 5734 } | |
| 5735 | |
| 5736 $svgTypeNeedingTearOff =~ s/>//; | |
| 5737 return $svgTypeNeedingTearOff; | |
| 5738 } | |
| 5739 | |
| 5740 sub IsSVGAnimatedType | |
| 5741 { | |
| 5742 my $type = shift; | |
| 5743 | |
| 5744 return 1 if $svgAnimatedTypeHash{$type}; | |
| 5745 return 0; | |
| 5746 } | |
| 5747 | |
| 5748 sub GetSequenceType | |
| 5749 { | |
| 5750 my $type = shift; | |
| 5751 | |
| 5752 return $1 if $type =~ /^sequence<([\w\d_\s]+)>.*/; | |
| 5753 return ""; | |
| 5754 } | |
| 5755 | |
| 5756 sub GetArrayType | |
| 5757 { | |
| 5758 my $type = shift; | |
| 5759 | |
| 5760 return $1 if $type =~ /^([\w\d_\s]+)\[\]/; | |
| 5761 return ""; | |
| 5762 } | |
| 5763 | |
| 5764 sub GetArrayOrSequenceType | |
| 5765 { | |
| 5766 my $type = shift; | |
| 5767 | |
| 5768 return GetArrayType($type) || GetSequenceType($type); | |
| 5769 } | |
| 5770 | |
| 5771 sub AssertNotSequenceType | |
| 5772 { | |
| 5773 my $type = shift; | |
| 5774 die "Sequences must not be used as the type of an attribute, constant or exc
eption field." if GetSequenceType($type); | |
| 5775 } | |
| 5776 | |
| 5777 sub FirstLetterToUpperCase | |
| 5778 { | |
| 5779 my $param = shift; | |
| 5780 my $ret = ucfirst($param); | |
| 5781 # xmlEncoding becomes XMLEncoding, but xmlllang becomes Xmllang. | |
| 5782 $ret =~ s/Xml/XML/ if $ret =~ /^Xml[^a-z]/; | |
| 5783 $ret =~ s/Css/CSS/ if $ret =~ /^Css[^T]/; # css -> setCSS, except setCssTex
t. | |
| 5784 $ret =~ s/Ime/IME/ if $ret =~ /^Ime/; # ime -> setIME | |
| 5785 return $ret; | |
| 5786 } | |
| 5787 | |
| 5788 # URL becomes url, but SetURL becomes setURL. | |
| 5789 sub ToMethodName | |
| 5790 { | |
| 5791 my $param = shift; | |
| 5792 my $ret = lcfirst($param); | |
| 5793 $ret =~ s/hTML/html/ if $ret =~ /^hTML/; | |
| 5794 $ret =~ s/uRL/url/ if $ret =~ /^uRL/; | |
| 5795 $ret =~ s/jS/js/ if $ret =~ /^jS/; | |
| 5796 $ret =~ s/xML/xml/ if $ret =~ /^xML/; | |
| 5797 $ret =~ s/xSLT/xslt/ if $ret =~ /^xSLT/; | |
| 5798 $ret =~ s/cSS/css/ if $ret =~ /^cSS/; | |
| 5799 | |
| 5800 # For HTML5 FileSystem API Flags attributes. | |
| 5801 # (create is widely used to instantiate an object and must be avoided.) | |
| 5802 $ret =~ s/^create/isCreate/ if $ret =~ /^create$/; | |
| 5803 $ret =~ s/^exclusive/isExclusive/ if $ret =~ /^exclusive$/; | |
| 5804 | |
| 5805 return $ret; | |
| 5806 } | |
| 5807 | |
| 5808 sub NamespaceForAttributeName | |
| 5809 { | |
| 5810 my ($interfaceName, $attributeName) = @_; | |
| 5811 return "SVGNames" if $interfaceName =~ /^SVG/ && !$svgAttributesInHTMLHash{$
attributeName}; | |
| 5812 return "HTMLNames"; | |
| 5813 } | |
| 5814 | |
| 5815 # Identifies overloaded functions and for each function adds an array with | |
| 5816 # links to its respective overloads (including itself). | |
| 5817 sub LinkOverloadedFunctions | |
| 5818 { | |
| 5819 my $interface = shift; | |
| 5820 | |
| 5821 my %nameToFunctionsMap = (); | |
| 5822 foreach my $function (@{$interface->functions}) { | |
| 5823 my $name = $function->name; | |
| 5824 $nameToFunctionsMap{$name} = [] if !exists $nameToFunctionsMap{$name} or
!$name; # Nameless functions cannot be overloaded | |
| 5825 push(@{$nameToFunctionsMap{$name}}, $function); | |
| 5826 $function->{overloads} = $nameToFunctionsMap{$name}; | |
| 5827 $function->{overloadIndex} = @{$nameToFunctionsMap{$name}}; | |
| 5828 } | |
| 5829 } | |
| 5830 | |
| 5831 sub AttributeNameForGetterAndSetter | |
| 5832 { | |
| 5833 my $attribute = shift; | |
| 5834 | |
| 5835 my $attributeName = GetImplName($attribute); | |
| 5836 if ($attribute->extendedAttributes->{"ImplementedAs"}) { | |
| 5837 $attributeName = $attribute->extendedAttributes->{"ImplementedAs"}; | |
| 5838 } | |
| 5839 my $attributeType = $attribute->type; | |
| 5840 | |
| 5841 # Avoid clash with C++ keyword. | |
| 5842 $attributeName = "_operator" if $attributeName eq "operator"; | |
| 5843 | |
| 5844 # SVGAElement defines a non-virtual "String& target() const" method which cl
ashes with "virtual String target() const" in Element. | |
| 5845 # To solve this issue the SVGAElement method was renamed to "svgTarget", tak
e care of that when calling this method. | |
| 5846 $attributeName = "svgTarget" if $attributeName eq "target" and $attributeTyp
e eq "SVGAnimatedString"; | |
| 5847 | |
| 5848 # SVG animated types need to use a special attribute name. | |
| 5849 # The rest of the special casing for SVG animated types is handled in the la
nguage-specific code generators. | |
| 5850 $attributeName .= "Animated" if IsSVGAnimatedType($attributeType); | |
| 5851 | |
| 5852 return $attributeName; | |
| 5853 } | |
| 5854 | |
| 5855 sub ContentAttributeName | |
| 5856 { | |
| 5857 my ($interfaceName, $attribute) = @_; | |
| 5858 | |
| 5859 my $contentAttributeName = $attribute->extendedAttributes->{"Reflect"}; | |
| 5860 return undef if !$contentAttributeName; | |
| 5861 | |
| 5862 $contentAttributeName = lc AttributeNameForGetterAndSetter($attribute) if $c
ontentAttributeName eq "VALUE_IS_MISSING"; | |
| 5863 | |
| 5864 my $namespace = NamespaceForAttributeName($interfaceName, $contentAttributeN
ame); | |
| 5865 | |
| 5866 AddToImplIncludes("${namespace}.h"); | |
| 5867 return "WebCore::${namespace}::${contentAttributeName}Attr"; | |
| 5868 } | |
| 5869 | |
| 5870 sub CanUseFastAttribute | |
| 5871 { | |
| 5872 my $attribute = shift; | |
| 5873 return !IsSVGAnimatedType($attribute->type); | |
| 5874 } | |
| 5875 | |
| 5876 sub GetterExpression | |
| 5877 { | |
| 5878 my ($interfaceName, $attribute) = @_; | |
| 5879 | |
| 5880 my $contentAttributeName = ContentAttributeName($interfaceName, $attribute); | |
| 5881 | |
| 5882 if (!$contentAttributeName) { | |
| 5883 return (ToMethodName(AttributeNameForGetterAndSetter($attribute))); | |
| 5884 } | |
| 5885 | |
| 5886 my $functionName; | |
| 5887 if ($attribute->extendedAttributes->{"URL"}) { | |
| 5888 $functionName = "getURLAttribute"; | |
| 5889 } elsif ($attribute->type eq "boolean") { | |
| 5890 if (CanUseFastAttribute($attribute)) { | |
| 5891 $functionName = "fastHasAttribute"; | |
| 5892 } else { | |
| 5893 $functionName = "hasAttribute"; | |
| 5894 } | |
| 5895 } elsif ($attribute->type eq "long") { | |
| 5896 $functionName = "getIntegralAttribute"; | |
| 5897 } elsif ($attribute->type eq "unsigned long") { | |
| 5898 $functionName = "getUnsignedIntegralAttribute"; | |
| 5899 } else { | |
| 5900 if ($contentAttributeName eq "WebCore::HTMLNames::idAttr") { | |
| 5901 $functionName = "getIdAttribute"; | |
| 5902 $contentAttributeName = ""; | |
| 5903 } elsif ($contentAttributeName eq "WebCore::HTMLNames::nameAttr") { | |
| 5904 $functionName = "getNameAttribute"; | |
| 5905 $contentAttributeName = ""; | |
| 5906 } elsif ($contentAttributeName eq "WebCore::HTMLNames::classAttr") { | |
| 5907 $functionName = "getClassAttribute"; | |
| 5908 $contentAttributeName = ""; | |
| 5909 } elsif (CanUseFastAttribute($attribute)) { | |
| 5910 $functionName = "fastGetAttribute"; | |
| 5911 } else { | |
| 5912 $functionName = "getAttribute"; | |
| 5913 } | |
| 5914 } | |
| 5915 | |
| 5916 return ($functionName, $contentAttributeName); | |
| 5917 } | |
| 5918 | |
| 5919 sub SetterExpression | |
| 5920 { | |
| 5921 my ($interfaceName, $attribute) = @_; | |
| 5922 | |
| 5923 my $contentAttributeName = ContentAttributeName($interfaceName, $attribute); | |
| 5924 | |
| 5925 if (!$contentAttributeName) { | |
| 5926 return ("set" . FirstLetterToUpperCase(AttributeNameForGetterAndSetter($
attribute))); | |
| 5927 } | |
| 5928 | |
| 5929 my $functionName; | |
| 5930 if ($attribute->type eq "boolean") { | |
| 5931 $functionName = "setBooleanAttribute"; | |
| 5932 } elsif ($attribute->type eq "long") { | |
| 5933 $functionName = "setIntegralAttribute"; | |
| 5934 } elsif ($attribute->type eq "unsigned long") { | |
| 5935 $functionName = "setUnsignedIntegralAttribute"; | |
| 5936 } else { | |
| 5937 $functionName = "setAttribute"; | |
| 5938 } | |
| 5939 | |
| 5940 return ($functionName, $contentAttributeName); | |
| 5941 } | |
| 5942 | |
| 5943 sub GenerateConditionalString | |
| 5944 { | |
| 5945 my $node = shift; | |
| 5946 | |
| 5947 my $conditional = $node->extendedAttributes->{"Conditional"}; | |
| 5948 if ($conditional) { | |
| 5949 return GenerateConditionalStringFromAttributeValue($conditional); | |
| 5950 } else { | |
| 5951 return ""; | |
| 5952 } | |
| 5953 } | |
| 5954 | |
| 5955 sub GenerateConditionalStringFromAttributeValue | |
| 5956 { | |
| 5957 my $conditional = shift; | |
| 5958 | |
| 5959 my $operator = ($conditional =~ /&/ ? '&' : ($conditional =~ /\|/ ? '|' : ''
)); | |
| 5960 if ($operator) { | |
| 5961 # Avoid duplicated conditions. | |
| 5962 my %conditions; | |
| 5963 map { $conditions{$_} = 1 } split('\\' . $operator, $conditional); | |
| 5964 return "ENABLE(" . join(") $operator$operator ENABLE(", sort keys %condi
tions) . ")"; | |
| 5965 } else { | |
| 5966 return "ENABLE(" . $conditional . ")"; | |
| 5967 } | |
| 5968 } | |
| 5969 | |
| 5970 sub GenerateCompileTimeCheckForEnumsIfNeeded | |
| 5971 { | |
| 5972 my $interface = shift; | |
| 5973 my $implClassName = GetImplName($interface); | |
| 5974 my @checks = (); | |
| 5975 # If necessary, check that all constants are available as enums with the sam
e value. | |
| 5976 if (!$interface->extendedAttributes->{"DoNotCheckConstants"} && @{$interface
->constants}) { | |
| 5977 push(@checks, "\n"); | |
| 5978 foreach my $constant (@{$interface->constants}) { | |
| 5979 my $reflect = $constant->extendedAttributes->{"Reflect"}; | |
| 5980 my $name = $reflect ? $reflect : $constant->name; | |
| 5981 my $value = $constant->value; | |
| 5982 my $conditionalString = GenerateConditionalString($constant); | |
| 5983 push(@checks, "#if ${conditionalString}\n") if $conditionalString; | |
| 5984 | |
| 5985 if ($constant->extendedAttributes->{"ImplementedBy"}) { | |
| 5986 my $implementedByImplName = GetImplNameFromImplementedBy($consta
nt->extendedAttributes->{"ImplementedBy"}); | |
| 5987 push(@checks, "COMPILE_ASSERT($value == " . $implementedByImplNa
me . "::$name, ${implClassName}Enum${name}IsWrongUseDoNotCheckConstants);\n"); | |
| 5988 } else { | |
| 5989 push(@checks, "COMPILE_ASSERT($value == ${implClassName}::$name,
${implClassName}Enum${name}IsWrongUseDoNotCheckConstants);\n"); | |
| 5990 } | |
| 5991 | |
| 5992 push(@checks, "#endif\n") if $conditionalString; | |
| 5993 } | |
| 5994 push(@checks, "\n"); | |
| 5995 } | |
| 5996 return @checks; | |
| 5997 } | |
| 5998 | |
| 5999 sub ExtendedAttributeContains | |
| 6000 { | |
| 6001 my $callWith = shift; | |
| 6002 return 0 unless $callWith; | |
| 6003 my $keyword = shift; | |
| 6004 | |
| 6005 my @callWithKeywords = split /\s*\&\s*/, $callWith; | |
| 6006 return grep { $_ eq $keyword } @callWithKeywords; | |
| 6007 } | |
| 6008 | |
| 6009 sub InheritsInterface | |
| 6010 { | |
| 6011 my $interface = shift; | |
| 6012 my $interfaceName = shift; | |
| 6013 my $found = 0; | |
| 6014 | |
| 6015 return 1 if $interfaceName eq $interface->name; | |
| 6016 ForAllParents($interface, sub { | |
| 6017 my $currentInterface = shift; | |
| 6018 if ($currentInterface->name eq $interfaceName) { | |
| 6019 $found = 1; | |
| 6020 } | |
| 6021 return 1 if $found; | |
| 6022 }, 0); | |
| 6023 | |
| 6024 return $found; | |
| 6025 } | |
| 6026 | |
| 6027 sub InheritsExtendedAttribute | |
| 6028 { | |
| 6029 my $interface = shift; | |
| 6030 my $extendedAttribute = shift; | |
| 6031 my $found = 0; | |
| 6032 | |
| 6033 return 1 if $interface->extendedAttributes->{$extendedAttribute}; | |
| 6034 ForAllParents($interface, sub { | |
| 6035 my $currentInterface = shift; | |
| 6036 if ($currentInterface->extendedAttributes->{$extendedAttribute}) { | |
| 6037 $found = 1; | |
| 6038 } | |
| 6039 return 1 if $found; | |
| 6040 }, 0); | |
| 6041 | |
| 6042 return $found; | |
| 6043 } | |
| 6044 | |
| 6045 1; | |
| OLD | NEW |