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, 2010 Apple Inc. All rights reserved. 7 # Copyright (C) 2009 Cameron McCormack <cam (at] mcc.id.au> 8 # Copyright (C) Research In Motion Limited 2010. All rights reserved. 9 # Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) 10 # 11 # This library is free software; you can redistribute it and/or 12 # modify it under the terms of the GNU Library General Public 13 # License as published by the Free Software Foundation; either 14 # version 2 of the License, or (at your option) any later version. 15 # 16 # This library is distributed in the hope that it will be useful, 17 # but WITHOUT ANY WARRANTY; without even the implied warranty of 18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 # Library General Public License for more details. 20 # 21 # You should have received a copy of the GNU Library General Public License 22 # along with this library; see the file COPYING.LIB. If not, write to 23 # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 24 # Boston, MA 02110-1301, USA. 25 26 package CodeGeneratorJS; 27 28 my $module = ""; 29 my $outputDir = ""; 30 my $writeDependencies = 0; 31 32 my @headerContentHeader = (); 33 my @headerContent = (); 34 my %headerIncludes = (); 35 my %headerTrailingIncludes = (); 36 37 my @implContentHeader = (); 38 my @implContent = (); 39 my %implIncludes = (); 40 my @depsContent = (); 41 my $numCachedAttributes = 0; 42 my $currentCachedAttribute = 0; 43 44 # Default .h template 45 my $headerTemplate = << "EOF"; 46 /* 47 This file is part of the WebKit open source project. 48 This file has been generated by generate-bindings.pl. DO NOT MODIFY! 49 50 This library is free software; you can redistribute it and/or 51 modify it under the terms of the GNU Library General Public 52 License as published by the Free Software Foundation; either 53 version 2 of the License, or (at your option) any later version. 54 55 This library is distributed in the hope that it will be useful, 56 but WITHOUT ANY WARRANTY; without even the implied warranty of 57 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 58 Library General Public License for more details. 59 60 You should have received a copy of the GNU Library General Public License 61 along with this library; see the file COPYING.LIB. If not, write to 62 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 63 Boston, MA 02110-1301, USA. 64 */ 65 EOF 66 67 # Default constructor 68 sub new 69 { 70 my $object = shift; 71 my $reference = { }; 72 73 $codeGenerator = shift; 74 $outputDir = shift; 75 shift; # $outputHeadersDir 76 shift; # $useLayerOnTop 77 shift; # $preprocessor 78 $writeDependencies = shift; 79 80 bless($reference, $object); 81 return $reference; 82 } 83 84 sub finish 85 { 86 my $object = shift; 87 88 # Commit changes! 89 $object->WriteData(); 90 } 91 92 sub leftShift($$) { 93 my ($value, $distance) = @_; 94 return (($value << $distance) & 0xFFFFFFFF); 95 } 96 97 # Params: 'domClass' struct 98 sub GenerateInterface 99 { 100 my $object = shift; 101 my $dataNode = shift; 102 my $defines = shift; 103 104 $codeGenerator->LinkOverloadedFunctions($dataNode); 105 106 # Start actual generation 107 if ($dataNode->extendedAttributes->{"Callback"}) { 108 $object->GenerateCallbackHeader($dataNode); 109 $object->GenerateCallbackImplementation($dataNode); 110 } else { 111 $object->GenerateHeader($dataNode); 112 $object->GenerateImplementation($dataNode); 113 } 114 115 my $name = $dataNode->name; 116 117 # Open files for writing 118 my $headerFileName = "$outputDir/JS$name.h"; 119 my $implFileName = "$outputDir/JS$name.cpp"; 120 my $depsFileName = "$outputDir/JS$name.dep"; 121 122 # Remove old dependency file. 123 unlink($depsFileName); 124 125 open($IMPL, ">$implFileName") || die "Couldn't open file $implFileName"; 126 open($HEADER, ">$headerFileName") || die "Couldn't open file $headerFileName"; 127 if (@depsContent) { 128 open($DEPS, ">$depsFileName") || die "Couldn't open file $depsFileName"; 129 } 130 } 131 132 sub GenerateAttributeEventListenerCall 133 { 134 my $className = shift; 135 my $implSetterFunctionName = shift; 136 my $windowEventListener = shift; 137 138 my $wrapperObject = $windowEventListener ? "globalObject" : "thisObject"; 139 my @GenerateEventListenerImpl = (); 140 141 if ($className eq "JSSVGElementInstance") { 142 # SVGElementInstances have to create JSEventListeners with the wrapper equal to the correspondingElement 143 $wrapperObject = "asObject(correspondingElementWrapper)"; 144 145 push(@GenerateEventListenerImpl, <<END); 146 JSValue correspondingElementWrapper = toJS(exec, imp->correspondingElement()); 147 if (correspondingElementWrapper.isObject()) 148 END 149 150 # Add leading whitespace to format the imp->set... line correctly 151 push(@GenerateEventListenerImpl, " "); 152 } 153 154 push(@GenerateEventListenerImpl, " imp->set$implSetterFunctionName(createJSAttributeEventListener(exec, value, $wrapperObject));\n"); 155 return @GenerateEventListenerImpl; 156 } 157 158 sub GenerateEventListenerCall 159 { 160 my $className = shift; 161 my $functionName = shift; 162 my $passRefPtrHandling = ($functionName eq "add") ? "" : ".get()"; 163 164 $implIncludes{"JSEventListener.h"} = 1; 165 166 my @GenerateEventListenerImpl = (); 167 my $wrapperObject = "castedThis"; 168 if ($className eq "JSSVGElementInstance") { 169 # SVGElementInstances have to create JSEventListeners with the wrapper equal to the correspondingElement 170 $wrapperObject = "asObject(correspondingElementWrapper)"; 171 172 push(@GenerateEventListenerImpl, <<END); 173 JSValue correspondingElementWrapper = toJS(exec, imp->correspondingElement()); 174 if (!correspondingElementWrapper.isObject()) 175 return JSValue::encode(jsUndefined()); 176 END 177 } 178 179 push(@GenerateEventListenerImpl, <<END); 180 JSValue listener = exec->argument(1); 181 if (!listener.isObject()) 182 return JSValue::encode(jsUndefined()); 183 imp->${functionName}EventListener(ustringToAtomicString(exec->argument(0).toString(exec)), JSEventListener::create(asObject(listener), $wrapperObject, false, currentWorld(exec))$passRefPtrHandling, exec->argument(2).toBoolean(exec)); 184 return JSValue::encode(jsUndefined()); 185 END 186 return @GenerateEventListenerImpl; 187 } 188 189 # Params: 'idlDocument' struct 190 sub GenerateModule 191 { 192 my $object = shift; 193 my $dataNode = shift; 194 195 $module = $dataNode->module; 196 } 197 198 sub GetParentClassName 199 { 200 my $dataNode = shift; 201 202 return $dataNode->extendedAttributes->{"LegacyParent"} if $dataNode->extendedAttributes->{"LegacyParent"}; 203 return "JSDOMWrapperWithGlobalPointer" if (@{$dataNode->parents} eq 0); 204 return "JS" . $codeGenerator->StripModule($dataNode->parents(0)); 205 } 206 207 sub GetVisibleClassName 208 { 209 my $className = shift; 210 211 return "DOMException" if $className eq "DOMCoreException"; 212 return "FormData" if $className eq "DOMFormData"; 213 return "MimeType" if $className eq "DOMMimeType"; 214 return "MimeTypeArray" if $className eq "DOMMimeTypeArray"; 215 return "Plugin" if $className eq "DOMPlugin"; 216 return "PluginArray" if $className eq "DOMPluginArray"; 217 218 return $className; 219 } 220 221 sub GetCallbackClassName 222 { 223 my $className = shift; 224 225 return "JSCustomVoidCallback" if $className eq "VoidCallback"; 226 return "JS$className"; 227 } 228 229 sub IndexGetterReturnsStrings 230 { 231 my $type = shift; 232 233 return 1 if $type eq "CSSStyleDeclaration" or $type eq "MediaList" or $type eq "DOMStringList" or $type eq "DOMTokenList" or $type eq "DOMSettableTokenList"; 234 return 0; 235 } 236 237 sub AddIncludesForType 238 { 239 my $type = $codeGenerator->StripModule(shift); 240 my $isCallback = @_ ? shift : 0; 241 242 # When we're finished with the one-file-per-class 243 # reorganization, we won't need these special cases. 244 if ($codeGenerator->IsPrimitiveType($type) or $codeGenerator->AvoidInclusionOfType($type) 245 or $type eq "DOMString" or $type eq "DOMObject" or $type eq "Array") { 246 } elsif ($type =~ /SVGPathSeg/) { 247 $joinedName = $type; 248 $joinedName =~ s/Abs|Rel//; 249 $implIncludes{"${joinedName}.h"} = 1; 250 } elsif ($type eq "XPathNSResolver") { 251 $implIncludes{"JSXPathNSResolver.h"} = 1; 252 $implIncludes{"JSCustomXPathNSResolver.h"} = 1; 253 } elsif ($isCallback) { 254 $implIncludes{"JS${type}.h"} = 1; 255 } else { 256 # default, include the same named file 257 $implIncludes{"${type}.h"} = 1; 258 } 259 260 # additional includes (things needed to compile the bindings but not the header) 261 262 if ($type eq "CanvasRenderingContext2D") { 263 $implIncludes{"CanvasGradient.h"} = 1; 264 $implIncludes{"CanvasPattern.h"} = 1; 265 $implIncludes{"CanvasStyle.h"} = 1; 266 } 267 268 if ($type eq "CanvasGradient" or $type eq "XPathNSResolver" or $type eq "MessagePort") { 269 $implIncludes{"PlatformString.h"} = 1; 270 } 271 272 if ($type eq "Document") { 273 $implIncludes{"NodeFilter.h"} = 1; 274 } 275 276 if ($type eq "MediaQueryListListener") { 277 $implIncludes{"MediaQueryListListener.h"} = 1; 278 } 279 } 280 281 # FIXME: This method will go away once all SVG animated properties are converted to the new scheme. 282 sub AddIncludesForSVGAnimatedType 283 { 284 my $type = shift; 285 $type =~ s/SVGAnimated//; 286 287 if ($type eq "Point" or $type eq "Rect") { 288 $implIncludes{"Float$type.h"} = 1; 289 } elsif ($type eq "String") { 290 $implIncludes{"PlatformString.h"} = 1; 291 } 292 } 293 294 sub IsScriptProfileType 295 { 296 my $type = shift; 297 return 1 if ($type eq "ScriptProfileNode"); 298 return 0; 299 } 300 301 sub AddTypedefForScriptProfileType 302 { 303 my $type = shift; 304 (my $jscType = $type) =~ s/Script//; 305 306 push(@headerContent, "typedef JSC::$jscType $type;\n\n"); 307 } 308 309 sub AddClassForwardIfNeeded 310 { 311 my $implClassName = shift; 312 313 # SVGAnimatedLength/Number/etc. are typedefs to SVGAnimatedTemplate, so don't use class forwards for them! 314 unless ($codeGenerator->IsSVGAnimatedType($implClassName) or IsScriptProfileType($implClassName)) { 315 push(@headerContent, "class $implClassName;\n\n"); 316 # ScriptProfile and ScriptProfileNode are typedefs to JSC::Profile and JSC::ProfileNode. 317 } elsif (IsScriptProfileType($implClassName)) { 318 AddTypedefForScriptProfileType($implClassName); 319 } 320 } 321 322 sub HashValueForClassAndName 323 { 324 my $class = shift; 325 my $name = shift; 326 327 # SVG Filter enums live in WebCore namespace (platform/graphics/) 328 if ($class =~ /^SVGFE*/ or $class =~ /^SVGComponentTransferFunctionElement$/) { 329 return "WebCore::$name"; 330 } 331 332 return "${class}::$name"; 333 } 334 335 sub hashTableAccessor 336 { 337 my $noStaticTables = shift; 338 my $className = shift; 339 if ($noStaticTables) { 340 return "get${className}Table(exec)"; 341 } else { 342 return "&${className}Table"; 343 } 344 } 345 346 sub prototypeHashTableAccessor 347 { 348 my $noStaticTables = shift; 349 my $className = shift; 350 if ($noStaticTables) { 351 return "get${className}PrototypeTable(exec)"; 352 } else { 353 return "&${className}PrototypeTable"; 354 } 355 } 356 357 sub GenerateConditionalStringFromAttributeValue 358 { 359 my $conditional = shift; 360 if ($conditional =~ /&/) { 361 return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; 362 } elsif ($conditional =~ /\|/) { 363 return "ENABLE(" . join(") || ENABLE(", split(/\|/, $conditional)) . ")"; 364 } else { 365 return "ENABLE(" . $conditional . ")"; 366 } 367 } 368 369 sub GenerateConditionalString 370 { 371 my $node = shift; 372 my $conditional = $node->extendedAttributes->{"Conditional"}; 373 if ($conditional) { 374 return GenerateConditionalStringFromAttributeValue($conditional); 375 } else { 376 return ""; 377 } 378 } 379 380 sub GenerateGetOwnPropertySlotBody 381 { 382 my ($dataNode, $interfaceName, $className, $implClassName, $hasAttributes, $inlined) = @_; 383 384 my $namespaceMaybe = ($inlined ? "JSC::" : ""); 385 386 my @getOwnPropertySlotImpl = (); 387 388 if ($interfaceName eq "NamedNodeMap" or $interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") { 389 push(@getOwnPropertySlotImpl, " ${namespaceMaybe}JSValue proto = prototype();\n"); 390 push(@getOwnPropertySlotImpl, " if (proto.isObject() && static_cast<${namespaceMaybe}JSObject*>(asObject(proto))->hasProperty(exec, propertyName))\n"); 391 push(@getOwnPropertySlotImpl, " return false;\n\n"); 392 } 393 394 my $manualLookupGetterGeneration = sub { 395 my $requiresManualLookup = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasNameGetter"}; 396 if ($requiresManualLookup) { 397 push(@getOwnPropertySlotImpl, " const ${namespaceMaybe}HashEntry* entry = ${className}Table.entry(exec, propertyName);\n"); 398 push(@getOwnPropertySlotImpl, " if (entry) {\n"); 399 push(@getOwnPropertySlotImpl, " slot.setCustom(this, entry->propertyGetter());\n"); 400 push(@getOwnPropertySlotImpl, " return true;\n"); 401 push(@getOwnPropertySlotImpl, " }\n"); 402 } 403 }; 404 405 if (!$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) { 406 &$manualLookupGetterGeneration(); 407 } 408 409 if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) { 410 push(@getOwnPropertySlotImpl, " bool ok;\n"); 411 push(@getOwnPropertySlotImpl, " unsigned index = propertyName.toUInt32(ok);\n"); 412 413 # If the item function returns a string then we let the ConvertNullStringTo handle the cases 414 # where the index is out of range. 415 if (IndexGetterReturnsStrings($implClassName)) { 416 push(@getOwnPropertySlotImpl, " if (ok) {\n"); 417 } else { 418 push(@getOwnPropertySlotImpl, " if (ok && index < static_cast<$implClassName*>(impl())->length()) {\n"); 419 } 420 if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) { 421 push(@getOwnPropertySlotImpl, " slot.setValue(getByIndex(exec, index));\n"); 422 } else { 423 push(@getOwnPropertySlotImpl, " slot.setCustomIndex(this, index, indexGetter);\n"); 424 } 425 push(@getOwnPropertySlotImpl, " return true;\n"); 426 push(@getOwnPropertySlotImpl, " }\n"); 427 } 428 429 if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) { 430 push(@getOwnPropertySlotImpl, " if (canGetItemsForName(exec, static_cast<$implClassName*>(impl()), propertyName)) {\n"); 431 push(@getOwnPropertySlotImpl, " slot.setCustom(this, nameGetter);\n"); 432 push(@getOwnPropertySlotImpl, " return true;\n"); 433 push(@getOwnPropertySlotImpl, " }\n"); 434 if ($inlined) { 435 $headerIncludes{"wtf/text/AtomicString.h"} = 1; 436 } else { 437 $implIncludes{"wtf/text/AtomicString.h"} = 1; 438 } 439 } 440 441 if ($dataNode->extendedAttributes->{"HasOverridingNameGetter"}) { 442 &$manualLookupGetterGeneration(); 443 } 444 445 if ($dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}) { 446 push(@getOwnPropertySlotImpl, " if (getOwnPropertySlotDelegate(exec, propertyName, slot))\n"); 447 push(@getOwnPropertySlotImpl, " return true;\n"); 448 } 449 450 if ($hasAttributes) { 451 if ($inlined) { 452 die "Cannot inline if NoStaticTables is set." if ($dataNode->extendedAttributes->{"NoStaticTables"}); 453 push(@getOwnPropertySlotImpl, " return ${namespaceMaybe}getStaticValueSlot<$className, Base>(exec, s_info.staticPropHashTable, this, propertyName, slot);\n"); 454 } else { 455 push(@getOwnPropertySlotImpl, " return ${namespaceMaybe}getStaticValueSlot<$className, Base>(exec, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n"); 456 } 457 } else { 458 push(@getOwnPropertySlotImpl, " return Base::getOwnPropertySlot(exec, propertyName, slot);\n"); 459 } 460 461 return @getOwnPropertySlotImpl; 462 } 463 464 sub GenerateGetOwnPropertyDescriptorBody 465 { 466 my ($dataNode, $interfaceName, $className, $implClassName, $hasAttributes, $inlined) = @_; 467 468 my $namespaceMaybe = ($inlined ? "JSC::" : ""); 469 470 my @getOwnPropertyDescriptorImpl = (); 471 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) { 472 if ($interfaceName eq "DOMWindow") { 473 push(@implContent, " if (!static_cast<$className*>(thisObject)->allowsAccessFrom(exec))\n"); 474 } else { 475 push(@implContent, " if (!allowsAccessFromFrame(exec, static_cast<$className*>(thisObject)->impl()->frame()))\n"); 476 } 477 push(@implContent, " return false;\n"); 478 } 479 480 if ($interfaceName eq "NamedNodeMap" or $interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") { 481 push(@getOwnPropertyDescriptorImpl, " ${namespaceMaybe}JSValue proto = prototype();\n"); 482 push(@getOwnPropertyDescriptorImpl, " if (proto.isObject() && static_cast<${namespaceMaybe}JSObject*>(asObject(proto))->hasProperty(exec, propertyName))\n"); 483 push(@getOwnPropertyDescriptorImpl, " return false;\n\n"); 484 } 485 486 my $manualLookupGetterGeneration = sub { 487 my $requiresManualLookup = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasNameGetter"}; 488 if ($requiresManualLookup) { 489 push(@getOwnPropertyDescriptorImpl, " const ${namespaceMaybe}HashEntry* entry = ${className}Table.entry(exec, propertyName);\n"); 490 push(@getOwnPropertyDescriptorImpl, " if (entry) {\n"); 491 push(@getOwnPropertyDescriptorImpl, " PropertySlot slot;\n"); 492 push(@getOwnPropertyDescriptorImpl, " slot.setCustom(this, entry->propertyGetter());\n"); 493 push(@getOwnPropertyDescriptorImpl, " descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());\n"); 494 push(@getOwnPropertyDescriptorImpl, " return true;\n"); 495 push(@getOwnPropertyDescriptorImpl, " }\n"); 496 } 497 }; 498 499 if (!$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) { 500 &$manualLookupGetterGeneration(); 501 } 502 503 if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) { 504 push(@getOwnPropertyDescriptorImpl, " bool ok;\n"); 505 push(@getOwnPropertyDescriptorImpl, " unsigned index = propertyName.toUInt32(ok);\n"); 506 push(@getOwnPropertyDescriptorImpl, " if (ok && index < static_cast<$implClassName*>(impl())->length()) {\n"); 507 if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) { 508 # Assume that if there's a setter, the index will be writable 509 if ($dataNode->extendedAttributes->{"HasIndexSetter"} || $dataNode->extendedAttributes->{"HasCustomIndexSetter"}) { 510 push(@getOwnPropertyDescriptorImpl, " descriptor.setDescriptor(getByIndex(exec, index), ${namespaceMaybe}DontDelete);\n"); 511 } else { 512 push(@getOwnPropertyDescriptorImpl, " descriptor.setDescriptor(getByIndex(exec, index), ${namespaceMaybe}DontDelete | ${namespaceMaybe}ReadOnly);\n"); 513 } 514 } else { 515 push(@getOwnPropertyDescriptorImpl, " ${namespaceMaybe}PropertySlot slot;\n"); 516 push(@getOwnPropertyDescriptorImpl, " slot.setCustomIndex(this, index, indexGetter);\n"); 517 # Assume that if there's a setter, the index will be writable 518 if ($dataNode->extendedAttributes->{"HasIndexSetter"} || $dataNode->extendedAttributes->{"HasCustomIndexSetter"}) { 519 push(@getOwnPropertyDescriptorImpl, " descriptor.setDescriptor(slot.getValue(exec, propertyName), ${namespaceMaybe}DontDelete);\n"); 520 } else { 521 push(@getOwnPropertyDescriptorImpl, " descriptor.setDescriptor(slot.getValue(exec, propertyName), ${namespaceMaybe}DontDelete | ${namespaceMaybe}ReadOnly);\n"); 522 } 523 } 524 push(@getOwnPropertyDescriptorImpl, " return true;\n"); 525 push(@getOwnPropertyDescriptorImpl, " }\n"); 526 } 527 528 if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) { 529 push(@getOwnPropertyDescriptorImpl, " if (canGetItemsForName(exec, static_cast<$implClassName*>(impl()), propertyName)) {\n"); 530 push(@getOwnPropertyDescriptorImpl, " ${namespaceMaybe}PropertySlot slot;\n"); 531 push(@getOwnPropertyDescriptorImpl, " slot.setCustom(this, nameGetter);\n"); 532 push(@getOwnPropertyDescriptorImpl, " descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);\n"); 533 push(@getOwnPropertyDescriptorImpl, " return true;\n"); 534 push(@getOwnPropertyDescriptorImpl, " }\n"); 535 if ($inlined) { 536 $headerIncludes{"wtf/text/AtomicString.h"} = 1; 537 } else { 538 $implIncludes{"wtf/text/AtomicString.h"} = 1; 539 } 540 } 541 542 if ($dataNode->extendedAttributes->{"HasOverridingNameGetter"}) { 543 &$manualLookupGetterGeneration(); 544 } 545 546 if ($dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}) { 547 push(@getOwnPropertyDescriptorImpl, " if (getOwnPropertyDescriptorDelegate(exec, propertyName, descriptor))\n"); 548 push(@getOwnPropertyDescriptorImpl, " return true;\n"); 549 } 550 551 if ($hasAttributes) { 552 if ($inlined) { 553 die "Cannot inline if NoStaticTables is set." if ($dataNode->extendedAttributes->{"NoStaticTables"}); 554 push(@getOwnPropertyDescriptorImpl, " return ${namespaceMaybe}getStaticValueDescriptor<$className, Base>(exec, s_info.staticPropHashTable, this, propertyName, descriptor);\n"); 555 } else { 556 push(@getOwnPropertyDescriptorImpl, " return ${namespaceMaybe}getStaticValueDescriptor<$className, Base>(exec, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n"); 557 } 558 } else { 559 push(@getOwnPropertyDescriptorImpl, " return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);\n"); 560 } 561 562 return @getOwnPropertyDescriptorImpl; 563 } 564 565 sub GenerateHeaderContentHeader 566 { 567 my $dataNode = shift; 568 my $className = "JS" . $dataNode->name; 569 570 my @headerContentHeader = split("\r", $headerTemplate); 571 572 # - Add header protection 573 push(@headerContentHeader, "\n#ifndef $className" . "_h"); 574 push(@headerContentHeader, "\n#define $className" . "_h\n\n"); 575 576 my $conditionalString = GenerateConditionalString($dataNode); 577 push(@headerContentHeader, "#if ${conditionalString}\n\n") if $conditionalString; 578 return @headerContentHeader; 579 } 580 581 sub GenerateImplementationContentHeader 582 { 583 my $dataNode = shift; 584 my $className = "JS" . $dataNode->name; 585 586 my @implContentHeader = split("\r", $headerTemplate); 587 588 push(@implContentHeader, "\n#include \"config.h\"\n"); 589 my $conditionalString = GenerateConditionalString($dataNode); 590 push(@implContentHeader, "\n#if ${conditionalString}\n\n") if $conditionalString; 591 push(@implContentHeader, "#include \"$className.h\"\n\n"); 592 return @implContentHeader; 593 } 594 595 my %usesToJSNewlyCreated = ( 596 "CDATASection" => 1, 597 "Element" => 1, 598 "Node" => 1, 599 "Text" => 1, 600 "Touch" => 1, 601 "TouchList" => 1 602 ); 603 604 sub GenerateHeader 605 { 606 my $object = shift; 607 my $dataNode = shift; 608 609 my $interfaceName = $dataNode->name; 610 my $className = "JS$interfaceName"; 611 my $implClassName = $interfaceName; 612 my @ancestorInterfaceNames = (); 613 my %structureFlags = (); 614 615 # We only support multiple parents with SVG (for now). 616 if (@{$dataNode->parents} > 1) { 617 die "A class can't have more than one parent" unless $interfaceName =~ /SVG/; 618 $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@ancestorInterfaceNames); 619 } 620 621 my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"}; 622 my $hasRealParent = @{$dataNode->parents} > 0; 623 my $hasParent = $hasLegacyParent || $hasRealParent; 624 my $parentClassName = GetParentClassName($dataNode); 625 my $eventTarget = $dataNode->extendedAttributes->{"EventTarget"}; 626 my $needsMarkChildren = $dataNode->extendedAttributes->{"CustomMarkFunction"} || $dataNode->extendedAttributes->{"EventTarget"}; 627 628 # - Add default header template and header protection 629 push(@headerContentHeader, GenerateHeaderContentHeader($dataNode)); 630 631 if ($hasParent) { 632 $headerIncludes{"$parentClassName.h"} = 1; 633 } else { 634 $headerIncludes{"JSDOMBinding.h"} = 1; 635 $headerIncludes{"<runtime/JSGlobalObject.h>"} = 1; 636 $headerIncludes{"<runtime/ObjectPrototype.h>"} = 1; 637 } 638 639 if ($dataNode->extendedAttributes->{"CustomCall"}) { 640 $headerIncludes{"<runtime/CallData.h>"} = 1; 641 } 642 643 if ($dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"}) { 644 $headerIncludes{"<runtime/Lookup.h>"} = 1; 645 $headerIncludes{"<wtf/AlwaysInline.h>"} = 1; 646 } 647 648 if ($hasParent && $dataNode->extendedAttributes->{"GenerateNativeConverter"}) { 649 $headerIncludes{"$implClassName.h"} = 1; 650 } 651 652 $headerIncludes{"<runtime/JSObjectWithGlobalObject.h>"} = 1; 653 $headerIncludes{"SVGElement.h"} = 1 if $className =~ /^JSSVG/; 654 655 my $implType = $implClassName; 656 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implType); 657 $implType = $svgNativeType if $svgNativeType; 658 659 my $svgPropertyOrListPropertyType; 660 $svgPropertyOrListPropertyType = $svgPropertyType if $svgPropertyType; 661 $svgPropertyOrListPropertyType = $svgListPropertyType if $svgListPropertyType; 662 663 my $numConstants = @{$dataNode->constants}; 664 my $numAttributes = @{$dataNode->attributes}; 665 my $numFunctions = @{$dataNode->functions}; 666 667 push(@headerContent, "\nnamespace WebCore {\n\n"); 668 669 if ($codeGenerator->IsSVGAnimatedType($implClassName)) { 670 $headerIncludes{"$implClassName.h"} = 1; 671 } else { 672 # Implementation class forward declaration 673 AddClassForwardIfNeeded($implClassName) unless $svgPropertyOrListPropertyType; 674 } 675 676 AddClassForwardIfNeeded("JSDOMWindowShell") if $interfaceName eq "DOMWindow"; 677 678 # Class declaration 679 push(@headerContent, "class $className : public $parentClassName {\n"); 680 push(@headerContent, " typedef $parentClassName Base;\n"); 681 push(@headerContent, "public:\n"); 682 683 # Constructor 684 if ($interfaceName eq "DOMWindow") { 685 push(@headerContent, " $className(JSC::JSGlobalData&, JSC::Structure*, PassRefPtr<$implType>, JSDOMWindowShell*);\n"); 686 } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) { 687 push(@headerContent, " $className(JSC::JSGlobalData&, JSC::Structure*, PassRefPtr<$implType>);\n"); 688 } else { 689 push(@headerContent, " $className(JSC::Structure*, JSDOMGlobalObject*, PassRefPtr<$implType>);\n"); 690 } 691 692 # Prototype 693 push(@headerContent, " static JSC::JSObject* createPrototype(JSC::ExecState*, JSC::JSGlobalObject*);\n") unless ($dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"}); 694 695 $headerTrailingIncludes{"${className}Custom.h"} = 1 if $dataNode->extendedAttributes->{"CustomHeader"}; 696 697 $implIncludes{"${className}Custom.h"} = 1 if !$dataNode->extendedAttributes->{"CustomHeader"} && ($dataNode->extendedAttributes->{"CustomPutFunction"} || $dataNode->extendedAttributes->{"DelegatingPutFunction"}); 698 699 my $hasGetter = $numAttributes > 0 700 || !($dataNode->extendedAttributes->{"OmitConstructor"} 701 || $dataNode->extendedAttributes->{"CustomConstructor"}) 702 || $dataNode->extendedAttributes->{"HasIndexGetter"} 703 || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} 704 || $dataNode->extendedAttributes->{"HasNumericIndexGetter"} 705 || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"} 706 || $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"} 707 || $dataNode->extendedAttributes->{"HasNameGetter"} 708 || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}; 709 710 # Getters 711 if ($hasGetter) { 712 push(@headerContent, " virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);\n"); 713 push(@headerContent, " virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&);\n"); 714 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"}; 715 push(@headerContent, " bool getOwnPropertySlotDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}; 716 push(@headerContent, " bool getOwnPropertyDescriptorDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n") if $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}; 717 $structureFlags{"JSC::OverridesGetOwnPropertySlot"} = 1; 718 } 719 720 # Check if we have any writable properties 721 my $hasReadWriteProperties = 0; 722 foreach (@{$dataNode->attributes}) { 723 if ($_->type !~ /^readonly\ attribute$/) { 724 $hasReadWriteProperties = 1; 725 } 726 } 727 728 my $hasSetter = $hasReadWriteProperties 729 || $dataNode->extendedAttributes->{"CustomPutFunction"} 730 || $dataNode->extendedAttributes->{"DelegatingPutFunction"} 731 || $dataNode->extendedAttributes->{"HasCustomIndexSetter"}; 732 733 # Getters 734 if ($hasSetter) { 735 push(@headerContent, " virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);\n"); 736 push(@headerContent, " virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValue);\n") if $dataNode->extendedAttributes->{"HasCustomIndexSetter"}; 737 push(@headerContent, " bool putDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, JSC::PutPropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingPutFunction"}; 738 } 739 740 # Class info 741 push(@headerContent, " static const JSC::ClassInfo s_info;\n\n"); 742 743 # Structure ID 744 if ($interfaceName eq "DOMWindow") { 745 $structureFlags{"JSC::ImplementsHasInstance"} = 1; 746 $structureFlags{"JSC::NeedsThisConversion"} = 1; 747 } 748 push(@headerContent, 749 " static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)\n" . 750 " {\n" . 751 " return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);\n" . 752 " }\n\n"); 753 754 # markChildren function 755 if ($needsMarkChildren) { 756 push(@headerContent, " virtual void markChildren(JSC::MarkStack&);\n\n"); 757 $structureFlags{"JSC::OverridesMarkChildren"} = 1; 758 } 759 760 # Custom pushEventHandlerScope function 761 push(@headerContent, " virtual JSC::ScopeChainNode* pushEventHandlerScope(JSC::ExecState*, JSC::ScopeChainNode*) const;\n\n") if $dataNode->extendedAttributes->{"CustomPushEventHandlerScope"}; 762 763 # Custom call functions 764 push(@headerContent, " virtual JSC::CallType getCallData(JSC::CallData&);\n\n") if $dataNode->extendedAttributes->{"CustomCall"}; 765 766 # Custom deleteProperty function 767 push(@headerContent, " virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&);\n") if $dataNode->extendedAttributes->{"CustomDeleteProperty"}; 768 769 # Custom getPropertyNames function exists on DOMWindow 770 if ($interfaceName eq "DOMWindow") { 771 push(@headerContent, " virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n"); 772 $structureFlags{"JSC::OverridesGetPropertyNames"} = 1; 773 } 774 775 # Custom defineProperty function exists on DOMWindow 776 push(@headerContent, " virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&, bool shouldThrow);\n") if $interfaceName eq "DOMWindow"; 777 778 # Custom getOwnPropertyNames function 779 if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"} || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) { 780 push(@headerContent, " virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n"); 781 $structureFlags{"JSC::OverridesGetPropertyNames"} = 1; 782 } 783 784 # Custom defineGetter function 785 push(@headerContent, " virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomDefineGetter"}; 786 787 # Custom defineSetter function 788 push(@headerContent, " virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomDefineSetter"}; 789 790 # Custom lookupGetter function 791 push(@headerContent, " virtual JSC::JSValue lookupGetter(JSC::ExecState*, const JSC::Identifier& propertyName);\n") if $dataNode->extendedAttributes->{"CustomLookupGetter"}; 792 793 # Custom lookupSetter function 794 push(@headerContent, " virtual JSC::JSValue lookupSetter(JSC::ExecState*, const JSC::Identifier& propertyName);\n") if $dataNode->extendedAttributes->{"CustomLookupSetter"}; 795 796 # Override toBoolean to return false for objects that want to 'MasqueradesAsUndefined'. 797 if ($dataNode->extendedAttributes->{"MasqueradesAsUndefined"}) { 798 push(@headerContent, " virtual bool toBoolean(JSC::ExecState*) const { return false; };\n"); 799 $structureFlags{"JSC::MasqueradesAsUndefined"} = 1; 800 } 801 802 # Constructor object getter 803 push(@headerContent, " static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*);\n") if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})); 804 805 my $numCustomFunctions = 0; 806 my $numCustomAttributes = 0; 807 808 # Attribute and function enums 809 if ($numAttributes > 0) { 810 foreach (@{$dataNode->attributes}) { 811 my $attribute = $_; 812 $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"}; 813 $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"CustomGetter"} || $attribute->signature->extendedAttributes->{"JSCCustomGetter"}; 814 $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"CustomSetter"} || $attribute->signature->extendedAttributes->{"JSCCustomSetter"}; 815 if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) { 816 push(@headerContent, " static const unsigned " . $attribute->signature->name . "Slot = $numCachedAttributes + Base::AnonymousSlotCount;\n"); 817 $numCachedAttributes++; 818 } 819 } 820 } 821 822 if ($numCachedAttributes > 0) { 823 push(@headerContent, " using $parentClassName" . "::putAnonymousValue;\n"); 824 push(@headerContent, " using $parentClassName" . "::getAnonymousValue;\n"); 825 } 826 if ($numCustomAttributes > 0) { 827 push(@headerContent, "\n // Custom attributes\n"); 828 829 foreach my $attribute (@{$dataNode->attributes}) { 830 if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"}) { 831 push(@headerContent, " JSC::JSValue " . $codeGenerator->WK_lcfirst($attribute->signature->name) . "(JSC::ExecState*) const;\n"); 832 if ($attribute->type !~ /^readonly/) { 833 push(@headerContent, " void set" . $codeGenerator->WK_ucfirst($attribute->signature->name) . "(JSC::ExecState*, JSC::JSValue);\n"); 834 } 835 } elsif ($attribute->signature->extendedAttributes->{"CustomGetter"} || $attribute->signature->extendedAttributes->{"JSCCustomGetter"}) { 836 push(@headerContent, " JSC::JSValue " . $codeGenerator->WK_lcfirst($attribute->signature->name) . "(JSC::ExecState*) const;\n"); 837 } elsif ($attribute->signature->extendedAttributes->{"CustomSetter"} || $attribute->signature->extendedAttributes->{"JSCCustomSetter"}) { 838 if ($attribute->type !~ /^readonly/) { 839 push(@headerContent, " void set" . $codeGenerator->WK_ucfirst($attribute->signature->name) . "(JSC::ExecState*, JSC::JSValue);\n"); 840 } 841 } 842 } 843 } 844 845 foreach my $function (@{$dataNode->functions}) { 846 $numCustomFunctions++ if $function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"JSCCustom"}; 847 } 848 849 if ($numCustomFunctions > 0) { 850 push(@headerContent, "\n // Custom functions\n"); 851 foreach my $function (@{$dataNode->functions}) { 852 if ($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"JSCCustom"}) { 853 my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementationFunction"} || $codeGenerator->WK_lcfirst($function->signature->name); 854 push(@headerContent, " JSC::JSValue " . $functionImplementationName . "(JSC::ExecState*);\n"); 855 } 856 } 857 } 858 859 if (!$hasParent) { 860 push(@headerContent, " $implType* impl() const { return m_impl.get(); }\n\n"); 861 push(@headerContent, "private:\n"); 862 push(@headerContent, " RefPtr<$implType> m_impl;\n"); 863 } elsif ($dataNode->extendedAttributes->{"GenerateNativeConverter"}) { 864 push(@headerContent, " $implClassName* impl() const\n"); 865 push(@headerContent, " {\n"); 866 push(@headerContent, " return static_cast<$implClassName*>(Base::impl());\n"); 867 push(@headerContent, " }\n"); 868 } 869 870 # anonymous slots 871 if ($numCachedAttributes) { 872 push(@headerContent, "public:\n"); 873 push(@headerContent, " static const unsigned AnonymousSlotCount = $numCachedAttributes + Base::AnonymousSlotCount;\n"); 874 } 875 876 # structure flags 877 push(@headerContent, "protected:\n"); 878 push(@headerContent, " static const unsigned StructureFlags = "); 879 foreach my $structureFlag (keys %structureFlags) { 880 push(@headerContent, $structureFlag . " | "); 881 } 882 push(@headerContent, "Base::StructureFlags;\n"); 883 884 # Index getter 885 if ($dataNode->extendedAttributes->{"HasIndexGetter"}) { 886 push(@headerContent, " static JSC::JSValue indexGetter(JSC::ExecState*, JSC::JSValue, unsigned);\n"); 887 } 888 if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) { 889 push(@headerContent, " JSC::JSValue getByIndex(JSC::ExecState*, unsigned index);\n"); 890 891 } 892 893 # Index setter 894 if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) { 895 push(@headerContent, " void indexSetter(JSC::ExecState*, unsigned index, JSC::JSValue);\n"); 896 } 897 # Name getter 898 if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) { 899 push(@headerContent, "private:\n"); 900 push(@headerContent, " static bool canGetItemsForName(JSC::ExecState*, $implClassName*, const JSC::Identifier&);\n"); 901 push(@headerContent, " static JSC::JSValue nameGetter(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&);\n"); 902 } 903 904 push(@headerContent, "};\n\n"); 905 906 if ($dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"} && !$dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}) { 907 push(@headerContent, "ALWAYS_INLINE bool ${className}::getOwnPropertySlot(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertySlot& slot)\n"); 908 push(@headerContent, "{\n"); 909 push(@headerContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 1)); 910 push(@headerContent, "}\n\n"); 911 push(@headerContent, "ALWAYS_INLINE bool ${className}::getOwnPropertyDescriptor(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertyDescriptor& descriptor)\n"); 912 push(@headerContent, "{\n"); 913 push(@headerContent, GenerateGetOwnPropertyDescriptorBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 1)); 914 push(@headerContent, "}\n\n"); 915 } 916 917 if (!$hasParent || $dataNode->extendedAttributes->{"GenerateToJS"} || $dataNode->extendedAttributes->{"CustomToJS"}) { 918 if ($svgPropertyType) { 919 push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType*);\n"); 920 } else { 921 push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType*);\n"); 922 } 923 } 924 if (!$hasParent || $dataNode->extendedAttributes->{"GenerateNativeConverter"}) { 925 if ($interfaceName eq "NodeFilter") { 926 push(@headerContent, "PassRefPtr<NodeFilter> toNodeFilter(JSC::JSGlobalData&, JSC::JSValue);\n"); 927 } else { 928 push(@headerContent, "$implType* to${interfaceName}(JSC::JSValue);\n"); 929 } 930 } 931 if ($usesToJSNewlyCreated{$interfaceName}) { 932 push(@headerContent, "JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject*, $interfaceName*);\n"); 933 } 934 935 push(@headerContent, "\n"); 936 937 # Add prototype declaration. 938 %structureFlags = (); 939 push(@headerContent, "class ${className}Prototype : public JSC::JSObjectWithGlobalObject {\n"); 940 push(@headerContent, " typedef JSC::JSObjectWithGlobalObject Base;\n"); 941 push(@headerContent, "public:\n"); 942 if ($interfaceName eq "DOMWindow") { 943 push(@headerContent, " void* operator new(size_t);\n"); 944 } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) { 945 push(@headerContent, " void* operator new(size_t, JSC::JSGlobalData*);\n"); 946 } else { 947 push(@headerContent, " static JSC::JSObject* self(JSC::ExecState*, JSC::JSGlobalObject*);\n"); 948 } 949 push(@headerContent, " static const JSC::ClassInfo s_info;\n"); 950 if ($numFunctions > 0 || $numConstants > 0 || $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) { 951 push(@headerContent, " virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n"); 952 push(@headerContent, " virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n"); 953 push(@headerContent, " bool getOwnPropertySlotDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}; 954 push(@headerContent, " bool getOwnPropertyDescriptorDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n") if $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}; 955 $structureFlags{"JSC::OverridesGetOwnPropertySlot"} = 1; 956 } 957 if ($dataNode->extendedAttributes->{"CustomMarkFunction"} or $needsMarkChildren) { 958 $structureFlags{"JSC::OverridesMarkChildren"} = 1; 959 } 960 push(@headerContent, 961 " static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)\n" . 962 " {\n" . 963 " return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);\n" . 964 " }\n"); 965 if ($dataNode->extendedAttributes->{"DelegatingPrototypePutFunction"}) { 966 push(@headerContent, " virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);\n"); 967 push(@headerContent, " bool putDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, JSC::PutPropertySlot&);\n"); 968 } 969 970 # Custom defineGetter function 971 push(@headerContent, " virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomPrototypeDefineGetter"}; 972 973 push(@headerContent, " ${className}Prototype(JSC::JSGlobalData& globalData, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) : JSC::JSObjectWithGlobalObject(globalData, globalObject, structure) { }\n"); 974 975 # structure flags 976 push(@headerContent, "protected:\n"); 977 push(@headerContent, " static const unsigned StructureFlags = "); 978 foreach my $structureFlag (keys %structureFlags) { 979 push(@headerContent, $structureFlag . " | "); 980 } 981 push(@headerContent, "Base::StructureFlags;\n"); 982 983 push(@headerContent, "};\n\n"); 984 985 # Conditionally emit the constructor object's declaration 986 if ($dataNode->extendedAttributes->{"CustomConstructFunction"}) { 987 GenerateConstructorDeclaration(\@headerContent, $className, $dataNode); 988 } 989 990 991 if ($numFunctions > 0) { 992 push(@headerContent,"// Functions\n\n"); 993 foreach my $function (@{$dataNode->functions}) { 994 next if $function->{overloadIndex} && $function->{overloadIndex} > 1; 995 my $functionName = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($function->signature->name); 996 push(@headerContent, "JSC::EncodedJSValue JSC_HOST_CALL ${functionName}(JSC::ExecState*);\n"); 997 } 998 } 999 1000 if ($numAttributes > 0 || !($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { 1001 push(@headerContent,"// Attributes\n\n"); 1002 foreach my $attribute (@{$dataNode->attributes}) { 1003 my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : ""); 1004 push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&);\n"); 1005 unless ($attribute->type =~ /readonly/) { 1006 my $setter = "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : ""); 1007 push(@headerContent, "void ${setter}(JSC::ExecState*, JSC::JSObject*, JSC::JSValue);\n"); 1008 } 1009 } 1010 1011 if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { 1012 my $getter = "js" . $interfaceName . "Constructor"; 1013 push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&);\n"); 1014 } 1015 1016 if ($dataNode->extendedAttributes->{"ReplaceableConstructor"}) { 1017 my $constructorFunctionName = "setJS" . $interfaceName . "Constructor"; 1018 push(@headerContent, "void ${constructorFunctionName}(JSC::ExecState*, JSC::JSObject*, JSC::JSValue);\n"); 1019 } 1020 } 1021 1022 if ($numConstants > 0) { 1023 push(@headerContent,"// Constants\n\n"); 1024 foreach my $constant (@{$dataNode->constants}) { 1025 my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name); 1026 push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&);\n"); 1027 } 1028 } 1029 1030 my $conditionalString = GenerateConditionalString($dataNode); 1031 push(@headerContent, "\n} // namespace WebCore\n\n"); 1032 push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString; 1033 push(@headerContent, "#endif\n"); 1034 1035 # - Generate dependencies. 1036 if ($writeDependencies && @ancestorInterfaceNames) { 1037 push(@depsContent, "$className.h : ", join(" ", map { "$_.idl" } @ancestorInterfaceNames), "\n"); 1038 push(@depsContent, map { "$_.idl :\n" } @ancestorInterfaceNames); 1039 } 1040 } 1041 1042 sub GenerateAttributesHashTable($$) 1043 { 1044 my ($object, $dataNode) = @_; 1045 1046 # FIXME: These should be functions on $dataNode. 1047 my $interfaceName = $dataNode->name; 1048 my $className = "JS$interfaceName"; 1049 1050 # - Add all attributes in a hashtable definition 1051 my $numAttributes = @{$dataNode->attributes}; 1052 $numAttributes++ if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})); 1053 1054 return 0 if !$numAttributes; 1055 1056 my $hashSize = $numAttributes; 1057 my $hashName = $className . "Table"; 1058 1059 my @hashKeys = (); 1060 my @hashSpecials = (); 1061 my @hashValue1 = (); 1062 my @hashValue2 = (); 1063 my %conditionals = (); 1064 1065 my @entries = (); 1066 1067 foreach my $attribute (@{$dataNode->attributes}) { 1068 my $name = $attribute->signature->name; 1069 push(@hashKeys, $name); 1070 1071 my @specials = (); 1072 push(@specials, "DontDelete") unless $attribute->signature->extendedAttributes->{"Deletable"}; 1073 push(@specials, "DontEnum") if $attribute->signature->extendedAttributes->{"DontEnum"}; 1074 push(@specials, "ReadOnly") if $attribute->type =~ /readonly/; 1075 my $special = (@specials > 0) ? join(" | ", @specials) : "0"; 1076 push(@hashSpecials, $special); 1077 1078 my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : ""); 1079 push(@hashValue1, $getter); 1080 1081 if ($attribute->type =~ /readonly/) { 1082 push(@hashValue2, "0"); 1083 } else { 1084 my $setter = "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : ""); 1085 push(@hashValue2, $setter); 1086 } 1087 1088 my $conditional = $attribute->signature->extendedAttributes->{"Conditional"}; 1089 if ($conditional) { 1090 $conditionals{$name} = $conditional; 1091 } 1092 } 1093 1094 if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { 1095 push(@hashKeys, "constructor"); 1096 my $getter = "js" . $interfaceName . "Constructor"; 1097 push(@hashValue1, $getter); 1098 if ($dataNode->extendedAttributes->{"ReplaceableConstructor"}) { 1099 my $setter = "setJS" . $interfaceName . "Constructor"; 1100 push(@hashValue2, $setter); 1101 push(@hashSpecials, "DontEnum | DontDelete"); 1102 } else { 1103 push(@hashValue2, "0"); 1104 push(@hashSpecials, "DontEnum | ReadOnly"); 1105 } 1106 } 1107 1108 $object->GenerateHashTable($hashName, $hashSize, 1109 \@hashKeys, \@hashSpecials, 1110 \@hashValue1, \@hashValue2, 1111 \%conditionals); 1112 return $numAttributes; 1113 } 1114 1115 sub GenerateParametersCheckExpression 1116 { 1117 my $numParameters = shift; 1118 my $function = shift; 1119 1120 my @andExpression = (); 1121 push(@andExpression, "exec->argumentCount() == $numParameters"); 1122 my $parameterIndex = 0; 1123 foreach $parameter (@{$function->parameters}) { 1124 last if $parameterIndex >= $numParameters; 1125 my $value = "exec->argument($parameterIndex)"; 1126 my $type = $codeGenerator->StripModule($parameter->type); 1127 1128 # Only DOMString or wrapper types are checked. 1129 # For DOMString, Null, Undefined and any Object are accepted too, as 1130 # these are acceptable values for a DOMString argument (any Object can 1131 # be converted to a string via .toString). 1132 if ($codeGenerator->IsStringType($type)) { 1133 push(@andExpression, "(${value}.isNull() || ${value}.isUndefined() || ${value}.isString() || ${value}.isObject())"); 1134 } elsif ($parameter->extendedAttributes->{"Callback"}) { 1135 # For Callbacks only checks if the value is null or object. 1136 push(@andExpression, "(${value}.isNull() || ${value}.isObject())"); 1137 } elsif (!IsNativeType($type)) { 1138 push(@andExpression, "(${value}.isNull() || (${value}.isObject() && asObject(${value})->inherits(&JS${type}::s_info)))"); 1139 } 1140 $parameterIndex++; 1141 } 1142 my $res = join(" && ", @andExpression); 1143 $res = "($res)" if @andExpression > 1; 1144 return $res; 1145 } 1146 1147 sub GenerateFunctionParametersCheck 1148 { 1149 my $function = shift; 1150 1151 my @orExpression = (); 1152 my $numParameters = 0; 1153 foreach $parameter (@{$function->parameters}) { 1154 if ($parameter->extendedAttributes->{"Optional"}) { 1155 push(@orExpression, GenerateParametersCheckExpression($numParameters, $function)); 1156 } 1157 $numParameters++; 1158 } 1159 push(@orExpression, GenerateParametersCheckExpression($numParameters, $function)); 1160 return join(" || ", @orExpression); 1161 } 1162 1163 sub GenerateOverloadedPrototypeFunction 1164 { 1165 my $function = shift; 1166 my $dataNode = shift; 1167 my $implClassName = shift; 1168 1169 # Generate code for choosing the correct overload to call. Overloads are 1170 # chosen based on the total number of arguments passed and the type of 1171 # values passed in non-primitive argument slots. When more than a single 1172 # overload is applicable, precedence is given according to the order of 1173 # declaration in the IDL. 1174 1175 my $functionName = "js${implClassName}PrototypeFunction" . $codeGenerator->WK_ucfirst($function->signature->name); 1176 1177 push(@implContent, "EncodedJSValue JSC_HOST_CALL ${functionName}(ExecState* exec)\n"); 1178 push(@implContent, <<END); 1179 { 1180 END 1181 foreach my $overload (@{$function->{overloads}}) { 1182 my $parametersCheck = GenerateFunctionParametersCheck($overload); 1183 push(@implContent, " if ($parametersCheck)\n"); 1184 push(@implContent, " return ${functionName}$overload->{overloadIndex}(exec);\n"); 1185 } 1186 push(@implContent, <<END); 1187 return throwVMTypeError(exec); 1188 } 1189 1190 END 1191 } 1192 1193 sub GenerateImplementation 1194 { 1195 my ($object, $dataNode) = @_; 1196 1197 my $interfaceName = $dataNode->name; 1198 my $className = "JS$interfaceName"; 1199 my $implClassName = $interfaceName; 1200 1201 my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"}; 1202 my $hasRealParent = @{$dataNode->parents} > 0; 1203 my $hasParent = $hasLegacyParent || $hasRealParent; 1204 my $parentClassName = GetParentClassName($dataNode); 1205 my $visibleClassName = GetVisibleClassName($interfaceName); 1206 my $eventTarget = $dataNode->extendedAttributes->{"EventTarget"}; 1207 my $needsMarkChildren = $dataNode->extendedAttributes->{"CustomMarkFunction"} || $dataNode->extendedAttributes->{"EventTarget"}; 1208 1209 # - Add default header template 1210 push(@implContentHeader, GenerateImplementationContentHeader($dataNode)); 1211 1212 AddIncludesForSVGAnimatedType($interfaceName) if $className =~ /^JSSVGAnimated/; 1213 1214 $implIncludes{"<wtf/GetPtr.h>"} = 1; 1215 $implIncludes{"<runtime/PropertyNameArray.h>"} = 1 if $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}; 1216 1217 AddIncludesForType($interfaceName); 1218 1219 @implContent = (); 1220 1221 push(@implContent, "\nusing namespace JSC;\n\n"); 1222 push(@implContent, "namespace WebCore {\n\n"); 1223 1224 push(@implContent, "ASSERT_CLASS_FITS_IN_CELL($className);\n\n"); 1225 1226 my $numAttributes = GenerateAttributesHashTable($object, $dataNode); 1227 1228 my $numConstants = @{$dataNode->constants}; 1229 my $numFunctions = @{$dataNode->functions}; 1230 1231 # - Add all constants 1232 if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { 1233 $hashSize = $numConstants; 1234 $hashName = $className . "ConstructorTable"; 1235 1236 @hashKeys = (); 1237 @hashValue1 = (); 1238 @hashValue2 = (); 1239 @hashSpecials = (); 1240 1241 # FIXME: we should not need a function for every constant. 1242 foreach my $constant (@{$dataNode->constants}) { 1243 push(@hashKeys, $constant->name); 1244 my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name); 1245 push(@hashValue1, $getter); 1246 push(@hashValue2, "0"); 1247 push(@hashSpecials, "DontDelete | ReadOnly"); 1248 } 1249 1250 $object->GenerateHashTable($hashName, $hashSize, 1251 \@hashKeys, \@hashSpecials, 1252 \@hashValue1, \@hashValue2); 1253 1254 push(@implContent, $codeGenerator->GenerateCompileTimeCheckForEnumsIfNeeded($dataNode)); 1255 1256 my $protoClassName = "${className}Prototype"; 1257 1258 GenerateConstructorDeclaration(\@implContent, $className, $dataNode) unless $dataNode->extendedAttributes->{"CustomConstructFunction"}; 1259 GenerateConstructorDefinition(\@implContent, $className, $protoClassName, $interfaceName, $visibleClassName, $dataNode); 1260 } 1261 1262 # - Add functions and constants to a hashtable definition 1263 $hashSize = $numFunctions + $numConstants; 1264 $hashName = $className . "PrototypeTable"; 1265 1266 @hashKeys = (); 1267 @hashValue1 = (); 1268 @hashValue2 = (); 1269 @hashSpecials = (); 1270 1271 # FIXME: we should not need a function for every constant. 1272 foreach my $constant (@{$dataNode->constants}) { 1273 push(@hashKeys, $constant->name); 1274 my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name); 1275 push(@hashValue1, $getter); 1276 push(@hashValue2, "0"); 1277 push(@hashSpecials, "DontDelete | ReadOnly"); 1278 } 1279 1280 foreach my $function (@{$dataNode->functions}) { 1281 next if $function->{overloadIndex} && $function->{overloadIndex} > 1; 1282 my $name = $function->signature->name; 1283 push(@hashKeys, $name); 1284 1285 my $value = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($name); 1286 push(@hashValue1, $value); 1287 1288 my $numParameters = @{$function->parameters}; 1289 push(@hashValue2, $numParameters); 1290 1291 my @specials = (); 1292 push(@specials, "DontDelete") unless $function->signature->extendedAttributes->{"Deletable"}; 1293 push(@specials, "DontEnum") if $function->signature->extendedAttributes->{"DontEnum"}; 1294 push(@specials, "Function"); 1295 my $special = (@specials > 0) ? join(" | ", @specials) : "0"; 1296 push(@hashSpecials, $special); 1297 } 1298 1299 $object->GenerateHashTable($hashName, $hashSize, 1300 \@hashKeys, \@hashSpecials, 1301 \@hashValue1, \@hashValue2); 1302 1303 if ($dataNode->extendedAttributes->{"NoStaticTables"}) { 1304 push(@implContent, "static const HashTable* get${className}PrototypeTable(ExecState* exec)\n"); 1305 push(@implContent, "{\n"); 1306 push(@implContent, " return getHashTableForGlobalData(exec->globalData(), &${className}PrototypeTable);\n"); 1307 push(@implContent, "}\n\n"); 1308 push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleClassName}Prototype\", &JSC::JSObjectWithGlobalObject::s_info, 0, get${className}PrototypeTable };\n\n"); 1309 } else { 1310 push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleClassName}Prototype\", &JSC::JSObjectWithGlobalObject::s_info, &${className}PrototypeTable, 0 };\n\n"); 1311 } 1312 if ($interfaceName eq "DOMWindow") { 1313 push(@implContent, "void* ${className}Prototype::operator new(size_t size)\n"); 1314 push(@implContent, "{\n"); 1315 push(@implContent, " return JSDOMWindow::commonJSGlobalData()->heap.allocate(size);\n"); 1316 push(@implContent, "}\n\n"); 1317 } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) { 1318 push(@implContent, "void* ${className}Prototype::operator new(size_t size, JSGlobalData* globalData)\n"); 1319 push(@implContent, "{\n"); 1320 push(@implContent, " return globalData->heap.allocate(size);\n"); 1321 push(@implContent, "}\n\n"); 1322 } else { 1323 push(@implContent, "JSObject* ${className}Prototype::self(ExecState* exec, JSGlobalObject* globalObject)\n"); 1324 push(@implContent, "{\n"); 1325 push(@implContent, " return getDOMPrototype<${className}>(exec, globalObject);\n"); 1326 push(@implContent, "}\n\n"); 1327 } 1328 if ($numConstants > 0 || $numFunctions > 0 || $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) { 1329 push(@implContent, "bool ${className}Prototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n"); 1330 push(@implContent, "{\n"); 1331 1332 if ($dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) { 1333 push(@implContent, " if (getOwnPropertySlotDelegate(exec, propertyName, slot))\n"); 1334 push(@implContent, " return true;\n"); 1335 } 1336 1337 if ($numConstants eq 0 && $numFunctions eq 0) { 1338 push(@implContent, " return Base::getOwnPropertySlot(exec, propertyName, slot);\n"); 1339 } elsif ($numConstants eq 0) { 1340 push(@implContent, " return getStaticFunctionSlot<JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n"); 1341 } elsif ($numFunctions eq 0) { 1342 push(@implContent, " return getStaticValueSlot<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n"); 1343 } else { 1344 push(@implContent, " return getStaticPropertySlot<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n"); 1345 } 1346 push(@implContent, "}\n\n"); 1347 1348 push(@implContent, "bool ${className}Prototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\n"); 1349 push(@implContent, "{\n"); 1350 1351 if ($dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) { 1352 push(@implContent, " if (getOwnPropertyDescriptorDelegate(exec, propertyName, descriptor))\n"); 1353 push(@implContent, " return true;\n"); 1354 } 1355 1356 if ($numConstants eq 0 && $numFunctions eq 0) { 1357 push(@implContent, " return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);\n"); 1358 } elsif ($numConstants eq 0) { 1359 push(@implContent, " return getStaticFunctionDescriptor<JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n"); 1360 } elsif ($numFunctions eq 0) { 1361 push(@implContent, " return getStaticValueDescriptor<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n"); 1362 } else { 1363 push(@implContent, " return getStaticPropertyDescriptor<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n"); 1364 } 1365 push(@implContent, "}\n\n"); 1366 } 1367 1368 if ($dataNode->extendedAttributes->{"DelegatingPrototypePutFunction"}) { 1369 push(@implContent, "void ${className}Prototype::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)\n"); 1370 push(@implContent, "{\n"); 1371 push(@implContent, " if (putDelegate(exec, propertyName, value, slot))\n"); 1372 push(@implContent, " return;\n"); 1373 push(@implContent, " Base::put(exec, propertyName, value, slot);\n"); 1374 push(@implContent, "}\n\n"); 1375 } 1376 1377 # - Initialize static ClassInfo object 1378 if ($numAttributes > 0 && $dataNode->extendedAttributes->{"NoStaticTables"}) { 1379 push(@implContent, "static const HashTable* get${className}Table(ExecState* exec)\n"); 1380 push(@implContent, "{\n"); 1381 push(@implContent, " return getHashTableForGlobalData(exec->globalData(), &${className}Table);\n"); 1382 push(@implContent, "}\n\n"); 1383 } 1384 1385 push(@implContent, "const ClassInfo $className" . "::s_info = { \"${visibleClassName}\", &" . $parentClassName . "::s_info, "); 1386 1387 if ($numAttributes > 0 && !$dataNode->extendedAttributes->{"NoStaticTables"}) { 1388 push(@implContent, "&${className}Table"); 1389 } else { 1390 push(@implContent, "0"); 1391 } 1392 if ($numAttributes > 0 && $dataNode->extendedAttributes->{"NoStaticTables"}) { 1393 push(@implContent, ", get${className}Table "); 1394 } else { 1395 push(@implContent, ", 0 "); 1396 } 1397 push(@implContent, "};\n\n"); 1398 1399 my $implType = $implClassName; 1400 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implType); 1401 $implType = $svgNativeType if $svgNativeType; 1402 1403 my $svgPropertyOrListPropertyType; 1404 $svgPropertyOrListPropertyType = $svgPropertyType if $svgPropertyType; 1405 $svgPropertyOrListPropertyType = $svgListPropertyType if $svgListPropertyType; 1406 1407 # Constructor 1408 if ($interfaceName eq "DOMWindow") { 1409 AddIncludesForType("JSDOMWindowShell"); 1410 push(@implContent, "${className}::$className(JSGlobalData& globalData, Structure* structure, PassRefPtr<$implType> impl, JSDOMWindowShell* shell)\n"); 1411 push(@implContent, " : $parentClassName(globalData, structure, impl, shell)\n"); 1412 } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) { 1413 AddIncludesForType($interfaceName); 1414 push(@implContent, "${className}::$className(JSGlobalData& globalData, Structure* structure, PassRefPtr<$implType> impl)\n"); 1415 push(@implContent, " : $parentClassName(globalData, structure, impl)\n"); 1416 } else { 1417 push(@implContent, "${className}::$className(Structure* structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl)\n"); 1418 if ($hasParent) { 1419 push(@implContent, " : $parentClassName(structure, globalObject, impl)\n"); 1420 } else { 1421 push(@implContent, " : $parentClassName(structure, globalObject)\n"); 1422 push(@implContent, " , m_impl(impl)\n"); 1423 } 1424 } 1425 push(@implContent, "{\n"); 1426 push(@implContent, " ASSERT(inherits(&s_info));\n"); 1427 if ($numCachedAttributes > 0) { 1428 push(@implContent, " for (unsigned i = Base::AnonymousSlotCount; i < AnonymousSlotCount; i++)\n"); 1429 push(@implContent, " putAnonymousValue(globalObject->globalData(), i, JSValue());\n"); 1430 } 1431 push(@implContent, "}\n\n"); 1432 1433 if ($needsMarkChildren && !$dataNode->extendedAttributes->{"CustomMarkFunction"}) { 1434 push(@implContent, "void ${className}::markChildren(MarkStack& markStack)\n"); 1435 push(@implContent, "{\n"); 1436 push(@implContent, " Base::markChildren(markStack);\n"); 1437 push(@implContent, " impl()->markJSEventListeners(markStack);\n"); 1438 push(@implContent, "}\n\n"); 1439 } 1440 1441 if (!$dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"}) { 1442 push(@implContent, "JSObject* ${className}::createPrototype(ExecState* exec, JSGlobalObject* globalObject)\n"); 1443 push(@implContent, "{\n"); 1444 if ($hasParent && $parentClassName ne "JSC::DOMNodeFilter") { 1445 push(@implContent, " return new (exec) ${className}Prototype(exec->globalData(), globalObject, ${className}Prototype::createStructure(exec->globalData(), ${parentClassName}Prototype::self(exec, globalObject)));\n"); 1446 } else { 1447 push(@implContent, " return new (exec) ${className}Prototype(exec->globalData(), globalObject, ${className}Prototype::createStructure(globalObject->globalData(), globalObject->objectPrototype()));\n"); 1448 } 1449 push(@implContent, "}\n\n"); 1450 } 1451 1452 my $hasGetter = $numAttributes > 0 1453 || !($dataNode->extendedAttributes->{"OmitConstructor"} 1454 || $dataNode->extendedAttributes->{"CustomConstructor"}) 1455 || $dataNode->extendedAttributes->{"HasIndexGetter"} 1456 || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} 1457 || $dataNode->extendedAttributes->{"HasNumericIndexGetter"} 1458 || $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"} 1459 || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"} 1460 || $dataNode->extendedAttributes->{"HasNameGetter"} 1461 || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}; 1462 1463 # Attributes 1464 if ($hasGetter) { 1465 if (!$dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"} && !$dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}) { 1466 push(@implContent, "bool ${className}::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n"); 1467 push(@implContent, "{\n"); 1468 push(@implContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 0)); 1469 push(@implContent, "}\n\n"); 1470 push(@implContent, "bool ${className}::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\n"); 1471 push(@implContent, "{\n"); 1472 push(@implContent, GenerateGetOwnPropertyDescriptorBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 0)); 1473 push(@implContent, "}\n\n"); 1474 } 1475 1476 if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) 1477 && !$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) { 1478 push(@implContent, "bool ${className}::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)\n"); 1479 push(@implContent, "{\n"); 1480 push(@implContent, " if (propertyName < static_cast<$implClassName*>(impl())->length()) {\n"); 1481 if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) { 1482 push(@implContent, " slot.setValue(getByIndex(exec, propertyName));\n"); 1483 } else { 1484 push(@implContent, " slot.setCustomIndex(this, propertyName, indexGetter);\n"); 1485 } 1486 push(@implContent, " return true;\n"); 1487 push(@implContent, " }\n"); 1488 push(@implContent, " return getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);\n"); 1489 push(@implContent, "}\n\n"); 1490 } 1491 1492 if ($numAttributes > 0) { 1493 foreach my $attribute (@{$dataNode->attributes}) { 1494 my $name = $attribute->signature->name; 1495 my $type = $codeGenerator->StripModule($attribute->signature->type); 1496 my $getFunctionName = "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : ""); 1497 my $implGetterFunctionName = $codeGenerator->WK_lcfirst($name); 1498 1499 my $attributeConditionalString = GenerateConditionalString($attribute->signature); 1500 push(@implContent, "#if ${attributeConditionalString}\n") if $attributeConditionalString; 1501 1502 push(@implContent, "JSValue ${getFunctionName}(ExecState* exec, JSValue slotBase, const Identifier&)\n"); 1503 push(@implContent, "{\n"); 1504 push(@implContent, " ${className}* castedThis = static_cast<$className*>(asObject(slotBase));\n"); 1505 1506 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && 1507 !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurity"} && 1508 !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurityOnGet"}) { 1509 push(@implContent, " if (!castedThis->allowsAccessFrom(exec))\n"); 1510 push(@implContent, " return jsUndefined();\n"); 1511 } 1512 1513 if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"} || $attribute->signature->extendedAttributes->{"CustomGetter"} || $attribute->signature->extendedAttributes->{"JSCCustomGetter"}) { 1514 push(@implContent, " return castedThis->$implGetterFunctionName(exec);\n"); 1515 } elsif ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) { 1516 $implIncludes{"JSDOMBinding.h"} = 1; 1517 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n"); 1518 push(@implContent, " return checkNodeSecurity(exec, imp->$implGetterFunctionName()) ? " . NativeToJSValue($attribute->signature, 0, $implClassName, "imp->$implGetterFunctionName()", "castedThis") . " : jsUndefined();\n"); 1519 } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) { 1520 $implIncludes{"Document.h"} = 1; 1521 $implIncludes{"JSDOMBinding.h"} = 1; 1522 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n"); 1523 push(@implContent, " return checkNodeSecurity(exec, imp->contentDocument()) ? " . NativeToJSValue($attribute->signature, 0, $implClassName, "imp->$implGetterFunctionName()", "castedThis") . " : jsUndefined();\n"); 1524 } elsif ($type eq "EventListener") { 1525 $implIncludes{"EventListener.h"} = 1; 1526 push(@implContent, " UNUSED_PARAM(exec);\n"); 1527 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n"); 1528 push(@implContent, " if (EventListener* listener = imp->$implGetterFunctionName()) {\n"); 1529 push(@implContent, " if (const JSEventListener* jsListener = JSEventListener::cast(listener)) {\n"); 1530 if ($implClassName eq "Document" || $implClassName eq "WorkerContext" || $implClassName eq "SharedWorkerContext" || $implClassName eq "DedicatedWorkerContext") { 1531 push(@implContent, " if (JSObject* jsFunction = jsListener->jsFunction(imp))\n"); 1532 } else { 1533 push(@implContent, " if (JSObject* jsFunction = jsListener->jsFunction(imp->scriptExecutionContext()))\n"); 1534 } 1535 push(@implContent, " return jsFunction;\n"); 1536 push(@implContent, " }\n"); 1537 push(@implContent, " }\n"); 1538 push(@implContent, " return jsNull();\n"); 1539 } elsif ($attribute->signature->type =~ /Constructor$/) { 1540 my $constructorType = $codeGenerator->StripModule($attribute->signature->type); 1541 $constructorType =~ s/Constructor$//; 1542 # Constructor attribute is only used by DOMWindow.idl, so it's correct to pass castedThis as the global object 1543 # Once JSDOMWrappers have a back-pointer to the globalObject we can pass castedThis->globalObject() 1544 push(@implContent, " return JS" . $constructorType . "::getConstructor(exec, castedThis);\n"); 1545 } elsif (!@{$attribute->getterExceptions}) { 1546 push(@implContent, " UNUSED_PARAM(exec);\n"); 1547 my $cacheIndex = 0; 1548 if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) { 1549 $cacheIndex = $currentCachedAttribute; 1550 $currentCachedAttribute++; 1551 push(@implContent, " if (JSValue cachedValue = castedThis->getAnonymousValue(" . $className . "::" . $attribute->signature->name . "Slot))\n"); 1552 push(@implContent, " return cachedValue;\n"); 1553 } 1554 1555 if ($svgListPropertyType) { 1556 push(@implContent, " JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "castedThis->impl()->$implGetterFunctionName()", "castedThis") . ";\n"); 1557 } elsif ($svgPropertyOrListPropertyType) { 1558 push(@implContent, " $svgPropertyOrListPropertyType& imp = castedThis->impl()->propertyReference();\n"); 1559 if ($svgPropertyOrListPropertyType eq "float") { # Special case for JSSVGNumber 1560 push(@implContent, " JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "imp", "castedThis") . ";\n"); 1561 } else { 1562 push(@implContent, " JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "imp.$implGetterFunctionName()", "castedThis") . ";\n"); 1563 } 1564 } else { 1565 my $getterExpression = "imp->" . $codeGenerator->GetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute) . ")"; 1566 my $jsType = NativeToJSValue($attribute->signature, 0, $implClassName, $getterExpression, "castedThis"); 1567 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n"); 1568 if ($codeGenerator->IsSVGAnimatedType($type)) { 1569 push(@implContent, " RefPtr<$type> obj = $jsType;\n"); 1570 push(@implContent, " JSValue result = toJS(exec, castedThis->globalObject(), obj.get());\n"); 1571 } else { 1572 push(@implContent, " JSValue result = $jsType;\n"); 1573 } 1574 } 1575 1576 push(@implContent, " castedThis->putAnonymousValue(exec->globalData(), " . $className . "::" . $attribute->signature->name . "Slot, result);\n") if ($attribute->signature->extendedAttributes->{"CachedAttribute"}); 1577 push(@implContent, " return result;\n"); 1578 1579 } else { 1580 push(@implContent, " ExceptionCode ec = 0;\n"); 1581 if ($svgPropertyOrListPropertyType) { 1582 push(@implContent, " $svgPropertyOrListPropertyType imp(*castedThis->impl());\n"); 1583 push(@implContent, " JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "imp.$implGetterFunctionName(ec)", "castedThis") . ";\n"); 1584 } else { 1585 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n"); 1586 push(@implContent, " JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "imp->$implGetterFunctionName(ec)", "castedThis") . ";\n"); 1587 } 1588 1589 push(@implContent, " setDOMException(exec, ec);\n"); 1590 push(@implContent, " return result;\n"); 1591 } 1592 1593 push(@implContent, "}\n\n"); 1594 1595 push(@implContent, "#endif\n") if $attributeConditionalString; 1596 1597 push(@implContent, "\n"); 1598 } 1599 1600 if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { 1601 my $constructorFunctionName = "js" . $interfaceName . "Constructor"; 1602 1603 push(@implContent, "JSValue ${constructorFunctionName}(ExecState* exec, JSValue slotBase, const Identifier&)\n"); 1604 push(@implContent, "{\n"); 1605 push(@implContent, " ${className}* domObject = static_cast<$className*>(asObject(slotBase));\n"); 1606 1607 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) { 1608 push(@implContent, " if (!domObject->allowsAccessFrom(exec))\n"); 1609 push(@implContent, " return jsUndefined();\n"); 1610 } 1611 1612 push(@implContent, " return ${className}::getConstructor(exec, domObject->globalObject());\n"); 1613 push(@implContent, "}\n\n"); 1614 } 1615 } 1616 1617 # Check if we have any writable attributes 1618 my $hasReadWriteProperties = 0; 1619 foreach my $attribute (@{$dataNode->attributes}) { 1620 $hasReadWriteProperties = 1 if $attribute->type !~ /^readonly/; 1621 } 1622 1623 my $hasSetter = $hasReadWriteProperties 1624 || $dataNode->extendedAttributes->{"DelegatingPutFunction"} 1625 || $dataNode->extendedAttributes->{"HasCustomIndexSetter"}; 1626 1627 if ($hasSetter) { 1628 if (!$dataNode->extendedAttributes->{"CustomPutFunction"}) { 1629 push(@implContent, "void ${className}::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)\n"); 1630 push(@implContent, "{\n"); 1631 if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) { 1632 push(@implContent, " bool ok;\n"); 1633 push(@implContent, " unsigned index = propertyName.toUInt32(ok);\n"); 1634 push(@implContent, " if (ok) {\n"); 1635 push(@implContent, " indexSetter(exec, index, value);\n"); 1636 push(@implContent, " return;\n"); 1637 push(@implContent, " }\n"); 1638 } 1639 if ($dataNode->extendedAttributes->{"DelegatingPutFunction"}) { 1640 push(@implContent, " if (putDelegate(exec, propertyName, value, slot))\n"); 1641 push(@implContent, " return;\n"); 1642 } 1643 1644 if ($hasReadWriteProperties) { 1645 push(@implContent, " lookupPut<$className, Base>(exec, propertyName, value, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, slot);\n"); 1646 } else { 1647 push(@implContent, " Base::put(exec, propertyName, value, slot);\n"); 1648 } 1649 push(@implContent, "}\n\n"); 1650 } 1651 1652 if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) { 1653 push(@implContent, "void ${className}::put(ExecState* exec, unsigned propertyName, JSValue value)\n"); 1654 push(@implContent, "{\n"); 1655 push(@implContent, " indexSetter(exec, propertyName, value);\n"); 1656 push(@implContent, " return;\n"); 1657 push(@implContent, "}\n\n"); 1658 } 1659 1660 if ($hasReadWriteProperties) { 1661 foreach my $attribute (@{$dataNode->attributes}) { 1662 if ($attribute->type !~ /^readonly/) { 1663 my $name = $attribute->signature->name; 1664 my $type = $codeGenerator->StripModule($attribute->signature->type); 1665 my $putFunctionName = "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : ""); 1666 my $implSetterFunctionName = $codeGenerator->WK_ucfirst($name); 1667 1668 my $attributeConditionalString = GenerateConditionalString($attribute->signature); 1669 push(@implContent, "#if ${attributeConditionalString}\n") if $attributeConditionalString; 1670 1671 push(@implContent, "void ${putFunctionName}(ExecState* exec, JSObject* thisObject, JSValue value)\n"); 1672 push(@implContent, "{\n"); 1673 1674 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) { 1675 if ($interfaceName eq "DOMWindow") { 1676 push(@implContent, " if (!static_cast<$className*>(thisObject)->allowsAccessFrom(exec))\n"); 1677 } else { 1678 push(@implContent, " if (!allowsAccessFromFrame(exec, static_cast<$className*>(thisObject)->impl()->frame()))\n"); 1679 } 1680 push(@implContent, " return;\n"); 1681 } 1682 1683 if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"} || $attribute->signature->extendedAttributes->{"CustomSetter"} || $attribute->signature->extendedAttributes->{"JSCCustomSetter"}) { 1684 push(@implContent, " static_cast<$className*>(thisObject)->set$implSetterFunctionName(exec, value);\n"); 1685 } elsif ($type eq "EventListener") { 1686 $implIncludes{"JSEventListener.h"} = 1; 1687 push(@implContent, " UNUSED_PARAM(exec);\n"); 1688 my $windowEventListener = $attribute->signature->extendedAttributes->{"WindowEventListener"}; 1689 if ($windowEventListener) { 1690 push(@implContent, " ${className}* castedThis = static_cast<${className}*>(thisObject);\n"); 1691 push(@implContent, " JSDOMGlobalObject* globalObject = castedThis->globalObject();\n"); 1692 } 1693 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(thisObject)->impl());\n"); 1694 if ((($interfaceName eq "DOMWindow") or ($interfaceName eq "WorkerContext")) and $name eq "onerror") { 1695 $implIncludes{"JSErrorHandler.h"} = 1; 1696 push(@implContent, " imp->set$implSetterFunctionName(createJSErrorHandler(exec, value, thisObject));\n"); 1697 } else { 1698 push(@implContent, GenerateAttributeEventListenerCall($className, $implSetterFunctionName, $windowEventListener)); 1699 } 1700 } elsif ($attribute->signature->type =~ /Constructor$/) { 1701 my $constructorType = $attribute->signature->type; 1702 $constructorType =~ s/Constructor$//; 1703 if ($constructorType ne "DOMObject") { 1704 $implIncludes{"JS" . $constructorType . ".h"} = 1; 1705 } 1706 push(@implContent, " // Shadowing a built-in constructor\n"); 1707 if ($interfaceName eq "DOMWindow" && $className eq "JSblah") { 1708 push(@implContent, " static_cast<$className*>(thisObject)->putDirect(exec->globalData(), exec->propertyNames().constructor, value);\n"); 1709 } else { 1710 push(@implContent, " static_cast<$className*>(thisObject)->putDirect(exec->globalData(), Identifier(exec, \"$name\"), value);\n"); 1711 } 1712 } elsif ($attribute->signature->extendedAttributes->{"Replaceable"}) { 1713 push(@implContent, " // Shadowing a built-in object\n"); 1714 push(@implContent, " static_cast<$className*>(thisObject)->putDirect(exec->globalData(), Identifier(exec, \"$name\"), value);\n"); 1715 } else { 1716 push(@implContent, " $className* castedThis = static_cast<$className*>(thisObject);\n"); 1717 push(@implContent, " $implType* imp = static_cast<$implType*>(castedThis->impl());\n"); 1718 push(@implContent, " ExceptionCode ec = 0;\n") if @{$attribute->setterExceptions}; 1719 1720 # If the "StrictTypeChecking" extended attribute is present, and the attribute's type is an 1721 # interface type, then if the incoming value does not implement that interface, a TypeError 1722 # is thrown rather than silently passing NULL to the C++ code. 1723 # Per the Web IDL and ECMAScript specifications, incoming values can always be converted to 1724 # both strings and numbers, so do not throw TypeError if the attribute is of these types. 1725 if ($attribute->signature->extendedAttributes->{"StrictTypeChecking"}) { 1726 $implIncludes{"<runtime/Error.h>"} = 1; 1727 1728 my $argType = $attribute->signature->type; 1729 if (!IsNativeType($argType)) { 1730 push(@implContent, " if (!value.isUndefinedOrNull() && !value.inherits(&JS${argType}::s_info)) {\n"); 1731 push(@implContent, " throwVMTypeError(exec);\n"); 1732 push(@implContent, " return;\n"); 1733 push(@implContent, " };\n"); 1734 } 1735 } 1736 1737 my $nativeValue = JSValueToNative($attribute->signature, "value"); 1738 if ($svgPropertyOrListPropertyType) { 1739 if ($svgPropertyType) { 1740 push(@implContent, " if (imp->role() == AnimValRole) {\n"); 1741 push(@implContent, " setDOMException(exec, NO_MODIFICATION_ALLOWED_ERR);\n"); 1742 push(@implContent, " return;\n"); 1743 push(@implContent, " }\n"); 1744 } 1745 push(@implContent, " $svgPropertyOrListPropertyType& podImp = imp->propertyReference();\n"); 1746 if ($svgPropertyOrListPropertyType eq "float") { # Special case for JSSVGNumber 1747 push(@implContent, " podImp = $nativeValue;\n"); 1748 } else { 1749 push(@implContent, " podImp.set$implSetterFunctionName($nativeValue"); 1750 push(@implContent, ", ec") if @{$attribute->setterExceptions}; 1751 push(@implContent, ");\n"); 1752 push(@implContent, " setDOMException(exec, ec);\n") if @{$attribute->setterExceptions}; 1753 } 1754 if ($svgPropertyType) { 1755 if (@{$attribute->setterExceptions}) { 1756 push(@implContent, " if (!ec)\n"); 1757 push(@implContent, " imp->commitChange();\n"); 1758 } else { 1759 push(@implContent, " imp->commitChange();\n"); 1760 } 1761 } 1762 } else { 1763 my $setterExpressionPrefix = $codeGenerator->SetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute); 1764 push(@implContent, " imp->$setterExpressionPrefix$nativeValue"); 1765 push(@implContent, ", ec") if @{$attribute->setterExceptions}; 1766 push(@implContent, ");\n"); 1767 push(@implContent, " setDOMException(exec, ec);\n") if @{$attribute->setterExceptions}; 1768 } 1769 } 1770 1771 push(@implContent, "}\n\n"); 1772 1773 push(@implContent, "#endif\n") if $attributeConditionalString; 1774 1775 push(@implContent, "\n"); 1776 } 1777 } 1778 } 1779 1780 if ($dataNode->extendedAttributes->{"ReplaceableConstructor"}) { 1781 my $constructorFunctionName = "setJS" . $interfaceName . "Constructor"; 1782 1783 push(@implContent, "void ${constructorFunctionName}(ExecState* exec, JSObject* thisObject, JSValue value)\n"); 1784 push(@implContent, "{\n"); 1785 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) { 1786 if ($interfaceName eq "DOMWindow") { 1787 push(@implContent, " if (!static_cast<$className*>(thisObject)->allowsAccessFrom(exec))\n"); 1788 } else { 1789 push(@implContent, " if (!allowsAccessFromFrame(exec, static_cast<$className*>(thisObject)->impl()->frame()))\n"); 1790 } 1791 push(@implContent, " return;\n"); 1792 } 1793 1794 push(@implContent, " // Shadowing a built-in constructor\n"); 1795 1796 if ($interfaceName eq "DOMWindow") { 1797 push(@implContent, " static_cast<$className*>(thisObject)->putDirect(exec->globalData(), exec->propertyNames().constructor, value);\n"); 1798 } else { 1799 push(@implContent, " static_cast<$className*>(thisObject)->putDirect(exec->globalData(), Identifier(exec, \"$name\"), value);\n"); 1800 } 1801 push(@implContent, "}\n\n"); 1802 } 1803 } 1804 } 1805 1806 if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) && !$dataNode->extendedAttributes->{"CustomGetPropertyNames"}) { 1807 push(@implContent, "void ${className}::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)\n"); 1808 push(@implContent, "{\n"); 1809 if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) { 1810 push(@implContent, " for (unsigned i = 0; i < static_cast<${implClassName}*>(impl())->length(); ++i)\n"); 1811 push(@implContent, " propertyNames.add(Identifier::from(exec, i));\n"); 1812 } 1813 push(@implContent, " Base::getOwnPropertyNames(exec, propertyNames, mode);\n"); 1814 push(@implContent, "}\n\n"); 1815 } 1816 1817 if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { 1818 push(@implContent, "JSValue ${className}::getConstructor(ExecState* exec, JSGlobalObject* globalObject)\n{\n"); 1819 push(@implContent, " return getDOMConstructor<${className}Constructor>(exec, static_cast<JSDOMGlobalObject*>(globalObject));\n"); 1820 push(@implContent, "}\n\n"); 1821 } 1822 1823 # Functions 1824 if ($numFunctions > 0) { 1825 foreach my $function (@{$dataNode->functions}) { 1826 AddIncludesForType($function->signature->type); 1827 1828 my $functionName = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($function->signature->name); 1829 1830 if ($function->{overloads} && @{$function->{overloads}} > 1) { 1831 # Append a number to an overloaded method's name to make it unique: 1832 $functionName = $functionName . $function->{overloadIndex}; 1833 # Make this function static to avoid compiler warnings, since we 1834 # don't generate a prototype for it in the header. 1835 push(@implContent, "static "); 1836 } 1837 1838 my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementationFunction"} || $codeGenerator->WK_lcfirst($function->signature->name); 1839 1840 push(@implContent, "EncodedJSValue JSC_HOST_CALL ${functionName}(ExecState* exec)\n"); 1841 push(@implContent, "{\n"); 1842 1843 $implIncludes{"<runtime/Error.h>"} = 1; 1844 1845 if ($interfaceName eq "DOMWindow") { 1846 push(@implContent, " $className* castedThis = toJSDOMWindow(exec->hostThisValue().toThisObject(exec));\n"); 1847 push(@implContent, " if (!castedThis)\n"); 1848 push(@implContent, " return throwVMTypeError(exec);\n"); 1849 } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) { 1850 push(@implContent, " $className* castedThis = to${className}(exec->hostThisValue().toThisObject(exec));\n"); 1851 push(@implContent, " if (!castedThis)\n"); 1852 push(@implContent, " return throwVMTypeError(exec);\n"); 1853 } else { 1854 push(@implContent, " JSValue thisValue = exec->hostThisValue();\n"); 1855 push(@implContent, " if (!thisValue.inherits(&${className}::s_info))\n"); 1856 push(@implContent, " return throwVMTypeError(exec);\n"); 1857 push(@implContent, " $className* castedThis = static_cast<$className*>(asObject(thisValue));\n"); 1858 } 1859 1860 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && 1861 !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) { 1862 push(@implContent, " if (!castedThis->allowsAccessFrom(exec))\n"); 1863 push(@implContent, " return JSValue::encode(jsUndefined());\n"); 1864 } 1865 1866 if ($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"JSCCustom"}) { 1867 push(@implContent, " return JSValue::encode(castedThis->" . $functionImplementationName . "(exec));\n"); 1868 } else { 1869 push(@implContent, " $implType* imp = static_cast<$implType*>(castedThis->impl());\n"); 1870 if ($svgPropertyType) { 1871 push(@implContent, " if (imp->role() == AnimValRole) {\n"); 1872 push(@implContent, " setDOMException(exec, NO_MODIFICATION_ALLOWED_ERR);\n"); 1873 push(@implContent, " return JSValue::encode(jsUndefined());\n"); 1874 push(@implContent, " }\n"); 1875 push(@implContent, " $svgPropertyType& podImp = imp->propertyReference();\n"); 1876 } 1877 1878 my $numParameters = @{$function->parameters}; 1879 1880 my $requiresAllArguments = $function->signature->extendedAttributes->{"RequiresAllArguments"}; 1881 if ($requiresAllArguments) { 1882 my $numMandatoryParams = @{$function->parameters}; 1883 foreach my $param (reverse(@{$function->parameters})) { 1884 if ($param->extendedAttributes->{"Optional"}) { 1885 $numMandatoryParams--; 1886 } else { 1887 last; 1888 } 1889 } 1890 push(@implContent, " if (exec->argumentCount() < $numMandatoryParams)\n"); 1891 if ($requiresAllArguments eq "Raise") { 1892 push(@implContent, " return throwVMError(exec, createSyntaxError(exec, \"Not enough arguments\"));\n"); 1893 } else { 1894 push(@implContent, " return JSValue::encode(jsUndefined());\n"); 1895 } 1896 } 1897 1898 if (@{$function->raisesExceptions}) { 1899 push(@implContent, " ExceptionCode ec = 0;\n"); 1900 } 1901 1902 if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) { 1903 push(@implContent, " if (!checkNodeSecurity(exec, imp->getSVGDocument(" . (@{$function->raisesExceptions} ? "ec" : "") .")))\n"); 1904 push(@implContent, " return JSValue::encode(jsUndefined());\n"); 1905 $implIncludes{"JSDOMBinding.h"} = 1; 1906 } 1907 1908 if ($function->signature->name eq "addEventListener") { 1909 push(@implContent, GenerateEventListenerCall($className, "add")); 1910 } elsif ($function->signature->name eq "removeEventListener") { 1911 push(@implContent, GenerateEventListenerCall($className, "remove")); 1912 } else { 1913 my $argsIndex = 0; 1914 my $paramIndex = 0; 1915 my $functionString = (($svgPropertyOrListPropertyType and !$svgListPropertyType) ? "podImp." : "imp->") . $functionImplementationName . "("; 1916 my $hasOptionalArguments = 0; 1917 1918 if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) { 1919 push(@implContent, " RefPtr<ScriptArguments> scriptArguments(createScriptArguments(exec, $numParameters));\n"); 1920 push(@implContent, " size_t maxStackSize = imp->shouldCaptureFullStackTrace() ? ScriptCallStack::maxCallStackSizeToCapture : 1;\n"); 1921 push(@implContent, " RefPtr<ScriptCallStack> callStack(createScriptCallStack(exec, maxStackSize));\n"); 1922 $implIncludes{"ScriptArguments.h"} = 1; 1923 $implIncludes{"ScriptCallStack.h"} = 1; 1924 $implIncludes{"ScriptCallStackFactory.h"} = 1; 1925 } 1926 1927 my $callWith = $function->signature->extendedAttributes->{"CallWith"}; 1928 if ($callWith) { 1929 my $callWithArg = "COMPILE_ASSERT(false)"; 1930 if ($callWith eq "DynamicFrame") { 1931 push(@implContent, " Frame* dynamicFrame = toDynamicFrame(exec);\n"); 1932 push(@implContent, " if (!dynamicFrame)\n"); 1933 push(@implContent, " return JSValue::encode(jsUndefined());\n"); 1934 $callWithArg = "dynamicFrame"; 1935 } elsif ($callWith eq "ScriptState") { 1936 $callWithArg = "exec"; 1937 } elsif ($callWith eq "ScriptExecutionContext") { 1938 push(@implContent, " ScriptExecutionContext* scriptContext = static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext();\n"); 1939 push(@implContent, " if (!scriptContext)\n"); 1940 push(@implContent, " return JSValue::encode(jsUndefined());\n"); 1941 $callWithArg = "scriptContext"; 1942 } 1943 $functionString .= ", " if $paramIndex; 1944 $functionString .= $callWithArg; 1945 $paramIndex++; 1946 } 1947 1948 $implIncludes{"ExceptionCode.h"} = 1; 1949 $implIncludes{"JSDOMBinding.h"} = 1; 1950 foreach my $parameter (@{$function->parameters}) { 1951 # Optional callbacks should be treated differently, because they always have a default value (0), 1952 # and we can reduce the number of overloaded functions that take a different number of parameters. 1953 if ($parameter->extendedAttributes->{"Optional"} && !$parameter->extendedAttributes->{"Callback"}) { 1954 # Generate early call if there are enough parameters. 1955 if (!$hasOptionalArguments) { 1956 push(@implContent, "\n int argsCount = exec->argumentCount();\n"); 1957 $hasOptionalArguments = 1; 1958 } 1959 push(@implContent, " if (argsCount <= $argsIndex) {\n"); 1960 GenerateImplementationFunctionCall($function, $functionString, $paramIndex, " " x 2, $svgPropertyType, $implClassName); 1961 push(@implContent, " }\n\n"); 1962 } 1963 1964 my $name = $parameter->name; 1965 my $argType = $codeGenerator->StripModule($parameter->type); 1966 1967 if ($argType eq "XPathNSResolver") { 1968 push(@implContent, " RefPtr<XPathNSResolver> customResolver;\n"); 1969 push(@implContent, " XPathNSResolver* resolver = toXPathNSResolver(exec->argument($argsIndex));\n"); 1970 push(@implContent, " if (!resolver) {\n"); 1971 push(@implContent, " customResolver = JSCustomXPathNSResolver::create(exec, exec->argument($argsIndex));\n"); 1972 push(@implContent, " if (exec->hadException())\n"); 1973 push(@implContent, " return JSValue::encode(jsUndefined());\n"); 1974 push(@implContent, " resolver = customResolver.get();\n"); 1975 push(@implContent, " }\n"); 1976 } elsif ($parameter->extendedAttributes->{"Callback"}) { 1977 my $callbackClassName = GetCallbackClassName($argType); 1978 $implIncludes{"$callbackClassName.h"} = 1; 1979 if ($parameter->extendedAttributes->{"Optional"}) { 1980 push(@implContent, " RefPtr<$argType> $name;\n"); 1981 push(@implContent, " if (exec->argumentCount() > $argsIndex && !exec->argument($argsIndex).isNull() && !exec->argument($argsIndex).isUndefined()) {\n"); 1982 push(@implContent, " if (!exec->argument($argsIndex).isObject()) {\n"); 1983 push(@implContent, " setDOMException(exec, TYPE_MISMATCH_ERR);\n"); 1984 push(@implContent, " return JSValue::encode(jsUndefined());\n"); 1985 push(@implContent, " }\n"); 1986 push(@implContent, " $name = ${callbackClassName}::create(asObject(exec->argument($argsIndex)), castedThis->globalObject());\n"); 1987 push(@implContent, " }\n"); 1988 } else { 1989 push(@implContent, " if (exec->argumentCount() <= $argsIndex || !exec->argument($argsIndex).isObject()) {\n"); 1990 push(@implContent, " setDOMException(exec, TYPE_MISMATCH_ERR);\n"); 1991 push(@implContent, " return JSValue::encode(jsUndefined());\n"); 1992 push(@implContent, " }\n"); 1993 push(@implContent, " RefPtr<$argType> $name = ${callbackClassName}::create(asObject(exec->argument($argsIndex)), castedThis->globalObject());\n"); 1994 } 1995 } else { 1996 # If the "StrictTypeChecking" extended attribute is present, and the argument's type is an 1997 # interface type, then if the incoming value does not implement that interface, a TypeError 1998 # is thrown rather than silently passing NULL to the C++ code. 1999 # Per the Web IDL and ECMAScript semantics, incoming values can always be converted to both 2000 # strings and numbers, so do not throw TypeError if the argument is of these types. 2001 if ($function->signature->extendedAttributes->{"StrictTypeChecking"}) { 2002 $implIncludes{"<runtime/Error.h>"} = 1; 2003 2004 my $argValue = "exec->argument($argsIndex)"; 2005 if (!IsNativeType($argType)) { 2006 push(@implContent, " if (exec->argumentCount() > $argsIndex && !${argValue}.isUndefinedOrNull() && !${argValue}.inherits(&JS${argType}::s_info))\n"); 2007 push(@implContent, " return throwVMTypeError(exec);\n"); 2008 } 2009 } 2010 2011 push(@implContent, " " . GetNativeTypeFromSignature($parameter) . " $name(" . JSValueToNative($parameter, "exec->argument($argsIndex)") . ");\n"); 2012 2013 # If a parameter is "an index" and it's negative it should throw an INDEX_SIZE_ERR exception. 2014 # But this needs to be done in the bindings, because the type is unsigned and the fact that it 2015 # was negative will be lost by the time we're inside the DOM. 2016 if ($parameter->extendedAttributes->{"IsIndex"}) { 2017 push(@implContent, " if ($name < 0) {\n"); 2018 push(@implContent, " setDOMException(exec, INDEX_SIZE_ERR);\n"); 2019 push(@implContent, " return JSValue::encode(jsUndefined());\n"); 2020 push(@implContent, " }\n"); 2021 } 2022 2023 # Check if the type conversion succeeded. 2024 push(@implContent, " if (exec->hadException())\n"); 2025 push(@implContent, " return JSValue::encode(jsUndefined());\n"); 2026 2027 if ($codeGenerator->IsSVGTypeNeedingTearOff($argType) and not $implClassName =~ /List$/) { 2028 push(@implContent, " if (!$name) {\n"); 2029 push(@implContent, " setDOMException(exec, TYPE_MISMATCH_ERR);\n"); 2030 push(@implContent, " return JSValue::encode(jsUndefined());\n"); 2031 push(@implContent, " }\n"); 2032 } 2033 } 2034 2035 $functionString .= ", " if $paramIndex; 2036 2037 if ($argType eq "NodeFilter") { 2038 $functionString .= "$name.get()"; 2039 } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($argType) and not $implClassName =~ /List$/) { 2040 $functionString .= "$name->propertyReference()"; 2041 } else { 2042 $functionString .= $name; 2043 } 2044 $argsIndex++; 2045 $paramIndex++; 2046 } 2047 2048 if ($function->signature->extendedAttributes->{"NeedsUserGestureCheck"}) { 2049 $functionString .= ", " if $paramIndex; 2050 $functionString .= "processingUserGesture()"; 2051 $paramIndex++; 2052 } 2053 2054 push(@implContent, "\n"); 2055 GenerateImplementationFunctionCall($function, $functionString, $paramIndex, " ", $svgPropertyType, $implClassName); 2056 } 2057 } 2058 push(@implContent, "}\n\n"); 2059 2060 if ($function->{overloads} && @{$function->{overloads}} > 1 && $function->{overloadIndex} == @{$function->{overloads}}) { 2061 # Generate a function dispatching call to the rest of the overloads. 2062 GenerateOverloadedPrototypeFunction($function, $dataNode, $implClassName); 2063 } 2064 } 2065 } 2066 2067 if ($numConstants > 0) { 2068 push(@implContent, "// Constant getters\n\n"); 2069 2070 foreach my $constant (@{$dataNode->constants}) { 2071 my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name); 2072 2073 # FIXME: this casts into int to match our previous behavior which turned 0xFFFFFFFF in -1 for NodeFilter.SHOW_ALL 2074 push(@implContent, "JSValue ${getter}(ExecState* exec, JSValue, const Identifier&)\n"); 2075 push(@implContent, "{\n"); 2076 if ($constant->type eq "DOMString") { 2077 push(@implContent, " return jsStringOrNull(exec, String(" . $constant->value . "));\n"); 2078 } else { 2079 push(@implContent, " UNUSED_PARAM(exec);\n"); 2080 push(@implContent, " return jsNumber(static_cast<int>(" . $constant->value . "));\n"); 2081 } 2082 push(@implContent, "}\n\n"); 2083 } 2084 } 2085 2086 if ($dataNode->extendedAttributes->{"HasIndexGetter"}) { 2087 push(@implContent, "\nJSValue ${className}::indexGetter(ExecState* exec, JSValue slotBase, unsigned index)\n"); 2088 push(@implContent, "{\n"); 2089 push(@implContent, " ${className}* thisObj = static_cast<$className*>(asObject(slotBase));\n"); 2090 if (IndexGetterReturnsStrings($implClassName)) { 2091 $implIncludes{"KURL.h"} = 1; 2092 push(@implContent, " return jsStringOrNull(exec, thisObj->impl()->item(index));\n"); 2093 } else { 2094 push(@implContent, " return toJS(exec, thisObj->globalObject(), static_cast<$implClassName*>(thisObj->impl())->item(index));\n"); 2095 } 2096 push(@implContent, "}\n\n"); 2097 if ($interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") { 2098 $implIncludes{"JSNode.h"} = 1; 2099 $implIncludes{"Node.h"} = 1; 2100 } 2101 } 2102 2103 if ($dataNode->extendedAttributes->{"HasNumericIndexGetter"}) { 2104 push(@implContent, "\nJSValue ${className}::getByIndex(ExecState*, unsigned index)\n"); 2105 push(@implContent, "{\n"); 2106 push(@implContent, " return jsNumber(static_cast<$implClassName*>(impl())->item(index));\n"); 2107 push(@implContent, "}\n\n"); 2108 if ($interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") { 2109 $implIncludes{"JSNode.h"} = 1; 2110 $implIncludes{"Node.h"} = 1; 2111 } 2112 } 2113 2114 if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateToJS"}) and !$dataNode->extendedAttributes->{"CustomToJS"}) { 2115 if ($svgPropertyType) { 2116 push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* impl)\n"); 2117 } else { 2118 push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* impl)\n"); 2119 } 2120 push(@implContent, "{\n"); 2121 if ($svgPropertyType) { 2122 push(@implContent, " return wrap<$className, $implType>(exec, globalObject, impl);\n"); 2123 } else { 2124 push(@implContent, " return wrap<$className>(exec, globalObject, impl);\n"); 2125 } 2126 push(@implContent, "}\n\n"); 2127 } 2128 2129 if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateNativeConverter"}) and !$dataNode->extendedAttributes->{"CustomNativeConverter"}) { 2130 push(@implContent, "$implType* to${interfaceName}(JSC::JSValue value)\n"); 2131 push(@implContent, "{\n"); 2132 push(@implContent, " return value.inherits(&${className}::s_info) ? static_cast<$className*>(asObject(value))->impl() : 0"); 2133 push(@implContent, ";\n}\n"); 2134 } 2135 2136 push(@implContent, "\n}\n"); 2137 2138 my $conditionalString = GenerateConditionalString($dataNode); 2139 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; 2140 } 2141 2142 sub GenerateCallbackHeader 2143 { 2144 my $object = shift; 2145 my $dataNode = shift; 2146 2147 my $interfaceName = $dataNode->name; 2148 my $className = "JS$interfaceName"; 2149 2150 # - Add default header template and header protection 2151 push(@headerContentHeader, GenerateHeaderContentHeader($dataNode)); 2152 2153 $headerIncludes{"ActiveDOMCallback.h"} = 1; 2154 $headerIncludes{"$interfaceName.h"} = 1; 2155 $headerIncludes{"JSCallbackData.h"} = 1; 2156 $headerIncludes{"<wtf/Forward.h>"} = 1; 2157 2158 push(@headerContent, "\nnamespace WebCore {\n\n"); 2159 push(@headerContent, "class $className : public $interfaceName, public ActiveDOMCallback {\n"); 2160 push(@headerContent, "public:\n"); 2161 2162 # The static create() method. 2163 push(@headerContent, " static PassRefPtr<$className> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject)\n"); 2164 push(@headerContent, " {\n"); 2165 push(@headerContent, " return adoptRef(new $className(callback, globalObject));\n"); 2166 push(@headerContent, " }\n\n"); 2167 2168 # Destructor 2169 push(@headerContent, " virtual ~$className();\n"); 2170 2171 # Functions 2172 my $numFunctions = @{$dataNode->functions}; 2173 if ($numFunctions > 0) { 2174 push(@headerContent, "\n // Functions\n"); 2175 foreach my $function (@{$dataNode->functions}) { 2176 my @params = @{$function->parameters}; 2177 if (!$function->signature->extendedAttributes->{"Custom"} && 2178 !(GetNativeType($function->signature->type) eq "bool")) { 2179 push(@headerContent, " COMPILE_ASSERT(false)"); 2180 } 2181 2182 push(@headerContent, " virtual " . GetNativeType($function->signature->type) . " " . $function->signature->name . "("); 2183 2184 my @args = (); 2185 foreach my $param (@params) { 2186 push(@args, GetNativeType($param->type) . " " . $param->name); 2187 } 2188 push(@headerContent, join(", ", @args)); 2189 2190 push(@headerContent, ");\n"); 2191 } 2192 } 2193 2194 push(@headerContent, "\nprivate:\n"); 2195 2196 # Constructor 2197 push(@headerContent, " $className(JSC::JSObject* callback, JSDOMGlobalObject*);\n\n"); 2198 2199 # Private members 2200 push(@headerContent, " JSCallbackData* m_data;\n"); 2201 push(@headerContent, "};\n\n"); 2202 2203 push(@headerContent, "} // namespace WebCore\n\n"); 2204 my $conditionalString = GenerateConditionalString($dataNode); 2205 push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString; 2206 push(@headerContent, "#endif\n"); 2207 } 2208 2209 sub GenerateCallbackImplementation 2210 { 2211 my ($object, $dataNode) = @_; 2212 2213 my $interfaceName = $dataNode->name; 2214 my $className = "JS$interfaceName"; 2215 2216 # - Add default header template 2217 push(@implContentHeader, GenerateImplementationContentHeader($dataNode)); 2218 2219 $implIncludes{"ScriptExecutionContext.h"} = 1; 2220 $implIncludes{"<runtime/JSLock.h>"} = 1; 2221 $implIncludes{"<wtf/MainThread.h>"} = 1; 2222 2223 @implContent = (); 2224 2225 push(@implContent, "\nusing namespace JSC;\n\n"); 2226 push(@implContent, "namespace WebCore {\n\n"); 2227 2228 # Constructor 2229 push(@implContent, "${className}::${className}(JSObject* callback, JSDOMGlobalObject* globalObject)\n"); 2230 push(@implContent, " : ActiveDOMCallback(globalObject->scriptExecutionContext())\n"); 2231 push(@implContent, " , m_data(new JSCallbackData(callback, globalObject))\n"); 2232 push(@implContent, "{\n"); 2233 push(@implContent, "}\n\n"); 2234 2235 # Destructor 2236 push(@implContent, "${className}::~${className}()\n"); 2237 push(@implContent, "{\n"); 2238 push(@implContent, " ScriptExecutionContext* context = scriptExecutionContext();\n"); 2239 push(@implContent, " // When the context is destroyed, all tasks with a reference to a callback\n"); 2240 push(@implContent, " // should be deleted. So if the context is 0, we are on the context thread.\n"); 2241 push(@implContent, " if (!context || context->isContextThread())\n"); 2242 push(@implContent, " delete m_data;\n"); 2243 push(@implContent, " else\n"); 2244 push(@implContent, " context->postTask(DeleteCallbackDataTask::create(m_data));\n"); 2245 push(@implContent, "#ifndef NDEBUG\n"); 2246 push(@implContent, " m_data = 0;\n"); 2247 push(@implContent, "#endif\n"); 2248 push(@implContent, "}\n"); 2249 2250 # Functions 2251 my $numFunctions = @{$dataNode->functions}; 2252 if ($numFunctions > 0) { 2253 push(@implContent, "\n// Functions\n"); 2254 foreach my $function (@{$dataNode->functions}) { 2255 my @params = @{$function->parameters}; 2256 if ($function->signature->extendedAttributes->{"Custom"} || 2257 !(GetNativeType($function->signature->type) eq "bool")) { 2258 next; 2259 } 2260 2261 AddIncludesForType($function->signature->type); 2262 push(@implContent, "\n" . GetNativeType($function->signature->type) . " ${className}::" . $function->signature->name . "("); 2263 2264 my @args = (); 2265 foreach my $param (@params) { 2266 AddIncludesForType($param->type, 1); 2267 push(@args, GetNativeType($param->type) . " " . $param->name); 2268 } 2269 push(@implContent, join(", ", @args)); 2270 push(@implContent, ")\n"); 2271 2272 push(@implContent, "{\n"); 2273 push(@implContent, " if (!canInvokeCallback())\n"); 2274 push(@implContent, " return true;\n\n"); 2275 push(@implContent, " RefPtr<$className> protect(this);\n\n"); 2276 push(@implContent, " JSLock lock(SilenceAssertionsOnly);\n\n"); 2277 push(@implContent, " ExecState* exec = m_data->globalObject()->globalExec();\n"); 2278 push(@implContent, " MarkedArgumentBuffer args;\n"); 2279 2280 foreach my $param (@params) { 2281 my $paramName = $param->name; 2282 if ($param->type eq "DOMString") { 2283 push(@implContent, " args.append(jsString(exec, ${paramName}));\n"); 2284 } else { 2285 push(@implContent, " args.append(toJS(exec, ${paramName}));\n"); 2286 } 2287 } 2288 2289 push(@implContent, "\n bool raisedException = false;\n"); 2290 push(@implContent, " m_data->invokeCallback(args, &raisedException);\n"); 2291 push(@implContent, " return !raisedException;\n"); 2292 push(@implContent, "}\n"); 2293 } 2294 } 2295 2296 push(@implContent, "\n}\n"); 2297 my $conditionalString = GenerateConditionalString($dataNode); 2298 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; 2299 } 2300 2301 sub GenerateImplementationFunctionCall() 2302 { 2303 my $function = shift; 2304 my $functionString = shift; 2305 my $paramIndex = shift; 2306 my $indent = shift; 2307 my $svgPropertyType = shift; 2308 my $implClassName = shift; 2309 2310 if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) { 2311 $functionString .= ", " if $paramIndex; 2312 $paramIndex += 2; 2313 $functionString .= "scriptArguments, callStack"; 2314 } 2315 2316 if (@{$function->raisesExceptions}) { 2317 $functionString .= ", " if $paramIndex; 2318 $functionString .= "ec"; 2319 } 2320 $functionString .= ")"; 2321 2322 if ($function->signature->type eq "void") { 2323 push(@implContent, $indent . "$functionString;\n"); 2324 push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions}; 2325 2326 if ($svgPropertyType) { 2327 if (@{$function->raisesExceptions}) { 2328 push(@implContent, $indent . "if (!ec)\n"); 2329 push(@implContent, $indent . " imp->commitChange();\n"); 2330 } else { 2331 push(@implContent, $indent . "imp->commitChange();\n"); 2332 } 2333 } 2334 2335 push(@implContent, $indent . "return JSValue::encode(jsUndefined());\n"); 2336 } else { 2337 push(@implContent, "\n" . $indent . "JSC::JSValue result = " . NativeToJSValue($function->signature, 1, $implClassName, $functionString, "castedThis") . ";\n"); 2338 push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions}; 2339 2340 $callWith = $function->signature->extendedAttributes->{"CallWith"}; 2341 if ($callWith and $callWith eq "ScriptState") { 2342 push(@implContent, $indent . "if (exec->hadException())\n"); 2343 push(@implContent, $indent . " return JSValue::encode(jsUndefined());\n"); 2344 } 2345 2346 push(@implContent, $indent . "return JSValue::encode(result);\n"); 2347 } 2348 } 2349 2350 sub GetNativeTypeFromSignature 2351 { 2352 my $signature = shift; 2353 my $type = $codeGenerator->StripModule($signature->type); 2354 2355 if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) { 2356 # Special-case index arguments because we need to check that they aren't < 0. 2357 return "int"; 2358 } 2359 2360 return GetNativeType($type); 2361 } 2362 2363 my %nativeType = ( 2364 "CompareHow" => "Range::CompareHow", 2365 "DOMString" => "const String&", 2366 "DOMObject" => "ScriptValue", 2367 "NodeFilter" => "RefPtr<NodeFilter>", 2368 "SerializedScriptValue" => "RefPtr<SerializedScriptValue>", 2369 "IDBKey" => "RefPtr<IDBKey>", 2370 "boolean" => "bool", 2371 "double" => "double", 2372 "float" => "float", 2373 "short" => "short", 2374 "long" => "int", 2375 "unsigned long" => "unsigned", 2376 "unsigned short" => "unsigned short", 2377 "long long" => "long long", 2378 "unsigned long long" => "unsigned long long", 2379 "MediaQueryListListener" => "RefPtr<MediaQueryListListener>" 2380 ); 2381 2382 sub GetNativeType 2383 { 2384 my $type = shift; 2385 2386 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($type); 2387 return "${svgNativeType}*" if $svgNativeType; 2388 return $nativeType{$type} if exists $nativeType{$type}; 2389 2390 # For all other types, the native type is a pointer with same type name as the IDL type. 2391 return "${type}*"; 2392 } 2393 2394 sub GetSVGPropertyTypes 2395 { 2396 my $implType = shift; 2397 2398 my $svgPropertyType; 2399 my $svgListPropertyType; 2400 my $svgNativeType; 2401 2402 return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $implType =~ /SVG/; 2403 2404 $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implType); 2405 return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $svgNativeType; 2406 2407 # Append space to avoid compilation errors when using PassRefPtr<$svgNativeType> 2408 $svgNativeType = "$svgNativeType "; 2409 2410 my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implType); 2411 if ($svgNativeType =~ /SVGPropertyTearOff/) { 2412 $svgPropertyType = $svgWrappedNativeType; 2413 $headerIncludes{"$svgWrappedNativeType.h"} = 1; 2414 $headerIncludes{"SVGAnimatedPropertyTearOff.h"} = 1; 2415 } elsif ($svgNativeType =~ /SVGListPropertyTearOff/ or $svgNativeType =~ /SVGStaticListPropertyTearOff/) { 2416 $svgListPropertyType = $svgWrappedNativeType; 2417 $headerIncludes{"$svgWrappedNativeType.h"} = 1; 2418 $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1; 2419 } elsif ($svgNativeType =~ /SVGTransformListPropertyTearOff/) { 2420 $svgListPropertyType = $svgWrappedNativeType; 2421 $headerIncludes{"$svgWrappedNativeType.h"} = 1; 2422 $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1; 2423 $headerIncludes{"SVGTransformListPropertyTearOff.h"} = 1; 2424 } elsif ($svgNativeType =~ /SVGPathSegListPropertyTearOff/) { 2425 $svgListPropertyType = $svgWrappedNativeType; 2426 $headerIncludes{"$svgWrappedNativeType.h"} = 1; 2427 $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1; 2428 $headerIncludes{"SVGPathSegListPropertyTearOff.h"} = 1; 2429 } 2430 2431 return ($svgPropertyType, $svgListPropertyType, $svgNativeType); 2432 } 2433 2434 sub IsNativeType 2435 { 2436 my $type = shift; 2437 return exists $nativeType{$type}; 2438 } 2439 2440 sub JSValueToNative 2441 { 2442 my $signature = shift; 2443 my $value = shift; 2444 2445 my $type = $codeGenerator->StripModule($signature->type); 2446 2447 return "$value.toBoolean(exec)" if $type eq "boolean"; 2448 return "$value.toNumber(exec)" if $type eq "double"; 2449 return "$value.toFloat(exec)" if $type eq "float"; 2450 return "$value.toInt32(exec)" if $type eq "long" or $type eq "short"; 2451 return "$value.toUInt32(exec)" if $type eq "unsigned long" or $type eq "unsigned short"; 2452 return "static_cast<$type>($value.toInteger(exec))" if $type eq "long long" or $type eq "unsigned long long"; 2453 2454 return "valueToDate(exec, $value)" if $type eq "Date"; 2455 return "static_cast<Range::CompareHow>($value.toInt32(exec))" if $type eq "CompareHow"; 2456 2457 if ($type eq "DOMString") { 2458 return "valueToStringWithNullCheck(exec, $value)" if $signature->extendedAttributes->{"ConvertNullToNullString"} || $signature->extendedAttributes->{"Reflect"}; 2459 return "valueToStringWithUndefinedOrNullCheck(exec, $value)" if $signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"}; 2460 return "ustringToString($value.toString(exec))"; 2461 } 2462 2463 if ($type eq "DOMObject") { 2464 return "exec->globalData(), $value"; 2465 } 2466 2467 if ($type eq "NodeFilter") { 2468 $implIncludes{"JS$type.h"} = 1; 2469 return "to$type(exec->globalData(), $value)"; 2470 } 2471 2472 if ($type eq "MediaQueryListListener") { 2473 $implIncludes{"MediaQueryListListener.h"} = 1; 2474 return "MediaQueryListListener::create(ScriptValue(exec->globalData(), " . $value ."))"; 2475 } 2476 2477 if ($type eq "SerializedScriptValue" or $type eq "any") { 2478 $implIncludes{"SerializedScriptValue.h"} = 1; 2479 return "SerializedScriptValue::create(exec, $value)"; 2480 } 2481 2482 if ($type eq "IDBKey") { 2483 $implIncludes{"IDBBindingUtilities.h"} = 1; 2484 $implIncludes{"IDBKey.h"} = 1; 2485 return "createIDBKeyFromValue(exec, $value)"; 2486 } 2487 2488 $implIncludes{"HTMLOptionElement.h"} = 1 if $type eq "HTMLOptionElement"; 2489 $implIncludes{"JSCustomVoidCallback.h"} = 1 if $type eq "VoidCallback"; 2490 $implIncludes{"Event.h"} = 1 if $type eq "Event"; 2491 2492 # Default, assume autogenerated type conversion routines 2493 $implIncludes{"JS$type.h"} = 1; 2494 return "to$type($value)"; 2495 } 2496 2497 sub NativeToJSValue 2498 { 2499 my $signature = shift; 2500 my $inFunctionCall = shift; 2501 my $implClassName = shift; 2502 my $value = shift; 2503 my $thisValue = shift; 2504 2505 my $type = $codeGenerator->StripModule($signature->type); 2506 2507 return "jsBoolean($value)" if $type eq "boolean"; 2508 2509 # Need to check Date type before IsPrimitiveType(). 2510 if ($type eq "Date") { 2511 return "jsDateOrNull(exec, $value)"; 2512 } 2513 2514 if ($signature->extendedAttributes->{"Reflect"} and ($type eq "unsigned long" or $type eq "unsigned short")) { 2515 $value =~ s/getUnsignedIntegralAttribute/getIntegralAttribute/g; 2516 return "jsNumber(std::max(0, " . $value . "))"; 2517 } 2518 2519 if ($codeGenerator->IsPrimitiveType($type) or $type eq "DOMTimeStamp") { 2520 return "jsNumber($value)"; 2521 } 2522 2523 if ($codeGenerator->IsStringType($type)) { 2524 $implIncludes{"KURL.h"} = 1; 2525 my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"}; 2526 if (defined $conv) { 2527 return "jsStringOrNull(exec, $value)" if $conv eq "Null"; 2528 return "jsStringOrUndefined(exec, $value)" if $conv eq "Undefined"; 2529 return "jsStringOrFalse(exec, $value)" if $conv eq "False"; 2530 2531 die "Unknown value for ConvertNullStringTo extended attribute"; 2532 } 2533 $conv = $signature->extendedAttributes->{"ConvertScriptString"}; 2534 return "jsOwnedStringOrNull(exec, $value)" if $conv; 2535 $implIncludes{"<runtime/JSString.h>"} = 1; 2536 return "jsString(exec, $value)"; 2537 } 2538 2539 my $globalObject = "$thisValue->globalObject()"; 2540 2541 if ($type eq "CSSStyleDeclaration") { 2542 $implIncludes{"CSSMutableStyleDeclaration.h"} = 1; 2543 } 2544 2545 if ($type eq "NodeList") { 2546 $implIncludes{"NameNodeList.h"} = 1; 2547 } 2548 2549 if ($type eq "DOMObject") { 2550 if ($implClassName eq "Document") { 2551 $implIncludes{"JSCanvasRenderingContext2D.h"} = 1; 2552 } else { 2553 return "$value.jsValue();"; 2554 } 2555 } elsif ($type =~ /SVGPathSeg/) { 2556 $implIncludes{"JS$type.h"} = 1; 2557 $joinedName = $type; 2558 $joinedName =~ s/Abs|Rel//; 2559 $implIncludes{"$joinedName.h"} = 1; 2560 } elsif ($type eq "SerializedScriptValue" or $type eq "any") { 2561 $implIncludes{"SerializedScriptValue.h"} = 1; 2562 return "$value ? $value->deserialize(exec, castedThis->globalObject()) : jsNull()"; 2563 } else { 2564 # Default, include header with same name. 2565 $implIncludes{"JS$type.h"} = 1; 2566 $implIncludes{"$type.h"} = 1 if not $codeGenerator->AvoidInclusionOfType($type); 2567 } 2568 2569 return $value if $codeGenerator->IsSVGAnimatedType($type); 2570 2571 if ($signature->extendedAttributes->{"ReturnsNew"}) { 2572 return "toJSNewlyCreated(exec, $globalObject, WTF::getPtr($value))"; 2573 } 2574 2575 if ($codeGenerator->IsSVGAnimatedType($implClassName)) { 2576 # Convert from abstract SVGProperty to real type, so the right toJS() method can be invoked. 2577 $value = "static_cast<" . GetNativeType($type) . ">($value)"; 2578 } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($type) and not $implClassName =~ /List$/) { 2579 my $tearOffType = $codeGenerator->GetSVGTypeNeedingTearOff($type); 2580 if ($codeGenerator->IsSVGTypeWithWritablePropertiesNeedingTearOff($type) and $inFunctionCall eq 0 and not defined $signature->extendedAttributes->{"Immutable"}) { 2581 my $getter = $value; 2582 $getter =~ s/imp\.//; 2583 $getter =~ s/imp->//; 2584 $getter =~ s/\(\)//; 2585 my $updateMethod = "&${implClassName}::update" . $codeGenerator->WK_ucfirst($getter); 2586 2587 my $selfIsTearOffType = $codeGenerator->IsSVGTypeNeedingTearOff($implClassName); 2588 if ($selfIsTearOffType) { 2589 $implIncludes{"SVGStaticPropertyWithParentTearOff.h"} = 1; 2590 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyWithParentTearOff<$implClassName, /; 2591 2592 if ($value =~ /matrix/ and $implClassName eq "SVGTransform") { 2593 # SVGTransform offers a matrix() method for internal usage that returns an AffineTransform 2594 # and a svgMatrix() method returning a SVGMatrix, used for the bindings. 2595 $value =~ s/matrix/svgMatrix/; 2596 } 2597 2598 $value = "${tearOffType}::create(castedThis->impl(), $value, $updateMethod)"; 2599 } else { 2600 $implIncludes{"SVGStaticPropertyTearOff.h"} = 1; 2601 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyTearOff<$implClassName, /; 2602 $value = "${tearOffType}::create(imp, $value, $updateMethod)"; 2603 } 2604 } elsif ($tearOffType =~ /SVGStaticListPropertyTearOff/) { 2605 my $extraImp = "GetOwnerElementForType<$implClassName, IsDerivedFromSVGElement<$implClassName>::value>::ownerElement(imp), "; 2606 $value = "${tearOffType}::create($extraImp$value)"; 2607 } elsif (not $tearOffType =~ /SVG(Point|PathSeg)List/) { 2608 $value = "${tearOffType}::create($value)"; 2609 } 2610 } 2611 2612 return "toJS(exec, $globalObject, WTF::getPtr($value))"; 2613 } 2614 2615 sub ceilingToPowerOf2 2616 { 2617 my ($size) = @_; 2618 2619 my $powerOf2 = 1; 2620 while ($size > $powerOf2) { 2621 $powerOf2 <<= 1; 2622 } 2623 2624 return $powerOf2; 2625 } 2626 2627 # Internal Helper 2628 sub GenerateHashTable 2629 { 2630 my $object = shift; 2631 2632 my $name = shift; 2633 my $size = shift; 2634 my $keys = shift; 2635 my $specials = shift; 2636 my $value1 = shift; 2637 my $value2 = shift; 2638 my $conditionals = shift; 2639 2640 # Generate size data for compact' size hash table 2641 2642 my @table = (); 2643 my @links = (); 2644 2645 my $compactSize = ceilingToPowerOf2($size * 2); 2646 2647 my $maxDepth = 0; 2648 my $collisions = 0; 2649 my $numEntries = $compactSize; 2650 2651 my $i = 0; 2652 foreach (@{$keys}) { 2653 my $depth = 0; 2654 my $h = $object->GenerateHashValue($_) % $numEntries; 2655 2656 while (defined($table[$h])) { 2657 if (defined($links[$h])) { 2658 $h = $links[$h]; 2659 $depth++; 2660 } else { 2661 $collisions++; 2662 $links[$h] = $compactSize; 2663 $h = $compactSize; 2664 $compactSize++; 2665 } 2666 } 2667 2668 $table[$h] = $i; 2669 2670 $i++; 2671 $maxDepth = $depth if ($depth > $maxDepth); 2672 } 2673 2674 # Start outputing the hashtables 2675 my $nameEntries = "${name}Values"; 2676 $nameEntries =~ s/:/_/g; 2677 2678 if (($name =~ /Prototype/) or ($name =~ /Constructor/)) { 2679 my $type = $name; 2680 my $implClass; 2681 2682 if ($name =~ /Prototype/) { 2683 $type =~ s/Prototype.*//; 2684 $implClass = $type; $implClass =~ s/Wrapper$//; 2685 push(@implContent, "/* Hash table for prototype */\n"); 2686 } else { 2687 $type =~ s/Constructor.*//; 2688 $implClass = $type; $implClass =~ s/Constructor$//; 2689 push(@implContent, "/* Hash table for constructor */\n"); 2690 } 2691 } else { 2692 push(@implContent, "/* Hash table */\n"); 2693 } 2694 2695 # Dump the hash table 2696 my $count = scalar @{$keys} + 1; 2697 push(@implContent, "#if ENABLE(JIT)\n"); 2698 push(@implContent, "#define THUNK_GENERATOR(generator) , generator\n"); 2699 push(@implContent, "#else\n"); 2700 push(@implContent, "#define THUNK_GENERATOR(generator)\n"); 2701 push(@implContent, "#endif\n"); 2702 push(@implContent, "\nstatic const HashTableValue $nameEntries\[$count\] =\n\{\n"); 2703 $i = 0; 2704 foreach my $key (@{$keys}) { 2705 my $conditional; 2706 my $targetType; 2707 2708 if ($conditionals) { 2709 $conditional = $conditionals->{$key}; 2710 } 2711 if ($conditional) { 2712 my $conditionalString = GenerateConditionalStringFromAttributeValue($conditional); 2713 push(@implContent, "#if ${conditionalString}\n"); 2714 } 2715 2716 if ("@$specials[$i]" =~ m/Function/) { 2717 $targetType = "static_cast<NativeFunction>"; 2718 } else { 2719 $targetType = "static_cast<PropertySlot::GetValueFunc>"; 2720 } 2721 push(@implContent, " { \"$key\", @$specials[$i], (intptr_t)" . $targetType . "(@$value1[$i]), (intptr_t)@$value2[$i] THUNK_GENERATOR(0) },\n"); 2722 if ($conditional) { 2723 push(@implContent, "#endif\n"); 2724 } 2725 ++$i; 2726 } 2727 push(@implContent, " { 0, 0, 0, 0 THUNK_GENERATOR(0) }\n"); 2728 push(@implContent, "};\n\n"); 2729 push(@implContent, "#undef THUNK_GENERATOR\n"); 2730 my $compactSizeMask = $numEntries - 1; 2731 push(@implContent, "static JSC_CONST_HASHTABLE HashTable $name = { $compactSize, $compactSizeMask, $nameEntries, 0 };\n"); 2732 } 2733 2734 # Internal helper 2735 sub GenerateHashValue 2736 { 2737 my $object = shift; 2738 2739 @chars = split(/ */, $_[0]); 2740 2741 # This hash is designed to work on 16-bit chunks at a time. But since the normal case 2742 # (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they 2743 # were 16-bit chunks, which should give matching results 2744 2745 my $EXP2_32 = 4294967296; 2746 2747 my $hash = 0x9e3779b9; 2748 my $l = scalar @chars; #I wish this was in Ruby --- Maks 2749 my $rem = $l & 1; 2750 $l = $l >> 1; 2751 2752 my $s = 0; 2753 2754 # Main loop 2755 for (; $l > 0; $l--) { 2756 $hash += ord($chars[$s]); 2757 my $tmp = leftShift(ord($chars[$s+1]), 11) ^ $hash; 2758 $hash = (leftShift($hash, 16)% $EXP2_32) ^ $tmp; 2759 $s += 2; 2760 $hash += $hash >> 11; 2761 $hash %= $EXP2_32; 2762 } 2763 2764 # Handle end case 2765 if ($rem != 0) { 2766 $hash += ord($chars[$s]); 2767 $hash ^= (leftShift($hash, 11)% $EXP2_32); 2768 $hash += $hash >> 17; 2769 } 2770 2771 # Force "avalanching" of final 127 bits 2772 $hash ^= leftShift($hash, 3); 2773 $hash += ($hash >> 5); 2774 $hash = ($hash% $EXP2_32); 2775 $hash ^= (leftShift($hash, 2)% $EXP2_32); 2776 $hash += ($hash >> 15); 2777 $hash = $hash% $EXP2_32; 2778 $hash ^= (leftShift($hash, 10)% $EXP2_32); 2779 2780 # this avoids ever returning a hash code of 0, since that is used to 2781 # signal "hash not computed yet", using a value that is likely to be 2782 # effectively the same as 0 when the low bits are masked 2783 $hash = 0x80000000 if ($hash == 0); 2784 2785 return $hash; 2786 } 2787 2788 # Internal helper 2789 sub WriteData 2790 { 2791 if (defined($IMPL)) { 2792 # Write content to file. 2793 print $IMPL @implContentHeader; 2794 2795 my @includes = (); 2796 foreach my $include (keys %implIncludes) { 2797 my $checkType = $include; 2798 $checkType =~ s/\.h//; 2799 next if $codeGenerator->IsSVGAnimatedType($checkType); 2800 2801 $include = "\"$include\"" unless $include =~ /^["<]/; # " 2802 push @includes, $include; 2803 } 2804 foreach my $include (sort @includes) { 2805 print $IMPL "#include $include\n"; 2806 } 2807 2808 print $IMPL @implContent; 2809 close($IMPL); 2810 undef($IMPL); 2811 2812 @implContentHeader = (); 2813 @implContent = (); 2814 %implIncludes = (); 2815 } 2816 2817 if (defined($HEADER)) { 2818 # Write content to file. 2819 print $HEADER @headerContentHeader; 2820 2821 my @includes = (); 2822 foreach my $include (keys %headerIncludes) { 2823 $include = "\"$include\"" unless $include =~ /^["<]/; # " 2824 push @includes, $include; 2825 } 2826 foreach my $include (sort @includes) { 2827 print $HEADER "#include $include\n"; 2828 } 2829 2830 print $HEADER @headerContent; 2831 2832 @includes = (); 2833 foreach my $include (keys %headerTrailingIncludes) { 2834 $include = "\"$include\"" unless $include =~ /^["<]/; # " 2835 push @includes, $include; 2836 } 2837 foreach my $include (sort @includes) { 2838 print $HEADER "#include $include\n"; 2839 } 2840 2841 close($HEADER); 2842 undef($HEADER); 2843 2844 @headerContentHeader = (); 2845 @headerContent = (); 2846 %headerIncludes = (); 2847 %headerTrailingIncludes = (); 2848 } 2849 2850 if (defined($DEPS)) { 2851 # Write dependency file. 2852 print $DEPS @depsContent; 2853 close($DEPS); 2854 undef($DEPS); 2855 2856 @depsContent = (); 2857 } 2858 } 2859 2860 sub GenerateConstructorDeclaration 2861 { 2862 my $outputArray = shift; 2863 my $className = shift; 2864 my $dataNode = shift; 2865 2866 my $constructorClassName = "${className}Constructor"; 2867 my $canConstruct = $dataNode->extendedAttributes->{"CanBeConstructed"}; 2868 my $callWith = $dataNode->extendedAttributes->{"CallWith"}; 2869 2870 push(@$outputArray, "class ${constructorClassName} : public DOMConstructorObject {\n"); 2871 push(@$outputArray, "public:\n"); 2872 push(@$outputArray, " ${constructorClassName}(JSC::ExecState*, JSDOMGlobalObject*);\n\n"); 2873 2874 push(@$outputArray, " virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n"); 2875 push(@$outputArray, " virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n"); 2876 push(@$outputArray, " static const JSC::ClassInfo s_info;\n"); 2877 2878 push(@$outputArray, " static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)\n"); 2879 push(@$outputArray, " {\n"); 2880 push(@$outputArray, " return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);\n"); 2881 push(@$outputArray, " }\n"); 2882 2883 push(@$outputArray, "protected:\n"); 2884 push(@$outputArray, " static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::ImplementsHasInstance | DOMConstructorObject::StructureFlags;\n"); 2885 2886 if ($canConstruct) { 2887 push(@$outputArray, " static JSC::EncodedJSValue JSC_HOST_CALL construct${className}(JSC::ExecState*);\n"); 2888 push(@$outputArray, " virtual JSC::ConstructType getConstructData(JSC::ConstructData&);\n"); 2889 } 2890 push(@$outputArray, "};\n\n"); 2891 } 2892 2893 sub GenerateConstructorDefinition 2894 { 2895 my $outputArray = shift; 2896 2897 my $className = shift; 2898 my $protoClassName = shift; 2899 my $interfaceName = shift; 2900 my $visibleClassName = shift; 2901 my $dataNode = shift; 2902 2903 my $constructorClassName = "${className}Constructor"; 2904 my $canConstruct = $dataNode->extendedAttributes->{"CanBeConstructed"}; 2905 my $customConstructFunction = $dataNode->extendedAttributes->{"CustomConstructFunction"}; 2906 my $callWith = $dataNode->extendedAttributes->{"CallWith"}; 2907 my $numberOfconstructParameters = $dataNode->extendedAttributes->{"ConstructorParameters"}; 2908 2909 push(@$outputArray, "const ClassInfo ${constructorClassName}::s_info = { \"${visibleClassName}Constructor\", &DOMConstructorObject::s_info, &${constructorClassName}Table, 0 };\n\n"); 2910 2911 push(@$outputArray, "${constructorClassName}::${constructorClassName}(ExecState* exec, JSDOMGlobalObject* globalObject)\n"); 2912 push(@$outputArray, " : DOMConstructorObject(${constructorClassName}::createStructure(globalObject->globalData(), globalObject->objectPrototype()), globalObject)\n"); 2913 push(@$outputArray, "{\n"); 2914 push(@$outputArray, " ASSERT(inherits(&s_info));\n"); 2915 if ($interfaceName eq "DOMWindow") { 2916 push(@$outputArray, " putDirect(exec->globalData(), exec->propertyNames().prototype, globalObject->prototype(), DontDelete | ReadOnly);\n"); 2917 } else { 2918 push(@$outputArray, " putDirect(exec->globalData(), exec->propertyNames().prototype, ${protoClassName}::self(exec, globalObject), DontDelete | ReadOnly);\n"); 2919 } 2920 push(@$outputArray, " putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(${numberOfconstructParameters}), ReadOnly | DontDelete | DontEnum);\n") if $numberOfconstructParameters; 2921 push(@$outputArray, "}\n\n"); 2922 2923 push(@$outputArray, "bool ${constructorClassName}::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n"); 2924 push(@$outputArray, "{\n"); 2925 push(@$outputArray, " return getStaticValueSlot<${constructorClassName}, JSDOMWrapper>(exec, &${constructorClassName}Table, this, propertyName, slot);\n"); 2926 push(@$outputArray, "}\n\n"); 2927 2928 push(@$outputArray, "bool ${constructorClassName}::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\n"); 2929 push(@$outputArray, "{\n"); 2930 push(@$outputArray, " return getStaticValueDescriptor<${constructorClassName}, JSDOMWrapper>(exec, &${constructorClassName}Table, this, propertyName, descriptor);\n"); 2931 push(@$outputArray, "}\n\n"); 2932 2933 if ($canConstruct) { 2934 if (!$customConstructFunction) { 2935 push(@$outputArray, "EncodedJSValue JSC_HOST_CALL ${constructorClassName}::construct${className}(ExecState* exec)\n"); 2936 push(@$outputArray, "{\n"); 2937 my $constructorArg = ""; 2938 if ($callWith and $callWith eq "ScriptExecutionContext") { 2939 $constructorArg = "context"; 2940 push(@$outputArray, " ScriptExecutionContext* context = static_cast<${constructorClassName}*>(exec->callee())->scriptExecutionContext();\n"); 2941 push(@$outputArray, " if (!context)\n"); 2942 push(@$outputArray, " return throwVMError(exec, createReferenceError(exec, \"Reference error\"));\n"); 2943 } 2944 push(@$outputArray, " return JSValue::encode(asObject(toJS(exec, static_cast<${constructorClassName}*>(exec->callee())->globalObject(), ${interfaceName}::create(${constructorArg}))));\n"); 2945 push(@$outputArray, "}\n\n"); 2946 } 2947 2948 push(@$outputArray, "ConstructType ${constructorClassName}::getConstructData(ConstructData& constructData)\n"); 2949 push(@$outputArray, "{\n"); 2950 push(@$outputArray, " constructData.native.function = construct${className};\n"); 2951 push(@$outputArray, " return ConstructTypeHost;\n"); 2952 push(@$outputArray, "}\n\n"); 2953 } 2954 } 2955 2956 1; 2957