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