| 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, 2014 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 code_generator_v8; | |
| 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 $verbose; | |
| 122 my $interfaceIdlFiles; | |
| 123 my $writeFileOnlyIfChanged; | |
| 124 my $sourceRoot; | |
| 125 | |
| 126 # Cache of IDL file pathnames. | |
| 127 my $idlFiles; | |
| 128 my $cachedInterfaces = {}; | |
| 129 | |
| 130 my %implIncludes = (); | |
| 131 my %headerIncludes = (); | |
| 132 | |
| 133 # Header code structure: | |
| 134 # Root ... Copyright, include duplication check | |
| 135 # Conditional ... #if FEATURE ... #endif (to be removed soon) | |
| 136 # Includes | |
| 137 # NameSpaceWebCore | |
| 138 # Class | |
| 139 # ClassPublic | |
| 140 # ClassPrivate | |
| 141 my %header; | |
| 142 | |
| 143 # Implementation code structure: | |
| 144 # Root ... Copyright | |
| 145 # Conditional ... #if FEATURE ... #endif (to be removed soon) | |
| 146 # Includes | |
| 147 # NameSpaceWebCore | |
| 148 # NameSpaceInternal ... namespace ${implClassName}V8Internal in case of no
n-callback | |
| 149 my %implementation; | |
| 150 | |
| 151 # The integer primitive types, a map from an IDL integer type to its | |
| 152 # binding-level type name. | |
| 153 # | |
| 154 # NOTE: For the unsigned types, the "UI" prefix is used (and not | |
| 155 # "Ui"), so as to match onto the naming of V8Binding conversion | |
| 156 # methods (and not the Typed Array naming scheme for unsigned types.) | |
| 157 my %integerTypeHash = ("byte" => "Int8", | |
| 158 "octet" => "UInt8", | |
| 159 "short" => "Int16", | |
| 160 "long" => "Int32", | |
| 161 "long long" => "Int64", | |
| 162 "unsigned short" => "UInt16", | |
| 163 "unsigned long" => "UInt32", | |
| 164 "unsigned long long" => "UInt64" | |
| 165 ); | |
| 166 | |
| 167 # Other primitive types | |
| 168 # | |
| 169 # Promise is not yet in the Web IDL spec but is going to be speced | |
| 170 # as primitive types in the future. | |
| 171 # Since V8 dosn't provide Promise primitive object currently, | |
| 172 # primitiveTypeHash doesn't contain Promise. | |
| 173 my %primitiveTypeHash = ("Date" => 1, | |
| 174 "DOMString" => 1, | |
| 175 "DOMTimeStamp" => 1, # typedef unsigned long long | |
| 176 "boolean" => 1, | |
| 177 "void" => 1, | |
| 178 "float" => 1, | |
| 179 "double" => 1, | |
| 180 ); | |
| 181 | |
| 182 my %nonWrapperTypes = ("CompareHow" => 1, | |
| 183 "Dictionary" => 1, | |
| 184 "EventHandler" => 1, | |
| 185 "EventListener" => 1, | |
| 186 "MediaQueryListListener" => 1, | |
| 187 "NodeFilter" => 1, | |
| 188 "SerializedScriptValue" => 1, | |
| 189 "any" => 1, | |
| 190 ); | |
| 191 | |
| 192 my %typedArrayHash = ("ArrayBuffer" => [], | |
| 193 "ArrayBufferView" => [], | |
| 194 "Uint8Array" => ["unsigned char", "v8::kExternalUnsignedBy
teArray"], | |
| 195 "Uint8ClampedArray" => ["unsigned char", "v8::kExternalPix
elArray"], | |
| 196 "Uint16Array" => ["unsigned short", "v8::kExternalUnsigned
ShortArray"], | |
| 197 "Uint32Array" => ["unsigned int", "v8::kExternalUnsignedIn
tArray"], | |
| 198 "Int8Array" => ["signed char", "v8::kExternalByteArray"], | |
| 199 "Int16Array" => ["short", "v8::kExternalShortArray"], | |
| 200 "Int32Array" => ["int", "v8::kExternalIntArray"], | |
| 201 "Float32Array" => ["float", "v8::kExternalFloatArray"], | |
| 202 "Float64Array" => ["double", "v8::kExternalDoubleArray"], | |
| 203 ); | |
| 204 | |
| 205 my %domNodeTypes = ("Attr" => 1, | |
| 206 "CDATASection" => 1, | |
| 207 "CharacterData" => 1, | |
| 208 "Comment" => 1, | |
| 209 "Document" => 1, | |
| 210 "DocumentFragment" => 1, | |
| 211 "DocumentType" => 1, | |
| 212 "Element" => 1, | |
| 213 "Entity" => 1, | |
| 214 "HTMLDocument" => 1, | |
| 215 "Node" => 1, | |
| 216 "Notation" => 1, | |
| 217 "ProcessingInstruction" => 1, | |
| 218 "ShadowRoot" => 1, | |
| 219 "Text" => 1, | |
| 220 "TestNode" => 1, | |
| 221 "TestInterfaceDocument" => 1, | |
| 222 "TestInterfaceNode" => 1, | |
| 223 "XMLDocument" => 1, | |
| 224 ); | |
| 225 | |
| 226 my %callbackFunctionTypeHash = (); | |
| 227 | |
| 228 my %enumTypeHash = (); | |
| 229 | |
| 230 my %svgAttributesInHTMLHash = ("class" => 1, "id" => 1, "onabort" => 1, "onclick
" => 1, | |
| 231 "onerror" => 1, "onload" => 1, "onmousedown" => 1
, | |
| 232 "onmouseenter" => 1, "onmouseleave" => 1, | |
| 233 "onmousemove" => 1, "onmouseout" => 1, "onmouseov
er" => 1, | |
| 234 "onmouseup" => 1, "onresize" => 1, "onscroll" =>
1, | |
| 235 "onunload" => 1); | |
| 236 | |
| 237 my %svgTypeNewPropertyImplementation = ( | |
| 238 "SVGAngle" => 1, | |
| 239 "SVGLength" => 1, | |
| 240 "SVGLengthList" => 1, | |
| 241 "SVGNumber" => 1, | |
| 242 "SVGNumberList" => 1, | |
| 243 "SVGPathSegList" => 1, | |
| 244 "SVGPoint" => 1, | |
| 245 "SVGPointList" => 1, | |
| 246 "SVGPreserveAspectRatio" => 1, | |
| 247 "SVGRect" => 1, | |
| 248 "SVGString" => 1, | |
| 249 "SVGStringList" => 1, | |
| 250 "SVGTransform" => 1, | |
| 251 "SVGTransformList" => 1, | |
| 252 ); | |
| 253 | |
| 254 my %svgTypeNeedingTearOff = ( | |
| 255 ); | |
| 256 | |
| 257 my %svgTypeWithWritablePropertiesNeedingTearOff = ( | |
| 258 ); | |
| 259 | |
| 260 # Default license header | |
| 261 my $licenseHeader = <<EOF; | |
| 262 /* | |
| 263 * Copyright (C) 2013 Google Inc. All rights reserved. | |
| 264 * | |
| 265 * Redistribution and use in source and binary forms, with or without | |
| 266 * modification, are permitted provided that the following conditions are | |
| 267 * met: | |
| 268 * | |
| 269 * * Redistributions of source code must retain the above copyright | |
| 270 * notice, this list of conditions and the following disclaimer. | |
| 271 * * Redistributions in binary form must reproduce the above | |
| 272 * copyright notice, this list of conditions and the following disclaimer | |
| 273 * in the documentation and/or other materials provided with the | |
| 274 * distribution. | |
| 275 * * Neither the name of Google Inc. nor the names of its | |
| 276 * contributors may be used to endorse or promote products derived from | |
| 277 * this software without specific prior written permission. | |
| 278 * | |
| 279 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 280 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 281 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 282 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 283 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 284 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 285 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 286 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 287 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 288 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 289 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 290 */ | |
| 291 | |
| 292 // This file has been auto-generated by code_generator_v8.pm. DO NOT MODIFY! | |
| 293 | |
| 294 EOF | |
| 295 | |
| 296 sub new | |
| 297 { | |
| 298 my $object = shift; | |
| 299 my $reference = { }; | |
| 300 | |
| 301 $idlDocument = shift; | |
| 302 $idlDirectories = shift; | |
| 303 $preprocessor = shift; | |
| 304 $verbose = shift; | |
| 305 $interfaceIdlFiles = shift; | |
| 306 $writeFileOnlyIfChanged = shift; | |
| 307 | |
| 308 $sourceRoot = dirname(dirname(dirname(Cwd::abs_path($0)))); | |
| 309 | |
| 310 bless($reference, $object); | |
| 311 return $reference; | |
| 312 } | |
| 313 | |
| 314 | |
| 315 sub IDLFileForInterface | |
| 316 { | |
| 317 my $interfaceName = shift; | |
| 318 | |
| 319 unless ($idlFiles) { | |
| 320 my @directories = map { $_ = "$sourceRoot/$_" if -d "$sourceRoot/$_"; $_
} @$idlDirectories; | |
| 321 push(@directories, "."); | |
| 322 | |
| 323 $idlFiles = { }; | |
| 324 foreach my $idlFile (@$interfaceIdlFiles) { | |
| 325 $idlFiles->{fileparse(basename($idlFile), ".idl")} = $idlFile; | |
| 326 } | |
| 327 | |
| 328 my $wanted = sub { | |
| 329 $idlFiles->{$1} = $File::Find::name if /^([A-Z].*)\.idl$/; | |
| 330 $File::Find::prune = 1 if /^\../; | |
| 331 }; | |
| 332 find($wanted, @directories); | |
| 333 } | |
| 334 | |
| 335 return $idlFiles->{$interfaceName}; | |
| 336 } | |
| 337 | |
| 338 sub ParseInterface | |
| 339 { | |
| 340 my $interfaceName = shift; | |
| 341 | |
| 342 if (exists $cachedInterfaces->{$interfaceName}) { | |
| 343 return $cachedInterfaces->{$interfaceName}; | |
| 344 } | |
| 345 | |
| 346 # Step #1: Find the IDL file associated with 'interface' | |
| 347 my $filename = IDLFileForInterface($interfaceName) | |
| 348 or die("Could NOT find IDL file for interface \"$interfaceName\" $!\n"); | |
| 349 | |
| 350 print " | |> Parsing parent IDL \"$filename\" for interface \"$interfaceN
ame\"\n" if $verbose; | |
| 351 | |
| 352 # Step #2: Parse the found IDL file (in quiet mode). | |
| 353 my $parser = idl_parser->new(1); | |
| 354 my $document = $parser->Parse($filename, $preprocessor); | |
| 355 | |
| 356 foreach my $interface (@{$document->interfaces}) { | |
| 357 if ($interface->name eq $interfaceName or $interface->isPartial) { | |
| 358 $cachedInterfaces->{$interfaceName} = $interface; | |
| 359 return $interface; | |
| 360 } | |
| 361 } | |
| 362 | |
| 363 die("Could NOT find interface definition for $interfaceName in $filename"); | |
| 364 } | |
| 365 | |
| 366 sub GenerateInterface | |
| 367 { | |
| 368 my $object = shift; | |
| 369 my $interface = shift; | |
| 370 | |
| 371 %callbackFunctionTypeHash = map { $_->name => $_ } @{$idlDocument->callbackF
unctions}; | |
| 372 %enumTypeHash = map { $_->name => $_->values } @{$idlDocument->enumerations}
; | |
| 373 my $v8ClassName = GetV8ClassName($interface); | |
| 374 my $defineName = $v8ClassName . "_h"; | |
| 375 my $internalNamespace = GetImplName($interface) . "V8Internal"; | |
| 376 | |
| 377 my $conditionalString = GenerateConditionalString($interface); | |
| 378 my $conditionalIf = ""; | |
| 379 my $conditionalEndif = ""; | |
| 380 if ($conditionalString) { | |
| 381 $conditionalIf = "#if ${conditionalString}"; | |
| 382 $conditionalEndif = "#endif // ${conditionalString}"; | |
| 383 } | |
| 384 | |
| 385 $header{root} = new Block("ROOT", "", ""); | |
| 386 # FIXME: newlines should be generated by Block::toString(). | |
| 387 $header{conditional} = new Block("Conditional", "$conditionalIf", $condition
alEndif ? "$conditionalEndif" : ""); | |
| 388 $header{includes} = new Block("Includes", "", ""); | |
| 389 $header{nameSpaceWebCore} = new Block("Namespace WebCore", "\nnamespace WebC
ore {\n", "}"); | |
| 390 $header{class} = new Block("Class definition", "", ""); | |
| 391 $header{classPublic} = new Block("Class public:", "public:", ""); | |
| 392 $header{classPrivate} = new Block("Class private:", "private:", ""); | |
| 393 | |
| 394 $header{root}->add($header{conditional}); | |
| 395 $header{conditional}->add($header{includes}); | |
| 396 $header{conditional}->add($header{nameSpaceWebCore}); | |
| 397 $header{nameSpaceWebCore}->add($header{class}); | |
| 398 $header{class}->add($header{classPublic}); | |
| 399 $header{class}->add($header{classPrivate}); | |
| 400 | |
| 401 # - Add default header template | |
| 402 $header{root}->addHeader($licenseHeader); | |
| 403 $header{root}->addHeader("#ifndef $defineName\n#define $defineName\n"); | |
| 404 $header{root}->addFooter("#endif // $defineName"); | |
| 405 | |
| 406 $implementation{root} = new Block("ROOT", "", ""); | |
| 407 $implementation{conditional} = new Block("Conditional", $conditionalIf, $con
ditionalEndif); | |
| 408 $implementation{includes} = new Block("Includes", "", ""); | |
| 409 | |
| 410 # FIXME: newlines should be generated by Block::toString(). | |
| 411 my $nameSpaceWebCoreBegin = "namespace WebCore {\n"; | |
| 412 my $nameSpaceWebCoreEnd = "} // namespace WebCore"; | |
| 413 $nameSpaceWebCoreBegin = "$nameSpaceWebCoreBegin\n" unless $interface->isCal
lback; | |
| 414 $nameSpaceWebCoreBegin = "\n$nameSpaceWebCoreBegin" if $interface->isCallbac
k; | |
| 415 $implementation{nameSpaceWebCore} = new Block("Namespace WebCore", $nameSpac
eWebCoreBegin, $nameSpaceWebCoreEnd); | |
| 416 $implementation{nameSpaceInternal} = new Block("Internal namespace", "namesp
ace $internalNamespace {\n", "} // namespace $internalNamespace\n"); | |
| 417 | |
| 418 $implementation{root}->add($implementation{conditional}); | |
| 419 $implementation{conditional}->add($implementation{includes}); | |
| 420 $implementation{conditional}->add($implementation{nameSpaceWebCore}); | |
| 421 if (!$interface->isCallback) { | |
| 422 $implementation{nameSpaceWebCore}->add($implementation{nameSpaceInternal
}); | |
| 423 } | |
| 424 | |
| 425 # - Add default header template | |
| 426 $implementation{root}->addHeader($licenseHeader); | |
| 427 $implementation{root}->addHeader("#include \"config.h\""); | |
| 428 $implementation{includes}->add("#include \"${v8ClassName}.h\"\n\n"); | |
| 429 | |
| 430 # Start actual generation | |
| 431 if ($interface->isCallback) { | |
| 432 $object->GenerateCallbackHeader($interface); | |
| 433 $object->GenerateCallbackImplementation($interface); | |
| 434 } else { | |
| 435 $object->GenerateHeader($interface); | |
| 436 $object->GenerateImplementation($interface); | |
| 437 } | |
| 438 } | |
| 439 | |
| 440 sub AddToImplIncludes | |
| 441 { | |
| 442 my $header = shift; | |
| 443 $implIncludes{$header} = 1; | |
| 444 } | |
| 445 | |
| 446 sub AddToHeaderIncludes | |
| 447 { | |
| 448 my @includes = @_; | |
| 449 | |
| 450 for my $include (@includes) { | |
| 451 $headerIncludes{$include} = 1; | |
| 452 } | |
| 453 } | |
| 454 | |
| 455 sub AddIncludesForType | |
| 456 { | |
| 457 my $type = shift; | |
| 458 | |
| 459 return if IsPrimitiveType($type) or IsEnumType($type) or $type eq "object"; | |
| 460 | |
| 461 $type = $1 if $type =~ /SVG\w+TearOff<(\w+)>/; | |
| 462 | |
| 463 # Handle non-wrapper types explicitly | |
| 464 if ($type eq "any" || IsCallbackFunctionType($type)) { | |
| 465 AddToImplIncludes("bindings/v8/ScriptValue.h"); | |
| 466 } elsif ($type eq "CompareHow") { | |
| 467 } elsif ($type eq "Dictionary") { | |
| 468 AddToImplIncludes("bindings/v8/Dictionary.h"); | |
| 469 } elsif ($type eq "EventHandler") { | |
| 470 AddToImplIncludes("bindings/v8/V8AbstractEventListener.h"); | |
| 471 AddToImplIncludes("bindings/v8/V8EventListenerList.h"); | |
| 472 } elsif ($type eq "EventListener") { | |
| 473 AddToImplIncludes("bindings/v8/BindingSecurity.h"); | |
| 474 AddToImplIncludes("bindings/v8/V8EventListenerList.h"); | |
| 475 AddToImplIncludes("core/frame/DOMWindow.h"); | |
| 476 } elsif ($type eq "MediaQueryListListener") { | |
| 477 AddToImplIncludes("core/css/MediaQueryListListener.h"); | |
| 478 } elsif ($type eq "Promise") { | |
| 479 AddToImplIncludes("bindings/v8/ScriptPromise.h"); | |
| 480 } elsif ($type eq "SerializedScriptValue") { | |
| 481 AddToImplIncludes("bindings/v8/SerializedScriptValue.h"); | |
| 482 } elsif (IsTypedArrayType($type)) { | |
| 483 AddToImplIncludes("bindings/v8/custom/V8${type}Custom.h"); | |
| 484 } elsif (my $arrayType = GetArrayType($type)) { | |
| 485 AddIncludesForType($arrayType); | |
| 486 } elsif (my $sequenceType = GetSequenceType($type)) { | |
| 487 AddIncludesForType($sequenceType); | |
| 488 } elsif (IsUnionType($type)) { | |
| 489 for my $unionMemberType (@{$type->unionMemberTypes}) { | |
| 490 AddIncludesForType($unionMemberType); | |
| 491 } | |
| 492 } else { | |
| 493 AddToImplIncludes("V8${type}.h"); | |
| 494 } | |
| 495 } | |
| 496 | |
| 497 sub HeaderFilesForInterface | |
| 498 { | |
| 499 my $interfaceName = shift; | |
| 500 my $implClassName = shift; | |
| 501 | |
| 502 my @includes = (); | |
| 503 if (IsPrimitiveType($interfaceName) or IsEnumType($interfaceName) or IsCallb
ackFunctionType($interfaceName)) { | |
| 504 # Not interface type, no header files | |
| 505 } else { | |
| 506 my $idlFilename = Cwd::abs_path(IDLFileForInterface($interfaceName)) or
die("Could NOT find IDL file for interface \"$interfaceName\" $!\n"); | |
| 507 my $idlRelPath = File::Spec->abs2rel($idlFilename, $sourceRoot); | |
| 508 push(@includes, dirname($idlRelPath) . "/" . $implClassName . ".h"); | |
| 509 } | |
| 510 return @includes; | |
| 511 } | |
| 512 | |
| 513 sub NeedsVisitDOMWrapper | |
| 514 { | |
| 515 my $interface = shift; | |
| 516 return ExtendedAttributeContains($interface->extendedAttributes->{"Custom"},
"VisitDOMWrapper") || $interface->extendedAttributes->{"SetWrapperReferenceFrom
"} || $interface->extendedAttributes->{"SetWrapperReferenceFromReference"} || $i
nterface->extendedAttributes->{"SetWrapperReferenceTo"} || SVGTypeNeedsToHoldCon
textElement($interface->name); | |
| 517 } | |
| 518 | |
| 519 sub GenerateVisitDOMWrapper | |
| 520 { | |
| 521 my $interface = shift; | |
| 522 my $implClassName = GetImplName($interface); | |
| 523 my $v8ClassName = GetV8ClassName($interface); | |
| 524 | |
| 525 if (ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "V
isitDOMWrapper")) { | |
| 526 return; | |
| 527 } | |
| 528 | |
| 529 my $nativeType = GetNativeTypeForConversions($interface); | |
| 530 my $code = <<END; | |
| 531 void ${v8ClassName}::visitDOMWrapper(void* object, const v8::Persistent<v8::Obje
ct>& wrapper, v8::Isolate* isolate) | |
| 532 { | |
| 533 ${nativeType}* impl = fromInternalPointer(object); | |
| 534 END | |
| 535 my $needSetWrapperReferenceContext = SVGTypeNeedsToHoldContextElement($inter
face->name) || $interface->extendedAttributes->{"SetWrapperReferenceTo"}; | |
| 536 if ($needSetWrapperReferenceContext) { | |
| 537 $code .= <<END; | |
| 538 v8::Local<v8::Object> creationContext = v8::Local<v8::Object>::New(isolate,
wrapper); | |
| 539 V8WrapperInstantiationScope scope(creationContext, isolate); | |
| 540 END | |
| 541 } | |
| 542 for my $setReference (@{$interface->extendedAttributes->{"SetWrapperReferenc
eTo"}}) { | |
| 543 my $setReferenceType = $setReference->type; | |
| 544 my $setReferenceV8Type = "V8".$setReferenceType; | |
| 545 | |
| 546 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGProp
ertyTypes($setReferenceType); | |
| 547 if ($svgPropertyType) { | |
| 548 $setReferenceType = $svgNativeType; | |
| 549 } | |
| 550 my $setReferenceImplType = GetImplNameFromImplementedBy($setReferenceTyp
e); | |
| 551 | |
| 552 my $setReferenceName = $setReference->name; | |
| 553 | |
| 554 AddIncludesForType($setReferenceType); | |
| 555 $code .= <<END; | |
| 556 ${setReferenceImplType}* ${setReferenceName} = impl->${setReferenceName}(); | |
| 557 if (${setReferenceName}) { | |
| 558 if (!DOMDataStore::containsWrapper<${setReferenceV8Type}>(${setReference
Name}, isolate)) | |
| 559 wrap(${setReferenceName}, creationContext, isolate); | |
| 560 DOMDataStore::setWrapperReference<${setReferenceV8Type}>(wrapper, ${setR
eferenceName}, isolate); | |
| 561 } | |
| 562 END | |
| 563 } | |
| 564 | |
| 565 my $isReachableMethod = $interface->extendedAttributes->{"SetWrapperReferenc
eFrom"}; | |
| 566 my $isReachableReferenceMethod = $interface->extendedAttributes->{"SetWrappe
rReferenceFromReference"}; | |
| 567 | |
| 568 if ($isReachableMethod || $isReachableReferenceMethod) { | |
| 569 AddToImplIncludes("bindings/v8/V8GCController.h"); | |
| 570 AddToImplIncludes("core/dom/Element.h"); | |
| 571 if ($isReachableMethod) { | |
| 572 $code .= <<END; | |
| 573 if (Node* owner = impl->${isReachableMethod}()) { | |
| 574 Node* root = V8GCController::opaqueRootForGC(owner, isolate); | |
| 575 isolate->SetReferenceFromGroup(v8::UniqueId(reinterpret_cast<intptr_t>(r
oot)), wrapper); | |
| 576 return; | |
| 577 } | |
| 578 END | |
| 579 } else { | |
| 580 $code .= <<END; | |
| 581 Node* root = V8GCController::opaqueRootForGC(&impl->${isReachableReferenceMe
thod}(), isolate); | |
| 582 isolate->SetReferenceFromGroup(v8::UniqueId(reinterpret_cast<intptr_t>(root)
), wrapper); | |
| 583 } | |
| 584 | |
| 585 END | |
| 586 } | |
| 587 } | |
| 588 | |
| 589 if (!$isReachableReferenceMethod) { | |
| 590 $code .= <<END; | |
| 591 setObjectGroup(object, wrapper, isolate); | |
| 592 } | |
| 593 | |
| 594 END | |
| 595 } | |
| 596 | |
| 597 $implementation{nameSpaceWebCore}->add($code); | |
| 598 } | |
| 599 | |
| 600 sub GetSVGPropertyTypes | |
| 601 { | |
| 602 my $implType = shift; | |
| 603 | |
| 604 my $svgPropertyType; | |
| 605 my $svgListPropertyType; | |
| 606 my $svgNativeType; | |
| 607 | |
| 608 return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $impl
Type =~ /SVG/; | |
| 609 | |
| 610 $svgNativeType = GetSVGTypeNeedingTearOff($implType); | |
| 611 return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $svgN
ativeType; | |
| 612 | |
| 613 # Append space to avoid compilation errors when using PassRefPtr<$svgNative
Type> | |
| 614 $svgNativeType = "$svgNativeType "; | |
| 615 | |
| 616 my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($implType); | |
| 617 if ($svgNativeType =~ /SVGPropertyTearOff/) { | |
| 618 $svgPropertyType = $svgWrappedNativeType; | |
| 619 AddToHeaderIncludes("core/svg/properties/SVGAnimatedPropertyTearOff.h"); | |
| 620 } elsif ($svgNativeType =~ /SVGListPropertyTearOff/ or $svgNativeType =~ /SV
GStaticListPropertyTearOff/ or $svgNativeType =~ /SVGTransformListPropertyTearOf
f/) { | |
| 621 $svgListPropertyType = $svgWrappedNativeType; | |
| 622 AddToHeaderIncludes("core/svg/properties/SVGAnimatedListPropertyTearOff.
h"); | |
| 623 } | |
| 624 | |
| 625 return ($svgPropertyType, $svgListPropertyType, $svgNativeType); | |
| 626 } | |
| 627 | |
| 628 sub GetIndexedGetterFunction | |
| 629 { | |
| 630 my $interface = shift; | |
| 631 | |
| 632 return GetSpecialAccessorFunctionForType($interface, "getter", "unsigned lon
g", 1); | |
| 633 } | |
| 634 | |
| 635 sub GetIndexedSetterFunction | |
| 636 { | |
| 637 my $interface = shift; | |
| 638 | |
| 639 return GetSpecialAccessorFunctionForType($interface, "setter", "unsigned lon
g", 2); | |
| 640 } | |
| 641 | |
| 642 sub GetIndexedDeleterFunction | |
| 643 { | |
| 644 my $interface = shift; | |
| 645 | |
| 646 return GetSpecialAccessorFunctionForType($interface, "deleter", "unsigned lo
ng", 1); | |
| 647 } | |
| 648 | |
| 649 sub GetNamedGetterFunction | |
| 650 { | |
| 651 my $interface = shift; | |
| 652 return GetSpecialAccessorFunctionForType($interface, "getter", "DOMString",
1); | |
| 653 } | |
| 654 | |
| 655 sub GetNamedSetterFunction | |
| 656 { | |
| 657 my $interface = shift; | |
| 658 return GetSpecialAccessorFunctionForType($interface, "setter", "DOMString",
2); | |
| 659 } | |
| 660 | |
| 661 sub GetNamedDeleterFunction | |
| 662 { | |
| 663 my $interface = shift; | |
| 664 return GetSpecialAccessorFunctionForType($interface, "deleter", "DOMString",
1); | |
| 665 } | |
| 666 | |
| 667 sub GetSpecialAccessorFunctionForType | |
| 668 { | |
| 669 my $interface = shift; | |
| 670 my $special = shift; | |
| 671 my $firstParameterType = shift; | |
| 672 my $numberOfParameters = shift; | |
| 673 | |
| 674 foreach my $function (@{$interface->functions}) { | |
| 675 my $specials = $function->specials; | |
| 676 my $specialExists = grep { $_ eq $special } @$specials; | |
| 677 my $parameters = $function->parameters; | |
| 678 if ($specialExists and scalar(@$parameters) == $numberOfParameters and $
parameters->[0]->type eq $firstParameterType) { | |
| 679 return $function; | |
| 680 } | |
| 681 } | |
| 682 | |
| 683 return 0; | |
| 684 } | |
| 685 | |
| 686 sub GetV8StringResourceMode | |
| 687 { | |
| 688 my $extendedAttributes = shift; | |
| 689 | |
| 690 # Blink uses the non-standard identifier NullString instead of Web IDL | |
| 691 # standard EmptyString, in [TreatNullAs=NullString] and [TreatUndefinedAs=Nu
llString], | |
| 692 # and does not support [TreatUndefinedAs=Null] or [TreatUndefinedAs=Missing] | |
| 693 # https://sites.google.com/a/chromium.org/dev/blink/webidl/blink-idl-extende
d-attributes#TOC-TreatNullAs-a-p-TreatUndefinedAs-a-p- | |
| 694 my $mode = ""; | |
| 695 if (($extendedAttributes->{"TreatNullAs"} and $extendedAttributes->{"TreatNu
llAs"} eq "NullString") and ($extendedAttributes->{"TreatUndefinedAs"} and $exte
ndedAttributes->{"TreatUndefinedAs"} eq "NullString")) { | |
| 696 $mode = "WithUndefinedOrNullCheck"; | |
| 697 } elsif ($extendedAttributes->{"TreatNullAs"} and $extendedAttributes->{"Tre
atNullAs"} eq "NullString") { | |
| 698 $mode = "WithNullCheck"; | |
| 699 } | |
| 700 return $mode; | |
| 701 } | |
| 702 | |
| 703 sub GenerateHeader | |
| 704 { | |
| 705 my $object = shift; | |
| 706 my $interface = shift; | |
| 707 | |
| 708 my $interfaceName = $interface->name; | |
| 709 my $implClassName = GetImplName($interface); | |
| 710 my $v8ClassName = GetV8ClassName($interface); | |
| 711 | |
| 712 LinkOverloadedFunctions($interface); | |
| 713 | |
| 714 # Ensure the IsDOMNodeType function is in sync. | |
| 715 die("IsDOMNodeType is out of date with respect to $interfaceName") if IsDOMN
odeType($interfaceName) != InheritsInterface($interface, "Node"); | |
| 716 | |
| 717 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGProperty
Types($interfaceName); | |
| 718 | |
| 719 my $parentInterface = $interface->parent; | |
| 720 AddToHeaderIncludes("V8${parentInterface}.h") if $parentInterface; | |
| 721 AddToHeaderIncludes("bindings/v8/WrapperTypeInfo.h"); | |
| 722 AddToHeaderIncludes("bindings/v8/V8Binding.h"); | |
| 723 AddToHeaderIncludes("bindings/v8/V8DOMWrapper.h"); | |
| 724 AddToHeaderIncludes("heap/Handle.h"); | |
| 725 AddToHeaderIncludes(HeaderFilesForInterface($interfaceName, $implClassName))
; | |
| 726 foreach my $headerInclude (sort keys(%headerIncludes)) { | |
| 727 $header{includes}->add("#include \"${headerInclude}\"\n"); | |
| 728 } | |
| 729 | |
| 730 $header{nameSpaceWebCore}->addHeader("\ntemplate<typename PropertyType> clas
s SVGPropertyTearOff;\n") if $svgPropertyType; | |
| 731 if ($svgNativeType) { | |
| 732 if ($svgNativeType =~ /SVGStaticListPropertyTearOff/) { | |
| 733 $header{nameSpaceWebCore}->addHeader("\ntemplate<typename PropertyTy
pe> class SVGStaticListPropertyTearOff;\n"); | |
| 734 } else { | |
| 735 $header{nameSpaceWebCore}->addHeader("\ntemplate<typename PropertyTy
pe> class SVGListPropertyTearOff;\n"); | |
| 736 } | |
| 737 } | |
| 738 | |
| 739 $header{nameSpaceWebCore}->addHeader("\nclass Dictionary;") if $interface->e
xtendedAttributes->{"EventConstructor"}; | |
| 740 | |
| 741 my $nativeType = GetNativeTypeForConversions($interface); | |
| 742 if ($interface->extendedAttributes->{"NamedConstructor"}) { | |
| 743 $header{nameSpaceWebCore}->addHeader(<<END); | |
| 744 | |
| 745 class V8${nativeType}Constructor { | |
| 746 public: | |
| 747 static v8::Handle<v8::FunctionTemplate> domTemplate(v8::Isolate*, WrapperWor
ldType); | |
| 748 static const WrapperTypeInfo wrapperTypeInfo; | |
| 749 }; | |
| 750 END | |
| 751 } | |
| 752 | |
| 753 $header{class}->addHeader("class $v8ClassName {"); | |
| 754 $header{class}->addFooter("};"); | |
| 755 | |
| 756 $header{classPublic}->add(<<END); | |
| 757 static bool hasInstance(v8::Handle<v8::Value>, v8::Isolate*); | |
| 758 static v8::Handle<v8::Object> findInstanceInPrototypeChain(v8::Handle<v8::Va
lue>, v8::Isolate*); | |
| 759 static v8::Handle<v8::FunctionTemplate> domTemplate(v8::Isolate*, WrapperWor
ldType); | |
| 760 static ${nativeType}* toNative(v8::Handle<v8::Object> object) | |
| 761 { | |
| 762 return fromInternalPointer(object->GetAlignedPointerFromInternalField(v8
DOMWrapperObjectIndex)); | |
| 763 } | |
| 764 static ${nativeType}* toNativeWithTypeCheck(v8::Isolate*, v8::Handle<v8::Val
ue>); | |
| 765 static const WrapperTypeInfo wrapperTypeInfo; | |
| 766 END | |
| 767 | |
| 768 $header{classPublic}->add(" static void derefObject(void*);\n"); | |
| 769 | |
| 770 if (NeedsVisitDOMWrapper($interface)) { | |
| 771 $header{classPublic}->add(" static void visitDOMWrapper(void*, const
v8::Persistent<v8::Object>&, v8::Isolate*);\n"); | |
| 772 } | |
| 773 | |
| 774 if (InheritsExtendedAttribute($interface, "ActiveDOMObject")) { | |
| 775 $header{classPublic}->add(" static ActiveDOMObject* toActiveDOMObject
(v8::Handle<v8::Object>);\n"); | |
| 776 } | |
| 777 | |
| 778 if (InheritsInterface($interface, "EventTarget")) { | |
| 779 $header{classPublic}->add(" static EventTarget* toEventTarget(v8::Han
dle<v8::Object>);\n"); | |
| 780 } | |
| 781 | |
| 782 if ($interfaceName eq "Window") { | |
| 783 $header{classPublic}->add(<<END); | |
| 784 static v8::Handle<v8::ObjectTemplate> getShadowObjectTemplate(v8::Isolate*,
WrapperWorldType); | |
| 785 END | |
| 786 } | |
| 787 | |
| 788 my @perContextEnabledFunctions; | |
| 789 foreach my $function (@{$interface->functions}) { | |
| 790 my $name = $function->name; | |
| 791 next if $name eq ""; | |
| 792 my $attrExt = $function->extendedAttributes; | |
| 793 | |
| 794 if (HasCustomMethod($attrExt) && $function->{overloadIndex} == 1) { | |
| 795 my $conditionalString = GenerateConditionalString($function); | |
| 796 $header{classPublic}->add("#if ${conditionalString}\n") if $conditio
nalString; | |
| 797 $header{classPublic}->add(<<END); | |
| 798 static void ${name}MethodCustom(const v8::FunctionCallbackInfo<v8::Value>&); | |
| 799 END | |
| 800 $header{classPublic}->add("#endif // ${conditionalString}\n") if $co
nditionalString; | |
| 801 } | |
| 802 if ($attrExt->{"PerContextEnabled"}) { | |
| 803 push(@perContextEnabledFunctions, $function); | |
| 804 } | |
| 805 } | |
| 806 | |
| 807 if (IsConstructable($interface)) { | |
| 808 $header{classPublic}->add(" static void constructorCallback(const v8:
:FunctionCallbackInfo<v8::Value>&);\n"); | |
| 809 END | |
| 810 } | |
| 811 if (HasCustomConstructor($interface)) { | |
| 812 $header{classPublic}->add(" static void constructorCustom(const v8::F
unctionCallbackInfo<v8::Value>&);\n"); | |
| 813 } | |
| 814 | |
| 815 my @perContextEnabledAttributes; | |
| 816 foreach my $attribute (@{$interface->attributes}) { | |
| 817 my $name = $attribute->name; | |
| 818 my $attrExt = $attribute->extendedAttributes; | |
| 819 my $conditionalString = GenerateConditionalString($attribute); | |
| 820 if (HasCustomGetter($attrExt) && !$attrExt->{"ImplementedBy"}) { | |
| 821 $header{classPublic}->add("#if ${conditionalString}\n") if $conditio
nalString; | |
| 822 $header{classPublic}->add(<<END); | |
| 823 static void ${name}AttributeGetterCustom(const v8::PropertyCallbackInfo<v8::
Value>&); | |
| 824 END | |
| 825 $header{classPublic}->add("#endif // ${conditionalString}\n") if $co
nditionalString; | |
| 826 } | |
| 827 if (HasCustomSetter($attribute) && !$attrExt->{"ImplementedBy"}) { | |
| 828 $header{classPublic}->add("#if ${conditionalString}\n") if $conditio
nalString; | |
| 829 $header{classPublic}->add(<<END); | |
| 830 static void ${name}AttributeSetterCustom(v8::Local<v8::Value>, const v8::Pro
pertyCallbackInfo<void>&); | |
| 831 END | |
| 832 $header{classPublic}->add("#endif // ${conditionalString}\n") if $co
nditionalString; | |
| 833 } | |
| 834 if ($attrExt->{"PerContextEnabled"}) { | |
| 835 push(@perContextEnabledAttributes, $attribute); | |
| 836 } | |
| 837 } | |
| 838 | |
| 839 GenerateHeaderNamedAndIndexedPropertyAccessors($interface); | |
| 840 GenerateHeaderLegacyCallAsFunction($interface); | |
| 841 GenerateHeaderCustomInternalFieldIndices($interface); | |
| 842 | |
| 843 my $toWrappedType; | |
| 844 my $fromWrappedType; | |
| 845 if ($interface->parent) { | |
| 846 my $v8ParentClassName = "V8" . $interface->parent; | |
| 847 $toWrappedType = "${v8ParentClassName}::toInternalPointer(impl)"; | |
| 848 $fromWrappedType = "static_cast<${nativeType}*>(${v8ParentClassName}::fr
omInternalPointer(object))"; | |
| 849 } else { | |
| 850 $toWrappedType = "impl"; | |
| 851 $fromWrappedType = "static_cast<${nativeType}*>(object)"; | |
| 852 } | |
| 853 | |
| 854 $header{classPublic}->add(<<END); | |
| 855 static inline void* toInternalPointer(${nativeType}* impl) | |
| 856 { | |
| 857 return $toWrappedType; | |
| 858 } | |
| 859 | |
| 860 static inline ${nativeType}* fromInternalPointer(void* object) | |
| 861 { | |
| 862 return $fromWrappedType; | |
| 863 } | |
| 864 END | |
| 865 | |
| 866 if ($interface->name eq "Window") { | |
| 867 $header{classPublic}->add(<<END); | |
| 868 static bool namedSecurityCheckCustom(v8::Local<v8::Object> host, v8::Local<v
8::Value> key, v8::AccessType, v8::Local<v8::Value> data); | |
| 869 static bool indexedSecurityCheckCustom(v8::Local<v8::Object> host, uint32_t
index, v8::AccessType, v8::Local<v8::Value> data); | |
| 870 END | |
| 871 } | |
| 872 | |
| 873 if (@perContextEnabledAttributes) { | |
| 874 $header{classPublic}->add(<<END); | |
| 875 static void installPerContextEnabledProperties(v8::Handle<v8::Object>, ${nat
iveType}*, v8::Isolate*); | |
| 876 END | |
| 877 } else { | |
| 878 $header{classPublic}->add(<<END); | |
| 879 static void installPerContextEnabledProperties(v8::Handle<v8::Object>, ${nat
iveType}*, v8::Isolate*) { } | |
| 880 END | |
| 881 } | |
| 882 | |
| 883 if (@perContextEnabledFunctions) { | |
| 884 $header{classPublic}->add(<<END); | |
| 885 static void installPerContextEnabledMethods(v8::Handle<v8::Object>, v8::Isol
ate*); | |
| 886 END | |
| 887 } else { | |
| 888 $header{classPublic}->add(<<END); | |
| 889 static void installPerContextEnabledMethods(v8::Handle<v8::Object>, v8::Isol
ate*) { } | |
| 890 END | |
| 891 } | |
| 892 | |
| 893 if ($interfaceName eq "HTMLElement") { | |
| 894 $header{classPublic}->add(<<END); | |
| 895 friend v8::Handle<v8::Object> createV8HTMLWrapper(HTMLElement*, v8::Handle<v
8::Object> creationContext, v8::Isolate*); | |
| 896 friend v8::Handle<v8::Object> createV8HTMLDirectWrapper(HTMLElement*, v8::Ha
ndle<v8::Object> creationContext, v8::Isolate*); | |
| 897 END | |
| 898 } elsif ($interfaceName eq "SVGElement") { | |
| 899 $header{classPublic}->add(<<END); | |
| 900 friend v8::Handle<v8::Object> createV8SVGWrapper(SVGElement*, v8::Handle<v8:
:Object> creationContext, v8::Isolate*); | |
| 901 friend v8::Handle<v8::Object> createV8SVGDirectWrapper(SVGElement*, v8::Hand
le<v8::Object> creationContext, v8::Isolate*); | |
| 902 friend v8::Handle<v8::Object> createV8SVGFallbackWrapper(SVGElement*, v8::Ha
ndle<v8::Object> creationContext, v8::Isolate*); | |
| 903 END | |
| 904 } elsif ($interfaceName eq "HTMLUnknownElement") { | |
| 905 $header{classPublic}->add(<<END); | |
| 906 friend v8::Handle<v8::Object> createV8HTMLFallbackWrapper(HTMLUnknownElement
*, v8::Handle<v8::Object> creationContext, v8::Isolate*); | |
| 907 END | |
| 908 } elsif ($interfaceName eq "Element") { | |
| 909 $header{classPublic}->add(<<END); | |
| 910 // This is a performance optimization hack. See V8Element::wrap. | |
| 911 friend v8::Handle<v8::Object> wrap(Node*, v8::Handle<v8::Object> creationCon
text, v8::Isolate*); | |
| 912 END | |
| 913 } | |
| 914 $header{classPublic}->add("\n"); # blank line to separate classPrivate | |
| 915 | |
| 916 my $customToV8 = ExtendedAttributeContains($interface->extendedAttributes->{
"Custom"}, "ToV8"); | |
| 917 my $passRefPtrType = GetPassRefPtrType($interface); | |
| 918 if (!$customToV8) { | |
| 919 $header{classPrivate}->add(<<END); | |
| 920 friend v8::Handle<v8::Object> wrap(${nativeType}*, v8::Handle<v8::Object> cr
eationContext, v8::Isolate*); | |
| 921 static v8::Handle<v8::Object> createWrapper(${passRefPtrType}, v8::Handle<v8
::Object> creationContext, v8::Isolate*); | |
| 922 END | |
| 923 } | |
| 924 | |
| 925 if ($customToV8) { | |
| 926 $header{nameSpaceWebCore}->add(<<END); | |
| 927 | |
| 928 class ${nativeType}; | |
| 929 v8::Handle<v8::Value> toV8(${nativeType}*, v8::Handle<v8::Object> creationContex
t, v8::Isolate*); | |
| 930 | |
| 931 template<class CallbackInfo> | |
| 932 inline void v8SetReturnValue(const CallbackInfo& callbackInfo, ${nativeType}* im
pl) | |
| 933 { | |
| 934 v8SetReturnValue(callbackInfo, toV8(impl, callbackInfo.Holder(), callbackInf
o.GetIsolate())); | |
| 935 } | |
| 936 | |
| 937 template<class CallbackInfo> | |
| 938 inline void v8SetReturnValueForMainWorld(const CallbackInfo& callbackInfo, ${nat
iveType}* impl) | |
| 939 { | |
| 940 v8SetReturnValue(callbackInfo, toV8(impl, callbackInfo.Holder(), callbackIn
fo.GetIsolate())); | |
| 941 } | |
| 942 | |
| 943 template<class CallbackInfo, class Wrappable> | |
| 944 inline void v8SetReturnValueFast(const CallbackInfo& callbackInfo, ${nativeType}
* impl, Wrappable*) | |
| 945 { | |
| 946 v8SetReturnValue(callbackInfo, toV8(impl, callbackInfo.Holder(), callbackIn
fo.GetIsolate())); | |
| 947 } | |
| 948 END | |
| 949 } else { | |
| 950 if (NeedsSpecialWrap($interface)) { | |
| 951 $header{nameSpaceWebCore}->add(<<END); | |
| 952 | |
| 953 v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> creation
Context, v8::Isolate*); | |
| 954 END | |
| 955 } else { | |
| 956 $header{nameSpaceWebCore}->add(<<END); | |
| 957 | |
| 958 inline v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> c
reationContext, v8::Isolate* isolate) | |
| 959 { | |
| 960 ASSERT(impl); | |
| 961 ASSERT(!DOMDataStore::containsWrapper<${v8ClassName}>(impl, isolate)); | |
| 962 return ${v8ClassName}::createWrapper(impl, creationContext, isolate); | |
| 963 } | |
| 964 END | |
| 965 } | |
| 966 | |
| 967 $header{nameSpaceWebCore}->add(<<END); | |
| 968 | |
| 969 inline v8::Handle<v8::Value> toV8(${nativeType}* impl, v8::Handle<v8::Object> cr
eationContext, v8::Isolate* isolate) | |
| 970 { | |
| 971 if (UNLIKELY(!impl)) | |
| 972 return v8::Null(isolate); | |
| 973 v8::Handle<v8::Value> wrapper = DOMDataStore::getWrapper<${v8ClassName}>(imp
l, isolate); | |
| 974 if (!wrapper.IsEmpty()) | |
| 975 return wrapper; | |
| 976 return wrap(impl, creationContext, isolate); | |
| 977 } | |
| 978 | |
| 979 template<typename CallbackInfo> | |
| 980 inline void v8SetReturnValue(const CallbackInfo& callbackInfo, ${nativeType}* im
pl) | |
| 981 { | |
| 982 if (UNLIKELY(!impl)) { | |
| 983 v8SetReturnValueNull(callbackInfo); | |
| 984 return; | |
| 985 } | |
| 986 if (DOMDataStore::setReturnValueFromWrapper<${v8ClassName}>(callbackInfo.Get
ReturnValue(), impl)) | |
| 987 return; | |
| 988 v8::Handle<v8::Object> wrapper = wrap(impl, callbackInfo.Holder(), callbackI
nfo.GetIsolate()); | |
| 989 v8SetReturnValue(callbackInfo, wrapper); | |
| 990 } | |
| 991 | |
| 992 template<typename CallbackInfo> | |
| 993 inline void v8SetReturnValueForMainWorld(const CallbackInfo& callbackInfo, ${nat
iveType}* impl) | |
| 994 { | |
| 995 ASSERT(worldType(callbackInfo.GetIsolate()) == MainWorld); | |
| 996 if (UNLIKELY(!impl)) { | |
| 997 v8SetReturnValueNull(callbackInfo); | |
| 998 return; | |
| 999 } | |
| 1000 if (DOMDataStore::setReturnValueFromWrapperForMainWorld<${v8ClassName}>(call
backInfo.GetReturnValue(), impl)) | |
| 1001 return; | |
| 1002 v8::Handle<v8::Value> wrapper = wrap(impl, callbackInfo.Holder(), callbackIn
fo.GetIsolate()); | |
| 1003 v8SetReturnValue(callbackInfo, wrapper); | |
| 1004 } | |
| 1005 | |
| 1006 template<class CallbackInfo, class Wrappable> | |
| 1007 inline void v8SetReturnValueFast(const CallbackInfo& callbackInfo, ${nativeType}
* impl, Wrappable* wrappable) | |
| 1008 { | |
| 1009 if (UNLIKELY(!impl)) { | |
| 1010 v8SetReturnValueNull(callbackInfo); | |
| 1011 return; | |
| 1012 } | |
| 1013 if (DOMDataStore::setReturnValueFromWrapperFast<${v8ClassName}>(callbackInfo
.GetReturnValue(), impl, callbackInfo.Holder(), wrappable)) | |
| 1014 return; | |
| 1015 v8::Handle<v8::Object> wrapper = wrap(impl, callbackInfo.Holder(), callbackI
nfo.GetIsolate()); | |
| 1016 v8SetReturnValue(callbackInfo, wrapper); | |
| 1017 } | |
| 1018 END | |
| 1019 } | |
| 1020 | |
| 1021 $header{nameSpaceWebCore}->add(<<END); | |
| 1022 | |
| 1023 inline v8::Handle<v8::Value> toV8($passRefPtrType impl, v8::Handle<v8::Object> c
reationContext, v8::Isolate* isolate) | |
| 1024 { | |
| 1025 return toV8(impl.get(), creationContext, isolate); | |
| 1026 } | |
| 1027 | |
| 1028 template<class CallbackInfo> | |
| 1029 inline void v8SetReturnValue(const CallbackInfo& callbackInfo, $passRefPtrType i
mpl) | |
| 1030 { | |
| 1031 v8SetReturnValue(callbackInfo, impl.get()); | |
| 1032 } | |
| 1033 | |
| 1034 template<class CallbackInfo> | |
| 1035 inline void v8SetReturnValueForMainWorld(const CallbackInfo& callbackInfo, $pass
RefPtrType impl) | |
| 1036 { | |
| 1037 v8SetReturnValueForMainWorld(callbackInfo, impl.get()); | |
| 1038 } | |
| 1039 | |
| 1040 template<class CallbackInfo, class Wrappable> | |
| 1041 inline void v8SetReturnValueFast(const CallbackInfo& callbackInfo, $passRefPtrTy
pe impl, Wrappable* wrappable) | |
| 1042 { | |
| 1043 v8SetReturnValueFast(callbackInfo, impl.get(), wrappable); | |
| 1044 } | |
| 1045 | |
| 1046 END | |
| 1047 | |
| 1048 if ($interface->extendedAttributes->{"EventConstructor"}) { | |
| 1049 $header{nameSpaceWebCore}->add("bool initialize${implClassName}(${implCl
assName}Init&, const Dictionary&, ExceptionState&, const v8::FunctionCallbackInf
o<v8::Value>& info, const String& = \"\");\n\n"); | |
| 1050 } | |
| 1051 } | |
| 1052 | |
| 1053 sub GetInternalFields | |
| 1054 { | |
| 1055 my $interface = shift; | |
| 1056 | |
| 1057 my @customInternalFields = (); | |
| 1058 # Event listeners on DOM nodes are explicitly supported in the GC controller
. | |
| 1059 if (!InheritsInterface($interface, "Node") && | |
| 1060 InheritsInterface($interface, "EventTarget")) { | |
| 1061 push(@customInternalFields, "eventListenerCacheIndex"); | |
| 1062 } | |
| 1063 # Persistent handle is stored in the last internal field. | |
| 1064 # FIXME: Remove this internal field. Since we need either of a persistent ha
ndle | |
| 1065 # (if the object is in oilpan) or a C++ pointer to the DOM object (if the ob
ject is not in oilpan), | |
| 1066 # we can share the internal field between the two cases. | |
| 1067 if (IsWillBeGarbageCollectedType($interface->name)) { | |
| 1068 push(@customInternalFields, "persistentHandleIndex"); | |
| 1069 } | |
| 1070 return @customInternalFields; | |
| 1071 } | |
| 1072 | |
| 1073 sub GenerateHeaderCustomInternalFieldIndices | |
| 1074 { | |
| 1075 my $interface = shift; | |
| 1076 my @customInternalFields = GetInternalFields($interface); | |
| 1077 my $customFieldCounter = 0; | |
| 1078 foreach my $customInternalField (@customInternalFields) { | |
| 1079 $header{classPublic}->add(<<END); | |
| 1080 static const int ${customInternalField} = v8DefaultWrapperInternalFieldCount
+ ${customFieldCounter}; | |
| 1081 END | |
| 1082 $customFieldCounter++; | |
| 1083 } | |
| 1084 $header{classPublic}->add(<<END); | |
| 1085 static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + $
{customFieldCounter}; | |
| 1086 END | |
| 1087 } | |
| 1088 | |
| 1089 sub GenerateHeaderNamedAndIndexedPropertyAccessors | |
| 1090 { | |
| 1091 my $interface = shift; | |
| 1092 | |
| 1093 my $indexedGetterFunction = GetIndexedGetterFunction($interface); | |
| 1094 my $hasCustomIndexedGetter = $indexedGetterFunction && $indexedGetterFunctio
n->extendedAttributes->{"Custom"}; | |
| 1095 | |
| 1096 my $indexedSetterFunction = GetIndexedSetterFunction($interface); | |
| 1097 my $hasCustomIndexedSetter = $indexedSetterFunction && $indexedSetterFunctio
n->extendedAttributes->{"Custom"}; | |
| 1098 | |
| 1099 my $indexedDeleterFunction = GetIndexedDeleterFunction($interface); | |
| 1100 my $hasCustomIndexedDeleters = $indexedDeleterFunction && $indexedDeleterFun
ction->extendedAttributes->{"Custom"}; | |
| 1101 | |
| 1102 my $namedGetterFunction = GetNamedGetterFunction($interface); | |
| 1103 my $hasCustomNamedGetter = $namedGetterFunction && HasCustomPropertyGetter($
namedGetterFunction->extendedAttributes); | |
| 1104 | |
| 1105 my $namedSetterFunction = GetNamedSetterFunction($interface); | |
| 1106 my $hasCustomNamedSetter = $namedSetterFunction && $namedSetterFunction->ext
endedAttributes->{"Custom"}; | |
| 1107 | |
| 1108 my $namedDeleterFunction = GetNamedDeleterFunction($interface); | |
| 1109 my $hasCustomNamedDeleter = $namedDeleterFunction && $namedDeleterFunction->
extendedAttributes->{"Custom"}; | |
| 1110 | |
| 1111 my $namedEnumeratorFunction = $namedGetterFunction && !$namedGetterFunction-
>extendedAttributes->{"NotEnumerable"}; | |
| 1112 my $hasCustomNamedEnumerator = $namedEnumeratorFunction && ExtendedAttribute
Contains($namedGetterFunction->extendedAttributes->{"Custom"}, "PropertyEnumerat
or"); | |
| 1113 my $hasCustomNamedQuery = $namedEnumeratorFunction && ExtendedAttributeConta
ins($namedGetterFunction->extendedAttributes->{"Custom"}, "PropertyQuery"); | |
| 1114 | |
| 1115 if ($hasCustomIndexedGetter) { | |
| 1116 $header{classPublic}->add(" static void indexedPropertyGetterCustom(u
int32_t, const v8::PropertyCallbackInfo<v8::Value>&);\n"); | |
| 1117 } | |
| 1118 | |
| 1119 if ($hasCustomIndexedSetter) { | |
| 1120 $header{classPublic}->add(" static void indexedPropertySetterCustom(u
int32_t, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&);\n"); | |
| 1121 } | |
| 1122 | |
| 1123 if ($hasCustomIndexedDeleters) { | |
| 1124 $header{classPublic}->add(" static void indexedPropertyDeleterCustom(
uint32_t, const v8::PropertyCallbackInfo<v8::Boolean>&);\n"); | |
| 1125 } | |
| 1126 | |
| 1127 if ($hasCustomNamedGetter) { | |
| 1128 $header{classPublic}->add(" static void namedPropertyGetterCustom(v8:
:Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>&);\n"); | |
| 1129 } | |
| 1130 | |
| 1131 if ($hasCustomNamedSetter) { | |
| 1132 $header{classPublic}->add(" static void namedPropertySetterCustom(v8:
:Local<v8::String>, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Val
ue>&);\n"); | |
| 1133 } | |
| 1134 | |
| 1135 if ($hasCustomNamedQuery) { | |
| 1136 $header{classPublic}->add(" static void namedPropertyQueryCustom(v8::
Local<v8::String>, const v8::PropertyCallbackInfo<v8::Integer>&);\n"); | |
| 1137 } | |
| 1138 | |
| 1139 if ($hasCustomNamedDeleter) { | |
| 1140 $header{classPublic}->add(" static void namedPropertyDeleterCustom(v8
::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Boolean>&);\n"); | |
| 1141 } | |
| 1142 | |
| 1143 if ($hasCustomNamedEnumerator) { | |
| 1144 $header{classPublic}->add(" static void namedPropertyEnumeratorCustom
(const v8::PropertyCallbackInfo<v8::Array>&);\n"); | |
| 1145 } | |
| 1146 } | |
| 1147 | |
| 1148 sub GenerateHeaderLegacyCallAsFunction | |
| 1149 { | |
| 1150 my $interface = shift; | |
| 1151 | |
| 1152 if (ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "L
egacyCallAsFunction")) { | |
| 1153 $header{classPublic}->add(" static void legacyCallCustom(const v8::Fu
nctionCallbackInfo<v8::Value>&);\n"); | |
| 1154 } | |
| 1155 } | |
| 1156 | |
| 1157 sub HasActivityLogging | |
| 1158 { | |
| 1159 my $forMainWorldSuffix = shift; | |
| 1160 my $attrExt = shift; | |
| 1161 my $access = shift; | |
| 1162 | |
| 1163 if (!$attrExt->{"ActivityLogging"}) { | |
| 1164 return 0; | |
| 1165 } | |
| 1166 my $logAllAccess = ($attrExt->{"ActivityLogging"} =~ /^For/); # No prefix,
starts with For*Worlds suffix | |
| 1167 my $logGetter = ($attrExt->{"ActivityLogging"} =~ /^Getter/); | |
| 1168 my $logSetter = ($attrExt->{"ActivityLogging"} =~ /^Setter/); | |
| 1169 my $logOnlyIsolatedWorlds = ($attrExt->{"ActivityLogging"} =~ /ForIsolatedWo
rlds$/); | |
| 1170 | |
| 1171 if ($logOnlyIsolatedWorlds && $forMainWorldSuffix eq "ForMainWorld") { | |
| 1172 return 0; | |
| 1173 } | |
| 1174 return $logAllAccess || ($logGetter && $access eq "Getter") || ($logSetter &
& $access eq "Setter"); | |
| 1175 } | |
| 1176 | |
| 1177 sub IsConstructable | |
| 1178 { | |
| 1179 my $interface = shift; | |
| 1180 | |
| 1181 return $interface->extendedAttributes->{"CustomConstructor"} || $interface->
extendedAttributes->{"Constructor"} || $interface->extendedAttributes->{"EventCo
nstructor"}; | |
| 1182 } | |
| 1183 | |
| 1184 sub HasCustomConstructor | |
| 1185 { | |
| 1186 my $interface = shift; | |
| 1187 | |
| 1188 return $interface->extendedAttributes->{"CustomConstructor"}; | |
| 1189 } | |
| 1190 | |
| 1191 sub HasCustomGetter | |
| 1192 { | |
| 1193 my $attrExt = shift; | |
| 1194 my $custom = $attrExt->{"Custom"}; | |
| 1195 return $custom && ($custom eq "VALUE_IS_MISSING" || $custom eq "Getter"); | |
| 1196 } | |
| 1197 | |
| 1198 sub HasCustomSetter | |
| 1199 { | |
| 1200 my $attribute = shift; | |
| 1201 my $custom = $attribute->extendedAttributes->{"Custom"}; | |
| 1202 return $custom && ($custom eq "VALUE_IS_MISSING" || $custom eq "Setter") &&
!IsReadonly($attribute); | |
| 1203 } | |
| 1204 | |
| 1205 sub HasCustomMethod | |
| 1206 { | |
| 1207 my $attrExt = shift; | |
| 1208 return $attrExt->{"Custom"}; | |
| 1209 } | |
| 1210 | |
| 1211 sub HasCustomPropertyGetter | |
| 1212 { | |
| 1213 my $attrExt = shift; | |
| 1214 my $custom = $attrExt->{"Custom"}; | |
| 1215 return $custom && ($custom eq "VALUE_IS_MISSING" || ExtendedAttributeContain
s($custom, "PropertyGetter")); | |
| 1216 } | |
| 1217 | |
| 1218 sub IsReadonly | |
| 1219 { | |
| 1220 my $attribute = shift; | |
| 1221 my $attrExt = $attribute->extendedAttributes; | |
| 1222 return $attribute->isReadOnly && !$attrExt->{"Replaceable"} && !$attrExt->{"
PutForwards"}; | |
| 1223 } | |
| 1224 | |
| 1225 sub GetV8ClassName | |
| 1226 { | |
| 1227 my $interface = shift; | |
| 1228 return "V8" . $interface->name; | |
| 1229 } | |
| 1230 | |
| 1231 sub GetImplName | |
| 1232 { | |
| 1233 my $interfaceOrAttributeOrFunction = shift; | |
| 1234 return $interfaceOrAttributeOrFunction->extendedAttributes->{"ImplementedAs"
} || $interfaceOrAttributeOrFunction->name; | |
| 1235 } | |
| 1236 | |
| 1237 sub GetImplNameFromImplementedBy | |
| 1238 { | |
| 1239 my $implementedBy = shift; | |
| 1240 | |
| 1241 my $interface = ParseInterface($implementedBy); | |
| 1242 | |
| 1243 return $interface->extendedAttributes->{"ImplementedAs"} || $implementedBy; | |
| 1244 } | |
| 1245 | |
| 1246 sub GenerateDomainSafeFunctionGetter | |
| 1247 { | |
| 1248 my $function = shift; | |
| 1249 my $interface = shift; | |
| 1250 my $forMainWorldSuffix = shift; | |
| 1251 | |
| 1252 my $implClassName = GetImplName($interface); | |
| 1253 my $v8ClassName = GetV8ClassName($interface); | |
| 1254 my $funcName = $function->name; | |
| 1255 | |
| 1256 my $functionLength = GetFunctionLength($function); | |
| 1257 my $signature = "v8::Signature::New(info.GetIsolate(), ${v8ClassName}::domTe
mplate(info.GetIsolate(), currentWorldType))"; | |
| 1258 if ($function->extendedAttributes->{"DoNotCheckSignature"}) { | |
| 1259 $signature = "v8::Local<v8::Signature>()"; | |
| 1260 } | |
| 1261 | |
| 1262 my $newTemplateParams = "${implClassName}V8Internal::${funcName}MethodCallba
ck${forMainWorldSuffix}, v8Undefined(), $signature"; | |
| 1263 | |
| 1264 AddToImplIncludes("bindings/v8/BindingSecurity.h"); | |
| 1265 $implementation{nameSpaceInternal}->add(<<END); | |
| 1266 static void ${funcName}OriginSafeMethodGetter${forMainWorldSuffix}(const v8::Pro
pertyCallbackInfo<v8::Value>& info) | |
| 1267 { | |
| 1268 static int domTemplateKey; // This address is used for a key to look up the
dom template. | |
| 1269 WrapperWorldType currentWorldType = worldType(info.GetIsolate()); | |
| 1270 V8PerIsolateData* data = V8PerIsolateData::from(info.GetIsolate()); | |
| 1271 v8::Handle<v8::FunctionTemplate> privateTemplate = data->domTemplate(current
WorldType, &domTemplateKey, $newTemplateParams, $functionLength); | |
| 1272 | |
| 1273 v8::Handle<v8::Object> holder = ${v8ClassName}::findInstanceInPrototypeChain
(info.This(), info.GetIsolate()); | |
| 1274 if (holder.IsEmpty()) { | |
| 1275 // This is only reachable via |object.__proto__.func|, in which case it | |
| 1276 // has already passed the same origin security check | |
| 1277 v8SetReturnValue(info, privateTemplate->GetFunction()); | |
| 1278 return; | |
| 1279 } | |
| 1280 ${implClassName}* imp = ${v8ClassName}::toNative(holder); | |
| 1281 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), imp->frame
(), DoNotReportSecurityError)) { | |
| 1282 static int sharedTemplateKey; // This address is used for a key to look
up the dom template. | |
| 1283 v8::Handle<v8::FunctionTemplate> sharedTemplate = data->domTemplate(curr
entWorldType, &sharedTemplateKey, $newTemplateParams, $functionLength); | |
| 1284 v8SetReturnValue(info, sharedTemplate->GetFunction()); | |
| 1285 return; | |
| 1286 } | |
| 1287 | |
| 1288 v8::Local<v8::Value> hiddenValue = getHiddenValue(info.GetIsolate(), info.Th
is(), "${funcName}"); | |
| 1289 if (!hiddenValue.IsEmpty()) { | |
| 1290 v8SetReturnValue(info, hiddenValue); | |
| 1291 return; | |
| 1292 } | |
| 1293 | |
| 1294 v8SetReturnValue(info, privateTemplate->GetFunction()); | |
| 1295 } | |
| 1296 | |
| 1297 END | |
| 1298 $implementation{nameSpaceInternal}->add(<<END); | |
| 1299 static void ${funcName}OriginSafeMethodGetterCallback${forMainWorldSuffix}(v8::L
ocal<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info) | |
| 1300 { | |
| 1301 TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMGetter"); | |
| 1302 ${implClassName}V8Internal::${funcName}OriginSafeMethodGetter${forMainWorldS
uffix}(info); | |
| 1303 TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution"); | |
| 1304 } | |
| 1305 | |
| 1306 END | |
| 1307 } | |
| 1308 | |
| 1309 sub GenerateDomainSafeFunctionSetter | |
| 1310 { | |
| 1311 my $interface = shift; | |
| 1312 | |
| 1313 my $interfaceName = $interface->name(); | |
| 1314 my $implClassName = GetImplName($interface); | |
| 1315 my $v8ClassName = GetV8ClassName($interface); | |
| 1316 | |
| 1317 AddToImplIncludes("bindings/v8/BindingSecurity.h"); | |
| 1318 $implementation{nameSpaceInternal}->add(<<END); | |
| 1319 static void ${implClassName}OriginSafeMethodSetter(v8::Local<v8::String> name, v
8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info) | |
| 1320 { | |
| 1321 v8::Handle<v8::Object> holder = ${v8ClassName}::findInstanceInPrototypeChain
(info.This(), info.GetIsolate()); | |
| 1322 if (holder.IsEmpty()) | |
| 1323 return; | |
| 1324 ${implClassName}* imp = ${v8ClassName}::toNative(holder); | |
| 1325 v8::String::Utf8Value attributeName(name); | |
| 1326 ExceptionState exceptionState(ExceptionState::SetterContext, *attributeName,
"${interfaceName}", info.Holder(), info.GetIsolate()); | |
| 1327 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), imp->frame
(), exceptionState)) { | |
| 1328 exceptionState.throwIfNeeded(); | |
| 1329 return; | |
| 1330 } | |
| 1331 | |
| 1332 setHiddenValue(info.GetIsolate(), info.This(), name, jsValue); | |
| 1333 } | |
| 1334 | |
| 1335 static void ${implClassName}OriginSafeMethodSetterCallback(v8::Local<v8::String>
name, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info) | |
| 1336 { | |
| 1337 TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMSetter"); | |
| 1338 ${implClassName}V8Internal::${implClassName}OriginSafeMethodSetter(name, jsV
alue, info); | |
| 1339 TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution"); | |
| 1340 } | |
| 1341 | |
| 1342 END | |
| 1343 } | |
| 1344 | |
| 1345 sub GenerateConstructorGetter | |
| 1346 { | |
| 1347 my $interface = shift; | |
| 1348 my $implClassName = GetImplName($interface); | |
| 1349 | |
| 1350 $implementation{nameSpaceInternal}->add(<<END); | |
| 1351 static void ${implClassName}ConstructorGetter(v8::Local<v8::String>, const v8::P
ropertyCallbackInfo<v8::Value>& info) | |
| 1352 { | |
| 1353 v8::Handle<v8::Value> data = info.Data(); | |
| 1354 ASSERT(data->IsExternal()); | |
| 1355 V8PerContextData* perContextData = V8PerContextData::from(info.Holder()->Cre
ationContext()); | |
| 1356 if (!perContextData) | |
| 1357 return; | |
| 1358 v8SetReturnValue(info, perContextData->constructorForType(WrapperTypeInfo::u
nwrap(data))); | |
| 1359 } | |
| 1360 | |
| 1361 END | |
| 1362 } | |
| 1363 | |
| 1364 sub GenerateFeatureObservation | |
| 1365 { | |
| 1366 my $measureAs = shift; | |
| 1367 | |
| 1368 if ($measureAs) { | |
| 1369 AddToImplIncludes("core/frame/UseCounter.h"); | |
| 1370 return " UseCounter::count(callingExecutionContext(info.GetIsolate())
, UseCounter::${measureAs});\n"; | |
| 1371 } | |
| 1372 | |
| 1373 return ""; | |
| 1374 } | |
| 1375 | |
| 1376 sub GenerateDeprecationNotification | |
| 1377 { | |
| 1378 my $deprecateAs = shift; | |
| 1379 if ($deprecateAs) { | |
| 1380 AddToImplIncludes("core/frame/UseCounter.h"); | |
| 1381 return " UseCounter::countDeprecation(callingExecutionContext(info.Ge
tIsolate()), UseCounter::${deprecateAs});\n"; | |
| 1382 } | |
| 1383 return ""; | |
| 1384 } | |
| 1385 | |
| 1386 sub GenerateActivityLogging | |
| 1387 { | |
| 1388 my $accessType = shift; | |
| 1389 my $interface = shift; | |
| 1390 my $propertyName = shift; | |
| 1391 | |
| 1392 my $interfaceName = $interface->name; | |
| 1393 | |
| 1394 AddToImplIncludes("bindings/v8/V8DOMActivityLogger.h"); | |
| 1395 | |
| 1396 my $code = ""; | |
| 1397 if ($accessType eq "Method") { | |
| 1398 $code .= <<END; | |
| 1399 V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->Ge
tCurrentContext()); | |
| 1400 if (contextData && contextData->activityLogger()) { | |
| 1401 Vector<v8::Handle<v8::Value> > loggerArgs = toNativeArguments<v8::Handle
<v8::Value> >(info, 0); | |
| 1402 contextData->activityLogger()->log("${interfaceName}.${propertyName}", i
nfo.Length(), loggerArgs.data(), "${accessType}"); | |
| 1403 } | |
| 1404 END | |
| 1405 } elsif ($accessType eq "Setter") { | |
| 1406 $code .= <<END; | |
| 1407 V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->Ge
tCurrentContext()); | |
| 1408 if (contextData && contextData->activityLogger()) { | |
| 1409 v8::Handle<v8::Value> loggerArg[] = { jsValue }; | |
| 1410 contextData->activityLogger()->log("${interfaceName}.${propertyName}", 1
, &loggerArg[0], "${accessType}"); | |
| 1411 } | |
| 1412 END | |
| 1413 } elsif ($accessType eq "Getter") { | |
| 1414 $code .= <<END; | |
| 1415 V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->Ge
tCurrentContext()); | |
| 1416 if (contextData && contextData->activityLogger()) | |
| 1417 contextData->activityLogger()->log("${interfaceName}.${propertyName}", 0
, 0, "${accessType}"); | |
| 1418 END | |
| 1419 } else { | |
| 1420 die "Unrecognized activity logging access type"; | |
| 1421 } | |
| 1422 | |
| 1423 return $code; | |
| 1424 } | |
| 1425 | |
| 1426 sub GenerateNormalAttributeGetterCallback | |
| 1427 { | |
| 1428 my $attribute = shift; | |
| 1429 my $interface = shift; | |
| 1430 my $forMainWorldSuffix = shift; | |
| 1431 my $exposeJSAccessors = shift; | |
| 1432 | |
| 1433 my $implClassName = GetImplName($interface); | |
| 1434 my $v8ClassName = GetV8ClassName($interface); | |
| 1435 my $attrExt = $attribute->extendedAttributes; | |
| 1436 my $attrName = $attribute->name; | |
| 1437 | |
| 1438 my $conditionalString = GenerateConditionalString($attribute); | |
| 1439 my $code = ""; | |
| 1440 $code .= "#if ${conditionalString}\n" if $conditionalString; | |
| 1441 | |
| 1442 if ($exposeJSAccessors) { | |
| 1443 $code .= "static void ${attrName}AttributeGetterCallback${forMainWorldSu
ffix}(const v8::FunctionCallbackInfo<v8::Value>& info)\n"; | |
| 1444 } else { | |
| 1445 $code .= "static void ${attrName}AttributeGetterCallback${forMainWorldSu
ffix}(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info)\n"
; | |
| 1446 } | |
| 1447 $code .= "{\n"; | |
| 1448 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMGetter\");\n"; | |
| 1449 $code .= GenerateFeatureObservation($attrExt->{"MeasureAs"}); | |
| 1450 $code .= GenerateDeprecationNotification($attrExt->{"DeprecateAs"}); | |
| 1451 if (HasActivityLogging($forMainWorldSuffix, $attrExt, "Getter")) { | |
| 1452 $code .= GenerateActivityLogging("Getter", $interface, "${attrName}"); | |
| 1453 } | |
| 1454 if (HasCustomGetter($attrExt)) { | |
| 1455 $code .= " ${v8ClassName}::${attrName}AttributeGetterCustom(info);\n"
; | |
| 1456 } else { | |
| 1457 $code .= " ${implClassName}V8Internal::${attrName}AttributeGetter${fo
rMainWorldSuffix}(info);\n"; | |
| 1458 } | |
| 1459 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n"; | |
| 1460 $code .= "}\n"; | |
| 1461 $code .= "#endif // ${conditionalString}\n" if $conditionalString; | |
| 1462 $code .= "\n"; | |
| 1463 | |
| 1464 $implementation{nameSpaceInternal}->add($code); | |
| 1465 } | |
| 1466 | |
| 1467 sub GetCachedAttribute | |
| 1468 { | |
| 1469 my $attribute = shift; | |
| 1470 my $attrExt = $attribute->extendedAttributes; | |
| 1471 if (($attribute->type eq "any" || $attribute->type eq "SerializedScriptValue
") && $attrExt->{"CachedAttribute"}) { | |
| 1472 return $attrExt->{"CachedAttribute"}; | |
| 1473 } | |
| 1474 return ""; | |
| 1475 } | |
| 1476 | |
| 1477 sub GenerateNormalAttributeGetter | |
| 1478 { | |
| 1479 my $attribute = shift; | |
| 1480 my $interface = shift; | |
| 1481 my $forMainWorldSuffix = shift; | |
| 1482 my $exposeJSAccessors = shift; | |
| 1483 | |
| 1484 my $interfaceName = $interface->name; | |
| 1485 my $implClassName = GetImplName($interface); | |
| 1486 my $v8ClassName = GetV8ClassName($interface); | |
| 1487 my $attrExt = $attribute->extendedAttributes; | |
| 1488 my $attrName = $attribute->name; | |
| 1489 my $attrType = $attribute->type; | |
| 1490 my $attrCached = GetCachedAttribute($attribute); | |
| 1491 | |
| 1492 if (HasCustomGetter($attrExt)) { | |
| 1493 return; | |
| 1494 } | |
| 1495 | |
| 1496 AssertNotSequenceType($attrType); | |
| 1497 my $nativeType = GetNativeType($attribute->type, $attribute->extendedAttribu
tes, ""); | |
| 1498 my $svgNativeType = GetSVGTypeNeedingTearOff($interfaceName); | |
| 1499 | |
| 1500 my $conditionalString = GenerateConditionalString($attribute); | |
| 1501 my $code = ""; | |
| 1502 $code .= "#if ${conditionalString}\n" if $conditionalString; | |
| 1503 if ($exposeJSAccessors) { | |
| 1504 $code .= "static void ${attrName}AttributeGetter${forMainWorldSuffix}(co
nst v8::FunctionCallbackInfo<v8::Value>& info)\n"; | |
| 1505 } else { | |
| 1506 $code .= "static void ${attrName}AttributeGetter${forMainWorldSuffix}(co
nst v8::PropertyCallbackInfo<v8::Value>& info)\n"; | |
| 1507 } | |
| 1508 $code .= "{\n"; | |
| 1509 if ($svgNativeType) { | |
| 1510 my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($interfaceNam
e); | |
| 1511 if ($svgWrappedNativeType =~ /List/) { | |
| 1512 $code .= <<END; | |
| 1513 $svgNativeType* imp = ${v8ClassName}::toNative(info.Holder()); | |
| 1514 END | |
| 1515 } else { | |
| 1516 $code .= <<END; | |
| 1517 $svgNativeType* wrapper = ${v8ClassName}::toNative(info.Holder()); | |
| 1518 $svgWrappedNativeType& impInstance = wrapper->propertyReference(); | |
| 1519 $svgWrappedNativeType* imp = &impInstance; | |
| 1520 END | |
| 1521 } | |
| 1522 } elsif ($attrExt->{"OnPrototype"} || $attrExt->{"Unforgeable"}) { | |
| 1523 if ($interfaceName eq "Window") { | |
| 1524 $code .= <<END; | |
| 1525 v8::Handle<v8::Object> holder = info.Holder(); | |
| 1526 END | |
| 1527 } else { | |
| 1528 # perform lookup first | |
| 1529 $code .= <<END; | |
| 1530 v8::Handle<v8::Object> holder = ${v8ClassName}::findInstanceInPrototypeChain
(info.This(), info.GetIsolate()); | |
| 1531 if (holder.IsEmpty()) | |
| 1532 return; | |
| 1533 END | |
| 1534 } | |
| 1535 $code .= <<END; | |
| 1536 ${implClassName}* imp = ${v8ClassName}::toNative(holder); | |
| 1537 END | |
| 1538 } else { | |
| 1539 my $reflect = $attribute->extendedAttributes->{"Reflect"}; | |
| 1540 my $url = $attribute->extendedAttributes->{"URL"}; | |
| 1541 if ($reflect && !$url && InheritsInterface($interface, "Node") && $attrT
ype eq "DOMString") { | |
| 1542 # Generate super-compact call for regular attribute getter: | |
| 1543 my ($functionName, @arguments) = GetterExpression($interfaceName, $a
ttribute); | |
| 1544 my $getterExpression = "imp->${functionName}(" . join(", ", @argumen
ts) . ")"; | |
| 1545 $code .= " Element* imp = V8Element::toNative(info.Holder());\n"; | |
| 1546 if ($attribute->extendedAttributes->{"ReflectOnly"}) { | |
| 1547 $code .= " String resultValue = ${getterExpression};\n"; | |
| 1548 $code .= GenerateReflectOnlyCheck($attribute->extendedAttributes
, " "); | |
| 1549 $getterExpression = "resultValue"; | |
| 1550 } | |
| 1551 $code .= " v8SetReturnValueString(info, ${getterExpression}, info
.GetIsolate());\n"; | |
| 1552 $code .= "}\n"; | |
| 1553 $code .= "#endif // ${conditionalString}\n" if $conditionalString; | |
| 1554 $code .= "\n"; | |
| 1555 $implementation{nameSpaceInternal}->add($code); | |
| 1556 return; | |
| 1557 # Skip the rest of the function! | |
| 1558 } | |
| 1559 my $imp = 0; | |
| 1560 if ($attrCached) { | |
| 1561 $imp = 1; | |
| 1562 $code .= <<END; | |
| 1563 v8::Handle<v8::String> propertyName = v8AtomicString(info.GetIsolate(), "${a
ttrName}"); | |
| 1564 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()); | |
| 1565 if (!imp->$attrCached()) { | |
| 1566 v8::Handle<v8::Value> jsValue = getHiddenValue(info.GetIsolate(), info.H
older(), propertyName); | |
| 1567 if (!jsValue.IsEmpty()) { | |
| 1568 v8SetReturnValue(info, jsValue); | |
| 1569 return; | |
| 1570 } | |
| 1571 } | |
| 1572 END | |
| 1573 } | |
| 1574 if (!$attribute->isStatic && !$imp) { | |
| 1575 $code .= <<END; | |
| 1576 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()); | |
| 1577 END | |
| 1578 } | |
| 1579 } | |
| 1580 | |
| 1581 my $raisesException = $attribute->extendedAttributes->{"RaisesException"}; | |
| 1582 my $useExceptions = 1 if $raisesException && ($raisesException eq "VALUE_IS_
MISSING" or $raisesException eq "Getter"); | |
| 1583 if ($useExceptions || $attribute->extendedAttributes->{"CheckSecurity"}) { | |
| 1584 $code .= " ExceptionState exceptionState(ExceptionState::GetterContex
t, \"${attrName}\", \"${interfaceName}\", info.Holder(), info.GetIsolate());\n"; | |
| 1585 } | |
| 1586 | |
| 1587 # Generate security checks if necessary | |
| 1588 if ($attribute->extendedAttributes->{"CheckSecurity"}) { | |
| 1589 AddToImplIncludes("bindings/v8/BindingSecurity.h"); | |
| 1590 $code .= " if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsol
ate(), imp->" . GetImplName($attribute) . "(), exceptionState)) {\n"; | |
| 1591 $code .= " v8SetReturnValueNull(info);\n"; | |
| 1592 $code .= " exceptionState.throwIfNeeded();\n"; | |
| 1593 $code .= " return;\n"; | |
| 1594 $code .= " }\n"; | |
| 1595 } | |
| 1596 | |
| 1597 my $isNullable = $attribute->isNullable; | |
| 1598 if ($isNullable) { | |
| 1599 $code .= " bool isNull = false;\n"; | |
| 1600 } | |
| 1601 | |
| 1602 my $getterString; | |
| 1603 my ($functionName, @arguments) = GetterExpression($interfaceName, $attribute
); | |
| 1604 push(@arguments, "isNull") if $isNullable; | |
| 1605 push(@arguments, "exceptionState") if $useExceptions; | |
| 1606 if ($attribute->extendedAttributes->{"ImplementedBy"}) { | |
| 1607 my $implementedBy = $attribute->extendedAttributes->{"ImplementedBy"}; | |
| 1608 my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy)
; | |
| 1609 AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implementedBy
ImplName)); | |
| 1610 if (!$attribute->isStatic) { | |
| 1611 $code .= " ASSERT(imp);\n"; | |
| 1612 unshift(@arguments, "*imp"); | |
| 1613 } | |
| 1614 $functionName = "${implementedByImplName}::${functionName}"; | |
| 1615 } elsif ($attribute->isStatic) { | |
| 1616 $functionName = "${implClassName}::${functionName}"; | |
| 1617 } else { | |
| 1618 $functionName = "imp->${functionName}"; | |
| 1619 } | |
| 1620 my ($arg, $subCode) = GenerateCallWith($attribute->extendedAttributes->{"Cal
lWith"}, " ", 0); | |
| 1621 $code .= $subCode; | |
| 1622 unshift(@arguments, @$arg); | |
| 1623 $getterString = "${functionName}(" . join(", ", @arguments) . ")"; | |
| 1624 | |
| 1625 my $expression; | |
| 1626 if ($attribute->type eq "EventHandler" && $interface->name eq "Window") { | |
| 1627 $code .= " if (!imp->document())\n"; | |
| 1628 $code .= " return;\n"; | |
| 1629 } | |
| 1630 | |
| 1631 if ($useExceptions || $isNullable) { | |
| 1632 if ($nativeType =~ /^V8StringResource/) { | |
| 1633 $code .= " " . ConvertToV8StringResource($attribute, $nativeType,
"cppValue", $getterString) . ";\n"; | |
| 1634 } else { | |
| 1635 $code .= " $nativeType jsValue = $getterString;\n"; | |
| 1636 $getterString = "jsValue"; | |
| 1637 } | |
| 1638 | |
| 1639 if ($isNullable) { | |
| 1640 $code .= " if (isNull) {\n"; | |
| 1641 $code .= " v8SetReturnValueNull(info);\n"; | |
| 1642 $code .= " return;\n"; | |
| 1643 $code .= " }\n"; | |
| 1644 } | |
| 1645 | |
| 1646 if ($useExceptions) { | |
| 1647 if ($useExceptions) { | |
| 1648 $code .= " if (UNLIKELY(exceptionState.throwIfNeeded()))\n"; | |
| 1649 $code .= " return;\n"; | |
| 1650 } | |
| 1651 | |
| 1652 if (ExtendedAttributeContains($attribute->extendedAttributes->{"Call
With"}, "ScriptState")) { | |
| 1653 $code .= " if (state.hadException()) {\n"; | |
| 1654 $code .= " throwError(state.exception(), info.GetIsolate(
));\n"; | |
| 1655 $code .= " return;\n"; | |
| 1656 $code .= " }\n"; | |
| 1657 } | |
| 1658 } | |
| 1659 | |
| 1660 $expression = "jsValue"; | |
| 1661 $expression .= ".release()" if (IsRefPtrType($attrType)); | |
| 1662 } else { | |
| 1663 # Can inline the function call into the return statement to avoid overhe
ad of using a Ref<> temporary | |
| 1664 $expression = $getterString; | |
| 1665 } | |
| 1666 | |
| 1667 if (ShouldKeepAttributeAlive($interface, $attribute, $attrType)) { | |
| 1668 my $arrayType = GetArrayType($attrType); | |
| 1669 if ($arrayType) { | |
| 1670 $code .= " v8SetReturnValue(info, v8Array(${getterString}, info.G
etIsolate()));\n"; | |
| 1671 $code .= "}\n\n"; | |
| 1672 $implementation{nameSpaceInternal}->add($code); | |
| 1673 return; | |
| 1674 } | |
| 1675 | |
| 1676 # Check for a wrapper in the wrapper cache. If there is one, we know tha
t a hidden reference has already | |
| 1677 # been created. If we don't find a wrapper, we create both a wrapper and
a hidden reference. | |
| 1678 my $nativeReturnType = GetNativeType($attrType); | |
| 1679 my $v8ReturnType = "V8" . $attrType; | |
| 1680 $code .= " $nativeReturnType result = ${getterString};\n"; | |
| 1681 if ($forMainWorldSuffix) { | |
| 1682 $code .= " if (result && DOMDataStore::setReturnValueFromWrapper$
{forMainWorldSuffix}<${v8ReturnType}>(info.GetReturnValue(), result.get()))\n"; | |
| 1683 } else { | |
| 1684 $code .= " if (result && DOMDataStore::setReturnValueFromWrapper<
${v8ReturnType}>(info.GetReturnValue(), result.get()))\n"; | |
| 1685 } | |
| 1686 $code .= " return;\n"; | |
| 1687 $code .= " v8::Handle<v8::Value> wrapper = toV8(result.get(), info.Ho
lder(), info.GetIsolate());\n"; | |
| 1688 $code .= " if (!wrapper.IsEmpty()) {\n"; | |
| 1689 $code .= " setHiddenValue(info.GetIsolate(), info.Holder(), \"${a
ttrName}\", wrapper);\n"; | |
| 1690 $code .= " v8SetReturnValue(info, wrapper);\n"; | |
| 1691 $code .= " }\n"; | |
| 1692 $code .= "}\n"; | |
| 1693 $code .= "#endif // ${conditionalString}\n" if $conditionalString; | |
| 1694 $code .= "\n"; | |
| 1695 $implementation{nameSpaceInternal}->add($code); | |
| 1696 return; | |
| 1697 } | |
| 1698 | |
| 1699 if ((IsSVGAnimatedType($interfaceName) or $interfaceName eq "SVGViewSpec") a
nd IsSVGTypeNeedingTearOff($attrType)) { | |
| 1700 AddToImplIncludes("V8$attrType.h"); | |
| 1701 my $svgNativeType = GetSVGTypeNeedingTearOff($attrType); | |
| 1702 # Convert from abstract SVGProperty to real type, so the right toJS() me
thod can be invoked. | |
| 1703 if ($forMainWorldSuffix eq "ForMainWorld") { | |
| 1704 $code .= " v8SetReturnValueForMainWorld(info, static_cast<$svgNat
iveType*>($expression));\n"; | |
| 1705 } else { | |
| 1706 $code .= " v8SetReturnValueFast(info, static_cast<$svgNativeType*
>($expression), imp);\n"; | |
| 1707 } | |
| 1708 } elsif (IsSVGTypeNeedingTearOff($attrType) and not $interfaceName =~ /List$
/) { | |
| 1709 AddToImplIncludes("V8$attrType.h"); | |
| 1710 AddToImplIncludes("core/svg/properties/SVGPropertyTearOff.h"); | |
| 1711 my $tearOffType = GetSVGTypeNeedingTearOff($attrType); | |
| 1712 my $wrappedValue; | |
| 1713 if ($tearOffType =~ /SVGStaticListPropertyTearOff/) { | |
| 1714 $wrappedValue = "WTF::getPtr(${tearOffType}::create(imp, $expres
sion))"; | |
| 1715 } else { | |
| 1716 $wrappedValue = "WTF::getPtr(${tearOffType}::create($expression)
)"; | |
| 1717 } | |
| 1718 if ($forMainWorldSuffix eq "ForMainWorld") { | |
| 1719 $code .= " v8SetReturnValueForMainWorld(info, $wrappedValue);\n"; | |
| 1720 } else { | |
| 1721 $code .= " v8SetReturnValueFast(info, $wrappedValue, imp);\n"; | |
| 1722 } | |
| 1723 } elsif ($attrCached) { | |
| 1724 if ($attribute->type eq "SerializedScriptValue") { | |
| 1725 $code .= <<END; | |
| 1726 RefPtr<SerializedScriptValue> serialized = $getterString; | |
| 1727 ScriptValue jsValue = serialized ? serialized->deserialize() : v8::Handle<v8
::Value>(v8::Null(info.GetIsolate())); | |
| 1728 setHiddenValue(info.GetIsolate(), info.Holder(), propertyName, jsValue); | |
| 1729 v8SetReturnValue(info, jsValue); | |
| 1730 END | |
| 1731 } else { | |
| 1732 if (!$useExceptions && !$isNullable) { | |
| 1733 $code .= <<END; | |
| 1734 ScriptValue jsValue = $getterString; | |
| 1735 END | |
| 1736 } | |
| 1737 $code .= <<END; | |
| 1738 setHiddenValue(info.GetIsolate(), info.Holder(), propertyName, jsValue.v8Val
ue()); | |
| 1739 v8SetReturnValue(info, jsValue.v8Value()); | |
| 1740 END | |
| 1741 } | |
| 1742 } elsif ($attribute->type eq "EventHandler") { | |
| 1743 AddToImplIncludes("bindings/v8/V8AbstractEventListener.h"); | |
| 1744 # FIXME: Pass the main world ID for main-world-only getters. | |
| 1745 my ($functionName, @arguments) = GetterExpression($interfaceName, $attri
bute); | |
| 1746 my $implementedBy = $attribute->extendedAttributes->{"ImplementedBy"}; | |
| 1747 if ($implementedBy) { | |
| 1748 my $implementedByImplName = GetImplNameFromImplementedBy($implemente
dBy); | |
| 1749 $functionName = "${implementedByImplName}::${functionName}"; | |
| 1750 $code .= " ASSERT(imp);\n"; | |
| 1751 push(@arguments, "*imp"); | |
| 1752 } else { | |
| 1753 $functionName = "imp->${functionName}"; | |
| 1754 } | |
| 1755 $code .= " EventListener* jsValue = ${functionName}(" . join(", ", @a
rguments) . ");\n"; | |
| 1756 $code .= " v8SetReturnValue(info, jsValue ? v8::Handle<v8::Value>(V8A
bstractEventListener::cast(jsValue)->getListenerObject(imp->executionContext()))
: v8::Handle<v8::Value>(v8::Null(info.GetIsolate())));\n"; | |
| 1757 } else { | |
| 1758 my $nativeValue = NativeToJSValue($attribute->type, $attribute->extended
Attributes, $expression, " ", "", "info.GetIsolate()", "info", "imp", $forMai
nWorldSuffix, "return"); | |
| 1759 $code .= "${nativeValue}\n"; | |
| 1760 } | |
| 1761 | |
| 1762 $code .= "}\n"; # end of getter | |
| 1763 $code .= "#endif // ${conditionalString}\n" if $conditionalString; | |
| 1764 $code .= "\n"; | |
| 1765 $implementation{nameSpaceInternal}->add($code); | |
| 1766 } | |
| 1767 | |
| 1768 sub ShouldKeepAttributeAlive | |
| 1769 { | |
| 1770 my ($interface, $attribute, $returnType) = @_; | |
| 1771 my $attrName = $attribute->name; | |
| 1772 | |
| 1773 # For readonly attributes (including Replaceable), as a general rule, for | |
| 1774 # performance reasons we keep the attribute wrapper alive while the owner | |
| 1775 # wrapper is alive, because the attribute never changes. | |
| 1776 return 0 if !IsWrapperType($returnType); | |
| 1777 return 0 if !IsReadonly($attribute) && !$attribute->extendedAttributes->{"Re
placeable"}; | |
| 1778 | |
| 1779 # However, there are a couple of exceptions. | |
| 1780 | |
| 1781 # Node lifetime is managed by object grouping. | |
| 1782 return 0 if InheritsInterface($interface, "Node"); | |
| 1783 return 0 if IsDOMNodeType($returnType); | |
| 1784 | |
| 1785 # To avoid adding a reference to itself. | |
| 1786 # FIXME: Introduce [DoNotKeepAttributeAliveForGC] and remove this hack | |
| 1787 # depending on the attribute name. | |
| 1788 return 0 if $attrName eq "self"; | |
| 1789 | |
| 1790 # FIXME: Remove these hard-coded hacks. | |
| 1791 return 0 if $returnType eq "EventTarget"; | |
| 1792 return 0 if $returnType eq "Window"; | |
| 1793 return 0 if $returnType =~ /SVG/; | |
| 1794 return 0 if $returnType =~ /HTML/; | |
| 1795 | |
| 1796 return 1; | |
| 1797 } | |
| 1798 | |
| 1799 sub GenerateReplaceableAttributeSetterCallback | |
| 1800 { | |
| 1801 my $interface = shift; | |
| 1802 my $implClassName = GetImplName($interface); | |
| 1803 | |
| 1804 my $code = ""; | |
| 1805 $code .= "static void ${implClassName}ReplaceableAttributeSetterCallback(v8:
:Local<v8::String> name, v8::Local<v8::Value> jsValue, const v8::PropertyCallbac
kInfo<void>& info)\n"; | |
| 1806 $code .= "{\n"; | |
| 1807 $code .= GenerateFeatureObservation($interface->extendedAttributes->{"Measur
eAs"}); | |
| 1808 $code .= GenerateDeprecationNotification($interface->extendedAttributes->{"D
eprecateAs"}); | |
| 1809 $code .= GenerateCustomElementInvocationScopeIfNeeded($interface->extendedAt
tributes); | |
| 1810 if (HasActivityLogging("", $interface->extendedAttributes, "Setter")) { | |
| 1811 die "IDL error: ActivityLog attribute cannot exist on a ReplacableAttri
buteSetterCallback"; | |
| 1812 } | |
| 1813 $code .= " ${implClassName}V8Internal::${implClassName}ReplaceableAttribu
teSetter(name, jsValue, info);\n"; | |
| 1814 $code .= "}\n\n"; | |
| 1815 $implementation{nameSpaceInternal}->add($code); | |
| 1816 } | |
| 1817 | |
| 1818 sub GenerateReplaceableAttributeSetter | |
| 1819 { | |
| 1820 my $interface = shift; | |
| 1821 | |
| 1822 my $interfaceName = $interface->name(); | |
| 1823 my $implClassName = GetImplName($interface); | |
| 1824 my $v8ClassName = GetV8ClassName($interface); | |
| 1825 | |
| 1826 my $code = ""; | |
| 1827 $code .= <<END; | |
| 1828 static void ${implClassName}ReplaceableAttributeSetter(v8::Local<v8::String> nam
e, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info) | |
| 1829 { | |
| 1830 END | |
| 1831 if ($interface->extendedAttributes->{"CheckSecurity"}) { | |
| 1832 AddToImplIncludes("bindings/v8/BindingSecurity.h"); | |
| 1833 $code .= <<END; | |
| 1834 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()); | |
| 1835 v8::String::Utf8Value attributeName(name); | |
| 1836 ExceptionState exceptionState(ExceptionState::SetterContext, *attributeName,
"${interfaceName}", info.Holder(), info.GetIsolate()); | |
| 1837 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), imp->frame
(), exceptionState)) { | |
| 1838 exceptionState.throwIfNeeded(); | |
| 1839 return; | |
| 1840 } | |
| 1841 END | |
| 1842 } | |
| 1843 | |
| 1844 $code .= <<END; | |
| 1845 info.This()->ForceSet(name, jsValue); | |
| 1846 } | |
| 1847 | |
| 1848 END | |
| 1849 $implementation{nameSpaceInternal}->add($code); | |
| 1850 } | |
| 1851 | |
| 1852 sub GenerateCustomElementInvocationScopeIfNeeded | |
| 1853 { | |
| 1854 my $code = ""; | |
| 1855 my $ext = shift; | |
| 1856 | |
| 1857 if ($ext->{"CustomElementCallbacks"} or $ext->{"Reflect"}) { | |
| 1858 AddToImplIncludes("core/dom/custom/CustomElementCallbackDispatcher.h"); | |
| 1859 $code .= <<END; | |
| 1860 CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope; | |
| 1861 END | |
| 1862 } | |
| 1863 return $code; | |
| 1864 } | |
| 1865 | |
| 1866 sub GenerateNormalAttributeSetterCallback | |
| 1867 { | |
| 1868 my $attribute = shift; | |
| 1869 my $interface = shift; | |
| 1870 my $forMainWorldSuffix = shift; | |
| 1871 my $exposeJSAccessors = shift; | |
| 1872 | |
| 1873 my $implClassName = GetImplName($interface); | |
| 1874 my $v8ClassName = GetV8ClassName($interface); | |
| 1875 my $attrExt = $attribute->extendedAttributes; | |
| 1876 my $attrName = $attribute->name; | |
| 1877 | |
| 1878 my $conditionalString = GenerateConditionalString($attribute); | |
| 1879 my $code = ""; | |
| 1880 $code .= "#if ${conditionalString}\n" if $conditionalString; | |
| 1881 | |
| 1882 if ($exposeJSAccessors) { | |
| 1883 $code .= "static void ${attrName}AttributeSetterCallback${forMainWorldSu
ffix}(const v8::FunctionCallbackInfo<v8::Value>& info)\n"; | |
| 1884 $code .= "{\n"; | |
| 1885 $code .= " v8::Local<v8::Value> jsValue = info[0];\n"; | |
| 1886 } else { | |
| 1887 $code .= "static void ${attrName}AttributeSetterCallback${forMainWorldSu
ffix}(v8::Local<v8::String>, v8::Local<v8::Value> jsValue, const v8::PropertyCal
lbackInfo<void>& info)\n"; | |
| 1888 $code .= "{\n"; | |
| 1889 } | |
| 1890 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMSetter\");\n"; | |
| 1891 $code .= GenerateFeatureObservation($attrExt->{"MeasureAs"}); | |
| 1892 $code .= GenerateDeprecationNotification($attrExt->{"DeprecateAs"}); | |
| 1893 if (HasActivityLogging($forMainWorldSuffix, $attrExt, "Setter")) { | |
| 1894 $code .= GenerateActivityLogging("Setter", $interface, "${attrName}"); | |
| 1895 } | |
| 1896 $code .= GenerateCustomElementInvocationScopeIfNeeded($attrExt); | |
| 1897 if (HasCustomSetter($attribute)) { | |
| 1898 $code .= " ${v8ClassName}::${attrName}AttributeSetterCustom(jsValue,
info);\n"; | |
| 1899 } else { | |
| 1900 $code .= " ${implClassName}V8Internal::${attrName}AttributeSetter${fo
rMainWorldSuffix}(jsValue, info);\n"; | |
| 1901 } | |
| 1902 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n"; | |
| 1903 $code .= "}\n"; | |
| 1904 $code .= "#endif // ${conditionalString}\n" if $conditionalString; | |
| 1905 $code .= "\n"; | |
| 1906 $implementation{nameSpaceInternal}->add($code); | |
| 1907 } | |
| 1908 | |
| 1909 sub FindAttributeWithName | |
| 1910 { | |
| 1911 my $interface = shift; | |
| 1912 my $attrName = shift; | |
| 1913 | |
| 1914 foreach my $attribute (@{$interface->attributes}) { | |
| 1915 if ($attribute->name eq $attrName) { | |
| 1916 return $attribute; | |
| 1917 } | |
| 1918 } | |
| 1919 } | |
| 1920 | |
| 1921 sub GenerateNormalAttributeSetter | |
| 1922 { | |
| 1923 my $attribute = shift; | |
| 1924 my $interface = shift; | |
| 1925 my $forMainWorldSuffix = shift; | |
| 1926 my $exposeJSAccessors = shift; | |
| 1927 | |
| 1928 my $interfaceName = $interface->name; | |
| 1929 my $implClassName = GetImplName($interface); | |
| 1930 my $v8ClassName = GetV8ClassName($interface); | |
| 1931 my $attrName = $attribute->name; | |
| 1932 my $attrExt = $attribute->extendedAttributes; | |
| 1933 my $attrType = $attribute->type; | |
| 1934 my $attrCached = GetCachedAttribute($attribute); | |
| 1935 | |
| 1936 if (HasCustomSetter($attribute)) { | |
| 1937 return; | |
| 1938 } | |
| 1939 | |
| 1940 my $conditionalString = GenerateConditionalString($attribute); | |
| 1941 my $code = ""; | |
| 1942 $code .= "#if ${conditionalString}\n" if $conditionalString; | |
| 1943 if ($exposeJSAccessors) { | |
| 1944 $code .= "static void ${attrName}AttributeSetter${forMainWorldSuffix}(v8
::Local<v8::Value> jsValue, const v8::FunctionCallbackInfo<v8::Value>& info)\n"; | |
| 1945 } else { | |
| 1946 $code .= "static void ${attrName}AttributeSetter${forMainWorldSuffix}(v8
::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info)\n"; | |
| 1947 } | |
| 1948 $code .= "{\n"; | |
| 1949 | |
| 1950 my $raisesException = $attribute->extendedAttributes->{"RaisesException"}; | |
| 1951 my $useExceptions = 1 if $raisesException && ($raisesException eq "VALUE_IS_
MISSING" or $raisesException eq "Setter"); | |
| 1952 my $hasStrictTypeChecking = 1 if ($interface->extendedAttributes->{"StrictTy
peChecking"} || $attribute->extendedAttributes->{"StrictTypeChecking"}) && IsWra
pperType($attrType); # Currently only actually check interface types | |
| 1953 | |
| 1954 # Can throw exceptions from accessors or during type conversion. | |
| 1955 my $isIntegerType = IsIntegerType($attribute->type); | |
| 1956 | |
| 1957 # We throw exceptions using 'ExceptionState' if the attribute explicitly | |
| 1958 # claims that exceptions may be raised, or if a strict type check might | |
| 1959 # fail, or if we're dealing with SVG, which does strange things with | |
| 1960 # tearoffs and read-only wrappers. | |
| 1961 if ($useExceptions or $hasStrictTypeChecking or GetSVGTypeNeedingTearOff($in
terfaceName) or GetSVGTypeNeedingTearOff($attrType) or $isIntegerType) { | |
| 1962 $code .= " ExceptionState exceptionState(ExceptionState::SetterContex
t, \"${attrName}\", \"${interfaceName}\", info.Holder(), info.GetIsolate());\n"; | |
| 1963 } | |
| 1964 | |
| 1965 # If the "StrictTypeChecking" extended attribute is present, and the | |
| 1966 # attribute's type is an interface type, then if the incoming value does not | |
| 1967 # implement that interface, a TypeError is thrown rather than silently | |
| 1968 # passing NULL to the C++ code. | |
| 1969 # Per the Web IDL and ECMAScript specifications, incoming values can always | |
| 1970 # be converted to both strings and numbers, so do not throw TypeError if the | |
| 1971 # attribute is of these types. | |
| 1972 if ($hasStrictTypeChecking) { | |
| 1973 $code .= " if (!isUndefinedOrNull(jsValue) && !V8${attrType}::hasInst
ance(jsValue, info.GetIsolate())) {\n"; | |
| 1974 $code .= " exceptionState.throwTypeError(\"The provided value is
not of type '${attrType}'.\");\n"; | |
| 1975 $code .= " exceptionState.throwIfNeeded();\n"; | |
| 1976 $code .= " return;\n"; | |
| 1977 $code .= " }\n"; | |
| 1978 } | |
| 1979 | |
| 1980 my $svgNativeType = GetSVGTypeNeedingTearOff($interfaceName); | |
| 1981 if ($svgNativeType) { | |
| 1982 my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($interfaceNam
e); | |
| 1983 if ($svgWrappedNativeType =~ /List$/) { | |
| 1984 $code .= <<END; | |
| 1985 $svgNativeType* imp = ${v8ClassName}::toNative(info.Holder()); | |
| 1986 END | |
| 1987 } else { | |
| 1988 $code .= " $svgNativeType* wrapper = ${v8ClassName}::toNative(inf
o.Holder());\n"; | |
| 1989 $code .= " if (wrapper->isReadOnly()) {\n"; | |
| 1990 $code .= " exceptionState.throwDOMException(NoModificationAll
owedError, \"The attribute is read-only.\");\n"; | |
| 1991 $code .= " exceptionState.throwIfNeeded();\n"; | |
| 1992 $code .= " return;\n"; | |
| 1993 $code .= " }\n"; | |
| 1994 $code .= " $svgWrappedNativeType& impInstance = wrapper->property
Reference();\n"; | |
| 1995 $code .= " $svgWrappedNativeType* imp = &impInstance;\n"; | |
| 1996 } | |
| 1997 } elsif ($attrExt->{"OnPrototype"}) { | |
| 1998 $code .= <<END; | |
| 1999 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()); | |
| 2000 END | |
| 2001 } elsif($attrExt->{"PutForwards"}) { | |
| 2002 my $destinationAttrName = $attrExt->{"PutForwards"}; | |
| 2003 my $destinationInterface = ParseInterface($attrType); | |
| 2004 die "[PutForwards=x] value must be a wrapper type" unless $destinationIn
terface; | |
| 2005 my $destinationAttribute = FindAttributeWithName($destinationInterface,
$destinationAttrName); | |
| 2006 die "[PutForwards=x] could not find $destinationAttrName in interface $a
ttrType" unless $destinationAttribute; | |
| 2007 $code .= <<END; | |
| 2008 ${implClassName}* proxyImp = ${v8ClassName}::toNative(info.Holder()); | |
| 2009 ${attrType}* imp = proxyImp->${attrName}(); | |
| 2010 if (!imp) | |
| 2011 return; | |
| 2012 END | |
| 2013 # Override attribute and fall through to forward setter call. | |
| 2014 $attribute = $destinationAttribute; | |
| 2015 $attrName = $attribute->name; | |
| 2016 $attrType = $attribute->type; | |
| 2017 $attrExt = $attribute->extendedAttributes; | |
| 2018 } else { | |
| 2019 my $reflect = $attribute->extendedAttributes->{"Reflect"}; | |
| 2020 if ($reflect && InheritsInterface($interface, "Node") && $attrType eq "D
OMString") { | |
| 2021 # Generate super-compact call for regular attribute setter: | |
| 2022 my $contentAttributeName = $reflect eq "VALUE_IS_MISSING" ? lc $attr
Name : $reflect; | |
| 2023 my $namespace = NamespaceForAttributeName($interfaceName, $contentAt
tributeName); | |
| 2024 my $mode = GetV8StringResourceMode($attribute->extendedAttributes); | |
| 2025 AddToImplIncludes("${namespace}.h"); | |
| 2026 $code .= " Element* imp = V8Element::toNative(info.Holder());\n"; | |
| 2027 $code .= " V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<
$mode>, cppValue, jsValue);\n"; | |
| 2028 # Attr (not Attribute) used in content attributes | |
| 2029 $code .= " imp->setAttribute(${namespace}::${contentAttributeName
}Attr, cppValue);\n"; | |
| 2030 $code .= "}\n"; | |
| 2031 $code .= "#endif // ${conditionalString}\n" if $conditionalString; | |
| 2032 $code .= "\n"; | |
| 2033 $implementation{nameSpaceInternal}->add($code); | |
| 2034 return; | |
| 2035 # Skip the rest of the function! | |
| 2036 } | |
| 2037 | |
| 2038 if (!$attribute->isStatic) { | |
| 2039 $code .= <<END; | |
| 2040 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()); | |
| 2041 END | |
| 2042 } | |
| 2043 } | |
| 2044 | |
| 2045 my $nativeType = GetNativeType($attribute->type, $attribute->extendedAttribu
tes, "parameter"); | |
| 2046 if ($attribute->type eq "EventHandler") { | |
| 2047 if ($interface->name eq "Window") { | |
| 2048 $code .= " if (!imp->document())\n"; | |
| 2049 $code .= " return;\n"; | |
| 2050 } | |
| 2051 } else { | |
| 2052 my $asSetterValue = 0; | |
| 2053 $code .= JSValueToNativeStatement($attribute->type, $attribute->extended
Attributes, $asSetterValue, "jsValue", "cppValue", " ", "info.GetIsolate()"); | |
| 2054 } | |
| 2055 | |
| 2056 if (IsEnumType($attrType)) { | |
| 2057 # setter ignores invalid enumeration values | |
| 2058 my @enumValues = ValidEnumValues($attrType); | |
| 2059 my @validEqualities = (); | |
| 2060 foreach my $enumValue (@enumValues) { | |
| 2061 push(@validEqualities, "string == \"$enumValue\""); | |
| 2062 } | |
| 2063 my $enumValidationExpression = join(" || ", @validEqualities); | |
| 2064 $code .= <<END; | |
| 2065 String string = cppValue; | |
| 2066 if (!($enumValidationExpression)) | |
| 2067 return; | |
| 2068 END | |
| 2069 } | |
| 2070 | |
| 2071 my $expression = "cppValue"; | |
| 2072 my $returnType = $attribute->type; | |
| 2073 if (IsRefPtrType($returnType) && !GetArrayType($returnType)) { | |
| 2074 $expression = "WTF::getPtr(" . $expression . ")"; | |
| 2075 } | |
| 2076 | |
| 2077 $code .= GenerateCustomElementInvocationScopeIfNeeded($attribute->extendedAt
tributes); | |
| 2078 | |
| 2079 my $returnSvgNativeType = GetSVGTypeNeedingTearOff($returnType); | |
| 2080 if ($returnSvgNativeType) { | |
| 2081 $code .= <<END; | |
| 2082 if (!$expression) { | |
| 2083 exceptionState.throwTypeError(\"The provided value is not of type '$retu
rnType'.\"); | |
| 2084 exceptionState.throwIfNeeded(); | |
| 2085 return; | |
| 2086 } | |
| 2087 END | |
| 2088 $expression = $expression . "->propertyReference()"; | |
| 2089 } | |
| 2090 | |
| 2091 if ($attribute->type eq "EventHandler") { | |
| 2092 my $implementedBy = $attribute->extendedAttributes->{"ImplementedBy"}; | |
| 2093 my $implementedByImplName; | |
| 2094 if ($implementedBy) { | |
| 2095 $implementedByImplName = GetImplNameFromImplementedBy($implementedBy
); | |
| 2096 } | |
| 2097 if (!InheritsInterface($interface, "Node")) { | |
| 2098 my $attrImplName = GetImplName($attribute); | |
| 2099 my @arguments; | |
| 2100 if ($implementedBy) { | |
| 2101 $attrImplName = "${implementedByImplName}::${attrImplName}"; | |
| 2102 $code .= " ASSERT(imp);\n"; | |
| 2103 push(@arguments, "*imp"); | |
| 2104 } else { | |
| 2105 $attrImplName = "imp->${attrImplName}"; | |
| 2106 } | |
| 2107 $code .= " moveEventListenerToNewWrapper(info.Holder(), ${attrImp
lName}(" . join(", ", @arguments) . "), jsValue, ${v8ClassName}::eventListenerCa
cheIndex, info.GetIsolate());\n"; | |
| 2108 } | |
| 2109 my ($functionName, @arguments) = SetterExpression($interfaceName, $attri
bute); | |
| 2110 if ($implementedBy) { | |
| 2111 $code .= " ASSERT(imp);\n"; | |
| 2112 $functionName = "${implementedByImplName}::${functionName}"; | |
| 2113 push(@arguments, "*imp"); | |
| 2114 } else { | |
| 2115 $functionName = "imp->${functionName}"; | |
| 2116 } | |
| 2117 if (($interfaceName eq "Window" or $interfaceName eq "WorkerGlobalScope"
) and $attribute->name eq "onerror") { | |
| 2118 AddToImplIncludes("bindings/v8/V8ErrorHandler.h"); | |
| 2119 push(@arguments, "V8EventListenerList::findOrCreateWrapper<V8ErrorHa
ndler>(jsValue, true, info.GetIsolate())"); | |
| 2120 } else { | |
| 2121 push(@arguments, "V8EventListenerList::getEventListener(jsValue, tru
e, ListenerFindOrCreate)"); | |
| 2122 } | |
| 2123 $code .= " ${functionName}(" . join(", ", @arguments) . ");\n"; | |
| 2124 } else { | |
| 2125 my ($functionName, @arguments) = SetterExpression($interfaceName, $attri
bute); | |
| 2126 push(@arguments, $expression); | |
| 2127 push(@arguments, "exceptionState") if $useExceptions; | |
| 2128 if ($attribute->extendedAttributes->{"ImplementedBy"}) { | |
| 2129 my $implementedBy = $attribute->extendedAttributes->{"ImplementedBy"
}; | |
| 2130 my $implementedByImplName = GetImplNameFromImplementedBy($implemente
dBy); | |
| 2131 AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implement
edByImplName)); | |
| 2132 if (!$attribute->isStatic) { | |
| 2133 $code .= " ASSERT(imp);\n"; | |
| 2134 unshift(@arguments, "*imp"); | |
| 2135 } | |
| 2136 $functionName = "${implementedByImplName}::${functionName}"; | |
| 2137 } elsif ($attribute->isStatic) { | |
| 2138 $functionName = "${implClassName}::${functionName}"; | |
| 2139 } else { | |
| 2140 $functionName = "imp->${functionName}"; | |
| 2141 } | |
| 2142 my ($arg, $subCode) = GenerateCallWith($attribute->extendedAttributes->{
"SetterCallWith"} || $attribute->extendedAttributes->{"CallWith"}, " ", 1); | |
| 2143 $code .= $subCode; | |
| 2144 unshift(@arguments, @$arg); | |
| 2145 $code .= " ${functionName}(" . join(", ", @arguments) . ");\n"; | |
| 2146 } | |
| 2147 | |
| 2148 if ($useExceptions) { | |
| 2149 $code .= " exceptionState.throwIfNeeded();\n"; | |
| 2150 } | |
| 2151 | |
| 2152 if (ExtendedAttributeContains($attribute->extendedAttributes->{"CallWith"},
"ScriptState")) { | |
| 2153 $code .= " if (state.hadException())\n"; | |
| 2154 $code .= " throwError(state.exception(), info.GetIsolate());\n"; | |
| 2155 } | |
| 2156 | |
| 2157 if ($svgNativeType) { | |
| 2158 if ($useExceptions) { | |
| 2159 $code .= " if (!exceptionState.hadException())\n"; | |
| 2160 $code .= " wrapper->commitChange();\n"; | |
| 2161 } else { | |
| 2162 $code .= " wrapper->commitChange();\n"; | |
| 2163 } | |
| 2164 } | |
| 2165 | |
| 2166 if ($attrCached) { | |
| 2167 $code .= <<END; | |
| 2168 deleteHiddenValue(info.GetIsolate(), info.Holder(), "${attrName}"); // Inval
idate the cached value. | |
| 2169 END | |
| 2170 } | |
| 2171 | |
| 2172 $code .= "}\n"; # end of setter | |
| 2173 $code .= "#endif // ${conditionalString}\n" if $conditionalString; | |
| 2174 $code .= "\n"; | |
| 2175 $implementation{nameSpaceInternal}->add($code); | |
| 2176 } | |
| 2177 | |
| 2178 sub NullOrOptionalCheck | |
| 2179 { | |
| 2180 my $parameter = shift; | |
| 2181 my $value = shift; | |
| 2182 | |
| 2183 # If undefined is passed for an optional argument, the argument should be | |
| 2184 # treated as missing; otherwise undefined is not allowed. | |
| 2185 if ($parameter->isNullable) { | |
| 2186 if ($parameter->isOptional) { | |
| 2187 return "isUndefinedOrNull($value)"; | |
| 2188 } | |
| 2189 return "${value}->IsNull()"; | |
| 2190 } | |
| 2191 if ($parameter->isOptional) { | |
| 2192 return "${value}->IsUndefined()"; | |
| 2193 } | |
| 2194 } | |
| 2195 | |
| 2196 sub GenerateParametersCheckExpression | |
| 2197 { | |
| 2198 my $numParameters = shift; | |
| 2199 my $function = shift; | |
| 2200 | |
| 2201 my @andExpression = (); | |
| 2202 push(@andExpression, "info.Length() == $numParameters"); | |
| 2203 my $parameterIndex = 0; | |
| 2204 foreach my $parameter (@{$function->parameters}) { | |
| 2205 last if $parameterIndex >= $numParameters; | |
| 2206 my $value = "info[$parameterIndex]"; | |
| 2207 my $type = $parameter->type; | |
| 2208 | |
| 2209 my $undefinedOrNullCheck = NullOrOptionalCheck($parameter, $value); | |
| 2210 | |
| 2211 # Only DOMString, wrapper types, and (to some degree) non-wrapper types | |
| 2212 # are checked. | |
| 2213 # | |
| 2214 # FIXME: If distinguishing non-primitive type from primitive type, | |
| 2215 # (e.g., sequence<DOMString> from DOMString or Dictionary from double) | |
| 2216 # the non-primitive type must appear *first* in the IDL file, | |
| 2217 # since we're not adding a check to primitive types. | |
| 2218 # This can be avoided if compute overloads for whole overload set at | |
| 2219 # once, rather than one method at a time, but that requires a complete | |
| 2220 # rewrite of this algorithm. | |
| 2221 # | |
| 2222 # For DOMString with StrictTypeChecking only Null, Undefined and Object | |
| 2223 # are accepted for compatibility. Otherwise, no restrictions are made to | |
| 2224 # match the non-overloaded behavior. | |
| 2225 # | |
| 2226 # FIXME: Implement WebIDL overload resolution algorithm. | |
| 2227 # https://code.google.com/p/chromium/issues/detail?id=293561 | |
| 2228 if ($type eq "DOMString") { | |
| 2229 if ($parameter->extendedAttributes->{"StrictTypeChecking"}) { | |
| 2230 push(@andExpression, "isUndefinedOrNull(${value}) || ${value}->I
sString() || ${value}->IsObject()"); | |
| 2231 } | |
| 2232 } elsif (IsCallbackInterface($parameter->type)) { | |
| 2233 # For Callbacks only checks if the value is null or function. | |
| 2234 push(@andExpression, "${value}->IsNull() || ${value}->IsFunction()")
; | |
| 2235 } elsif (GetArrayOrSequenceType($type)) { | |
| 2236 if ($parameter->isNullable) { | |
| 2237 push(@andExpression, "${value}->IsNull() || ${value}->IsArray()"
); | |
| 2238 } else { | |
| 2239 push(@andExpression, "${value}->IsArray()"); | |
| 2240 } | |
| 2241 } elsif (IsWrapperType($type)) { | |
| 2242 if ($parameter->isNullable) { | |
| 2243 push(@andExpression, "${value}->IsNull() || V8${type}::hasInstan
ce($value, info.GetIsolate())"); | |
| 2244 } else { | |
| 2245 push(@andExpression, "V8${type}::hasInstance($value, info.GetIso
late())"); | |
| 2246 } | |
| 2247 } elsif ($nonWrapperTypes{$type}) { | |
| 2248 # Non-wrapper types are just objects: we don't distinguish type | |
| 2249 if ($undefinedOrNullCheck) { | |
| 2250 push(@andExpression, "$undefinedOrNullCheck || ${value}->IsObjec
t()"); | |
| 2251 } else { | |
| 2252 push(@andExpression, "${value}->IsObject()"); | |
| 2253 } | |
| 2254 } | |
| 2255 | |
| 2256 $parameterIndex++; | |
| 2257 } | |
| 2258 @andExpression = map { "($_)" } @andExpression; | |
| 2259 my $res = "(" . join(" && ", @andExpression) . ")"; | |
| 2260 return $res; | |
| 2261 } | |
| 2262 | |
| 2263 # As per Web IDL specification, the length of a function Object is | |
| 2264 # its number of mandatory parameters. | |
| 2265 sub GetFunctionLength | |
| 2266 { | |
| 2267 my $function = shift; | |
| 2268 | |
| 2269 my $numMandatoryParams = 0; | |
| 2270 foreach my $parameter (@{$function->parameters}) { | |
| 2271 # Abort as soon as we find the first optional parameter as no mandatory | |
| 2272 # parameter can follow an optional one. | |
| 2273 last if $parameter->isOptional; | |
| 2274 $numMandatoryParams++; | |
| 2275 } | |
| 2276 return $numMandatoryParams; | |
| 2277 } | |
| 2278 | |
| 2279 sub GenerateFunctionParametersCheck | |
| 2280 { | |
| 2281 my $function = shift; | |
| 2282 | |
| 2283 my @orExpression = (); | |
| 2284 my $numParameters = 0; | |
| 2285 my $hasVariadic = 0; | |
| 2286 my $numMandatoryParams = @{$function->parameters}; | |
| 2287 foreach my $parameter (@{$function->parameters}) { | |
| 2288 if ($parameter->isOptional) { | |
| 2289 push(@orExpression, GenerateParametersCheckExpression($numParameters
, $function)); | |
| 2290 $numMandatoryParams--; | |
| 2291 } | |
| 2292 if ($parameter->isVariadic) { | |
| 2293 $hasVariadic = 1; | |
| 2294 last; | |
| 2295 } | |
| 2296 $numParameters++; | |
| 2297 } | |
| 2298 if (!$hasVariadic) { | |
| 2299 push(@orExpression, GenerateParametersCheckExpression($numParameters, $f
unction)); | |
| 2300 } | |
| 2301 return ($numMandatoryParams, join(" || ", @orExpression)); | |
| 2302 } | |
| 2303 | |
| 2304 sub GenerateOverloadedFunction | |
| 2305 { | |
| 2306 my $function = shift; | |
| 2307 my $interface = shift; | |
| 2308 my $forMainWorldSuffix = shift; | |
| 2309 | |
| 2310 # Generate code for choosing the correct overload to call. Overloads are | |
| 2311 # chosen based on the total number of arguments passed and the type of | |
| 2312 # values passed in non-primitive argument slots. When more than a single | |
| 2313 # overload is applicable, precedence is given according to the order of | |
| 2314 # declaration in the IDL. | |
| 2315 | |
| 2316 my $name = $function->name; | |
| 2317 my $interfaceName = $interface->name; | |
| 2318 my $implClassName = GetImplName($interface); | |
| 2319 | |
| 2320 my $conditionalString = GenerateConditionalString($function); | |
| 2321 my $leastNumMandatoryParams = 255; | |
| 2322 | |
| 2323 my $code = ""; | |
| 2324 $code .= "#if ${conditionalString}\n\n" if $conditionalString; | |
| 2325 $code .= <<END; | |
| 2326 static void ${name}Method${forMainWorldSuffix}(const v8::FunctionCallbackInfo<v8
::Value>& info) | |
| 2327 { | |
| 2328 END | |
| 2329 foreach my $overload (@{$function->{overloads}}) { | |
| 2330 my ($numMandatoryParams, $parametersCheck) = GenerateFunctionParametersC
heck($overload); | |
| 2331 $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams <
$leastNumMandatoryParams); | |
| 2332 $code .= " if ($parametersCheck) {\n"; | |
| 2333 my $overloadedIndexString = $overload->{overloadIndex}; | |
| 2334 $code .= " ${name}${overloadedIndexString}Method${forMainWorldSuf
fix}(info);\n"; | |
| 2335 $code .= " return;\n"; | |
| 2336 $code .= " }\n"; | |
| 2337 } | |
| 2338 if ($leastNumMandatoryParams >= 1) { | |
| 2339 $code .= " ExceptionState exceptionState(ExceptionState::ExecutionCon
text, \"${name}\", \"${interfaceName}\", info.Holder(), info.GetIsolate());\n"; | |
| 2340 $code .= " if (UNLIKELY(info.Length() < $leastNumMandatoryParams)) {\
n"; | |
| 2341 $code .= " exceptionState.throwTypeError(ExceptionMessages::notEn
oughArguments($leastNumMandatoryParams, info.Length()));\n"; | |
| 2342 $code .= " exceptionState.throwIfNeeded();\n"; | |
| 2343 $code .= " return;\n"; | |
| 2344 $code .= " }\n"; | |
| 2345 $code .= <<END; | |
| 2346 exceptionState.throwTypeError(\"No function was found that matched the signa
ture provided.\"); | |
| 2347 exceptionState.throwIfNeeded(); | |
| 2348 END | |
| 2349 } else { | |
| 2350 $code .=<<END; | |
| 2351 throwTypeError(ExceptionMessages::failedToExecute(\"${name}\", \"${interface
Name}\", \"No function was found that matched the signature provided.\"), info.G
etIsolate()); | |
| 2352 END | |
| 2353 } | |
| 2354 $code .= "}\n\n"; | |
| 2355 $code .= "#endif // ${conditionalString}\n\n" if $conditionalString; | |
| 2356 $implementation{nameSpaceInternal}->add($code); | |
| 2357 } | |
| 2358 | |
| 2359 sub GenerateFunctionCallback | |
| 2360 { | |
| 2361 my $function = shift; | |
| 2362 my $interface = shift; | |
| 2363 my $forMainWorldSuffix = shift; | |
| 2364 | |
| 2365 my $implClassName = GetImplName($interface); | |
| 2366 my $v8ClassName = GetV8ClassName($interface); | |
| 2367 my $name = $function->name; | |
| 2368 | |
| 2369 if ($name eq "") { | |
| 2370 return; | |
| 2371 } | |
| 2372 | |
| 2373 my $conditionalString = GenerateConditionalString($function); | |
| 2374 my $code = ""; | |
| 2375 $code .= "#if ${conditionalString}\n" if $conditionalString; | |
| 2376 $code .= <<END; | |
| 2377 static void ${name}MethodCallback${forMainWorldSuffix}(const v8::FunctionCallbac
kInfo<v8::Value>& info) | |
| 2378 { | |
| 2379 END | |
| 2380 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMMethod\");\n"; | |
| 2381 $code .= GenerateFeatureObservation($function->extendedAttributes->{"Measure
As"}); | |
| 2382 $code .= GenerateDeprecationNotification($function->extendedAttributes->{"De
precateAs"}); | |
| 2383 if (HasActivityLogging($forMainWorldSuffix, $function->extendedAttributes, "
Access")) { | |
| 2384 $code .= GenerateActivityLogging("Method", $interface, "${name}"); | |
| 2385 } | |
| 2386 if (HasCustomMethod($function->extendedAttributes)) { | |
| 2387 $code .= " ${v8ClassName}::${name}MethodCustom(info);\n"; | |
| 2388 } else { | |
| 2389 $code .= " ${implClassName}V8Internal::${name}Method${forMainWorldSuf
fix}(info);\n"; | |
| 2390 } | |
| 2391 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n"; | |
| 2392 $code .= "}\n"; | |
| 2393 $code .= "#endif // ${conditionalString}\n" if $conditionalString; | |
| 2394 $code .= "\n"; | |
| 2395 $implementation{nameSpaceInternal}->add($code); | |
| 2396 } | |
| 2397 | |
| 2398 sub GenerateFunction | |
| 2399 { | |
| 2400 my $function = shift; | |
| 2401 my $interface = shift; | |
| 2402 my $forMainWorldSuffix = shift; | |
| 2403 | |
| 2404 my $interfaceName = $interface->name; | |
| 2405 my $implClassName = GetImplName($interface); | |
| 2406 my $v8ClassName = GetV8ClassName($interface); | |
| 2407 my $name = $function->name; | |
| 2408 my $unoverloadedName = $function->name; | |
| 2409 my $implName = GetImplName($function); | |
| 2410 my $funcExt = $function->extendedAttributes; | |
| 2411 | |
| 2412 # Add includes for types even if custom | |
| 2413 my $returnType = $function->type; | |
| 2414 AddIncludesForType($returnType); | |
| 2415 foreach my $parameter (@{$function->parameters}) { | |
| 2416 my $paramType = $parameter->type; | |
| 2417 AddIncludesForType($paramType); | |
| 2418 } | |
| 2419 | |
| 2420 if (HasCustomMethod($funcExt) || $name eq "") { | |
| 2421 return; | |
| 2422 } | |
| 2423 | |
| 2424 if (@{$function->{overloads}} > 1) { | |
| 2425 # Append a number to an overloaded method's name to make it unique: | |
| 2426 $name = $name . $function->{overloadIndex}; | |
| 2427 } | |
| 2428 | |
| 2429 my $conditionalString = GenerateConditionalString($function); | |
| 2430 my $code = ""; | |
| 2431 $code .= "#if ${conditionalString}\n" if $conditionalString; | |
| 2432 $code .= "static void ${name}Method${forMainWorldSuffix}(const v8::FunctionC
allbackInfo<v8::Value>& info)\n"; | |
| 2433 $code .= "{\n"; | |
| 2434 | |
| 2435 # We throw exceptions using 'ExceptionState' for a function if: | |
| 2436 # - it explicitly claims that exceptions may be raised (or should be if ty
pe checks fail.) | |
| 2437 # - event listeners. | |
| 2438 # - security-checking. | |
| 2439 # - weird SVG stuff. | |
| 2440 # - takes a parameter that might raise an exception on conversion. | |
| 2441 # | |
| 2442 my $isEventListener = $name eq "addEventListener" || $name eq "removeEventLi
stener"; | |
| 2443 my $isEventDispatcher = $name eq "dispatchEvent"; | |
| 2444 my $isSecurityCheckNecessary = $interface->extendedAttributes->{"CheckSecuri
ty"} && !$function->extendedAttributes->{"DoNotCheckSecurity"}; | |
| 2445 my $raisesExceptions = $function->extendedAttributes->{"RaisesException"}; | |
| 2446 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGProperty
Types($interfaceName); | |
| 2447 my $isNonListSVGType = $svgNativeType && !($interfaceName =~ /List$/); | |
| 2448 | |
| 2449 my $hasExceptionState = $raisesExceptions || $isEventListener || $isSecurity
CheckNecessary || $isNonListSVGType || HasExceptionRaisingParameter($function); | |
| 2450 if ($hasExceptionState) { | |
| 2451 $code .= " ExceptionState exceptionState(ExceptionState::ExecutionCon
text, \"${unoverloadedName}\", \"${interfaceName}\", info.Holder(), info.GetIsol
ate());\n"; | |
| 2452 } | |
| 2453 | |
| 2454 if ($isEventListener || $isEventDispatcher) { | |
| 2455 AddToImplIncludes("bindings/v8/BindingSecurity.h"); | |
| 2456 AddToImplIncludes("bindings/v8/V8EventListenerList.h"); | |
| 2457 AddToImplIncludes("core/frame/DOMWindow.h"); | |
| 2458 $code .= <<END; | |
| 2459 EventTarget* impl = ${v8ClassName}::toNative(info.Holder()); | |
| 2460 if (DOMWindow* window = impl->toDOMWindow()) { | |
| 2461 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), window
->frame(), exceptionState)) { | |
| 2462 exceptionState.throwIfNeeded(); | |
| 2463 return; | |
| 2464 } | |
| 2465 if (!window->document()) | |
| 2466 return; | |
| 2467 } | |
| 2468 END | |
| 2469 } | |
| 2470 if ($isEventListener) { | |
| 2471 my $lookupType = ($name eq "addEventListener") ? "OrCreate" : "Only"; | |
| 2472 my $passRefPtrHandling = ($name eq "addEventListener") ? "" : ".get()"; | |
| 2473 my $hiddenValueAction = ($name eq "addEventListener") ? "addHiddenValueT
oArray" : "removeHiddenValueFromArray"; | |
| 2474 | |
| 2475 $code .= <<END; | |
| 2476 RefPtr<EventListener> listener = V8EventListenerList::getEventListener(info[
1], false, ListenerFind${lookupType}); | |
| 2477 if (listener) { | |
| 2478 V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, ev
entName, info[0]); | |
| 2479 impl->${implName}(eventName, listener${passRefPtrHandling}, info[2]->Boo
leanValue()); | |
| 2480 if (!impl->toNode()) | |
| 2481 ${hiddenValueAction}(info.Holder(), info[1], ${v8ClassName}::eventLi
stenerCacheIndex, info.GetIsolate()); | |
| 2482 } | |
| 2483 } | |
| 2484 END | |
| 2485 $code .= "#endif // ${conditionalString}\n" if $conditionalString; | |
| 2486 $code .= "\n"; | |
| 2487 $implementation{nameSpaceInternal}->add($code); | |
| 2488 return; | |
| 2489 } | |
| 2490 | |
| 2491 $code .= GenerateArgumentsCountCheck($function, $interface, $hasExceptionSta
te); | |
| 2492 | |
| 2493 if ($svgNativeType) { | |
| 2494 my $nativeClassName = GetNativeType($interfaceName); | |
| 2495 if ($interfaceName =~ /List$/) { | |
| 2496 $code .= " $nativeClassName imp = ${v8ClassName}::toNative(info.H
older());\n"; | |
| 2497 } else { | |
| 2498 AddToImplIncludes("core/dom/ExceptionCode.h"); | |
| 2499 $code .= " $nativeClassName wrapper = ${v8ClassName}::toNative(in
fo.Holder());\n"; | |
| 2500 $code .= " if (wrapper->isReadOnly()) {\n"; | |
| 2501 $code .= " exceptionState.throwDOMException(NoModificationAll
owedError, \"The object is read-only.\");\n"; | |
| 2502 $code .= " exceptionState.throwIfNeeded();\n"; | |
| 2503 $code .= " return;\n"; | |
| 2504 $code .= " }\n"; | |
| 2505 my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($interfac
eName); | |
| 2506 $code .= " $svgWrappedNativeType& impInstance = wrapper->property
Reference();\n"; | |
| 2507 $code .= " $svgWrappedNativeType* imp = &impInstance;\n"; | |
| 2508 } | |
| 2509 } elsif (!$function->isStatic) { | |
| 2510 $code .= <<END; | |
| 2511 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()); | |
| 2512 END | |
| 2513 } | |
| 2514 | |
| 2515 $code .= GenerateCustomElementInvocationScopeIfNeeded($funcExt); | |
| 2516 | |
| 2517 # Check domain security if needed | |
| 2518 if ($isSecurityCheckNecessary) { | |
| 2519 # We have not find real use cases yet. | |
| 2520 AddToImplIncludes("bindings/v8/BindingSecurity.h"); | |
| 2521 $code .= <<END; | |
| 2522 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), imp->frame
(), exceptionState)) { | |
| 2523 exceptionState.throwIfNeeded(); | |
| 2524 return; | |
| 2525 } | |
| 2526 END | |
| 2527 } | |
| 2528 | |
| 2529 if ($function->extendedAttributes->{"CheckSecurity"}) { | |
| 2530 AddToImplIncludes("bindings/v8/BindingSecurity.h"); | |
| 2531 $code .= " if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsol
ate(), imp->" . GetImplName($function) . "(exceptionState), exceptionState)) {\n
"; | |
| 2532 $code .= " v8SetReturnValueNull(info);\n"; | |
| 2533 $code .= " exceptionState.throwIfNeeded();\n"; | |
| 2534 $code .= " return;\n"; | |
| 2535 $code .= " }\n"; | |
| 2536 END | |
| 2537 } | |
| 2538 | |
| 2539 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersC
heck($function, $interface, $forMainWorldSuffix, $hasExceptionState); | |
| 2540 $code .= $parameterCheckString; | |
| 2541 | |
| 2542 # Build the function call string. | |
| 2543 $code .= GenerateFunctionCallString($function, $paramIndex, " ", $interfa
ce, $forMainWorldSuffix, $hasExceptionState, %replacements); | |
| 2544 $code .= "}\n"; | |
| 2545 $code .= "#endif // ${conditionalString}\n" if $conditionalString; | |
| 2546 $code .= "\n"; | |
| 2547 $implementation{nameSpaceInternal}->add($code); | |
| 2548 } | |
| 2549 | |
| 2550 sub GenerateCallWith | |
| 2551 { | |
| 2552 my $callWith = shift; | |
| 2553 return ([], "") unless $callWith; | |
| 2554 my $indent = shift; | |
| 2555 my $returnVoid = shift; | |
| 2556 my $function = shift; | |
| 2557 my $code = ""; | |
| 2558 | |
| 2559 my @callWithArgs; | |
| 2560 if (ExtendedAttributeContains($callWith, "ScriptState")) { | |
| 2561 $code .= $indent . "ScriptState* currentState = ScriptState::current();\
n"; | |
| 2562 $code .= $indent . "if (!currentState)\n"; | |
| 2563 $code .= $indent . " return" . ($returnVoid ? "" : " v8Undefined()")
. ";\n"; | |
| 2564 $code .= $indent . "ScriptState& state = *currentState;\n"; | |
| 2565 push(@callWithArgs, "&state"); | |
| 2566 AddToImplIncludes("bindings/v8/ScriptState.h"); | |
| 2567 } | |
| 2568 if (ExtendedAttributeContains($callWith, "ExecutionContext")) { | |
| 2569 $code .= $indent . "ExecutionContext* scriptContext = currentExecutionCo
ntext(info.GetIsolate());\n"; | |
| 2570 push(@callWithArgs, "scriptContext"); | |
| 2571 } | |
| 2572 if ($function and ExtendedAttributeContains($callWith, "ScriptArguments")) { | |
| 2573 $code .= $indent . "RefPtr<ScriptArguments> scriptArguments(createScript
Arguments(info, " . @{$function->parameters} . "));\n"; | |
| 2574 push(@callWithArgs, "scriptArguments.release()"); | |
| 2575 AddToImplIncludes("bindings/v8/ScriptCallStackFactory.h"); | |
| 2576 AddToImplIncludes("core/inspector/ScriptArguments.h"); | |
| 2577 } | |
| 2578 if (ExtendedAttributeContains($callWith, "ActiveWindow")) { | |
| 2579 push(@callWithArgs, "callingDOMWindow(info.GetIsolate())"); | |
| 2580 } | |
| 2581 if (ExtendedAttributeContains($callWith, "FirstWindow")) { | |
| 2582 push(@callWithArgs, "enteredDOMWindow(info.GetIsolate())"); | |
| 2583 } | |
| 2584 return ([@callWithArgs], $code); | |
| 2585 } | |
| 2586 | |
| 2587 sub GenerateArgumentsCountCheck | |
| 2588 { | |
| 2589 my $function = shift; | |
| 2590 my $interface = shift; | |
| 2591 my $hasExceptionState = shift; | |
| 2592 | |
| 2593 my $functionName = $function->name; | |
| 2594 my $interfaceName = $interface->name; | |
| 2595 my $implClassName = GetImplName($interface); | |
| 2596 | |
| 2597 my $isConstructor = $functionName eq "Constructor" || $functionName eq "Name
dConstructor"; | |
| 2598 my $numMandatoryParams = 0; | |
| 2599 my $allowNonOptional = 1; | |
| 2600 foreach my $param (@{$function->parameters}) { | |
| 2601 if ($param->isOptional or $param->isVariadic) { | |
| 2602 $allowNonOptional = 0; | |
| 2603 } else { | |
| 2604 die "An argument must not be declared to be optional unless all subs
equent arguments to the operation are also optional." if !$allowNonOptional; | |
| 2605 $numMandatoryParams++; | |
| 2606 } | |
| 2607 } | |
| 2608 return "" unless $numMandatoryParams; | |
| 2609 | |
| 2610 my $argumentsCountCheckString = ""; | |
| 2611 $argumentsCountCheckString .= " if (UNLIKELY(info.Length() < $numMandator
yParams)) {\n"; | |
| 2612 if ($hasExceptionState) { | |
| 2613 $argumentsCountCheckString .= " exceptionState.throwTypeError(Exc
eptionMessages::notEnoughArguments($numMandatoryParams, info.Length()));\n"; | |
| 2614 $argumentsCountCheckString .= " exceptionState.throwIfNeeded();\n
"; | |
| 2615 } elsif ($isConstructor) { | |
| 2616 $argumentsCountCheckString .= " throwTypeError(ExceptionMessages:
:failedToConstruct(\"$interfaceName\", ExceptionMessages::notEnoughArguments($nu
mMandatoryParams, info.Length())), info.GetIsolate());\n"; | |
| 2617 } else { | |
| 2618 $argumentsCountCheckString .= " throwTypeError(ExceptionMessages:
:failedToExecute(\"$functionName\", \"$interfaceName\", ExceptionMessages::notEn
oughArguments($numMandatoryParams, info.Length())), info.GetIsolate());\n"; | |
| 2619 } | |
| 2620 $argumentsCountCheckString .= " return;\n"; | |
| 2621 $argumentsCountCheckString .= " }\n"; | |
| 2622 return $argumentsCountCheckString; | |
| 2623 } | |
| 2624 | |
| 2625 sub GenerateParametersCheck | |
| 2626 { | |
| 2627 my $function = shift; | |
| 2628 my $interface = shift; | |
| 2629 my $forMainWorldSuffix = shift; | |
| 2630 my $hasExceptionState = shift; | |
| 2631 my $style = shift || "new"; | |
| 2632 | |
| 2633 my $functionName = $function->name; | |
| 2634 my $interfaceName = $interface->name; | |
| 2635 my $implClassName = GetImplName($interface); | |
| 2636 | |
| 2637 my $parameterCheckString = ""; | |
| 2638 my $paramIndex = 0; | |
| 2639 my %replacements = (); | |
| 2640 | |
| 2641 foreach my $parameter (@{$function->parameters}) { | |
| 2642 my $humanFriendlyIndex = $paramIndex + 1; | |
| 2643 my $nativeType = GetNativeType($parameter->type, $parameter->extendedAtt
ributes, "parameter"); | |
| 2644 | |
| 2645 # Optional arguments without [Default=...] should generate an early call
with fewer arguments. | |
| 2646 # Optional Dictionary arguments always considered to have default of emp
ty dictionary. | |
| 2647 if ($parameter->isOptional && !$parameter->extendedAttributes->{"Default
"} && $nativeType ne "Dictionary" && !IsCallbackInterface($parameter->type)) { | |
| 2648 $parameterCheckString .= <<END; | |
| 2649 if (UNLIKELY(info.Length() <= $paramIndex)) { | |
| 2650 END | |
| 2651 $parameterCheckString .= GenerateFunctionCallString($function, $para
mIndex, " " x 2, $interface, $forMainWorldSuffix, $hasExceptionState, %replac
ements); | |
| 2652 $parameterCheckString .= <<END; | |
| 2653 return; | |
| 2654 } | |
| 2655 END | |
| 2656 } | |
| 2657 | |
| 2658 my $parameterName = $parameter->name; | |
| 2659 if (IsCallbackInterface($parameter->type)) { | |
| 2660 my $v8ClassName = "V8" . $parameter->type; | |
| 2661 AddToImplIncludes("$v8ClassName.h"); | |
| 2662 if ($parameter->isOptional) { | |
| 2663 $parameterCheckString .= " OwnPtr<" . $parameter->type . "> $
parameterName;\n"; | |
| 2664 $parameterCheckString .= " if (info.Length() > $paramIndex &&
!isUndefinedOrNull(info[$paramIndex])) {\n"; | |
| 2665 $parameterCheckString .= " if (!info[$paramIndex]->IsFunc
tion()) {\n"; | |
| 2666 if ($hasExceptionState) { | |
| 2667 $parameterCheckString .= " exceptionState.throwTy
peError(\"The callback provided as parameter $humanFriendlyIndex is not a functi
on.\");\n"; | |
| 2668 $parameterCheckString .= " exceptionState.throwIf
Needed();\n"; | |
| 2669 } else { | |
| 2670 $parameterCheckString .= " throwTypeError(Excepti
onMessages::failedToExecute(\"$functionName\", \"$interfaceName\", \"The callbac
k provided as parameter $humanFriendlyIndex is not a function.\"), info.GetIsola
te());\n"; | |
| 2671 } | |
| 2672 $parameterCheckString .= " return;\n"; | |
| 2673 $parameterCheckString .= " }\n"; | |
| 2674 $parameterCheckString .= " $parameterName = ${v8ClassName
}::create(v8::Handle<v8::Function>::Cast(info[$paramIndex]), currentExecutionCon
text(info.GetIsolate()));\n"; | |
| 2675 $parameterCheckString .= " }\n"; | |
| 2676 } else { | |
| 2677 $parameterCheckString .= " if (info.Length() <= $paramIndex |
| "; | |
| 2678 if ($parameter->isNullable) { | |
| 2679 $parameterCheckString .= "!(info[$paramIndex]->IsFunction()
|| info[$paramIndex]->IsNull())"; | |
| 2680 } else { | |
| 2681 $parameterCheckString .= "!info[$paramIndex]->IsFunction()"; | |
| 2682 } | |
| 2683 $parameterCheckString .= ") {\n"; | |
| 2684 if ($hasExceptionState) { | |
| 2685 $parameterCheckString .= " exceptionState.throwTypeEr
ror(\"The callback provided as parameter $humanFriendlyIndex is not a function.\
");\n"; | |
| 2686 $parameterCheckString .= " exceptionState.throwIfNeed
ed();\n"; | |
| 2687 } else { | |
| 2688 $parameterCheckString .= " throwTypeError(ExceptionMe
ssages::failedToExecute(\"$functionName\", \"$interfaceName\", \"The callback pr
ovided as parameter $humanFriendlyIndex is not a function.\"), info.GetIsolate()
);\n"; | |
| 2689 } | |
| 2690 $parameterCheckString .= " return;\n"; | |
| 2691 $parameterCheckString .= " }\n"; | |
| 2692 $parameterCheckString .= " OwnPtr<" . $parameter->type . "> $
parameterName = "; | |
| 2693 $parameterCheckString .= "info[$paramIndex]->IsNull() ? nullptr
: " if $parameter->isNullable; | |
| 2694 $parameterCheckString .= "${v8ClassName}::create(v8::Handle<v8::
Function>::Cast(info[$paramIndex]), currentExecutionContext(info.GetIsolate()));
\n"; | |
| 2695 } | |
| 2696 } elsif ($parameter->extendedAttributes->{"Clamp"}) { | |
| 2697 my $nativeValue = "${parameterName}NativeValue"; | |
| 2698 my $idlType = $parameter->type; | |
| 2699 $parameterCheckString .= " $nativeType $parameterName = 0;\n"
; | |
| 2700 $parameterCheckString .= " V8TRYCATCH_VOID(double, $nativeVal
ue, info[$paramIndex]->NumberValue());\n"; | |
| 2701 $parameterCheckString .= " if (!std::isnan($nativeValue))\n"; | |
| 2702 $parameterCheckString .= " $parameterName = clampTo<$idlT
ype>($nativeValue);\n"; | |
| 2703 } elsif ($parameter->type eq "SerializedScriptValue") { | |
| 2704 AddToImplIncludes("bindings/v8/SerializedScriptValue.h"); | |
| 2705 $parameterCheckString .= " $nativeType $parameterName = Serialize
dScriptValue::create(info[$paramIndex], 0, 0, exceptionState, info.GetIsolate())
;\n"; | |
| 2706 $parameterCheckString .= " if (exceptionState.throwIfNeeded())\n"
; | |
| 2707 $parameterCheckString .= " return;\n"; | |
| 2708 } elsif ($parameter->isVariadic) { | |
| 2709 my $nativeElementType = GetNativeType($parameter->type); | |
| 2710 if ($nativeElementType =~ />$/) { | |
| 2711 $nativeElementType .= " "; | |
| 2712 } | |
| 2713 | |
| 2714 my $argType = $parameter->type; | |
| 2715 if (IsWrapperType($argType)) { | |
| 2716 $parameterCheckString .= " Vector<$nativeElementType> $parame
terName;\n"; | |
| 2717 $parameterCheckString .= " for (int i = $paramIndex; i < info
.Length(); ++i) {\n"; | |
| 2718 $parameterCheckString .= " if (!V8${argType}::hasInstance
(info[i], info.GetIsolate())) {\n"; | |
| 2719 if ($hasExceptionState) { | |
| 2720 $parameterCheckString .= " exceptionState.throwTy
peError(\"parameter $humanFriendlyIndex is not of type \'$argType\'.\");\n"; | |
| 2721 $parameterCheckString .= " exceptionState.throwIf
Needed();\n"; | |
| 2722 } else { | |
| 2723 $parameterCheckString .= " throwTypeError(Excepti
onMessages::failedToExecute(\"$functionName\", \"$interfaceName\", \"parameter $
humanFriendlyIndex is not of type \'$argType\'.\"), info.GetIsolate());\n"; | |
| 2724 } | |
| 2725 $parameterCheckString .= " return;\n"; | |
| 2726 $parameterCheckString .= " }\n"; | |
| 2727 $parameterCheckString .= " $parameterName.append(V8${argT
ype}::toNative(v8::Handle<v8::Object>::Cast(info[i])));\n"; | |
| 2728 $parameterCheckString .= " }\n"; | |
| 2729 } else { | |
| 2730 $parameterCheckString .= " V8TRYCATCH_VOID(Vector<$nativeElem
entType>, $parameterName, toNativeArguments<$nativeElementType>(info, $paramInde
x));\n"; | |
| 2731 } | |
| 2732 } elsif ($nativeType =~ /^V8StringResource/) { | |
| 2733 my $default = defined $parameter->extendedAttributes->{"Default"} ?
$parameter->extendedAttributes->{"Default"} : ""; | |
| 2734 my $jsValue = $parameter->isOptional && $default eq "NullString" ? "
argumentOrNull(info, $paramIndex)" : "info[$paramIndex]"; | |
| 2735 my $stringResourceParameterName = $parameterName; | |
| 2736 my $isNullable = IsNullableParameter($parameter); | |
| 2737 if ($isNullable) { | |
| 2738 $parameterCheckString .= " bool ${parameterName}IsNull = $jsV
alue->IsNull();\n"; | |
| 2739 $stringResourceParameterName .= "StringResource"; | |
| 2740 } | |
| 2741 $parameterCheckString .= JSValueToNativeStatement($parameter->type,
$parameter->extendedAttributes, $humanFriendlyIndex, $jsValue, $stringResourcePa
rameterName, " ", "info.GetIsolate()"); | |
| 2742 $parameterCheckString .= " String $parameterName = $stringResourc
eParameterName;\n" if $isNullable; | |
| 2743 if (IsEnumType($parameter->type)) { | |
| 2744 my @enumValues = ValidEnumValues($parameter->type); | |
| 2745 my @validEqualities = (); | |
| 2746 foreach my $enumValue (@enumValues) { | |
| 2747 push(@validEqualities, "string == \"$enumValue\""); | |
| 2748 } | |
| 2749 my $enumValidationExpression = join(" || ", @validEqualities); | |
| 2750 $parameterCheckString .= " String string = $parameterName;\n
"; | |
| 2751 $parameterCheckString .= " if (!($enumValidationExpression))
{\n"; | |
| 2752 if ($hasExceptionState) { | |
| 2753 $parameterCheckString .= " exceptionState.throwTypeEr
ror(\"parameter $humanFriendlyIndex (\'\" + string + \"\') is not a valid enum v
alue.\");\n"; | |
| 2754 $parameterCheckString .= " exceptionState.throwIfNeed
ed();\n"; | |
| 2755 } else { | |
| 2756 $parameterCheckString .= " throwTypeError(ExceptionMe
ssages::failedToExecute(\"$functionName\", \"$interfaceName\", \"parameter $huma
nFriendlyIndex (\'\" + string + \"\') is not a valid enum value.\"), info.GetIso
late());\n"; | |
| 2757 } | |
| 2758 $parameterCheckString .= " return;\n"; | |
| 2759 $parameterCheckString .= " }\n"; | |
| 2760 } | |
| 2761 } else { | |
| 2762 # If the [StrictTypeChecking] extended attribute is present, type | |
| 2763 # check interface type arguments for correct type and nullability. | |
| 2764 # | |
| 2765 # If the argument is passed, and is not |undefined| or |null|, then | |
| 2766 # it must implement the interface type, otherwise throw a TypeError | |
| 2767 # If the parameter is nullable, then both |undefined| and |null| | |
| 2768 # pass a NULL pointer to the C++ code, otherwise these also throw. | |
| 2769 # Without [StrictTypeChecking], in all these cases NULL is silently | |
| 2770 # passed to the C++ code. | |
| 2771 # | |
| 2772 # Per the Web IDL and ECMAScript specifications, incoming values | |
| 2773 # can always be converted to primitive types and strings (including | |
| 2774 # |undefined| and |null|), so do not throw TypeError for these. | |
| 2775 if ($function->extendedAttributes->{"StrictTypeChecking"} || $interf
ace->extendedAttributes->{"StrictTypeChecking"}) { | |
| 2776 my $argValue = "info[$paramIndex]"; | |
| 2777 my $argType = $parameter->type; | |
| 2778 if (IsWrapperType($argType)) { | |
| 2779 my $undefinedNullCheck = $parameter->isNullable ? " !isUndef
inedOrNull($argValue) &&" : ""; | |
| 2780 $parameterCheckString .= " if (info.Length() > $paramInde
x &&$undefinedNullCheck !V8${argType}::hasInstance($argValue, info.GetIsolate())
) {\n"; | |
| 2781 if ($hasExceptionState) { | |
| 2782 $parameterCheckString .= " exceptionState.throwTy
peError(\"parameter $humanFriendlyIndex is not of type \'$argType\'.\");\n"; | |
| 2783 $parameterCheckString .= " exceptionState.throwIf
Needed();\n"; | |
| 2784 }else { | |
| 2785 $parameterCheckString .= " throwTypeError(Excepti
onMessages::failedToExecute(\"$functionName\", \"$interfaceName\", \"parameter $
humanFriendlyIndex is not of type \'$argType\'.\"), info.GetIsolate());\n"; | |
| 2786 } | |
| 2787 $parameterCheckString .= " return;\n"; | |
| 2788 $parameterCheckString .= " }\n"; | |
| 2789 } | |
| 2790 } | |
| 2791 my $default = defined $parameter->extendedAttributes->{"Default"} ?
$parameter->extendedAttributes->{"Default"} : ""; | |
| 2792 my $jsValue = $parameter->isOptional && $default eq "NullString" ? "
argumentOrNull(info, $paramIndex)" : "info[$paramIndex]"; | |
| 2793 my $isNullable = IsNullableParameter($parameter); | |
| 2794 $parameterCheckString .= " bool ${parameterName}IsNull = $jsValue
->IsNull();\n" if $isNullable; | |
| 2795 $parameterCheckString .= JSValueToNativeStatement($parameter->type,
$parameter->extendedAttributes, $humanFriendlyIndex, $jsValue, $parameterName, "
", "info.GetIsolate()"); | |
| 2796 if ($nativeType eq 'Dictionary' or $nativeType eq 'ScriptPromise') { | |
| 2797 $parameterCheckString .= " if (!$parameterName.isUndefinedOrN
ull() && !$parameterName.isObject()) {\n"; | |
| 2798 if ($hasExceptionState) { | |
| 2799 $parameterCheckString .= " exceptionState.throwTypeEr
ror(\"parameter ${humanFriendlyIndex} ('${parameterName}') is not an object.\");
\n"; | |
| 2800 $parameterCheckString .= " exceptionState.throwIfNeed
ed();\n"; | |
| 2801 } elsif ($functionName eq "Constructor") { | |
| 2802 $parameterCheckString .= " throwTypeError(ExceptionMe
ssages::failedToConstruct(\"$interfaceName\", \"parameter ${humanFriendlyIndex}
('${parameterName}') is not an object.\"), info.GetIsolate());\n"; | |
| 2803 } else { | |
| 2804 $parameterCheckString .= " throwTypeError(ExceptionMe
ssages::failedToExecute(\"$functionName\", \"$interfaceName\", \"parameter ${hum
anFriendlyIndex} ('${parameterName}') is not an object.\"), info.GetIsolate());\
n"; | |
| 2805 } | |
| 2806 $parameterCheckString .= " return;\n"; | |
| 2807 $parameterCheckString .= " }\n"; | |
| 2808 } | |
| 2809 } | |
| 2810 | |
| 2811 $paramIndex++; | |
| 2812 } | |
| 2813 return ($parameterCheckString, $paramIndex, %replacements); | |
| 2814 } | |
| 2815 | |
| 2816 sub GenerateOverloadedConstructorCallback | |
| 2817 { | |
| 2818 my $interface = shift; | |
| 2819 my $interfaceName = $interface->name; | |
| 2820 my $implClassName = GetImplName($interface); | |
| 2821 | |
| 2822 my $code .= <<END; | |
| 2823 static void constructor(const v8::FunctionCallbackInfo<v8::Value>& info) | |
| 2824 { | |
| 2825 END | |
| 2826 my $leastNumMandatoryParams = 255; | |
| 2827 foreach my $constructor (@{$interface->constructors}) { | |
| 2828 my $name = "constructor" . $constructor->overloadedIndex; | |
| 2829 my ($numMandatoryParams, $parametersCheck) = GenerateFunctionParametersC
heck($constructor); | |
| 2830 $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams <
$leastNumMandatoryParams); | |
| 2831 $code .= " if ($parametersCheck) {\n"; | |
| 2832 $code .= " ${implClassName}V8Internal::${name}(info);\n"; | |
| 2833 $code .= " return;\n"; | |
| 2834 $code .= " }\n"; | |
| 2835 } | |
| 2836 if ($leastNumMandatoryParams >= 1) { | |
| 2837 $code .= <<END; | |
| 2838 ExceptionState exceptionState(ExceptionState::ConstructionContext, \"${inter
faceName}\", info.Holder(), info.GetIsolate()); | |
| 2839 if (UNLIKELY(info.Length() < $leastNumMandatoryParams)) { | |
| 2840 exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments($lea
stNumMandatoryParams, info.Length())); | |
| 2841 exceptionState.throwIfNeeded(); | |
| 2842 return; | |
| 2843 } | |
| 2844 exceptionState.throwTypeError(\"No matching constructor signature.\"); | |
| 2845 exceptionState.throwIfNeeded(); | |
| 2846 END | |
| 2847 } else { | |
| 2848 $code .= <<END; | |
| 2849 throwTypeError(ExceptionMessages::failedToConstruct(\"${interfaceName}\", \"
No matching constructor signature.\"), info.GetIsolate()); | |
| 2850 END | |
| 2851 } | |
| 2852 $code .= "}\n\n"; | |
| 2853 $implementation{nameSpaceInternal}->add($code); | |
| 2854 } | |
| 2855 | |
| 2856 sub GenerateSingleConstructorCallback | |
| 2857 { | |
| 2858 my $interface = shift; | |
| 2859 my $function = shift; | |
| 2860 | |
| 2861 my $interfaceName = $interface->name; | |
| 2862 my $implClassName = GetImplName($interface); | |
| 2863 my $v8ClassName = GetV8ClassName($interface); | |
| 2864 my $overloadedIndexString = ""; | |
| 2865 if ($function->overloadedIndex > 0) { | |
| 2866 $overloadedIndexString .= $function->overloadedIndex; | |
| 2867 } | |
| 2868 | |
| 2869 my $constructorRaisesException = $interface->extendedAttributes->{"RaisesExc
eption"} && $interface->extendedAttributes->{"RaisesException"} eq "Constructor"
; | |
| 2870 my $hasExceptionState = $function->extendedAttributes->{"RaisesException"} |
| $constructorRaisesException || HasExceptionRaisingParameter($function); | |
| 2871 | |
| 2872 my @beforeArgumentList; | |
| 2873 my @afterArgumentList; | |
| 2874 my $code = ""; | |
| 2875 $code .= <<END; | |
| 2876 static void constructor${overloadedIndexString}(const v8::FunctionCallbackInfo<v
8::Value>& info) | |
| 2877 { | |
| 2878 END | |
| 2879 | |
| 2880 if ($hasExceptionState) { | |
| 2881 $code .= " ExceptionState exceptionState(ExceptionState::Construction
Context, \"${interfaceName}\", info.Holder(), info.GetIsolate());\n"; | |
| 2882 } | |
| 2883 if ($function->overloadedIndex == 0) { | |
| 2884 $code .= GenerateArgumentsCountCheck($function, $interface, $hasExceptio
nState); | |
| 2885 } | |
| 2886 | |
| 2887 # FIXME: Currently [Constructor(...)] does not yet support optional argument
s without [Default=...] | |
| 2888 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersC
heck($function, $interface, "", $hasExceptionState); | |
| 2889 $code .= $parameterCheckString; | |
| 2890 | |
| 2891 if ($interface->extendedAttributes->{"ConstructorCallWith"}) { | |
| 2892 if (ExtendedAttributeContains($interface->extendedAttributes->{"Construc
torCallWith"}, "ExecutionContext")) { | |
| 2893 push(@beforeArgumentList, "context"); | |
| 2894 $code .= " ExecutionContext* context = currentExecutionContext(in
fo.GetIsolate());\n"; | |
| 2895 } | |
| 2896 if (ExtendedAttributeContains($interface->extendedAttributes->{"Construc
torCallWith"}, "Document")) { | |
| 2897 push(@beforeArgumentList, "document"); | |
| 2898 $code .= " Document& document = *toDocument(currentExecutionConte
xt(info.GetIsolate()));\n"; | |
| 2899 } | |
| 2900 } | |
| 2901 | |
| 2902 if ($constructorRaisesException) { | |
| 2903 push(@afterArgumentList, "exceptionState"); | |
| 2904 } | |
| 2905 | |
| 2906 my @argumentList; | |
| 2907 my $index = 0; | |
| 2908 foreach my $parameter (@{$function->parameters}) { | |
| 2909 last if $index eq $paramIndex; | |
| 2910 if ($replacements{$parameter->name}) { | |
| 2911 push(@argumentList, $replacements{$parameter->name}); | |
| 2912 } else { | |
| 2913 push(@argumentList, $parameter->name); | |
| 2914 } | |
| 2915 $index++; | |
| 2916 } | |
| 2917 | |
| 2918 my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterAr
gumentList); | |
| 2919 my $refPtrType = IsWillBeGarbageCollectedType($interfaceName) ? "RefPtrWillB
eRawPtr<$implClassName>" : "RefPtr<$implClassName>"; | |
| 2920 $code .= " $refPtrType impl = ${implClassName}::create(${argumentString})
;\n"; | |
| 2921 $code .= " v8::Handle<v8::Object> wrapper = info.Holder();\n"; | |
| 2922 | |
| 2923 if ($constructorRaisesException) { | |
| 2924 $code .= " if (exceptionState.throwIfNeeded())\n"; | |
| 2925 $code .= " return;\n"; | |
| 2926 } | |
| 2927 | |
| 2928 $code .= <<END; | |
| 2929 | |
| 2930 V8DOMWrapper::associateObjectWithWrapper<${v8ClassName}>(impl.release(), &${
v8ClassName}::wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration:
:Dependent); | |
| 2931 v8SetReturnValue(info, wrapper); | |
| 2932 } | |
| 2933 | |
| 2934 END | |
| 2935 $implementation{nameSpaceInternal}->add($code); | |
| 2936 } | |
| 2937 | |
| 2938 # The Web IDL specification states that Interface objects for interfaces MUST ha
ve a property named | |
| 2939 # "length" that returns the length of the shortest argument list of the entries
in the effective | |
| 2940 # overload set for constructors. In other words, use the lowest number of mandat
ory arguments among | |
| 2941 # all constructors. | |
| 2942 sub GetInterfaceLength | |
| 2943 { | |
| 2944 my $interface = shift; | |
| 2945 | |
| 2946 my $leastConstructorLength = 0; | |
| 2947 if ($interface->extendedAttributes->{"EventConstructor"}) { | |
| 2948 $leastConstructorLength = 1; | |
| 2949 } elsif ($interface->extendedAttributes->{"Constructor"} || $interface->exte
ndedAttributes->{"CustomConstructor"}) { | |
| 2950 my @constructors = @{$interface->constructors}; | |
| 2951 my @customConstructors = @{$interface->customConstructors}; | |
| 2952 $leastConstructorLength = 255; | |
| 2953 foreach my $constructor (@constructors, @customConstructors) { | |
| 2954 my $constructorLength = GetFunctionLength($constructor); | |
| 2955 $leastConstructorLength = $constructorLength if ($constructorLength
< $leastConstructorLength); | |
| 2956 } | |
| 2957 } | |
| 2958 | |
| 2959 return $leastConstructorLength; | |
| 2960 } | |
| 2961 | |
| 2962 sub GenerateConstructorCallback | |
| 2963 { | |
| 2964 my $interface = shift; | |
| 2965 | |
| 2966 my $implClassName = GetImplName($interface); | |
| 2967 my $v8ClassName = GetV8ClassName($interface); | |
| 2968 my $code = ""; | |
| 2969 $code .= "void ${v8ClassName}::constructorCallback(const v8::FunctionCallbac
kInfo<v8::Value>& info)\n"; | |
| 2970 $code .= "{\n"; | |
| 2971 $code .= " TRACE_EVENT_SCOPED_SAMPLING_STATE(\"Blink\", \"DOMConstructor\
");\n"; | |
| 2972 $code .= GenerateFeatureObservation($interface->extendedAttributes->{"Measur
eAs"}); | |
| 2973 $code .= GenerateDeprecationNotification($interface->extendedAttributes->{"D
eprecateAs"}); | |
| 2974 $code .= GenerateConstructorHeader($interface->name); | |
| 2975 if (HasCustomConstructor($interface)) { | |
| 2976 $code .= " ${v8ClassName}::constructorCustom(info);\n"; | |
| 2977 } else { | |
| 2978 $code .= " ${implClassName}V8Internal::constructor(info);\n"; | |
| 2979 } | |
| 2980 $code .= "}\n\n"; | |
| 2981 $implementation{nameSpaceWebCore}->add($code); | |
| 2982 } | |
| 2983 | |
| 2984 sub GenerateConstructor | |
| 2985 { | |
| 2986 my $interface = shift; | |
| 2987 | |
| 2988 if (@{$interface->constructors} == 1) { | |
| 2989 GenerateSingleConstructorCallback($interface, @{$interface->constructors
}[0]); | |
| 2990 } else { | |
| 2991 foreach my $constructor (@{$interface->constructors}) { | |
| 2992 GenerateSingleConstructorCallback($interface, $constructor); | |
| 2993 } | |
| 2994 GenerateOverloadedConstructorCallback($interface); | |
| 2995 } | |
| 2996 } | |
| 2997 | |
| 2998 sub GenerateEventConstructor | |
| 2999 { | |
| 3000 my $interface = shift; | |
| 3001 | |
| 3002 my $interfaceName = $interface->name; | |
| 3003 my $implClassName = GetImplName($interface); | |
| 3004 my $v8ClassName = GetV8ClassName($interface); | |
| 3005 | |
| 3006 my $constructorRaisesException = $interface->extendedAttributes->{"RaisesExc
eption"} && $interface->extendedAttributes->{"RaisesException"} eq "Constructor"
; | |
| 3007 | |
| 3008 my @anyAttributeNames; | |
| 3009 foreach my $attribute (@{$interface->attributes}) { | |
| 3010 if ($attribute->type eq "any") { | |
| 3011 push(@anyAttributeNames, $attribute->name); | |
| 3012 } | |
| 3013 } | |
| 3014 | |
| 3015 AddToImplIncludes("bindings/v8/Dictionary.h"); | |
| 3016 $implementation{nameSpaceInternal}->add(<<END); | |
| 3017 static void constructor(const v8::FunctionCallbackInfo<v8::Value>& info) | |
| 3018 { | |
| 3019 ExceptionState exceptionState(ExceptionState::ConstructionContext, \"${inter
faceName}\", info.Holder(), info.GetIsolate()); | |
| 3020 if (info.Length() < 1) { | |
| 3021 exceptionState.throwTypeError("An event name must be provided."); | |
| 3022 exceptionState.throwIfNeeded(); | |
| 3023 return; | |
| 3024 } | |
| 3025 | |
| 3026 V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, type, info[0]); | |
| 3027 END | |
| 3028 | |
| 3029 foreach my $attrName (@anyAttributeNames) { | |
| 3030 $implementation{nameSpaceInternal}->add(" v8::Local<v8::Value> ${attr
Name};\n"); | |
| 3031 } | |
| 3032 | |
| 3033 $implementation{nameSpaceInternal}->add(<<END); | |
| 3034 ${implClassName}Init eventInit; | |
| 3035 if (info.Length() >= 2) { | |
| 3036 V8TRYCATCH_VOID(Dictionary, options, Dictionary(info[1], info.GetIsolate
())); | |
| 3037 if (!initialize${implClassName}(eventInit, options, exceptionState, info
)) { | |
| 3038 exceptionState.throwIfNeeded(); | |
| 3039 return; | |
| 3040 } | |
| 3041 END | |
| 3042 | |
| 3043 # Store 'any'-typed properties on the wrapper to avoid leaking them between
isolated worlds. | |
| 3044 foreach my $attrName (@anyAttributeNames) { | |
| 3045 $implementation{nameSpaceInternal}->add(<<END); | |
| 3046 options.get("${attrName}", ${attrName}); | |
| 3047 if (!${attrName}.IsEmpty()) | |
| 3048 setHiddenValue(info.GetIsolate(), info.Holder(), "${attrName}", ${at
trName}); | |
| 3049 END | |
| 3050 } | |
| 3051 | |
| 3052 $implementation{nameSpaceInternal}->add(<<END); | |
| 3053 } | |
| 3054 END | |
| 3055 | |
| 3056 my $exceptionStateArgument = ""; | |
| 3057 if ($constructorRaisesException) { | |
| 3058 ${exceptionStateArgument} = ", exceptionState"; | |
| 3059 } | |
| 3060 | |
| 3061 $implementation{nameSpaceInternal}->add(<<END); | |
| 3062 RefPtr<${implClassName}> event = ${implClassName}::create(type, eventInit${e
xceptionStateArgument}); | |
| 3063 END | |
| 3064 | |
| 3065 if ($constructorRaisesException) { | |
| 3066 $implementation{nameSpaceInternal}->add(<<END); | |
| 3067 if (exceptionState.throwIfNeeded()) | |
| 3068 return; | |
| 3069 END | |
| 3070 } | |
| 3071 | |
| 3072 if (@anyAttributeNames) { | |
| 3073 # Separate check to simplify Python code | |
| 3074 AddToImplIncludes("bindings/v8/SerializedScriptValue.h"); | |
| 3075 } | |
| 3076 if (@anyAttributeNames && $interface->name ne 'ErrorEvent') { | |
| 3077 # If we're in an isolated world, create a SerializedScriptValue and | |
| 3078 # store it in the event for later cloning if the property is accessed | |
| 3079 # from another world. | |
| 3080 # The main world case is handled lazily (in Custom code). | |
| 3081 # | |
| 3082 # We do not clone Error objects (exceptions), for 2 reasons: | |
| 3083 # 1) Errors carry a reference to the isolated world's global object, | |
| 3084 # and thus passing it around would cause leakage. | |
| 3085 # 2) Errors cannot be cloned (or serialized): | |
| 3086 # http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom
-interfaces.html#safe-passing-of-structured-data | |
| 3087 $implementation{nameSpaceInternal}->add(" if (DOMWrapperWorld::curren
t(info.GetIsolate())->isIsolatedWorld()) {\n"); | |
| 3088 foreach my $attrName (@anyAttributeNames) { | |
| 3089 my $setter = "setSerialized" . FirstLetterToUpperCase($attrName); | |
| 3090 $implementation{nameSpaceInternal}->add(<<END); | |
| 3091 if (!${attrName}.IsEmpty()) | |
| 3092 event->${setter}(SerializedScriptValue::createAndSwallowExceptions($
{attrName}, info.GetIsolate())); | |
| 3093 END | |
| 3094 } | |
| 3095 $implementation{nameSpaceInternal}->add(" }\n\n"); | |
| 3096 } | |
| 3097 | |
| 3098 $implementation{nameSpaceInternal}->add(<<END); | |
| 3099 v8::Handle<v8::Object> wrapper = info.Holder(); | |
| 3100 V8DOMWrapper::associateObjectWithWrapper<${v8ClassName}>(event.release(), &$
{v8ClassName}::wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration
::Dependent); | |
| 3101 v8SetReturnValue(info, wrapper); | |
| 3102 } | |
| 3103 | |
| 3104 END | |
| 3105 | |
| 3106 my $code = ""; | |
| 3107 $code .= <<END; | |
| 3108 bool initialize${implClassName}(${implClassName}Init& eventInit, const Dictionar
y& options, ExceptionState& exceptionState, const v8::FunctionCallbackInfo<v8::V
alue>& info, const String& forEventName) | |
| 3109 { | |
| 3110 Dictionary::ConversionContext conversionContext(forEventName.isEmpty() ? Str
ing("${interfaceName}") : forEventName, "", exceptionState); | |
| 3111 END | |
| 3112 | |
| 3113 if ($interface->parent) { | |
| 3114 my $interfaceBase = $interface->parent; | |
| 3115 $code .= <<END; | |
| 3116 if (!initialize${interfaceBase}(eventInit, options, exceptionState, info, fo
rEventName.isEmpty() ? String("${interfaceName}") : forEventName)) | |
| 3117 return false; | |
| 3118 | |
| 3119 END | |
| 3120 } | |
| 3121 | |
| 3122 foreach my $attribute (@{$interface->attributes}) { | |
| 3123 if ($attribute->extendedAttributes->{"InitializedByEventConstructor"}) { | |
| 3124 if ($attribute->type ne "any") { | |
| 3125 my $attributeName = $attribute->name; | |
| 3126 my $attributeImplName = GetImplName($attribute); | |
| 3127 | |
| 3128 my $isNullable = $attribute->isNullable ? "true" : "false"; | |
| 3129 my $dictionaryGetter = "options.convert(conversionContext.setCon
versionType(\"" . $attribute->type . "\", $isNullable), \"$attributeName\", even
tInit.$attributeImplName)"; | |
| 3130 my $deprecation = $attribute->extendedAttributes->{"DeprecateAs"
}; | |
| 3131 if ($deprecation) { | |
| 3132 $code .= " if ($dictionaryGetter) {\n"; | |
| 3133 $code .= " if (options.hasProperty(\"$attributeName\"
))\n"; | |
| 3134 $code .= " " . GenerateDeprecationNotification($depre
cation); | |
| 3135 $code .= " } else {\n"; | |
| 3136 $code .= " return false;\n"; | |
| 3137 $code .= " }\n"; | |
| 3138 } else { | |
| 3139 $code .= " if (!$dictionaryGetter)\n"; | |
| 3140 $code .= " return false;\n"; | |
| 3141 } | |
| 3142 } | |
| 3143 } | |
| 3144 } | |
| 3145 | |
| 3146 $code .= <<END; | |
| 3147 return true; | |
| 3148 } | |
| 3149 | |
| 3150 END | |
| 3151 $implementation{nameSpaceWebCore}->add($code); | |
| 3152 } | |
| 3153 | |
| 3154 sub GenerateNamedConstructor | |
| 3155 { | |
| 3156 my $function = shift; | |
| 3157 my $interface = shift; | |
| 3158 | |
| 3159 my $interfaceName = $interface->name; | |
| 3160 my $implClassName = GetImplName($interface); | |
| 3161 my $v8ClassName = GetV8ClassName($interface); | |
| 3162 my $constructorRaisesException = $interface->extendedAttributes->{"RaisesExc
eption"} && $interface->extendedAttributes->{"RaisesException"} eq "Constructor"
; | |
| 3163 my $raisesExceptions = $function->extendedAttributes->{"RaisesException"} ||
$constructorRaisesException || HasExceptionRaisingParameter($function); | |
| 3164 | |
| 3165 my $maybeObserveFeature = GenerateFeatureObservation($function->extendedAttr
ibutes->{"MeasureAs"}); | |
| 3166 my $maybeDeprecateFeature = GenerateDeprecationNotification($function->exten
dedAttributes->{"DeprecateAs"}); | |
| 3167 | |
| 3168 my @beforeArgumentList; | |
| 3169 my @afterArgumentList; | |
| 3170 | |
| 3171 my $toActiveDOMObject = InheritsExtendedAttribute($interface, "ActiveDOMObje
ct") ? "${v8ClassName}::toActiveDOMObject" : "0"; | |
| 3172 my $toEventTarget = InheritsInterface($interface, "EventTarget") ? "${v8Clas
sName}::toEventTarget" : "0"; | |
| 3173 my $derefObject = "${v8ClassName}::derefObject"; | |
| 3174 my $isGarbageCollected = IsWillBeGarbageCollectedType($interfaceName) ? "tru
e" : "false"; | |
| 3175 | |
| 3176 $implementation{nameSpaceWebCore}->add(<<END); | |
| 3177 const WrapperTypeInfo ${v8ClassName}Constructor::wrapperTypeInfo = { gin::kEmbed
derBlink, ${v8ClassName}Constructor::domTemplate, $derefObject, $toActiveDOMObje
ct, $toEventTarget, 0, ${v8ClassName}::installPerContextEnabledMethods, 0, Wrapp
erTypeObjectPrototype, $isGarbageCollected }; | |
| 3178 | |
| 3179 END | |
| 3180 | |
| 3181 my $code = ""; | |
| 3182 $code .= <<END; | |
| 3183 static void ${v8ClassName}ConstructorCallback(const v8::FunctionCallbackInfo<v8:
:Value>& info) | |
| 3184 { | |
| 3185 END | |
| 3186 $code .= $maybeObserveFeature if $maybeObserveFeature; | |
| 3187 $code .= $maybeDeprecateFeature if $maybeDeprecateFeature; | |
| 3188 $code .= GenerateConstructorHeader($function->extendedAttributes->{"NamedCon
structor"}); | |
| 3189 $code .= <<END; | |
| 3190 Document* document = currentDocument(info.GetIsolate()); | |
| 3191 ASSERT(document); | |
| 3192 | |
| 3193 // Make sure the document is added to the DOM Node map. Otherwise, the ${imp
lClassName} instance | |
| 3194 // may end up being the only node in the map and get garbage-collected prema
turely. | |
| 3195 toV8(document, info.Holder(), info.GetIsolate()); | |
| 3196 | |
| 3197 END | |
| 3198 | |
| 3199 my $hasExceptionState = $raisesExceptions; | |
| 3200 if ($hasExceptionState) { | |
| 3201 $code .= " ExceptionState exceptionState(ExceptionState::Construction
Context, \"${interfaceName}\", info.Holder(), info.GetIsolate());\n"; | |
| 3202 } | |
| 3203 $code .= GenerateArgumentsCountCheck($function, $interface, $hasExceptionSta
te); | |
| 3204 | |
| 3205 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersC
heck($function, $interface, "", $hasExceptionState); | |
| 3206 $code .= $parameterCheckString; | |
| 3207 | |
| 3208 push(@beforeArgumentList, "*document"); | |
| 3209 | |
| 3210 if ($constructorRaisesException) { | |
| 3211 push(@afterArgumentList, "exceptionState"); | |
| 3212 } | |
| 3213 | |
| 3214 my @argumentList; | |
| 3215 my $index = 0; | |
| 3216 foreach my $parameter (@{$function->parameters}) { | |
| 3217 last if $index eq $paramIndex; | |
| 3218 if ($replacements{$parameter->name}) { | |
| 3219 push(@argumentList, $replacements{$parameter->name}); | |
| 3220 } else { | |
| 3221 push(@argumentList, $parameter->name); | |
| 3222 } | |
| 3223 $index++; | |
| 3224 } | |
| 3225 | |
| 3226 my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterAr
gumentList); | |
| 3227 $code .= " RefPtr<${implClassName}> impl = ${implClassName}::createForJSC
onstructor(${argumentString});\n"; | |
| 3228 $code .= " v8::Handle<v8::Object> wrapper = info.Holder();\n"; | |
| 3229 | |
| 3230 if ($constructorRaisesException) { | |
| 3231 $code .= " if (exceptionState.throwIfNeeded())\n"; | |
| 3232 $code .= " return;\n"; | |
| 3233 } | |
| 3234 | |
| 3235 $code .= <<END; | |
| 3236 | |
| 3237 V8DOMWrapper::associateObjectWithWrapper<${v8ClassName}>(impl.release(), &${
v8ClassName}Constructor::wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperCon
figuration::Dependent); | |
| 3238 v8SetReturnValue(info, wrapper); | |
| 3239 } | |
| 3240 | |
| 3241 END | |
| 3242 $implementation{nameSpaceWebCore}->add($code); | |
| 3243 | |
| 3244 $code = <<END; | |
| 3245 v8::Handle<v8::FunctionTemplate> ${v8ClassName}Constructor::domTemplate(v8::Isol
ate* isolate, WrapperWorldType currentWorldType) | |
| 3246 { | |
| 3247 static int domTemplateKey; // This address is used for a key to look up the
dom template. | |
| 3248 V8PerIsolateData* data = V8PerIsolateData::from(isolate); | |
| 3249 v8::Local<v8::FunctionTemplate> result = data->existingDOMTemplate(currentWo
rldType, &domTemplateKey); | |
| 3250 if (!result.IsEmpty()) | |
| 3251 return result; | |
| 3252 | |
| 3253 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate"); | |
| 3254 v8::EscapableHandleScope scope(isolate); | |
| 3255 result = v8::FunctionTemplate::New(isolate, ${v8ClassName}ConstructorCallbac
k); | |
| 3256 | |
| 3257 v8::Local<v8::ObjectTemplate> instanceTemplate = result->InstanceTemplate(); | |
| 3258 instanceTemplate->SetInternalFieldCount(${v8ClassName}::internalFieldCount); | |
| 3259 result->SetClassName(v8AtomicString(isolate, "${implClassName}")); | |
| 3260 result->Inherit(${v8ClassName}::domTemplate(isolate, currentWorldType)); | |
| 3261 data->setDOMTemplate(currentWorldType, &domTemplateKey, result); | |
| 3262 | |
| 3263 return scope.Escape(result); | |
| 3264 } | |
| 3265 | |
| 3266 END | |
| 3267 $implementation{nameSpaceWebCore}->add($code); | |
| 3268 } | |
| 3269 | |
| 3270 sub GenerateConstructorHeader | |
| 3271 { | |
| 3272 my $constructorName = shift; | |
| 3273 | |
| 3274 AddToImplIncludes("bindings/v8/V8ObjectConstructor.h"); | |
| 3275 my $content = <<END; | |
| 3276 if (!info.IsConstructCall()) { | |
| 3277 throwTypeError(ExceptionMessages::failedToConstruct("$constructorName",
"Please use the 'new' operator, this DOM object constructor cannot be called as
a function."), info.GetIsolate()); | |
| 3278 return; | |
| 3279 } | |
| 3280 | |
| 3281 if (ConstructorMode::current() == ConstructorMode::WrapExistingObject) { | |
| 3282 v8SetReturnValue(info, info.Holder()); | |
| 3283 return; | |
| 3284 } | |
| 3285 | |
| 3286 END | |
| 3287 return $content; | |
| 3288 } | |
| 3289 | |
| 3290 sub GenerateAttributeConfigurationArray | |
| 3291 { | |
| 3292 my $interface = shift; | |
| 3293 my $attributes = shift; | |
| 3294 my $exposeJSAccessors = shift; | |
| 3295 | |
| 3296 my $code = ""; | |
| 3297 foreach my $attribute (@$attributes) { | |
| 3298 my $conditionalString = GenerateConditionalString($attribute); | |
| 3299 my $subCode = ""; | |
| 3300 $subCode .= "#if ${conditionalString}\n" if $conditionalString; | |
| 3301 $subCode .= GenerateAttributeConfiguration($interface, $attribute, ",",
"", $exposeJSAccessors); | |
| 3302 $subCode .= "#endif // ${conditionalString}\n" if $conditionalString; | |
| 3303 $code .= $subCode; | |
| 3304 } | |
| 3305 return $code; | |
| 3306 } | |
| 3307 | |
| 3308 sub GenerateAttributeConfigurationParameters | |
| 3309 { | |
| 3310 my $interface = shift; | |
| 3311 my $attribute = shift; | |
| 3312 my $attrName = $attribute->name; | |
| 3313 my $attrExt = $attribute->extendedAttributes; | |
| 3314 my $implClassName = GetImplName($interface); | |
| 3315 | |
| 3316 my @accessControlList; | |
| 3317 if (my $doNotCheckSecurity = $attrExt->{"DoNotCheckSecurity"}) { | |
| 3318 if ($doNotCheckSecurity eq "Getter") { | |
| 3319 push(@accessControlList, "v8::ALL_CAN_READ"); | |
| 3320 } elsif ($doNotCheckSecurity eq "Setter") { | |
| 3321 push(@accessControlList, "v8::ALL_CAN_WRITE"); | |
| 3322 } else { | |
| 3323 push(@accessControlList, "v8::ALL_CAN_READ"); | |
| 3324 if (!IsReadonly($attribute)) { | |
| 3325 push(@accessControlList, "v8::ALL_CAN_WRITE"); | |
| 3326 } | |
| 3327 } | |
| 3328 } | |
| 3329 if ($attrExt->{"Unforgeable"}) { | |
| 3330 push(@accessControlList, "v8::PROHIBITS_OVERWRITING"); | |
| 3331 } | |
| 3332 @accessControlList = ("v8::DEFAULT") unless @accessControlList; | |
| 3333 my $accessControl = "static_cast<v8::AccessControl>(" . join(" | ", @accessC
ontrolList) . ")"; | |
| 3334 | |
| 3335 my $customAccessor = HasCustomGetter($attrExt) || HasCustomSetter($attribute
) || ""; | |
| 3336 if ($customAccessor eq "VALUE_IS_MISSING") { | |
| 3337 # use the naming convension, interface + (capitalize) attr name | |
| 3338 $customAccessor = $implClassName . "::" . $attrName; | |
| 3339 } | |
| 3340 | |
| 3341 my $getter; | |
| 3342 my $setter; | |
| 3343 my $getterForMainWorld; | |
| 3344 my $setterForMainWorld; | |
| 3345 | |
| 3346 my $isConstructor = ($attribute->type =~ /Constructor$/); | |
| 3347 | |
| 3348 # Check attributes. | |
| 3349 # As per Web IDL specification, constructor properties on the ECMAScript glo
bal object should be | |
| 3350 # configurable and should not be enumerable. | |
| 3351 my @propAttributeList; | |
| 3352 if ($attrExt->{"NotEnumerable"} || $isConstructor) { | |
| 3353 push(@propAttributeList, "v8::DontEnum"); | |
| 3354 } | |
| 3355 if ($attrExt->{"Unforgeable"} && !$isConstructor) { | |
| 3356 push(@propAttributeList, "v8::DontDelete"); | |
| 3357 } | |
| 3358 @propAttributeList = ("v8::None") unless @propAttributeList; | |
| 3359 my $propAttribute = join(" | ", @propAttributeList); | |
| 3360 | |
| 3361 my $onProto = "0 /* on instance */"; | |
| 3362 my $data = "0"; # no data | |
| 3363 | |
| 3364 # Constructor | |
| 3365 if ($isConstructor) { | |
| 3366 my $constructorType = $attribute->type; | |
| 3367 $constructorType =~ s/Constructor$//; | |
| 3368 | |
| 3369 # For NamedConstructors we do not generate a header file. The code for t
he NamedConstructor | |
| 3370 # gets generated when we generate the code for its interface. | |
| 3371 if ($constructorType !~ /Constructor$/) { | |
| 3372 AddToImplIncludes("V8${constructorType}.h"); | |
| 3373 } | |
| 3374 $data = "const_cast<WrapperTypeInfo*>(&V8${constructorType}::wrapperType
Info)"; | |
| 3375 $getter = "${implClassName}V8Internal::${implClassName}ConstructorGetter
"; | |
| 3376 $setter = "${implClassName}V8Internal::${implClassName}ReplaceableAttrib
uteSetterCallback"; | |
| 3377 $getterForMainWorld = "0"; | |
| 3378 $setterForMainWorld = "0"; | |
| 3379 } else { | |
| 3380 # Default Getter and Setter | |
| 3381 $getter = "${implClassName}V8Internal::${attrName}AttributeGetterCallbac
k"; | |
| 3382 $setter = "${implClassName}V8Internal::${attrName}AttributeSetterCallbac
k"; | |
| 3383 $getterForMainWorld = "${getter}ForMainWorld"; | |
| 3384 $setterForMainWorld = "${setter}ForMainWorld"; | |
| 3385 | |
| 3386 if (!HasCustomSetter($attribute) && !$attrExt->{"PutForwards"} && $attrE
xt->{"Replaceable"}) { | |
| 3387 $setter = "${implClassName}V8Internal::${implClassName}ReplaceableAt
tributeSetterCallback"; | |
| 3388 $setterForMainWorld = "0"; | |
| 3389 } | |
| 3390 } | |
| 3391 | |
| 3392 # Read only attributes | |
| 3393 if (IsReadonly($attribute)) { | |
| 3394 $setter = "0"; | |
| 3395 $setterForMainWorld = "0"; | |
| 3396 } | |
| 3397 | |
| 3398 # An accessor can be installed on the prototype | |
| 3399 if ($attrExt->{"OnPrototype"}) { | |
| 3400 $onProto = "1 /* on prototype */"; | |
| 3401 } | |
| 3402 | |
| 3403 if (!$attrExt->{"PerWorldBindings"}) { | |
| 3404 $getterForMainWorld = "0"; | |
| 3405 $setterForMainWorld = "0"; | |
| 3406 } | |
| 3407 | |
| 3408 return ($attrName, $getter, $setter, $getterForMainWorld, $setterForMainWorl
d, $data, $accessControl, "static_cast<v8::PropertyAttribute>($propAttribute)",
$onProto); | |
| 3409 } | |
| 3410 | |
| 3411 sub GenerateAttributeConfiguration | |
| 3412 { | |
| 3413 my $interface = shift; | |
| 3414 my $attribute = shift; | |
| 3415 my $delimiter = shift; | |
| 3416 my $indent = shift; | |
| 3417 my $exposeJSAccessors = shift; | |
| 3418 | |
| 3419 my $code = ""; | |
| 3420 | |
| 3421 my ($attrName, $getter, $setter, $getterForMainWorld, $setterForMainWorld, $
data, $accessControl, $propAttribute, $onProto) = GenerateAttributeConfiguration
Parameters($interface, $attribute, $exposeJSAccessors); | |
| 3422 if ($exposeJSAccessors) { | |
| 3423 $code .= $indent . " {\"$attrName\", $getter, $setter, $getterForMain
World, $setterForMainWorld, $data, $accessControl, $propAttribute}" . $delimiter
. "\n"; | |
| 3424 } else { | |
| 3425 $code .= $indent . " {\"$attrName\", $getter, $setter, $getterForMain
World, $setterForMainWorld, $data, $accessControl, $propAttribute, $onProto}" .
$delimiter . "\n"; | |
| 3426 } | |
| 3427 return $code; | |
| 3428 } | |
| 3429 | |
| 3430 sub GenerateStaticAttribute | |
| 3431 { | |
| 3432 my $interface = shift; | |
| 3433 my $attribute = shift; | |
| 3434 my $attrExt = $attribute->extendedAttributes; | |
| 3435 my $code = ""; | |
| 3436 | |
| 3437 my ($attrName, $getter, $setter, $getterForMainWorld, $setterForMainWorld, $
data, $accessControl, $propAttribute, $onProto) = GenerateAttributeConfiguration
Parameters($interface, $attribute); | |
| 3438 | |
| 3439 die "Static attributes do not support optimized getters or setters for the m
ain world" if $getterForMainWorld || $setterForMainWorld; | |
| 3440 | |
| 3441 my $conditionalString = GenerateConditionalString($attribute); | |
| 3442 | |
| 3443 $code .= "#if ${conditionalString}\n" if $conditionalString; | |
| 3444 $code .= " functionTemplate->SetNativeDataProperty(v8AtomicString(isolate
, \"$attrName\"), $getter, $setter, v8::External::New(isolate, $data), $propAttr
ibute, v8::Handle<v8::AccessorSignature>(), $accessControl);\n"; | |
| 3445 $code .= "#endif // ${conditionalString}\n" if $conditionalString; | |
| 3446 | |
| 3447 return $code; | |
| 3448 } | |
| 3449 | |
| 3450 sub IsStandardFunction | |
| 3451 { | |
| 3452 my $interface = shift; | |
| 3453 my $function = shift; | |
| 3454 | |
| 3455 my $interfaceName = $interface->name; | |
| 3456 my $attrExt = $function->extendedAttributes; | |
| 3457 return 0 if $attrExt->{"Unforgeable"}; | |
| 3458 return 0 if $function->isStatic; | |
| 3459 return 0 if $attrExt->{"RuntimeEnabled"}; | |
| 3460 return 0 if $attrExt->{"PerContextEnabled"}; | |
| 3461 return 0 if $attrExt->{"DoNotCheckSignature"}; | |
| 3462 return 0 if ($attrExt->{"DoNotCheckSecurity"} && ($interface->extendedAttrib
utes->{"CheckSecurity"} || $interfaceName eq "Window")); | |
| 3463 return 0 if $attrExt->{"NotEnumerable"}; | |
| 3464 return 0 if $attrExt->{"ReadOnly"}; | |
| 3465 return 1; | |
| 3466 } | |
| 3467 | |
| 3468 sub GenerateNonStandardFunction | |
| 3469 { | |
| 3470 my $interface = shift; | |
| 3471 my $function = shift; | |
| 3472 my $code = ""; | |
| 3473 | |
| 3474 my $implClassName = GetImplName($interface); | |
| 3475 my $attrExt = $function->extendedAttributes; | |
| 3476 my $name = $function->name; | |
| 3477 | |
| 3478 my $property_attributes = "v8::DontDelete"; | |
| 3479 if ($attrExt->{"NotEnumerable"}) { | |
| 3480 $property_attributes .= " | v8::DontEnum"; | |
| 3481 } | |
| 3482 if ($attrExt->{"ReadOnly"}) { | |
| 3483 $property_attributes .= " | v8::ReadOnly"; | |
| 3484 } | |
| 3485 | |
| 3486 my $commentInfo = "Function '$name' (Extended Attributes: '" . join(' ', key
s(%{$attrExt})) . "')"; | |
| 3487 | |
| 3488 my $template = "prototypeTemplate"; | |
| 3489 if ($attrExt->{"Unforgeable"}) { | |
| 3490 $template = "instanceTemplate"; | |
| 3491 } | |
| 3492 if ($function->isStatic) { | |
| 3493 $template = "functionTemplate"; | |
| 3494 } | |
| 3495 | |
| 3496 my $conditional4 = ""; # 4 space indent context | |
| 3497 my $conditional8 = ""; # 8 space indent context | |
| 3498 if ($attrExt->{"RuntimeEnabled"}) { | |
| 3499 # Only call Set()/SetAccessor() if this method should be enabled | |
| 3500 my $runtimeEnabledFunction = GetRuntimeEnabledFunctionName($function); | |
| 3501 $conditional4 = "if (${runtimeEnabledFunction}())\n "; | |
| 3502 } | |
| 3503 if ($attrExt->{"PerContextEnabled"}) { | |
| 3504 # Only call Set()/SetAccessor() if this method should be enabled | |
| 3505 my $contextEnabledFunction = GetContextEnabledFunctionName($function); | |
| 3506 $conditional4 = "if (${contextEnabledFunction}(impl->document()))\n
"; | |
| 3507 } | |
| 3508 $conditional8 = $conditional4 . " " if $conditional4 ne ""; | |
| 3509 | |
| 3510 if ($interface->extendedAttributes->{"CheckSecurity"} && $attrExt->{"DoNotCh
eckSecurity"}) { | |
| 3511 my $setter = $attrExt->{"ReadOnly"} ? "0" : "${implClassName}V8Internal:
:${implClassName}OriginSafeMethodSetterCallback"; | |
| 3512 # Functions that are marked DoNotCheckSecurity are always readable but i
f they are changed | |
| 3513 # and then accessed on a different domain we do not return the underlyin
g value but instead | |
| 3514 # return a new copy of the original function. This is achieved by storin
g the changed value | |
| 3515 # as hidden property. | |
| 3516 if ($function->extendedAttributes->{"PerWorldBindings"}) { | |
| 3517 $code .= <<END; | |
| 3518 if (currentWorldType == MainWorld) { | |
| 3519 ${conditional8}$template->SetAccessor(v8AtomicString(isolate, "$name"),
${implClassName}V8Internal::${name}OriginSafeMethodGetterCallbackForMainWorld, $
{setter}, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>($p
roperty_attributes)); | |
| 3520 } else { | |
| 3521 ${conditional8}$template->SetAccessor(v8AtomicString(isolate, "$name"),
${implClassName}V8Internal::${name}OriginSafeMethodGetterCallback, ${setter}, v8
Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>($property_attr
ibutes)); | |
| 3522 } | |
| 3523 END | |
| 3524 } else { | |
| 3525 $code .= " ${conditional4}$template->SetAccessor(v8AtomicString(i
solate, \"$name\"), ${implClassName}V8Internal::${name}OriginSafeMethodGetterCal
lback, ${setter}, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttri
bute>($property_attributes));\n"; | |
| 3526 } | |
| 3527 | |
| 3528 return $code; | |
| 3529 } | |
| 3530 | |
| 3531 my $signature = "defaultSignature"; | |
| 3532 if ($attrExt->{"DoNotCheckSignature"} || $function->isStatic) { | |
| 3533 $signature = "v8::Local<v8::Signature>()"; | |
| 3534 } | |
| 3535 | |
| 3536 my $conditionalString = GenerateConditionalString($function); | |
| 3537 $code .= "#if ${conditionalString}\n" if $conditionalString; | |
| 3538 | |
| 3539 if ($property_attributes eq "v8::DontDelete") { | |
| 3540 $property_attributes = ""; | |
| 3541 } else { | |
| 3542 $property_attributes = ", static_cast<v8::PropertyAttribute>($property_a
ttributes)"; | |
| 3543 } | |
| 3544 | |
| 3545 if ($template eq "prototypeTemplate" && $conditional4 eq "" && $signature eq
"defaultSignature" && $property_attributes eq "") { | |
| 3546 die "This shouldn't happen: Class '$implClassName' $commentInfo\n"; | |
| 3547 } | |
| 3548 | |
| 3549 my $functionLength = GetFunctionLength($function); | |
| 3550 | |
| 3551 if ($function->extendedAttributes->{"PerWorldBindings"}) { | |
| 3552 $code .= " if (currentWorldType == MainWorld) {\n"; | |
| 3553 $code .= " ${conditional8}$template->Set(v8AtomicString(isolate,
\"$name\"), v8::FunctionTemplate::New(isolate, ${implClassName}V8Internal::${nam
e}MethodCallbackForMainWorld, v8Undefined(), ${signature}, $functionLength)$prop
erty_attributes);\n"; | |
| 3554 $code .= " } else {\n"; | |
| 3555 $code .= " ${conditional8}$template->Set(v8AtomicString(isolate,
\"$name\"), v8::FunctionTemplate::New(isolate, ${implClassName}V8Internal::${nam
e}MethodCallback, v8Undefined(), ${signature}, $functionLength)$property_attribu
tes);\n"; | |
| 3556 $code .= " }\n"; | |
| 3557 } else { | |
| 3558 $code .= " ${conditional4}$template->Set(v8AtomicString(isolate, \"$n
ame\"), v8::FunctionTemplate::New(isolate, ${implClassName}V8Internal::${name}Me
thodCallback, v8Undefined(), ${signature}, $functionLength)$property_attributes)
;\n"; | |
| 3559 } | |
| 3560 $code .= "#endif // ${conditionalString}\n" if $conditionalString; | |
| 3561 return $code; | |
| 3562 } | |
| 3563 | |
| 3564 sub GenerateIsNullExpression | |
| 3565 { | |
| 3566 my $type = shift; | |
| 3567 my $variableName = shift; | |
| 3568 if (IsUnionType($type)) { | |
| 3569 my $types = $type->unionMemberTypes; | |
| 3570 my @expression = (); | |
| 3571 for my $i (0 .. scalar(@$types)-1) { | |
| 3572 my $unionMemberEnabledVariable = $variableName . $i . "Enabled"; | |
| 3573 push @expression, "!${unionMemberEnabledVariable}"; | |
| 3574 } | |
| 3575 return join " && ", @expression; | |
| 3576 } | |
| 3577 if (IsRefPtrType($type)) { | |
| 3578 return "!${variableName}"; | |
| 3579 } elsif ($type eq "DOMString") { | |
| 3580 return "${variableName}.isNull()"; | |
| 3581 } elsif ($type eq "Promise") { | |
| 3582 return "${variableName}.isNull()"; | |
| 3583 } else { | |
| 3584 return ""; | |
| 3585 } | |
| 3586 } | |
| 3587 | |
| 3588 sub GenerateIfElseStatement | |
| 3589 { | |
| 3590 my $type = shift; | |
| 3591 my $outputVariableName = shift; | |
| 3592 my $conditions = shift; | |
| 3593 my $statements = shift; | |
| 3594 | |
| 3595 my $code = ""; | |
| 3596 if (@$conditions == 1) { | |
| 3597 $code .= " ${type} ${outputVariableName} = " . $statements->[0] . "\n
"; | |
| 3598 } else { | |
| 3599 $code .= " ${type} ${outputVariableName};\n"; | |
| 3600 for my $i (0 .. @$conditions - 1) { | |
| 3601 my $token = "else if"; | |
| 3602 $token = "if" if $i == 0; | |
| 3603 $token = "else" if $i == @$conditions - 1; | |
| 3604 $code .= " ${token}"; | |
| 3605 $code .= " (" . $conditions->[$i] . ")" if $conditions->[$i]; | |
| 3606 $code .= "\n"; | |
| 3607 $code .= " ${outputVariableName} = " . $statements->[$i] . "\
n"; | |
| 3608 } | |
| 3609 } | |
| 3610 return $code; | |
| 3611 } | |
| 3612 | |
| 3613 sub GenerateImplementationIndexedPropertyAccessors | |
| 3614 { | |
| 3615 my $interface = shift; | |
| 3616 my $interfaceName = $interface->name; | |
| 3617 my $implClassName = GetImplName($interface); | |
| 3618 my $v8ClassName = GetV8ClassName($interface); | |
| 3619 | |
| 3620 my $indexedGetterFunction = GetIndexedGetterFunction($interface); | |
| 3621 if ($indexedGetterFunction) { | |
| 3622 # includes for return type even if custom | |
| 3623 my $returnType = $indexedGetterFunction->type; | |
| 3624 AddIncludesForType($returnType); | |
| 3625 my $hasCustomIndexedGetter = $indexedGetterFunction->extendedAttributes-
>{"Custom"}; | |
| 3626 if (!$hasCustomIndexedGetter) { | |
| 3627 GenerateImplementationIndexedPropertyGetter($interface, $indexedGett
erFunction); | |
| 3628 } | |
| 3629 GenerateImplementationIndexedPropertyGetterCallback($interface, $hasCust
omIndexedGetter); | |
| 3630 } | |
| 3631 | |
| 3632 my $indexedSetterFunction = GetIndexedSetterFunction($interface); | |
| 3633 if ($indexedSetterFunction) { | |
| 3634 AddIncludesForType($indexedSetterFunction->parameters->[1]->type); # in
cludes for argument type even if custom | |
| 3635 my $hasCustomIndexedSetter = $indexedSetterFunction->extendedAttributes-
>{"Custom"}; | |
| 3636 if (!$hasCustomIndexedSetter) { | |
| 3637 GenerateImplementationIndexedPropertySetter($interface, $indexedSett
erFunction); | |
| 3638 } | |
| 3639 GenerateImplementationIndexedPropertySetterCallback($interface, $hasCust
omIndexedSetter); | |
| 3640 } | |
| 3641 | |
| 3642 my $indexedDeleterFunction = GetIndexedDeleterFunction($interface); | |
| 3643 if ($indexedDeleterFunction) { | |
| 3644 my $hasCustomIndexedDeleter = $indexedDeleterFunction->extendedAttribute
s->{"Custom"}; | |
| 3645 if (!$hasCustomIndexedDeleter) { | |
| 3646 GenerateImplementationIndexedPropertyDeleter($interface, $indexedDel
eterFunction); | |
| 3647 } | |
| 3648 GenerateImplementationIndexedPropertyDeleterCallback($interface, $hasCus
tomIndexedDeleter); | |
| 3649 } | |
| 3650 | |
| 3651 my $indexedEnumeratorFunction = $indexedGetterFunction; | |
| 3652 $indexedEnumeratorFunction = 0 if $indexedGetterFunction && $indexedGetterFu
nction->extendedAttributes->{"NotEnumerable"}; | |
| 3653 | |
| 3654 my $indexedQueryFunction = 0; | |
| 3655 # If there is an enumerator, there MUST be a query method to properly commun
icate property attributes. | |
| 3656 my $hasQuery = $indexedQueryFunction || $indexedEnumeratorFunction; | |
| 3657 | |
| 3658 my $setOn = "Instance"; | |
| 3659 | |
| 3660 # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallba
cks) and it's used on Window | |
| 3661 # instead of deleters or enumerators. In addition, the getter should be set
on prototype template, to | |
| 3662 # get implementation straight out of the Window prototype regardless of what
prototype is actually set | |
| 3663 # on the object. | |
| 3664 if ($interfaceName eq "Window") { | |
| 3665 $setOn = "Prototype"; | |
| 3666 } | |
| 3667 | |
| 3668 my $code = ""; | |
| 3669 if ($indexedGetterFunction || $indexedSetterFunction || $indexedDeleterFunct
ion || $indexedEnumeratorFunction || $hasQuery) { | |
| 3670 $code .= " functionTemplate->${setOn}Template()->SetIndexedPropertyHa
ndler(${implClassName}V8Internal::indexedPropertyGetterCallback"; | |
| 3671 $code .= $indexedSetterFunction ? ", ${implClassName}V8Internal::indexed
PropertySetterCallback" : ", 0"; | |
| 3672 $code .= ", 0"; # IndexedPropertyQuery -- not being used at the moment. | |
| 3673 $code .= $indexedDeleterFunction ? ", ${implClassName}V8Internal::indexe
dPropertyDeleterCallback" : ", 0"; | |
| 3674 $code .= $indexedEnumeratorFunction ? ", indexedPropertyEnumerator<${imp
lClassName}>" : ", 0"; | |
| 3675 $code .= ");\n"; | |
| 3676 } | |
| 3677 | |
| 3678 return $code; | |
| 3679 } | |
| 3680 | |
| 3681 sub GenerateImplementationIndexedPropertyGetter | |
| 3682 { | |
| 3683 my $interface = shift; | |
| 3684 my $indexedGetterFunction = shift; | |
| 3685 my $implClassName = GetImplName($interface); | |
| 3686 my $v8ClassName = GetV8ClassName($interface); | |
| 3687 my $methodName = GetImplName($indexedGetterFunction) || "anonymousIndexedGet
ter"; | |
| 3688 my $interfaceName = $interface->name; | |
| 3689 | |
| 3690 my $returnType = $indexedGetterFunction->type; | |
| 3691 my $nativeType = GetNativeType($returnType); | |
| 3692 my $nativeValue = "result"; | |
| 3693 $nativeValue .= ".release()" if (IsRefPtrType($returnType)); | |
| 3694 my $isNull = GenerateIsNullExpression($returnType, "result"); | |
| 3695 my $returnJSValueCode = NativeToJSValue($indexedGetterFunction->type, $index
edGetterFunction->extendedAttributes, $nativeValue, " ", "", "info.GetIsolate
()", "info", "imp", "", "return"); | |
| 3696 my $raisesExceptions = $indexedGetterFunction->extendedAttributes->{"RaisesE
xception"}; | |
| 3697 my $methodCallCode = GenerateMethodCall($returnType, "result", "imp->${metho
dName}", "index", $raisesExceptions); | |
| 3698 my $getterCode = "static void indexedPropertyGetter(uint32_t index, const v8
::PropertyCallbackInfo<v8::Value>& info)\n"; | |
| 3699 $getterCode .= "{\n"; | |
| 3700 $getterCode .= " ${implClassName}* imp = ${v8ClassName}::toNative(info.Ho
lder());\n"; | |
| 3701 if ($raisesExceptions) { | |
| 3702 $getterCode .= " ExceptionState exceptionState(ExceptionState::Indexe
dGetterContext, \"${interfaceName}\", info.Holder(), info.GetIsolate());\n"; | |
| 3703 } | |
| 3704 $getterCode .= $methodCallCode . "\n"; | |
| 3705 if ($raisesExceptions) { | |
| 3706 $getterCode .= " if (exceptionState.throwIfNeeded())\n"; | |
| 3707 $getterCode .= " return;\n"; | |
| 3708 } | |
| 3709 if (IsUnionType($returnType)) { | |
| 3710 $getterCode .= "${returnJSValueCode}\n"; | |
| 3711 $getterCode .= " return;\n"; | |
| 3712 } else { | |
| 3713 $getterCode .= " if (${isNull})\n"; | |
| 3714 $getterCode .= " return;\n"; | |
| 3715 $getterCode .= $returnJSValueCode . "\n"; | |
| 3716 } | |
| 3717 $getterCode .= "}\n\n"; | |
| 3718 $implementation{nameSpaceInternal}->add($getterCode); | |
| 3719 } | |
| 3720 | |
| 3721 sub GenerateImplementationIndexedPropertyGetterCallback | |
| 3722 { | |
| 3723 my $interface = shift; | |
| 3724 my $hasCustom = shift; | |
| 3725 my $implClassName = GetImplName($interface); | |
| 3726 my $v8ClassName = GetV8ClassName($interface); | |
| 3727 | |
| 3728 my $code = "static void indexedPropertyGetterCallback(uint32_t index, const
v8::PropertyCallbackInfo<v8::Value>& info)\n"; | |
| 3729 $code .= "{\n"; | |
| 3730 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMIndexedProperty
\");\n"; | |
| 3731 if ($hasCustom) { | |
| 3732 $code .= " ${v8ClassName}::indexedPropertyGetterCustom(index, info);\
n"; | |
| 3733 } else { | |
| 3734 $code .= " ${implClassName}V8Internal::indexedPropertyGetter(index, i
nfo);\n"; | |
| 3735 } | |
| 3736 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n"; | |
| 3737 $code .= "}\n\n"; | |
| 3738 $implementation{nameSpaceInternal}->add($code); | |
| 3739 } | |
| 3740 | |
| 3741 sub GenerateImplementationIndexedPropertySetterCallback | |
| 3742 { | |
| 3743 my $interface = shift; | |
| 3744 my $hasCustom = shift; | |
| 3745 my $implClassName = GetImplName($interface); | |
| 3746 my $v8ClassName = GetV8ClassName($interface); | |
| 3747 | |
| 3748 my $code = "static void indexedPropertySetterCallback(uint32_t index, v8::Lo
cal<v8::Value> jsValue, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; | |
| 3749 $code .= "{\n"; | |
| 3750 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMIndexedProperty
\");\n"; | |
| 3751 if ($hasCustom) { | |
| 3752 $code .= " ${v8ClassName}::indexedPropertySetterCustom(index, jsValue
, info);\n"; | |
| 3753 } else { | |
| 3754 $code .= " ${implClassName}V8Internal::indexedPropertySetter(index, j
sValue, info);\n"; | |
| 3755 } | |
| 3756 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n"; | |
| 3757 $code .= "}\n\n"; | |
| 3758 $implementation{nameSpaceInternal}->add($code); | |
| 3759 } | |
| 3760 | |
| 3761 sub GenerateImplementationIndexedPropertyDeleterCallback | |
| 3762 { | |
| 3763 my $interface = shift; | |
| 3764 my $hasCustom = shift; | |
| 3765 my $implClassName = GetImplName($interface); | |
| 3766 my $v8ClassName = GetV8ClassName($interface); | |
| 3767 | |
| 3768 my $code = "static void indexedPropertyDeleterCallback(uint32_t index, const
v8::PropertyCallbackInfo<v8::Boolean>& info)\n"; | |
| 3769 $code .= "{\n"; | |
| 3770 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMIndexedProperty
\");\n"; | |
| 3771 if ($hasCustom) { | |
| 3772 $code .= " ${v8ClassName}::indexedPropertyDeleterCustom(index, info);
\n"; | |
| 3773 } else { | |
| 3774 $code .= " ${implClassName}V8Internal::indexedPropertyDeleter(index,
info);\n"; | |
| 3775 } | |
| 3776 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n"; | |
| 3777 $code .= "}\n\n"; | |
| 3778 $implementation{nameSpaceInternal}->add($code); | |
| 3779 } | |
| 3780 | |
| 3781 sub GenerateImplementationIndexedPropertySetter | |
| 3782 { | |
| 3783 my $interface = shift; | |
| 3784 my $indexedSetterFunction = shift; | |
| 3785 my $implClassName = GetImplName($interface); | |
| 3786 my $v8ClassName = GetV8ClassName($interface); | |
| 3787 my $methodName = GetImplName($indexedSetterFunction) || "anonymousIndexedSet
ter"; | |
| 3788 my $interfaceName = $interface->name; | |
| 3789 | |
| 3790 my $type = $indexedSetterFunction->parameters->[1]->type; | |
| 3791 my $raisesExceptions = $indexedSetterFunction->extendedAttributes->{"RaisesE
xception"}; | |
| 3792 my $treatNullAs = $indexedSetterFunction->parameters->[1]->extendedAttribute
s->{"TreatNullAs"}; | |
| 3793 my $treatUndefinedAs = $indexedSetterFunction->parameters->[1]->extendedAttr
ibutes->{"TreatUndefinedAs"}; | |
| 3794 | |
| 3795 my $code = "static void indexedPropertySetter(uint32_t index, v8::Local<v8::
Value> jsValue, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; | |
| 3796 $code .= "{\n"; | |
| 3797 | |
| 3798 my $asSetterValue = 0; | |
| 3799 $code .= " ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()
);\n"; | |
| 3800 $code .= JSValueToNativeStatement($indexedSetterFunction->parameters->[1]->t
ype, $indexedSetterFunction->extendedAttributes, $asSetterValue, "jsValue", "pro
pertyValue", " ", "info.GetIsolate()"); | |
| 3801 | |
| 3802 my $extraArguments = ""; | |
| 3803 if ($raisesExceptions || IsIntegerType($type)) { | |
| 3804 $code .= " ExceptionState exceptionState(ExceptionState::IndexedSette
rContext, \"${interfaceName}\", info.Holder(), info.GetIsolate());\n"; | |
| 3805 if ($raisesExceptions) { | |
| 3806 $extraArguments = ", exceptionState"; | |
| 3807 } | |
| 3808 } | |
| 3809 | |
| 3810 if ($indexedSetterFunction->extendedAttributes->{"StrictTypeChecking"} && Is
WrapperType($type)) { | |
| 3811 $code .= <<END; | |
| 3812 if (!isUndefinedOrNull(jsValue) && !V8${type}::hasInstance(jsValue, info.Get
Isolate())) { | |
| 3813 exceptionState.throwTypeError("The provided value is not of type '$type'
."); | |
| 3814 exceptionState.throwIfNeeded(); | |
| 3815 return; | |
| 3816 } | |
| 3817 END | |
| 3818 } | |
| 3819 | |
| 3820 $code .= " bool result = imp->${methodName}(index, propertyValue$extraArg
uments);\n"; | |
| 3821 | |
| 3822 if ($raisesExceptions) { | |
| 3823 $code .= " if (exceptionState.throwIfNeeded())\n"; | |
| 3824 $code .= " return;\n"; | |
| 3825 } | |
| 3826 $code .= " if (!result)\n"; | |
| 3827 $code .= " return;\n"; | |
| 3828 $code .= " v8SetReturnValue(info, jsValue);\n"; | |
| 3829 $code .= "}\n\n"; | |
| 3830 $implementation{nameSpaceInternal}->add($code); | |
| 3831 } | |
| 3832 | |
| 3833 sub GenerateImplementationNamedPropertyAccessors | |
| 3834 { | |
| 3835 my $interface = shift; | |
| 3836 | |
| 3837 my $interfaceName = $interface->name; | |
| 3838 my $implClassName = GetImplName($interface); | |
| 3839 my $v8ClassName = GetV8ClassName($interface); | |
| 3840 | |
| 3841 my $namedGetterFunction = GetNamedGetterFunction($interface); | |
| 3842 my $namedEnumeratorFunction = $namedGetterFunction && !$namedGetterFunction-
>extendedAttributes->{"NotEnumerable"}; | |
| 3843 | |
| 3844 if ($namedGetterFunction) { | |
| 3845 # includes for return type even if custom | |
| 3846 my $returnType = $namedGetterFunction->type; | |
| 3847 AddIncludesForType($returnType); | |
| 3848 my $hasCustomNamedGetter = HasCustomPropertyGetter($namedGetterFunction-
>extendedAttributes); | |
| 3849 if (!$hasCustomNamedGetter) { | |
| 3850 GenerateImplementationNamedPropertyGetter($interface, $namedGetterFu
nction); | |
| 3851 } | |
| 3852 GenerateImplementationNamedPropertyGetterCallback($interface, $hasCustom
NamedGetter); | |
| 3853 } | |
| 3854 | |
| 3855 my $namedSetterFunction = GetNamedSetterFunction($interface); | |
| 3856 if ($namedSetterFunction) { | |
| 3857 AddIncludesForType($namedSetterFunction->parameters->[1]->type); # incl
udes for argument type even if custom | |
| 3858 my $hasCustomNamedSetter = $namedSetterFunction->extendedAttributes->{"C
ustom"}; | |
| 3859 if (!$hasCustomNamedSetter) { | |
| 3860 GenerateImplementationNamedPropertySetter($interface, $namedSetterFu
nction); | |
| 3861 } | |
| 3862 GenerateImplementationNamedPropertySetterCallback($interface, $hasCustom
NamedSetter); | |
| 3863 } | |
| 3864 | |
| 3865 if ($namedEnumeratorFunction) { | |
| 3866 my $hasCustomNamedQuery = ExtendedAttributeContains($namedGetterFunction
->extendedAttributes->{"Custom"}, "PropertyQuery"); | |
| 3867 if (!$hasCustomNamedQuery) { | |
| 3868 GenerateImplementationNamedPropertyQuery($interface); | |
| 3869 } | |
| 3870 GenerateImplementationNamedPropertyQueryCallback($interface, $hasCustomN
amedQuery); | |
| 3871 } | |
| 3872 | |
| 3873 my $namedDeleterFunction = GetNamedDeleterFunction($interface); | |
| 3874 if ($namedDeleterFunction) { | |
| 3875 my $hasCustomNamedDeleter = $namedDeleterFunction->extendedAttributes->{
"Custom"}; | |
| 3876 if (!$hasCustomNamedDeleter) { | |
| 3877 GenerateImplementationNamedPropertyDeleter($interface, $namedDeleter
Function); | |
| 3878 } | |
| 3879 GenerateImplementationNamedPropertyDeleterCallback($interface, $hasCusto
mNamedDeleter); | |
| 3880 } | |
| 3881 | |
| 3882 if ($namedEnumeratorFunction) { | |
| 3883 my $hasCustomNamedEnumerator = ExtendedAttributeContains($namedGetterFun
ction->extendedAttributes->{"Custom"}, "PropertyEnumerator"); | |
| 3884 if (!$hasCustomNamedEnumerator) { | |
| 3885 GenerateImplementationNamedPropertyEnumerator($interface); | |
| 3886 } | |
| 3887 GenerateImplementationNamedPropertyEnumeratorCallback($interface, $hasCu
stomNamedEnumerator); | |
| 3888 } | |
| 3889 | |
| 3890 my $subCode = ""; | |
| 3891 if ($namedGetterFunction || $namedSetterFunction || $namedDeleterFunction ||
$namedEnumeratorFunction) { | |
| 3892 my $setOn = "Instance"; | |
| 3893 | |
| 3894 # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCa
llbacks) and it's used on Window | |
| 3895 # instead of deleters or enumerators. In addition, the getter should be
set on prototype template, to | |
| 3896 # get implementation straight out of the Window prototype regardless of
what prototype is actually set | |
| 3897 # on the object. | |
| 3898 if ($interfaceName eq "Window") { | |
| 3899 $setOn = "Prototype"; | |
| 3900 } | |
| 3901 | |
| 3902 $subCode .= " functionTemplate->${setOn}Template()->SetNamedPropertyH
andler("; | |
| 3903 $subCode .= $namedGetterFunction ? "${implClassName}V8Internal::namedPro
pertyGetterCallback, " : "0, "; | |
| 3904 $subCode .= $namedSetterFunction ? "${implClassName}V8Internal::namedPro
pertySetterCallback, " : "0, "; | |
| 3905 $subCode .= $namedEnumeratorFunction ? "${implClassName}V8Internal::name
dPropertyQueryCallback, " : "0, "; | |
| 3906 $subCode .= $namedDeleterFunction ? "${implClassName}V8Internal::namedPr
opertyDeleterCallback, " : "0, "; | |
| 3907 $subCode .= $namedEnumeratorFunction ? "${implClassName}V8Internal::name
dPropertyEnumeratorCallback" : "0"; | |
| 3908 $subCode .= ");\n"; | |
| 3909 } | |
| 3910 | |
| 3911 return $subCode; | |
| 3912 } | |
| 3913 | |
| 3914 sub GenerateImplementationNamedPropertyGetterCallback | |
| 3915 { | |
| 3916 my $interface = shift; | |
| 3917 my $hasCustom = shift; | |
| 3918 my $implClassName = GetImplName($interface); | |
| 3919 my $v8ClassName = GetV8ClassName($interface); | |
| 3920 | |
| 3921 my $code = "static void namedPropertyGetterCallback(v8::Local<v8::String> na
me, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; | |
| 3922 $code .= "{\n"; | |
| 3923 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\"
);\n"; | |
| 3924 if ($hasCustom) { | |
| 3925 $code .= " ${v8ClassName}::namedPropertyGetterCustom(name, info);\n"; | |
| 3926 } else { | |
| 3927 $code .= " ${implClassName}V8Internal::namedPropertyGetter(name, info
);\n"; | |
| 3928 } | |
| 3929 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n"; | |
| 3930 $code .= "}\n\n"; | |
| 3931 $implementation{nameSpaceInternal}->add($code); | |
| 3932 } | |
| 3933 | |
| 3934 sub GenerateImplementationNamedPropertySetterCallback | |
| 3935 { | |
| 3936 my $interface = shift; | |
| 3937 my $hasCustom = shift; | |
| 3938 my $implClassName = GetImplName($interface); | |
| 3939 my $v8ClassName = GetV8ClassName($interface); | |
| 3940 | |
| 3941 my $code = "static void namedPropertySetterCallback(v8::Local<v8::String> na
me, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<v8::Value>& inf
o)\n"; | |
| 3942 $code .= "{\n"; | |
| 3943 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\"
);\n"; | |
| 3944 if ($hasCustom) { | |
| 3945 $code .= " ${v8ClassName}::namedPropertySetterCustom(name, jsValue, i
nfo);\n"; | |
| 3946 } else { | |
| 3947 $code .= " ${implClassName}V8Internal::namedPropertySetter(name, jsVa
lue, info);\n"; | |
| 3948 } | |
| 3949 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n"; | |
| 3950 $code .= "}\n\n"; | |
| 3951 $implementation{nameSpaceInternal}->add($code); | |
| 3952 } | |
| 3953 | |
| 3954 sub GenerateImplementationNamedPropertyDeleterCallback | |
| 3955 { | |
| 3956 my $interface = shift; | |
| 3957 my $hasCustom = shift; | |
| 3958 my $implClassName = GetImplName($interface); | |
| 3959 my $v8ClassName = GetV8ClassName($interface); | |
| 3960 | |
| 3961 my $code = "static void namedPropertyDeleterCallback(v8::Local<v8::String> n
ame, const v8::PropertyCallbackInfo<v8::Boolean>& info)\n"; | |
| 3962 $code .= "{\n"; | |
| 3963 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\"
);\n"; | |
| 3964 if ($hasCustom) { | |
| 3965 $code .= " ${v8ClassName}::namedPropertyDeleterCustom(name, info);\n"
; | |
| 3966 } else { | |
| 3967 $code .= " ${implClassName}V8Internal::namedPropertyDeleter(name, inf
o);\n"; | |
| 3968 } | |
| 3969 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n"; | |
| 3970 $code .= "}\n\n"; | |
| 3971 $implementation{nameSpaceInternal}->add($code); | |
| 3972 } | |
| 3973 | |
| 3974 sub GenerateImplementationNamedPropertyEnumeratorCallback | |
| 3975 { | |
| 3976 my $interface = shift; | |
| 3977 my $hasCustom = shift; | |
| 3978 my $implClassName = GetImplName($interface); | |
| 3979 my $v8ClassName = GetV8ClassName($interface); | |
| 3980 | |
| 3981 my $code = "static void namedPropertyEnumeratorCallback(const v8::PropertyCa
llbackInfo<v8::Array>& info)\n"; | |
| 3982 $code .= "{\n"; | |
| 3983 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\"
);\n"; | |
| 3984 if ($hasCustom) { | |
| 3985 $code .= " ${v8ClassName}::namedPropertyEnumeratorCustom(info);\n"; | |
| 3986 } else { | |
| 3987 $code .= " ${implClassName}V8Internal::namedPropertyEnumerator(info);
\n"; | |
| 3988 } | |
| 3989 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n"; | |
| 3990 $code .= "}\n\n"; | |
| 3991 $implementation{nameSpaceInternal}->add($code); | |
| 3992 } | |
| 3993 | |
| 3994 sub GenerateImplementationNamedPropertyQueryCallback | |
| 3995 { | |
| 3996 my $interface = shift; | |
| 3997 my $hasCustom = shift; | |
| 3998 my $implClassName = GetImplName($interface); | |
| 3999 my $v8ClassName = GetV8ClassName($interface); | |
| 4000 | |
| 4001 my $code = "static void namedPropertyQueryCallback(v8::Local<v8::String> nam
e, const v8::PropertyCallbackInfo<v8::Integer>& info)\n"; | |
| 4002 $code .= "{\n"; | |
| 4003 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\"
);\n"; | |
| 4004 if ($hasCustom) { | |
| 4005 $code .= " ${v8ClassName}::namedPropertyQueryCustom(name, info);\n"; | |
| 4006 } else { | |
| 4007 $code .= " ${implClassName}V8Internal::namedPropertyQuery(name, info)
;\n"; | |
| 4008 } | |
| 4009 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n"; | |
| 4010 $code .= "}\n\n"; | |
| 4011 $implementation{nameSpaceInternal}->add($code); | |
| 4012 } | |
| 4013 | |
| 4014 sub GenerateMethodCall | |
| 4015 { | |
| 4016 my $returnType = shift; # string or UnionType | |
| 4017 my $returnName = shift; | |
| 4018 my $functionExpression = shift; | |
| 4019 my $firstArgument = shift; | |
| 4020 my $raisesExceptions = shift; | |
| 4021 | |
| 4022 my @arguments = (); | |
| 4023 push @arguments, $firstArgument; | |
| 4024 if ($raisesExceptions) { | |
| 4025 push @arguments, "exceptionState"; | |
| 4026 } | |
| 4027 | |
| 4028 if (IsUnionType($returnType)) { | |
| 4029 my $code = ""; | |
| 4030 my @extraArguments = (); | |
| 4031 for my $i (0..scalar(@{$returnType->unionMemberTypes})-1) { | |
| 4032 my $unionMemberType = $returnType->unionMemberTypes->[$i]; | |
| 4033 my $nativeType = GetNativeType($unionMemberType); | |
| 4034 my $unionMemberVariable = $returnName . $i; | |
| 4035 my $unionMemberEnabledVariable = $returnName . $i . "Enabled"; | |
| 4036 $code .= " bool ${unionMemberEnabledVariable} = false;\n"; | |
| 4037 $code .= " ${nativeType} ${unionMemberVariable};\n"; | |
| 4038 push @extraArguments, $unionMemberEnabledVariable; | |
| 4039 push @extraArguments, $unionMemberVariable; | |
| 4040 } | |
| 4041 push @arguments, @extraArguments; | |
| 4042 $code .= " ${functionExpression}(" . (join ", ", @arguments) . ");"; | |
| 4043 return $code; | |
| 4044 } else { | |
| 4045 my $nativeType = GetNativeType($returnType); | |
| 4046 return " ${nativeType} result = ${functionExpression}(" . (join ", ",
@arguments) . ");" | |
| 4047 } | |
| 4048 } | |
| 4049 | |
| 4050 sub GenerateImplementationNamedPropertyGetter | |
| 4051 { | |
| 4052 my $interface = shift; | |
| 4053 my $namedGetterFunction = shift; | |
| 4054 my $implClassName = GetImplName($interface); | |
| 4055 my $v8ClassName = GetV8ClassName($interface); | |
| 4056 my $methodName = GetImplName($namedGetterFunction) || "anonymousNamedGetter"
; | |
| 4057 my $interfaceName = $interface->name; | |
| 4058 | |
| 4059 my $returnType = $namedGetterFunction->type; | |
| 4060 my $isNull = GenerateIsNullExpression($returnType, "result"); | |
| 4061 my $nativeValue = "result"; | |
| 4062 $nativeValue .= ".release()" if (IsRefPtrType($returnType)); | |
| 4063 my $returnJSValueCode = NativeToJSValue($namedGetterFunction->type, $namedGe
tterFunction->extendedAttributes, $nativeValue, " ", "", "info.GetIsolate()",
"info", "imp", "", "return"); | |
| 4064 my $raisesExceptions = $namedGetterFunction->extendedAttributes->{"RaisesExc
eption"}; | |
| 4065 my $methodCallCode = GenerateMethodCall($returnType, "result", "imp->${metho
dName}", "propertyName", $raisesExceptions); | |
| 4066 | |
| 4067 my $code = "static void namedPropertyGetter(v8::Local<v8::String> name, cons
t v8::PropertyCallbackInfo<v8::Value>& info)\n"; | |
| 4068 $code .= "{\n"; | |
| 4069 if (!$interface->extendedAttributes->{"OverrideBuiltins"}) { | |
| 4070 $code .= " if (info.Holder()->HasRealNamedProperty(name))\n"; | |
| 4071 $code .= " return;\n"; | |
| 4072 $code .= " if (!info.Holder()->GetRealNamedPropertyInPrototypeChain(n
ame).IsEmpty())\n"; | |
| 4073 $code .= " return;\n"; | |
| 4074 $code .= "\n"; | |
| 4075 } | |
| 4076 $code .= " ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()
);\n"; | |
| 4077 $code .= " AtomicString propertyName = toCoreAtomicString(name);\n"; | |
| 4078 if ($raisesExceptions) { | |
| 4079 $code .= " v8::String::Utf8Value namedProperty(name);\n"; | |
| 4080 $code .= " ExceptionState exceptionState(ExceptionState::GetterContex
t, *namedProperty, \"${interfaceName}\", info.Holder(), info.GetIsolate());\n"; | |
| 4081 } | |
| 4082 $code .= $methodCallCode . "\n"; | |
| 4083 if ($raisesExceptions) { | |
| 4084 $code .= " if (exceptionState.throwIfNeeded())\n"; | |
| 4085 $code .= " return;\n"; | |
| 4086 } | |
| 4087 $code .= " if (${isNull})\n"; | |
| 4088 $code .= " return;\n"; | |
| 4089 $code .= $returnJSValueCode . "\n"; | |
| 4090 $code .= "}\n\n"; | |
| 4091 $implementation{nameSpaceInternal}->add($code); | |
| 4092 } | |
| 4093 | |
| 4094 sub GenerateImplementationNamedPropertySetter | |
| 4095 { | |
| 4096 my $interface = shift; | |
| 4097 my $namedSetterFunction = shift; | |
| 4098 my $implClassName = GetImplName($interface); | |
| 4099 my $v8ClassName = GetV8ClassName($interface); | |
| 4100 my $methodName = GetImplName($namedSetterFunction) || "anonymousNamedSetter"
; | |
| 4101 my $interfaceName = $interface->name; | |
| 4102 | |
| 4103 my $type = $namedSetterFunction->parameters->[1]->type; | |
| 4104 my $raisesExceptions = $namedSetterFunction->extendedAttributes->{"RaisesExc
eption"}; | |
| 4105 my $treatNullAs = $namedSetterFunction->parameters->[1]->extendedAttributes-
>{"TreatNullAs"}; | |
| 4106 my $treatUndefinedAs = $namedSetterFunction->parameters->[1]->extendedAttrib
utes->{"TreatUndefinedAs"}; | |
| 4107 | |
| 4108 my $code = "static void namedPropertySetter(v8::Local<v8::String> name, v8::
Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; | |
| 4109 $code .= "{\n"; | |
| 4110 if (!$interface->extendedAttributes->{"OverrideBuiltins"}) { | |
| 4111 $code .= " if (info.Holder()->HasRealNamedProperty(name))\n"; | |
| 4112 $code .= " return;\n"; | |
| 4113 $code .= " if (!info.Holder()->GetRealNamedPropertyInPrototypeChain(n
ame).IsEmpty())\n"; | |
| 4114 $code .= " return;\n"; | |
| 4115 $code .= "\n"; | |
| 4116 } | |
| 4117 | |
| 4118 my $asSetterValue = 0; | |
| 4119 $code .= " ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()
);\n"; | |
| 4120 $code .= JSValueToNativeStatement($namedSetterFunction->parameters->[0]->typ
e, $namedSetterFunction->extendedAttributes, $asSetterValue, "name", "propertyNa
me", " ", "info.GetIsolate()"); | |
| 4121 $code .= JSValueToNativeStatement($namedSetterFunction->parameters->[1]->typ
e, $namedSetterFunction->extendedAttributes, $asSetterValue, "jsValue", "propert
yValue", " ", "info.GetIsolate()"); | |
| 4122 | |
| 4123 my $extraArguments = ""; | |
| 4124 if ($raisesExceptions || IsIntegerType($type)) { | |
| 4125 $code .= " v8::String::Utf8Value namedProperty(name);\n"; | |
| 4126 $code .= " ExceptionState exceptionState(ExceptionState::SetterContex
t, *namedProperty, \"${interfaceName}\", info.Holder(), info.GetIsolate());\n"; | |
| 4127 if ($raisesExceptions) { | |
| 4128 $extraArguments = ", exceptionState"; | |
| 4129 } | |
| 4130 } | |
| 4131 | |
| 4132 $code .= " bool result = imp->$methodName(propertyName, propertyValue$ext
raArguments);\n"; | |
| 4133 if ($raisesExceptions) { | |
| 4134 $code .= " if (exceptionState.throwIfNeeded())\n"; | |
| 4135 $code .= " return;\n"; | |
| 4136 } | |
| 4137 $code .= " if (!result)\n"; | |
| 4138 $code .= " return;\n"; | |
| 4139 $code .= " v8SetReturnValue(info, jsValue);\n"; | |
| 4140 $code .= "}\n\n"; | |
| 4141 $implementation{nameSpaceInternal}->add($code); | |
| 4142 } | |
| 4143 | |
| 4144 sub GenerateImplementationIndexedPropertyDeleter | |
| 4145 { | |
| 4146 my $interface = shift; | |
| 4147 my $indexedDeleterFunction = shift; | |
| 4148 my $implClassName = GetImplName($interface); | |
| 4149 my $v8ClassName = GetV8ClassName($interface); | |
| 4150 my $methodName = GetImplName($indexedDeleterFunction) || "anonymousIndexedDe
leter"; | |
| 4151 my $interfaceName = $interface->name; | |
| 4152 | |
| 4153 my $raisesExceptions = $indexedDeleterFunction->extendedAttributes->{"Raises
Exception"}; | |
| 4154 | |
| 4155 my $code = "static void indexedPropertyDeleter(uint32_t index, const v8::Pro
pertyCallbackInfo<v8::Boolean>& info)\n"; | |
| 4156 $code .= "{\n"; | |
| 4157 $code .= " ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()
);\n"; | |
| 4158 my $extraArguments = ""; | |
| 4159 if ($raisesExceptions) { | |
| 4160 $code .= " ExceptionState exceptionState(ExceptionState::IndexedDelet
ionContext, \"${interfaceName}\", info.Holder(), info.GetIsolate());\n"; | |
| 4161 $extraArguments = ", exceptionState"; | |
| 4162 } | |
| 4163 $code .= " DeleteResult result = imp->${methodName}(index$extraArguments)
;\n"; | |
| 4164 if ($raisesExceptions) { | |
| 4165 $code .= " if (exceptionState.throwIfNeeded())\n"; | |
| 4166 $code .= " return;\n"; | |
| 4167 } | |
| 4168 $code .= " if (result != DeleteUnknownProperty)\n"; | |
| 4169 $code .= " return v8SetReturnValueBool(info, result == DeleteSuccess)
;\n"; | |
| 4170 $code .= "}\n\n"; | |
| 4171 $implementation{nameSpaceInternal}->add($code); | |
| 4172 } | |
| 4173 | |
| 4174 sub GenerateImplementationNamedPropertyDeleter | |
| 4175 { | |
| 4176 my $interface = shift; | |
| 4177 my $namedDeleterFunction = shift; | |
| 4178 my $implClassName = GetImplName($interface); | |
| 4179 my $v8ClassName = GetV8ClassName($interface); | |
| 4180 my $methodName = GetImplName($namedDeleterFunction) || "anonymousNamedDelete
r"; | |
| 4181 my $interfaceName = $interface->name; | |
| 4182 | |
| 4183 my $raisesExceptions = $namedDeleterFunction->extendedAttributes->{"RaisesEx
ception"}; | |
| 4184 | |
| 4185 my $code = "static void namedPropertyDeleter(v8::Local<v8::String> name, con
st v8::PropertyCallbackInfo<v8::Boolean>& info)\n"; | |
| 4186 $code .= "{\n"; | |
| 4187 $code .= " ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()
);\n"; | |
| 4188 $code .= " AtomicString propertyName = toCoreAtomicString(name);\n"; | |
| 4189 my $extraArguments = ""; | |
| 4190 if ($raisesExceptions) { | |
| 4191 $code .= " v8::String::Utf8Value namedProperty(name);\n"; | |
| 4192 $code .= " ExceptionState exceptionState(ExceptionState::DeletionCont
ext, *namedProperty, \"${interfaceName}\", info.Holder(), info.GetIsolate());\n"
; | |
| 4193 $extraArguments .= ", exceptionState"; | |
| 4194 } | |
| 4195 $code .= " DeleteResult result = imp->${methodName}(propertyName$extraArg
uments);\n"; | |
| 4196 if ($raisesExceptions) { | |
| 4197 $code .= " if (exceptionState.throwIfNeeded())\n"; | |
| 4198 $code .= " return;\n"; | |
| 4199 } | |
| 4200 $code .= " if (result != DeleteUnknownProperty)\n"; | |
| 4201 $code .= " return v8SetReturnValueBool(info, result == DeleteSuccess)
;\n"; | |
| 4202 $code .= "}\n\n"; | |
| 4203 $implementation{nameSpaceInternal}->add($code); | |
| 4204 } | |
| 4205 | |
| 4206 sub GenerateImplementationNamedPropertyEnumerator | |
| 4207 { | |
| 4208 my $interface = shift; | |
| 4209 my $implClassName = GetImplName($interface); | |
| 4210 my $v8ClassName = GetV8ClassName($interface); | |
| 4211 my $interfaceName = $interface->name; | |
| 4212 | |
| 4213 $implementation{nameSpaceInternal}->add(<<END); | |
| 4214 static void namedPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& i
nfo) | |
| 4215 { | |
| 4216 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()); | |
| 4217 Vector<String> names; | |
| 4218 ExceptionState exceptionState(ExceptionState::EnumerationContext, \"${interf
aceName}\", info.Holder(), info.GetIsolate()); | |
| 4219 imp->namedPropertyEnumerator(names, exceptionState); | |
| 4220 if (exceptionState.throwIfNeeded()) | |
| 4221 return; | |
| 4222 v8::Handle<v8::Array> v8names = v8::Array::New(info.GetIsolate(), names.size
()); | |
| 4223 for (size_t i = 0; i < names.size(); ++i) | |
| 4224 v8names->Set(v8::Integer::New(info.GetIsolate(), i), v8String(info.GetIs
olate(), names[i])); | |
| 4225 v8SetReturnValue(info, v8names); | |
| 4226 } | |
| 4227 | |
| 4228 END | |
| 4229 } | |
| 4230 | |
| 4231 sub GenerateImplementationNamedPropertyQuery | |
| 4232 { | |
| 4233 my $interface = shift; | |
| 4234 my $implClassName = GetImplName($interface); | |
| 4235 my $v8ClassName = GetV8ClassName($interface); | |
| 4236 my $interfaceName = $interface->name; | |
| 4237 | |
| 4238 $implementation{nameSpaceInternal}->add(<<END); | |
| 4239 static void namedPropertyQuery(v8::Local<v8::String> name, const v8::PropertyCal
lbackInfo<v8::Integer>& info) | |
| 4240 { | |
| 4241 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()); | |
| 4242 AtomicString propertyName = toCoreAtomicString(name); | |
| 4243 v8::String::Utf8Value namedProperty(name); | |
| 4244 ExceptionState exceptionState(ExceptionState::GetterContext, *namedProperty,
"${interfaceName}", info.Holder(), info.GetIsolate()); | |
| 4245 bool result = imp->namedPropertyQuery(propertyName, exceptionState); | |
| 4246 if (exceptionState.throwIfNeeded()) | |
| 4247 return; | |
| 4248 if (!result) | |
| 4249 return; | |
| 4250 v8SetReturnValueInt(info, v8::None); | |
| 4251 } | |
| 4252 | |
| 4253 END | |
| 4254 } | |
| 4255 | |
| 4256 sub GenerateImplementationLegacyCallAsFunction | |
| 4257 { | |
| 4258 my $interface = shift; | |
| 4259 my $code = ""; | |
| 4260 | |
| 4261 my $v8ClassName = GetV8ClassName($interface); | |
| 4262 | |
| 4263 if (ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "L
egacyCallAsFunction")) { | |
| 4264 $code .= " functionTemplate->InstanceTemplate()->SetCallAsFunctionHan
dler(${v8ClassName}::legacyCallCustom);\n"; | |
| 4265 } | |
| 4266 return $code; | |
| 4267 } | |
| 4268 | |
| 4269 sub GenerateImplementationMarkAsUndetectable | |
| 4270 { | |
| 4271 my $interface = shift; | |
| 4272 my $code = ""; | |
| 4273 | |
| 4274 # Needed for legacy support of document.all | |
| 4275 if ($interface->name eq "HTMLAllCollection") | |
| 4276 { | |
| 4277 $code .= " functionTemplate->InstanceTemplate()->MarkAsUndetectable()
;\n"; | |
| 4278 } | |
| 4279 return $code; | |
| 4280 } | |
| 4281 | |
| 4282 sub GenerateImplementation | |
| 4283 { | |
| 4284 my $object = shift; | |
| 4285 my $interface = shift; | |
| 4286 my $interfaceName = $interface->name; | |
| 4287 my $implClassName = GetImplName($interface); | |
| 4288 my $v8ClassName = GetV8ClassName($interface); | |
| 4289 my $nativeType = GetNativeTypeForConversions($interface); | |
| 4290 | |
| 4291 AddToImplIncludes("RuntimeEnabledFeatures.h"); | |
| 4292 AddToImplIncludes("bindings/v8/ExceptionState.h"); | |
| 4293 AddToImplIncludes("core/dom/ContextFeatures.h"); | |
| 4294 AddToImplIncludes("core/dom/Document.h"); | |
| 4295 AddToImplIncludes("platform/TraceEvent.h"); | |
| 4296 AddToImplIncludes("wtf/GetPtr.h"); | |
| 4297 AddToImplIncludes("wtf/RefPtr.h"); | |
| 4298 | |
| 4299 AddIncludesForType($interfaceName); | |
| 4300 if ($interface->extendedAttributes->{"CheckSecurity"}) { | |
| 4301 AddToImplIncludes("bindings/v8/BindingSecurity.h"); | |
| 4302 } | |
| 4303 | |
| 4304 my $toActiveDOMObject = InheritsExtendedAttribute($interface, "ActiveDOMObje
ct") ? "${v8ClassName}::toActiveDOMObject" : "0"; | |
| 4305 my $toEventTarget = InheritsInterface($interface, "EventTarget") ? "${v8Clas
sName}::toEventTarget" : "0"; | |
| 4306 my $visitDOMWrapper = NeedsVisitDOMWrapper($interface) ? "${v8ClassName}::vi
sitDOMWrapper" : "0"; | |
| 4307 my $derefObject = "${v8ClassName}::derefObject"; | |
| 4308 | |
| 4309 # Find the super descriptor. | |
| 4310 my $parentClass = ""; | |
| 4311 my $parentClassTemplate = ""; | |
| 4312 if ($interface->parent) { | |
| 4313 my $parent = $interface->parent; | |
| 4314 $parentClass = "V8" . $parent; | |
| 4315 $parentClassTemplate = $parentClass . "::domTemplate(isolate, currentWor
ldType)"; | |
| 4316 } | |
| 4317 | |
| 4318 my $parentClassInfo = $parentClass ? "&${parentClass}::wrapperTypeInfo" : "0
"; | |
| 4319 my $WrapperTypePrototype = $interface->isException ? "WrapperTypeExceptionPr
ototype" : "WrapperTypeObjectPrototype"; | |
| 4320 | |
| 4321 if (!IsSVGTypeNeedingTearOff($interfaceName)) { | |
| 4322 my $code = <<END; | |
| 4323 static void initializeScriptWrappableForInterface(${implClassName}* object) | |
| 4324 { | |
| 4325 if (ScriptWrappable::wrapperCanBeStoredInObject(object)) | |
| 4326 ScriptWrappable::setTypeInfoInObject(object, &${v8ClassName}::wrapperTyp
eInfo); | |
| 4327 else | |
| 4328 ASSERT_NOT_REACHED(); | |
| 4329 } | |
| 4330 | |
| 4331 } // namespace WebCore | |
| 4332 | |
| 4333 // In ScriptWrappable::init, the use of a local function declaration has an issu
e on Windows: | |
| 4334 // the local declaration does not pick up the surrounding namespace. Therefore,
we provide this function | |
| 4335 // in the global namespace. | |
| 4336 // (More info on the MSVC bug here: http://connect.microsoft.com/VisualStudio/fe
edback/details/664619/the-namespace-of-local-function-declarations-in-c) | |
| 4337 END | |
| 4338 | |
| 4339 if (GetNamespaceForInterface($interface) eq "WebCore") { | |
| 4340 $code .= "void webCoreInitializeScriptWrappableForInterface(WebCore::${i
mplClassName}* object)\n"; | |
| 4341 } else { | |
| 4342 $code .= "void webCoreInitializeScriptWrappableForInterface(${implClassN
ame}* object)\n"; | |
| 4343 } | |
| 4344 | |
| 4345 $code .= <<END; | |
| 4346 { | |
| 4347 WebCore::initializeScriptWrappableForInterface(object); | |
| 4348 } | |
| 4349 | |
| 4350 namespace WebCore { | |
| 4351 END | |
| 4352 $implementation{nameSpaceWebCore}->addHeader($code); | |
| 4353 } | |
| 4354 | |
| 4355 my $code = "const WrapperTypeInfo ${v8ClassName}::wrapperTypeInfo = { gin::k
EmbedderBlink, ${v8ClassName}::domTemplate, $derefObject, $toActiveDOMObject, $t
oEventTarget, "; | |
| 4356 $code .= "$visitDOMWrapper, ${v8ClassName}::installPerContextEnabledMethods,
$parentClassInfo, $WrapperTypePrototype, "; | |
| 4357 $code .= IsWillBeGarbageCollectedType($interfaceName) ? "true" : "false"; | |
| 4358 $code .= " };\n"; | |
| 4359 $implementation{nameSpaceWebCore}->addHeader($code); | |
| 4360 | |
| 4361 $implementation{nameSpaceInternal}->add("template <typename T> void V8_USE(T
) { }\n\n"); | |
| 4362 | |
| 4363 my $hasConstructors = 0; | |
| 4364 my $hasReplaceable = 0; | |
| 4365 | |
| 4366 # Generate property accessors for attributes. | |
| 4367 for (my $index = 0; $index < @{$interface->attributes}; $index++) { | |
| 4368 my $attribute = @{$interface->attributes}[$index]; | |
| 4369 my $attrType = $attribute->type; | |
| 4370 my $attrExt = $attribute->extendedAttributes; | |
| 4371 | |
| 4372 # Generate special code for the constructor attributes. | |
| 4373 if ($attrType =~ /Constructor$/) { | |
| 4374 if (!HasCustomGetter($attrExt)) { | |
| 4375 $hasConstructors = 1; | |
| 4376 } | |
| 4377 next; | |
| 4378 } | |
| 4379 | |
| 4380 AddIncludesForType($attrType); | |
| 4381 | |
| 4382 if ($attrType eq "EventHandler" && $interfaceName eq "Window") { | |
| 4383 $attrExt->{"OnPrototype"} = 1; | |
| 4384 } | |
| 4385 | |
| 4386 if ($attrType eq "SerializedScriptValue") { | |
| 4387 AddToImplIncludes("bindings/v8/SerializedScriptValue.h"); | |
| 4388 } | |
| 4389 | |
| 4390 my $isReplaceable = 0; | |
| 4391 if (!HasCustomSetter($attribute) && !$attrExt->{"PutForwards"} && $attrE
xt->{"Replaceable"}) { | |
| 4392 $isReplaceable = 1; | |
| 4393 $hasReplaceable = 1; | |
| 4394 } | |
| 4395 | |
| 4396 my $exposeJSAccessors = $attrExt->{"ExposeJSAccessors"}; | |
| 4397 my @worldSuffixes = (""); | |
| 4398 if ($attrExt->{"PerWorldBindings"}) { | |
| 4399 push(@worldSuffixes, "ForMainWorld"); | |
| 4400 } | |
| 4401 foreach my $worldSuffix (@worldSuffixes) { | |
| 4402 GenerateNormalAttributeGetter($attribute, $interface, $worldSuffix,
$exposeJSAccessors); | |
| 4403 GenerateNormalAttributeGetterCallback($attribute, $interface, $world
Suffix, $exposeJSAccessors); | |
| 4404 if (!$isReplaceable && !IsReadonly($attribute)) { | |
| 4405 GenerateNormalAttributeSetter($attribute, $interface, $worldSuff
ix, $exposeJSAccessors); | |
| 4406 GenerateNormalAttributeSetterCallback($attribute, $interface, $w
orldSuffix, $exposeJSAccessors); | |
| 4407 } | |
| 4408 } | |
| 4409 } | |
| 4410 | |
| 4411 if ($hasConstructors) { | |
| 4412 GenerateConstructorGetter($interface); | |
| 4413 } | |
| 4414 | |
| 4415 if ($hasConstructors || $hasReplaceable) { | |
| 4416 GenerateReplaceableAttributeSetter($interface); | |
| 4417 GenerateReplaceableAttributeSetterCallback($interface); | |
| 4418 } | |
| 4419 | |
| 4420 if (NeedsVisitDOMWrapper($interface)) { | |
| 4421 GenerateVisitDOMWrapper($interface); | |
| 4422 } | |
| 4423 | |
| 4424 if ($interface->extendedAttributes->{"CheckSecurity"} && $interface->name ne
"Window") { | |
| 4425 GenerateSecurityCheckFunctions($interface); | |
| 4426 } | |
| 4427 | |
| 4428 my @perContextEnabledFunctions; | |
| 4429 my @normalFunctions; | |
| 4430 my $needsDomainSafeFunctionSetter = 0; | |
| 4431 # Generate methods for functions. | |
| 4432 foreach my $function (@{$interface->functions}) { | |
| 4433 next if $function->name eq ""; # Skip anonymous special operations | |
| 4434 my @worldSuffixes = (""); | |
| 4435 if ($function->extendedAttributes->{"PerWorldBindings"}) { | |
| 4436 push(@worldSuffixes, "ForMainWorld"); | |
| 4437 } | |
| 4438 foreach my $worldSuffix (@worldSuffixes) { | |
| 4439 GenerateFunction($function, $interface, $worldSuffix); | |
| 4440 if ($function->{overloadIndex} == @{$function->{overloads}}) { | |
| 4441 if ($function->{overloadIndex} > 1) { | |
| 4442 GenerateOverloadedFunction($function, $interface, $worldSuff
ix); | |
| 4443 } | |
| 4444 GenerateFunctionCallback($function, $interface, $worldSuffix); | |
| 4445 } | |
| 4446 | |
| 4447 # If the function does not need domain security check, we need to | |
| 4448 # generate an access getter that returns different function objects | |
| 4449 # for different calling context. | |
| 4450 if ($interface->extendedAttributes->{"CheckSecurity"} && $function->
extendedAttributes->{"DoNotCheckSecurity"} && (!HasCustomMethod($function->exten
dedAttributes) || $function->{overloadIndex} == 1)) { | |
| 4451 GenerateDomainSafeFunctionGetter($function, $interface, $worldSu
ffix); | |
| 4452 if (!$function->extendedAttributes->{"ReadOnly"}) { | |
| 4453 $needsDomainSafeFunctionSetter = 1; | |
| 4454 } | |
| 4455 } | |
| 4456 } | |
| 4457 | |
| 4458 # Separate out functions that are enabled per context so we can process
them specially. | |
| 4459 if ($function->extendedAttributes->{"PerContextEnabled"}) { | |
| 4460 push(@perContextEnabledFunctions, $function); | |
| 4461 } else { | |
| 4462 push(@normalFunctions, $function); | |
| 4463 } | |
| 4464 } | |
| 4465 | |
| 4466 if ($needsDomainSafeFunctionSetter) { | |
| 4467 GenerateDomainSafeFunctionSetter($interface); | |
| 4468 } | |
| 4469 | |
| 4470 # Attributes | |
| 4471 my $attributes = $interface->attributes; | |
| 4472 | |
| 4473 # For the Window interface we partition the attributes into the | |
| 4474 # ones that disallows shadowing and the rest. | |
| 4475 my @disallowsShadowing; | |
| 4476 # Also separate out attributes that are enabled at runtime so we can process
them specially. | |
| 4477 my @runtimeEnabledAttributes; | |
| 4478 my @perContextEnabledAttributes; | |
| 4479 my @normalAttributes; | |
| 4480 my @normalAccessors; | |
| 4481 my @staticAttributes; | |
| 4482 foreach my $attribute (@$attributes) { | |
| 4483 | |
| 4484 if ($attribute->isStatic) { | |
| 4485 push(@staticAttributes, $attribute); | |
| 4486 } elsif ($interfaceName eq "Window" && $attribute->extendedAttributes->{
"Unforgeable"}) { | |
| 4487 push(@disallowsShadowing, $attribute); | |
| 4488 } elsif ($attribute->extendedAttributes->{"PerContextEnabled"}) { | |
| 4489 push(@perContextEnabledAttributes, $attribute); | |
| 4490 } elsif ($attribute->extendedAttributes->{"RuntimeEnabled"}) { | |
| 4491 push(@runtimeEnabledAttributes, $attribute); | |
| 4492 } elsif ($attribute->extendedAttributes->{"ExposeJSAccessors"}) { | |
| 4493 push(@normalAccessors, $attribute); | |
| 4494 } else { | |
| 4495 push(@normalAttributes, $attribute); | |
| 4496 } | |
| 4497 } | |
| 4498 AddToImplIncludes("bindings/v8/V8DOMConfiguration.h"); | |
| 4499 # Put the attributes that disallow shadowing on the shadow object. | |
| 4500 if (@disallowsShadowing) { | |
| 4501 my $code = ""; | |
| 4502 $code .= "static const V8DOMConfiguration::AttributeConfiguration shadow
Attributes[] = {\n"; | |
| 4503 $code .= GenerateAttributeConfigurationArray($interface, \@disallowsShad
owing); | |
| 4504 $code .= "};\n\n"; | |
| 4505 $implementation{nameSpaceWebCore}->add($code); | |
| 4506 } | |
| 4507 | |
| 4508 my $hasAttributes = 0; | |
| 4509 if (@normalAttributes) { | |
| 4510 $hasAttributes = 1; | |
| 4511 my $code = ""; | |
| 4512 $code .= "static const V8DOMConfiguration::AttributeConfiguration ${v8Cl
assName}Attributes[] = {\n"; | |
| 4513 $code .= GenerateAttributeConfigurationArray($interface, \@normalAttribu
tes); | |
| 4514 $code .= "};\n\n"; | |
| 4515 $implementation{nameSpaceWebCore}->add($code); | |
| 4516 } | |
| 4517 | |
| 4518 my $hasAccessors = 0; | |
| 4519 if (@normalAccessors) { | |
| 4520 $hasAccessors = 1; | |
| 4521 my $code = ""; | |
| 4522 $code .= "static const V8DOMConfiguration::AccessorConfiguration ${v8Cla
ssName}Accessors[] = {\n"; | |
| 4523 $code .= GenerateAttributeConfigurationArray($interface, \@normalAccesso
rs, "accessor"); | |
| 4524 $code .= "};\n\n"; | |
| 4525 $implementation{nameSpaceWebCore}->add($code); | |
| 4526 } | |
| 4527 | |
| 4528 # Setup table of standard callback functions | |
| 4529 my $hasFunctions = 0; | |
| 4530 $code = ""; | |
| 4531 foreach my $function (@normalFunctions) { | |
| 4532 # Only one table entry is needed for overloaded functions: | |
| 4533 next if $function->{overloadIndex} > 1; | |
| 4534 # Don't put any nonstandard functions into this table: | |
| 4535 next if !IsStandardFunction($interface, $function); | |
| 4536 next if $function->name eq ""; | |
| 4537 if (!$hasFunctions) { | |
| 4538 $hasFunctions = 1; | |
| 4539 $code .= "static const V8DOMConfiguration::MethodConfiguration ${v8C
lassName}Methods[] = {\n"; | |
| 4540 } | |
| 4541 my $name = $function->name; | |
| 4542 my $methodForMainWorld = "0"; | |
| 4543 if ($function->extendedAttributes->{"PerWorldBindings"}) { | |
| 4544 $methodForMainWorld = "${implClassName}V8Internal::${name}MethodCall
backForMainWorld"; | |
| 4545 } | |
| 4546 my $functionLength = GetFunctionLength($function); | |
| 4547 my $conditionalString = GenerateConditionalString($function); | |
| 4548 $code .= "#if ${conditionalString}\n" if $conditionalString; | |
| 4549 $code .= <<END; | |
| 4550 {"$name", ${implClassName}V8Internal::${name}MethodCallback, ${methodForMain
World}, ${functionLength}}, | |
| 4551 END | |
| 4552 $code .= "#endif // ${conditionalString}\n" if $conditionalString; | |
| 4553 } | |
| 4554 $code .= "};\n\n" if $hasFunctions; | |
| 4555 $implementation{nameSpaceWebCore}->add($code); | |
| 4556 | |
| 4557 my $hasConstants = 0; | |
| 4558 if (@{$interface->constants}) { | |
| 4559 $hasConstants = 1; | |
| 4560 } | |
| 4561 | |
| 4562 if (!HasCustomConstructor($interface)) { | |
| 4563 if ($interface->extendedAttributes->{"NamedConstructor"}) { | |
| 4564 GenerateNamedConstructor(@{$interface->constructors}[0], $interface)
; | |
| 4565 } elsif ($interface->extendedAttributes->{"Constructor"}) { | |
| 4566 GenerateConstructor($interface); | |
| 4567 } elsif ($interface->extendedAttributes->{"EventConstructor"}) { | |
| 4568 GenerateEventConstructor($interface); | |
| 4569 } | |
| 4570 } | |
| 4571 if (IsConstructable($interface)) { | |
| 4572 GenerateConstructorCallback($interface); | |
| 4573 } | |
| 4574 | |
| 4575 my $accessCheck = ""; | |
| 4576 if ($interface->extendedAttributes->{"CheckSecurity"} && $interfaceName ne "
Window") { | |
| 4577 $accessCheck = "instanceTemplate->SetAccessCheckCallbacks(${implClassNam
e}V8Internal::namedSecurityCheck, ${implClassName}V8Internal::indexedSecurityChe
ck, v8::External::New(isolate, const_cast<WrapperTypeInfo*>(&${v8ClassName}::wra
pperTypeInfo)));"; | |
| 4578 } | |
| 4579 | |
| 4580 # For the Window interface, generate the shadow object template | |
| 4581 # configuration method. | |
| 4582 if ($interfaceName eq "Window") { | |
| 4583 $implementation{nameSpaceWebCore}->add(<<END); | |
| 4584 static void configureShadowObjectTemplate(v8::Handle<v8::ObjectTemplate> templ,
v8::Isolate* isolate, WrapperWorldType currentWorldType) | |
| 4585 { | |
| 4586 V8DOMConfiguration::installAttributes(templ, v8::Handle<v8::ObjectTemplate>(
), shadowAttributes, WTF_ARRAY_LENGTH(shadowAttributes), isolate, currentWorldTy
pe); | |
| 4587 | |
| 4588 // Install a security handler with V8. | |
| 4589 templ->SetAccessCheckCallbacks(V8Window::namedSecurityCheckCustom, V8Window:
:indexedSecurityCheckCustom, v8::External::New(isolate, const_cast<WrapperTypeIn
fo*>(&V8Window::wrapperTypeInfo))); | |
| 4590 templ->SetInternalFieldCount(V8Window::internalFieldCount); | |
| 4591 } | |
| 4592 | |
| 4593 END | |
| 4594 } | |
| 4595 | |
| 4596 if (!$parentClassTemplate) { | |
| 4597 $parentClassTemplate = "v8::Local<v8::FunctionTemplate>()"; | |
| 4598 } | |
| 4599 | |
| 4600 # Generate the template configuration method | |
| 4601 $code = <<END; | |
| 4602 static void configure${v8ClassName}Template(v8::Handle<v8::FunctionTemplate> fun
ctionTemplate, v8::Isolate* isolate, WrapperWorldType currentWorldType) | |
| 4603 { | |
| 4604 functionTemplate->ReadOnlyPrototype(); | |
| 4605 | |
| 4606 v8::Local<v8::Signature> defaultSignature; | |
| 4607 END | |
| 4608 | |
| 4609 # Define constants, attributes, accessors and operations. | |
| 4610 my $runtimeEnabledIndent = ""; | |
| 4611 if ($interface->extendedAttributes->{"RuntimeEnabled"}) { | |
| 4612 my $runtimeEnabledFunction = GetRuntimeEnabledFunctionName($interface); | |
| 4613 $runtimeEnabledIndent = " "; | |
| 4614 $code .= <<END; | |
| 4615 if (!${runtimeEnabledFunction}()) | |
| 4616 defaultSignature = V8DOMConfiguration::installDOMClassTemplate(functionT
emplate, \"\", $parentClassTemplate, ${v8ClassName}::internalFieldCount, 0, 0, 0
, 0, 0, 0, isolate, currentWorldType); | |
| 4617 else | |
| 4618 END | |
| 4619 } | |
| 4620 $code .= $runtimeEnabledIndent . " defaultSignature = V8DOMConfiguration:
:installDOMClassTemplate(functionTemplate, \"${interfaceName}\", $parentClassTem
plate, ${v8ClassName}::internalFieldCount,\n"; | |
| 4621 $code .= $runtimeEnabledIndent . " " . ($hasAttributes ? "${v8ClassNa
me}Attributes, WTF_ARRAY_LENGTH(${v8ClassName}Attributes),\n" : "0, 0,\n"); | |
| 4622 $code .= $runtimeEnabledIndent . " " . ($hasAccessors ? "${v8ClassNam
e}Accessors, WTF_ARRAY_LENGTH(${v8ClassName}Accessors),\n" : "0, 0,\n"); | |
| 4623 $code .= $runtimeEnabledIndent . " " . ($hasFunctions ? "${v8ClassNam
e}Methods, WTF_ARRAY_LENGTH(${v8ClassName}Methods),\n" : "0, 0,\n"); | |
| 4624 $code .= $runtimeEnabledIndent . " isolate, currentWorldType);\n"; | |
| 4625 | |
| 4626 if (IsConstructable($interface)) { | |
| 4627 $code .= " functionTemplate->SetCallHandler(${v8ClassName}::construct
orCallback);\n"; | |
| 4628 my $interfaceLength = GetInterfaceLength($interface); | |
| 4629 $code .= " functionTemplate->SetLength(${interfaceLength});\n"; | |
| 4630 } | |
| 4631 | |
| 4632 $code .= <<END; | |
| 4633 v8::Local<v8::ObjectTemplate> ALLOW_UNUSED instanceTemplate = functionTempla
te->InstanceTemplate(); | |
| 4634 v8::Local<v8::ObjectTemplate> ALLOW_UNUSED prototypeTemplate = functionTempl
ate->PrototypeTemplate(); | |
| 4635 END | |
| 4636 | |
| 4637 if ($accessCheck) { | |
| 4638 $code .= " $accessCheck\n"; | |
| 4639 } | |
| 4640 | |
| 4641 # Define runtime enabled attributes. | |
| 4642 foreach my $runtimeEnabledAttribute (@runtimeEnabledAttributes) { | |
| 4643 my $runtimeEnabledFunction = GetRuntimeEnabledFunctionName($runtimeEnabl
edAttribute); | |
| 4644 my $conditionalString = GenerateConditionalString($runtimeEnabledAttribu
te); | |
| 4645 $code .= "#if ${conditionalString}\n" if $conditionalString; | |
| 4646 $code .= " if (${runtimeEnabledFunction}()) {\n"; | |
| 4647 $code .= " static const V8DOMConfiguration::AttributeConfiguratio
n attributeConfiguration =\\\n"; | |
| 4648 $code .= GenerateAttributeConfiguration($interface, $runtimeEnabledAttri
bute, ";", " "); | |
| 4649 $code .= <<END; | |
| 4650 V8DOMConfiguration::installAttribute(instanceTemplate, prototypeTemplate
, attributeConfiguration, isolate, currentWorldType); | |
| 4651 } | |
| 4652 END | |
| 4653 $code .= "#endif // ${conditionalString}\n" if $conditionalString; | |
| 4654 } | |
| 4655 | |
| 4656 my @runtimeEnabledConstants; | |
| 4657 if ($hasConstants) { | |
| 4658 # Define constants. | |
| 4659 $code .= " static const V8DOMConfiguration::ConstantConfiguration ${v
8ClassName}Constants[] = {\n"; | |
| 4660 foreach my $constant (@{$interface->constants}) { | |
| 4661 my $name = $constant->name; | |
| 4662 my $value = $constant->value; | |
| 4663 my $attrExt = $constant->extendedAttributes; | |
| 4664 my $implementedBy = $attrExt->{"ImplementedBy"}; | |
| 4665 if ($implementedBy) { | |
| 4666 my $implementedByImplName = GetImplNameFromImplementedBy($implem
entedBy); | |
| 4667 AddToImplIncludes(HeaderFilesForInterface($implementedBy, $imple
mentedByImplName)); | |
| 4668 } | |
| 4669 if ($attrExt->{"RuntimeEnabled"}) { | |
| 4670 push(@runtimeEnabledConstants, $constant); | |
| 4671 } else { | |
| 4672 $code .= <<END; | |
| 4673 {"${name}", $value}, | |
| 4674 END | |
| 4675 } | |
| 4676 } | |
| 4677 $code .= " };\n"; | |
| 4678 $code .= <<END; | |
| 4679 V8DOMConfiguration::installConstants(functionTemplate, prototypeTemplate, ${
v8ClassName}Constants, WTF_ARRAY_LENGTH(${v8ClassName}Constants), isolate); | |
| 4680 END | |
| 4681 # Define runtime enabled constants. | |
| 4682 foreach my $runtimeEnabledConstant (@runtimeEnabledConstants) { | |
| 4683 my $runtimeEnabledFunction = GetRuntimeEnabledFunctionName($runtimeE
nabledConstant); | |
| 4684 my $name = $runtimeEnabledConstant->name; | |
| 4685 my $value = $runtimeEnabledConstant->value; | |
| 4686 $code .= " if (${runtimeEnabledFunction}()) {\n"; | |
| 4687 $code .= <<END; | |
| 4688 static const V8DOMConfiguration::ConstantConfiguration constantConfigura
tion = {"${name}", static_cast<signed int>(${value})}; | |
| 4689 V8DOMConfiguration::installConstants(functionTemplate, prototypeTemplate
, &constantConfiguration, 1, isolate); | |
| 4690 END | |
| 4691 $code .= " }\n"; | |
| 4692 } | |
| 4693 $code .= join "", GenerateCompileTimeCheckForEnumsIfNeeded($interface); | |
| 4694 } | |
| 4695 | |
| 4696 $code .= GenerateImplementationIndexedPropertyAccessors($interface); | |
| 4697 $code .= GenerateImplementationNamedPropertyAccessors($interface); | |
| 4698 $code .= GenerateImplementationLegacyCallAsFunction($interface); | |
| 4699 $code .= GenerateImplementationMarkAsUndetectable($interface); | |
| 4700 | |
| 4701 # Define operations. | |
| 4702 my $total_functions = 0; | |
| 4703 foreach my $function (@normalFunctions) { | |
| 4704 # Only one accessor is needed for overloaded operations. | |
| 4705 next if $function->{overloadIndex} > 1; | |
| 4706 next if $function->name eq ""; | |
| 4707 | |
| 4708 $total_functions++; | |
| 4709 next if IsStandardFunction($interface, $function); | |
| 4710 $code .= GenerateNonStandardFunction($interface, $function); | |
| 4711 } | |
| 4712 | |
| 4713 # Define static attributes. | |
| 4714 foreach my $attribute (@staticAttributes) { | |
| 4715 $code .= GenerateStaticAttribute($interface, $attribute); | |
| 4716 } | |
| 4717 | |
| 4718 # Special cases | |
| 4719 if ($interfaceName eq "Window") { | |
| 4720 $code .= <<END; | |
| 4721 | |
| 4722 prototypeTemplate->SetInternalFieldCount(V8Window::internalFieldCount); | |
| 4723 functionTemplate->SetHiddenPrototype(true); | |
| 4724 instanceTemplate->SetInternalFieldCount(V8Window::internalFieldCount); | |
| 4725 // Set access check callbacks, but turned off initially. | |
| 4726 // When a context is detached from a frame, turn on the access check. | |
| 4727 // Turning on checks also invalidates inline caches of the object. | |
| 4728 instanceTemplate->SetAccessCheckCallbacks(V8Window::namedSecurityCheckCustom
, V8Window::indexedSecurityCheckCustom, v8::External::New(isolate, const_cast<Wr
apperTypeInfo*>(&V8Window::wrapperTypeInfo)), false); | |
| 4729 END | |
| 4730 } | |
| 4731 if ($interfaceName eq "HTMLDocument" or $interfaceName eq "DedicatedWorkerGl
obalScope" or $interfaceName eq "SharedWorkerGlobalScope" or $interfaceName eq "
ServiceWorkerGlobalScope") { | |
| 4732 $code .= <<END; | |
| 4733 functionTemplate->SetHiddenPrototype(true); | |
| 4734 END | |
| 4735 } | |
| 4736 | |
| 4737 $code .= <<END; | |
| 4738 | |
| 4739 // Custom toString template | |
| 4740 functionTemplate->Set(v8AtomicString(isolate, "toString"), V8PerIsolateData:
:current()->toStringTemplate()); | |
| 4741 } | |
| 4742 | |
| 4743 END | |
| 4744 $implementation{nameSpaceWebCore}->add($code); | |
| 4745 | |
| 4746 AddToImplIncludes("bindings/v8/V8ObjectConstructor.h"); | |
| 4747 $implementation{nameSpaceWebCore}->add(<<END); | |
| 4748 v8::Handle<v8::FunctionTemplate> ${v8ClassName}::domTemplate(v8::Isolate* isolat
e, WrapperWorldType currentWorldType) | |
| 4749 { | |
| 4750 V8PerIsolateData* data = V8PerIsolateData::from(isolate); | |
| 4751 V8PerIsolateData::TemplateMap::iterator result = data->templateMap(currentWo
rldType).find(&wrapperTypeInfo); | |
| 4752 if (result != data->templateMap(currentWorldType).end()) | |
| 4753 return result->value.newLocal(isolate); | |
| 4754 | |
| 4755 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate"); | |
| 4756 v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate, V
8ObjectConstructor::isValidConstructorMode); | |
| 4757 configure${v8ClassName}Template(templ, isolate, currentWorldType); | |
| 4758 data->templateMap(currentWorldType).add(&wrapperTypeInfo, UnsafePersistent<v
8::FunctionTemplate>(isolate, templ)); | |
| 4759 return templ; | |
| 4760 } | |
| 4761 | |
| 4762 bool ${v8ClassName}::hasInstance(v8::Handle<v8::Value> jsValue, v8::Isolate* iso
late) | |
| 4763 { | |
| 4764 return V8PerIsolateData::from(isolate)->hasInstance(&wrapperTypeInfo, jsValu
e); | |
| 4765 } | |
| 4766 | |
| 4767 v8::Handle<v8::Object> ${v8ClassName}::findInstanceInPrototypeChain(v8::Handle<v
8::Value> jsValue, v8::Isolate* isolate) | |
| 4768 { | |
| 4769 return V8PerIsolateData::from(isolate)->findInstanceInPrototypeChain(&wrappe
rTypeInfo, jsValue); | |
| 4770 } | |
| 4771 | |
| 4772 ${nativeType}* ${v8ClassName}::toNativeWithTypeCheck(v8::Isolate* isolate, v8::H
andle<v8::Value> value) | |
| 4773 { | |
| 4774 return hasInstance(value, isolate) ? fromInternalPointer(v8::Handle<v8::Obje
ct>::Cast(value)->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex)) :
0; | |
| 4775 } | |
| 4776 | |
| 4777 END | |
| 4778 | |
| 4779 if (@perContextEnabledAttributes) { | |
| 4780 my $code = ""; | |
| 4781 $code .= <<END; | |
| 4782 void ${v8ClassName}::installPerContextEnabledProperties(v8::Handle<v8::Object> i
nstanceTemplate, ${nativeType}* impl, v8::Isolate* isolate) | |
| 4783 { | |
| 4784 v8::Local<v8::Object> prototypeTemplate = v8::Local<v8::Object>::Cast(instan
ceTemplate->GetPrototype()); | |
| 4785 END | |
| 4786 | |
| 4787 # Define per-context enabled attributes. | |
| 4788 foreach my $perContextEnabledAttribute (@perContextEnabledAttributes) { | |
| 4789 my $contextEnabledFunction = GetContextEnabledFunctionName($perConte
xtEnabledAttribute); | |
| 4790 $code .= " if (${contextEnabledFunction}(impl->document())) {\n"; | |
| 4791 | |
| 4792 $code .= " static const V8DOMConfiguration::AttributeConfigur
ation attributeConfiguration =\\\n"; | |
| 4793 $code .= GenerateAttributeConfiguration($interface, $perContextEnabl
edAttribute, ";", " "); | |
| 4794 $code .= <<END; | |
| 4795 V8DOMConfiguration::installAttribute(instanceTemplate, prototypeTemplate
, attributeConfiguration, isolate); | |
| 4796 END | |
| 4797 $code .= " }\n"; | |
| 4798 } | |
| 4799 $code .= <<END; | |
| 4800 } | |
| 4801 | |
| 4802 END | |
| 4803 $implementation{nameSpaceWebCore}->add($code); | |
| 4804 } | |
| 4805 | |
| 4806 if (@perContextEnabledFunctions) { | |
| 4807 my $code = ""; | |
| 4808 $code .= <<END; | |
| 4809 void ${v8ClassName}::installPerContextEnabledMethods(v8::Handle<v8::Object> prot
otypeTemplate, v8::Isolate* isolate) | |
| 4810 { | |
| 4811 END | |
| 4812 # Define per-context enabled operations. | |
| 4813 $code .= <<END; | |
| 4814 v8::Local<v8::Signature> defaultSignature = v8::Signature::New(isolate, domT
emplate(isolate, worldType(isolate))); | |
| 4815 | |
| 4816 ExecutionContext* context = toExecutionContext(prototypeTemplate->CreationCo
ntext()); | |
| 4817 END | |
| 4818 | |
| 4819 foreach my $perContextEnabledFunction (@perContextEnabledFunctions) { | |
| 4820 my $contextEnabledFunction = GetContextEnabledFunctionName($perConte
xtEnabledFunction); | |
| 4821 my $functionLength = GetFunctionLength($perContextEnabledFunction); | |
| 4822 my $conditionalString = GenerateConditionalString($perContextEnabled
Function); | |
| 4823 $code .= "\n#if ${conditionalString}\n" if $conditionalString; | |
| 4824 $code .= " if (context && context->isDocument() && ${contextEnabl
edFunction}(toDocument(context)))\n"; | |
| 4825 my $name = $perContextEnabledFunction->name; | |
| 4826 $code .= <<END; | |
| 4827 prototypeTemplate->Set(v8AtomicString(isolate, "$name"), v8::FunctionTem
plate::New(isolate, ${implClassName}V8Internal::${name}MethodCallback, v8Undefin
ed(), defaultSignature, $functionLength)->GetFunction()); | |
| 4828 END | |
| 4829 $code .= "#endif // ${conditionalString}\n" if $conditionalString; | |
| 4830 } | |
| 4831 | |
| 4832 $code .= <<END; | |
| 4833 } | |
| 4834 | |
| 4835 END | |
| 4836 $implementation{nameSpaceWebCore}->add($code); | |
| 4837 } | |
| 4838 | |
| 4839 if (InheritsExtendedAttribute($interface, "ActiveDOMObject")) { | |
| 4840 $implementation{nameSpaceWebCore}->add(<<END); | |
| 4841 ActiveDOMObject* ${v8ClassName}::toActiveDOMObject(v8::Handle<v8::Object> wrappe
r) | |
| 4842 { | |
| 4843 return toNative(wrapper); | |
| 4844 } | |
| 4845 | |
| 4846 END | |
| 4847 } | |
| 4848 | |
| 4849 if (InheritsInterface($interface, "EventTarget")) { | |
| 4850 $implementation{nameSpaceWebCore}->add(<<END); | |
| 4851 EventTarget* ${v8ClassName}::toEventTarget(v8::Handle<v8::Object> object) | |
| 4852 { | |
| 4853 return toNative(object); | |
| 4854 } | |
| 4855 | |
| 4856 END | |
| 4857 } | |
| 4858 | |
| 4859 if ($interfaceName eq "Window") { | |
| 4860 $implementation{nameSpaceWebCore}->add(<<END); | |
| 4861 v8::Handle<v8::ObjectTemplate> V8Window::getShadowObjectTemplate(v8::Isolate* is
olate, WrapperWorldType currentWorldType) | |
| 4862 { | |
| 4863 if (currentWorldType == MainWorld) { | |
| 4864 DEFINE_STATIC_LOCAL(v8::Persistent<v8::ObjectTemplate>, V8WindowShadowOb
jectCacheForMainWorld, ()); | |
| 4865 if (V8WindowShadowObjectCacheForMainWorld.IsEmpty()) { | |
| 4866 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate"); | |
| 4867 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isola
te); | |
| 4868 configureShadowObjectTemplate(templ, isolate, currentWorldType); | |
| 4869 V8WindowShadowObjectCacheForMainWorld.Reset(isolate, templ); | |
| 4870 return templ; | |
| 4871 } | |
| 4872 return v8::Local<v8::ObjectTemplate>::New(isolate, V8WindowShadowObjectC
acheForMainWorld); | |
| 4873 } else { | |
| 4874 DEFINE_STATIC_LOCAL(v8::Persistent<v8::ObjectTemplate>, V8WindowShadowOb
jectCacheForNonMainWorld, ()); | |
| 4875 if (V8WindowShadowObjectCacheForNonMainWorld.IsEmpty()) { | |
| 4876 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate"); | |
| 4877 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isola
te); | |
| 4878 configureShadowObjectTemplate(templ, isolate, currentWorldType); | |
| 4879 V8WindowShadowObjectCacheForNonMainWorld.Reset(isolate, templ); | |
| 4880 return templ; | |
| 4881 } | |
| 4882 return v8::Local<v8::ObjectTemplate>::New(isolate, V8WindowShadowObjectC
acheForNonMainWorld); | |
| 4883 } | |
| 4884 } | |
| 4885 | |
| 4886 END | |
| 4887 } | |
| 4888 | |
| 4889 GenerateSpecialWrap($interface, $v8ClassName); | |
| 4890 GenerateToV8Converters($interface, $v8ClassName); | |
| 4891 | |
| 4892 $implementation{nameSpaceWebCore}->add("void ${v8ClassName}::derefObject(voi
d* object)\n"); | |
| 4893 $implementation{nameSpaceWebCore}->add("{\n"); | |
| 4894 if (IsWillBeGarbageCollectedType($interface->name)) { | |
| 4895 $implementation{nameSpaceWebCore}->add("#if !ENABLE(OILPAN)\n"); | |
| 4896 } | |
| 4897 $implementation{nameSpaceWebCore}->add(" fromInternalPointer(object)->der
ef();\n"); | |
| 4898 if (IsWillBeGarbageCollectedType($interface->name)) { | |
| 4899 $implementation{nameSpaceWebCore}->add("#endif // !ENABLE(OILPAN)\n"); | |
| 4900 } | |
| 4901 $implementation{nameSpaceWebCore}->add("}\n\n"); | |
| 4902 | |
| 4903 $implementation{nameSpaceWebCore}->add(<<END); | |
| 4904 template<> | |
| 4905 v8::Handle<v8::Value> toV8NoInline(${nativeType}* impl, v8::Handle<v8::Object> c
reationContext, v8::Isolate* isolate) | |
| 4906 { | |
| 4907 return toV8(impl, creationContext, isolate); | |
| 4908 } | |
| 4909 | |
| 4910 END | |
| 4911 } | |
| 4912 | |
| 4913 sub GenerateHeaderContentHeader | |
| 4914 { | |
| 4915 my $interface = shift; | |
| 4916 my $v8ClassName = GetV8ClassName($interface); | |
| 4917 my $conditionalString = GenerateConditionalString($interface); | |
| 4918 | |
| 4919 my @headerContentHeader = split("\r", $licenseHeader); | |
| 4920 | |
| 4921 push(@headerContentHeader, "#ifndef ${v8ClassName}" . "_h\n"); | |
| 4922 push(@headerContentHeader, "#define ${v8ClassName}" . "_h\n\n"); | |
| 4923 push(@headerContentHeader, "#if ${conditionalString}\n") if $conditionalStri
ng; | |
| 4924 return join "", @headerContentHeader; | |
| 4925 } | |
| 4926 | |
| 4927 sub GenerateCallbackHeader | |
| 4928 { | |
| 4929 my $object = shift; | |
| 4930 my $interface = shift; | |
| 4931 | |
| 4932 my $interfaceName = $interface->name; | |
| 4933 my $implClassName = GetImplName($interface); | |
| 4934 my $v8ClassName = GetV8ClassName($interface); | |
| 4935 | |
| 4936 my @includes = (); | |
| 4937 push(@includes, "bindings/v8/ActiveDOMCallback.h"); | |
| 4938 push(@includes, "bindings/v8/DOMWrapperWorld.h"); | |
| 4939 push(@includes, "bindings/v8/ScopedPersistent.h"); | |
| 4940 push(@includes, HeaderFilesForInterface($interfaceName, $implClassName)); | |
| 4941 for my $include (sort @includes) { | |
| 4942 $header{includes}->add("#include \"$include\"\n"); | |
| 4943 } | |
| 4944 $header{nameSpaceWebCore}->addHeader("\nclass ExecutionContext;\n"); | |
| 4945 $header{class}->addHeader("class $v8ClassName FINAL : public $implClassName,
public ActiveDOMCallback {"); | |
| 4946 $header{class}->addFooter("};\n"); | |
| 4947 | |
| 4948 $header{classPublic}->add(<<END); | |
| 4949 static PassOwnPtr<${v8ClassName}> create(v8::Handle<v8::Function> callback,
ExecutionContext* context) | |
| 4950 { | |
| 4951 ASSERT(context); | |
| 4952 return adoptPtr(new ${v8ClassName}(callback, context)); | |
| 4953 } | |
| 4954 | |
| 4955 virtual ~${v8ClassName}(); | |
| 4956 | |
| 4957 END | |
| 4958 | |
| 4959 # Functions | |
| 4960 my $numFunctions = @{$interface->functions}; | |
| 4961 if ($numFunctions > 0) { | |
| 4962 foreach my $function (@{$interface->functions}) { | |
| 4963 my $code = " virtual " . GetNativeTypeForCallbacks($function->typ
e) . " " . $function->name . "("; | |
| 4964 | |
| 4965 my @args = (); | |
| 4966 if (ExtendedAttributeContains($function->extendedAttributes->{"CallW
ith"}, "ThisValue")) { | |
| 4967 push(@args, GetNativeType("any") . " thisValue"); | |
| 4968 } | |
| 4969 my @params = @{$function->parameters}; | |
| 4970 foreach my $param (@params) { | |
| 4971 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $par
am->name); | |
| 4972 } | |
| 4973 $code .= join(", ", @args); | |
| 4974 $code .= ") OVERRIDE;\n"; | |
| 4975 $header{classPublic}->add($code); | |
| 4976 } | |
| 4977 } | |
| 4978 | |
| 4979 $header{classPrivate}->add(<<END); | |
| 4980 ${v8ClassName}(v8::Handle<v8::Function>, ExecutionContext*); | |
| 4981 | |
| 4982 v8::Isolate* m_isolate; | |
| 4983 ScopedPersistent<v8::Function> m_callback; | |
| 4984 RefPtr<DOMWrapperWorld> m_world; | |
| 4985 END | |
| 4986 } | |
| 4987 | |
| 4988 sub GenerateCallbackImplementation | |
| 4989 { | |
| 4990 my $object = shift; | |
| 4991 my $interface = shift; | |
| 4992 my $v8ClassName = GetV8ClassName($interface); | |
| 4993 | |
| 4994 AddToImplIncludes("core/dom/ExecutionContext.h"); | |
| 4995 AddToImplIncludes("bindings/v8/V8Binding.h"); | |
| 4996 AddToImplIncludes("bindings/v8/V8Callback.h"); | |
| 4997 AddToImplIncludes("wtf/Assertions.h"); | |
| 4998 AddToImplIncludes("wtf/GetPtr.h"); | |
| 4999 AddToImplIncludes("wtf/RefPtr.h"); | |
| 5000 | |
| 5001 $implementation{nameSpaceWebCore}->add(<<END); | |
| 5002 ${v8ClassName}::${v8ClassName}(v8::Handle<v8::Function> callback, ExecutionConte
xt* context) | |
| 5003 : ActiveDOMCallback(context) | |
| 5004 , m_isolate(toIsolate(context)) | |
| 5005 , m_callback(m_isolate, callback) | |
| 5006 , m_world(DOMWrapperWorld::current(m_isolate)) | |
| 5007 { | |
| 5008 } | |
| 5009 | |
| 5010 END | |
| 5011 | |
| 5012 $implementation{nameSpaceWebCore}->add(<<END); | |
| 5013 ${v8ClassName}::~${v8ClassName}() | |
| 5014 { | |
| 5015 } | |
| 5016 | |
| 5017 END | |
| 5018 | |
| 5019 # Functions | |
| 5020 my $numFunctions = @{$interface->functions}; | |
| 5021 if ($numFunctions > 0) { | |
| 5022 foreach my $function (@{$interface->functions}) { | |
| 5023 my $code = ""; | |
| 5024 my @params = @{$function->parameters}; | |
| 5025 | |
| 5026 # Add includes for types even if custom | |
| 5027 AddIncludesForType($function->type); | |
| 5028 foreach my $param (@params) { | |
| 5029 AddIncludesForType($param->type); | |
| 5030 } | |
| 5031 next if $function->extendedAttributes->{"Custom"}; | |
| 5032 | |
| 5033 die "We only support callbacks that return boolean or void values.\n
" unless ($function->type eq "boolean" || $function->type eq "void"); | |
| 5034 my $defaultReturn = $function->type eq "boolean" ? " true" : ""; | |
| 5035 $code .= GetNativeTypeForCallbacks($function->type) . " ${v8ClassNam
e}::" . $function->name . "("; | |
| 5036 my $callWithThisValue = ExtendedAttributeContains($function->extende
dAttributes->{"CallWith"}, "ThisValue"); | |
| 5037 | |
| 5038 my @args = (); | |
| 5039 if ($callWithThisValue) { | |
| 5040 push(@args, GetNativeTypeForCallbacks("any") . " thisValue"); | |
| 5041 } | |
| 5042 foreach my $param (@params) { | |
| 5043 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $par
am->name); | |
| 5044 } | |
| 5045 $code .= join(", ", @args); | |
| 5046 | |
| 5047 $code .= ")\n"; | |
| 5048 $code .= "{\n"; | |
| 5049 $code .= " if (!canInvokeCallback())\n"; | |
| 5050 $code .= " return${defaultReturn};\n\n"; | |
| 5051 $code .= " v8::HandleScope handleScope(m_isolate);\n\n"; | |
| 5052 $code .= " v8::Handle<v8::Context> v8Context = toV8Context(execut
ionContext(), m_world.get());\n"; | |
| 5053 $code .= " if (v8Context.IsEmpty())\n"; | |
| 5054 $code .= " return${defaultReturn};\n\n"; | |
| 5055 $code .= " v8::Context::Scope scope(v8Context);\n"; | |
| 5056 | |
| 5057 my $thisObjectHandle = ""; | |
| 5058 if ($callWithThisValue) { | |
| 5059 $code .= " v8::Handle<v8::Value> thisHandle = thisValue.v8Val
ue();\n"; | |
| 5060 $code .= " if (thisHandle.IsEmpty()) {\n"; | |
| 5061 $code .= " if (!isScriptControllerTerminating())\n"; | |
| 5062 $code .= " CRASH();\n"; | |
| 5063 $code .= " return${defaultReturn};\n"; | |
| 5064 $code .= " }\n"; | |
| 5065 $code .= " ASSERT(thisHandle->IsObject());\n"; | |
| 5066 $thisObjectHandle = "v8::Handle<v8::Object>::Cast(thisHandle), "
; | |
| 5067 } | |
| 5068 @args = (); | |
| 5069 foreach my $param (@params) { | |
| 5070 my $paramName = $param->name; | |
| 5071 $code .= NativeToJSValue($param->type, $param->extendedAttribute
s, $paramName, " ", "v8::Handle<v8::Value> ${paramName}Handle =", "m_isolate"
, "") . "\n"; | |
| 5072 $code .= " if (${paramName}Handle.IsEmpty()) {\n"; | |
| 5073 $code .= " if (!isScriptControllerTerminating())\n"; | |
| 5074 $code .= " CRASH();\n"; | |
| 5075 $code .= " return${defaultReturn};\n"; | |
| 5076 $code .= " }\n"; | |
| 5077 push(@args, "${paramName}Handle"); | |
| 5078 } | |
| 5079 | |
| 5080 if (scalar(@args) > 0) { | |
| 5081 $code .= " v8::Handle<v8::Value> argv[] = { "; | |
| 5082 $code .= join(", ", @args); | |
| 5083 $code .= " };\n\n"; | |
| 5084 } else { | |
| 5085 $code .= " v8::Handle<v8::Value> *argv = 0;\n\n"; | |
| 5086 } | |
| 5087 $code .= " "; | |
| 5088 if ($function->type eq "boolean") { | |
| 5089 $code .= "return "; | |
| 5090 } | |
| 5091 $code .= "invokeCallback(m_callback.newLocal(m_isolate), ${thisObjec
tHandle}" . scalar(@args) . ", argv, executionContext(), m_isolate);\n"; | |
| 5092 $code .= "}\n\n"; | |
| 5093 $implementation{nameSpaceWebCore}->add($code); | |
| 5094 } | |
| 5095 } | |
| 5096 } | |
| 5097 | |
| 5098 sub GenerateSpecialWrap | |
| 5099 { | |
| 5100 my $interface = shift; | |
| 5101 my $v8ClassName = shift; | |
| 5102 my $nativeType = GetNativeTypeForConversions($interface); | |
| 5103 | |
| 5104 my $specialWrap = $interface->extendedAttributes->{"SpecialWrapFor"}; | |
| 5105 my $isDocument = InheritsInterface($interface, "Document"); | |
| 5106 if (!$specialWrap && !$isDocument) { | |
| 5107 return; | |
| 5108 } | |
| 5109 | |
| 5110 my $code = ""; | |
| 5111 $code .= <<END; | |
| 5112 v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> creation
Context, v8::Isolate* isolate) | |
| 5113 { | |
| 5114 ASSERT(impl); | |
| 5115 END | |
| 5116 if ($specialWrap) { | |
| 5117 foreach my $type (split(/\s*\|\s*/, $specialWrap)) { | |
| 5118 AddToImplIncludes("V8${type}.h"); | |
| 5119 $code .= <<END; | |
| 5120 if (impl->is${type}()) | |
| 5121 return wrap(to${type}(impl), creationContext, isolate); | |
| 5122 END | |
| 5123 } | |
| 5124 } | |
| 5125 $code .= <<END; | |
| 5126 v8::Handle<v8::Object> wrapper = ${v8ClassName}::createWrapper(impl, creatio
nContext, isolate); | |
| 5127 END | |
| 5128 if ($isDocument) { | |
| 5129 AddToImplIncludes("bindings/v8/ScriptController.h"); | |
| 5130 AddToImplIncludes("bindings/v8/V8WindowShell.h"); | |
| 5131 $code .= <<END; | |
| 5132 if (wrapper.IsEmpty()) | |
| 5133 return wrapper; | |
| 5134 DOMWrapperWorld* world = DOMWrapperWorld::current(isolate); | |
| 5135 if (world->isMainWorld()) { | |
| 5136 if (LocalFrame* frame = impl->frame()) | |
| 5137 frame->script().windowShell(world)->updateDocumentWrapper(wrapper); | |
| 5138 } | |
| 5139 END | |
| 5140 } | |
| 5141 $code .= <<END; | |
| 5142 return wrapper; | |
| 5143 } | |
| 5144 | |
| 5145 END | |
| 5146 $implementation{nameSpaceWebCore}->add($code); | |
| 5147 } | |
| 5148 | |
| 5149 sub GenerateToV8Converters | |
| 5150 { | |
| 5151 my $interface = shift; | |
| 5152 my $v8ClassName = shift; | |
| 5153 my $interfaceName = $interface->name; | |
| 5154 | |
| 5155 if (ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "T
oV8")) { | |
| 5156 return; | |
| 5157 } | |
| 5158 | |
| 5159 my $passRefPtrType = GetPassRefPtrType($interface); | |
| 5160 | |
| 5161 my $wrapperConfiguration = "WrapperConfiguration::Independent"; | |
| 5162 if (InheritsExtendedAttribute($interface, "ActiveDOMObject") | |
| 5163 || InheritsExtendedAttribute($interface, "DependentLifetime") | |
| 5164 || NeedsVisitDOMWrapper($interface)) { | |
| 5165 $wrapperConfiguration = "WrapperConfiguration::Dependent"; | |
| 5166 } | |
| 5167 | |
| 5168 my $code = ""; | |
| 5169 $code .= <<END; | |
| 5170 v8::Handle<v8::Object> ${v8ClassName}::createWrapper(${passRefPtrType} impl, v8:
:Handle<v8::Object> creationContext, v8::Isolate* isolate) | |
| 5171 { | |
| 5172 ASSERT(impl); | |
| 5173 ASSERT(!DOMDataStore::containsWrapper<${v8ClassName}>(impl.get(), isolate)); | |
| 5174 if (ScriptWrappable::wrapperCanBeStoredInObject(impl.get())) { | |
| 5175 const WrapperTypeInfo* actualInfo = ScriptWrappable::getTypeInfoFromObje
ct(impl.get()); | |
| 5176 // Might be a XXXConstructor::wrapperTypeInfo instead of an XXX::wrapper
TypeInfo. These will both have | |
| 5177 // the same object de-ref functions, though, so use that as the basis of
the check. | |
| 5178 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(actualInfo->derefObjectFunction
== wrapperTypeInfo.derefObjectFunction); | |
| 5179 } | |
| 5180 | |
| 5181 END | |
| 5182 | |
| 5183 if (InheritsInterface($interface, "Document")) { | |
| 5184 AddToImplIncludes("bindings/v8/ScriptController.h"); | |
| 5185 AddToImplIncludes("core/frame/LocalFrame.h"); | |
| 5186 $code .= <<END; | |
| 5187 if (LocalFrame* frame = impl->frame()) { | |
| 5188 if (frame->script().initializeMainWorld()) { | |
| 5189 // initializeMainWorld may have created a wrapper for the object, re
try from the start. | |
| 5190 v8::Handle<v8::Object> wrapper = DOMDataStore::getWrapper<${v8ClassN
ame}>(impl.get(), isolate); | |
| 5191 if (!wrapper.IsEmpty()) | |
| 5192 return wrapper; | |
| 5193 } | |
| 5194 } | |
| 5195 END | |
| 5196 } | |
| 5197 | |
| 5198 $code .= <<END; | |
| 5199 v8::Handle<v8::Object> wrapper = V8DOMWrapper::createWrapper(creationContext
, &wrapperTypeInfo, toInternalPointer(impl.get()), isolate); | |
| 5200 if (UNLIKELY(wrapper.IsEmpty())) | |
| 5201 return wrapper; | |
| 5202 | |
| 5203 END | |
| 5204 if (InheritsInterface($interface, "AudioBuffer")) { | |
| 5205 AddToImplIncludes("modules/webaudio/AudioBuffer.h"); | |
| 5206 $code .= <<END; | |
| 5207 for (unsigned i = 0, n = impl->numberOfChannels(); i < n; i++) { | |
| 5208 Float32Array* channelData = impl->getChannelData(i); | |
| 5209 channelData->buffer()->setDeallocationObserver(V8ArrayBufferDeallocation
Observer::instanceTemplate()); | |
| 5210 } | |
| 5211 END | |
| 5212 } | |
| 5213 | |
| 5214 | |
| 5215 $code .= <<END; | |
| 5216 installPerContextEnabledProperties(wrapper, impl.get(), isolate); | |
| 5217 V8DOMWrapper::associateObjectWithWrapper<$v8ClassName>(impl, &wrapperTypeInf
o, wrapper, isolate, $wrapperConfiguration); | |
| 5218 return wrapper; | |
| 5219 } | |
| 5220 | |
| 5221 END | |
| 5222 $implementation{nameSpaceWebCore}->add($code); | |
| 5223 } | |
| 5224 | |
| 5225 sub GenerateSecurityCheckFunctions | |
| 5226 { | |
| 5227 my $interface = shift; | |
| 5228 my $implClassName = GetImplName($interface); | |
| 5229 my $v8ClassName = GetV8ClassName($interface); | |
| 5230 | |
| 5231 AddToImplIncludes("bindings/v8/BindingSecurity.h"); | |
| 5232 $implementation{nameSpaceInternal}->add(<<END); | |
| 5233 bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::Access
Type type, v8::Local<v8::Value>) | |
| 5234 { | |
| 5235 $implClassName* imp = ${v8ClassName}::toNative(host); | |
| 5236 return BindingSecurity::shouldAllowAccessToFrame(v8::Isolate::GetCurrent(),
imp->frame(), DoNotReportSecurityError); | |
| 5237 } | |
| 5238 | |
| 5239 END | |
| 5240 $implementation{nameSpaceInternal}->add(<<END); | |
| 5241 bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8
::AccessType type, v8::Local<v8::Value>) | |
| 5242 { | |
| 5243 $implClassName* imp = ${v8ClassName}::toNative(host); | |
| 5244 return BindingSecurity::shouldAllowAccessToFrame(v8::Isolate::GetCurrent(),
imp->frame(), DoNotReportSecurityError); | |
| 5245 } | |
| 5246 | |
| 5247 END | |
| 5248 } | |
| 5249 | |
| 5250 sub GetNativeTypeForConversions | |
| 5251 { | |
| 5252 my $interface = shift; | |
| 5253 my $implClassName = GetImplName($interface); | |
| 5254 $implClassName = GetSVGTypeNeedingTearOff($interface->name) if IsSVGTypeNeed
ingTearOff($interface->name); | |
| 5255 return $implClassName; | |
| 5256 } | |
| 5257 | |
| 5258 sub GetNamespaceForInterface | |
| 5259 { | |
| 5260 my $interface = shift; | |
| 5261 return "WTF" if IsTypedArrayType($interface->name); | |
| 5262 return "WebCore"; | |
| 5263 } | |
| 5264 | |
| 5265 sub GenerateFunctionCallString | |
| 5266 { | |
| 5267 my $function = shift; | |
| 5268 my $numberOfParameters = shift; | |
| 5269 my $indent = shift; | |
| 5270 my $interface = shift; | |
| 5271 my $forMainWorldSuffix = shift; | |
| 5272 my $hasExceptionState = shift; | |
| 5273 my %replacements = @_; | |
| 5274 | |
| 5275 my $interfaceName = $interface->name; | |
| 5276 my $implClassName = GetImplName($interface); | |
| 5277 my $name = GetImplName($function); | |
| 5278 my $returnType = $function->type; | |
| 5279 my $code = ""; | |
| 5280 my $isSVGTearOffType = (IsSVGTypeNeedingTearOff($returnType) and not $interf
aceName =~ /List$/); | |
| 5281 | |
| 5282 my $index = 0; | |
| 5283 my $humanFriendlyIndex = $index + 1; | |
| 5284 | |
| 5285 my @arguments; | |
| 5286 my $functionName; | |
| 5287 my $implementedBy = $function->extendedAttributes->{"ImplementedBy"}; | |
| 5288 if ($implementedBy) { | |
| 5289 my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy)
; | |
| 5290 AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implementedBy
ImplName)); | |
| 5291 if (!$function->isStatic) { | |
| 5292 $code .= " ASSERT(imp);\n"; | |
| 5293 unshift(@arguments, "*imp"); | |
| 5294 } | |
| 5295 $functionName = "${implementedByImplName}::${name}"; | |
| 5296 } elsif ($function->isStatic) { | |
| 5297 $functionName = "${implClassName}::${name}"; | |
| 5298 } else { | |
| 5299 $functionName = "imp->${name}"; | |
| 5300 } | |
| 5301 | |
| 5302 my $callWith = $function->extendedAttributes->{"CallWith"}; | |
| 5303 my ($callWithArgs, $subCode) = GenerateCallWith($callWith, $indent, 1, $func
tion); | |
| 5304 $code .= $subCode; | |
| 5305 unshift(@arguments, @$callWithArgs); | |
| 5306 $index += @$callWithArgs; | |
| 5307 $humanFriendlyIndex = $index + 1; | |
| 5308 | |
| 5309 $numberOfParameters += @$callWithArgs; | |
| 5310 | |
| 5311 foreach my $parameter (@{$function->parameters}) { | |
| 5312 if ($index eq $numberOfParameters) { | |
| 5313 last; | |
| 5314 } | |
| 5315 my $paramName = $parameter->name; | |
| 5316 my $paramType = $parameter->type; | |
| 5317 | |
| 5318 if ($replacements{$paramName}) { | |
| 5319 push @arguments, $replacements{$paramName}; | |
| 5320 } elsif (IsSVGTypeNeedingTearOff($parameter->type) and not $interfaceNam
e =~ /List$/) { | |
| 5321 push @arguments, "$paramName->propertyReference()"; | |
| 5322 if ($hasExceptionState) { | |
| 5323 $code .= <<END; | |
| 5324 if (!$paramName) { | |
| 5325 exceptionState.throwTypeError(\"parameter $humanFriendlyIndex is not of
type '${ \$parameter->type }'.\"); | |
| 5326 exceptionState.throwIfNeeded(); | |
| 5327 return; | |
| 5328 } | |
| 5329 END | |
| 5330 } else { | |
| 5331 $code .= <<END; | |
| 5332 if (!$paramName) { | |
| 5333 throwTypeError(ExceptionMessages::failedToExecute(\"$name\", \"$interfac
eName\", \"parameter $humanFriendlyIndex is not of type '${ \$parameter->type }'
.\"), info.GetIsolate()); | |
| 5334 return; | |
| 5335 } | |
| 5336 END | |
| 5337 } | |
| 5338 } elsif (IsNullableParameter($parameter)) { | |
| 5339 push @arguments, "${paramName}IsNull ? 0 : &$paramName"; | |
| 5340 } elsif (IsCallbackInterface($paramType) or $paramType eq "NodeFilter" o
r $paramType eq "XPathNSResolver") { | |
| 5341 push @arguments, "$paramName.release()"; | |
| 5342 } else { | |
| 5343 push @arguments, $paramName; | |
| 5344 } | |
| 5345 $index++; | |
| 5346 $humanFriendlyIndex = $index + 1; | |
| 5347 } | |
| 5348 | |
| 5349 # Support for returning a union type. | |
| 5350 if (IsUnionType($returnType)) { | |
| 5351 my $types = $returnType->unionMemberTypes; | |
| 5352 for my $i (0 .. scalar(@$types)-1) { | |
| 5353 my $unionMemberType = $types->[$i]; | |
| 5354 my $unionMemberNativeType = GetNativeType($unionMemberType); | |
| 5355 my $unionMemberNumber = $i + 1; | |
| 5356 my $unionMemberVariable = "result" . $i; | |
| 5357 my $unionMemberEnabledVariable = "result" . $i . "Enabled"; | |
| 5358 $code .= " bool ${unionMemberEnabledVariable} = false;\n"; | |
| 5359 $code .= " ${unionMemberNativeType} ${unionMemberVariable};\n"; | |
| 5360 push @arguments, $unionMemberEnabledVariable; | |
| 5361 push @arguments, $unionMemberVariable; | |
| 5362 } | |
| 5363 } | |
| 5364 | |
| 5365 if ($function->extendedAttributes->{"RaisesException"}) { | |
| 5366 push @arguments, "exceptionState"; | |
| 5367 } | |
| 5368 | |
| 5369 my $functionString = "$functionName(" . join(", ", @arguments) . ")"; | |
| 5370 | |
| 5371 my $return = "result"; | |
| 5372 my $returnIsRef = IsRefPtrType($returnType); | |
| 5373 | |
| 5374 if ($returnType eq "void" || IsUnionType($returnType)) { | |
| 5375 $code .= $indent . "$functionString;\n"; | |
| 5376 } elsif (ExtendedAttributeContains($callWith, "ScriptState") or $function->e
xtendedAttributes->{"RaisesException"}) { | |
| 5377 my $nativeReturnType = GetNativeType($returnType, {}, ""); | |
| 5378 $nativeReturnType = GetSVGWrappedTypeNeedingTearOff($returnType) if $isS
VGTearOffType; | |
| 5379 | |
| 5380 $code .= $indent . $nativeReturnType . " result = $functionString;\n"; | |
| 5381 } else { | |
| 5382 # Can inline the function call into the return statement to avoid overhe
ad of using a Ref<> temporary | |
| 5383 $return = $functionString; | |
| 5384 $returnIsRef = 0; | |
| 5385 } | |
| 5386 | |
| 5387 if ($function->extendedAttributes->{"RaisesException"}) { | |
| 5388 $code .= $indent . "if (exceptionState.throwIfNeeded())\n"; | |
| 5389 $code .= $indent . " return;\n"; | |
| 5390 } | |
| 5391 | |
| 5392 if (ExtendedAttributeContains($callWith, "ScriptState")) { | |
| 5393 $code .= $indent . "if (state.hadException()) {\n"; | |
| 5394 $code .= $indent . " v8::Local<v8::Value> exception = state.exception
();\n"; | |
| 5395 $code .= $indent . " state.clearException();\n"; | |
| 5396 $code .= $indent . " throwError(exception, info.GetIsolate());\n"; | |
| 5397 $code .= $indent . " return;\n"; | |
| 5398 $code .= $indent . "}\n"; | |
| 5399 } | |
| 5400 | |
| 5401 if ($isSVGTearOffType) { | |
| 5402 AddToImplIncludes("V8$returnType.h"); | |
| 5403 AddToImplIncludes("core/svg/properties/SVGPropertyTearOff.h"); | |
| 5404 my $svgNativeType = GetSVGTypeNeedingTearOff($returnType); | |
| 5405 # FIXME: Update for all ScriptWrappables. | |
| 5406 if (IsDOMNodeType($interfaceName)) { | |
| 5407 if ($forMainWorldSuffix eq "ForMainWorld") { | |
| 5408 $code .= $indent . "v8SetReturnValueForMainWorld(info, WTF::getP
tr(${svgNativeType}::create($return)));\n"; | |
| 5409 } else { | |
| 5410 $code .= $indent . "v8SetReturnValueFast(info, WTF::getPtr(${svg
NativeType}::create($return)), imp);\n"; | |
| 5411 } | |
| 5412 } else { | |
| 5413 $code .= $indent . "v8SetReturnValue${forMainWorldSuffix}(info, WTF:
:getPtr(${svgNativeType}::create($return)));\n"; | |
| 5414 } | |
| 5415 return $code; | |
| 5416 } | |
| 5417 | |
| 5418 # If the implementing class is a POD type, commit changes | |
| 5419 if (IsSVGTypeNeedingTearOff($interfaceName) and not $interfaceName =~ /List$
/) { | |
| 5420 $code .= $indent . "wrapper->commitChange();\n"; | |
| 5421 } | |
| 5422 | |
| 5423 $return .= ".release()" if ($returnIsRef); | |
| 5424 | |
| 5425 my $nativeValue; | |
| 5426 # FIXME: Update for all ScriptWrappables. | |
| 5427 if (IsDOMNodeType($interfaceName)) { | |
| 5428 $nativeValue = NativeToJSValue($function->type, $function->extendedAttri
butes, $return, $indent, "", "info.GetIsolate()", "info", "imp", $forMainWorldSu
ffix, "return"); | |
| 5429 } else { | |
| 5430 $nativeValue = NativeToJSValue($function->type, $function->extendedAttri
butes, $return, $indent, "", "info.GetIsolate()", "info", 0, $forMainWorldSuffix
, "return"); | |
| 5431 } | |
| 5432 | |
| 5433 $code .= $nativeValue . "\n" if $nativeValue; # Skip blank line for void re
turn type | |
| 5434 | |
| 5435 return $code; | |
| 5436 } | |
| 5437 | |
| 5438 sub GetNativeType | |
| 5439 { | |
| 5440 my $type = shift; | |
| 5441 my $extendedAttributes = shift; | |
| 5442 my $isParameter = shift; | |
| 5443 | |
| 5444 my $svgNativeType = GetSVGTypeNeedingTearOff($type); | |
| 5445 if ($svgNativeType) { | |
| 5446 if ($svgNativeType =~ /List$/) { | |
| 5447 return "${svgNativeType}*"; | |
| 5448 } else { | |
| 5449 return "RefPtr<${svgNativeType} >"; | |
| 5450 } | |
| 5451 } | |
| 5452 | |
| 5453 return "float" if $type eq "float"; | |
| 5454 return "double" if $type eq "double"; | |
| 5455 return "int" if $type eq "long" or $type eq "int" or $type eq "short" or $ty
pe eq "byte"; | |
| 5456 if ($type eq "unsigned long" or $type eq "unsigned int" or $type eq "unsigne
d short" or $type eq "octet") { | |
| 5457 return "unsigned"; | |
| 5458 } | |
| 5459 return "long long" if $type eq "long long"; | |
| 5460 return "unsigned long long" if $type eq "unsigned long long"; | |
| 5461 return "bool" if $type eq "boolean"; | |
| 5462 | |
| 5463 if (($type eq "DOMString" || IsEnumType($type)) and $isParameter) { | |
| 5464 my $mode = GetV8StringResourceMode($extendedAttributes); | |
| 5465 # FIXME: Add the case for 'elsif ($attributeOrParameter->extendedAttribu
tes->{"TreatUndefinedAs"} and $attributeOrParameter->extendedAttributes->{"Treat
UndefinedAs"} eq "NullString"))'. | |
| 5466 return "V8StringResource<$mode>"; | |
| 5467 } | |
| 5468 | |
| 5469 return "String" if $type eq "DOMString" or IsEnumType($type); | |
| 5470 | |
| 5471 return "ScriptPromise" if $type eq "Promise"; | |
| 5472 | |
| 5473 return "Range::CompareHow" if $type eq "CompareHow"; | |
| 5474 return "DOMTimeStamp" if $type eq "DOMTimeStamp"; | |
| 5475 return "double" if $type eq "Date"; | |
| 5476 return "ScriptValue" if $type eq "any" or IsCallbackFunctionType($type); | |
| 5477 return "Dictionary" if $type eq "Dictionary"; | |
| 5478 | |
| 5479 die "UnionType is not supported" if IsUnionType($type); | |
| 5480 | |
| 5481 if (IsTypedArrayType($type)) { | |
| 5482 return $isParameter ? "${type}*" : "RefPtr<${type}>"; | |
| 5483 } | |
| 5484 | |
| 5485 # We need to check [ImplementedAs] extended attribute for wrapper types. | |
| 5486 return "RefPtrWillBeRawPtr<$type>" if $type eq "XPathNSResolver"; # FIXME:
Remove custom bindings for XPathNSResolver. | |
| 5487 if (IsWrapperType($type)) { | |
| 5488 my $interface = ParseInterface($type); | |
| 5489 my $implClassName = GetImplName($interface); | |
| 5490 if ($isParameter) { | |
| 5491 return "$implClassName*"; | |
| 5492 } elsif (IsWillBeGarbageCollectedType($interface->name)) { | |
| 5493 return "RefPtrWillBeRawPtr<$implClassName>"; | |
| 5494 } else { | |
| 5495 return "RefPtr<$implClassName>"; | |
| 5496 } | |
| 5497 } | |
| 5498 return "RefPtr<$type>" if IsRefPtrType($type) and (not $isParameter or $nonW
rapperTypes{$type}); | |
| 5499 | |
| 5500 my $arrayOrSequenceType = GetArrayOrSequenceType($type); | |
| 5501 | |
| 5502 if ($arrayOrSequenceType) { | |
| 5503 my $nativeType = GetNativeType($arrayOrSequenceType); | |
| 5504 $nativeType .= " " if ($nativeType =~ />$/); | |
| 5505 return "Vector<${nativeType}>"; | |
| 5506 } | |
| 5507 | |
| 5508 # Default, assume native type is a pointer with same type name as idl type | |
| 5509 return "${type}*"; | |
| 5510 } | |
| 5511 | |
| 5512 sub GetNativeTypeForCallbacks | |
| 5513 { | |
| 5514 my $type = shift; | |
| 5515 return "const String&" if $type eq "DOMString"; | |
| 5516 return "PassRefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValu
e"; | |
| 5517 return "void" if $type eq "void"; | |
| 5518 | |
| 5519 # Callbacks use raw pointers, so pass isParameter = 1 | |
| 5520 my $nativeType = GetNativeType($type, {}, "parameter"); | |
| 5521 return "const $nativeType&" if $nativeType =~ /^Vector/; | |
| 5522 return $nativeType; | |
| 5523 } | |
| 5524 | |
| 5525 sub JSValueToNativeStatement | |
| 5526 { | |
| 5527 my $type = shift; | |
| 5528 my $extendedAttributes = shift; | |
| 5529 my $argIndexOrZero = shift; | |
| 5530 my $jsValue = shift; | |
| 5531 my $variableName = shift; | |
| 5532 my $indent = shift; | |
| 5533 my $getIsolate = shift; | |
| 5534 | |
| 5535 my $nativeType = GetNativeType($type, $extendedAttributes, "parameter"); | |
| 5536 my $native_value = JSValueToNative($type, $extendedAttributes, $argIndexOrZe
ro, $jsValue, $getIsolate); | |
| 5537 my $code = ""; | |
| 5538 if ($type eq "DOMString" || IsEnumType($type)) { | |
| 5539 die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8St
ringResource/; | |
| 5540 if ($type eq "DOMString" or IsEnumType($type)) { | |
| 5541 $code .= $indent . "V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID($nativeType
, $variableName, $native_value);\n" | |
| 5542 } else { | |
| 5543 $code .= $indent . "$nativeType $variableName($native_value, true);\
n"; | |
| 5544 } | |
| 5545 } elsif (IsIntegerType($type)) { | |
| 5546 $code .= $indent . "V8TRYCATCH_EXCEPTION_VOID($nativeType, $variableName
, $native_value, exceptionState);\n"; | |
| 5547 } else { | |
| 5548 $code .= $indent . "V8TRYCATCH_VOID($nativeType, $variableName, $native_
value);\n"; | |
| 5549 } | |
| 5550 return $code; | |
| 5551 } | |
| 5552 | |
| 5553 | |
| 5554 sub JSValueToNative | |
| 5555 { | |
| 5556 my $type = shift; | |
| 5557 my $extendedAttributes = shift; | |
| 5558 # Argument position (1-indexed) or 0 if for a setter's value. | |
| 5559 my $argIndexOrZero = shift; | |
| 5560 my $value = shift; | |
| 5561 my $getIsolate = shift; | |
| 5562 | |
| 5563 return "$value->BooleanValue()" if $type eq "boolean"; | |
| 5564 return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $t
ype eq "double"; | |
| 5565 | |
| 5566 if (IsIntegerType($type)) { | |
| 5567 my $conversion = "to" . $integerTypeHash{$type} . "($value"; | |
| 5568 if ($extendedAttributes->{"EnforceRange"}) { | |
| 5569 return "${conversion}, EnforceRange, exceptionState)"; | |
| 5570 } else { | |
| 5571 return "${conversion}, exceptionState)"; | |
| 5572 } | |
| 5573 } | |
| 5574 return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "C
ompareHow"; | |
| 5575 return "toCoreDate($value)" if $type eq "Date"; | |
| 5576 | |
| 5577 if ($type eq "DOMString" or IsEnumType($type)) { | |
| 5578 return $value; | |
| 5579 } | |
| 5580 | |
| 5581 if ($type eq "SerializedScriptValue") { | |
| 5582 AddToImplIncludes("bindings/v8/SerializedScriptValue.h"); | |
| 5583 return "SerializedScriptValue::create($value, $getIsolate)"; | |
| 5584 } | |
| 5585 | |
| 5586 if ($type eq "Dictionary") { | |
| 5587 AddToImplIncludes("bindings/v8/Dictionary.h"); | |
| 5588 return "Dictionary($value, $getIsolate)"; | |
| 5589 } | |
| 5590 | |
| 5591 if ($type eq "any" || IsCallbackFunctionType($type)) { | |
| 5592 AddToImplIncludes("bindings/v8/ScriptValue.h"); | |
| 5593 return "ScriptValue($value, $getIsolate)"; | |
| 5594 } | |
| 5595 | |
| 5596 if ($type eq "Promise") { | |
| 5597 AddToImplIncludes("bindings/v8/ScriptPromise.h"); | |
| 5598 return "ScriptPromise($value, $getIsolate)"; | |
| 5599 } | |
| 5600 | |
| 5601 if ($type eq "NodeFilter") { | |
| 5602 return "toNodeFilter($value, $getIsolate)"; | |
| 5603 } | |
| 5604 | |
| 5605 if ($type eq "Window") { | |
| 5606 return "toDOMWindow($value, $getIsolate)"; | |
| 5607 } | |
| 5608 | |
| 5609 if ($type eq "MediaQueryListListener") { | |
| 5610 AddToImplIncludes("core/css/MediaQueryListListener.h"); | |
| 5611 return "MediaQueryListListener::create(ScriptValue(" . $value . ", $getI
solate))"; | |
| 5612 } | |
| 5613 | |
| 5614 if ($type eq "EventTarget") { | |
| 5615 return "V8DOMWrapper::isDOMWrapper($value) ? toWrapperTypeInfo(v8::Handl
e<v8::Object>::Cast($value))->toEventTarget(v8::Handle<v8::Object>::Cast($value)
) : 0"; | |
| 5616 } | |
| 5617 | |
| 5618 if (IsTypedArrayType($type)) { | |
| 5619 AddIncludesForType($type); | |
| 5620 return "$value->Is${type}() ? V8${type}::toNative(v8::Handle<v8::${type}
>::Cast($value)) : 0" | |
| 5621 } | |
| 5622 | |
| 5623 if ($type eq "XPathNSResolver") { | |
| 5624 return "toXPathNSResolver($value, $getIsolate)"; | |
| 5625 } | |
| 5626 | |
| 5627 my $arrayOrSequenceType = GetArrayOrSequenceType($type); | |
| 5628 | |
| 5629 if ($arrayOrSequenceType) { | |
| 5630 if (IsRefPtrType($arrayOrSequenceType)) { | |
| 5631 AddToImplIncludes("V8${arrayOrSequenceType}.h"); | |
| 5632 return "(toRefPtrNativeArray<${arrayOrSequenceType}, V8${arrayOrSequ
enceType}>($value, $argIndexOrZero, $getIsolate))"; | |
| 5633 } | |
| 5634 return "toNativeArray<" . GetNativeType($arrayOrSequenceType) . ">($valu
e, $argIndexOrZero, $getIsolate)"; | |
| 5635 } | |
| 5636 | |
| 5637 AddIncludesForType($type); | |
| 5638 | |
| 5639 AddToImplIncludes("V8${type}.h"); | |
| 5640 return "V8${type}::toNativeWithTypeCheck(info.GetIsolate(), $value)"; | |
| 5641 } | |
| 5642 | |
| 5643 sub IsUnionType | |
| 5644 { | |
| 5645 my $type = shift; # string or UnionType | |
| 5646 if(ref($type) eq "UnionType") { | |
| 5647 die "Currently only 2 values of non-union type is supported as union typ
e.\n" unless @{$type->unionMemberTypes} == 2; | |
| 5648 return 1; | |
| 5649 } | |
| 5650 return 0; | |
| 5651 } | |
| 5652 | |
| 5653 sub IsWrapperType | |
| 5654 { | |
| 5655 my $type = shift; | |
| 5656 return 0 if GetArrayType($type); | |
| 5657 return 0 if GetSequenceType($type); | |
| 5658 return 0 if IsCallbackFunctionType($type); | |
| 5659 return 0 if IsEnumType($type); | |
| 5660 return 0 if IsPrimitiveType($type); | |
| 5661 return 0 if $type eq "Promise"; | |
| 5662 return !$nonWrapperTypes{$type}; | |
| 5663 } | |
| 5664 | |
| 5665 sub IsCallbackInterface | |
| 5666 { | |
| 5667 my $type = shift; | |
| 5668 return 0 unless IsWrapperType($type); | |
| 5669 return 0 if IsTypedArrayType($type); | |
| 5670 | |
| 5671 my $idlFile = IDLFileForInterface($type) | |
| 5672 or die("Could NOT find IDL file for interface \"$type\"!\n"); | |
| 5673 | |
| 5674 open FILE, "<", $idlFile; | |
| 5675 my @lines = <FILE>; | |
| 5676 close FILE; | |
| 5677 | |
| 5678 my $fileContents = join('', @lines); | |
| 5679 return ($fileContents =~ /callback\s+interface\s+(\w+)\s*{/gs); | |
| 5680 } | |
| 5681 | |
| 5682 sub GetNativeTypeOfTypedArray | |
| 5683 { | |
| 5684 my $interface = shift; | |
| 5685 my $interfaceName = $interface->name; | |
| 5686 die "TypedArray of unknown type is found" unless $typedArrayHash{$interface-
>name}; | |
| 5687 return @{$typedArrayHash{$interface->name}}; | |
| 5688 } | |
| 5689 | |
| 5690 sub IsDOMNodeType | |
| 5691 { | |
| 5692 my $type = shift; | |
| 5693 | |
| 5694 return 1 if $domNodeTypes{$type}; | |
| 5695 return 1 if $type =~ /^HTML.*Element$/; | |
| 5696 return 1 if $type =~ /^SVG.*Element$/; | |
| 5697 | |
| 5698 return 0; | |
| 5699 } | |
| 5700 | |
| 5701 | |
| 5702 sub NativeToJSValue | |
| 5703 { | |
| 5704 my $type = shift; | |
| 5705 my $extendedAttributes = shift; | |
| 5706 my $nativeValue = shift; | |
| 5707 my $indent = shift; # added before every line | |
| 5708 my $receiver = shift; # "return" or "<variableName> =" | |
| 5709 my $getIsolate = shift; | |
| 5710 die "An Isolate is mandatory for native value => JS value conversion." unles
s $getIsolate; | |
| 5711 my $getCallbackInfo = shift || ""; | |
| 5712 my $creationContext = $getCallbackInfo ? "${getCallbackInfo}.Holder()" : "v8
::Handle<v8::Object>()"; | |
| 5713 my $getScriptWrappable = shift || ""; | |
| 5714 my $forMainWorldSuffix = shift || ""; | |
| 5715 my $returnValueArg = shift || 0; | |
| 5716 my $isReturnValue = $returnValueArg eq "return"; | |
| 5717 | |
| 5718 if (IsUnionType($type)) { | |
| 5719 my $types = $type->unionMemberTypes; | |
| 5720 my @codes = (); | |
| 5721 for my $i (0 .. scalar(@$types)-1) { | |
| 5722 my $unionMemberType = $types->[$i]; | |
| 5723 my $unionMemberNumber = $i + 1; | |
| 5724 my $unionMemberVariable = $nativeValue . $i; | |
| 5725 my $unionMemberEnabledVariable = $nativeValue . $i . "Enabled"; | |
| 5726 my $unionMemberNativeValue = $unionMemberVariable; | |
| 5727 $unionMemberNativeValue .= ".release()" if (IsRefPtrType($unionMembe
rType)); | |
| 5728 my $returnJSValueCode = NativeToJSValue($unionMemberType, $extendedA
ttributes, $unionMemberNativeValue, $indent . " ", $receiver, $getIsolate, $g
etCallbackInfo, $getScriptWrappable, $forMainWorldSuffix, $returnValueArg); | |
| 5729 my $code = ""; | |
| 5730 if ($isReturnValue) { | |
| 5731 $code .= "${indent}if (${unionMemberEnabledVariable}) {\n"; | |
| 5732 $code .= "${returnJSValueCode}\n"; | |
| 5733 $code .= "${indent} return;\n"; | |
| 5734 $code .= "${indent}}"; | |
| 5735 } else { | |
| 5736 $code .= "${indent}if (${unionMemberEnabledVariable})\n"; | |
| 5737 $code .= "${returnJSValueCode}"; | |
| 5738 } | |
| 5739 push @codes, $code; | |
| 5740 } | |
| 5741 if ($isReturnValue) { | |
| 5742 # Fall back to returning null if none of the union members results a
re returned. | |
| 5743 push @codes, "${indent}v8SetReturnValueNull(${getCallbackInfo});"; | |
| 5744 } | |
| 5745 return join "\n", @codes; | |
| 5746 } | |
| 5747 | |
| 5748 if ($type eq "boolean") { | |
| 5749 return "${indent}v8SetReturnValueBool(${getCallbackInfo}, ${nativeValue}
);" if $isReturnValue; | |
| 5750 return "$indent$receiver v8Boolean($nativeValue, $getIsolate);"; | |
| 5751 } | |
| 5752 | |
| 5753 if ($type eq "void") { # equivalent to v8Undefined() | |
| 5754 return "" if $isReturnValue; | |
| 5755 return "$indent$receiver v8Undefined();" | |
| 5756 } | |
| 5757 | |
| 5758 # HTML5 says that unsigned reflected attributes should be in the range | |
| 5759 # [0, 2^31). When a value isn't in this range, a default value (or 0) | |
| 5760 # should be returned instead. | |
| 5761 if ($extendedAttributes->{"Reflect"} and ($type eq "unsigned long" or $type
eq "unsigned short")) { | |
| 5762 $nativeValue =~ s/getUnsignedIntegralAttribute/getIntegralAttribute/g; | |
| 5763 return "${indent}v8SetReturnValueUnsigned(${getCallbackInfo}, std::max(0
, ${nativeValue}));" if $isReturnValue; | |
| 5764 return "$indent$receiver v8::Integer::NewFromUnsigned($getIsolate, std::
max(0, " . $nativeValue . "));"; | |
| 5765 } | |
| 5766 | |
| 5767 my $nativeType = GetNativeType($type); | |
| 5768 if ($nativeType eq "int") { | |
| 5769 return "${indent}v8SetReturnValueInt(${getCallbackInfo}, ${nativeValue})
;" if $isReturnValue; | |
| 5770 return "$indent$receiver v8::Integer::New($getIsolate, $nativeValue);"; | |
| 5771 } | |
| 5772 | |
| 5773 if ($nativeType eq "unsigned") { | |
| 5774 return "${indent}v8SetReturnValueUnsigned(${getCallbackInfo}, ${nativeVa
lue});" if $isReturnValue; | |
| 5775 return "$indent$receiver v8::Integer::NewFromUnsigned($getIsolate, $nati
veValue);"; | |
| 5776 } | |
| 5777 | |
| 5778 if ($type eq "Date") { | |
| 5779 return "${indent}v8SetReturnValue(${getCallbackInfo}, v8DateOrNull($nati
veValue, $getIsolate));" if $isReturnValue; | |
| 5780 return "$indent$receiver v8DateOrNull($nativeValue, $getIsolate);" | |
| 5781 } | |
| 5782 | |
| 5783 # long long and unsigned long long are not representable in ECMAScript. | |
| 5784 if ($type eq "long long" or $type eq "unsigned long long" or $type eq "DOMTi
meStamp") { | |
| 5785 return "${indent}v8SetReturnValue(${getCallbackInfo}, static_cast<double
>($nativeValue));" if $isReturnValue; | |
| 5786 return "$indent$receiver v8::Number::New($getIsolate, static_cast<double
>($nativeValue));"; | |
| 5787 } | |
| 5788 | |
| 5789 if ($type eq "DOMString" && $extendedAttributes->{"ReflectOnly"}) { | |
| 5790 my $code = "${indent}String resultValue = ${nativeValue};\n"; | |
| 5791 $code .= GenerateReflectOnlyCheck($extendedAttributes, ${indent}); | |
| 5792 return "${code}${indent}v8SetReturnValueString(${getCallbackInfo}, resul
tValue, $getIsolate);" if $isReturnValue; | |
| 5793 return "${code}$indent$receiver resultValue"; | |
| 5794 } | |
| 5795 | |
| 5796 my $conv = $extendedAttributes->{"TreatReturnedNullStringAs"}; | |
| 5797 if (($type eq "DOMString" || IsEnumType($type)) && $isReturnValue) { | |
| 5798 my $functionSuffix = ""; | |
| 5799 if (defined $conv) { | |
| 5800 if ($conv eq "Null") { | |
| 5801 $functionSuffix = "OrNull"; | |
| 5802 } elsif ($conv eq "Undefined") { | |
| 5803 $functionSuffix = "OrUndefined"; | |
| 5804 } else { | |
| 5805 die "Unknown value for TreatReturnedNullStringAs extended attrib
ute"; | |
| 5806 } | |
| 5807 } | |
| 5808 return "${indent}v8SetReturnValueString${functionSuffix}(${getCallbackIn
fo}, $nativeValue, $getIsolate);"; | |
| 5809 } | |
| 5810 | |
| 5811 if ($type eq "DOMString" or IsEnumType($type)) { | |
| 5812 my $returnValue = ""; | |
| 5813 if (defined $conv) { | |
| 5814 if ($conv eq "Null") { | |
| 5815 $returnValue = "v8StringOrNull($nativeValue, $getIsolate)"; | |
| 5816 } elsif ($conv eq "Undefined") { | |
| 5817 $returnValue = "v8StringOrUndefined($nativeValue, $getIsolate)"; | |
| 5818 } else { | |
| 5819 die "Unknown value for TreatReturnedNullStringAs extended attrib
ute"; | |
| 5820 } | |
| 5821 } else { | |
| 5822 $returnValue = "v8String($getIsolate, $nativeValue)"; | |
| 5823 } | |
| 5824 return "$indent$receiver $returnValue;"; | |
| 5825 } | |
| 5826 | |
| 5827 if (IsPrimitiveType($type)) { | |
| 5828 die "unexpected type $type" if not ($type eq "float" or $type eq "double
"); | |
| 5829 return "${indent}v8SetReturnValue(${getCallbackInfo}, ${nativeValue});"
if $isReturnValue; | |
| 5830 return "$indent$receiver v8::Number::New($getIsolate, $nativeValue);"; | |
| 5831 } | |
| 5832 | |
| 5833 if ($nativeType eq "ScriptValue" or $nativeType eq "ScriptPromise") { | |
| 5834 return "${indent}v8SetReturnValue(${getCallbackInfo}, ${nativeValue}.v8V
alue());" if $isReturnValue; | |
| 5835 return "$indent$receiver $nativeValue.v8Value();"; | |
| 5836 } | |
| 5837 | |
| 5838 my $arrayOrSequenceType = GetArrayOrSequenceType($type); | |
| 5839 | |
| 5840 if ($arrayOrSequenceType) { | |
| 5841 if (IsRefPtrType($arrayOrSequenceType)) { | |
| 5842 AddIncludesForType($arrayOrSequenceType); | |
| 5843 } | |
| 5844 return "${indent}v8SetReturnValue(${getCallbackInfo}, v8Array($nativeVal
ue, $getIsolate));" if $isReturnValue; | |
| 5845 return "$indent$receiver v8Array($nativeValue, $getIsolate);"; | |
| 5846 } | |
| 5847 | |
| 5848 AddIncludesForType($type); | |
| 5849 | |
| 5850 if ($type eq "SerializedScriptValue") { | |
| 5851 my $returnValue = "$nativeValue ? $nativeValue->deserialize() : v8::Hand
le<v8::Value>(v8::Null($getIsolate))"; | |
| 5852 return "${indent}v8SetReturnValue(${getCallbackInfo}, $returnValue);" if
$isReturnValue; | |
| 5853 return "$indent$receiver $returnValue;"; | |
| 5854 } | |
| 5855 | |
| 5856 if ($getScriptWrappable) { | |
| 5857 # FIXME: Use safe handles | |
| 5858 if ($isReturnValue) { | |
| 5859 if ($forMainWorldSuffix eq "ForMainWorld") { | |
| 5860 return "${indent}v8SetReturnValueForMainWorld(${getCallbackInfo}
, $nativeValue);"; | |
| 5861 } | |
| 5862 return "${indent}v8SetReturnValueFast(${getCallbackInfo}, $nativeVal
ue, $getScriptWrappable);"; | |
| 5863 } | |
| 5864 } | |
| 5865 # FIXME: Use safe handles | |
| 5866 return "${indent}v8SetReturnValue(${getCallbackInfo}, $nativeValue);" if $is
ReturnValue; | |
| 5867 return "$indent$receiver toV8($nativeValue, $creationContext, $getIsolate);"
; | |
| 5868 } | |
| 5869 | |
| 5870 sub WriteData | |
| 5871 { | |
| 5872 my $object = shift; | |
| 5873 my $interface = shift; | |
| 5874 my $outputDirectory = shift; | |
| 5875 | |
| 5876 my $name = $interface->name; | |
| 5877 my $headerFileName = "$outputDirectory/V8$name.h"; | |
| 5878 my $implFileName = "$outputDirectory/V8$name.cpp"; | |
| 5879 | |
| 5880 my @includes = (); | |
| 5881 foreach my $include (keys %implIncludes) { | |
| 5882 push @includes, "\"$include\""; | |
| 5883 } | |
| 5884 | |
| 5885 #FIXME: do not treat main header special | |
| 5886 my $mainInclude = "\"V8$name.h\""; | |
| 5887 foreach my $include (sort @includes) { | |
| 5888 $implementation{includes}->add("#include $include\n") unless $include eq
$mainInclude; | |
| 5889 } | |
| 5890 $implementation{includes}->add("\n") unless $interface->isCallback; | |
| 5891 WriteFileIfChanged($implFileName, $implementation{root}->toString()); | |
| 5892 | |
| 5893 %implIncludes = (); | |
| 5894 | |
| 5895 WriteFileIfChanged($headerFileName, $header{root}->toString()); | |
| 5896 } | |
| 5897 | |
| 5898 sub ConvertToV8StringResource | |
| 5899 { | |
| 5900 my $attributeOrParameter = shift; | |
| 5901 my $nativeType = shift; | |
| 5902 my $variableName = shift; | |
| 5903 my $value = shift; | |
| 5904 | |
| 5905 die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8String
Resource/; | |
| 5906 if ($attributeOrParameter->type eq "DOMString" or IsEnumType($attributeOrPar
ameter->type)) { | |
| 5907 return "V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID($nativeType, $variableName,
$value);" | |
| 5908 } else { | |
| 5909 return "$nativeType $variableName($value, true);"; | |
| 5910 } | |
| 5911 } | |
| 5912 | |
| 5913 # Returns the RuntimeEnabledFeatures function name that is hooked up to check if
a method/attribute is enabled. | |
| 5914 sub GetRuntimeEnabledFunctionName | |
| 5915 { | |
| 5916 my $signature = shift; | |
| 5917 | |
| 5918 # Given [RuntimeEnabled=FeatureName], | |
| 5919 # return RuntimeEnabledFeatures::{featureName}Enabled; | |
| 5920 my $featureName = ToMethodName($signature->extendedAttributes->{"RuntimeEnab
led"}); | |
| 5921 return "RuntimeEnabledFeatures::${featureName}Enabled"; | |
| 5922 } | |
| 5923 | |
| 5924 sub GetContextEnabledFunctionName | |
| 5925 { | |
| 5926 my $signature = shift; | |
| 5927 | |
| 5928 # Given [PerContextEnabled=FeatureName], | |
| 5929 # return ContextFeatures::{featureName}Enabled | |
| 5930 my $featureName = ToMethodName($signature->extendedAttributes->{"PerContextE
nabled"}); | |
| 5931 return "ContextFeatures::${featureName}Enabled"; | |
| 5932 } | |
| 5933 | |
| 5934 sub GetPassRefPtrType | |
| 5935 { | |
| 5936 my $interface = shift; | |
| 5937 my $nativeType = GetNativeTypeForConversions($interface); | |
| 5938 | |
| 5939 my $willBe = IsWillBeGarbageCollectedType($interface->name) ? "WillBeRawPtr"
: ""; | |
| 5940 my $extraSpace = $nativeType =~ />$/ ? " " : ""; | |
| 5941 return "PassRefPtr${willBe}<${nativeType}${extraSpace}>"; | |
| 5942 } | |
| 5943 | |
| 5944 sub WriteFileIfChanged | |
| 5945 { | |
| 5946 my $fileName = shift; | |
| 5947 my $contents = shift; | |
| 5948 | |
| 5949 if (-f $fileName && $writeFileOnlyIfChanged) { | |
| 5950 open FH, "<", $fileName or die "Couldn't open $fileName: $!\n"; | |
| 5951 my @lines = <FH>; | |
| 5952 my $oldContents = join "", @lines; | |
| 5953 close FH; | |
| 5954 return if $contents eq $oldContents; | |
| 5955 } | |
| 5956 open FH, ">", $fileName or die "Couldn't open $fileName: $!\n"; | |
| 5957 print FH $contents; | |
| 5958 close FH; | |
| 5959 } | |
| 5960 | |
| 5961 sub ForAllParents | |
| 5962 { | |
| 5963 my $interface = shift; | |
| 5964 my $beforeRecursion = shift; | |
| 5965 my $afterRecursion = shift; | |
| 5966 | |
| 5967 my $recurse; | |
| 5968 $recurse = sub { | |
| 5969 my $currentInterface = shift; | |
| 5970 | |
| 5971 if ($currentInterface->parent) { | |
| 5972 my $parentInterface = ParseInterface($currentInterface->parent); | |
| 5973 if ($beforeRecursion) { | |
| 5974 &$beforeRecursion($parentInterface) eq 'prune' and return; | |
| 5975 } | |
| 5976 &$recurse($parentInterface); | |
| 5977 &$afterRecursion($parentInterface) if $afterRecursion; | |
| 5978 } | |
| 5979 }; | |
| 5980 | |
| 5981 &$recurse($interface); | |
| 5982 } | |
| 5983 | |
| 5984 sub IsPrimitiveType | |
| 5985 { | |
| 5986 my $type = shift; | |
| 5987 | |
| 5988 return 1 if $integerTypeHash{$type}; | |
| 5989 return 1 if $primitiveTypeHash{$type}; | |
| 5990 return 0; | |
| 5991 } | |
| 5992 | |
| 5993 sub IsIntegerType | |
| 5994 { | |
| 5995 my $type = shift; | |
| 5996 | |
| 5997 return 1 if $integerTypeHash{$type}; | |
| 5998 return 0; | |
| 5999 } | |
| 6000 | |
| 6001 sub IsCallbackFunctionType | |
| 6002 { | |
| 6003 my $type = shift; | |
| 6004 | |
| 6005 return 1 if $callbackFunctionTypeHash{$type}; | |
| 6006 return 0; | |
| 6007 } | |
| 6008 | |
| 6009 sub IsEnumType | |
| 6010 { | |
| 6011 my $type = shift; | |
| 6012 | |
| 6013 return 1 if $enumTypeHash{$type}; | |
| 6014 return 0; | |
| 6015 } | |
| 6016 | |
| 6017 sub ValidEnumValues | |
| 6018 { | |
| 6019 my $type = shift; | |
| 6020 | |
| 6021 return @{$enumTypeHash{$type}}; | |
| 6022 } | |
| 6023 | |
| 6024 sub IsSVGTypeNeedingTearOff | |
| 6025 { | |
| 6026 my $type = shift; | |
| 6027 | |
| 6028 return 1 if $svgTypeNeedingTearOff{$type}; | |
| 6029 return 0; | |
| 6030 } | |
| 6031 | |
| 6032 sub IsTypedArrayType | |
| 6033 { | |
| 6034 my $type = shift; | |
| 6035 return 1 if $typedArrayHash{$type}; | |
| 6036 return 0; | |
| 6037 } | |
| 6038 | |
| 6039 sub IsWillBeGarbageCollectedType | |
| 6040 { | |
| 6041 my $interfaceName = shift; | |
| 6042 return 0 unless IsWrapperType($interfaceName); | |
| 6043 my $interface = ParseInterface($interfaceName); | |
| 6044 return InheritsExtendedAttribute($interface, "WillBeGarbageCollected"); | |
| 6045 } | |
| 6046 | |
| 6047 sub IsRefPtrType | |
| 6048 { | |
| 6049 my $type = shift; | |
| 6050 | |
| 6051 return 0 if $type eq "any"; | |
| 6052 return 0 if IsPrimitiveType($type); | |
| 6053 return 0 if GetArrayType($type); | |
| 6054 return 0 if GetSequenceType($type); | |
| 6055 return 0 if $type eq "Promise"; | |
| 6056 return 0 if IsCallbackFunctionType($type); | |
| 6057 return 0 if IsEnumType($type); | |
| 6058 return 0 if IsUnionType($type); | |
| 6059 return 0 if $type eq "Dictionary"; | |
| 6060 | |
| 6061 return 1; | |
| 6062 } | |
| 6063 | |
| 6064 sub IsNullableParameter | |
| 6065 { | |
| 6066 my $parameter = shift; | |
| 6067 | |
| 6068 return $parameter->isNullable && !IsRefPtrType($parameter->type) && $paramet
er->type ne "Dictionary"; | |
| 6069 } | |
| 6070 | |
| 6071 sub GetSVGTypeNeedingTearOff | |
| 6072 { | |
| 6073 my $type = shift; | |
| 6074 | |
| 6075 return $svgTypeNeedingTearOff{$type} if exists $svgTypeNeedingTearOff{$type}
; | |
| 6076 return undef; | |
| 6077 } | |
| 6078 | |
| 6079 sub GetSVGWrappedTypeNeedingTearOff | |
| 6080 { | |
| 6081 my $type = shift; | |
| 6082 | |
| 6083 my $svgTypeNeedingTearOff = GetSVGTypeNeedingTearOff($type); | |
| 6084 return $svgTypeNeedingTearOff if not $svgTypeNeedingTearOff; | |
| 6085 | |
| 6086 if ($svgTypeNeedingTearOff =~ /SVGPropertyTearOff/) { | |
| 6087 $svgTypeNeedingTearOff =~ s/SVGPropertyTearOff<//; | |
| 6088 } elsif ($svgTypeNeedingTearOff =~ /SVGListPropertyTearOff/) { | |
| 6089 $svgTypeNeedingTearOff =~ s/SVGListPropertyTearOff<//; | |
| 6090 } elsif ($svgTypeNeedingTearOff =~ /SVGStaticListPropertyTearOff/) { | |
| 6091 $svgTypeNeedingTearOff =~ s/SVGStaticListPropertyTearOff<//; | |
| 6092 } elsif ($svgTypeNeedingTearOff =~ /SVGTransformListPropertyTearOff/) { | |
| 6093 $svgTypeNeedingTearOff =~ s/SVGTransformListPropertyTearOff<//; | |
| 6094 } | |
| 6095 | |
| 6096 $svgTypeNeedingTearOff =~ s/>//; | |
| 6097 return $svgTypeNeedingTearOff; | |
| 6098 } | |
| 6099 | |
| 6100 sub IsSVGAnimatedType | |
| 6101 { | |
| 6102 my $type = shift; | |
| 6103 | |
| 6104 return $type =~ /^SVGAnimated/; | |
| 6105 } | |
| 6106 | |
| 6107 sub SVGTypeNeedsToHoldContextElement | |
| 6108 { | |
| 6109 my $type = shift; | |
| 6110 | |
| 6111 return IsSVGTypeNeedingTearOff($type) || IsSVGAnimatedType($type); | |
| 6112 } | |
| 6113 | |
| 6114 sub GetSequenceType | |
| 6115 { | |
| 6116 my $type = shift; | |
| 6117 | |
| 6118 return $1 if $type =~ /^sequence<([\w\d_\s]+)>.*/; | |
| 6119 return ""; | |
| 6120 } | |
| 6121 | |
| 6122 sub GetArrayType | |
| 6123 { | |
| 6124 my $type = shift; | |
| 6125 | |
| 6126 return $1 if $type =~ /^([\w\d_\s]+)\[\]/; | |
| 6127 return ""; | |
| 6128 } | |
| 6129 | |
| 6130 sub GetArrayOrSequenceType | |
| 6131 { | |
| 6132 my $type = shift; | |
| 6133 | |
| 6134 return GetArrayType($type) || GetSequenceType($type); | |
| 6135 } | |
| 6136 | |
| 6137 sub AssertNotSequenceType | |
| 6138 { | |
| 6139 my $type = shift; | |
| 6140 die "Sequences must not be used as the type of an attribute, constant or exc
eption field." if GetSequenceType($type); | |
| 6141 } | |
| 6142 | |
| 6143 sub FirstLetterToUpperCase | |
| 6144 { | |
| 6145 my $param = shift; | |
| 6146 my $ret = ucfirst($param); | |
| 6147 # Capitalize initial acronym, e.g., xml -> setXML | |
| 6148 $ret =~ s/Xml/XML/ if $ret =~ /^Xml/; | |
| 6149 $ret =~ s/Css/CSS/ if $ret =~ /^Css/; | |
| 6150 $ret =~ s/Html/HTML/ if $ret =~ /^Html/; | |
| 6151 $ret =~ s/Ime/IME/ if $ret =~ /^Ime/; | |
| 6152 $ret =~ s/Svg/SVG/ if $ret =~ /^Svg/; | |
| 6153 return $ret; | |
| 6154 } | |
| 6155 | |
| 6156 # URL becomes url, but SetURL becomes setURL. | |
| 6157 sub ToMethodName | |
| 6158 { | |
| 6159 my $param = shift; | |
| 6160 my $ret = lcfirst($param); | |
| 6161 $ret =~ s/hTML/html/ if $ret =~ /^hTML/; | |
| 6162 $ret =~ s/iME/ime/ if $ret =~ /^iME/; | |
| 6163 $ret =~ s/uRL/url/ if $ret =~ /^uRL/; | |
| 6164 $ret =~ s/jS/js/ if $ret =~ /^jS/; | |
| 6165 $ret =~ s/xML/xml/ if $ret =~ /^xML/; | |
| 6166 $ret =~ s/xSLT/xslt/ if $ret =~ /^xSLT/; | |
| 6167 $ret =~ s/cSS/css/ if $ret =~ /^cSS/; | |
| 6168 | |
| 6169 # For HTML5 FileSystem API Flags attributes. | |
| 6170 # (create is widely used to instantiate an object and must be avoided.) | |
| 6171 $ret =~ s/^create/isCreate/ if $ret =~ /^create$/; | |
| 6172 $ret =~ s/^exclusive/isExclusive/ if $ret =~ /^exclusive$/; | |
| 6173 | |
| 6174 return $ret; | |
| 6175 } | |
| 6176 | |
| 6177 sub NamespaceForAttributeName | |
| 6178 { | |
| 6179 my ($interfaceName, $attributeName) = @_; | |
| 6180 return "SVGNames" if $interfaceName =~ /^SVG/ && !$svgAttributesInHTMLHash{$
attributeName}; | |
| 6181 return "HTMLNames"; | |
| 6182 } | |
| 6183 | |
| 6184 # Identifies overloaded functions and for each function adds an array with | |
| 6185 # links to its respective overloads (including itself). | |
| 6186 sub LinkOverloadedFunctions | |
| 6187 { | |
| 6188 my $interface = shift; | |
| 6189 | |
| 6190 my %nameToFunctionsMap = (); | |
| 6191 foreach my $function (@{$interface->functions}) { | |
| 6192 my $name = $function->name; | |
| 6193 $nameToFunctionsMap{$name} = [] if !exists $nameToFunctionsMap{$name} or
!$name; # Nameless functions cannot be overloaded | |
| 6194 push(@{$nameToFunctionsMap{$name}}, $function); | |
| 6195 $function->{overloads} = $nameToFunctionsMap{$name}; | |
| 6196 $function->{overloadIndex} = @{$nameToFunctionsMap{$name}}; | |
| 6197 } | |
| 6198 } | |
| 6199 | |
| 6200 sub AttributeNameForGetterAndSetter | |
| 6201 { | |
| 6202 my $attribute = shift; | |
| 6203 | |
| 6204 my $attributeName = GetImplName($attribute); | |
| 6205 if ($attribute->extendedAttributes->{"ImplementedAs"}) { | |
| 6206 $attributeName = $attribute->extendedAttributes->{"ImplementedAs"}; | |
| 6207 } | |
| 6208 my $attributeType = $attribute->type; | |
| 6209 | |
| 6210 return $attributeName; | |
| 6211 } | |
| 6212 | |
| 6213 sub ContentAttributeName | |
| 6214 { | |
| 6215 my ($interfaceName, $attribute) = @_; | |
| 6216 | |
| 6217 my $contentAttributeName = $attribute->extendedAttributes->{"Reflect"}; | |
| 6218 return undef if !$contentAttributeName; | |
| 6219 | |
| 6220 $contentAttributeName = lc AttributeNameForGetterAndSetter($attribute) if $c
ontentAttributeName eq "VALUE_IS_MISSING"; | |
| 6221 | |
| 6222 my $namespace = NamespaceForAttributeName($interfaceName, $contentAttributeN
ame); | |
| 6223 | |
| 6224 AddToImplIncludes("${namespace}.h"); | |
| 6225 # Attr (not Attribute) used in core content attributes | |
| 6226 return "${namespace}::${contentAttributeName}Attr"; | |
| 6227 } | |
| 6228 | |
| 6229 sub GetterExpression | |
| 6230 { | |
| 6231 my ($interfaceName, $attribute) = @_; | |
| 6232 | |
| 6233 my $contentAttributeName = ContentAttributeName($interfaceName, $attribute); | |
| 6234 | |
| 6235 if (!$contentAttributeName) { | |
| 6236 return (ToMethodName(AttributeNameForGetterAndSetter($attribute))); | |
| 6237 } | |
| 6238 | |
| 6239 my $functionName; | |
| 6240 if ($attribute->extendedAttributes->{"URL"}) { | |
| 6241 $functionName = "getURLAttribute"; | |
| 6242 } elsif ($attribute->type eq "boolean") { | |
| 6243 $functionName = "fastHasAttribute"; | |
| 6244 } elsif ($attribute->type eq "long") { | |
| 6245 $functionName = "getIntegralAttribute"; | |
| 6246 } elsif ($attribute->type eq "unsigned long") { | |
| 6247 $functionName = "getUnsignedIntegralAttribute"; | |
| 6248 } else { | |
| 6249 if ($contentAttributeName eq "HTMLNames::idAttr") { | |
| 6250 $functionName = "getIdAttribute"; | |
| 6251 $contentAttributeName = ""; | |
| 6252 } elsif ($contentAttributeName eq "HTMLNames::nameAttr") { | |
| 6253 $functionName = "getNameAttribute"; | |
| 6254 $contentAttributeName = ""; | |
| 6255 } elsif ($contentAttributeName eq "HTMLNames::classAttr") { | |
| 6256 $functionName = "getClassAttribute"; | |
| 6257 $contentAttributeName = ""; | |
| 6258 } else { | |
| 6259 # We cannot use fast attributes for animated SVG types. | |
| 6260 $functionName = IsSVGAnimatedType($attribute->type) ? "getAttribute"
: "fastGetAttribute"; | |
| 6261 } | |
| 6262 } | |
| 6263 | |
| 6264 return ($functionName, $contentAttributeName); | |
| 6265 } | |
| 6266 | |
| 6267 sub SetterExpression | |
| 6268 { | |
| 6269 my ($interfaceName, $attribute) = @_; | |
| 6270 | |
| 6271 my $contentAttributeName = ContentAttributeName($interfaceName, $attribute); | |
| 6272 | |
| 6273 if (!$contentAttributeName) { | |
| 6274 return ("set" . FirstLetterToUpperCase(AttributeNameForGetterAndSetter($
attribute))); | |
| 6275 } | |
| 6276 | |
| 6277 my $functionName; | |
| 6278 if ($attribute->type eq "boolean") { | |
| 6279 $functionName = "setBooleanAttribute"; | |
| 6280 } elsif ($attribute->type eq "long") { | |
| 6281 $functionName = "setIntegralAttribute"; | |
| 6282 } elsif ($attribute->type eq "unsigned long") { | |
| 6283 $functionName = "setUnsignedIntegralAttribute"; | |
| 6284 } else { | |
| 6285 $functionName = "setAttribute"; | |
| 6286 } | |
| 6287 | |
| 6288 return ($functionName, $contentAttributeName); | |
| 6289 } | |
| 6290 | |
| 6291 sub GenerateConditionalString | |
| 6292 { | |
| 6293 my $node = shift; | |
| 6294 | |
| 6295 my $conditional = $node->extendedAttributes->{"Conditional"}; | |
| 6296 if ($conditional) { | |
| 6297 return GenerateConditionalStringFromAttributeValue($conditional); | |
| 6298 } else { | |
| 6299 return ""; | |
| 6300 } | |
| 6301 } | |
| 6302 | |
| 6303 sub GenerateConditionalStringFromAttributeValue | |
| 6304 { | |
| 6305 my $conditional = shift; | |
| 6306 | |
| 6307 my $operator = ($conditional =~ /&/ ? '&' : ($conditional =~ /\|/ ? '|' : ''
)); | |
| 6308 if ($operator) { | |
| 6309 # Avoid duplicated conditions. | |
| 6310 my %conditions; | |
| 6311 map { $conditions{$_} = 1 } split('\\' . $operator, $conditional); | |
| 6312 return "ENABLE(" . join(") $operator$operator ENABLE(", sort keys %condi
tions) . ")"; | |
| 6313 } else { | |
| 6314 return "ENABLE(" . $conditional . ")"; | |
| 6315 } | |
| 6316 } | |
| 6317 | |
| 6318 sub GenerateCompileTimeCheckForEnumsIfNeeded | |
| 6319 { | |
| 6320 my $interface = shift; | |
| 6321 my $implClassName = GetImplName($interface); | |
| 6322 my @checks = (); | |
| 6323 # If necessary, check that all constants are available as enums with the sam
e value. | |
| 6324 if (!$interface->extendedAttributes->{"DoNotCheckConstants"} && @{$interface
->constants}) { | |
| 6325 foreach my $constant (@{$interface->constants}) { | |
| 6326 my $reflect = $constant->extendedAttributes->{"Reflect"}; | |
| 6327 my $name = $reflect ? $reflect : $constant->name; | |
| 6328 my $value = $constant->value; | |
| 6329 | |
| 6330 if ($constant->extendedAttributes->{"ImplementedBy"}) { | |
| 6331 my $implementedByImplName = GetImplNameFromImplementedBy($consta
nt->extendedAttributes->{"ImplementedBy"}); | |
| 6332 push(@checks, " COMPILE_ASSERT($value == " . $implementedByIm
plName . "::$name, TheValueOf${implClassName}_${name}DoesntMatchWithImplementati
on);\n"); | |
| 6333 } else { | |
| 6334 push(@checks, " COMPILE_ASSERT($value == ${implClassName}::$n
ame, TheValueOf${implClassName}_${name}DoesntMatchWithImplementation);\n"); | |
| 6335 } | |
| 6336 } | |
| 6337 } | |
| 6338 return @checks; | |
| 6339 } | |
| 6340 | |
| 6341 sub GenerateReflectOnlyCheck | |
| 6342 { | |
| 6343 my $extendedAttributes = shift; | |
| 6344 my $indent = shift; | |
| 6345 | |
| 6346 my $attributeValueList = $extendedAttributes->{"ReflectOnly"}; | |
| 6347 my @knownValues = split(quotemeta("|"), $attributeValueList); | |
| 6348 | |
| 6349 my $missingValueDefault = $extendedAttributes->{"ReflectMissing"}; | |
| 6350 if ($missingValueDefault) { | |
| 6351 if (!grep { $_ eq $missingValueDefault } @knownValues) { | |
| 6352 die "The [ReflectMissing] attribute value '${missingValueDefault}' i
s not a known value "; | |
| 6353 } | |
| 6354 $missingValueDefault = "resultValue = \"${missingValueDefault}\""; | |
| 6355 } else { | |
| 6356 $missingValueDefault = ""; | |
| 6357 } | |
| 6358 | |
| 6359 my $invalidValueDefault = $extendedAttributes->{"ReflectInvalid"}; | |
| 6360 if ($invalidValueDefault) { | |
| 6361 if (!grep { $_ eq $invalidValueDefault } @knownValues) { | |
| 6362 die "The [ReflectInvalid] attribute value '${invalidValueDefault}' i
s not a known value "; | |
| 6363 } | |
| 6364 $invalidValueDefault = "resultValue = \"${invalidValueDefault}\""; | |
| 6365 } else { | |
| 6366 $invalidValueDefault = "resultValue = \"\""; | |
| 6367 } | |
| 6368 | |
| 6369 my @normalizeAttributeCode = (); | |
| 6370 | |
| 6371 # Attributes without a value (div empty-attribute>) can be | |
| 6372 # separately reflected to some value. | |
| 6373 | |
| 6374 my $isAttributeValueMissing = "resultValue.isEmpty()"; | |
| 6375 my $emptyValueDefault = $extendedAttributes->{"ReflectEmpty"}; | |
| 6376 if ($emptyValueDefault) { | |
| 6377 if (!grep { $_ eq $emptyValueDefault } @knownValues) { | |
| 6378 die "The [ReflectEmpty] attribute value '${emptyValueDefault}' is no
t a known value "; | |
| 6379 } | |
| 6380 $isAttributeValueMissing = "resultValue.isNull()"; | |
| 6381 push(@normalizeAttributeCode, "${indent}} else if (resultValue.isEmpty()
) {"); | |
| 6382 push(@normalizeAttributeCode, "${indent} resultValue = \"$emptyValueD
efault\";"); | |
| 6383 } | |
| 6384 | |
| 6385 # Attribute is limited to only known values: check that the attribute | |
| 6386 # value is one of those..and if not, set it to the empty string. | |
| 6387 # ( http://www.whatwg.org/specs/web-apps/current-work/#limited-to-only-known
-values ) | |
| 6388 # | |
| 6389 foreach my $knownValue (@knownValues) { | |
| 6390 push(@normalizeAttributeCode, "${indent}} else if (equalIgnoringCase(res
ultValue, \"$knownValue\")) {"); | |
| 6391 push(@normalizeAttributeCode, "${indent} resultValue = \"$knownValue\
";"); | |
| 6392 } | |
| 6393 my $normalizeAttributeValue = join("\n", @normalizeAttributeCode); | |
| 6394 my $code .= <<END; | |
| 6395 ${indent}if ($isAttributeValueMissing) { | |
| 6396 ${indent} $missingValueDefault; | |
| 6397 ${normalizeAttributeValue} | |
| 6398 ${indent}} else { | |
| 6399 ${indent} $invalidValueDefault; | |
| 6400 ${indent}} | |
| 6401 END | |
| 6402 return "${code}"; | |
| 6403 } | |
| 6404 | |
| 6405 sub ExtendedAttributeContains | |
| 6406 { | |
| 6407 my $extendedAttributeValue = shift; | |
| 6408 return 0 unless $extendedAttributeValue; | |
| 6409 my $keyword = shift; | |
| 6410 | |
| 6411 my @extendedAttributeValues = split /\s*(\&|\|)\s*/, $extendedAttributeValue
; | |
| 6412 return grep { $_ eq $keyword } @extendedAttributeValues; | |
| 6413 } | |
| 6414 | |
| 6415 sub InheritsInterface | |
| 6416 { | |
| 6417 my $interface = shift; | |
| 6418 my $interfaceName = shift; | |
| 6419 my $found = 0; | |
| 6420 | |
| 6421 return 1 if $interfaceName eq $interface->name; | |
| 6422 ForAllParents($interface, sub { | |
| 6423 my $currentInterface = shift; | |
| 6424 if ($currentInterface->name eq $interfaceName) { | |
| 6425 $found = 1; | |
| 6426 } | |
| 6427 return 1 if $found; | |
| 6428 }, 0); | |
| 6429 | |
| 6430 return $found; | |
| 6431 } | |
| 6432 | |
| 6433 sub InheritsExtendedAttribute | |
| 6434 { | |
| 6435 my $interface = shift; | |
| 6436 my $extendedAttribute = shift; | |
| 6437 my $found = 0; | |
| 6438 | |
| 6439 return 1 if $interface->extendedAttributes->{$extendedAttribute}; | |
| 6440 ForAllParents($interface, sub { | |
| 6441 my $currentInterface = shift; | |
| 6442 if ($currentInterface->extendedAttributes->{$extendedAttribute}) { | |
| 6443 $found = 1; | |
| 6444 } | |
| 6445 return 1 if $found; | |
| 6446 }, 0); | |
| 6447 | |
| 6448 return $found; | |
| 6449 } | |
| 6450 | |
| 6451 sub NeedsSpecialWrap | |
| 6452 { | |
| 6453 my $interface = shift; | |
| 6454 | |
| 6455 return 1 if ExtendedAttributeContains($interface->extendedAttributes->{"Cust
om"}, "ToV8"); | |
| 6456 return 1 if ExtendedAttributeContains($interface->extendedAttributes->{"Cust
om"}, "Wrap"); | |
| 6457 return 1 if $interface->extendedAttributes->{"SpecialWrapFor"}; | |
| 6458 return 1 if InheritsInterface($interface, "Document"); | |
| 6459 | |
| 6460 return 0; | |
| 6461 } | |
| 6462 | |
| 6463 sub HasExceptionRaisingParameter | |
| 6464 { | |
| 6465 my $function = shift; | |
| 6466 | |
| 6467 foreach my $parameter (@{$function->parameters}) { | |
| 6468 if ($parameter->type eq "SerializedScriptValue") { | |
| 6469 return 1; | |
| 6470 } elsif (IsIntegerType($parameter->type)) { | |
| 6471 return 1; | |
| 6472 } | |
| 6473 } | |
| 6474 return 0; | |
| 6475 } | |
| 6476 | |
| 6477 1; | |
| OLD | NEW |