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