1 # 2 # Copyright (C) 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann (at] kde.org> 3 # Copyright (C) 2006 Anders Carlsson <andersca (at] mac.com> 4 # Copyright (C) 2006, 2007 Samuel Weinig <sam (at] webkit.org> 5 # Copyright (C) 2006 Alexey Proskuryakov <ap (at] webkit.org> 6 # Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 7 # Copyright (C) 2009 Cameron McCormack <cam (at] mcc.id.au> 8 # 9 # This library is free software; you can redistribute it and/or 10 # modify it under the terms of the GNU Library General Public 11 # License as published by the Free Software Foundation; either 12 # version 2 of the License, or (at your option) any later version. 13 # 14 # This library is distributed in the hope that it will be useful, 15 # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 # Library General Public License for more details. 18 # 19 # You should have received a copy of the GNU Library General Public License 20 # aint with this library; see the file COPYING.LIB. If not, write to 21 # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 22 # Boston, MA 02110-1301, USA. 23 24 package CodeGeneratorJS; 25 26 use File::stat; 27 28 my $module = ""; 29 my $outputDir = ""; 30 my $writeDependencies = 0; 31 32 my @headerContentHeader = (); 33 my @headerContent = (); 34 my %headerIncludes = (); 35 36 my @implContentHeader = (); 37 my @implContent = (); 38 my %implIncludes = (); 39 my @depsContent = (); 40 my $numCachedAttributes = 0; 41 my $currentCachedAttribute = 0; 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., 51 Franklin Street, Fifth Floor, 62 Boston, MA 02110-1301, 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 shift; # $useLayerOnTop 75 shift; # $preprocessor 76 $writeDependencies = shift; 77 78 bless($reference, $object); 79 return $reference; 80 } 81 82 sub finish 83 { 84 my $object = shift; 85 86 # Commit changes! 87 $object->WriteData(); 88 } 89 90 sub leftShift($$) { 91 my ($value, $distance) = @_; 92 return (($value << $distance) & 0xFFFFFFFF); 93 } 94 95 # Params: 'domClass' struct 96 sub GenerateInterface 97 { 98 my $object = shift; 99 my $dataNode = shift; 100 my $defines = shift; 101 102 # Start actual generation 103 $object->GenerateHeader($dataNode); 104 $object->GenerateImplementation($dataNode); 105 106 my $name = $dataNode->name; 107 108 # Open files for writing 109 my $headerFileName = "$outputDir/JS$name.h"; 110 my $implFileName = "$outputDir/JS$name.cpp"; 111 my $depsFileName = "$outputDir/JS$name.dep"; 112 113 # Remove old dependency file. 114 unlink($depsFileName); 115 116 open($IMPL, ">$implFileName") || die "Couldn't open file $implFileName"; 117 open($HEADER, ">$headerFileName") || die "Couldn't open file $headerFileName"; 118 if (@depsContent) { 119 open($DEPS, ">$depsFileName") || die "Couldn't open file $depsFileName"; 120 } 121 } 122 123 # Params: 'idlDocument' struct 124 sub GenerateModule 125 { 126 my $object = shift; 127 my $dataNode = shift; 128 129 $module = $dataNode->module; 130 } 131 132 sub GetParentClassName 133 { 134 my $dataNode = shift; 135 136 return $dataNode->extendedAttributes->{"LegacyParent"} if $dataNode->extendedAttributes->{"LegacyParent"}; 137 return "DOMObjectWithGlobalPointer" if (@{$dataNode->parents} eq 0); 138 return "JS" . $codeGenerator->StripModule($dataNode->parents(0)); 139 } 140 141 sub GetVisibleClassName 142 { 143 my $className = shift; 144 145 return "DOMException" if $className eq "DOMCoreException"; 146 return $className; 147 } 148 149 sub AvoidInclusionOfType 150 { 151 my $type = shift; 152 153 # Special case: SVGRect.h / SVGPoint.h / SVGNumber.h / SVGMatrix.h do not exist. 154 return 1 if $type eq "SVGRect" or $type eq "SVGPoint" or $type eq "SVGNumber" or $type eq "SVGMatrix"; 155 return 0; 156 } 157 158 sub IndexGetterReturnsStrings 159 { 160 my $type = shift; 161 162 return 1 if $type eq "CSSStyleDeclaration" or $type eq "MediaList" or $type eq "CSSVariablesDeclaration"; 163 return 0; 164 } 165 166 sub AddIncludesForType 167 { 168 my $type = $codeGenerator->StripModule(shift); 169 170 # When we're finished with the one-file-per-class 171 # reorganization, we won't need these special cases. 172 if ($codeGenerator->IsPrimitiveType($type) or AvoidInclusionOfType($type) 173 or $type eq "DOMString" or $type eq "DOMObject" or $type eq "Array") { 174 } elsif ($type =~ /SVGPathSeg/) { 175 $joinedName = $type; 176 $joinedName =~ s/Abs|Rel//; 177 $implIncludes{"${joinedName}.h"} = 1; 178 } elsif ($type eq "XPathNSResolver") { 179 $implIncludes{"JSXPathNSResolver.h"} = 1; 180 $implIncludes{"JSCustomXPathNSResolver.h"} = 1; 181 } else { 182 # default, include the same named file 183 $implIncludes{"${type}.h"} = 1; 184 } 185 186 # additional includes (things needed to compile the bindings but not the header) 187 188 if ($type eq "CanvasRenderingContext2D") { 189 $implIncludes{"CanvasGradient.h"} = 1; 190 $implIncludes{"CanvasPattern.h"} = 1; 191 $implIncludes{"CanvasStyle.h"} = 1; 192 } 193 194 if ($type eq "CanvasGradient" or $type eq "XPathNSResolver" or $type eq "MessagePort") { 195 $implIncludes{"PlatformString.h"} = 1; 196 } 197 198 if ($type eq "Document") { 199 $implIncludes{"NodeFilter.h"} = 1; 200 } 201 } 202 203 sub AddIncludesForSVGAnimatedType 204 { 205 my $type = shift; 206 $type =~ s/SVGAnimated//; 207 208 if ($type eq "Point" or $type eq "Rect") { 209 $implIncludes{"Float$type.h"} = 1; 210 } elsif ($type eq "String") { 211 $implIncludes{"PlatformString.h"} = 1; 212 } 213 } 214 215 sub AddClassForwardIfNeeded 216 { 217 my $implClassName = shift; 218 219 # SVGAnimatedLength/Number/etc. are typedefs to SVGAnimatedTemplate, so don't use class forwards for them! 220 push(@headerContent, "class $implClassName;\n\n") unless $codeGenerator->IsSVGAnimatedType($implClassName); 221 } 222 223 sub IsSVGTypeNeedingContextParameter 224 { 225 my $implClassName = shift; 226 227 return 0 unless $implClassName =~ /SVG/; 228 return 0 if $implClassName =~ /Element/; 229 my @noContextNeeded = ("SVGPaint", "SVGColor", "SVGDocument", "SVGZoomEvent"); 230 foreach (@noContextNeeded) { 231 return 0 if $implClassName eq $_; 232 } 233 return 1; 234 } 235 236 sub HashValueForClassAndName 237 { 238 my $class = shift; 239 my $name = shift; 240 241 # SVG Filter enums live in WebCore namespace (platform/graphics/) 242 if ($class =~ /^SVGFE*/ or $class =~ /^SVGComponentTransferFunctionElement$/) { 243 return "WebCore::$name"; 244 } 245 246 return "${class}::$name"; 247 } 248 249 sub hashTableAccessor 250 { 251 my $noStaticTables = shift; 252 my $className = shift; 253 if ($noStaticTables) { 254 return "get${className}Table(exec)"; 255 } else { 256 return "&${className}Table"; 257 } 258 } 259 260 sub prototypeHashTableAccessor 261 { 262 my $noStaticTables = shift; 263 my $className = shift; 264 if ($noStaticTables) { 265 return "get${className}PrototypeTable(exec)"; 266 } else { 267 return "&${className}PrototypeTable"; 268 } 269 } 270 271 sub GenerateGetOwnPropertySlotBody 272 { 273 my ($dataNode, $interfaceName, $className, $implClassName, $hasAttributes, $inlined) = @_; 274 275 my $namespaceMaybe = ($inlined ? "JSC::" : ""); 276 277 my @getOwnPropertySlotImpl = (); 278 279 if ($interfaceName eq "NamedNodeMap" or $interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") { 280 push(@getOwnPropertySlotImpl, " ${namespaceMaybe}JSValue proto = prototype();\n"); 281 push(@getOwnPropertySlotImpl, " if (proto.isObject() && static_cast<${namespaceMaybe}JSObject*>(asObject(proto))->hasProperty(exec, propertyName))\n"); 282 push(@getOwnPropertySlotImpl, " return false;\n\n"); 283 } 284 285 my $manualLookupGetterGeneration = sub { 286 my $requiresManualLookup = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasNameGetter"}; 287 if ($requiresManualLookup) { 288 push(@getOwnPropertySlotImpl, " const ${namespaceMaybe}HashEntry* entry = ${className}Table.entry(exec, propertyName);\n"); 289 push(@getOwnPropertySlotImpl, " if (entry) {\n"); 290 push(@getOwnPropertySlotImpl, " slot.setCustom(this, entry->propertyGetter());\n"); 291 push(@getOwnPropertySlotImpl, " return true;\n"); 292 push(@getOwnPropertySlotImpl, " }\n"); 293 } 294 }; 295 296 if (!$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) { 297 &$manualLookupGetterGeneration(); 298 } 299 300 if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) { 301 push(@getOwnPropertySlotImpl, " bool ok;\n"); 302 push(@getOwnPropertySlotImpl, " unsigned index = propertyName.toUInt32(&ok, false);\n"); 303 304 # If the item function returns a string then we let the ConvertNullStringTo handle the cases 305 # where the index is out of range. 306 if (IndexGetterReturnsStrings($implClassName)) { 307 push(@getOwnPropertySlotImpl, " if (ok) {\n"); 308 } else { 309 push(@getOwnPropertySlotImpl, " if (ok && index < static_cast<$implClassName*>(impl())->length()) {\n"); 310 } 311 if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) { 312 push(@getOwnPropertySlotImpl, " slot.setValue(getByIndex(exec, index));\n"); 313 } else { 314 push(@getOwnPropertySlotImpl, " slot.setCustomIndex(this, index, indexGetter);\n"); 315 } 316 push(@getOwnPropertySlotImpl, " return true;\n"); 317 push(@getOwnPropertySlotImpl, " }\n"); 318 } 319 320 if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) { 321 push(@getOwnPropertySlotImpl, " if (canGetItemsForName(exec, static_cast<$implClassName*>(impl()), propertyName)) {\n"); 322 push(@getOwnPropertySlotImpl, " slot.setCustom(this, nameGetter);\n"); 323 push(@getOwnPropertySlotImpl, " return true;\n"); 324 push(@getOwnPropertySlotImpl, " }\n"); 325 if ($inlined) { 326 $headerIncludes{"AtomicString.h"} = 1; 327 } else { 328 $implIncludes{"AtomicString.h"} = 1; 329 } 330 } 331 332 if ($dataNode->extendedAttributes->{"HasOverridingNameGetter"}) { 333 &$manualLookupGetterGeneration(); 334 } 335 336 if ($dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}) { 337 push(@getOwnPropertySlotImpl, " if (getOwnPropertySlotDelegate(exec, propertyName, slot))\n"); 338 push(@getOwnPropertySlotImpl, " return true;\n"); 339 } 340 341 if ($hasAttributes) { 342 if ($inlined) { 343 die "Cannot inline if NoStaticTables is set." if ($dataNode->extendedAttributes->{"NoStaticTables"}); 344 push(@getOwnPropertySlotImpl, " return ${namespaceMaybe}getStaticValueSlot<$className, Base>(exec, s_info.staticPropHashTable, this, propertyName, slot);\n"); 345 } else { 346 push(@getOwnPropertySlotImpl, " return ${namespaceMaybe}getStaticValueSlot<$className, Base>(exec, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n"); 347 } 348 } else { 349 push(@getOwnPropertySlotImpl, " return Base::getOwnPropertySlot(exec, propertyName, slot);\n"); 350 } 351 352 return @getOwnPropertySlotImpl; 353 } 354 355 sub GenerateGetOwnPropertyDescriptorBody 356 { 357 my ($dataNode, $interfaceName, $className, $implClassName, $hasAttributes, $inlined) = @_; 358 359 my $namespaceMaybe = ($inlined ? "JSC::" : ""); 360 361 my @getOwnPropertyDescriptorImpl = (); 362 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) { 363 if ($interfaceName eq "DOMWindow") { 364 push(@implContent, " if (!static_cast<$className*>(thisObject)->allowsAccessFrom(exec))\n"); 365 } else { 366 push(@implContent, " if (!allowsAccessFromFrame(exec, static_cast<$className*>(thisObject)->impl()->frame()))\n"); 367 } 368 push(@implContent, " return false;\n"); 369 } 370 371 if ($interfaceName eq "NamedNodeMap" or $interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") { 372 push(@getOwnPropertyDescriptorImpl, " ${namespaceMaybe}JSValue proto = prototype();\n"); 373 push(@getOwnPropertyDescriptorImpl, " if (proto.isObject() && static_cast<${namespaceMaybe}JSObject*>(asObject(proto))->hasProperty(exec, propertyName))\n"); 374 push(@getOwnPropertyDescriptorImpl, " return false;\n\n"); 375 } 376 377 my $manualLookupGetterGeneration = sub { 378 my $requiresManualLookup = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasNameGetter"}; 379 if ($requiresManualLookup) { 380 push(@getOwnPropertyDescriptorImpl, " const ${namespaceMaybe}HashEntry* entry = ${className}Table.entry(exec, propertyName);\n"); 381 push(@getOwnPropertyDescriptorImpl, " if (entry) {\n"); 382 push(@getOwnPropertyDescriptorImpl, " PropertySlot slot;\n"); 383 push(@getOwnPropertyDescriptorImpl, " slot.setCustom(this, entry->propertyGetter());\n"); 384 push(@getOwnPropertyDescriptorImpl, " descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());\n"); 385 push(@getOwnPropertyDescriptorImpl, " return true;\n"); 386 push(@getOwnPropertyDescriptorImpl, " }\n"); 387 } 388 }; 389 390 if (!$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) { 391 &$manualLookupGetterGeneration(); 392 } 393 394 if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) { 395 push(@getOwnPropertyDescriptorImpl, " bool ok;\n"); 396 push(@getOwnPropertyDescriptorImpl, " unsigned index = propertyName.toUInt32(&ok, false);\n"); 397 push(@getOwnPropertyDescriptorImpl, " if (ok && index < static_cast<$implClassName*>(impl())->length()) {\n"); 398 if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) { 399 # Assume that if there's a setter, the index will be writable 400 if ($dataNode->extendedAttributes->{"HasIndexSetter"} || $dataNode->extendedAttributes->{"HasCustomIndexSetter"}) { 401 push(@getOwnPropertyDescriptorImpl, " descriptor.setDescriptor(getByIndex(exec, index), ${namespaceMaybe}DontDelete);\n"); 402 } else { 403 push(@getOwnPropertyDescriptorImpl, " descriptor.setDescriptor(getByIndex(exec, index), ${namespaceMaybe}DontDelete | ${namespaceMaybe}ReadOnly);\n"); 404 } 405 } else { 406 push(@getOwnPropertyDescriptorImpl, " ${namespaceMaybe}PropertySlot slot;\n"); 407 push(@getOwnPropertyDescriptorImpl, " slot.setCustomIndex(this, index, indexGetter);\n"); 408 # Assume that if there's a setter, the index will be writable 409 if ($dataNode->extendedAttributes->{"HasIndexSetter"} || $dataNode->extendedAttributes->{"HasCustomIndexSetter"}) { 410 push(@getOwnPropertyDescriptorImpl, " descriptor.setDescriptor(slot.getValue(exec, propertyName), ${namespaceMaybe}DontDelete);\n"); 411 } else { 412 push(@getOwnPropertyDescriptorImpl, " descriptor.setDescriptor(slot.getValue(exec, propertyName), ${namespaceMaybe}DontDelete | ${namespaceMaybe}ReadOnly);\n"); 413 } 414 } 415 push(@getOwnPropertyDescriptorImpl, " return true;\n"); 416 push(@getOwnPropertyDescriptorImpl, " }\n"); 417 } 418 419 if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) { 420 push(@getOwnPropertyDescriptorImpl, " if (canGetItemsForName(exec, static_cast<$implClassName*>(impl()), propertyName)) {\n"); 421 push(@getOwnPropertyDescriptorImpl, " ${namespaceMaybe}PropertySlot slot;\n"); 422 push(@getOwnPropertyDescriptorImpl, " slot.setCustom(this, nameGetter);\n"); 423 push(@getOwnPropertyDescriptorImpl, " descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);\n"); 424 push(@getOwnPropertyDescriptorImpl, " return true;\n"); 425 push(@getOwnPropertyDescriptorImpl, " }\n"); 426 if ($inlined) { 427 $headerIncludes{"AtomicString.h"} = 1; 428 } else { 429 $implIncludes{"AtomicString.h"} = 1; 430 } 431 } 432 433 if ($dataNode->extendedAttributes->{"HasOverridingNameGetter"}) { 434 &$manualLookupGetterGeneration(); 435 } 436 437 if ($dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}) { 438 push(@getOwnPropertyDescriptorImpl, " if (getOwnPropertyDescriptorDelegate(exec, propertyName, descriptor))\n"); 439 push(@getOwnPropertyDescriptorImpl, " return true;\n"); 440 } 441 442 if ($hasAttributes) { 443 if ($inlined) { 444 die "Cannot inline if NoStaticTables is set." if ($dataNode->extendedAttributes->{"NoStaticTables"}); 445 push(@getOwnPropertyDescriptorImpl, " return ${namespaceMaybe}getStaticValueDescriptor<$className, Base>(exec, s_info.staticPropHashTable, this, propertyName, descriptor);\n"); 446 } else { 447 push(@getOwnPropertyDescriptorImpl, " return ${namespaceMaybe}getStaticValueDescriptor<$className, Base>(exec, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n"); 448 } 449 } else { 450 push(@getOwnPropertyDescriptorImpl, " return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);\n"); 451 } 452 453 return @getOwnPropertyDescriptorImpl; 454 } 455 456 my %usesToJSNewlyCreated = ( 457 "CDATASection" => 1, 458 "Element" => 1, 459 "Node" => 1, 460 "Text" => 1, 461 "Touch" => 1, 462 "TouchList" => 1 463 ); 464 465 sub GenerateHeader 466 { 467 my $object = shift; 468 my $dataNode = shift; 469 470 my $interfaceName = $dataNode->name; 471 my $className = "JS$interfaceName"; 472 my $implClassName = $interfaceName; 473 my @ancestorInterfaceNames = (); 474 my %structureFlags = (); 475 476 # We only support multiple parents with SVG (for now). 477 if (@{$dataNode->parents} > 1) { 478 die "A class can't have more than one parent" unless $interfaceName =~ /SVG/; 479 $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@ancestorInterfaceNames); 480 } 481 482 my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"}; 483 my $hasRealParent = @{$dataNode->parents} > 0; 484 my $hasParent = $hasLegacyParent || $hasRealParent; 485 my $parentClassName = GetParentClassName($dataNode); 486 my $conditional = $dataNode->extendedAttributes->{"Conditional"}; 487 my $eventTarget = $dataNode->extendedAttributes->{"EventTarget"}; 488 my $needsMarkChildren = $dataNode->extendedAttributes->{"CustomMarkFunction"} || $dataNode->extendedAttributes->{"EventTarget"}; 489 490 # - Add default header template 491 @headerContentHeader = split("\r", $headerTemplate); 492 493 # - Add header protection 494 push(@headerContentHeader, "\n#ifndef $className" . "_h"); 495 push(@headerContentHeader, "\n#define $className" . "_h\n\n"); 496 497 my $conditionalString; 498 if ($conditional) { 499 $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; 500 push(@headerContentHeader, "#if ${conditionalString}\n\n"); 501 } 502 503 if ($hasParent) { 504 $headerIncludes{"$parentClassName.h"} = 1; 505 } else { 506 $headerIncludes{"JSDOMBinding.h"} = 1; 507 $headerIncludes{"<runtime/JSGlobalObject.h>"} = 1; 508 $headerIncludes{"<runtime/ObjectPrototype.h>"} = 1; 509 } 510 511 if ($dataNode->extendedAttributes->{"CustomCall"}) { 512 $headerIncludes{"<runtime/CallData.h>"} = 1; 513 } 514 515 if ($dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"}) { 516 $headerIncludes{"<runtime/Lookup.h>"} = 1; 517 $headerIncludes{"<wtf/AlwaysInline.h>"} = 1; 518 } 519 520 if ($hasParent && $dataNode->extendedAttributes->{"GenerateNativeConverter"}) { 521 $headerIncludes{"$implClassName.h"} = 1; 522 } 523 524 $headerIncludes{"SVGElement.h"} = 1 if $className =~ /^JSSVG/; 525 526 # Get correct pass/store types respecting PODType flag 527 my $podType = $dataNode->extendedAttributes->{"PODType"}; 528 my $implType = $podType ? "JSSVGPODTypeWrapper<$podType> " : $implClassName; 529 $headerIncludes{"$podType.h"} = 1 if $podType and $podType ne "float"; 530 531 $headerIncludes{"JSSVGPODTypeWrapper.h"} = 1 if $podType; 532 533 my $numConstants = @{$dataNode->constants}; 534 my $numAttributes = @{$dataNode->attributes}; 535 my $numFunctions = @{$dataNode->functions}; 536 537 push(@headerContent, "\nnamespace WebCore {\n\n"); 538 539 # Implementation class forward declaration 540 AddClassForwardIfNeeded($implClassName) unless $podType; 541 AddClassForwardIfNeeded("JSDOMWindowShell") if $interfaceName eq "DOMWindow"; 542 543 # Class declaration 544 push(@headerContent, "class $className : public $parentClassName {\n"); 545 push(@headerContent, " typedef $parentClassName Base;\n"); 546 push(@headerContent, "public:\n"); 547 548 # Constructor 549 if ($interfaceName eq "DOMWindow") { 550 push(@headerContent, " $className(NonNullPassRefPtr<JSC::Structure>, PassRefPtr<$implType>, JSDOMWindowShell*);\n"); 551 } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) { 552 push(@headerContent, " $className(NonNullPassRefPtr<JSC::Structure>, PassRefPtr<$implType>);\n"); 553 } else { 554 push(@headerContent, " $className(NonNullPassRefPtr<JSC::Structure>, JSDOMGlobalObject*, PassRefPtr<$implType>);\n"); 555 } 556 557 # Destructor 558 push(@headerContent, " virtual ~$className();\n") if (!$hasParent or $eventTarget or $interfaceName eq "DOMWindow"); 559 560 # Prototype 561 push(@headerContent, " static JSC::JSObject* createPrototype(JSC::ExecState*, JSC::JSGlobalObject*);\n") unless ($dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"}); 562 563 $implIncludes{"${className}Custom.h"} = 1 if $dataNode->extendedAttributes->{"CustomHeader"} || $dataNode->extendedAttributes->{"CustomPutFunction"} || $dataNode->extendedAttributes->{"DelegatingPutFunction"}; 564 565 my $hasGetter = $numAttributes > 0 566 || !($dataNode->extendedAttributes->{"OmitConstructor"} 567 || $dataNode->extendedAttributes->{"CustomConstructor"}) 568 || $dataNode->extendedAttributes->{"HasIndexGetter"} 569 || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} 570 || $dataNode->extendedAttributes->{"HasNumericIndexGetter"} 571 || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"} 572 || $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"} 573 || $dataNode->extendedAttributes->{"HasNameGetter"} 574 || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}; 575 576 # Getters 577 if ($hasGetter) { 578 push(@headerContent, " virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);\n"); 579 push(@headerContent, " virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&);\n"); 580 push(@headerContent, " virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);\n") if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) && !$dataNode->extendedAttributes->{"HasOverridingNameGetter"}; 581 push(@headerContent, " bool getOwnPropertySlotDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}; 582 push(@headerContent, " bool getOwnPropertyDescriptorDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n") if $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}; 583 $structureFlags{"JSC::OverridesGetOwnPropertySlot"} = 1; 584 } 585 586 # Check if we have any writable properties 587 my $hasReadWriteProperties = 0; 588 foreach (@{$dataNode->attributes}) { 589 if ($_->type !~ /^readonly\ attribute$/) { 590 $hasReadWriteProperties = 1; 591 } 592 } 593 594 my $hasSetter = $hasReadWriteProperties 595 || $dataNode->extendedAttributes->{"CustomPutFunction"} 596 || $dataNode->extendedAttributes->{"DelegatingPutFunction"} 597 || $dataNode->extendedAttributes->{"HasCustomIndexSetter"}; 598 599 # Getters 600 if ($hasSetter) { 601 push(@headerContent, " virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);\n"); 602 push(@headerContent, " virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValue);\n") if $dataNode->extendedAttributes->{"HasCustomIndexSetter"}; 603 push(@headerContent, " bool putDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, JSC::PutPropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingPutFunction"}; 604 } 605 606 # Class info 607 push(@headerContent, " virtual const JSC::ClassInfo* classInfo() const { return &s_info; }\n"); 608 push(@headerContent, " static const JSC::ClassInfo s_info;\n\n"); 609 610 # Structure ID 611 if ($interfaceName eq "DOMWindow") { 612 $structureFlags{"JSC::ImplementsHasInstance"} = 1; 613 $structureFlags{"JSC::NeedsThisConversion"} = 1; 614 } 615 push(@headerContent, 616 " static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype)\n" . 617 " {\n" . 618 " return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount);\n" . 619 " }\n\n"); 620 621 # markChildren function 622 if ($needsMarkChildren) { 623 push(@headerContent, " virtual void markChildren(JSC::MarkStack&);\n\n"); 624 $structureFlags{"JSC::OverridesMarkChildren"} = 1; 625 } 626 627 # Custom pushEventHandlerScope function 628 push(@headerContent, " virtual void pushEventHandlerScope(JSC::ExecState*, JSC::ScopeChain&) const;\n\n") if $dataNode->extendedAttributes->{"CustomPushEventHandlerScope"}; 629 630 # Custom call functions 631 push(@headerContent, " virtual JSC::CallType getCallData(JSC::CallData&);\n\n") if $dataNode->extendedAttributes->{"CustomCall"}; 632 633 # Custom deleteProperty function 634 push(@headerContent, " virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&);\n") if $dataNode->extendedAttributes->{"CustomDeleteProperty"}; 635 636 # Custom getPropertyNames function exists on DOMWindow 637 if ($interfaceName eq "DOMWindow") { 638 push(@headerContent, " virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n"); 639 $structureFlags{"JSC::OverridesGetPropertyNames"} = 1; 640 } 641 642 # Custom defineProperty function exists on DOMWindow 643 push(@headerContent, " virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&, bool shouldThrow);\n") if $interfaceName eq "DOMWindow"; 644 645 # Custom getOwnPropertyNames function 646 if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"} || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) { 647 push(@headerContent, " virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n"); 648 $structureFlags{"JSC::OverridesGetPropertyNames"} = 1; 649 } 650 651 # Custom defineGetter function 652 push(@headerContent, " virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomDefineGetter"}; 653 654 # Custom defineSetter function 655 push(@headerContent, " virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomDefineSetter"}; 656 657 # Custom lookupGetter function 658 push(@headerContent, " virtual JSC::JSValue lookupGetter(JSC::ExecState*, const JSC::Identifier& propertyName);\n") if $dataNode->extendedAttributes->{"CustomLookupGetter"}; 659 660 # Custom lookupSetter function 661 push(@headerContent, " virtual JSC::JSValue lookupSetter(JSC::ExecState*, const JSC::Identifier& propertyName);\n") if $dataNode->extendedAttributes->{"CustomLookupSetter"}; 662 663 # Override toBoolean to return false for objects that want to 'MasqueradesAsUndefined'. 664 if ($dataNode->extendedAttributes->{"MasqueradesAsUndefined"}) { 665 push(@headerContent, " virtual bool toBoolean(JSC::ExecState*) const { return false; };\n"); 666 $structureFlags{"JSC::MasqueradesAsUndefined"} = 1; 667 } 668 669 # Constructor object getter 670 push(@headerContent, " static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*);\n") if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})); 671 672 my $numCustomFunctions = 0; 673 my $numCustomAttributes = 0; 674 675 # Attribute and function enums 676 if ($numAttributes > 0) { 677 foreach (@{$dataNode->attributes}) { 678 my $attribute = $_; 679 $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"}; 680 $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"CustomGetter"} || $attribute->signature->extendedAttributes->{"JSCCustomGetter"}; 681 $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"CustomSetter"} || $attribute->signature->extendedAttributes->{"JSCCustomSetter"}; 682 if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) { 683 push(@headerContent, " static const unsigned " . $attribute->signature->name . "Slot = $numCachedAttributes + Base::AnonymousSlotCount;\n"); 684 $numCachedAttributes++; 685 } 686 } 687 } 688 689 if ($numCachedAttributes > 0) { 690 push(@headerContent, " using $parentClassName" . "::putAnonymousValue;\n"); 691 push(@headerContent, " using $parentClassName" . "::getAnonymousValue;\n"); 692 } 693 if ($numCustomAttributes > 0) { 694 push(@headerContent, "\n // Custom attributes\n"); 695 696 foreach my $attribute (@{$dataNode->attributes}) { 697 if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"}) { 698 push(@headerContent, " JSC::JSValue " . $codeGenerator->WK_lcfirst($attribute->signature->name) . "(JSC::ExecState*) const;\n"); 699 if ($attribute->type !~ /^readonly/) { 700 push(@headerContent, " void set" . $codeGenerator->WK_ucfirst($attribute->signature->name) . "(JSC::ExecState*, JSC::JSValue);\n"); 701 } 702 } elsif ($attribute->signature->extendedAttributes->{"CustomGetter"} || $attribute->signature->extendedAttributes->{"JSCCustomGetter"}) { 703 push(@headerContent, " JSC::JSValue " . $codeGenerator->WK_lcfirst($attribute->signature->name) . "(JSC::ExecState*) const;\n"); 704 } elsif ($attribute->signature->extendedAttributes->{"CustomSetter"} || $attribute->signature->extendedAttributes->{"JSCCustomSetter"}) { 705 if ($attribute->type !~ /^readonly/) { 706 push(@headerContent, " void set" . $codeGenerator->WK_ucfirst($attribute->signature->name) . "(JSC::ExecState*, JSC::JSValue);\n"); 707 } 708 } 709 } 710 } 711 712 foreach my $function (@{$dataNode->functions}) { 713 $numCustomFunctions++ if $function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"JSCCustom"}; 714 } 715 716 if ($numCustomFunctions > 0) { 717 push(@headerContent, "\n // Custom functions\n"); 718 foreach my $function (@{$dataNode->functions}) { 719 if ($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"JSCCustom"}) { 720 my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementationFunction"} || $codeGenerator->WK_lcfirst($function->signature->name); 721 push(@headerContent, " JSC::JSValue " . $functionImplementationName . "(JSC::ExecState*, const JSC::ArgList&);\n"); 722 } 723 } 724 } 725 726 if (!$hasParent) { 727 # Extra space after JSSVGPODTypeWrapper<> to make RefPtr<Wrapper<> > compile. 728 my $implType = $podType ? "JSSVGPODTypeWrapper<$podType> " : $implClassName; 729 push(@headerContent, " $implType* impl() const { return m_impl.get(); }\n\n"); 730 push(@headerContent, "private:\n"); 731 push(@headerContent, " RefPtr<$implType> m_impl;\n"); 732 } elsif ($dataNode->extendedAttributes->{"GenerateNativeConverter"}) { 733 push(@headerContent, " $implClassName* impl() const\n"); 734 push(@headerContent, " {\n"); 735 push(@headerContent, " return static_cast<$implClassName*>(Base::impl());\n"); 736 push(@headerContent, " }\n"); 737 } 738 739 # anonymous slots 740 if ($numCachedAttributes) { 741 push(@headerContent, "public:\n"); 742 push(@headerContent, " static const unsigned AnonymousSlotCount = $numCachedAttributes + Base::AnonymousSlotCount;\n"); 743 } 744 745 # structure flags 746 push(@headerContent, "protected:\n"); 747 push(@headerContent, " static const unsigned StructureFlags = "); 748 foreach my $structureFlag (keys %structureFlags) { 749 push(@headerContent, $structureFlag . " | "); 750 } 751 push(@headerContent, "Base::StructureFlags;\n"); 752 753 # Index getter 754 if ($dataNode->extendedAttributes->{"HasIndexGetter"}) { 755 push(@headerContent, " static JSC::JSValue indexGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n"); 756 } 757 if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) { 758 push(@headerContent, " JSC::JSValue getByIndex(JSC::ExecState*, unsigned index);\n"); 759 760 } 761 762 # Index setter 763 if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) { 764 push(@headerContent, " void indexSetter(JSC::ExecState*, unsigned index, JSC::JSValue);\n"); 765 } 766 # Name getter 767 if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) { 768 push(@headerContent, "private:\n"); 769 push(@headerContent, " static bool canGetItemsForName(JSC::ExecState*, $implClassName*, const JSC::Identifier&);\n"); 770 push(@headerContent, " static JSC::JSValue nameGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n"); 771 } 772 773 push(@headerContent, "};\n\n"); 774 775 if ($dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"} && !$dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}) { 776 push(@headerContent, "ALWAYS_INLINE bool ${className}::getOwnPropertySlot(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertySlot& slot)\n"); 777 push(@headerContent, "{\n"); 778 push(@headerContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 1)); 779 push(@headerContent, "}\n\n"); 780 push(@headerContent, "ALWAYS_INLINE bool ${className}::getOwnPropertyDescriptor(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertyDescriptor& descriptor)\n"); 781 push(@headerContent, "{\n"); 782 push(@headerContent, GenerateGetOwnPropertyDescriptorBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 1)); 783 push(@headerContent, "}\n\n"); 784 } 785 786 if (!$hasParent || $dataNode->extendedAttributes->{"GenerateToJS"} || $dataNode->extendedAttributes->{"CustomToJS"}) { 787 if ($podType) { 788 push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, JSSVGPODTypeWrapper<$podType>*, SVGElement*);\n"); 789 } elsif (IsSVGTypeNeedingContextParameter($implClassName)) { 790 push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType*, SVGElement* context);\n"); 791 } else { 792 push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType*);\n"); 793 } 794 } 795 if (!$hasParent || $dataNode->extendedAttributes->{"GenerateNativeConverter"}) { 796 if ($podType) { 797 push(@headerContent, "$podType to${interfaceName}(JSC::JSValue);\n"); 798 } elsif ($interfaceName eq "NodeFilter") { 799 push(@headerContent, "PassRefPtr<NodeFilter> toNodeFilter(JSC::JSValue);\n"); 800 } else { 801 push(@headerContent, "$implClassName* to${interfaceName}(JSC::JSValue);\n"); 802 } 803 } 804 if ($usesToJSNewlyCreated{$interfaceName}) { 805 push(@headerContent, "JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject*, $interfaceName*);\n"); 806 } 807 808 push(@headerContent, "\n"); 809 810 # Add prototype declaration. 811 %structureFlags = (); 812 push(@headerContent, "class ${className}Prototype : public JSC::JSObject {\n"); 813 push(@headerContent, " typedef JSC::JSObject Base;\n"); 814 push(@headerContent, "public:\n"); 815 if ($interfaceName eq "DOMWindow") { 816 push(@headerContent, " void* operator new(size_t);\n"); 817 } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) { 818 push(@headerContent, " void* operator new(size_t, JSC::JSGlobalData*);\n"); 819 } else { 820 push(@headerContent, " static JSC::JSObject* self(JSC::ExecState*, JSC::JSGlobalObject*);\n"); 821 } 822 push(@headerContent, " virtual const JSC::ClassInfo* classInfo() const { return &s_info; }\n"); 823 push(@headerContent, " static const JSC::ClassInfo s_info;\n"); 824 if ($numFunctions > 0 || $numConstants > 0 || $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) { 825 push(@headerContent, " virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n"); 826 push(@headerContent, " virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n"); 827 push(@headerContent, " bool getOwnPropertySlotDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}; 828 push(@headerContent, " bool getOwnPropertyDescriptorDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n") if $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}; 829 $structureFlags{"JSC::OverridesGetOwnPropertySlot"} = 1; 830 } 831 if ($dataNode->extendedAttributes->{"CustomMarkFunction"} or $needsMarkChildren) { 832 $structureFlags{"JSC::OverridesMarkChildren"} = 1; 833 } 834 push(@headerContent, 835 " static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype)\n" . 836 " {\n" . 837 " return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount);\n" . 838 " }\n"); 839 if ($dataNode->extendedAttributes->{"DelegatingPrototypePutFunction"}) { 840 push(@headerContent, " virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);\n"); 841 push(@headerContent, " bool putDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, JSC::PutPropertySlot&);\n"); 842 } 843 844 # Custom defineGetter function 845 push(@headerContent, " virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomPrototypeDefineGetter"}; 846 847 push(@headerContent, " ${className}Prototype(NonNullPassRefPtr<JSC::Structure> structure) : JSC::JSObject(structure) { }\n"); 848 849 # structure flags 850 push(@headerContent, "protected:\n"); 851 push(@headerContent, " static const unsigned StructureFlags = "); 852 foreach my $structureFlag (keys %structureFlags) { 853 push(@headerContent, $structureFlag . " | "); 854 } 855 push(@headerContent, "Base::StructureFlags;\n"); 856 857 push(@headerContent, "};\n\n"); 858 859 if ($numFunctions > 0) { 860 push(@headerContent,"// Functions\n\n"); 861 foreach my $function (@{$dataNode->functions}) { 862 my $functionName = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($function->signature->name); 863 push(@headerContent, "JSC::JSValue JSC_HOST_CALL ${functionName}(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);\n"); 864 } 865 } 866 867 if ($numAttributes > 0 || !($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { 868 push(@headerContent,"// Attributes\n\n"); 869 foreach my $attribute (@{$dataNode->attributes}) { 870 my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : ""); 871 push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n"); 872 unless ($attribute->type =~ /readonly/) { 873 my $setter = "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : ""); 874 push(@headerContent, "void ${setter}(JSC::ExecState*, JSC::JSObject*, JSC::JSValue);\n"); 875 } 876 } 877 878 if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { 879 my $getter = "js" . $interfaceName . "Constructor"; 880 push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n"); 881 } 882 } 883 884 if ($numConstants > 0) { 885 push(@headerContent,"// Constants\n\n"); 886 foreach my $constant (@{$dataNode->constants}) { 887 my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name); 888 push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n"); 889 } 890 } 891 892 push(@headerContent, "\n} // namespace WebCore\n\n"); 893 push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditional; 894 push(@headerContent, "#endif\n"); 895 896 # - Generate dependencies. 897 if ($writeDependencies && @ancestorInterfaceNames) { 898 push(@depsContent, "$className.h : ", join(" ", map { "$_.idl" } @ancestorInterfaceNames), "\n"); 899 push(@depsContent, map { "$_.idl :\n" } @ancestorInterfaceNames); 900 } 901 } 902 903 sub GenerateImplementation 904 { 905 my ($object, $dataNode) = @_; 906 907 my $interfaceName = $dataNode->name; 908 my $className = "JS$interfaceName"; 909 my $implClassName = $interfaceName; 910 911 my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"}; 912 my $hasRealParent = @{$dataNode->parents} > 0; 913 my $hasParent = $hasLegacyParent || $hasRealParent; 914 my $parentClassName = GetParentClassName($dataNode); 915 my $conditional = $dataNode->extendedAttributes->{"Conditional"}; 916 my $visibleClassName = GetVisibleClassName($interfaceName); 917 my $eventTarget = $dataNode->extendedAttributes->{"EventTarget"}; 918 my $needsMarkChildren = $dataNode->extendedAttributes->{"CustomMarkFunction"} || $dataNode->extendedAttributes->{"EventTarget"}; 919 920 # - Add default header template 921 @implContentHeader = split("\r", $headerTemplate); 922 923 push(@implContentHeader, "\n#include \"config.h\"\n"); 924 my $conditionalString; 925 if ($conditional) { 926 $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; 927 push(@implContentHeader, "\n#if ${conditionalString}\n\n"); 928 } 929 push(@implContentHeader, "#include \"$className.h\"\n\n"); 930 931 AddIncludesForSVGAnimatedType($interfaceName) if $className =~ /^JSSVGAnimated/; 932 933 $implIncludes{"<wtf/GetPtr.h>"} = 1; 934 $implIncludes{"<runtime/PropertyNameArray.h>"} = 1 if $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}; 935 936 AddIncludesForType($interfaceName); 937 938 @implContent = (); 939 940 push(@implContent, "\nusing namespace JSC;\n\n"); 941 push(@implContent, "namespace WebCore {\n\n"); 942 943 push(@implContent, "ASSERT_CLASS_FITS_IN_CELL($className);\n\n"); 944 945 # - Add all attributes in a hashtable definition 946 my $numAttributes = @{$dataNode->attributes}; 947 $numAttributes++ if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})); 948 949 if ($numAttributes > 0) { 950 my $hashSize = $numAttributes; 951 my $hashName = $className . "Table"; 952 953 my @hashKeys = (); 954 my @hashSpecials = (); 955 my @hashValue1 = (); 956 my @hashValue2 = (); 957 my %conditionals = (); 958 959 my @entries = (); 960 961 foreach my $attribute (@{$dataNode->attributes}) { 962 my $name = $attribute->signature->name; 963 push(@hashKeys, $name); 964 965 my @specials = (); 966 push(@specials, "DontDelete") unless $attribute->signature->extendedAttributes->{"Deletable"}; 967 push(@specials, "DontEnum") if $attribute->signature->extendedAttributes->{"DontEnum"}; 968 push(@specials, "ReadOnly") if $attribute->type =~ /readonly/; 969 my $special = (@specials > 0) ? join("|", @specials) : "0"; 970 push(@hashSpecials, $special); 971 972 my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : ""); 973 push(@hashValue1, $getter); 974 975 if ($attribute->type =~ /readonly/) { 976 push(@hashValue2, "0"); 977 } else { 978 my $setter = "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : ""); 979 push(@hashValue2, $setter); 980 } 981 982 my $conditional = $attribute->signature->extendedAttributes->{"Conditional"}; 983 if ($conditional) { 984 $conditionals{$name} = $conditional; 985 } 986 } 987 988 if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { 989 push(@hashKeys, "constructor"); 990 my $getter = "js" . $interfaceName . "Constructor"; 991 push(@hashValue1, $getter); 992 push(@hashValue2, "0"); 993 push(@hashSpecials, "DontEnum|ReadOnly"); # FIXME: Setting the constructor should be possible. 994 } 995 996 $object->GenerateHashTable($hashName, $hashSize, 997 \@hashKeys, \@hashSpecials, 998 \@hashValue1, \@hashValue2, 999 \%conditionals); 1000 } 1001 1002 my $numConstants = @{$dataNode->constants}; 1003 my $numFunctions = @{$dataNode->functions}; 1004 1005 # - Add all constants 1006 if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { 1007 $hashSize = $numConstants; 1008 $hashName = $className . "ConstructorTable"; 1009 1010 @hashKeys = (); 1011 @hashValue1 = (); 1012 @hashValue2 = (); 1013 @hashSpecials = (); 1014 1015 # FIXME: we should not need a function for every constant. 1016 foreach my $constant (@{$dataNode->constants}) { 1017 push(@hashKeys, $constant->name); 1018 my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name); 1019 push(@hashValue1, $getter); 1020 push(@hashValue2, "0"); 1021 push(@hashSpecials, "DontDelete|ReadOnly"); 1022 } 1023 1024 $object->GenerateHashTable($hashName, $hashSize, 1025 \@hashKeys, \@hashSpecials, 1026 \@hashValue1, \@hashValue2); 1027 1028 my $protoClassName; 1029 $protoClassName = "${className}Prototype"; 1030 1031 push(@implContent, constructorFor($className, $protoClassName, $interfaceName, $visibleClassName, $dataNode->extendedAttributes->{"CanBeConstructed"})); 1032 } 1033 1034 # - Add functions and constants to a hashtable definition 1035 $hashSize = $numFunctions + $numConstants; 1036 $hashName = $className . "PrototypeTable"; 1037 1038 @hashKeys = (); 1039 @hashValue1 = (); 1040 @hashValue2 = (); 1041 @hashSpecials = (); 1042 1043 # FIXME: we should not need a function for every constant. 1044 foreach my $constant (@{$dataNode->constants}) { 1045 push(@hashKeys, $constant->name); 1046 my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name); 1047 push(@hashValue1, $getter); 1048 push(@hashValue2, "0"); 1049 push(@hashSpecials, "DontDelete|ReadOnly"); 1050 } 1051 1052 foreach my $function (@{$dataNode->functions}) { 1053 my $name = $function->signature->name; 1054 push(@hashKeys, $name); 1055 1056 my $value = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($name); 1057 push(@hashValue1, $value); 1058 1059 my $numParameters = @{$function->parameters}; 1060 push(@hashValue2, $numParameters); 1061 1062 my @specials = (); 1063 push(@specials, "DontDelete") unless $function->signature->extendedAttributes->{"Deletable"}; 1064 push(@specials, "DontEnum") if $function->signature->extendedAttributes->{"DontEnum"}; 1065 push(@specials, "Function"); 1066 my $special = (@specials > 0) ? join("|", @specials) : "0"; 1067 push(@hashSpecials, $special); 1068 } 1069 1070 $object->GenerateHashTable($hashName, $hashSize, 1071 \@hashKeys, \@hashSpecials, 1072 \@hashValue1, \@hashValue2); 1073 1074 if ($dataNode->extendedAttributes->{"NoStaticTables"}) { 1075 push(@implContent, "static const HashTable* get${className}PrototypeTable(ExecState* exec)\n"); 1076 push(@implContent, "{\n"); 1077 push(@implContent, " return getHashTableForGlobalData(exec->globalData(), &${className}PrototypeTable);\n"); 1078 push(@implContent, "}\n"); 1079 push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleClassName}Prototype\", 0, 0, get${className}PrototypeTable };\n\n"); 1080 } else { 1081 push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleClassName}Prototype\", 0, &${className}PrototypeTable, 0 };\n\n"); 1082 } 1083 if ($interfaceName eq "DOMWindow") { 1084 push(@implContent, "void* ${className}Prototype::operator new(size_t size)\n"); 1085 push(@implContent, "{\n"); 1086 push(@implContent, " return JSDOMWindow::commonJSGlobalData()->heap.allocate(size);\n"); 1087 push(@implContent, "}\n\n"); 1088 } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) { 1089 push(@implContent, "void* ${className}Prototype::operator new(size_t size, JSGlobalData* globalData)\n"); 1090 push(@implContent, "{\n"); 1091 push(@implContent, " return globalData->heap.allocate(size);\n"); 1092 push(@implContent, "}\n\n"); 1093 } else { 1094 push(@implContent, "JSObject* ${className}Prototype::self(ExecState* exec, JSGlobalObject* globalObject)\n"); 1095 push(@implContent, "{\n"); 1096 push(@implContent, " return getDOMPrototype<${className}>(exec, globalObject);\n"); 1097 push(@implContent, "}\n\n"); 1098 } 1099 if ($numConstants > 0 || $numFunctions > 0 || $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) { 1100 push(@implContent, "bool ${className}Prototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n"); 1101 push(@implContent, "{\n"); 1102 1103 if ($dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) { 1104 push(@implContent, " if (getOwnPropertySlotDelegate(exec, propertyName, slot))\n"); 1105 push(@implContent, " return true;\n"); 1106 } 1107 1108 if ($numConstants eq 0 && $numFunctions eq 0) { 1109 push(@implContent, " return Base::getOwnPropertySlot(exec, propertyName, slot);\n"); 1110 } elsif ($numConstants eq 0) { 1111 push(@implContent, " return getStaticFunctionSlot<JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n"); 1112 } elsif ($numFunctions eq 0) { 1113 push(@implContent, " return getStaticValueSlot<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n"); 1114 } else { 1115 push(@implContent, " return getStaticPropertySlot<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n"); 1116 } 1117 push(@implContent, "}\n\n"); 1118 1119 push(@implContent, "bool ${className}Prototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\n"); 1120 push(@implContent, "{\n"); 1121 1122 if ($dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) { 1123 push(@implContent, " if (getOwnPropertyDescriptorDelegate(exec, propertyName, descriptor))\n"); 1124 push(@implContent, " return true;\n"); 1125 } 1126 1127 if ($numConstants eq 0 && $numFunctions eq 0) { 1128 push(@implContent, " return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);\n"); 1129 } elsif ($numConstants eq 0) { 1130 push(@implContent, " return getStaticFunctionDescriptor<JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n"); 1131 } elsif ($numFunctions eq 0) { 1132 push(@implContent, " return getStaticValueDescriptor<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n"); 1133 } else { 1134 push(@implContent, " return getStaticPropertyDescriptor<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n"); 1135 } 1136 push(@implContent, "}\n\n"); 1137 } 1138 1139 if ($dataNode->extendedAttributes->{"DelegatingPrototypePutFunction"}) { 1140 push(@implContent, "void ${className}Prototype::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)\n"); 1141 push(@implContent, "{\n"); 1142 push(@implContent, " if (putDelegate(exec, propertyName, value, slot))\n"); 1143 push(@implContent, " return;\n"); 1144 push(@implContent, " Base::put(exec, propertyName, value, slot);\n"); 1145 push(@implContent, "}\n\n"); 1146 } 1147 1148 # - Initialize static ClassInfo object 1149 if ($numAttributes > 0 && $dataNode->extendedAttributes->{"NoStaticTables"}) { 1150 push(@implContent, "static const HashTable* get${className}Table(ExecState* exec)\n"); 1151 push(@implContent, "{\n"); 1152 push(@implContent, " return getHashTableForGlobalData(exec->globalData(), &${className}Table);\n"); 1153 push(@implContent, "}\n"); 1154 } 1155 push(@implContent, "const ClassInfo $className" . "::s_info = { \"${visibleClassName}\", "); 1156 if ($hasParent) { 1157 push(@implContent, "&" . $parentClassName . "::s_info, "); 1158 } else { 1159 push(@implContent, "0, "); 1160 } 1161 1162 if ($numAttributes > 0 && !$dataNode->extendedAttributes->{"NoStaticTables"}) { 1163 push(@implContent, "&${className}Table"); 1164 } else { 1165 push(@implContent, "0"); 1166 } 1167 if ($numAttributes > 0 && $dataNode->extendedAttributes->{"NoStaticTables"}) { 1168 push(@implContent, ", get${className}Table "); 1169 } else { 1170 push(@implContent, ", 0 "); 1171 } 1172 push(@implContent, "};\n\n"); 1173 1174 # Get correct pass/store types respecting PODType flag 1175 my $podType = $dataNode->extendedAttributes->{"PODType"}; 1176 my $implType = $podType ? "JSSVGPODTypeWrapper<$podType> " : $implClassName; 1177 1178 # Constructor 1179 if ($interfaceName eq "DOMWindow") { 1180 AddIncludesForType("JSDOMWindowShell"); 1181 push(@implContent, "${className}::$className(NonNullPassRefPtr<Structure> structure, PassRefPtr<$implType> impl, JSDOMWindowShell* shell)\n"); 1182 push(@implContent, " : $parentClassName(structure, impl, shell)\n"); 1183 } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) { 1184 AddIncludesForType($interfaceName); 1185 push(@implContent, "${className}::$className(NonNullPassRefPtr<Structure> structure, PassRefPtr<$implType> impl)\n"); 1186 push(@implContent, " : $parentClassName(structure, impl)\n"); 1187 } else { 1188 push(@implContent, "${className}::$className(NonNullPassRefPtr<Structure> structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl)\n"); 1189 if ($hasParent) { 1190 push(@implContent, " : $parentClassName(structure, globalObject, impl)\n"); 1191 } else { 1192 push(@implContent, " : $parentClassName(structure, globalObject)\n"); 1193 push(@implContent, " , m_impl(impl)\n"); 1194 } 1195 } 1196 push(@implContent, "{\n"); 1197 if ($numCachedAttributes > 0) { 1198 push(@implContent, " for (unsigned i = Base::AnonymousSlotCount; i < AnonymousSlotCount; i++)\n"); 1199 push(@implContent, " putAnonymousValue(i, JSValue());\n"); 1200 } 1201 push(@implContent, "}\n\n"); 1202 1203 # Destructor 1204 if (!$hasParent || $eventTarget) { 1205 push(@implContent, "${className}::~$className()\n"); 1206 push(@implContent, "{\n"); 1207 1208 if ($eventTarget) { 1209 $implIncludes{"RegisteredEventListener.h"} = 1; 1210 push(@implContent, " impl()->invalidateJSEventListeners(this);\n"); 1211 } 1212 1213 if (!$dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"}) { 1214 if ($interfaceName eq "Node") { 1215 push(@implContent, " forgetDOMNode(this, impl(), impl()->document());\n"); 1216 } else { 1217 push(@implContent, " forgetDOMObject(this, impl());\n"); 1218 } 1219 1220 push(@implContent, " JSSVGContextCache::forgetWrapper(this);\n") if IsSVGTypeNeedingContextParameter($implClassName); 1221 } 1222 1223 push(@implContent, "}\n\n"); 1224 } 1225 1226 if ($needsMarkChildren && !$dataNode->extendedAttributes->{"CustomMarkFunction"}) { 1227 push(@implContent, "void ${className}::markChildren(MarkStack& markStack)\n"); 1228 push(@implContent, "{\n"); 1229 push(@implContent, " Base::markChildren(markStack);\n"); 1230 push(@implContent, " impl()->markJSEventListeners(markStack);\n"); 1231 push(@implContent, "}\n\n"); 1232 } 1233 1234 if (!$dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"}) { 1235 push(@implContent, "JSObject* ${className}::createPrototype(ExecState* exec, JSGlobalObject* globalObject)\n"); 1236 push(@implContent, "{\n"); 1237 if ($hasParent && $parentClassName ne "JSC::DOMNodeFilter") { 1238 push(@implContent, " return new (exec) ${className}Prototype(${className}Prototype::createStructure(${parentClassName}Prototype::self(exec, globalObject)));\n"); 1239 } else { 1240 push(@implContent, " return new (exec) ${className}Prototype(${className}Prototype::createStructure(globalObject->objectPrototype()));\n"); 1241 } 1242 push(@implContent, "}\n\n"); 1243 } 1244 1245 my $hasGetter = $numAttributes > 0 1246 || !($dataNode->extendedAttributes->{"OmitConstructor"} 1247 || $dataNode->extendedAttributes->{"CustomConstructor"}) 1248 || $dataNode->extendedAttributes->{"HasIndexGetter"} 1249 || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} 1250 || $dataNode->extendedAttributes->{"HasNumericIndexGetter"} 1251 || $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"} 1252 || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"} 1253 || $dataNode->extendedAttributes->{"HasNameGetter"} 1254 || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}; 1255 1256 # Attributes 1257 if ($hasGetter) { 1258 if (!$dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"} && !$dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}) { 1259 push(@implContent, "bool ${className}::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n"); 1260 push(@implContent, "{\n"); 1261 push(@implContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 0)); 1262 push(@implContent, "}\n\n"); 1263 push(@implContent, "bool ${className}::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\n"); 1264 push(@implContent, "{\n"); 1265 push(@implContent, GenerateGetOwnPropertyDescriptorBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 0)); 1266 push(@implContent, "}\n\n"); 1267 } 1268 1269 if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) 1270 && !$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) { 1271 push(@implContent, "bool ${className}::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)\n"); 1272 push(@implContent, "{\n"); 1273 push(@implContent, " if (propertyName < static_cast<$implClassName*>(impl())->length()) {\n"); 1274 if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) { 1275 push(@implContent, " slot.setValue(getByIndex(exec, propertyName));\n"); 1276 } else { 1277 push(@implContent, " slot.setCustomIndex(this, propertyName, indexGetter);\n"); 1278 } 1279 push(@implContent, " return true;\n"); 1280 push(@implContent, " }\n"); 1281 push(@implContent, " return getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);\n"); 1282 push(@implContent, "}\n\n"); 1283 } 1284 1285 if ($numAttributes > 0) { 1286 foreach my $attribute (@{$dataNode->attributes}) { 1287 my $name = $attribute->signature->name; 1288 my $type = $codeGenerator->StripModule($attribute->signature->type); 1289 my $getFunctionName = "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : ""); 1290 my $implGetterFunctionName = $codeGenerator->WK_lcfirst($name); 1291 1292 my $conditional = $attribute->signature->extendedAttributes->{"Conditional"}; 1293 if ($conditional) { 1294 $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; 1295 push(@implContent, "#if ${conditionalString}\n"); 1296 } 1297 1298 push(@implContent, "JSValue ${getFunctionName}(ExecState* exec, const Identifier&, const PropertySlot& slot)\n"); 1299 push(@implContent, "{\n"); 1300 push(@implContent, " ${className}* castedThis = static_cast<$className*>(asObject(slot.slotBase()));\n"); 1301 1302 my $implClassNameForValueConversion = ""; 1303 if (!$podType and ($codeGenerator->IsSVGAnimatedType($implClassName) or $attribute->type !~ /^readonly/)) { 1304 $implClassNameForValueConversion = $implClassName; 1305 } 1306 1307 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && 1308 !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurity"} && 1309 !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurityOnGet"}) { 1310 push(@implContent, " if (!castedThis->allowsAccessFrom(exec))\n"); 1311 push(@implContent, " return jsUndefined();\n"); 1312 } 1313 1314 if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"} || $attribute->signature->extendedAttributes->{"CustomGetter"} || $attribute->signature->extendedAttributes->{"JSCCustomGetter"}) { 1315 push(@implContent, " return castedThis->$implGetterFunctionName(exec);\n"); 1316 } elsif ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) { 1317 $implIncludes{"JSDOMBinding.h"} = 1; 1318 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n"); 1319 push(@implContent, " return checkNodeSecurity(exec, imp->$implGetterFunctionName()) ? " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$implGetterFunctionName()", "castedThis") . " : jsUndefined();\n"); 1320 } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) { 1321 $implIncludes{"Document.h"} = 1; 1322 $implIncludes{"JSDOMBinding.h"} = 1; 1323 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n"); 1324 push(@implContent, " return checkNodeSecurity(exec, imp->contentDocument()) ? " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$implGetterFunctionName()", "castedThis") . " : jsUndefined();\n"); 1325 } elsif ($type eq "EventListener") { 1326 $implIncludes{"EventListener.h"} = 1; 1327 push(@implContent, " UNUSED_PARAM(exec);\n"); 1328 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n"); 1329 push(@implContent, " if (EventListener* listener = imp->$implGetterFunctionName()) {\n"); 1330 push(@implContent, " if (const JSEventListener* jsListener = JSEventListener::cast(listener)) {\n"); 1331 if ($implClassName eq "Document" || $implClassName eq "WorkerContext" || $implClassName eq "SharedWorkerContext" || $implClassName eq "DedicatedWorkerContext") { 1332 push(@implContent, " if (JSObject* jsFunction = jsListener->jsFunction(imp))\n"); 1333 } else { 1334 push(@implContent, " if (JSObject* jsFunction = jsListener->jsFunction(imp->scriptExecutionContext()))\n"); 1335 } 1336 push(@implContent, " return jsFunction;\n"); 1337 push(@implContent, " }\n"); 1338 push(@implContent, " }\n"); 1339 push(@implContent, " return jsNull();\n"); 1340 } elsif ($attribute->signature->type =~ /Constructor$/) { 1341 my $constructorType = $codeGenerator->StripModule($attribute->signature->type); 1342 $constructorType =~ s/Constructor$//; 1343 # Constructor attribute is only used by DOMWindow.idl, so it's correct to pass castedThis as the global object 1344 # Once DOMObjects have a back-pointer to the globalObject we can pass castedThis->globalObject() 1345 push(@implContent, " return JS" . $constructorType . "::getConstructor(exec, castedThis);\n"); 1346 } elsif (!@{$attribute->getterExceptions}) { 1347 push(@implContent, " UNUSED_PARAM(exec);\n"); 1348 my $cacheIndex = 0; 1349 if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) { 1350 $cacheIndex = $currentCachedAttribute; 1351 $currentCachedAttribute++; 1352 push(@implContent, " if (JSValue cachedValue = castedThis->getAnonymousValue(" . $className . "::" . $attribute->signature->name . "Slot))\n"); 1353 push(@implContent, " return cachedValue;\n"); 1354 } 1355 if ($podType) { 1356 push(@implContent, " $podType imp(*castedThis->impl());\n"); 1357 if ($podType eq "float") { # Special case for JSSVGNumber 1358 push(@implContent, " JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp", "castedThis") . ";\n"); 1359 } else { 1360 push(@implContent, " JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$implGetterFunctionName()", "castedThis") . ";\n"); 1361 } 1362 } else { 1363 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n"); 1364 my $value; 1365 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; 1366 my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"}; 1367 if ($reflect || $reflectURL) { 1368 my $contentAttributeName = (($reflect || $reflectURL) eq "1") ? $name : ($reflect || $reflectURL); 1369 my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName); 1370 $implIncludes{"${namespace}.h"} = 1; 1371 my $getAttributeFunctionName = $reflectURL ? "getURLAttribute" : "getAttribute"; 1372 $value = "imp->$getAttributeFunctionName(${namespace}::${contentAttributeName}Attr)" 1373 } else { 1374 $value = "imp->$implGetterFunctionName()"; 1375 } 1376 my $jsType = NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, $value, "castedThis"); 1377 if ($codeGenerator->IsSVGAnimatedType($type)) { 1378 push(@implContent, " RefPtr<$type> obj = $jsType;\n"); 1379 push(@implContent, " JSValue result = toJS(exec, castedThis->globalObject(), obj.get(), imp);\n"); 1380 } else { 1381 push(@implContent, " JSValue result = $jsType;\n"); 1382 } 1383 } 1384 1385 push(@implContent, " castedThis->putAnonymousValue(" . $className . "::" . $attribute->signature->name . "Slot, result);\n") if ($attribute->signature->extendedAttributes->{"CachedAttribute"}); 1386 push(@implContent, " return result;\n"); 1387 1388 } else { 1389 push(@implContent, " ExceptionCode ec = 0;\n"); 1390 if ($podType) { 1391 push(@implContent, " $podType imp(*castedThis->impl());\n"); 1392 push(@implContent, " JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$implGetterFunctionName(ec)", "castedThis") . ";\n"); 1393 } else { 1394 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n"); 1395 push(@implContent, " JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$implGetterFunctionName(ec)", "castedThis") . ";\n"); 1396 } 1397 1398 push(@implContent, " setDOMException(exec, ec);\n"); 1399 push(@implContent, " return result;\n"); 1400 } 1401 1402 push(@implContent, "}\n"); 1403 1404 if ($conditional) { 1405 push(@implContent, "#endif\n"); 1406 } 1407 1408 push(@implContent, "\n"); 1409 } 1410 1411 if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { 1412 my $constructorFunctionName = "js" . $interfaceName . "Constructor"; 1413 1414 push(@implContent, "JSValue ${constructorFunctionName}(ExecState* exec, const Identifier&, const PropertySlot& slot)\n"); 1415 push(@implContent, "{\n"); 1416 push(@implContent, " ${className}* domObject = static_cast<$className*>(asObject(slot.slotBase()));\n"); 1417 push(@implContent, " return ${className}::getConstructor(exec, domObject->globalObject());\n"); 1418 push(@implContent, "}\n"); 1419 } 1420 } 1421 1422 # Check if we have any writable attributes 1423 my $hasReadWriteProperties = 0; 1424 foreach my $attribute (@{$dataNode->attributes}) { 1425 $hasReadWriteProperties = 1 if $attribute->type !~ /^readonly/; 1426 } 1427 1428 my $hasSetter = $hasReadWriteProperties 1429 || $dataNode->extendedAttributes->{"DelegatingPutFunction"} 1430 || $dataNode->extendedAttributes->{"HasCustomIndexSetter"}; 1431 1432 if ($hasSetter) { 1433 if (!$dataNode->extendedAttributes->{"CustomPutFunction"}) { 1434 push(@implContent, "void ${className}::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)\n"); 1435 push(@implContent, "{\n"); 1436 if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) { 1437 push(@implContent, " bool ok;\n"); 1438 push(@implContent, " unsigned index = propertyName.toUInt32(&ok, false);\n"); 1439 push(@implContent, " if (ok) {\n"); 1440 push(@implContent, " indexSetter(exec, index, value);\n"); 1441 push(@implContent, " return;\n"); 1442 push(@implContent, " }\n"); 1443 } 1444 if ($dataNode->extendedAttributes->{"DelegatingPutFunction"}) { 1445 push(@implContent, " if (putDelegate(exec, propertyName, value, slot))\n"); 1446 push(@implContent, " return;\n"); 1447 } 1448 1449 if ($hasReadWriteProperties) { 1450 push(@implContent, " lookupPut<$className, Base>(exec, propertyName, value, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, slot);\n"); 1451 } else { 1452 push(@implContent, " Base::put(exec, propertyName, value, slot);\n"); 1453 } 1454 push(@implContent, "}\n\n"); 1455 } 1456 1457 if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) { 1458 push(@implContent, "void ${className}::put(ExecState* exec, unsigned propertyName, JSValue value)\n"); 1459 push(@implContent, "{\n"); 1460 push(@implContent, " indexSetter(exec, propertyName, value);\n"); 1461 push(@implContent, " return;\n"); 1462 push(@implContent, "}\n\n"); 1463 } 1464 1465 if ($hasReadWriteProperties) { 1466 foreach my $attribute (@{$dataNode->attributes}) { 1467 if ($attribute->type !~ /^readonly/) { 1468 my $name = $attribute->signature->name; 1469 my $type = $codeGenerator->StripModule($attribute->signature->type); 1470 my $putFunctionName = "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : ""); 1471 my $implSetterFunctionName = $codeGenerator->WK_ucfirst($name); 1472 1473 push(@implContent, "void ${putFunctionName}(ExecState* exec, JSObject* thisObject, JSValue value)\n"); 1474 push(@implContent, "{\n"); 1475 1476 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) { 1477 if ($interfaceName eq "DOMWindow") { 1478 push(@implContent, " if (!static_cast<$className*>(thisObject)->allowsAccessFrom(exec))\n"); 1479 } else { 1480 push(@implContent, " if (!allowsAccessFromFrame(exec, static_cast<$className*>(thisObject)->impl()->frame()))\n"); 1481 } 1482 push(@implContent, " return;\n"); 1483 } 1484 1485 if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"} || $attribute->signature->extendedAttributes->{"CustomSetter"} || $attribute->signature->extendedAttributes->{"JSCCustomSetter"}) { 1486 push(@implContent, " static_cast<$className*>(thisObject)->set$implSetterFunctionName(exec, value);\n"); 1487 } elsif ($type eq "EventListener") { 1488 $implIncludes{"JSEventListener.h"} = 1; 1489 push(@implContent, " UNUSED_PARAM(exec);\n"); 1490 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(thisObject)->impl());\n"); 1491 push(@implContent, " imp->set$implSetterFunctionName(createJSAttributeEventListener(exec, value, thisObject));\n"); 1492 } elsif ($attribute->signature->type =~ /Constructor$/) { 1493 my $constructorType = $attribute->signature->type; 1494 $constructorType =~ s/Constructor$//; 1495 $implIncludes{"JS" . $constructorType . ".h"} = 1; 1496 push(@implContent, " // Shadowing a built-in constructor\n"); 1497 push(@implContent, " static_cast<$className*>(thisObject)->putDirect(Identifier(exec, \"$name\"), value);\n"); 1498 } elsif ($attribute->signature->extendedAttributes->{"Replaceable"}) { 1499 push(@implContent, " // Shadowing a built-in object\n"); 1500 push(@implContent, " static_cast<$className*>(thisObject)->putDirect(Identifier(exec, \"$name\"), value);\n"); 1501 } else { 1502 push(@implContent, " $className* castedThisObj = static_cast<$className*>(thisObject);\n"); 1503 push(@implContent, " $implType* imp = static_cast<$implType*>(castedThisObj->impl());\n"); 1504 if ($podType) { 1505 push(@implContent, " $podType podImp(*imp);\n"); 1506 if ($podType eq "float") { # Special case for JSSVGNumber 1507 push(@implContent, " podImp = " . JSValueToNative($attribute->signature, "value") . ";\n"); 1508 } else { 1509 push(@implContent, " podImp.set$implSetterFunctionName(" . JSValueToNative($attribute->signature, "value") . ");\n"); 1510 } 1511 push(@implContent, " imp->commitChange(podImp, castedThisObj);\n"); 1512 } else { 1513 my $nativeValue = JSValueToNative($attribute->signature, "value"); 1514 push(@implContent, " ExceptionCode ec = 0;\n") if @{$attribute->setterExceptions}; 1515 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; 1516 my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"}; 1517 if ($reflect || $reflectURL) { 1518 my $contentAttributeName = (($reflect || $reflectURL) eq "1") ? $name : ($reflect || $reflectURL); 1519 my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName); 1520 $implIncludes{"${namespace}.h"} = 1; 1521 push(@implContent, " imp->setAttribute(${namespace}::${contentAttributeName}Attr, $nativeValue"); 1522 } else { 1523 push(@implContent, " imp->set$implSetterFunctionName($nativeValue"); 1524 } 1525 push(@implContent, ", ec") if @{$attribute->setterExceptions}; 1526 push(@implContent, ");\n"); 1527 push(@implContent, " setDOMException(exec, ec);\n") if @{$attribute->setterExceptions}; 1528 if (IsSVGTypeNeedingContextParameter($implClassName)) { 1529 push(@implContent, " JSSVGContextCache::propagateSVGDOMChange(castedThisObj, imp->associatedAttributeName());\n"); 1530 } 1531 } 1532 } 1533 1534 push(@implContent, "}\n\n"); 1535 } 1536 } 1537 } 1538 } 1539 } 1540 1541 if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) && !$dataNode->extendedAttributes->{"CustomGetPropertyNames"}) { 1542 push(@implContent, "void ${className}::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)\n"); 1543 push(@implContent, "{\n"); 1544 if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) { 1545 push(@implContent, " for (unsigned i = 0; i < static_cast<${implClassName}*>(impl())->length(); ++i)\n"); 1546 push(@implContent, " propertyNames.add(Identifier::from(exec, i));\n"); 1547 } 1548 push(@implContent, " Base::getOwnPropertyNames(exec, propertyNames, mode);\n"); 1549 push(@implContent, "}\n\n"); 1550 } 1551 1552 if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { 1553 push(@implContent, "JSValue ${className}::getConstructor(ExecState* exec, JSGlobalObject* globalObject)\n{\n"); 1554 push(@implContent, " return getDOMConstructor<${className}Constructor>(exec, static_cast<JSDOMGlobalObject*>(globalObject));\n"); 1555 push(@implContent, "}\n\n"); 1556 } 1557 1558 # Functions 1559 if ($numFunctions > 0) { 1560 foreach my $function (@{$dataNode->functions}) { 1561 AddIncludesForType($function->signature->type); 1562 1563 my $functionName = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($function->signature->name); 1564 my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementationFunction"} || $codeGenerator->WK_lcfirst($function->signature->name); 1565 1566 push(@implContent, "JSValue JSC_HOST_CALL ${functionName}(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)\n"); 1567 push(@implContent, "{\n"); 1568 push(@implContent, " UNUSED_PARAM(args);\n"); 1569 1570 $implIncludes{"<runtime/Error.h>"} = 1; 1571 1572 if ($interfaceName eq "DOMWindow") { 1573 push(@implContent, " $className* castedThisObj = toJSDOMWindow(thisValue.toThisObject(exec));\n"); 1574 push(@implContent, " if (!castedThisObj)\n"); 1575 push(@implContent, " return throwError(exec, TypeError);\n"); 1576 } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) { 1577 push(@implContent, " $className* castedThisObj = to${className}(thisValue.toThisObject(exec));\n"); 1578 push(@implContent, " if (!castedThisObj)\n"); 1579 push(@implContent, " return throwError(exec, TypeError);\n"); 1580 } else { 1581 push(@implContent, " if (!thisValue.inherits(&${className}::s_info))\n"); 1582 push(@implContent, " return throwError(exec, TypeError);\n"); 1583 push(@implContent, " $className* castedThisObj = static_cast<$className*>(asObject(thisValue));\n"); 1584 } 1585 1586 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && 1587 !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) { 1588 push(@implContent, " if (!castedThisObj->allowsAccessFrom(exec))\n"); 1589 push(@implContent, " return jsUndefined();\n"); 1590 } 1591 1592 # Special case for JSSVGLengthList / JSSVGTransformList / JSSVGPointList / JSSVGNumberList 1593 # Instead of having JSSVG*Custom.cpp implementations for the SVGList interface for all of these 1594 # classes, we directly forward the calls to JSSVGPODListCustom, which centralizes the otherwise 1595 # duplicated code for the JSSVG*List classes mentioned above. 1596 my $svgPODListType; 1597 if ($implClassName =~ /SVG.*List/) { 1598 $svgPODListType = $implClassName; 1599 $svgPODListType =~ s/List$//; 1600 $svgPODListType = "" unless $codeGenerator->IsPodType($svgPODListType); 1601 1602 # Ignore additional (non-SVGList) SVGTransformList methods, that are not handled through JSSVGPODListCustom 1603 $svgPODListType = "" if $functionImplementationName =~ /createSVGTransformFromMatrix/; 1604 $svgPODListType = "" if $functionImplementationName =~ /consolidate/; 1605 } 1606 1607 if ($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"JSCCustom"}) { 1608 push(@implContent, " return castedThisObj->" . $functionImplementationName . "(exec, args);\n"); 1609 } elsif ($svgPODListType) { 1610 $implIncludes{"JS${svgPODListType}.h"} = 1; 1611 $implIncludes{"JSSVGPODListCustom.h"} = 1; 1612 push(@implContent, " return JSSVGPODListCustom::$functionImplementationName<$className, " . GetNativeType($svgPODListType) 1613 . ">(castedThisObj, exec, args, to" . $svgPODListType . ");\n"); 1614 } else { 1615 push(@implContent, " $implType* imp = static_cast<$implType*>(castedThisObj->impl());\n"); 1616 push(@implContent, " $podType podImp(*imp);\n") if $podType; 1617 1618 my $numParameters = @{$function->parameters}; 1619 1620 if ($function->signature->extendedAttributes->{"RequiresAllArguments"}) { 1621 push(@implContent, " if (args.size() < $numParameters)\n"); 1622 push(@implContent, " return jsUndefined();\n"); 1623 } 1624 1625 if (@{$function->raisesExceptions}) { 1626 push(@implContent, " ExceptionCode ec = 0;\n"); 1627 } 1628 1629 if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) { 1630 push(@implContent, " if (!checkNodeSecurity(exec, imp->getSVGDocument(" . (@{$function->raisesExceptions} ? "ec" : "") .")))\n"); 1631 push(@implContent, " return jsUndefined();\n"); 1632 $implIncludes{"JSDOMBinding.h"} = 1; 1633 } 1634 1635 my $paramIndex = 0; 1636 my $functionString = ($podType ? "podImp." : "imp->") . $functionImplementationName . "("; 1637 1638 my $hasOptionalArguments = 0; 1639 1640 if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) { 1641 push(@implContent, " ScriptCallStack callStack(exec, args, $numParameters);\n"); 1642 $implIncludes{"ScriptCallStack.h"} = 1; 1643 } 1644 1645 foreach my $parameter (@{$function->parameters}) { 1646 if (!$hasOptionalArguments && $parameter->extendedAttributes->{"Optional"}) { 1647 push(@implContent, "\n int argsCount = args.size();\n"); 1648 $hasOptionalArguments = 1; 1649 } 1650 1651 if ($hasOptionalArguments) { 1652 push(@implContent, " if (argsCount < " . ($paramIndex + 1) . ") {\n"); 1653 GenerateImplementationFunctionCall($function, $functionString, $paramIndex, " " x 2, $podType, $implClassName); 1654 push(@implContent, " }\n\n"); 1655 } 1656 1657 my $name = $parameter->name; 1658 1659 if ($parameter->type eq "XPathNSResolver") { 1660 push(@implContent, " RefPtr<XPathNSResolver> customResolver;\n"); 1661 push(@implContent, " XPathNSResolver* resolver = toXPathNSResolver(args.at($paramIndex));\n"); 1662 push(@implContent, " if (!resolver) {\n"); 1663 push(@implContent, " customResolver = JSCustomXPathNSResolver::create(exec, args.at($paramIndex));\n"); 1664 push(@implContent, " if (exec->hadException())\n"); 1665 push(@implContent, " return jsUndefined();\n"); 1666 push(@implContent, " resolver = customResolver.get();\n"); 1667 push(@implContent, " }\n"); 1668 } else { 1669 push(@implContent, " " . GetNativeTypeFromSignature($parameter) . " $name = " . JSValueToNative($parameter, "args.at($paramIndex)") . ";\n"); 1670 1671 # If a parameter is "an index" and it's negative it should throw an INDEX_SIZE_ERR exception. 1672 # But this needs to be done in the bindings, because the type is unsigned and the fact that it 1673 # was negative will be lost by the time we're inside the DOM. 1674 if ($parameter->extendedAttributes->{"IsIndex"}) { 1675 $implIncludes{"ExceptionCode.h"} = 1; 1676 push(@implContent, " if ($name < 0) {\n"); 1677 push(@implContent, " setDOMException(exec, INDEX_SIZE_ERR);\n"); 1678 push(@implContent, " return jsUndefined();\n"); 1679 push(@implContent, " }\n"); 1680 } 1681 } 1682 1683 $functionString .= ", " if $paramIndex; 1684 1685 if ($parameter->type eq "NodeFilter") { 1686 $functionString .= "$name.get()"; 1687 } else { 1688 $functionString .= $name; 1689 } 1690 $paramIndex++; 1691 } 1692 1693 if ($function->signature->extendedAttributes->{"NeedsUserGestureCheck"}) { 1694 $functionString .= ", " if $paramIndex; 1695 $functionString .= "processingUserGesture(exec)"; 1696 $paramIndex++; 1697 } 1698 1699 push(@implContent, "\n"); 1700 GenerateImplementationFunctionCall($function, $functionString, $paramIndex, " ", $podType, $implClassName); 1701 } 1702 push(@implContent, "}\n\n"); 1703 } 1704 } 1705 1706 if ($numConstants > 0) { 1707 push(@implContent, "// Constant getters\n\n"); 1708 1709 foreach my $constant (@{$dataNode->constants}) { 1710 my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name); 1711 1712 # FIXME: this casts into int to match our previous behavior which turned 0xFFFFFFFF in -1 for NodeFilter.SHOW_ALL 1713 push(@implContent, "JSValue ${getter}(ExecState* exec, const Identifier&, const PropertySlot&)\n"); 1714 push(@implContent, "{\n"); 1715 push(@implContent, " return jsNumber(exec, static_cast<int>(" . $constant->value . "));\n"); 1716 push(@implContent, "}\n\n"); 1717 } 1718 } 1719 1720 if ($dataNode->extendedAttributes->{"HasIndexGetter"}) { 1721 push(@implContent, "\nJSValue ${className}::indexGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)\n"); 1722 push(@implContent, "{\n"); 1723 push(@implContent, " ${className}* thisObj = static_cast<$className*>(asObject(slot.slotBase()));\n"); 1724 if (IndexGetterReturnsStrings($implClassName)) { 1725 $implIncludes{"KURL.h"} = 1; 1726 push(@implContent, " return jsStringOrNull(exec, thisObj->impl()->item(slot.index()));\n"); 1727 } else { 1728 push(@implContent, " return toJS(exec, thisObj->globalObject(), static_cast<$implClassName*>(thisObj->impl())->item(slot.index()));\n"); 1729 } 1730 push(@implContent, "}\n"); 1731 if ($interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") { 1732 $implIncludes{"JSNode.h"} = 1; 1733 $implIncludes{"Node.h"} = 1; 1734 } 1735 } 1736 1737 if ($dataNode->extendedAttributes->{"HasNumericIndexGetter"}) { 1738 push(@implContent, "\nJSValue ${className}::getByIndex(ExecState* exec, unsigned index)\n"); 1739 push(@implContent, "{\n"); 1740 push(@implContent, " return jsNumber(exec, static_cast<$implClassName*>(impl())->item(index));\n"); 1741 push(@implContent, "}\n"); 1742 if ($interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") { 1743 $implIncludes{"JSNode.h"} = 1; 1744 $implIncludes{"Node.h"} = 1; 1745 } 1746 } 1747 1748 if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateToJS"}) and !$dataNode->extendedAttributes->{"CustomToJS"}) { 1749 if ($podType) { 1750 push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, JSSVGPODTypeWrapper<$podType>* object, SVGElement* context)\n"); 1751 } elsif (IsSVGTypeNeedingContextParameter($implClassName)) { 1752 push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* object, SVGElement* context)\n"); 1753 } else { 1754 push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* object)\n"); 1755 } 1756 push(@implContent, "{\n"); 1757 if ($podType) { 1758 push(@implContent, " return getDOMObjectWrapper<$className, JSSVGPODTypeWrapper<$podType> >(exec, globalObject, object, context);\n"); 1759 } elsif (IsSVGTypeNeedingContextParameter($implClassName)) { 1760 push(@implContent, " return getDOMObjectWrapper<$className>(exec, globalObject, object, context);\n"); 1761 } else { 1762 push(@implContent, " return getDOMObjectWrapper<$className>(exec, globalObject, object);\n"); 1763 } 1764 push(@implContent, "}\n"); 1765 } 1766 1767 if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateNativeConverter"}) and !$dataNode->extendedAttributes->{"CustomNativeConverter"}) { 1768 if ($podType) { 1769 push(@implContent, "$podType to${interfaceName}(JSC::JSValue value)\n"); 1770 } else { 1771 push(@implContent, "$implClassName* to${interfaceName}(JSC::JSValue value)\n"); 1772 } 1773 1774 push(@implContent, "{\n"); 1775 1776 push(@implContent, " return value.inherits(&${className}::s_info) ? " . ($podType ? "($podType) *" : "") . "static_cast<$className*>(asObject(value))->impl() : "); 1777 if ($podType and $podType ne "float") { 1778 push(@implContent, "$podType();\n}\n"); 1779 } else { 1780 push(@implContent, "0;\n}\n"); 1781 } 1782 } 1783 1784 push(@implContent, "\n}\n"); 1785 1786 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditional; 1787 } 1788 1789 sub GenerateImplementationFunctionCall() 1790 { 1791 my $function = shift; 1792 my $functionString = shift; 1793 my $paramIndex = shift; 1794 my $indent = shift; 1795 my $podType = shift; 1796 my $implClassName = shift; 1797 1798 if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) { 1799 $functionString .= ", " if $paramIndex; 1800 ++$paramIndex; 1801 $functionString .= "&callStack"; 1802 } 1803 1804 if (@{$function->raisesExceptions}) { 1805 $functionString .= ", " if $paramIndex; 1806 $functionString .= "ec"; 1807 } 1808 $functionString .= ")"; 1809 1810 if ($function->signature->type eq "void") { 1811 push(@implContent, $indent . "$functionString;\n"); 1812 push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions}; 1813 push(@implContent, $indent . "imp->commitChange(podImp, castedThisObj);\n") if $podType; 1814 push(@implContent, $indent . "return jsUndefined();\n"); 1815 } else { 1816 push(@implContent, "\n" . $indent . "JSC::JSValue result = " . NativeToJSValue($function->signature, 1, $implClassName, "", $functionString, "castedThisObj") . ";\n"); 1817 push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions}; 1818 1819 if ($podType and not $function->signature->extendedAttributes->{"Immutable"}) { 1820 # Immutable methods do not commit changes back to the instance, thus producing 1821 # a new instance rather than mutating existing one. 1822 push(@implContent, $indent . "imp->commitChange(podImp, castedThisObj);\n"); 1823 } 1824 1825 push(@implContent, $indent . "return result;\n"); 1826 } 1827 } 1828 1829 sub GetNativeTypeFromSignature 1830 { 1831 my $signature = shift; 1832 my $type = $codeGenerator->StripModule($signature->type); 1833 1834 if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) { 1835 # Special-case index arguments because we need to check that they aren't < 0. 1836 return "int"; 1837 } 1838 1839 return GetNativeType($type); 1840 } 1841 1842 my %nativeType = ( 1843 "CompareHow" => "Range::CompareHow", 1844 "DOMString" => "const UString&", 1845 "NodeFilter" => "RefPtr<NodeFilter>", 1846 "SVGAngle" => "SVGAngle", 1847 "SVGLength" => "SVGLength", 1848 "SVGMatrix" => "AffineTransform", 1849 "SVGNumber" => "float", 1850 "SVGPaintType" => "SVGPaint::SVGPaintType", 1851 "SVGPreserveAspectRatio" => "SVGPreserveAspectRatio", 1852 "SVGPoint" => "FloatPoint", 1853 "SVGRect" => "FloatRect", 1854 "SVGTransform" => "SVGTransform", 1855 "boolean" => "bool", 1856 "double" => "double", 1857 "float" => "float", 1858 "long" => "int", 1859 "unsigned long" => "unsigned", 1860 "unsigned short" => "unsigned short", 1861 "long long" => "long long", 1862 "unsigned long long" => "unsigned long long", 1863 ); 1864 1865 sub GetNativeType 1866 { 1867 my $type = shift; 1868 1869 return $nativeType{$type} if exists $nativeType{$type}; 1870 1871 # For all other types, the native type is a pointer with same type name as the IDL type. 1872 return "${type}*"; 1873 } 1874 1875 sub JSValueToNative 1876 { 1877 my $signature = shift; 1878 my $value = shift; 1879 1880 my $type = $codeGenerator->StripModule($signature->type); 1881 1882 return "$value.toBoolean(exec)" if $type eq "boolean"; 1883 return "$value.toNumber(exec)" if $type eq "double"; 1884 return "$value.toFloat(exec)" if $type eq "float" or $type eq "SVGNumber"; 1885 return "$value.toInt32(exec)" if $type eq "unsigned long" or $type eq "long" or $type eq "unsigned short"; 1886 return "static_cast<$type>($value.toInteger(exec))" if $type eq "long long" or $type eq "unsigned long long"; 1887 1888 return "valueToDate(exec, $value)" if $type eq "Date"; 1889 return "static_cast<Range::CompareHow>($value.toInt32(exec))" if $type eq "CompareHow"; 1890 return "static_cast<SVGPaint::SVGPaintType>($value.toInt32(exec))" if $type eq "SVGPaintType"; 1891 1892 if ($type eq "DOMString") { 1893 return "valueToStringWithNullCheck(exec, $value)" if $signature->extendedAttributes->{"ConvertNullToNullString"}; 1894 return "valueToStringWithUndefinedOrNullCheck(exec, $value)" if $signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"}; 1895 return "$value.toString(exec)"; 1896 } 1897 1898 if ($type eq "SerializedScriptValue" or $type eq "any") { 1899 $implIncludes{"SerializedScriptValue.h"} = 1; 1900 return "SerializedScriptValue::create(exec, $value)"; 1901 } 1902 1903 $implIncludes{"FloatPoint.h"} = 1 if $type eq "SVGPoint"; 1904 $implIncludes{"FloatRect.h"} = 1 if $type eq "SVGRect"; 1905 $implIncludes{"HTMLOptionElement.h"} = 1 if $type eq "HTMLOptionElement"; 1906 $implIncludes{"JSCustomVoidCallback.h"} = 1 if $type eq "VoidCallback"; 1907 $implIncludes{"Event.h"} = 1 if $type eq "Event"; 1908 1909 # Default, assume autogenerated type conversion routines 1910 $implIncludes{"JS$type.h"} = 1; 1911 return "to$type($value)"; 1912 } 1913 1914 sub NativeToJSValue 1915 { 1916 my $signature = shift; 1917 my $inFunctionCall = shift; 1918 my $implClassName = shift; 1919 my $implClassNameForValueConversion = shift; 1920 my $value = shift; 1921 my $thisValue = shift; 1922 1923 my $type = $codeGenerator->StripModule($signature->type); 1924 1925 return "jsBoolean($value)" if $type eq "boolean"; 1926 1927 # Need to check Date type before IsPrimitiveType(). 1928 if ($type eq "Date") { 1929 return "jsDateOrNull(exec, $value)"; 1930 } 1931 if ($codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType" or $type eq "DOMTimeStamp") { 1932 $implIncludes{"<runtime/JSNumberCell.h>"} = 1; 1933 return "jsNumber(exec, $value)"; 1934 } 1935 1936 if ($codeGenerator->IsStringType($type)) { 1937 $implIncludes{"KURL.h"} = 1; 1938 my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"}; 1939 if (defined $conv) { 1940 return "jsStringOrNull(exec, $value)" if $conv eq "Null"; 1941 return "jsStringOrUndefined(exec, $value)" if $conv eq "Undefined"; 1942 return "jsStringOrFalse(exec, $value)" if $conv eq "False"; 1943 1944 die "Unknown value for ConvertNullStringTo extended attribute"; 1945 } 1946 $implIncludes{"<runtime/JSString.h>"} = 1; 1947 return "jsString(exec, $value)"; 1948 } 1949 1950 my $globalObject = "$thisValue->globalObject()"; 1951 if ($codeGenerator->IsPodType($type)) { 1952 $implIncludes{"JS$type.h"} = 1; 1953 1954 my $nativeType = GetNativeType($type); 1955 1956 my $getter = $value; 1957 $getter =~ s/imp->//; 1958 $getter =~ s/\(\)//; 1959 1960 my $setter = "set" . $codeGenerator->WK_ucfirst($getter); 1961 1962 # Function calls will never return 'modifyable' POD types (ie. SVGRect getBBox()) - no need to keep track changes to the returned SVGRect 1963 if ($inFunctionCall eq 0 1964 and not $codeGenerator->IsSVGAnimatedType($implClassName) 1965 and $codeGenerator->IsPodTypeWithWriteableProperties($type) 1966 and not defined $signature->extendedAttributes->{"Immutable"}) { 1967 if ($codeGenerator->IsPodType($implClassName)) { 1968 return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($value, $thisValue->impl()).get(), JSSVGContextCache::svgContextForDOMObject(castedThis))"; 1969 } else { 1970 return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName>::create(imp, &${implClassName}::$getter, &${implClassName}::$setter).get(), imp)"; 1971 } 1972 } 1973 1974 if ($implClassNameForValueConversion eq "") { 1975 return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), 0 /* no context on purpose */)"; 1976 } else { 1977 return "toJS(exec, $globalObject, JSSVGDynamicPODTypeWrapperCache<$nativeType, $implClassNameForValueConversion>::lookupOrCreateWrapper(imp, &${implClassNameForValueConversion}::$getter, &${implClassNameForValueConversion}::$setter).get(), JSSVGContextCache::svgContextForDOMObject(castedThis));" 1978 } 1979 } 1980 1981 if ($codeGenerator->IsSVGAnimatedType($type)) { 1982 # Some SVGFE*Element.idl use 'operator' as attribute name, rewrite as '_operator' to avoid clashes with C/C++ 1983 $value =~ s/operator\(\)/_operator\(\)/ if ($value =~ /operator/); 1984 $value =~ s/\(\)//; 1985 $value .= "Animated()"; 1986 } 1987 1988 if ($type eq "CSSStyleDeclaration") { 1989 $implIncludes{"CSSMutableStyleDeclaration.h"} = 1; 1990 } 1991 1992 if ($type eq "NodeList") { 1993 $implIncludes{"NameNodeList.h"} = 1; 1994 } 1995 1996 if ($type eq "DOMObject") { 1997 $implIncludes{"JSCanvasRenderingContext2D.h"} = 1; 1998 } elsif ($type =~ /SVGPathSeg/) { 1999 $implIncludes{"JS$type.h"} = 1; 2000 $joinedName = $type; 2001 $joinedName =~ s/Abs|Rel//; 2002 $implIncludes{"$joinedName.h"} = 1; 2003 } elsif ($type eq "SerializedScriptValue" or $type eq "any") { 2004 $implIncludes{"SerializedScriptValue.h"} = 1; 2005 return "$value ? $value->deserialize(exec, castedThis->globalObject()) : jsNull()"; 2006 } else { 2007 # Default, include header with same name. 2008 $implIncludes{"JS$type.h"} = 1; 2009 $implIncludes{"$type.h"} = 1; 2010 } 2011 2012 return $value if $codeGenerator->IsSVGAnimatedType($type); 2013 2014 if (IsSVGTypeNeedingContextParameter($type)) { 2015 my $contextPtr = IsSVGTypeNeedingContextParameter($implClassName) ? "JSSVGContextCache::svgContextForDOMObject(castedThis)" : "imp"; 2016 return "toJS(exec, $globalObject, WTF::getPtr($value), $contextPtr)"; 2017 } 2018 2019 if ($signature->extendedAttributes->{"ReturnsNew"}) { 2020 return "toJSNewlyCreated(exec, $globalObject, WTF::getPtr($value))"; 2021 } 2022 2023 return "toJS(exec, $globalObject, WTF::getPtr($value))"; 2024 } 2025 2026 sub ceilingToPowerOf2 2027 { 2028 my ($size) = @_; 2029 2030 my $powerOf2 = 1; 2031 while ($size > $powerOf2) { 2032 $powerOf2 <<= 1; 2033 } 2034 2035 return $powerOf2; 2036 } 2037 2038 # Internal Helper 2039 sub GenerateHashTable 2040 { 2041 my $object = shift; 2042 2043 my $name = shift; 2044 my $size = shift; 2045 my $keys = shift; 2046 my $specials = shift; 2047 my $value1 = shift; 2048 my $value2 = shift; 2049 my $conditionals = shift; 2050 2051 # Generate size data for two hash tables 2052 # - The 'perfect' size makes a table large enough for perfect hashing 2053 # - The 'compact' size uses the legacy table format for smaller table sizes 2054 2055 # Perfect size 2056 my @hashes = (); 2057 foreach my $key (@{$keys}) { 2058 push @hashes, $object->GenerateHashValue($key); 2059 } 2060 2061 # Compact size 2062 my @table = (); 2063 my @links = (); 2064 2065 my $compactSize = ceilingToPowerOf2($size * 2); 2066 2067 my $maxDepth = 0; 2068 my $collisions = 0; 2069 my $numEntries = $compactSize; 2070 2071 my $i = 0; 2072 foreach (@{$keys}) { 2073 my $depth = 0; 2074 my $h = $object->GenerateHashValue($_) % $numEntries; 2075 2076 while (defined($table[$h])) { 2077 if (defined($links[$h])) { 2078 $h = $links[$h]; 2079 $depth++; 2080 } else { 2081 $collisions++; 2082 $links[$h] = $compactSize; 2083 $h = $compactSize; 2084 $compactSize++; 2085 } 2086 } 2087 2088 $table[$h] = $i; 2089 2090 $i++; 2091 $maxDepth = $depth if ($depth > $maxDepth); 2092 } 2093 2094 # Collect hashtable information 2095 my $perfectSize; 2096 tableSizeLoop: 2097 for ($perfectSize = ceilingToPowerOf2(scalar @{$keys}); ; $perfectSize += $perfectSize) { 2098 my @table = (); 2099 my $i = 0; 2100 foreach my $hash (@hashes) { 2101 my $h = $hash % $perfectSize; 2102 next tableSizeLoop if defined $table[$h]; 2103 $table[$h] = $i++; 2104 } 2105 last; 2106 } 2107 2108 # Start outputing the hashtables 2109 my $nameEntries = "${name}Values"; 2110 $nameEntries =~ s/:/_/g; 2111 2112 if (($name =~ /Prototype/) or ($name =~ /Constructor/)) { 2113 my $type = $name; 2114 my $implClass; 2115 2116 if ($name =~ /Prototype/) { 2117 $type =~ s/Prototype.*//; 2118 $implClass = $type; $implClass =~ s/Wrapper$//; 2119 push(@implContent, "/* Hash table for prototype */\n"); 2120 } else { 2121 $type =~ s/Constructor.*//; 2122 $implClass = $type; $implClass =~ s/Constructor$//; 2123 push(@implContent, "/* Hash table for constructor */\n"); 2124 } 2125 } else { 2126 push(@implContent, "/* Hash table */\n"); 2127 } 2128 2129 # Dump the hash table 2130 my $count = scalar @{$keys} + 1; 2131 push(@implContent, "\nstatic const HashTableValue $nameEntries\[$count\] =\n\{\n"); 2132 $i = 0; 2133 foreach my $key (@{$keys}) { 2134 my $conditional; 2135 2136 if ($conditionals) { 2137 $conditional = $conditionals->{$key}; 2138 } 2139 if ($conditional) { 2140 my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; 2141 push(@implContent, "#if ${conditionalString}\n"); 2142 } 2143 push(@implContent, " { \"$key\", @$specials[$i], (intptr_t)@$value1[$i], (intptr_t)@$value2[$i] },\n"); 2144 if ($conditional) { 2145 push(@implContent, "#endif\n"); 2146 } 2147 ++$i; 2148 } 2149 push(@implContent, " { 0, 0, 0, 0 }\n"); 2150 push(@implContent, "};\n\n"); 2151 my $perfectSizeMask = $perfectSize - 1; 2152 my $compactSizeMask = $numEntries - 1; 2153 push(@implContent, "static JSC_CONST_HASHTABLE HashTable $name =\n"); 2154 push(@implContent, "#if ENABLE(PERFECT_HASH_SIZE)\n"); 2155 push(@implContent, " { $perfectSizeMask, $nameEntries, 0 };\n"); 2156 push(@implContent, "#else\n"); 2157 push(@implContent, " { $compactSize, $compactSizeMask, $nameEntries, 0 };\n"); 2158 push(@implContent, "#endif\n\n"); 2159 } 2160 2161 # Internal helper 2162 sub GenerateHashValue 2163 { 2164 my $object = shift; 2165 2166 @chars = split(/ */, $_[0]); 2167 2168 # This hash is designed to work on 16-bit chunks at a time. But since the normal case 2169 # (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they 2170 # were 16-bit chunks, which should give matching results 2171 2172 my $EXP2_32 = 4294967296; 2173 2174 my $hash = 0x9e3779b9; 2175 my $l = scalar @chars; #I wish this was in Ruby --- Maks 2176 my $rem = $l & 1; 2177 $l = $l >> 1; 2178 2179 my $s = 0; 2180 2181 # Main loop 2182 for (; $l > 0; $l--) { 2183 $hash += ord($chars[$s]); 2184 my $tmp = leftShift(ord($chars[$s+1]), 11) ^ $hash; 2185 $hash = (leftShift($hash, 16)% $EXP2_32) ^ $tmp; 2186 $s += 2; 2187 $hash += $hash >> 11; 2188 $hash %= $EXP2_32; 2189 } 2190 2191 # Handle end case 2192 if ($rem != 0) { 2193 $hash += ord($chars[$s]); 2194 $hash ^= (leftShift($hash, 11)% $EXP2_32); 2195 $hash += $hash >> 17; 2196 } 2197 2198 # Force "avalanching" of final 127 bits 2199 $hash ^= leftShift($hash, 3); 2200 $hash += ($hash >> 5); 2201 $hash = ($hash% $EXP2_32); 2202 $hash ^= (leftShift($hash, 2)% $EXP2_32); 2203 $hash += ($hash >> 15); 2204 $hash = $hash% $EXP2_32; 2205 $hash ^= (leftShift($hash, 10)% $EXP2_32); 2206 2207 # this avoids ever returning a hash code of 0, since that is used to 2208 # signal "hash not computed yet", using a value that is likely to be 2209 # effectively the same as 0 when the low bits are masked 2210 $hash = 0x80000000 if ($hash == 0); 2211 2212 return $hash; 2213 } 2214 2215 # Internal helper 2216 sub WriteData 2217 { 2218 if (defined($IMPL)) { 2219 # Write content to file. 2220 print $IMPL @implContentHeader; 2221 2222 my @includes = (); 2223 foreach my $include (keys %implIncludes) { 2224 my $checkType = $include; 2225 $checkType =~ s/\.h//; 2226 next if $codeGenerator->IsSVGAnimatedType($checkType); 2227 2228 $include = "\"$include\"" unless $include =~ /^["<]/; # " 2229 push @includes, $include; 2230 } 2231 foreach my $include (sort @includes) { 2232 print $IMPL "#include $include\n"; 2233 } 2234 2235 print $IMPL @implContent; 2236 close($IMPL); 2237 undef($IMPL); 2238 2239 @implContentHeader = (); 2240 @implContent = (); 2241 %implIncludes = (); 2242 } 2243 2244 if (defined($HEADER)) { 2245 # Write content to file. 2246 print $HEADER @headerContentHeader; 2247 2248 my @includes = (); 2249 foreach my $include (keys %headerIncludes) { 2250 $include = "\"$include\"" unless $include =~ /^["<]/; # " 2251 push @includes, $include; 2252 } 2253 foreach my $include (sort @includes) { 2254 print $HEADER "#include $include\n"; 2255 } 2256 2257 print $HEADER @headerContent; 2258 close($HEADER); 2259 undef($HEADER); 2260 2261 @headerContentHeader = (); 2262 @headerContent = (); 2263 %headerIncludes = (); 2264 } 2265 2266 if (defined($DEPS)) { 2267 # Write dependency file. 2268 print $DEPS @depsContent; 2269 close($DEPS); 2270 undef($DEPS); 2271 2272 @depsContent = (); 2273 } 2274 } 2275 2276 sub constructorFor 2277 { 2278 my $className = shift; 2279 my $protoClassName = shift; 2280 my $interfaceName = shift; 2281 my $visibleClassName = shift; 2282 my $canConstruct = shift; 2283 my $constructorClassName = "${className}Constructor"; 2284 2285 my $implContent = << "EOF"; 2286 class ${constructorClassName} : public DOMConstructorObject { 2287 public: 2288 ${constructorClassName}(ExecState* exec, JSDOMGlobalObject* globalObject) 2289 : DOMConstructorObject(${constructorClassName}::createStructure(globalObject->objectPrototype()), globalObject) 2290 { 2291 putDirect(exec->propertyNames().prototype, ${protoClassName}::self(exec, globalObject), None); 2292 } 2293 virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); 2294 virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); 2295 virtual const ClassInfo* classInfo() const { return &s_info; } 2296 static const ClassInfo s_info; 2297 2298 static PassRefPtr<Structure> createStructure(JSValue proto) 2299 { 2300 return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); 2301 } 2302 2303 protected: 2304 static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | DOMConstructorObject::StructureFlags; 2305 EOF 2306 2307 if ($canConstruct) { 2308 $implContent .= << "EOF"; 2309 static JSObject* construct${interfaceName}(ExecState* exec, JSObject* constructor, const ArgList&) 2310 { 2311 return asObject(toJS(exec, static_cast<${constructorClassName}*>(constructor)->globalObject(), ${interfaceName}::create())); 2312 } 2313 virtual ConstructType getConstructData(ConstructData& constructData) 2314 { 2315 constructData.native.function = construct${interfaceName}; 2316 return ConstructTypeHost; 2317 } 2318 EOF 2319 } 2320 2321 $implContent .= << "EOF"; 2322 }; 2323 2324 const ClassInfo ${constructorClassName}::s_info = { "${visibleClassName}Constructor", 0, &${constructorClassName}Table, 0 }; 2325 2326 bool ${constructorClassName}::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) 2327 { 2328 return getStaticValueSlot<${constructorClassName}, DOMObject>(exec, &${constructorClassName}Table, this, propertyName, slot); 2329 } 2330 2331 bool ${constructorClassName}::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) 2332 { 2333 return getStaticValueDescriptor<${constructorClassName}, DOMObject>(exec, &${constructorClassName}Table, this, propertyName, descriptor); 2334 } 2335 2336 EOF 2337 2338 $implJSCInclude{"JSNumberCell.h"} = 1; # FIXME: What is this for? 2339 2340 return $implContent; 2341 } 2342 2343 1; 2344