1 2 # Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann (at] kde.org> 3 # Copyright (C) 2006 Anders Carlsson <andersca (at] mac.com> 4 # Copyright (C) 2006 Samuel Weinig <sam.weinig (at] gmail.com> 5 # Copyright (C) 2006 Alexey Proskuryakov <ap (at] webkit.org> 6 # Copyright (C) 2006 Apple Computer, Inc. 7 # Copyright (C) 2007, 2008, 2009 Google Inc. 8 # Copyright (C) 2009 Cameron McCormack <cam (at] mcc.id.au> 9 # 10 # This library is free software; you can redistribute it and/or 11 # modify it under the terms of the GNU Library General Public 12 # License as published by the Free Software Foundation; either 13 # version 2 of the License, or (at your option) any later version. 14 # 15 # This library is distributed in the hope that it will be useful, 16 # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 # Library General Public License for more details. 19 # 20 # You should have received a copy of the GNU Library General Public License 21 # aint with this library; see the file COPYING.LIB. If not, write to 22 # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 23 # Boston, MA 02111-1307, USA. 24 # 25 26 package CodeGeneratorV8; 27 28 use File::stat; 29 use Digest::MD5; 30 31 my $module = ""; 32 my $outputDir = ""; 33 34 my @headerContent = (); 35 my @implContentHeader = (); 36 my @implFixedHeader = (); 37 my @implContent = (); 38 my @implContentDecls = (); 39 my %implIncludes = (); 40 41 my @allParents = (); 42 43 # Default .h template 44 my $headerTemplate = << "EOF"; 45 /* 46 This file is part of the WebKit open source project. 47 This file has been generated by generate-bindings.pl. DO NOT MODIFY! 48 49 This library is free software; you can redistribute it and/or 50 modify it under the terms of the GNU Library General Public 51 License as published by the Free Software Foundation; either 52 version 2 of the License, or (at your option) any later version. 53 54 This library is distributed in the hope that it will be useful, 55 but WITHOUT ANY WARRANTY; without even the implied warranty of 56 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 57 Library General Public License for more details. 58 59 You should have received a copy of the GNU Library General Public License 60 along with this library; see the file COPYING.LIB. If not, write to 61 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 62 Boston, MA 02111-1307, USA. 63 */ 64 EOF 65 66 # Default constructor 67 sub new 68 { 69 my $object = shift; 70 my $reference = { }; 71 72 $codeGenerator = shift; 73 $outputDir = shift; 74 75 bless($reference, $object); 76 return $reference; 77 } 78 79 sub finish 80 { 81 my $object = shift; 82 83 # Commit changes! 84 $object->WriteData(); 85 } 86 87 sub leftShift($$) { 88 my ($value, $distance) = @_; 89 return (($value << $distance) & 0xFFFFFFFF); 90 } 91 92 # Workaround for V8 bindings difference where RGBColor is not a POD type. 93 sub IsPodType 94 { 95 my $type = shift; 96 return $codeGenerator->IsPodType($type); 97 } 98 99 # Params: 'domClass' struct 100 sub GenerateInterface 101 { 102 my $object = shift; 103 my $dataNode = shift; 104 my $defines = shift; 105 106 # Start actual generation 107 $object->GenerateHeader($dataNode); 108 $object->GenerateImplementation($dataNode); 109 110 my $name = $dataNode->name; 111 112 # Open files for writing 113 my $headerFileName = "$outputDir/V8$name.h"; 114 my $implFileName = "$outputDir/V8$name.cpp"; 115 116 open($IMPL, ">$implFileName") || die "Couldn't open file $implFileName"; 117 open($HEADER, ">$headerFileName") || die "Couldn't open file $headerFileName"; 118 } 119 120 # Params: 'idlDocument' struct 121 sub GenerateModule 122 { 123 my $object = shift; 124 my $dataNode = shift; 125 126 $module = $dataNode->module; 127 } 128 129 sub GetLegacyHeaderIncludes 130 { 131 my $legacyParent = shift; 132 133 die "Don't know what headers to include for module $module"; 134 } 135 136 sub AvoidInclusionOfType 137 { 138 my $type = shift; 139 140 # Special case: SVGRect.h / SVGPoint.h / SVGNumber.h / SVGMatrix.h do not exist. 141 return 1 if $type eq "SVGRect" or $type eq "SVGPoint" or $type eq "SVGNumber" or $type eq "SVGMatrix"; 142 return 0; 143 } 144 145 sub UsesManualToJSImplementation 146 { 147 my $type = shift; 148 149 return 1 if $type eq "SVGPathSeg"; 150 return 0; 151 } 152 153 sub AddIncludesForType 154 { 155 my $type = $codeGenerator->StripModule(shift); 156 157 # When we're finished with the one-file-per-class 158 # reorganization, we won't need these special cases. 159 if (!$codeGenerator->IsPrimitiveType($type) and !AvoidInclusionOfType($type) and $type ne "Date") { 160 # default, include the same named file 161 $implIncludes{GetV8HeaderName(${type})} = 1; 162 163 if ($type =~ /SVGPathSeg/) { 164 $joinedName = $type; 165 $joinedName =~ s/Abs|Rel//; 166 $implIncludes{"${joinedName}.h"} = 1; 167 } 168 } 169 170 # additional includes (things needed to compile the bindings but not the header) 171 172 if ($type eq "CanvasRenderingContext2D") { 173 $implIncludes{"CanvasGradient.h"} = 1; 174 $implIncludes{"CanvasPattern.h"} = 1; 175 $implIncludes{"CanvasStyle.h"} = 1; 176 } 177 178 if ($type eq "CanvasGradient" or $type eq "XPathNSResolver") { 179 $implIncludes{"PlatformString.h"} = 1; 180 } 181 182 if ($type eq "CSSStyleDeclaration") { 183 $implIncludes{"CSSMutableStyleDeclaration.h"} = 1; 184 } 185 186 if ($type eq "Plugin" or $type eq "PluginArray" or $type eq "MimeTypeArray") { 187 # So we can get String -> AtomicString conversion for namedItem(). 188 $implIncludes{"AtomicString.h"} = 1; 189 } 190 } 191 192 sub AddIncludesForSVGAnimatedType 193 { 194 my $type = shift; 195 $type =~ s/SVGAnimated//; 196 197 if ($type eq "Point" or $type eq "Rect") { 198 $implIncludes{"Float$type.h"} = 1; 199 } elsif ($type eq "String") { 200 $implIncludes{"PlatformString.h"} = 1; 201 } 202 203 $implIncludes{"SVGAnimatedTemplate.h"} = 1; 204 } 205 206 sub AddClassForwardIfNeeded 207 { 208 my $implClassName = shift; 209 210 # SVGAnimatedLength/Number/etc.. are typedefs to SVGAnimtatedTemplate, so don't use class forwards for them! 211 push(@headerContent, "class $implClassName;\n\n") unless $codeGenerator->IsSVGAnimatedType($implClassName); 212 } 213 214 # If the node has a [Conditional=XXX] attribute, returns an "ENABLE(XXX)" string for use in an #if. 215 sub GenerateConditionalString 216 { 217 my $node = shift; 218 my $conditional = $node->extendedAttributes->{"Conditional"}; 219 if ($conditional) { 220 return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; 221 } else { 222 return ""; 223 } 224 } 225 226 sub GenerateHeader 227 { 228 my $object = shift; 229 my $dataNode = shift; 230 231 my $interfaceName = $dataNode->name; 232 my $className = "V8$interfaceName"; 233 my $implClassName = $interfaceName; 234 235 # Copy contents of parent classes except the first parent or if it is 236 # EventTarget. 237 $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@allParents, 1); 238 239 my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"}; 240 my $conditionalString = GenerateConditionalString($dataNode); 241 242 # - Add default header template 243 @headerContent = split("\r", $headerTemplate); 244 245 push(@headerContent, "\n#if ${conditionalString}\n\n") if $conditionalString; 246 push(@headerContent, "\n#ifndef $className" . "_H"); 247 push(@headerContent, "\n#define $className" . "_H\n\n"); 248 249 # Get correct pass/store types respecting PODType flag 250 my $podType = $dataNode->extendedAttributes->{"PODType"}; 251 252 push(@headerContent, "#include \"$podType.h\"\n") if $podType and ($podType ne "double" and $podType ne "float" and $podType ne "RGBA32"); 253 254 push(@headerContent, "#include <v8.h>\n"); 255 push(@headerContent, "#include <wtf/HashMap.h>\n"); 256 push(@headerContent, "#include \"StringHash.h\"\n"); 257 push(@headerContent, "#include \"V8Index.h\"\n"); 258 push(@headerContent, GetHeaderClassInclude($implClassName)); 259 push(@headerContent, "\nnamespace WebCore {\n"); 260 if ($podType) { 261 push(@headerContent, "\ntemplate<typename PODType> class V8SVGPODTypeWrapper;\n"); 262 } 263 push(@headerContent, "\nclass $className {\n"); 264 265 my $nativeType = GetNativeTypeForConversions($interfaceName); 266 if ($podType) { 267 $nativeType = "V8SVGPODTypeWrapper<${nativeType} >"; 268 } 269 my $forceNewObjectParameter = IsDOMNodeType($interfaceName) ? ", bool forceNewObject = false" : ""; 270 push(@headerContent, <<END); 271 272 public: 273 static bool HasInstance(v8::Handle<v8::Value> value); 274 static v8::Persistent<v8::FunctionTemplate> GetRawTemplate(); 275 static v8::Persistent<v8::FunctionTemplate> GetTemplate(); 276 static ${nativeType}* toNative(v8::Handle<v8::Object>); 277 static v8::Handle<v8::Object> wrap(${nativeType}*${forceNewObjectParameter}); 278 END 279 280 if ($implClassName eq "DOMWindow") { 281 push(@headerContent, <<END); 282 static v8::Persistent<v8::ObjectTemplate> GetShadowObjectTemplate(); 283 END 284 } 285 286 my @enabledAtRuntime; 287 foreach my $function (@{$dataNode->functions}) { 288 my $name = $function->signature->name; 289 my $attrExt = $function->signature->extendedAttributes; 290 291 # FIXME: We should only be generating callback declarations for functions labeled [Custom] or [V8Custom], 292 # but we can't do that due to some mislabeled functions in the idl's (https://bugs.webkit.org/show_bug.cgi?id=33066). 293 push(@headerContent, <<END); 294 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments&); 295 END 296 if ($attrExt->{"EnabledAtRuntime"}) { 297 push(@enabledAtRuntime, $function); 298 } 299 } 300 301 if ($dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"CanBeConstructed"}) { 302 push(@headerContent, <<END); 303 static v8::Handle<v8::Value> constructorCallback(const v8::Arguments& args); 304 END 305 } 306 307 foreach my $attribute (@{$dataNode->attributes}) { 308 my $name = $attribute->signature->name; 309 my $attrExt = $attribute->signature->extendedAttributes; 310 if ($attrExt->{"V8CustomGetter"} || $attrExt->{"CustomGetter"} 311 || $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) { 312 push(@headerContent, <<END); 313 static v8::Handle<v8::Value> ${name}AccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info); 314 END 315 } 316 if ($attrExt->{"V8CustomSetter"} || $attrExt->{"CustomSetter"} 317 || $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) { 318 push(@headerContent, <<END); 319 static void ${name}AccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info); 320 END 321 } 322 if ($attrExt->{"EnabledAtRuntime"}) { 323 push(@enabledAtRuntime, $attribute); 324 } 325 } 326 327 GenerateHeaderNamedAndIndexedPropertyAccessors($dataNode); 328 GenerateHeaderCustomCall($dataNode); 329 GenerateHeaderCustomInternalFieldIndices($dataNode); 330 331 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) { 332 push(@headerContent, <<END); 333 static bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType, v8::Local<v8::Value> data); 334 static bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType, v8::Local<v8::Value> data); 335 END 336 } 337 338 push(@headerContent, <<END); 339 }; 340 341 v8::Handle<v8::Value> toV8(${nativeType}*${forceNewObjectParameter}); 342 END 343 if (IsRefPtrType($implClassName)) { 344 push(@headerContent, <<END); 345 v8::Handle<v8::Value> toV8(PassRefPtr<${nativeType} >${forceNewObjectParameter}); 346 END 347 } 348 349 push(@headerContent, "}\n\n"); 350 push(@headerContent, "#endif // $className" . "_H\n"); 351 352 push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString; 353 } 354 355 sub GetInternalFields 356 { 357 my $dataNode = shift; 358 my $name = $dataNode->name; 359 360 # FIXME: I am hideous and hard-coded. Make me beautiful. 361 return ("cacheIndex", "implementationIndex") if ($name eq "Document") || ($name eq "SVGDocument"); 362 return ("cacheIndex", "implementationIndex", "markerIndex", "shadowIndex") if $name eq "HTMLDocument"; 363 return ("cacheIndex") if IsNodeSubType($dataNode); 364 return ("cacheIndex") if $name eq "EventSource"; 365 return ("cacheIndex") if $name eq "XMLHttpRequest"; 366 return ("cacheIndex") if $name eq "XMLHttpRequestUpload"; 367 return ("cacheIndex") if $name eq "MessagePort"; 368 return ("port1Index", "port2Index") if ($name eq "MessageChannel"); 369 return ("cacheIndex") if $name eq "AbstractWorker"; 370 return ("abstractWorkerCacheIndex", "cacheIndex") if $name eq "Worker"; 371 return ("abstractWorkerCacheIndex", "cacheIndex") if $name eq "WorkerContext"; 372 return ("abstractWorkerCacheIndex", "workerContextCacheIndex", "cacheIndex") if $name eq "DedicatedWorkerContext"; 373 return ("abstractWorkerCacheIndex", "cacheIndex") if $name eq "SharedWorker"; 374 return ("abstractWorkerCacheIndex", "workerContextCacheIndex", "cacheIndex") if $name eq "SharedWorkerContext"; 375 return ("cacheIndex") if $name eq "Notification"; 376 return ("cacheIndex") if $name eq "IDBRequest"; 377 return ("cacheIndex") if $name eq "SVGElementInstance"; 378 return ("consoleIndex", "historyIndex", "locationbarIndex", "menubarIndex", "navigatorIndex", "personalbarIndex", 379 "screenIndex", "scrollbarsIndex", "selectionIndex", "statusbarIndex", "toolbarIndex", "locationIndex", 380 "domSelectionIndex", "cacheIndex", "enteredIsolatedWorldIndex") if $name eq "DOMWindow"; 381 return ("cacheIndex") if $name eq "DOMApplicationCache"; 382 return ("cacheIndex") if $name eq "WebSocket"; 383 return ("ownerNodeIndex") if ($name eq "StyleSheet") || ($name eq "CSSStyleSheet"); 384 return ("ownerNodeIndex") if ($name eq "NamedNodeMap"); 385 return (); 386 } 387 388 sub GetHeaderClassInclude 389 { 390 my $className = shift; 391 if ($className =~ /SVGPathSeg/) { 392 $className =~ s/Abs|Rel//; 393 } 394 return "" if (AvoidInclusionOfType($className)); 395 return "#include \"SVGAnimatedTemplate.h\"\n" if ($codeGenerator->IsSVGAnimatedType($className)); 396 return "#include \"${className}.h\"\n"; 397 } 398 399 sub GenerateHeaderCustomInternalFieldIndices 400 { 401 my $dataNode = shift; 402 my @customInternalFields = GetInternalFields($dataNode); 403 my $customFieldCounter = 0; 404 foreach my $customInternalField (@customInternalFields) { 405 push(@headerContent, <<END); 406 static const int ${customInternalField} = v8DefaultWrapperInternalFieldCount + ${customFieldCounter}; 407 END 408 $customFieldCounter++; 409 } 410 push(@headerContent, <<END); 411 static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + ${customFieldCounter}; 412 END 413 } 414 415 my %indexerSpecialCases = ( 416 "Storage" => 1, 417 "HTMLAppletElement" => 1, 418 "HTMLDocument" => 1, 419 "HTMLEmbedElement" => 1, 420 "HTMLObjectElement" => 1 421 ); 422 423 sub GenerateHeaderNamedAndIndexedPropertyAccessors 424 { 425 my $dataNode = shift; 426 my $interfaceName = $dataNode->name; 427 my $hasCustomIndexedGetter = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}; 428 my $hasCustomIndexedSetter = $dataNode->extendedAttributes->{"HasCustomIndexSetter"} && !$dataNode->extendedAttributes->{"HasNumericIndexGetter"}; 429 my $hasCustomNamedGetter = $dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}; 430 my $hasCustomNamedSetter = $dataNode->extendedAttributes->{"DelegatingPutFunction"}; 431 my $hasCustomDeleters = $dataNode->extendedAttributes->{"CustomDeleteProperty"}; 432 my $hasCustomEnumerator = $dataNode->extendedAttributes->{"CustomGetPropertyNames"}; 433 if ($interfaceName eq "HTMLOptionsCollection") { 434 $interfaceName = "HTMLCollection"; 435 $hasCustomIndexedGetter = 1; 436 $hasCustomNamedGetter = 1; 437 } 438 if ($interfaceName eq "DOMWindow") { 439 $hasCustomDeleterr = 0; 440 $hasEnumerator = 0; 441 } 442 if ($interfaceName eq "HTMLSelectElement") { 443 $hasCustomNamedGetter = 1; 444 } 445 my $isIndexerSpecialCase = exists $indexerSpecialCases{$interfaceName}; 446 447 if ($hasCustomIndexedGetter || $isIndexerSpecialCase) { 448 push(@headerContent, <<END); 449 static v8::Handle<v8::Value> indexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info); 450 END 451 } 452 453 if ($isIndexerSpecialCase || $hasCustomIndexedSetter) { 454 push(@headerContent, <<END); 455 static v8::Handle<v8::Value> indexedPropertySetter(uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info); 456 END 457 } 458 if ($hasCustomDeleters) { 459 push(@headerContent, <<END); 460 static v8::Handle<v8::Boolean> indexedPropertyDeleter(uint32_t index, const v8::AccessorInfo& info); 461 END 462 } 463 if ($hasCustomNamedGetter) { 464 push(@headerContent, <<END); 465 static v8::Handle<v8::Value> namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info); 466 END 467 } 468 if ($hasCustomNamedSetter) { 469 push(@headerContent, <<END); 470 static v8::Handle<v8::Value> namedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info); 471 END 472 } 473 if ($hasCustomDeleters || $interfaceName eq "HTMLDocument") { 474 push(@headerContent, <<END); 475 static v8::Handle<v8::Boolean> namedPropertyDeleter(v8::Local<v8::String> name, const v8::AccessorInfo& info); 476 END 477 } 478 if ($hasCustomEnumerator) { 479 push(@headerContent, <<END); 480 static v8::Handle<v8::Array> namedPropertyEnumerator(const v8::AccessorInfo& info); 481 END 482 } 483 } 484 485 sub GenerateHeaderCustomCall 486 { 487 my $dataNode = shift; 488 489 if ($dataNode->extendedAttributes->{"CustomCall"}) { 490 push(@headerContent, " static v8::Handle<v8::Value> callAsFunctionCallback(const v8::Arguments&);\n"); 491 } 492 if ($dataNode->name eq "Event") { 493 push(@headerContent, " static v8::Handle<v8::Value> dataTransferAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n"); 494 push(@headerContent, " static void valueAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info);\n"); 495 } 496 if ($dataNode->name eq "Location") { 497 push(@headerContent, " static v8::Handle<v8::Value> assignAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n"); 498 push(@headerContent, " static v8::Handle<v8::Value> reloadAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n"); 499 push(@headerContent, " static v8::Handle<v8::Value> replaceAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n"); 500 } 501 } 502 503 sub GenerateSetDOMException 504 { 505 my $indent = shift; 506 my $result = ""; 507 508 $result .= $indent . "if (UNLIKELY(ec)) {\n"; 509 $result .= $indent . " V8Proxy::setDOMException(ec);\n"; 510 $result .= $indent . " return v8::Handle<v8::Value>();\n"; 511 $result .= $indent . "}\n"; 512 513 return $result; 514 } 515 516 sub IsSubType 517 { 518 my $dataNode = shift; 519 my $parentType = shift; 520 return 1 if ($dataNode->name eq $parentType); 521 foreach (@allParents) { 522 my $parent = $codeGenerator->StripModule($_); 523 return 1 if $parent eq $parentType; 524 } 525 return 0; 526 } 527 528 sub IsNodeSubType 529 { 530 my $dataNode = shift; 531 return IsSubType($dataNode, "Node"); 532 } 533 534 sub IsEventSubType 535 { 536 my $dataNode = shift; 537 return IsSubType($dataNode, "Event"); 538 } 539 540 sub GenerateDomainSafeFunctionGetter 541 { 542 my $function = shift; 543 my $dataNode = shift; 544 my $implClassName = shift; 545 546 my $className = "V8" . $dataNode->name; 547 my $funcName = $function->signature->name; 548 549 my $signature = "v8::Signature::New(" . $className . "::GetRawTemplate())"; 550 if ($function->signature->extendedAttributes->{"V8DoNotCheckSignature"}) { 551 $signature = "v8::Local<v8::Signature>()"; 552 } 553 554 my $newTemplateString = GenerateNewFunctionTemplate($function, $dataNode, $signature); 555 556 push(@implContentDecls, <<END); 557 static v8::Handle<v8::Value> ${funcName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { 558 INC_STATS(\"DOM.$implClassName.$funcName._get\"); 559 static v8::Persistent<v8::FunctionTemplate> private_template = 560 v8::Persistent<v8::FunctionTemplate>::New($newTemplateString); 561 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(${className}::GetTemplate(), info.This()); 562 if (holder.IsEmpty()) { 563 // can only reach here by 'object.__proto__.func', and it should passed 564 // domain security check already 565 return private_template->GetFunction(); 566 } 567 ${implClassName}* imp = ${className}::toNative(holder); 568 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false)) { 569 static v8::Persistent<v8::FunctionTemplate> shared_template = 570 v8::Persistent<v8::FunctionTemplate>::New($newTemplateString); 571 return shared_template->GetFunction(); 572 573 } else { 574 return private_template->GetFunction(); 575 } 576 } 577 578 END 579 } 580 581 sub GenerateConstructorGetter 582 { 583 my $implClassName = shift; 584 my $classIndex = shift; 585 586 push(@implContentDecls, <<END); 587 static v8::Handle<v8::Value> ${implClassName}ConstructorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { 588 INC_STATS(\"DOM.$implClassName.constructors._get\"); 589 v8::Handle<v8::Value> data = info.Data(); 590 ASSERT(data->IsNumber()); 591 V8ClassIndex::V8WrapperType type = V8ClassIndex::FromInt(data->Int32Value()); 592 END 593 594 if ($classIndex eq "DOMWINDOW") { 595 push(@implContentDecls, <<END); 596 // Get the proxy corresponding to the DOMWindow if possible to 597 // make sure that the constructor function is constructed in the 598 // context of the DOMWindow and not in the context of the caller. 599 return V8DOMWrapper::getConstructor(type, V8DOMWindow::toNative(info.Holder())); 600 END 601 } elsif ($classIndex eq "DEDICATEDWORKERCONTEXT" or $classIndex eq "WORKERCONTEXT" or $classIndex eq "SHAREDWORKERCONTEXT") { 602 push(@implContentDecls, <<END); 603 return V8DOMWrapper::getConstructor(type, V8WorkerContext::toNative(info.Holder())); 604 END 605 } else { 606 push(@implContentDecls, " return v8::Handle<v8::Value>();"); 607 } 608 609 push(@implContentDecls, <<END); 610 611 } 612 613 END 614 } 615 616 sub GenerateNormalAttrGetter 617 { 618 my $attribute = shift; 619 my $dataNode = shift; 620 my $implClassName = shift; 621 my $interfaceName = shift; 622 623 my $attrExt = $attribute->signature->extendedAttributes; 624 625 my $attrName = $attribute->signature->name; 626 627 my $attrType = GetTypeFromSignature($attribute->signature); 628 my $attrIsPodType = IsPodType($attrType); 629 630 my $nativeType = GetNativeTypeFromSignature($attribute->signature, -1); 631 my $isPodType = IsPodType($implClassName); 632 my $skipContext = 0; 633 634 635 if ($isPodType) { 636 $implClassName = GetNativeType($implClassName); 637 $implIncludes{"V8SVGPODTypeWrapper.h"} = 1; 638 } 639 640 # Special case: SVGZoomEvent's attributes are all read-only 641 if ($implClassName eq "SVGZoomEvent") { 642 $attrIsPodType = 0; 643 $skipContext = 1; 644 } 645 646 # Special case: SVGSVGEelement::viewport is read-only 647 if (($implClassName eq "SVGSVGElement") and ($attrName eq "viewport")) { 648 $attrIsPodType = 0; 649 $skipContext = 1; 650 } 651 652 # Special case for SVGColor 653 if (($implClassName eq "SVGColor") and ($attrName eq "rgbColor")) { 654 $attrIsPodType = 0; 655 } 656 657 my $getterStringUsesImp = $implClassName ne "float"; 658 659 # Getter 660 push(@implContentDecls, <<END); 661 static v8::Handle<v8::Value> ${attrName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { 662 INC_STATS(\"DOM.$implClassName.$attrName._get\"); 663 END 664 665 if ($isPodType) { 666 push(@implContentDecls, <<END); 667 V8SVGPODTypeWrapper<$implClassName>* imp_wrapper = V8SVGPODTypeWrapper<$implClassName>::toNative(info.Holder()); 668 $implClassName imp_instance = *imp_wrapper; 669 END 670 if ($getterStringUsesImp) { 671 push(@implContentDecls, <<END); 672 $implClassName* imp = &imp_instance; 673 END 674 } 675 676 } elsif ($attrExt->{"v8OnProto"} || $attrExt->{"V8DisallowShadowing"}) { 677 if ($interfaceName eq "DOMWindow") { 678 push(@implContentDecls, <<END); 679 v8::Handle<v8::Object> holder = info.Holder(); 680 END 681 } else { 682 # perform lookup first 683 push(@implContentDecls, <<END); 684 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8${interfaceName}::GetTemplate(), info.This()); 685 if (holder.IsEmpty()) return v8::Handle<v8::Value>(); 686 END 687 } 688 push(@implContentDecls, <<END); 689 ${implClassName}* imp = V8${implClassName}::toNative(holder); 690 END 691 } else { 692 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; 693 if ($getterStringUsesImp && $reflect && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) { 694 # Generate super-compact call for regular attribute getter: 695 my $contentAttributeName = $reflect eq "1" ? $attrName : $reflect; 696 my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName); 697 $implIncludes{"${namespace}.h"} = 1; 698 push(@implContentDecls, " return getElementStringAttr(info, ${namespace}::${contentAttributeName}Attr);\n"); 699 push(@implContentDecls, " }\n\n"); 700 return; 701 # Skip the rest of the function! 702 } 703 push(@implContentDecls, <<END); 704 ${implClassName}* imp = V8${implClassName}::toNative(info.Holder()); 705 END 706 } 707 708 # Generate security checks if necessary 709 if ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) { 710 push(@implContentDecls, " if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->$attrName())) return v8::Handle<v8::Value>();\n\n"); 711 } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) { 712 push(@implContentDecls, " if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->contentDocument())) return v8::Handle<v8::Value>();\n\n"); 713 } 714 715 my $useExceptions = 1 if @{$attribute->getterExceptions} and !($isPodType); 716 if ($useExceptions) { 717 $implIncludes{"ExceptionCode.h"} = 1; 718 push(@implContentDecls, " ExceptionCode ec = 0;\n"); 719 } 720 721 if ($attribute->signature->extendedAttributes->{"v8referenceattr"}) { 722 $attrName = $attribute->signature->extendedAttributes->{"v8referenceattr"}; 723 } 724 725 my $getterFunc = $codeGenerator->WK_lcfirst($attrName); 726 727 if ($codeGenerator->IsSVGAnimatedType($attribute->signature->type)) { 728 # Some SVGFE*Element.idl use 'operator' as attribute name; rewrite as '_operator' to avoid clashes with C/C++ 729 $getterFunc = "_" . $getterFunc if ($attrName =~ /operator/); 730 $getterFunc .= "Animated"; 731 } 732 733 my $returnType = GetTypeFromSignature($attribute->signature); 734 735 my $getterString; 736 if ($getterStringUsesImp) { 737 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; 738 my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"}; 739 if ($reflect || $reflectURL) { 740 my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL); 741 my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName); 742 $implIncludes{"${namespace}.h"} = 1; 743 my $getAttributeFunctionName = $reflectURL ? "getURLAttribute" : "getAttribute"; 744 $getterString = "imp->$getAttributeFunctionName(${namespace}::${contentAttributeName}Attr"; 745 } else { 746 $getterString = "imp->$getterFunc("; 747 } 748 $getterString .= "ec" if $useExceptions; 749 $getterString .= ")"; 750 if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) { 751 $getterString .= ".toInt()"; 752 } 753 } else { 754 $getterString = "imp_instance"; 755 } 756 757 my $result; 758 my $wrapper; 759 760 if ($attrIsPodType) { 761 $implIncludes{"V8SVGPODTypeWrapper.h"} = 1; 762 763 my $getter = $getterString; 764 $getter =~ s/imp->//; 765 $getter =~ s/\(\)//; 766 my $setter = "set" . $codeGenerator->WK_ucfirst($getter); 767 768 my $implClassIsAnimatedType = $codeGenerator->IsSVGAnimatedType($implClassName); 769 if (not $implClassIsAnimatedType and $codeGenerator->IsPodTypeWithWriteableProperties($attrType) and not defined $attribute->signature->extendedAttributes->{"Immutable"}) { 770 if (IsPodType($implClassName)) { 771 my $wrapper = "V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($getterString, imp_wrapper)"; 772 push(@implContentDecls, " RefPtr<V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName> > wrapper = $wrapper;\n"); 773 } else { 774 my $wrapper = "V8SVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName>::create(imp, &${implClassName}::$getter, &${implClassName}::$setter)"; 775 push(@implContentDecls, " RefPtr<V8SVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName> > wrapper = $wrapper;\n"); 776 } 777 } else { 778 if ($implClassIsAnimatedType) { 779 # We can't hash member function pointers, so instead generate 780 # some hashing material based on the names of the methods. 781 my $hashhex = substr(Digest::MD5::md5_hex("${implClassName}::$getter ${implClassName}::$setter)"), 0, 8); 782 my $wrapper = "V8SVGDynamicPODTypeWrapperCache<$nativeType, $implClassName>::lookupOrCreateWrapper(imp, &${implClassName}::$getter, &${implClassName}::$setter, 0x$hashhex)"; 783 push(@implContentDecls, " RefPtr<V8SVGPODTypeWrapper<" . $nativeType . "> > wrapper = $wrapper;\n"); 784 } else { 785 my $wrapper = GenerateSVGStaticPodTypeWrapper($returnType, $getterString); 786 push(@implContentDecls, " RefPtr<V8SVGStaticPODTypeWrapper<" . $nativeType . "> > wrapper = $wrapper;\n"); 787 } 788 } 789 790 } else { 791 if ($attribute->signature->type eq "EventListener" && $dataNode->name eq "DOMWindow") { 792 push(@implContentDecls, " if (!imp->document())\n"); 793 push(@implContentDecls, " return v8::Handle<v8::Value>();\n"); 794 } 795 796 if ($useExceptions) { 797 push(@implContentDecls, " $nativeType v = "); 798 push(@implContentDecls, "$getterString;\n"); 799 push(@implContentDecls, GenerateSetDOMException(" ")); 800 $result = "v"; 801 $result .= ".release()" if (IsRefPtrType($returnType)); 802 } else { 803 # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary 804 $result = $getterString; 805 } 806 } 807 808 if (IsSVGTypeNeedingContextParameter($attrType) && !$skipContext) { 809 if ($attrIsPodType) { 810 push(@implContentDecls, GenerateSVGContextAssignment($implClassName, "wrapper.get()", " ")); 811 } else { 812 push(@implContentDecls, GenerateSVGContextRetrieval($implClassName, " ")); 813 # The templating associated with passing withSVGContext()'s return value directly into toV8 can get compilers confused, 814 # so just manually set the return value to a PassRefPtr of the expected type. 815 push(@implContentDecls, " PassRefPtr<$attrType> resultAsPassRefPtr = V8Proxy::withSVGContext($result, context);\n"); 816 $result = "resultAsPassRefPtr"; 817 } 818 } 819 820 if ($attrIsPodType) { 821 $implIncludes{"V8${attrType}.h"} = 1; 822 push(@implContentDecls, " return toV8(wrapper.release().get());\n"); 823 } else { 824 push(@implContentDecls, " " . ReturnNativeToJSValue($attribute->signature, $result, " ").";\n"); 825 } 826 827 push(@implContentDecls, " }\n\n"); # end of getter 828 } 829 830 831 sub GenerateReplaceableAttrSetter 832 { 833 my $implClassName = shift; 834 835 push(@implContentDecls, 836 " static void ${attrName}AttrSetter(v8::Local<v8::String> name," . 837 " v8::Local<v8::Value> value, const v8::AccessorInfo& info) {\n"); 838 839 push(@implContentDecls, " INC_STATS(\"DOM.$implClassName.$attrName._set\");\n"); 840 841 push(@implContentDecls, " v8::Local<v8::String> ${attrName}_string = v8::String::New(\"${attrName}\");\n"); 842 push(@implContentDecls, " info.Holder()->Delete(${attrName}_string);\n"); 843 push(@implContentDecls, " info.This()->Set(${attrName}_string, value);\n"); 844 push(@implContentDecls, " }\n\n"); 845 } 846 847 848 sub GenerateNormalAttrSetter 849 { 850 my $attribute = shift; 851 my $dataNode = shift; 852 my $implClassName = shift; 853 my $interfaceName = shift; 854 855 my $attrExt = $attribute->signature->extendedAttributes; 856 857 push(@implContentDecls, 858 " static void ${attrName}AttrSetter(v8::Local<v8::String> name," . 859 " v8::Local<v8::Value> value, const v8::AccessorInfo& info) {\n"); 860 861 push(@implContentDecls, " INC_STATS(\"DOM.$implClassName.$attrName._set\");\n"); 862 863 my $isPodType = IsPodType($implClassName); 864 865 if ($isPodType) { 866 $implClassName = GetNativeType($implClassName); 867 $implIncludes{"V8SVGPODTypeWrapper.h"} = 1; 868 push(@implContentDecls, " V8SVGPODTypeWrapper<$implClassName>* wrapper = V8SVGPODTypeWrapper<$implClassName>::toNative(info.Holder());\n"); 869 push(@implContentDecls, " $implClassName imp_instance = *wrapper;\n"); 870 push(@implContentDecls, " $implClassName* imp = &imp_instance;\n"); 871 872 } elsif ($attrExt->{"v8OnProto"}) { 873 if ($interfaceName eq "DOMWindow") { 874 push(@implContentDecls, <<END); 875 v8::Handle<v8::Object> holder = info.Holder(); 876 END 877 } else { 878 # perform lookup first 879 push(@implContentDecls, <<END); 880 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8${interfaceName}::GetTemplate(), info.This()); 881 if (holder.IsEmpty()) return; 882 END 883 } 884 push(@implContentDecls, <<END); 885 ${implClassName}* imp = V8${implClassName}::toNative(holder); 886 END 887 } else { 888 my $attrType = GetTypeFromSignature($attribute->signature); 889 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; 890 my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"}; 891 if (($reflect || $reflectURL) && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) { 892 # Generate super-compact call for regular attribute setter: 893 my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL); 894 my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName); 895 $implIncludes{"${namespace}.h"} = 1; 896 push(@implContentDecls, " setElementStringAttr(info, ${namespace}::${contentAttributeName}Attr, value);\n"); 897 push(@implContentDecls, " }\n\n"); 898 return; 899 # Skip the rest of the function! 900 } 901 902 push(@implContentDecls, <<END); 903 ${implClassName}* imp = V8${implClassName}::toNative(info.Holder()); 904 END 905 } 906 907 my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0); 908 if ($attribute->signature->type eq "EventListener") { 909 if ($dataNode->name eq "DOMWindow") { 910 push(@implContentDecls, " if (!imp->document())\n"); 911 push(@implContentDecls, " return;\n"); 912 } 913 } else { 914 push(@implContentDecls, " $nativeType v = " . JSValueToNative($attribute->signature, "value") . ";\n"); 915 } 916 917 my $result = ""; 918 if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) { 919 $result .= "WebCore::String::number("; 920 } 921 $result .= "v"; 922 if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) { 923 $result .= ")"; 924 } 925 my $returnType = GetTypeFromSignature($attribute->signature); 926 if (IsRefPtrType($returnType)) { 927 $result = "WTF::getPtr(" . $result . ")"; 928 } 929 930 my $useExceptions = 1 if @{$attribute->setterExceptions} and !($isPodType); 931 932 if ($useExceptions) { 933 $implIncludes{"ExceptionCode.h"} = 1; 934 push(@implContentDecls, " ExceptionCode ec = 0;\n"); 935 } 936 937 if ($implClassName eq "float") { 938 push(@implContentDecls, " *imp = $result;\n"); 939 } else { 940 my $implSetterFunctionName = $codeGenerator->WK_ucfirst($attrName); 941 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; 942 my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"}; 943 if ($reflect || $reflectURL) { 944 my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL); 945 my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName); 946 $implIncludes{"${namespace}.h"} = 1; 947 push(@implContentDecls, " imp->setAttribute(${namespace}::${contentAttributeName}Attr, $result"); 948 } elsif ($attribute->signature->type eq "EventListener") { 949 $implIncludes{"V8AbstractEventListener.h"} = 1; 950 push(@implContentDecls, " transferHiddenDependency(info.Holder(), imp->$attrName(), value, V8${interfaceName}::cacheIndex);\n"); 951 push(@implContentDecls, " imp->set$implSetterFunctionName(V8DOMWrapper::getEventListener(imp, value, true, ListenerFindOrCreate)"); 952 } else { 953 push(@implContentDecls, " imp->set$implSetterFunctionName($result"); 954 } 955 push(@implContentDecls, ", ec") if $useExceptions; 956 push(@implContentDecls, ");\n"); 957 } 958 959 if ($useExceptions) { 960 push(@implContentDecls, " if (UNLIKELY(ec))\n"); 961 push(@implContentDecls, " V8Proxy::setDOMException(ec);\n"); 962 } 963 964 if ($isPodType) { 965 push(@implContentDecls, " wrapper->commitChange(*imp, V8Proxy::svgContext(wrapper));\n"); 966 } elsif (IsSVGTypeNeedingContextParameter($implClassName)) { 967 $implIncludes{"SVGElement.h"} = 1; 968 969 my $currentObject = "imp"; 970 if ($isPodType) { 971 $currentObject = "wrapper"; 972 } 973 974 push(@implContentDecls, " if (SVGElement* context = V8Proxy::svgContext($currentObject)) {\n"); 975 push(@implContentDecls, " context->svgAttributeChanged(imp->associatedAttributeName());\n"); 976 push(@implContentDecls, " }\n"); 977 } 978 979 push(@implContentDecls, " return;\n"); 980 push(@implContentDecls, " }\n\n"); # end of setter 981 } 982 983 sub GetFunctionTemplateCallbackName 984 { 985 $function = shift; 986 $dataNode = shift; 987 988 my $interfaceName = $dataNode->name; 989 my $name = $function->signature->name; 990 991 if ($function->signature->extendedAttributes->{"Custom"} || 992 $function->signature->extendedAttributes->{"V8Custom"}) { 993 if ($function->signature->extendedAttributes->{"Custom"} && 994 $function->signature->extendedAttributes->{"V8Custom"}) { 995 die "Custom and V8Custom should be mutually exclusive!" 996 } 997 return "V8${interfaceName}::${name}Callback"; 998 } else { 999 return "${interfaceName}Internal::${name}Callback"; 1000 } 1001 } 1002 1003 sub GenerateNewFunctionTemplate 1004 { 1005 $function = shift; 1006 $dataNode = shift; 1007 $signature = shift; 1008 1009 my $callback = GetFunctionTemplateCallbackName($function, $dataNode); 1010 return "v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), $signature)"; 1011 } 1012 1013 sub GenerateFunctionCallback 1014 { 1015 my $function = shift; 1016 my $dataNode = shift; 1017 my $classIndex = shift; 1018 my $implClassName = shift; 1019 1020 my $interfaceName = $dataNode->name; 1021 my $name = $function->signature->name; 1022 1023 push(@implContentDecls, 1024 " static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args) {\n" . 1025 " INC_STATS(\"DOM.$implClassName.$name\");\n"); 1026 1027 my $numParameters = @{$function->parameters}; 1028 1029 if ($function->signature->extendedAttributes->{"RequiresAllArguments"}) { 1030 push(@implContentDecls, 1031 " if (args.Length() < $numParameters) return v8::Handle<v8::Value>();\n"); 1032 } 1033 1034 if (IsPodType($implClassName)) { 1035 my $nativeClassName = GetNativeType($implClassName); 1036 push(@implContentDecls, " V8SVGPODTypeWrapper<$nativeClassName>* imp_wrapper = V8SVGPODTypeWrapper<$nativeClassName>::toNative(args.Holder());\n"); 1037 push(@implContentDecls, " $nativeClassName imp_instance = *imp_wrapper;\n"); 1038 push(@implContentDecls, " $nativeClassName* imp = &imp_instance;\n"); 1039 } else { 1040 push(@implContentDecls, <<END); 1041 ${implClassName}* imp = V8${implClassName}::toNative(args.Holder()); 1042 END 1043 } 1044 1045 # Check domain security if needed 1046 if (($dataNode->extendedAttributes->{"CheckDomainSecurity"} 1047 || $interfaceName eq "DOMWindow") 1048 && !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) { 1049 # We have not find real use cases yet. 1050 push(@implContentDecls, 1051 " if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) {\n". 1052 " return v8::Handle<v8::Value>();\n" . 1053 " }\n"); 1054 } 1055 1056 my $raisesExceptions = @{$function->raisesExceptions}; 1057 if (!$raisesExceptions) { 1058 foreach my $parameter (@{$function->parameters}) { 1059 if (TypeCanFailConversion($parameter) or $parameter->extendedAttributes->{"IsIndex"}) { 1060 $raisesExceptions = 1; 1061 } 1062 } 1063 } 1064 1065 if ($raisesExceptions) { 1066 $implIncludes{"ExceptionCode.h"} = 1; 1067 push(@implContentDecls, " ExceptionCode ec = 0;\n"); 1068 push(@implContentDecls, " {\n"); 1069 # The brace here is needed to prevent the ensuing 'goto fail's from jumping past constructors 1070 # of objects (like Strings) declared later, causing compile errors. The block scope ends 1071 # right before the label 'fail:'. 1072 } 1073 1074 if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) { 1075 push(@implContentDecls, 1076 " OwnPtr<ScriptCallStack> callStack(ScriptCallStack::create(args, $numParameters));\n". 1077 " if (!callStack)\n". 1078 " return v8::Undefined();\n"); 1079 $implIncludes{"ScriptCallStack.h"} = 1; 1080 } 1081 if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) { 1082 push(@implContentDecls, 1083 " if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->getSVGDocument(ec)))\n" . 1084 " return v8::Handle<v8::Value>();\n"); 1085 } 1086 1087 my $paramIndex = 0; 1088 foreach my $parameter (@{$function->parameters}) { 1089 TranslateParameter($parameter); 1090 1091 my $parameterName = $parameter->name; 1092 1093 if ($parameter->extendedAttributes->{"Optional"}) { 1094 # Generate early call if there are not enough parameters. 1095 push(@implContentDecls, " if (args.Length() <= $paramIndex) {\n"); 1096 my $functionCall = GenerateFunctionCallString($function, $paramIndex, " " x 2, $implClassName); 1097 push(@implContentDecls, $functionCall); 1098 push(@implContentDecls, " }\n"); 1099 } 1100 1101 if (BasicTypeCanFailConversion($parameter)) { 1102 push(@implContentDecls, " bool ${parameterName}Ok;\n"); 1103 } 1104 1105 push(@implContentDecls, " " . GetNativeTypeFromSignature($parameter, $paramIndex) . " $parameterName = "); 1106 push(@implContentDecls, JSValueToNative($parameter, "args[$paramIndex]", 1107 BasicTypeCanFailConversion($parameter) ? "${parameterName}Ok" : undef) . ";\n"); 1108 1109 if (TypeCanFailConversion($parameter)) { 1110 $implIncludes{"ExceptionCode.h"} = 1; 1111 push(@implContentDecls, 1112 " if (UNLIKELY(!$parameterName" . (BasicTypeCanFailConversion($parameter) ? "Ok" : "") . ")) {\n" . 1113 " ec = TYPE_MISMATCH_ERR;\n" . 1114 " goto fail;\n" . 1115 " }\n"); 1116 } 1117 1118 if ($parameter->extendedAttributes->{"IsIndex"}) { 1119 $implIncludes{"ExceptionCode.h"} = 1; 1120 push(@implContentDecls, 1121 " if (UNLIKELY($parameterName < 0)) {\n" . 1122 " ec = INDEX_SIZE_ERR;\n" . 1123 " goto fail;\n" . 1124 " }\n"); 1125 } 1126 1127 $paramIndex++; 1128 } 1129 1130 # Build the function call string. 1131 my $callString = GenerateFunctionCallString($function, $paramIndex, " ", $implClassName); 1132 push(@implContentDecls, "$callString"); 1133 1134 if ($raisesExceptions) { 1135 push(@implContentDecls, " }\n"); 1136 push(@implContentDecls, " fail:\n"); 1137 push(@implContentDecls, " V8Proxy::setDOMException(ec);\n"); 1138 push(@implContentDecls, " return v8::Handle<v8::Value>();\n"); 1139 } 1140 1141 push(@implContentDecls, " }\n\n"); 1142 } 1143 1144 sub GenerateBatchedAttributeData 1145 { 1146 my $dataNode = shift; 1147 my $interfaceName = $dataNode->name; 1148 my $attributes = shift; 1149 1150 foreach my $attribute (@$attributes) { 1151 my $conditionalString = GenerateConditionalString($attribute->signature); 1152 push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString; 1153 GenerateSingleBatchedAttribute($interfaceName, $attribute, ",", ""); 1154 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; 1155 } 1156 } 1157 1158 sub GenerateSingleBatchedAttribute 1159 { 1160 my $interfaceName = shift; 1161 my $attribute = shift; 1162 my $delimiter = shift; 1163 my $indent = shift; 1164 my $attrName = $attribute->signature->name; 1165 my $attrExt = $attribute->signature->extendedAttributes; 1166 1167 my $accessControl = "v8::DEFAULT"; 1168 if ($attrExt->{"DoNotCheckDomainSecurityOnGet"}) { 1169 $accessControl = "v8::ALL_CAN_READ"; 1170 } elsif ($attrExt->{"DoNotCheckDomainSecurityOnSet"}) { 1171 $accessControl = "v8::ALL_CAN_WRITE"; 1172 } elsif ($attrExt->{"DoNotCheckDomainSecurity"}) { 1173 $accessControl = "v8::ALL_CAN_READ"; 1174 if (!($attribute->type =~ /^readonly/) && !($attrExt->{"V8ReadOnly"})) { 1175 $accessControl .= "|v8::ALL_CAN_WRITE"; 1176 } 1177 } 1178 if ($attrExt->{"V8DisallowShadowing"}) { 1179 $accessControl .= "|v8::PROHIBITS_OVERWRITING"; 1180 } 1181 $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")"; 1182 1183 my $customAccessor = 1184 $attrExt->{"Custom"} || 1185 $attrExt->{"CustomSetter"} || 1186 $attrExt->{"CustomGetter"} || 1187 $attrExt->{"V8Custom"} || 1188 $attrExt->{"V8CustomSetter"} || 1189 $attrExt->{"V8CustomGetter"} || 1190 ""; 1191 if ($customAccessor eq 1) { 1192 # use the naming convension, interface + (capitalize) attr name 1193 $customAccessor = $interfaceName . "::" . $attrName; 1194 } 1195 1196 my $getter; 1197 my $setter; 1198 my $propAttr = "v8::None"; 1199 my $hasCustomSetter = 0; 1200 1201 # Check attributes. 1202 if ($attrExt->{"DontEnum"}) { 1203 $propAttr .= "|v8::DontEnum"; 1204 } 1205 if ($attrExt->{"V8DisallowShadowing"}) { 1206 $propAttr .= "|v8::DontDelete"; 1207 } 1208 1209 my $on_proto = "0 /* on instance */"; 1210 my $data = "V8ClassIndex::INVALID_CLASS_INDEX /* no data */"; 1211 1212 # Constructor 1213 if ($attribute->signature->type =~ /Constructor$/) { 1214 my $constructorType = $codeGenerator->StripModule($attribute->signature->type); 1215 $constructorType =~ s/Constructor$//; 1216 my $constructorIndex = uc($constructorType); 1217 if ($customAccessor) { 1218 $getter = "V8${customAccessor}AccessorGetter"; 1219 } else { 1220 $data = "V8ClassIndex::${constructorIndex}"; 1221 $getter = "${interfaceName}Internal::${interfaceName}ConstructorGetter"; 1222 } 1223 $setter = "0"; 1224 $propAttr = "v8::ReadOnly"; 1225 1226 } else { 1227 # Default Getter and Setter 1228 $getter = "${interfaceName}Internal::${attrName}AttrGetter"; 1229 $setter = "${interfaceName}Internal::${attrName}AttrSetter"; 1230 1231 # Custom Setter 1232 if ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) { 1233 $hasCustomSetter = 1; 1234 $setter = "V8${customAccessor}AccessorSetter"; 1235 } 1236 1237 # Custom Getter 1238 if ($attrExt->{"CustomGetter"} || $attrExt->{"V8CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) { 1239 $getter = "V8${customAccessor}AccessorGetter"; 1240 } 1241 } 1242 1243 # Replaceable 1244 if ($attrExt->{"Replaceable"} && !$hasCustomSetter) { 1245 $setter = "0"; 1246 # Handle the special case of window.top being marked as Replaceable. 1247 # FIXME: Investigate whether we could treat window.top as replaceable 1248 # and allow shadowing without it being a security hole. 1249 if (!($interfaceName eq "DOMWindow" and $attrName eq "top")) { 1250 $propAttr .= "|v8::ReadOnly"; 1251 } 1252 } 1253 1254 # Read only attributes 1255 if ($attribute->type =~ /^readonly/ || $attrExt->{"V8ReadOnly"}) { 1256 $setter = "0"; 1257 } 1258 1259 # An accessor can be installed on the proto 1260 if ($attrExt->{"v8OnProto"}) { 1261 $on_proto = "1 /* on proto */"; 1262 } 1263 1264 my $commentInfo = "Attribute '$attrName' (Type: '" . $attribute->type . 1265 "' ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')"; 1266 1267 push(@implContent, $indent . " {\n"); 1268 push(@implContent, $indent . " \/\/ $commentInfo\n"); 1269 push(@implContent, $indent . " \"$attrName\",\n"); 1270 push(@implContent, $indent . " $getter,\n"); 1271 push(@implContent, $indent . " $setter,\n"); 1272 push(@implContent, $indent . " $data,\n"); 1273 push(@implContent, $indent . " $accessControl,\n"); 1274 push(@implContent, $indent . " static_cast<v8::PropertyAttribute>($propAttr),\n"); 1275 push(@implContent, $indent . " $on_proto\n"); 1276 push(@implContent, $indent . " }" . $delimiter . "\n"); 1277 END 1278 } 1279 1280 sub GenerateImplementationIndexer 1281 { 1282 my $dataNode = shift; 1283 my $indexer = shift; 1284 my $interfaceName = $dataNode->name; 1285 1286 # FIXME: Figure out what HasNumericIndexGetter is really supposed to do. Right now, it's only set on WebGL-related files. 1287 my $hasCustomSetter = $dataNode->extendedAttributes->{"HasCustomIndexSetter"} && !$dataNode->extendedAttributes->{"HasNumericIndexGetter"}; 1288 my $hasGetter = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}; 1289 1290 # FIXME: Find a way to not have to special-case HTMLOptionsCollection. 1291 if ($interfaceName eq "HTMLOptionsCollection") { 1292 $hasGetter = 1; 1293 } 1294 # FIXME: If the parent interface of $dataNode already has 1295 # HasIndexGetter, we don't need to handle the getter here. 1296 if ($interfaceName eq "WebKitCSSTransformValue") { 1297 $hasGetter = 0; 1298 } 1299 1300 # FIXME: Investigate and remove this nastinesss. In V8, named property handling and indexer handling are apparently decoupled, 1301 # which means that object[X] where X is a number doesn't reach named property indexer. So we need to provide 1302 # simplistic, mirrored indexer handling in addition to named property handling. 1303 my $isSpecialCase = exists $indexerSpecialCases{$interfaceName}; 1304 if ($isSpecialCase) { 1305 $hasGetter = 1; 1306 if ($dataNode->extendedAttributes->{"DelegatingPutFunction"}) { 1307 $hasCustomSetter = 1; 1308 } 1309 } 1310 1311 if (!$hasGetter) { 1312 return; 1313 } 1314 1315 $implIncludes{"V8Collection.h"} = 1; 1316 1317 my $indexerType = $indexer ? $indexer->type : 0; 1318 1319 # FIXME: Remove this once toV8 helper methods are implemented (see https://bugs.webkit.org/show_bug.cgi?id=32563). 1320 if ($interfaceName eq "WebKitCSSKeyframesRule") { 1321 $indexerType = "WebKitCSSKeyframeRule"; 1322 } 1323 1324 if ($indexerType && !$hasCustomSetter) { 1325 if ($indexerType eq "DOMString") { 1326 my $conversion = $indexer->extendedAttributes->{"ConvertNullStringTo"}; 1327 if ($conversion && $conversion eq "Null") { 1328 push(@implContent, <<END); 1329 setCollectionStringOrNullIndexedGetter<${interfaceName}>(desc); 1330 END 1331 } else { 1332 push(@implContent, <<END); 1333 setCollectionStringIndexedGetter<${interfaceName}>(desc); 1334 END 1335 } 1336 } else { 1337 my $indexerClassIndex = uc($indexerType); 1338 push(@implContent, <<END); 1339 setCollectionIndexedGetter<${interfaceName}, ${indexerType}>(desc, V8ClassIndex::${indexerClassIndex}); 1340 END 1341 # Include the header for this indexer type, because setCollectionIndexedGetter() requires toV8() for this type. 1342 $implIncludes{"V8${indexerType}.h"} = 1; 1343 } 1344 1345 return; 1346 } 1347 1348 my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"}; 1349 my $hasEnumerator = !$isSpecialCase && IsNodeSubType($dataNode); 1350 my $setOn = "Instance"; 1351 1352 # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow 1353 # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to 1354 # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set 1355 # on the object. 1356 if ($interfaceName eq "DOMWindow") { 1357 $setOn = "Prototype"; 1358 $hasDeleter = 0; 1359 } 1360 1361 push(@implContent, " desc->${setOn}Template()->SetIndexedPropertyHandler(V8${interfaceName}::indexedPropertyGetter"); 1362 push(@implContent, $hasCustomSetter ? ", V8${interfaceName}::indexedPropertySetter" : ", 0"); 1363 push(@implContent, ", 0"); # IndexedPropertyQuery -- not being used at the moment. 1364 push(@implContent, $hasDeleter ? ", V8${interfaceName}::indexedPropertyDeleter" : ", 0"); 1365 push(@implContent, ", nodeCollectionIndexedPropertyEnumerator<${interfaceName}>, v8::Integer::New(V8ClassIndex::NODE)") if $hasEnumerator; 1366 push(@implContent, ");\n"); 1367 } 1368 1369 sub GenerateImplementationNamedPropertyGetter 1370 { 1371 my $dataNode = shift; 1372 my $namedPropertyGetter = shift; 1373 my $interfaceName = $dataNode->name; 1374 my $hasCustomGetter = $dataNode->extendedAttributes->{"HasOverridingNameGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}; 1375 1376 # FIXME: Remove hard-coded HTMLOptionsCollection reference by changing HTMLOptionsCollection to not inherit 1377 # from HTMLCollection per W3C spec (http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/html.html#HTMLOptionsCollection). 1378 if ($interfaceName eq "HTMLOptionsCollection") { 1379 $interfaceName = "HTMLCollection"; 1380 $hasCustomGetter = 1; 1381 } 1382 1383 my $hasGetter = $dataNode->extendedAttributes->{"HasNameGetter"} || $hasCustomGetter || $namedPropertyGetter; 1384 if (!$hasGetter) { 1385 return; 1386 } 1387 1388 if ($namedPropertyGetter && $namedPropertyGetter->type ne "Node" && !$namedPropertyGetter->extendedAttributes->{"Custom"} && !$hasCustomGetter) { 1389 $implIncludes{"V8Collection.h"} = 1; 1390 my $type = $namedPropertyGetter->type; 1391 my $classIndex = uc($type); 1392 push(@implContent, <<END); 1393 setCollectionNamedGetter<${interfaceName}, ${type}>(desc, V8ClassIndex::${classIndex}); 1394 END 1395 return; 1396 } 1397 1398 my $hasSetter = $dataNode->extendedAttributes->{"DelegatingPutFunction"}; 1399 # FIXME: Try to remove hard-coded HTMLDocument reference by aligning handling of document.all with JSC bindings. 1400 my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"} || $interfaceName eq "HTMLDocument"; 1401 my $hasEnumerator = $dataNode->extendedAttributes->{"CustomGetPropertyNames"}; 1402 my $setOn = "Instance"; 1403 1404 # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow 1405 # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to 1406 # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set 1407 # on the object. 1408 if ($interfaceName eq "DOMWindow") { 1409 $setOn = "Prototype"; 1410 $hasDeleter = 0; 1411 $hasEnumerator = 0; 1412 } 1413 1414 push(@implContent, " desc->${setOn}Template()->SetNamedPropertyHandler(V8${interfaceName}::namedPropertyGetter, "); 1415 push(@implContent, $hasSetter ? "V8${interfaceName}::namedPropertySetter, " : "0, "); 1416 push(@implContent, "0, "); # NamedPropertyQuery -- not being used at the moment. 1417 push(@implContent, $hasDeleter ? "V8${interfaceName}::namedPropertyDeleter, " : "0, "); 1418 push(@implContent, $hasEnumerator ? "V8${interfaceName}::namedPropertyEnumerator" : "0"); 1419 push(@implContent, ");\n"); 1420 } 1421 1422 sub GenerateImplementationCustomCall 1423 { 1424 my $dataNode = shift; 1425 my $interfaceName = $dataNode->name; 1426 my $hasCustomCall = $dataNode->extendedAttributes->{"CustomCall"}; 1427 1428 # FIXME: Remove hard-coded HTMLOptionsCollection reference. 1429 if ($interfaceName eq "HTMLOptionsCollection") { 1430 $interfaceName = "HTMLCollection"; 1431 $hasCustomCall = 1; 1432 } 1433 1434 if ($hasCustomCall) { 1435 push(@implContent, " desc->InstanceTemplate()->SetCallAsFunctionHandler(V8${interfaceName}::callAsFunctionCallback);\n"); 1436 } 1437 } 1438 1439 sub GenerateImplementationMasqueradesAsUndefined 1440 { 1441 my $dataNode = shift; 1442 if ($dataNode->extendedAttributes->{"MasqueradesAsUndefined"}) 1443 { 1444 push(@implContent, " desc->InstanceTemplate()->MarkAsUndetectable();\n"); 1445 } 1446 } 1447 1448 sub GenerateImplementation 1449 { 1450 my $object = shift; 1451 my $dataNode = shift; 1452 my $interfaceName = $dataNode->name; 1453 my $className = "V8$interfaceName"; 1454 my $implClassName = $interfaceName; 1455 my $classIndex = uc($codeGenerator->StripModule($interfaceName)); 1456 1457 my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"}; 1458 my $conditionalString = GenerateConditionalString($dataNode); 1459 1460 # - Add default header template 1461 @implContentHeader = split("\r", $headerTemplate); 1462 1463 push(@implFixedHeader, 1464 "#include \"config.h\"\n" . 1465 "#include \"RuntimeEnabledFeatures.h\"\n" . 1466 "#include \"V8Proxy.h\"\n" . 1467 "#include \"V8Binding.h\"\n" . 1468 "#include \"V8BindingState.h\"\n" . 1469 "#include \"V8DOMWrapper.h\"\n" . 1470 "#include \"V8IsolatedContext.h\"\n\n" . 1471 "#undef LOG\n\n"); 1472 1473 push(@implFixedHeader, "\n#if ${conditionalString}\n\n") if $conditionalString; 1474 1475 if ($className =~ /^V8SVGAnimated/) { 1476 AddIncludesForSVGAnimatedType($interfaceName); 1477 } 1478 1479 $implIncludes{"${className}.h"} = 1; 1480 1481 AddIncludesForType($interfaceName); 1482 1483 push(@implContentDecls, "namespace WebCore {\n"); 1484 push(@implContentDecls, "namespace ${interfaceName}Internal {\n\n"); 1485 push(@implContentDecls, "template <typename T> void V8_USE(T) { }\n\n"); 1486 1487 my $hasConstructors = 0; 1488 # Generate property accessors for attributes. 1489 for ($index = 0; $index < @{$dataNode->attributes}; $index++) { 1490 $attribute = @{$dataNode->attributes}[$index]; 1491 $attrName = $attribute->signature->name; 1492 $attrType = $attribute->signature->type; 1493 1494 # Generate special code for the constructor attributes. 1495 if ($attrType =~ /Constructor$/) { 1496 if (!($attribute->signature->extendedAttributes->{"CustomGetter"} || 1497 $attribute->signature->extendedAttributes->{"V8CustomGetter"})) { 1498 $hasConstructors = 1; 1499 } 1500 next; 1501 } 1502 1503 if ($attrType eq "EventListener" && $interfaceName eq "DOMWindow") { 1504 $attribute->signature->extendedAttributes->{"v8OnProto"} = 1; 1505 } 1506 1507 # Do not generate accessor if this is a custom attribute. The 1508 # call will be forwarded to a hand-written accessor 1509 # implementation. 1510 if ($attribute->signature->extendedAttributes->{"Custom"} || 1511 $attribute->signature->extendedAttributes->{"V8Custom"}) { 1512 next; 1513 } 1514 1515 # Generate the accessor. 1516 if (!($attribute->signature->extendedAttributes->{"CustomGetter"} || 1517 $attribute->signature->extendedAttributes->{"V8CustomGetter"})) { 1518 GenerateNormalAttrGetter($attribute, $dataNode, $implClassName, $interfaceName); 1519 } 1520 if (!($attribute->signature->extendedAttributes->{"CustomSetter"} || 1521 $attribute->signature->extendedAttributes->{"V8CustomSetter"})) { 1522 if ($attribute->signature->extendedAttributes->{"Replaceable"}) { 1523 $dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"} || die "Replaceable attribute can only be used in interface that defines ExtendsDOMGlobalObject attribute!"; 1524 # GenerateReplaceableAttrSetter($implClassName); 1525 } elsif ($attribute->type !~ /^readonly/ && !$attribute->signature->extendedAttributes->{"V8ReadOnly"}) { 1526 GenerateNormalAttrSetter($attribute, $dataNode, $implClassName, $interfaceName); 1527 } 1528 } 1529 } 1530 1531 if ($hasConstructors) { 1532 GenerateConstructorGetter($implClassName, $classIndex); 1533 } 1534 1535 my $indexer; 1536 my $namedPropertyGetter; 1537 # Generate methods for functions. 1538 foreach my $function (@{$dataNode->functions}) { 1539 # hack for addEventListener/RemoveEventListener 1540 # FIXME: avoid naming conflict 1541 if (!($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"V8Custom"})) { 1542 GenerateFunctionCallback($function, $dataNode, $classIndex, $implClassName); 1543 } 1544 1545 if ($function->signature->name eq "item") { 1546 $indexer = $function->signature; 1547 } 1548 1549 if ($function->signature->name eq "namedItem") { 1550 $namedPropertyGetter = $function->signature; 1551 } 1552 1553 # If the function does not need domain security check, we need to 1554 # generate an access getter that returns different function objects 1555 # for different calling context. 1556 if (($dataNode->extendedAttributes->{"CheckDomainSecurity"} || ($interfaceName eq "DOMWindow")) && $function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) { 1557 GenerateDomainSafeFunctionGetter($function, $dataNode, $implClassName); 1558 } 1559 } 1560 1561 # Attributes 1562 my $attributes = $dataNode->attributes; 1563 1564 # For the DOMWindow interface we partition the attributes into the 1565 # ones that disallows shadowing and the rest. 1566 my @disallowsShadowing; 1567 # Also separate out attributes that are enabled at runtime so we can process them specially. 1568 my @enabledAtRuntime; 1569 my @normal; 1570 foreach my $attribute (@$attributes) { 1571 1572 if ($interfaceName eq "DOMWindow" && $attribute->signature->extendedAttributes->{"V8DisallowShadowing"}) { 1573 push(@disallowsShadowing, $attribute); 1574 } elsif ($attribute->signature->extendedAttributes->{"EnabledAtRuntime"}) { 1575 push(@enabledAtRuntime, $attribute); 1576 } else { 1577 push(@normal, $attribute); 1578 } 1579 } 1580 $attributes = \@normal; 1581 # Put the attributes that disallow shadowing on the shadow object. 1582 if (@disallowsShadowing) { 1583 push(@implContent, "static const BatchedAttribute shadow_attrs[] = {\n"); 1584 GenerateBatchedAttributeData($dataNode, \@disallowsShadowing); 1585 push(@implContent, "};\n"); 1586 } 1587 1588 my $has_attributes = 0; 1589 if (@$attributes) { 1590 $has_attributes = 1; 1591 push(@implContent, "static const BatchedAttribute ${interfaceName}_attrs[] = {\n"); 1592 GenerateBatchedAttributeData($dataNode, $attributes); 1593 push(@implContent, "};\n"); 1594 } 1595 1596 # Setup table of standard callback functions 1597 $num_callbacks = 0; 1598 $has_callbacks = 0; 1599 foreach my $function (@{$dataNode->functions}) { 1600 my $attrExt = $function->signature->extendedAttributes; 1601 # Don't put any nonstandard functions into this table: 1602 if ($attrExt->{"V8OnInstance"}) { 1603 next; 1604 } 1605 if ($attrExt->{"EnabledAtRuntime"} || RequiresCustomSignature($function) || $attrExt->{"V8DoNotCheckSignature"}) { 1606 next; 1607 } 1608 if ($attrExt->{"DoNotCheckDomainSecurity"} && 1609 ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) { 1610 next; 1611 } 1612 if ($attrExt->{"DontEnum"} || $attrExt->{"V8ReadOnly"}) { 1613 next; 1614 } 1615 if (!$has_callbacks) { 1616 $has_callbacks = 1; 1617 push(@implContent, "static const BatchedCallback ${interfaceName}_callbacks[] = {\n"); 1618 } 1619 my $name = $function->signature->name; 1620 my $callback = GetFunctionTemplateCallbackName($function, $dataNode); 1621 push(@implContent, <<END); 1622 {"$name", $callback}, 1623 END 1624 $num_callbacks++; 1625 } 1626 push(@implContent, "};\n") if $has_callbacks; 1627 1628 # Setup constants 1629 my $has_constants = 0; 1630 if (@{$dataNode->constants}) { 1631 $has_constants = 1; 1632 push(@implContent, "static const BatchedConstant ${interfaceName}_consts[] = {\n"); 1633 } 1634 foreach my $constant (@{$dataNode->constants}) { 1635 my $name = $constant->name; 1636 my $value = $constant->value; 1637 # FIXME: we need the static_cast here only because of one constant, NodeFilter.idl 1638 # defines "const unsigned long SHOW_ALL = 0xFFFFFFFF". It would be better if we 1639 # handled this here, and converted it to a -1 constant in the c++ output. 1640 push(@implContent, <<END); 1641 { "${name}", static_cast<signed int>($value) }, 1642 END 1643 } 1644 if ($has_constants) { 1645 push(@implContent, "};\n"); 1646 } 1647 1648 push(@implContentDecls, "} // namespace ${interfaceName}Internal\n\n"); 1649 1650 # In namespace WebCore, add generated implementation for 'CanBeConstructed'. 1651 if ($dataNode->extendedAttributes->{"CanBeConstructed"} && !$dataNode->extendedAttributes->{"CustomConstructor"}) { 1652 push(@implContent, <<END); 1653 v8::Handle<v8::Value> ${className}::constructorCallback(const v8::Arguments& args) 1654 { 1655 INC_STATS("DOM.${interfaceName}.Contructor"); 1656 return V8Proxy::constructDOMObject<V8ClassIndex::${classIndex}, $interfaceName>(args); 1657 } 1658 END 1659 } 1660 1661 my $access_check = ""; 1662 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !($interfaceName eq "DOMWindow")) { 1663 $access_check = "instance->SetAccessCheckCallbacks(V8${interfaceName}::namedSecurityCheck, V8${interfaceName}::indexedSecurityCheck, v8::Integer::New(V8ClassIndex::ToInt(V8ClassIndex::${classIndex})));"; 1664 } 1665 1666 # For the DOMWindow interface, generate the shadow object template 1667 # configuration method. 1668 if ($implClassName eq "DOMWindow") { 1669 push(@implContent, <<END); 1670 static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Persistent<v8::ObjectTemplate> templ) { 1671 batchConfigureAttributes(templ, 1672 v8::Handle<v8::ObjectTemplate>(), 1673 shadow_attrs, 1674 sizeof(shadow_attrs)/sizeof(*shadow_attrs)); 1675 1676 // Install a security handler with V8. 1677 templ->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::Integer::New(V8ClassIndex::DOMWINDOW)); 1678 templ->SetInternalFieldCount(V8DOMWindow::internalFieldCount); 1679 return templ; 1680 } 1681 END 1682 } 1683 1684 # find the super descriptor 1685 my $parentClassTemplate = ""; 1686 foreach (@{$dataNode->parents}) { 1687 my $parent = $codeGenerator->StripModule($_); 1688 if ($parent eq "EventTarget") { next; } 1689 $implIncludes{"V8${parent}.h"} = 1; 1690 $parentClassTemplate = "V8" . $parent . "::GetTemplate()"; 1691 last; 1692 } 1693 if (!$parentClassTemplate) { 1694 $parentClassTemplate = "v8::Persistent<v8::FunctionTemplate>()"; 1695 } 1696 1697 # Generate the template configuration method 1698 push(@implContent, <<END); 1699 static v8::Persistent<v8::FunctionTemplate> Configure${className}Template(v8::Persistent<v8::FunctionTemplate> desc) { 1700 v8::Local<v8::Signature> default_signature = configureTemplate(desc, \"${interfaceName}\", 1701 $parentClassTemplate, V8${interfaceName}::internalFieldCount, 1702 END 1703 # Set up our attributes if we have them 1704 if ($has_attributes) { 1705 push(@implContent, <<END); 1706 ${interfaceName}_attrs, sizeof(${interfaceName}_attrs)/sizeof(*${interfaceName}_attrs), 1707 END 1708 } else { 1709 push(@implContent, <<END); 1710 NULL, 0, 1711 END 1712 } 1713 1714 if ($has_callbacks) { 1715 push(@implContent, <<END); 1716 ${interfaceName}_callbacks, sizeof(${interfaceName}_callbacks)/sizeof(*${interfaceName}_callbacks)); 1717 END 1718 } else { 1719 push(@implContent, <<END); 1720 NULL, 0); 1721 END 1722 } 1723 1724 if ($dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"CanBeConstructed"}) { 1725 push(@implContent, <<END); 1726 desc->SetCallHandler(V8${interfaceName}::constructorCallback); 1727 END 1728 } 1729 1730 if ($access_check or @enabledAtRuntime or @{$dataNode->functions} or $has_constants) { 1731 push(@implContent, <<END); 1732 v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate(); 1733 v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate(); 1734 END 1735 } 1736 1737 push(@implContent, " $access_check\n"); 1738 1739 # Setup the enable-at-runtime attrs if we have them 1740 foreach my $runtime_attr (@enabledAtRuntime) { 1741 # A function named RuntimeEnabledFeatures::{methodName}Enabled() need to be written by hand. 1742 $enable_function = "RuntimeEnabledFeatures::" . $codeGenerator->WK_lcfirst($runtime_attr->signature->name) . "Enabled"; 1743 my $conditionalString = GenerateConditionalString($runtime_attr->signature); 1744 push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString; 1745 push(@implContent, " if (${enable_function}()) {\n"); 1746 push(@implContent, " static const BatchedAttribute attrData =\\\n"); 1747 GenerateSingleBatchedAttribute($interfaceName, $runtime_attr, ";", " "); 1748 push(@implContent, <<END); 1749 configureAttribute(instance, proto, attrData); 1750 } 1751 END 1752 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; 1753 } 1754 1755 GenerateImplementationIndexer($dataNode, $indexer); 1756 GenerateImplementationNamedPropertyGetter($dataNode, $namedPropertyGetter); 1757 GenerateImplementationCustomCall($dataNode); 1758 GenerateImplementationMasqueradesAsUndefined($dataNode); 1759 1760 # Define our functions with Set() or SetAccessor() 1761 $total_functions = 0; 1762 foreach my $function (@{$dataNode->functions}) { 1763 $total_functions++; 1764 my $attrExt = $function->signature->extendedAttributes; 1765 my $name = $function->signature->name; 1766 1767 my $property_attributes = "v8::DontDelete"; 1768 if ($attrExt->{"DontEnum"}) { 1769 $property_attributes .= "|v8::DontEnum"; 1770 } 1771 if ($attrExt->{"V8ReadOnly"}) { 1772 $property_attributes .= "|v8::ReadOnly"; 1773 } 1774 1775 my $commentInfo = "Function '$name' (ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')"; 1776 1777 my $template = "proto"; 1778 if ($attrExt->{"V8OnInstance"}) { 1779 $template = "instance"; 1780 } 1781 1782 my $conditional = ""; 1783 if ($attrExt->{"EnabledAtRuntime"}) { 1784 # Only call Set()/SetAccessor() if this method should be enabled 1785 $enable_function = "RuntimeEnabledFeatures::" . $codeGenerator->WK_lcfirst($function->signature->name) . "Enabled"; 1786 $conditional = "if (${enable_function}())\n"; 1787 } 1788 1789 if ($attrExt->{"DoNotCheckDomainSecurity"} && 1790 ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) { 1791 # Mark the accessor as ReadOnly and set it on the proto object so 1792 # it can be shadowed. This is really a hack to make it work. 1793 # There are several sceneria to call into the accessor: 1794 # 1) from the same domain: "window.open": 1795 # the accessor finds the DOM wrapper in the proto chain; 1796 # 2) from the same domain: "window.__proto__.open": 1797 # the accessor will NOT find a DOM wrapper in the prototype chain 1798 # 3) from another domain: "window.open": 1799 # the access find the DOM wrapper in the prototype chain 1800 # "window.__proto__.open" from another domain will fail when 1801 # accessing '__proto__' 1802 # 1803 # The solution is very hacky and fragile, it really needs to be replaced 1804 # by a better solution. 1805 $property_attributes .= "|v8::ReadOnly"; 1806 push(@implContent, <<END); 1807 1808 // $commentInfo 1809 $conditional $template->SetAccessor( 1810 v8::String::New("$name"), 1811 ${interfaceName}Internal::${name}AttrGetter, 1812 0, 1813 v8::Handle<v8::Value>(), 1814 v8::ALL_CAN_READ, 1815 static_cast<v8::PropertyAttribute>($property_attributes)); 1816 END 1817 $num_callbacks++; 1818 next; 1819 } 1820 1821 my $signature = "default_signature"; 1822 if ($attrExt->{"V8DoNotCheckSignature"}){ 1823 $signature = "v8::Local<v8::Signature>()"; 1824 } 1825 1826 if (RequiresCustomSignature($function)) { 1827 $signature = "${name}_signature"; 1828 push(@implContent, "\n // Custom Signature '$name'\n", CreateCustomSignature($function)); 1829 } 1830 1831 # Normal function call is a template 1832 my $callback = GetFunctionTemplateCallbackName($function, $dataNode); 1833 1834 if ($property_attributes eq "v8::DontDelete") { 1835 $property_attributes = ""; 1836 } else { 1837 $property_attributes = ", static_cast<v8::PropertyAttribute>($property_attributes)"; 1838 } 1839 1840 if ($template eq "proto" && $conditional eq "" && $signature eq "default_signature" && $property_attributes eq "") { 1841 # Standard type of callback, already created in the batch, so skip it here. 1842 next; 1843 } 1844 1845 push(@implContent, <<END); 1846 ${conditional}$template->Set(v8::String::New("$name"), v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), ${signature})$property_attributes); 1847 END 1848 $num_callbacks++; 1849 } 1850 1851 die "Wrong number of callbacks generated for $interfaceName ($num_callbacks, should be $total_functions)" if $num_callbacks != $total_functions; 1852 1853 if ($has_constants) { 1854 push(@implContent, <<END); 1855 batchConfigureConstants(desc, proto, ${interfaceName}_consts, sizeof(${interfaceName}_consts)/sizeof(*${interfaceName}_consts)); 1856 END 1857 } 1858 1859 # Special cases 1860 if ($interfaceName eq "DOMWindow") { 1861 push(@implContent, <<END); 1862 1863 proto->SetInternalFieldCount(V8DOMWindow::internalFieldCount); 1864 desc->SetHiddenPrototype(true); 1865 instance->SetInternalFieldCount(V8DOMWindow::internalFieldCount); 1866 // Set access check callbacks, but turned off initially. 1867 // When a context is detached from a frame, turn on the access check. 1868 // Turning on checks also invalidates inline caches of the object. 1869 instance->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::Integer::New(V8ClassIndex::DOMWINDOW), false); 1870 END 1871 } 1872 if ($interfaceName eq "Location") { 1873 push(@implContent, <<END); 1874 1875 // For security reasons, these functions are on the instance instead 1876 // of on the prototype object to insure that they cannot be overwritten. 1877 instance->SetAccessor(v8::String::New("reload"), V8Location::reloadAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly)); 1878 instance->SetAccessor(v8::String::New("replace"), V8Location::replaceAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly)); 1879 instance->SetAccessor(v8::String::New("assign"), V8Location::assignAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly)); 1880 END 1881 } 1882 1883 my $nativeType = GetNativeTypeForConversions($interfaceName); 1884 if ($dataNode->extendedAttributes->{"PODType"}) { 1885 $nativeType = "V8SVGPODTypeWrapper<${nativeType}>"; 1886 } 1887 push(@implContent, <<END); 1888 1889 // Custom toString template 1890 desc->Set(getToStringName(), getToStringTemplate()); 1891 return desc; 1892 } 1893 1894 v8::Persistent<v8::FunctionTemplate> ${className}::GetRawTemplate() { 1895 static v8::Persistent<v8::FunctionTemplate> ${className}_raw_cache_ = createRawTemplate(); 1896 return ${className}_raw_cache_; 1897 } 1898 1899 v8::Persistent<v8::FunctionTemplate> ${className}::GetTemplate() { 1900 static v8::Persistent<v8::FunctionTemplate> ${className}_cache_ = Configure${className}Template(GetRawTemplate()); 1901 return ${className}_cache_; 1902 } 1903 1904 ${nativeType}* ${className}::toNative(v8::Handle<v8::Object> object) { 1905 return reinterpret_cast<${nativeType}*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex)); 1906 } 1907 1908 bool ${className}::HasInstance(v8::Handle<v8::Value> value) { 1909 return GetRawTemplate()->HasInstance(value); 1910 } 1911 1912 END 1913 1914 if ($implClassName eq "DOMWindow") { 1915 push(@implContent, <<END); 1916 v8::Persistent<v8::ObjectTemplate> V8DOMWindow::GetShadowObjectTemplate() { 1917 static v8::Persistent<v8::ObjectTemplate> V8DOMWindowShadowObject_cache_; 1918 if (V8DOMWindowShadowObject_cache_.IsEmpty()) { 1919 V8DOMWindowShadowObject_cache_ = v8::Persistent<v8::ObjectTemplate>::New(v8::ObjectTemplate::New()); 1920 ConfigureShadowObjectTemplate(V8DOMWindowShadowObject_cache_); 1921 } 1922 return V8DOMWindowShadowObject_cache_; 1923 } 1924 END 1925 } 1926 1927 GenerateToV8Converters($dataNode, $interfaceName, $className, $nativeType); 1928 1929 push(@implContent, <<END); 1930 } // namespace WebCore 1931 END 1932 1933 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; 1934 } 1935 1936 sub GenerateToV8Converters 1937 { 1938 my $dataNode = shift; 1939 my $interfaceName = shift; 1940 my $className = shift; 1941 my $nativeType = shift; 1942 1943 my $wrapperType = "V8ClassIndex::" . uc($interfaceName); 1944 my $domMapFunction = GetDomMapFunction($dataNode, $interfaceName); 1945 my $forceNewObjectInput = IsDOMNodeType($interfaceName) ? ", bool forceNewObject" : ""; 1946 my $forceNewObjectCall = IsDOMNodeType($interfaceName) ? ", forceNewObject" : ""; 1947 1948 push(@implContent, <<END); 1949 1950 v8::Handle<v8::Object> ${className}::wrap(${nativeType}* impl${forceNewObjectInput}) { 1951 v8::Handle<v8::Object> wrapper; 1952 V8Proxy* proxy = 0; 1953 END 1954 1955 if (IsNodeSubType($dataNode)) { 1956 push(@implContent, <<END); 1957 if (impl->document()) { 1958 proxy = V8Proxy::retrieve(impl->document()->frame()); 1959 if (proxy && static_cast<Node*>(impl->document()) == static_cast<Node*>(impl)) 1960 proxy->windowShell()->initContextIfNeeded(); 1961 } 1962 1963 END 1964 } 1965 1966 if ($domMapFunction) { 1967 push(@implContent, " if (!forceNewObject) {\n") if IsDOMNodeType($interfaceName); 1968 if (IsNodeSubType($dataNode)) { 1969 push(@implContent, " wrapper = V8DOMWrapper::getWrapper(impl);\n"); 1970 } else { 1971 push(@implContent, " wrapper = ${domMapFunction}.get(impl);\n"); 1972 } 1973 push(@implContent, <<END); 1974 if (!wrapper.IsEmpty()) 1975 return wrapper; 1976 END 1977 push(@implContent, " }\n") if IsDOMNodeType($interfaceName); 1978 } 1979 if (IsNodeSubType($dataNode)) { 1980 push(@implContent, <<END); 1981 1982 v8::Handle<v8::Context> context; 1983 if (proxy) 1984 context = proxy->context(); 1985 1986 // Enter the node's context and create the wrapper in that context. 1987 if (!context.IsEmpty()) 1988 context->Enter(); 1989 END 1990 } 1991 1992 push(@implContent, <<END); 1993 wrapper = V8DOMWrapper::instantiateV8Object(proxy, ${wrapperType}, impl); 1994 END 1995 1996 if (IsNodeSubType($dataNode)) { 1997 push(@implContent, <<END); 1998 // Exit the node's context if it was entered. 1999 if (!context.IsEmpty()) 2000 context->Exit(); 2001 END 2002 } 2003 2004 push(@implContent, <<END); 2005 if (wrapper.IsEmpty()) 2006 return wrapper; 2007 END 2008 push(@implContent, "\n impl->ref();\n") if IsRefPtrType($interfaceName); 2009 2010 if ($domMapFunction) { 2011 push(@implContent, <<END); 2012 ${domMapFunction}.set(impl, v8::Persistent<v8::Object>::New(wrapper)); 2013 END 2014 } 2015 2016 push(@implContent, <<END); 2017 return wrapper; 2018 } 2019 END 2020 2021 if (IsRefPtrType($interfaceName)) { 2022 push(@implContent, <<END); 2023 2024 v8::Handle<v8::Value> toV8(PassRefPtr<${nativeType} > impl${forceNewObjectInput}) { 2025 return toV8(impl.get()${forceNewObjectCall}); 2026 } 2027 END 2028 } 2029 2030 if (!HasCustomToV8Implementation($dataNode, $interfaceName)) { 2031 push(@implContent, <<END); 2032 2033 v8::Handle<v8::Value> toV8(${nativeType}* impl${forceNewObjectInput}) { 2034 if (!impl) 2035 return v8::Null(); 2036 return ${className}::wrap(impl${forceNewObjectCall}); 2037 } 2038 END 2039 } 2040 } 2041 2042 sub HasCustomToV8Implementation { 2043 # FIXME: This subroutine is lame. Probably should be an .idl attribute (CustomToV8)? 2044 $dataNode = shift; 2045 $interfaceName = shift; 2046 2047 # We generate a custom converter (but JSC doesn't) for the following: 2048 return 1 if $interfaceName eq "BarInfo"; 2049 return 1 if $interfaceName eq "CSSStyleSheet"; 2050 return 1 if $interfaceName eq "CanvasPixelArray"; 2051 return 1 if $interfaceName eq "DOMSelection"; 2052 return 1 if $interfaceName eq "DOMWindow"; 2053 return 1 if $interfaceName eq "Element"; 2054 return 1 if $interfaceName eq "Location"; 2055 return 1 if $interfaceName eq "HTMLDocument"; 2056 return 1 if $interfaceName eq "HTMLElement"; 2057 return 1 if $interfaceName eq "History"; 2058 return 1 if $interfaceName eq "NamedNodeMap"; 2059 return 1 if $interfaceName eq "Navigator"; 2060 return 1 if $interfaceName eq "SVGDocument"; 2061 return 1 if $interfaceName eq "SVGElement"; 2062 return 1 if $interfaceName eq "Screen"; 2063 return 1 if $interfaceName eq "WorkerContext"; 2064 # We don't generate a custom converter (but JSC does) for the following: 2065 return 0 if $interfaceName eq "AbstractWorker"; 2066 return 0 if $interfaceName eq "CanvasRenderingContext"; 2067 return 0 if $interfaceName eq "ImageData"; 2068 return 0 if $interfaceName eq "SVGElementInstance"; 2069 2070 # For everything else, do what JSC does. 2071 return $dataNode->extendedAttributes->{"CustomToJS"}; 2072 } 2073 2074 sub GetDomMapFunction 2075 { 2076 my $dataNode = shift; 2077 my $type = shift; 2078 return "getDOMSVGElementInstanceMap()" if $type eq "SVGElementInstance"; 2079 return "getDOMNodeMap()" if IsNodeSubType($dataNode); 2080 # Only use getDOMSVGObjectWithContextMap() for non-node svg objects 2081 return "getDOMSVGObjectWithContextMap()" if $type =~ /SVG/; 2082 return "" if $type eq "DOMImplementation"; 2083 return "getActiveDOMObjectMap()" if IsActiveDomType($type); 2084 return "getDOMObjectMap()"; 2085 } 2086 2087 sub IsActiveDomType 2088 { 2089 # FIXME: Consider making this an .idl attribute. 2090 my $type = shift; 2091 return 1 if $type eq "MessagePort"; 2092 return 1 if $type eq "XMLHttpRequest"; 2093 return 1 if $type eq "WebSocket"; 2094 return 1 if $type eq "Worker"; 2095 return 1 if $type eq "SharedWorker"; 2096 return 0; 2097 } 2098 2099 sub GetNativeTypeForConversions 2100 { 2101 my $type = shift; 2102 return "FloatRect" if $type eq "SVGRect"; 2103 return "FloatPoint" if $type eq "SVGPoint"; 2104 return "AffineTransform" if $type eq "SVGMatrix"; 2105 return "float" if $type eq "SVGNumber"; 2106 return $type; 2107 } 2108 2109 sub GenerateFunctionCallString() 2110 { 2111 my $function = shift; 2112 my $numberOfParameters = shift; 2113 my $indent = shift; 2114 my $implClassName = shift; 2115 2116 my $name = $function->signature->name; 2117 my $isPodType = IsPodType($implClassName); 2118 my $returnType = GetTypeFromSignature($function->signature); 2119 my $returnsPodType = IsPodType($returnType); 2120 my $nativeReturnType = GetNativeType($returnType, 0); 2121 my $result = ""; 2122 2123 # Special case: SVG matrix transform methods should not mutate 2124 # the matrix but return a copy 2125 my $copyFirst = 0; 2126 if ($implClassName eq "SVGMatrix" && $function->signature->type eq "SVGMatrix") { 2127 $copyFirst = 1; 2128 } 2129 2130 if ($function->signature->extendedAttributes->{"v8implname"}) { 2131 $name = $function->signature->extendedAttributes->{"v8implname"}; 2132 } 2133 2134 if ($function->signature->extendedAttributes->{"ImplementationFunction"}) { 2135 $name = $function->signature->extendedAttributes->{"ImplementationFunction"}; 2136 } 2137 2138 my $functionString = "imp->${name}("; 2139 2140 if ($copyFirst) { 2141 $functionString = "result.${name}("; 2142 } 2143 2144 my $returnsListItemPodType = 0; 2145 # SVG lists functions that return POD types require special handling 2146 if (IsSVGListTypeNeedingSpecialHandling($implClassName) && IsSVGListMethod($name) && $returnsPodType) { 2147 $returnsListItemPodType = 1; 2148 $result .= $indent . "SVGList<RefPtr<SVGPODListItem<$nativeReturnType> > >* listImp = imp;\n"; 2149 $functionString = "listImp->${name}("; 2150 } 2151 2152 my $first = 1; 2153 my $index = 0; 2154 2155 foreach my $parameter (@{$function->parameters}) { 2156 if ($index eq $numberOfParameters) { 2157 last; 2158 } 2159 if ($first) { $first = 0; } 2160 else { $functionString .= ", "; } 2161 my $paramName = $parameter->name; 2162 my $paramType = $parameter->type; 2163 2164 # This is a bit of a hack... we need to convert parameters to methods on SVG lists 2165 # of POD types which are items in the list to appropriate SVGList<> instances 2166 if ($returnsListItemPodType && $paramType . "List" eq $implClassName) { 2167 $paramName = "SVGPODListItem<" . GetNativeType($paramType, 1) . ">::copy($paramName)"; 2168 } 2169 2170 if ($parameter->type eq "NodeFilter" || $parameter->type eq "XPathNSResolver") { 2171 $functionString .= "$paramName.get()"; 2172 } else { 2173 $functionString .= $paramName; 2174 } 2175 $index++; 2176 } 2177 2178 if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) { 2179 $functionString .= ", " if not $first; 2180 $functionString .= "callStack.get()"; 2181 if ($first) { $first = 0; } 2182 } 2183 2184 if ($function->signature->extendedAttributes->{"NeedsUserGestureCheck"}) { 2185 $functionString .= ", " if not $first; 2186 # FIXME: We need to pass DOMWrapperWorld as a parameter. 2187 # See http://trac.webkit.org/changeset/54182 2188 $functionString .= "processingUserGesture()"; 2189 if ($first) { $first = 0; } 2190 } 2191 2192 if (@{$function->raisesExceptions}) { 2193 $functionString .= ", " if not $first; 2194 $functionString .= "ec"; 2195 } 2196 $functionString .= ")"; 2197 2198 my $return = "result"; 2199 my $returnIsRef = IsRefPtrType($returnType); 2200 2201 if ($returnType eq "void") { 2202 $result .= $indent . "$functionString;\n"; 2203 } elsif ($copyFirst) { 2204 $result .= 2205 $indent . GetNativeType($returnType, 0) . " result = *imp;\n" . 2206 $indent . "$functionString;\n"; 2207 } elsif ($returnsListItemPodType) { 2208 $result .= $indent . "RefPtr<SVGPODListItem<$nativeReturnType> > result = $functionString;\n"; 2209 } elsif (@{$function->raisesExceptions} or $returnsPodType or $isPodType or IsSVGTypeNeedingContextParameter($returnType)) { 2210 $result .= $indent . $nativeReturnType . " result = $functionString;\n"; 2211 } else { 2212 # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary 2213 $return = $functionString; 2214 $returnIsRef = 0; 2215 } 2216 2217 if (@{$function->raisesExceptions}) { 2218 $result .= $indent . "if (UNLIKELY(ec)) goto fail;\n"; 2219 } 2220 2221 # If the return type is a POD type, separate out the wrapper generation 2222 if ($returnsListItemPodType) { 2223 $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = "; 2224 $result .= "V8SVGPODTypeWrapperCreatorForList<" . $nativeReturnType . ">::create($return, imp->associatedAttributeName());\n"; 2225 $return = "wrapper"; 2226 } elsif ($returnsPodType) { 2227 $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = "; 2228 $result .= GenerateSVGStaticPodTypeWrapper($returnType, $return) . ";\n"; 2229 $return = "wrapper"; 2230 } 2231 2232 my $generatedSVGContextRetrieval = 0; 2233 # If the return type needs an SVG context, output it 2234 if (IsSVGTypeNeedingContextParameter($returnType)) { 2235 $result .= GenerateSVGContextAssignment($implClassName, $return . ".get()", $indent); 2236 $generatedSVGContextRetrieval = 1; 2237 } 2238 2239 if (IsSVGTypeNeedingContextParameter($implClassName) && $implClassName =~ /List$/ && IsSVGListMutator($name)) { 2240 if (!$generatedSVGContextRetrieval) { 2241 $result .= GenerateSVGContextRetrieval($implClassName, $indent); 2242 $generatedSVGContextRetrieval = 1; 2243 } 2244 2245 $result .= $indent . "context->svgAttributeChanged(imp->associatedAttributeName());\n"; 2246 $implIncludes{"SVGElement.h"} = 1; 2247 } 2248 2249 # If the implementing class is a POD type, commit changes 2250 if ($isPodType) { 2251 if (!$generatedSVGContextRetrieval) { 2252 $result .= GenerateSVGContextRetrieval($implClassName, $indent); 2253 $generatedSVGContextRetrieval = 1; 2254 } 2255 2256 $result .= $indent . "imp_wrapper->commitChange(imp_instance, context);\n"; 2257 } 2258 2259 if ($returnsPodType) { 2260 $implIncludes{"V8${returnType}.h"} = 1; 2261 $result .= $indent . "return toV8(wrapper.release());\n"; 2262 } else { 2263 $return .= ".release()" if ($returnIsRef); 2264 $result .= $indent . ReturnNativeToJSValue($function->signature, $return, $indent) . ";\n"; 2265 } 2266 2267 return $result; 2268 } 2269 2270 2271 sub GetTypeFromSignature 2272 { 2273 my $signature = shift; 2274 2275 return $codeGenerator->StripModule($signature->type); 2276 } 2277 2278 2279 sub GetNativeTypeFromSignature 2280 { 2281 my $signature = shift; 2282 my $parameterIndex = shift; 2283 2284 my $type = GetTypeFromSignature($signature); 2285 2286 if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) { 2287 # Special-case index arguments because we need to check that they aren't < 0. 2288 return "int"; 2289 } 2290 2291 $type = GetNativeType($type, $parameterIndex >= 0 ? 1 : 0); 2292 2293 if ($parameterIndex >= 0 && $type eq "V8Parameter") { 2294 my $mode = ""; 2295 if ($signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"}) { 2296 $mode = "WithUndefinedOrNullCheck"; 2297 } elsif ($signature->extendedAttributes->{"ConvertNullToNullString"}) { 2298 $mode = "WithNullCheck"; 2299 } 2300 $type .= "<$mode>"; 2301 } 2302 2303 return $type; 2304 } 2305 2306 sub IsRefPtrType 2307 { 2308 my $type = shift; 2309 2310 return 0 if $type eq "boolean"; 2311 return 0 if $type eq "float"; 2312 return 0 if $type eq "int"; 2313 return 0 if $type eq "Date"; 2314 return 0 if $type eq "DOMString"; 2315 return 0 if $type eq "double"; 2316 return 0 if $type eq "short"; 2317 return 0 if $type eq "long"; 2318 return 0 if $type eq "unsigned"; 2319 return 0 if $type eq "unsigned long"; 2320 return 0 if $type eq "unsigned short"; 2321 return 0 if $type eq "SVGAnimatedPoints"; 2322 2323 return 1; 2324 } 2325 2326 sub GetNativeType 2327 { 2328 my $type = shift; 2329 my $isParameter = shift; 2330 2331 if ($type eq "float" or $type eq "double") { 2332 return $type; 2333 } 2334 2335 return "V8Parameter" if ($type eq "DOMString" or $type eq "DOMUserData") and $isParameter; 2336 return "int" if $type eq "int"; 2337 return "int" if $type eq "short" or $type eq "unsigned short"; 2338 return "unsigned" if $type eq "unsigned long"; 2339 return "int" if $type eq "long"; 2340 return "long long" if $type eq "long long"; 2341 return "unsigned long long" if $type eq "unsigned long long"; 2342 return "bool" if $type eq "boolean"; 2343 return "String" if $type eq "DOMString"; 2344 return "Range::CompareHow" if $type eq "CompareHow"; 2345 return "FloatRect" if $type eq "SVGRect"; 2346 return "FloatPoint" if $type eq "SVGPoint"; 2347 return "AffineTransform" if $type eq "SVGMatrix"; 2348 return "SVGTransform" if $type eq "SVGTransform"; 2349 return "SVGLength" if $type eq "SVGLength"; 2350 return "SVGAngle" if $type eq "SVGAngle"; 2351 return "float" if $type eq "SVGNumber"; 2352 return "SVGPreserveAspectRatio" if $type eq "SVGPreserveAspectRatio"; 2353 return "SVGPaint::SVGPaintType" if $type eq "SVGPaintType"; 2354 return "DOMTimeStamp" if $type eq "DOMTimeStamp"; 2355 return "unsigned" if $type eq "unsigned int"; 2356 return "Node*" if $type eq "EventTarget" and $isParameter; 2357 return "double" if $type eq "Date"; 2358 2359 return "String" if $type eq "DOMUserData"; # FIXME: Temporary hack? 2360 2361 # temporary hack 2362 return "RefPtr<NodeFilter>" if $type eq "NodeFilter"; 2363 2364 # necessary as resolvers could be constructed on fly. 2365 return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver"; 2366 2367 return "RefPtr<${type}>" if IsRefPtrType($type) and not $isParameter; 2368 2369 # Default, assume native type is a pointer with same type name as idl type 2370 return "${type}*"; 2371 } 2372 2373 2374 my %typeCanFailConversion = ( 2375 "Attr" => 1, 2376 "WebGLArray" => 0, 2377 "WebGLBuffer" => 0, 2378 "WebGLByteArray" => 0, 2379 "WebGLUnsignedByteArray" => 0, 2380 "WebGLContextAttributes" => 0, 2381 "WebGLFloatArray" => 0, 2382 "WebGLFramebuffer" => 0, 2383 "CanvasGradient" => 0, 2384 "WebGLIntArray" => 0, 2385 "CanvasPixelArray" => 0, 2386 "WebGLProgram" => 0, 2387 "WebGLRenderbuffer" => 0, 2388 "WebGLShader" => 0, 2389 "WebGLShortArray" => 0, 2390 "WebGLTexture" => 0, 2391 "WebGLUniformLocation" => 0, 2392 "CompareHow" => 0, 2393 "DataGridColumn" => 0, 2394 "DOMString" => 0, 2395 "DOMWindow" => 0, 2396 "DocumentType" => 0, 2397 "Element" => 0, 2398 "Event" => 0, 2399 "EventListener" => 0, 2400 "EventTarget" => 0, 2401 "HTMLCanvasElement" => 0, 2402 "HTMLElement" => 0, 2403 "HTMLImageElement" => 0, 2404 "HTMLOptionElement" => 0, 2405 "HTMLVideoElement" => 0, 2406 "Node" => 0, 2407 "NodeFilter" => 0, 2408 "MessagePort" => 0, 2409 "NSResolver" => 0, 2410 "Range" => 0, 2411 "SQLResultSet" => 0, 2412 "Storage" => 0, 2413 "SVGAngle" => 1, 2414 "SVGElement" => 0, 2415 "SVGLength" => 1, 2416 "SVGMatrix" => 1, 2417 "SVGNumber" => 0, 2418 "SVGPaintType" => 0, 2419 "SVGPathSeg" => 0, 2420 "SVGPoint" => 1, 2421 "SVGPreserveAspectRatio" => 1, 2422 "SVGRect" => 1, 2423 "SVGTransform" => 1, 2424 "TouchList" => 0, 2425 "VoidCallback" => 1, 2426 "WebKitCSSMatrix" => 0, 2427 "WebKitPoint" => 0, 2428 "XPathEvaluator" => 0, 2429 "XPathNSResolver" => 0, 2430 "XPathResult" => 0, 2431 "boolean" => 0, 2432 "double" => 0, 2433 "float" => 0, 2434 "long" => 0, 2435 "unsigned long" => 0, 2436 "unsigned short" => 0, 2437 "long long" => 0, 2438 "unsigned long long" => 0 2439 ); 2440 2441 2442 sub TranslateParameter 2443 { 2444 my $signature = shift; 2445 2446 # The IDL uses some pseudo-types which don't really exist. 2447 if ($signature->type eq "TimeoutHandler") { 2448 $signature->type("DOMString"); 2449 } 2450 } 2451 2452 sub BasicTypeCanFailConversion 2453 { 2454 my $signature = shift; 2455 my $type = GetTypeFromSignature($signature); 2456 2457 return 1 if $type eq "SVGAngle"; 2458 return 1 if $type eq "SVGLength"; 2459 return 1 if $type eq "SVGMatrix"; 2460 return 1 if $type eq "SVGPoint"; 2461 return 1 if $type eq "SVGPreserveAspectRatio"; 2462 return 1 if $type eq "SVGRect"; 2463 return 1 if $type eq "SVGTransform"; 2464 return 0; 2465 } 2466 2467 sub TypeCanFailConversion 2468 { 2469 my $signature = shift; 2470 2471 my $type = GetTypeFromSignature($signature); 2472 2473 $implIncludes{"ExceptionCode.h"} = 1 if $type eq "Attr"; 2474 2475 return $typeCanFailConversion{$type} if exists $typeCanFailConversion{$type}; 2476 2477 die "Don't know whether a JS value can fail conversion to type $type."; 2478 } 2479 2480 sub JSValueToNative 2481 { 2482 my $signature = shift; 2483 my $value = shift; 2484 my $okParam = shift; 2485 my $maybeOkParam = $okParam ? ", ${okParam}" : ""; 2486 2487 my $type = GetTypeFromSignature($signature); 2488 2489 return "$value" if $type eq "JSObject"; 2490 return "$value->BooleanValue()" if $type eq "boolean"; 2491 return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $type eq "double"; 2492 return "$value->NumberValue()" if $type eq "SVGNumber"; 2493 2494 return "toInt32($value${maybeOkParam})" if $type eq "unsigned long" or $type eq "unsigned short" or $type eq "long"; 2495 return "toInt64($value)" if $type eq "unsigned long long" or $type eq "long long"; 2496 return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "CompareHow"; 2497 return "static_cast<SVGPaint::SVGPaintType>($value->ToInt32()->Int32Value())" if $type eq "SVGPaintType"; 2498 return "toWebCoreDate($value)" if $type eq "Date"; 2499 2500 if ($type eq "DOMString" or $type eq "DOMUserData") { 2501 return $value; 2502 } 2503 2504 if ($type eq "SerializedScriptValue") { 2505 $implIncludes{"SerializedScriptValue.h"} = 1; 2506 return "SerializedScriptValue::create($value)"; 2507 } 2508 2509 if ($type eq "NodeFilter") { 2510 return "V8DOMWrapper::wrapNativeNodeFilter($value)"; 2511 } 2512 2513 if ($type eq "SVGRect") { 2514 $implIncludes{"FloatRect.h"} = 1; 2515 } 2516 2517 if ($type eq "SVGPoint") { 2518 $implIncludes{"FloatPoint.h"} = 1; 2519 } 2520 2521 # Default, assume autogenerated type conversion routines 2522 if ($type eq "EventTarget") { 2523 $implIncludes{"V8Node.h"} = 1; 2524 2525 # EventTarget is not in DOM hierarchy, but all Nodes are EventTarget. 2526 return "V8Node::HasInstance($value) ? V8Node::toNative(v8::Handle<v8::Object>::Cast($value)) : 0"; 2527 } 2528 2529 if ($type eq "XPathNSResolver") { 2530 return "V8DOMWrapper::getXPathNSResolver($value)"; 2531 } 2532 2533 AddIncludesForType($type); 2534 2535 if (IsDOMNodeType($type)) { 2536 $implIncludes{"V8${type}.h"} = 1; 2537 2538 # Perform type checks on the parameter, if it is expected Node type, 2539 # return NULL. 2540 return "V8${type}::HasInstance($value) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0"; 2541 } else { 2542 # TODO: Temporary to avoid Window name conflict. 2543 my $classIndex = uc($type); 2544 my $implClassName = ${type}; 2545 2546 $implIncludes{"V8$type.h"} = 1; 2547 2548 if (IsPodType($type)) { 2549 my $nativeType = GetNativeType($type); 2550 $implIncludes{"V8SVGPODTypeWrapper.h"} = 1; 2551 2552 return "V8SVGPODTypeUtil::toSVGPODType<${nativeType}>(V8ClassIndex::${classIndex}, $value${maybeOkParam})" 2553 } 2554 2555 $implIncludes{"V8${type}.h"} = 1; 2556 2557 # Perform type checks on the parameter, if it is expected Node type, 2558 # return NULL. 2559 return "V8${type}::HasInstance($value) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0"; 2560 } 2561 } 2562 2563 2564 sub GetV8HeaderName 2565 { 2566 my $type = shift; 2567 return "V8Event.h" if $type eq "DOMTimeStamp"; 2568 return "EventListener.h" if $type eq "EventListener"; 2569 return "EventTarget.h" if $type eq "EventTarget"; 2570 return "SerializedScriptValue.h" if $type eq "SerializedScriptValue"; 2571 return "V8${type}.h"; 2572 } 2573 2574 2575 sub CreateCustomSignature 2576 { 2577 my $function = shift; 2578 my $count = @{$function->parameters}; 2579 my $name = $function->signature->name; 2580 my $result = " const int ${name}_argc = ${count};\n" . 2581 " v8::Handle<v8::FunctionTemplate> ${name}_argv[${name}_argc] = { "; 2582 my $first = 1; 2583 foreach my $parameter (@{$function->parameters}) { 2584 if ($first) { $first = 0; } 2585 else { $result .= ", "; } 2586 if (IsWrapperType($parameter->type)) { 2587 if ($parameter->type eq "XPathNSResolver") { 2588 # Special case for XPathNSResolver. All other browsers accepts a callable, 2589 # so, even though it's against IDL, accept objects here. 2590 $result .= "v8::Handle<v8::FunctionTemplate>()"; 2591 } else { 2592 my $type = $parameter->type; 2593 my $header = GetV8HeaderName($type); 2594 $implIncludes{$header} = 1; 2595 $result .= "V8${type}::GetRawTemplate()"; 2596 } 2597 } else { 2598 $result .= "v8::Handle<v8::FunctionTemplate>()"; 2599 } 2600 } 2601 $result .= " };\n"; 2602 $result .= " v8::Handle<v8::Signature> ${name}_signature = v8::Signature::New(desc, ${name}_argc, ${name}_argv);\n"; 2603 return $result; 2604 } 2605 2606 2607 sub RequiresCustomSignature 2608 { 2609 my $function = shift; 2610 # No signature needed for Custom function 2611 if ($function->signature->extendedAttributes->{"Custom"} || 2612 $function->signature->extendedAttributes->{"V8Custom"}) { 2613 return 0; 2614 } 2615 2616 foreach my $parameter (@{$function->parameters}) { 2617 if (IsWrapperType($parameter->type)) { 2618 return 1; 2619 } 2620 } 2621 return 0; 2622 } 2623 2624 2625 my %non_wrapper_types = ( 2626 'float' => 1, 2627 'double' => 1, 2628 'short' => 1, 2629 'unsigned short' => 1, 2630 'long' => 1, 2631 'unsigned long' => 1, 2632 'boolean' => 1, 2633 'long long' => 1, 2634 'unsigned long long' => 1, 2635 'DOMString' => 1, 2636 'CompareHow' => 1, 2637 'SVGAngle' => 1, 2638 'SVGRect' => 1, 2639 'SVGPoint' => 1, 2640 'SVGPreserveAspectRatio' => 1, 2641 'SVGMatrix' => 1, 2642 'SVGTransform' => 1, 2643 'SVGLength' => 1, 2644 'SVGNumber' => 1, 2645 'SVGPaintType' => 1, 2646 'DOMTimeStamp' => 1, 2647 'JSObject' => 1, 2648 'EventTarget' => 1, 2649 'NodeFilter' => 1, 2650 'EventListener' => 1 2651 ); 2652 2653 2654 sub IsWrapperType 2655 { 2656 my $type = $codeGenerator->StripModule(shift); 2657 return !($non_wrapper_types{$type}); 2658 } 2659 2660 sub IsDOMNodeType 2661 { 2662 my $type = shift; 2663 2664 return 1 if $type eq 'Attr'; 2665 return 1 if $type eq 'CDATASection'; 2666 return 1 if $type eq 'Comment'; 2667 return 1 if $type eq 'Document'; 2668 return 1 if $type eq 'DocumentFragment'; 2669 return 1 if $type eq 'DocumentType'; 2670 return 1 if $type eq 'Element'; 2671 return 1 if $type eq 'EntityReference'; 2672 return 1 if $type eq 'HTMLCanvasElement'; 2673 return 1 if $type eq 'HTMLDocument'; 2674 return 1 if $type eq 'HTMLElement'; 2675 return 1 if $type eq 'HTMLFormElement'; 2676 return 1 if $type eq 'HTMLTableCaptionElement'; 2677 return 1 if $type eq 'HTMLTableSectionElement'; 2678 return 1 if $type eq 'Node'; 2679 return 1 if $type eq 'ProcessingInstruction'; 2680 return 1 if $type eq 'SVGElement'; 2681 return 1 if $type eq 'SVGDocument'; 2682 return 1 if $type eq 'SVGSVGElement'; 2683 return 1 if $type eq 'SVGUseElement'; 2684 return 1 if $type eq 'Text'; 2685 2686 return 0; 2687 } 2688 2689 2690 sub ReturnNativeToJSValue 2691 { 2692 my $signature = shift; 2693 my $value = shift; 2694 my $indent = shift; 2695 my $type = GetTypeFromSignature($signature); 2696 2697 return "return v8::Date::New(static_cast<double>($value))" if $type eq "DOMTimeStamp"; 2698 return "return v8Boolean($value)" if $type eq "boolean"; 2699 return "return v8::Handle<v8::Value>()" if $type eq "void"; # equivalent to v8::Undefined() 2700 2701 # For all the types where we use 'int' as the representation type, 2702 # we use Integer::New which has a fast Smi conversion check. 2703 my $nativeType = GetNativeType($type); 2704 return "return v8::Integer::New($value)" if $nativeType eq "int"; 2705 return "return v8::Integer::NewFromUnsigned($value)" if $nativeType eq "unsigned"; 2706 2707 return "return v8DateOrNull($value);" if $type eq "Date"; 2708 return "return v8::Number::New($value)" if $codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType"; 2709 2710 if ($codeGenerator->IsStringType($type)) { 2711 my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"}; 2712 if (defined $conv) { 2713 return "return v8StringOrNull($value)" if $conv eq "Null"; 2714 return "return v8StringOrUndefined($value)" if $conv eq "Undefined"; 2715 return "return v8StringOrFalse($value)" if $conv eq "False"; 2716 2717 die "Unknown value for ConvertNullStringTo extended attribute"; 2718 } 2719 return "return v8String($value)"; 2720 } 2721 2722 AddIncludesForType($type); 2723 2724 # special case for non-DOM node interfaces 2725 if (IsDOMNodeType($type)) { 2726 return "return toV8(${value}" . ($signature->extendedAttributes->{"ReturnsNew"} ? ", true)" : ")"); 2727 } 2728 2729 if ($type eq "EventTarget") { 2730 return "return V8DOMWrapper::convertEventTargetToV8Object($value)"; 2731 } 2732 2733 if ($type eq "EventListener") { 2734 $implIncludes{"V8AbstractEventListener.h"} = 1; 2735 return "return ${value} ? v8::Handle<v8::Value>(static_cast<V8AbstractEventListener*>(${value})->getListenerObject(imp->scriptExecutionContext())) : v8::Handle<v8::Value>(v8::Null())"; 2736 } 2737 2738 if ($type eq "SerializedScriptValue") { 2739 $implIncludes{"$type.h"} = 1; 2740 return "return $value->deserialize()"; 2741 } 2742 2743 $implIncludes{"wtf/RefCounted.h"} = 1; 2744 $implIncludes{"wtf/RefPtr.h"} = 1; 2745 $implIncludes{"wtf/GetPtr.h"} = 1; 2746 2747 if (IsPodType($type)) { 2748 $value = GenerateSVGStaticPodTypeWrapper($type, $value) . ".get()"; 2749 } 2750 2751 return "return toV8($value)"; 2752 } 2753 2754 sub GenerateSVGStaticPodTypeWrapper { 2755 my $type = shift; 2756 my $value = shift; 2757 2758 $implIncludes{"V8$type.h"}=1; 2759 $implIncludes{"V8SVGPODTypeWrapper.h"} = 1; 2760 2761 my $nativeType = GetNativeType($type); 2762 return "V8SVGStaticPODTypeWrapper<$nativeType>::create($value)"; 2763 } 2764 2765 # Internal helper 2766 sub WriteData 2767 { 2768 if (defined($IMPL)) { 2769 # Write content to file. 2770 print $IMPL @implContentHeader; 2771 2772 print $IMPL @implFixedHeader; 2773 2774 foreach my $implInclude (sort keys(%implIncludes)) { 2775 my $checkType = $implInclude; 2776 $checkType =~ s/\.h//; 2777 2778 print $IMPL "#include \"$implInclude\"\n" unless $codeGenerator->IsSVGAnimatedType($checkType); 2779 } 2780 2781 print $IMPL "\n"; 2782 print $IMPL @implContentDecls; 2783 print $IMPL @implContent; 2784 close($IMPL); 2785 undef($IMPL); 2786 2787 %implIncludes = (); 2788 @implFixedHeader = (); 2789 @implHeaderContent = (); 2790 @implContentDecls = (); 2791 @implContent = (); 2792 } 2793 2794 if (defined($HEADER)) { 2795 # Write content to file. 2796 print $HEADER @headerContent; 2797 close($HEADER); 2798 undef($HEADER); 2799 2800 @headerContent = (); 2801 } 2802 } 2803 2804 sub IsSVGTypeNeedingContextParameter 2805 { 2806 my $implClassName = shift; 2807 2808 if ($implClassName =~ /SVG/ and not $implClassName =~ /Element/) { 2809 return 1 unless $implClassName =~ /SVGPaint/ or $implClassName =~ /SVGColor/ or $implClassName =~ /SVGDocument/; 2810 } 2811 2812 return 0; 2813 } 2814 2815 sub GenerateSVGContextAssignment 2816 { 2817 my $srcType = shift; 2818 my $value = shift; 2819 my $indent = shift; 2820 2821 $result = GenerateSVGContextRetrieval($srcType, $indent); 2822 $result .= $indent . "V8Proxy::setSVGContext($value, context);\n"; 2823 2824 return $result; 2825 } 2826 2827 sub GenerateSVGContextRetrieval 2828 { 2829 my $srcType = shift; 2830 my $indent = shift; 2831 2832 my $srcIsPodType = IsPodType($srcType); 2833 2834 my $srcObject = "imp"; 2835 if ($srcIsPodType) { 2836 $srcObject = "imp_wrapper"; 2837 } 2838 2839 my $contextDecl; 2840 2841 if (IsSVGTypeNeedingContextParameter($srcType)) { 2842 $contextDecl = "V8Proxy::svgContext($srcObject)"; 2843 } else { 2844 $contextDecl = $srcObject; 2845 } 2846 2847 return $indent . "SVGElement* context = $contextDecl;\n"; 2848 } 2849 2850 sub IsSVGListMutator 2851 { 2852 my $functionName = shift; 2853 2854 return 1 if $functionName eq "clear"; 2855 return 1 if $functionName eq "initialize"; 2856 return 1 if $functionName eq "insertItemBefore"; 2857 return 1 if $functionName eq "replaceItem"; 2858 return 1 if $functionName eq "removeItem"; 2859 return 1 if $functionName eq "appendItem"; 2860 2861 return 0; 2862 } 2863 2864 sub IsSVGListMethod 2865 { 2866 my $functionName = shift; 2867 2868 return 1 if $functionName eq "getFirst"; 2869 return 1 if $functionName eq "getLast"; 2870 return 1 if $functionName eq "getItem"; 2871 2872 return IsSVGListMutator($functionName); 2873 } 2874 2875 sub IsSVGListTypeNeedingSpecialHandling 2876 { 2877 my $className = shift; 2878 2879 return 1 if $className eq "SVGPointList"; 2880 return 1 if $className eq "SVGTransformList"; 2881 2882 return 0; 2883 } 2884 2885 sub DebugPrint 2886 { 2887 my $output = shift; 2888 2889 print $output; 2890 print "\n"; 2891 } 2892