File indexing completed on 2024-05-12 15:37:27
0001 # 0002 # Copyright (C) 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> 0003 # Copyright (C) 2006 Anders Carlsson <andersca@mac.com> 0004 # Copyright (C) 2006, 2007 Samuel Weinig <sam@webkit.org> 0005 # Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org> 0006 # Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. 0007 # 0008 # This library is free software; you can redistribute it and/or 0009 # modify it under the terms of the GNU Library General Public 0010 # License as published by the Free Software Foundation; either 0011 # version 2 of the License, or (at your option) any later version. 0012 # 0013 # This library is distributed in the hope that it will be useful, 0014 # but WITHOUT ANY WARRANTY; without even the implied warranty of 0015 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0016 # Library General Public License for more details. 0017 # 0018 # You should have received a copy of the GNU Library General Public License 0019 # aint with this library; see the file COPYING.LIB. If not, write to 0020 # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0021 # Boston, MA 02110-1301, USA. 0022 0023 package CodeGeneratorJS; 0024 0025 use File::stat; 0026 0027 my $module = ""; 0028 my $outputDir = ""; 0029 0030 my @headerContent = (); 0031 my @implContentHeader = (); 0032 my @implContent = (); 0033 my %implIncludes = (); 0034 0035 # Default .h template 0036 my $headerTemplate = << "EOF"; 0037 /* 0038 This file has been generated by generate-bindings.pl. DO NOT MODIFY! 0039 0040 This library is free software; you can redistribute it and/or 0041 modify it under the terms of the GNU Library General Public 0042 License as published by the Free Software Foundation; either 0043 version 2 of the License, or (at your option) any later version. 0044 0045 This library is distributed in the hope that it will be useful, 0046 but WITHOUT ANY WARRANTY; without even the implied warranty of 0047 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0048 Library General Public License for more details. 0049 0050 You should have received a copy of the GNU Library General Public License 0051 along with this library; see the file COPYING.LIB. If not, write to 0052 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0053 Boston, MA 02110-1301, USA. 0054 */ 0055 EOF 0056 0057 # Default constructor 0058 sub new 0059 { 0060 my $object = shift; 0061 my $reference = { }; 0062 0063 $codeGenerator = shift; 0064 $outputDir = shift; 0065 0066 bless($reference, $object); 0067 return $reference; 0068 } 0069 0070 sub finish 0071 { 0072 my $object = shift; 0073 0074 # Commit changes! 0075 $object->WriteData(); 0076 } 0077 0078 sub leftShift($$) { 0079 my ($value, $distance) = @_; 0080 return (($value << $distance) & 0xFFFFFFFF); 0081 } 0082 0083 # Uppercase the first letter, while respecting WebKit style guidelines. 0084 # E.g., xmlEncoding becomes XMLEncoding, but xmlllang becomes Xmllang. 0085 sub WK_ucfirst 0086 { 0087 my $param = shift; 0088 my $ret = ucfirst($param); 0089 $ret =~ s/Xml/XML/ if $ret =~ /^Xml[^a-z]/; 0090 return $ret; 0091 } 0092 0093 # Params: 'domClass' struct 0094 sub GenerateInterface 0095 { 0096 my $object = shift; 0097 my $dataNode = shift; 0098 my $defines = shift; 0099 0100 # Start actual generation 0101 $object->GenerateHeader($dataNode); 0102 $object->GenerateImplementation($dataNode); 0103 0104 my $name = $dataNode->name; 0105 0106 # Open files for writing 0107 my $headerFileName = "$outputDir/JS$name.h"; 0108 my $implFileName = "$outputDir/JS$name.cpp"; 0109 0110 open($IMPL, ">$implFileName") || die "Couldn't open file $implFileName"; 0111 open($HEADER, ">$headerFileName") || die "Couldn't open file $headerFileName"; 0112 } 0113 0114 # Params: 'idlDocument' struct 0115 sub GenerateModule 0116 { 0117 my $object = shift; 0118 my $dataNode = shift; 0119 0120 $module = $dataNode->module; 0121 } 0122 0123 sub GetParentClassName 0124 { 0125 my $dataNode = shift; 0126 0127 return $dataNode->extendedAttributes->{"LegacyParent"} if $dataNode->extendedAttributes->{"LegacyParent"}; 0128 return "KJS::DOMObject" if @{$dataNode->parents} eq 0; 0129 return "JS" . $codeGenerator->StripModule($dataNode->parents(0)); 0130 } 0131 0132 sub GetLegacyHeaderIncludes 0133 { 0134 my $legacyParent = shift; 0135 0136 return "#include \"JSHTMLInputElementBase.h\"\n\n" if $legacyParent eq "JSHTMLInputElementBase"; 0137 return "#include \"kjs_window.h\"\n\n" if $legacyParent eq "KJS::Window"; 0138 return "#include \"kjs_events.h\"\n\n" if $module eq "events"; 0139 return "#include \"kjs_css.h\"\n\n" if $module eq "css"; 0140 return "#include \"kjs_html.h\"\n\n" if $module eq "html"; 0141 0142 die "Don't know what headers to include for module $module"; 0143 } 0144 0145 sub AvoidInclusionOfType 0146 { 0147 my $type = shift; 0148 0149 # Special case: SVGRect.h / SVGPoint.h / SVGNumber.h / SVGMatrix.h do not exist. 0150 return 1 if $type eq "SVGRect" or $type eq "SVGPoint" or $type eq "SVGNumber" or $type eq "SVGMatrix"; 0151 return 0; 0152 } 0153 0154 sub UsesManualToJSImplementation 0155 { 0156 my $type = shift; 0157 0158 return 1 if $type eq "Node" or $type eq "Document" or $type eq "HTMLCollection" or $type eq "SVGPathSeg" or $type eq "StyleSheet" or $type eq "CSSRule" or $type eq "CSSValue" or $type eq "Event"; 0159 return 0; 0160 } 0161 0162 sub IndexGetterReturnsStrings 0163 { 0164 my $type = shift; 0165 0166 return 1 if $type eq "CSSStyleDeclaration" or $type eq "MediaList"; 0167 return 0; 0168 } 0169 0170 sub CreateSVGContextInterfaceName 0171 { 0172 my $type = shift; 0173 0174 return $type if $codeGenerator->IsSVGAnimatedType($type); 0175 return "SVGPathSeg" if $type =~ /^SVGPathSeg/ and $type ne "SVGPathSegList"; 0176 0177 return ""; 0178 } 0179 0180 sub AddIncludesForType 0181 { 0182 my $type = $codeGenerator->StripModule(shift); 0183 0184 # When we're finished with the one-file-per-class 0185 # reorganization, we won't need these special cases. 0186 if ($codeGenerator->IsPrimitiveType($type) or AvoidInclusionOfType($type) 0187 or $type eq "DOMString" or $type eq "KJS::DOMObject" or $type eq "RGBColor") { 0188 } elsif ($type =~ /SVGPathSeg/) { 0189 $joinedName = $type; 0190 $joinedName =~ s/Abs|Rel//; 0191 $implIncludes{"${joinedName}.h"} = 1; 0192 } elsif ($type eq "XPathNSResolver") { 0193 $implIncludes{"JSXPathNSResolver.h"} = 1; 0194 $implIncludes{"JSCustomXPathNSResolver.h"} = 1; 0195 } else { 0196 # default, include the same named file 0197 $implIncludes{"${type}.h"} = 1; 0198 } 0199 0200 # additional includes (things needed to compile the bindings but not the header) 0201 0202 if ($type eq "CanvasRenderingContext2D") { 0203 $implIncludes{"CanvasGradient.h"} = 1; 0204 $implIncludes{"CanvasPattern.h"} = 1; 0205 $implIncludes{"CanvasStyle.h"} = 1; 0206 } 0207 0208 if ($type eq "CanvasGradient" or $type eq "XPathNSResolver") { 0209 $implIncludes{"PlatformString.h"} = 1; 0210 } 0211 } 0212 0213 sub AddIncludesForSVGAnimatedType 0214 { 0215 my $type = shift; 0216 $type =~ s/SVGAnimated//; 0217 0218 if ($type eq "Point" or $type eq "Rect") { 0219 $implIncludes{"Float$type.h"} = 1; 0220 } elsif ($type eq "String") { 0221 $implIncludes{"PlatformString.h"} = 1; 0222 } 0223 } 0224 0225 sub AddClassForwardIfNeeded 0226 { 0227 my $implClassName = shift; 0228 0229 # SVGAnimatedLength/Number/etc.. are typedefs to SVGAnimtatedTemplate, so don't use class forwards for them! 0230 push(@headerContent, "class $implClassName;\n\n") unless $codeGenerator->IsSVGAnimatedType($implClassName); 0231 } 0232 0233 sub IsSVGTypeNeedingContextParameter 0234 { 0235 my $implClassName = shift; 0236 0237 if ($implClassName =~ /SVG/ and not $implClassName =~ /Element/) { 0238 return 1 unless $implClassName =~ /SVGPaint/ or $implClassName =~ /SVGColor/ or $implClassName =~ /SVGDocument/; 0239 } 0240 0241 return 0; 0242 } 0243 0244 sub HashValueForClassAndName 0245 { 0246 my $class = shift; 0247 my $name = shift; 0248 0249 # SVG Filter enums live in WebCore namespace (platform/graphics/) 0250 if ($class =~ /^SVGFE*/ or $class =~ /^SVGComponentTransferFunctionElement$/) { 0251 return "khtml::$name"; 0252 } 0253 0254 return "${class}::$name"; 0255 } 0256 0257 sub GenerateHeader 0258 { 0259 my $object = shift; 0260 my $dataNode = shift; 0261 0262 my $interfaceName = $dataNode->name; 0263 my $className = "JS$interfaceName"; 0264 my $implClassName = $interfaceName; 0265 0266 # We only support multiple parents with SVG (for now). 0267 if (@{$dataNode->parents} > 1) { 0268 die "A class can't have more than one parent" unless $interfaceName =~ /SVG/; 0269 $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode); 0270 } 0271 0272 my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"}; 0273 my $hasRealParent = @{$dataNode->parents} > 0; 0274 my $hasParent = $hasLegacyParent || $hasRealParent; 0275 my $parentClassName = GetParentClassName($dataNode); 0276 my $conditional = $dataNode->extendedAttributes->{"Conditional"}; 0277 0278 # - Add default header template 0279 @headerContent = split("\r", $headerTemplate); 0280 0281 # - Add header protection 0282 push(@headerContent, "\n#ifndef $className" . "_h"); 0283 push(@headerContent, "\n#define $className" . "_h\n\n"); 0284 0285 my $conditionalString; 0286 if ($conditional) { 0287 $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; 0288 push(@headerContent, "\n#if ${conditionalString}\n\n"); 0289 } 0290 0291 if (exists $dataNode->extendedAttributes->{"LegacyParent"}) { 0292 push(@headerContent, GetLegacyHeaderIncludes($dataNode->extendedAttributes->{"LegacyParent"})); 0293 } else { 0294 if ($hasParent) { 0295 push(@headerContent, "#include \"$parentClassName.h\"\n"); 0296 } else { 0297 push(@headerContent, "#include \"kjs_binding.h\"\n"); 0298 } 0299 } 0300 0301 # Get correct pass/store types respecting PODType flag 0302 my $podType = $dataNode->extendedAttributes->{"PODType"}; 0303 my $passType = $podType ? "JSSVGPODTypeWrapper<$podType>*" : "$implClassName*"; 0304 push(@headerContent, "#include \"$podType.h\"\n") if $podType and $podType ne "float"; 0305 0306 push(@headerContent, "#include \"JSSVGPODTypeWrapper.h\"\n") if $podType; 0307 0308 my $numConstants = @{$dataNode->constants}; 0309 my $numAttributes = @{$dataNode->attributes}; 0310 my $numFunctions = @{$dataNode->functions}; 0311 0312 push(@headerContent, "\nnamespace khtml {\n\n"); 0313 0314 # Implementation class forward declaration 0315 AddClassForwardIfNeeded($implClassName) unless $podType; 0316 0317 # Class declaration 0318 push(@headerContent, "class $className : public $parentClassName {\n"); 0319 push(@headerContent, "public:\n"); 0320 0321 # Constructor 0322 if ($dataNode->extendedAttributes->{"DoNotCache"}) { 0323 push(@headerContent, " $className($passType);\n"); 0324 } else { 0325 if (IsSVGTypeNeedingContextParameter($implClassName)) { 0326 push(@headerContent, " $className(KJS::ExecState*, $passType, SVGElement* context);\n"); 0327 } else { 0328 push(@headerContent, " $className(KJS::ExecState*, $passType);\n"); 0329 } 0330 } 0331 0332 # Destructor 0333 if (!$hasParent or $interfaceName eq "Document") { 0334 push(@headerContent, " virtual ~$className();\n"); 0335 } 0336 0337 # Getters 0338 if ($numAttributes > 0 || $dataNode->extendedAttributes->{"GenerateConstructor"}) { 0339 push(@headerContent, " using KJS::JSObject::getOwnPropertySlot;\n"); 0340 push(@headerContent, " virtual bool getOwnPropertySlot(KJS::ExecState*, const KJS::Identifier&, KJS::PropertySlot&);\n"); 0341 push(@headerContent, " KJS::JSValue* getValueProperty(KJS::ExecState*, int token) const;\n"); 0342 if ($dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}) { 0343 push(@headerContent, " bool customGetOwnPropertySlot(KJS::ExecState*, const KJS::Identifier&, KJS::PropertySlot&);\n"); 0344 } 0345 } 0346 0347 # Check if we have any writable properties 0348 my $hasReadWriteProperties = 0; 0349 foreach (@{$dataNode->attributes}) { 0350 if ($_->type !~ /^readonly\ attribute$/) { 0351 $hasReadWriteProperties = 1; 0352 } 0353 } 0354 0355 if ($hasReadWriteProperties) { 0356 push(@headerContent, " using KJS::JSObject::put;\n"); 0357 push(@headerContent, " virtual void put(KJS::ExecState*, const KJS::Identifier&, KJS::JSValue*, int attr = KJS::None);\n"); 0358 push(@headerContent, " void putValueProperty(KJS::ExecState*, int, KJS::JSValue*, int attr);\n"); 0359 if ($dataNode->extendedAttributes->{"CustomPutFunction"}) { 0360 push(@headerContent, " bool customPut(KJS::ExecState*, const KJS::Identifier&, KJS::JSValue*, int attr);\n"); 0361 } 0362 } 0363 0364 # Class info 0365 push(@headerContent, " virtual const KJS::ClassInfo* classInfo() const { return &s_info; }\n"); 0366 push(@headerContent, " static const KJS::ClassInfo s_info;\n\n"); 0367 0368 # Custom mark function 0369 if ($dataNode->extendedAttributes->{"CustomMarkFunction"}) { 0370 push(@headerContent, " virtual void mark();\n\n"); 0371 } 0372 0373 # Custom pushEventHandlerScope function 0374 if ($dataNode->extendedAttributes->{"CustomPushEventHandlerScope"}) { 0375 push(@headerContent, " virtual void pushEventHandlerScope(KJS::ExecState*, KJS::ScopeChain&) const;\n\n"); 0376 } 0377 0378 # Custom call functions 0379 if ($dataNode->extendedAttributes->{"CustomCall"}) { 0380 push(@headerContent, " virtual KJS::JSValue* callAsFunction(KJS::ExecState*, KJS::JSObject*, const KJS::List&);\n"); 0381 push(@headerContent, " virtual bool implementsCall() const;\n\n"); 0382 } 0383 0384 # Constructor object getter 0385 if ($dataNode->extendedAttributes->{"GenerateConstructor"}) { 0386 push(@headerContent, " static KJS::JSValue* getConstructor(KJS::ExecState*);\n"); 0387 } 0388 0389 my $numCustomFunctions = 0; 0390 my $numCustomAttributes = 0; 0391 0392 # Attribute and function enums 0393 my $hasAttrFunctionEnum = ($numAttributes + $numFunctions > 0) || $dataNode->extendedAttributes->{"GenerateConstructor"}; 0394 push(@headerContent, " enum {\n") if ($hasAttrFunctionEnum); 0395 0396 if ($numAttributes > 0) { 0397 push(@headerContent, " // Attributes\n "); 0398 0399 my $i = -1; 0400 foreach (@{$dataNode->attributes}) { 0401 my $attribute = $_; 0402 0403 $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"Custom"}; 0404 $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"CustomGetter"}; 0405 $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"CustomSetter"}; 0406 0407 $i++; 0408 if ((($i % 4) eq 0) and ($i ne 0)) { 0409 push(@headerContent, "\n "); 0410 } 0411 0412 my $value = $attribute->signature->type =~ /Constructor$/ 0413 ? $attribute->signature->name . "ConstructorAttrNum" 0414 : WK_ucfirst($attribute->signature->name) . "AttrNum"; 0415 $value .= ", " if (($i < $numAttributes - 1) or (($i eq $numAttributes - 1) and (($numFunctions ne 0) or $dataNode->extendedAttributes->{"GenerateConstructor"}))); 0416 push(@headerContent, $value); 0417 } 0418 } 0419 0420 if ($dataNode->extendedAttributes->{"GenerateConstructor"}) { 0421 push(@headerContent, "\n\n") if $numAttributes > 0; 0422 push(@headerContent, " // The Constructor Attribute\n"); 0423 push(@headerContent, " ConstructorAttrNum" . ($numFunctions ? ", " : "")); 0424 } 0425 0426 if ($numFunctions > 0) { 0427 push(@headerContent, "\n\n") if $numAttributes > 0 || $dataNode->extendedAttributes->{"GenerateConstructor"}; 0428 push(@headerContent," // Functions\n "); 0429 0430 $i = -1; 0431 foreach my $function (@{$dataNode->functions}) { 0432 $i++; 0433 0434 push(@headerContent, "\n ") if ((($i % 4) eq 0) and ($i ne 0)); 0435 0436 $numCustomFunctions++ if $function->signature->extendedAttributes->{"Custom"}; 0437 0438 my $value = WK_ucfirst($function->signature->name) . "FuncNum"; 0439 $value .= ", " if ($i < $numFunctions - 1); 0440 push(@headerContent, $value); 0441 } 0442 } 0443 0444 0445 push(@headerContent, "\n };\n") if ($hasAttrFunctionEnum); 0446 0447 if ($numCustomAttributes > 0) { 0448 push(@headerContent, "\n // Custom attributes\n"); 0449 0450 foreach my $attribute (@{$dataNode->attributes}) { 0451 if ($attribute->signature->extendedAttributes->{"Custom"}) { 0452 push(@headerContent, " KJS::JSValue* " . $attribute->signature->name . "(KJS::ExecState*) const;\n"); 0453 if ($attribute->type !~ /^readonly/) { 0454 push(@headerContent, " void set" . WK_ucfirst($attribute->signature->name) . "(KJS::ExecState*, KJS::JSValue*);\n"); 0455 } 0456 } elsif ($attribute->signature->extendedAttributes->{"CustomGetter"}) { 0457 push(@headerContent, " KJS::JSValue* " . $attribute->signature->name . "(KJS::ExecState*) const;\n"); 0458 } elsif ($attribute->signature->extendedAttributes->{"CustomSetter"}) { 0459 if ($attribute->type !~ /^readonly/) { 0460 push(@headerContent, " void set" . WK_ucfirst($attribute->signature->name) . "(KJS::ExecState*, KJS::JSValue*);\n"); 0461 } 0462 } 0463 } 0464 } 0465 0466 if ($numCustomFunctions > 0) { 0467 push(@headerContent, "\n // Custom functions\n"); 0468 foreach my $function (@{$dataNode->functions}) { 0469 if ($function->signature->extendedAttributes->{"Custom"}) { 0470 push(@headerContent, " KJS::JSValue* " . $function->signature->name . "(KJS::ExecState*, const KJS::List&);\n"); 0471 } 0472 } 0473 } 0474 0475 # Index setter 0476 if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) { 0477 push(@headerContent, " void indexSetter(KJS::ExecState*, unsigned index, KJS::JSValue*, int attr);\n"); 0478 } 0479 0480 if (!$hasParent) { 0481 if ($podType) { 0482 push(@headerContent, " JSSVGPODTypeWrapper<$podType>* impl() const { return m_impl.get(); }\n"); 0483 push(@headerContent, " SVGElement* context() const { return m_context.get(); }\n\n"); 0484 push(@headerContent, "private:\n"); 0485 push(@headerContent, " RefPtr<SVGElement> m_context;\n"); 0486 push(@headerContent, " RefPtr<JSSVGPODTypeWrapper<$podType> > m_impl;\n"); 0487 } elsif (IsSVGTypeNeedingContextParameter($implClassName)) { 0488 push(@headerContent, " $implClassName* impl() const { return m_impl.get(); }\n"); 0489 push(@headerContent, " SVGElement* context() const { return m_context.get(); }\n\n"); 0490 push(@headerContent, "private:\n"); 0491 push(@headerContent, " RefPtr<SVGElement> m_context;\n"); 0492 push(@headerContent, " RefPtr<$implClassName > m_impl;\n"); 0493 } else { 0494 push(@headerContent, " $implClassName* impl() const { return m_impl.get(); }\n\n"); 0495 push(@headerContent, "private:\n"); 0496 push(@headerContent, " RefPtr<$implClassName> m_impl;\n"); 0497 } 0498 } elsif ($dataNode->extendedAttributes->{"GenerateNativeConverter"}) { 0499 push(@headerContent, " $implClassName* impl() const;\n"); 0500 } 0501 0502 # Index getter 0503 if ($dataNode->extendedAttributes->{"HasIndexGetter"}) { 0504 push(@headerContent, "private:\n"); 0505 push(@headerContent, " static KJS::JSValue* indexGetter(KJS::ExecState*, KJS::JSObject*, const KJS::Identifier&, const KJS::PropertySlot&);\n"); 0506 } 0507 # Name getter 0508 if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) { 0509 push(@headerContent, "private:\n"); 0510 push(@headerContent, " static bool canGetItemsForName(KJS::ExecState*, $implClassName*, const KJS::Identifier&);\n"); 0511 push(@headerContent, " static KJS::JSValue* nameGetter(KJS::ExecState*, KJS::JSObject*, const KJS::Identifier&, const KJS::PropertySlot&);\n"); 0512 } 0513 0514 push(@headerContent, "};\n\n"); 0515 0516 if (!$hasParent || $dataNode->extendedAttributes->{"GenerateToJS"}) { 0517 if ($podType) { 0518 push(@headerContent, "KJS::JSValue* toJS(KJS::ExecState*, JSSVGPODTypeWrapper<$podType>*, SVGElement* context);\n"); 0519 } elsif (IsSVGTypeNeedingContextParameter($implClassName)) { 0520 push(@headerContent, "KJS::JSValue* toJS(KJS::ExecState*, $passType, SVGElement* context);\n"); 0521 } elsif ($interfaceName eq "Node") { 0522 push(@headerContent, "KJS::JSValue* toJS(KJS::ExecState*, PassRefPtr<Node>);\n"); 0523 } else { 0524 push(@headerContent, "KJS::JSValue* toJS(KJS::ExecState*, $passType);\n"); 0525 } 0526 } 0527 if (!$hasParent || $dataNode->extendedAttributes->{"GenerateNativeConverter"}) { 0528 if ($podType) { 0529 push(@headerContent, "$podType to${interfaceName}(KJS::JSValue*);\n"); 0530 } else { 0531 push(@headerContent, "$implClassName* to${interfaceName}(KJS::JSValue*);\n"); 0532 } 0533 } 0534 push(@headerContent, "\n"); 0535 0536 # Add prototype declaration -- code adopted from the KJS_DEFINE_PROTOTYPE and KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE macros 0537 push(@headerContent, "class ${className}Prototype : public KJS::JSObject {\n"); 0538 push(@headerContent, "public:\n"); 0539 if ($dataNode->extendedAttributes->{"DoNotCache"}) { 0540 push(@headerContent, " static KJS::JSObject* self();\n"); 0541 } else { 0542 push(@headerContent, " static KJS::JSObject* self(KJS::ExecState* exec);\n"); 0543 } 0544 push(@headerContent, " virtual const KJS::ClassInfo* classInfo() const { return &s_info; }\n"); 0545 push(@headerContent, " static const KJS::ClassInfo s_info;\n"); 0546 if ($numFunctions > 0 || $numConstants > 0) { 0547 push(@headerContent, " using KJS::JSObject::getOwnPropertySlot;\n"); 0548 push(@headerContent, " bool getOwnPropertySlot(KJS::ExecState*, const KJS::Identifier&, KJS::PropertySlot&);\n"); 0549 } 0550 if ($numConstants ne 0) { 0551 push(@headerContent, " KJS::JSValue* getValueProperty(KJS::ExecState*, int token) const;\n"); 0552 } 0553 if ($dataNode->extendedAttributes->{"DoNotCache"}) { 0554 push(@headerContent, " ${className}Prototype() { }\n"); 0555 } else { 0556 push(@headerContent, " ${className}Prototype(KJS::ExecState* exec)\n"); 0557 if ($hasParent && $parentClassName ne "KJS::DOMNodeFilter") { 0558 push(@headerContent, " : KJS::JSObject(${parentClassName}Prototype::self(exec)) { }\n"); 0559 } else { 0560 push(@headerContent, " : KJS::JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()) { }\n"); 0561 } 0562 } 0563 0564 push(@headerContent, "};\n\n"); 0565 0566 if ($numFunctions > 0) { 0567 push(@headerContent, prototypeFunctionFor($className)); 0568 } 0569 0570 push(@headerContent, "} // namespace khtml\n\n"); 0571 push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditional; 0572 push(@headerContent, "#endif\n"); 0573 } 0574 0575 sub GenerateImplementation 0576 { 0577 my ($object, $dataNode) = @_; 0578 0579 my $interfaceName = $dataNode->name; 0580 my $className = "JS$interfaceName"; 0581 my $implClassName = $interfaceName; 0582 0583 my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"}; 0584 my $hasRealParent = @{$dataNode->parents} > 0; 0585 my $hasParent = $hasLegacyParent || $hasRealParent; 0586 my $parentClassName = GetParentClassName($dataNode); 0587 my $conditional = $dataNode->extendedAttributes->{"Conditional"}; 0588 0589 # - Add default header template 0590 @implContentHeader = split("\r", $headerTemplate); 0591 push(@implContentHeader, "\n#include <wtf/Platform.h>\n\n"); 0592 my $conditionalString; 0593 if ($conditional) { 0594 $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; 0595 push(@implContentHeader, "\n#if ${conditionalString}\n\n"); 0596 } 0597 0598 if ($className =~ /^JSSVG/) { 0599 push(@implContentHeader, "#include \"Document.h\"\n"); 0600 push(@implContentHeader, "#include \"Frame.h\"\n"); 0601 push(@implContentHeader, "#include \"SVGDocumentExtensions.h\"\n"); 0602 push(@implContentHeader, "#include \"SVGElement.h\"\n"); 0603 push(@implContentHeader, "#include \"SVGAnimatedTemplate.h\"\n"); 0604 0605 if ($className =~ /^JSSVGAnimated/) { 0606 AddIncludesForSVGAnimatedType($interfaceName); 0607 } 0608 } 0609 0610 push(@implContentHeader, "#include \"$className.h\"\n\n"); 0611 push(@implContentHeader, "#include <wtf/GetPtr.h>\n\n"); 0612 push(@implContentHeader, "#include <kjs/ExecState.h>\n\n"); 0613 push(@implContentHeader, "using namespace KJS;\n\n"); 0614 0615 AddIncludesForType($interfaceName); 0616 0617 @implContent = (); 0618 0619 push(@implContent, "\nusing namespace KJS;\n\n"); 0620 push(@implContent, "namespace khtml {\n\n"); 0621 0622 # - Add all attributes in a hashtable definition 0623 my $numAttributes = @{$dataNode->attributes}; 0624 $numAttributes++ if $dataNode->extendedAttributes->{"GenerateConstructor"}; 0625 0626 if ($numAttributes > 0) { 0627 my $hashSize = $numAttributes; 0628 my $hashName = $className . "Table"; 0629 0630 my @hashKeys = (); # ie. 'insertBefore' 0631 my @hashValues = (); # ie. 'JSNode::InsertBefore' 0632 my @hashSpecials = (); # ie. 'DontDelete|Function' 0633 my @hashParameters = (); # ie. '2' 0634 0635 foreach my $attribute (@{$dataNode->attributes}) { 0636 my $name = $attribute->signature->name; 0637 push(@hashKeys, $name); 0638 0639 my $value = $className . "::" . ($attribute->signature->type =~ /Constructor$/ 0640 ? $attribute->signature->name . "ConstructorAttrNum" 0641 : WK_ucfirst($attribute->signature->name) . "AttrNum"); 0642 push(@hashValues, $value); 0643 0644 my @specials = (); 0645 push(@specials, "DontDelete") unless $attribute->signature->extendedAttributes->{"Deletable"}; 0646 push(@specials, "DontEnum") if $attribute->signature->extendedAttributes->{"DontEnum"}; 0647 push(@specials, "ReadOnly") if $attribute->type =~ /readonly/; 0648 my $special = (@specials > 0) ? join("|", @specials) : "0"; 0649 push(@hashSpecials, $special); 0650 0651 my $numParameters = "0"; 0652 push(@hashParameters, $numParameters); 0653 } 0654 0655 if ($dataNode->extendedAttributes->{"GenerateConstructor"}) { 0656 push(@hashKeys, "constructor"); 0657 push(@hashValues, $className . "::ConstructorAttrNum"); 0658 push(@hashSpecials, "DontDelete|DontEnum|ReadOnly"); 0659 push(@hashParameters, "0"); 0660 } 0661 0662 $object->GenerateHashTable($hashName, $hashSize, 0663 \@hashKeys, \@hashValues, 0664 \@hashSpecials, \@hashParameters); 0665 } 0666 0667 my $numConstants = @{$dataNode->constants}; 0668 my $numFunctions = @{$dataNode->functions}; 0669 0670 # - Add all constants 0671 if ($dataNode->extendedAttributes->{"GenerateConstructor"}) { 0672 $hashSize = $numConstants; 0673 $hashName = $className . "ConstructorTable"; 0674 0675 @hashKeys = (); 0676 @hashValues = (); 0677 @hashSpecials = (); 0678 @hashParameters = (); 0679 0680 foreach my $constant (@{$dataNode->constants}) { 0681 my $name = $constant->name; 0682 push(@hashKeys, $name); 0683 0684 my $value = HashValueForClassAndName($implClassName, $name); 0685 push(@hashValues, $value); 0686 0687 my $special = "DontDelete|ReadOnly"; 0688 push(@hashSpecials, $special); 0689 0690 my $numParameters = 0; 0691 push(@hashParameters, $numParameters); 0692 } 0693 0694 $object->GenerateHashTable($hashName, $hashSize, 0695 \@hashKeys, \@hashValues, 0696 \@hashSpecials, \@hashParameters); 0697 0698 my $protoClassName; 0699 $protoClassName = "${className}Prototype"; 0700 0701 push(@implContent, constructorFor($className, $protoClassName, $interfaceName, $dataNode->extendedAttributes->{"CanBeConstructed"})); 0702 } 0703 0704 # - Add functions and constants to a hashtable definition 0705 $hashSize = $numFunctions + $numConstants; 0706 $hashName = $className . "PrototypeTable"; 0707 0708 @hashKeys = (); 0709 @hashValues = (); 0710 @hashSpecials = (); 0711 @hashParameters = (); 0712 0713 foreach my $constant (@{$dataNode->constants}) { 0714 my $name = $constant->name; 0715 push(@hashKeys, $name); 0716 0717 my $value = HashValueForClassAndName($implClassName, $name); 0718 push(@hashValues, $value); 0719 0720 my $special = "DontDelete|ReadOnly"; 0721 push(@hashSpecials, $special); 0722 0723 my $numParameters = 0; 0724 push(@hashParameters, $numParameters); 0725 } 0726 0727 foreach my $function (@{$dataNode->functions}) { 0728 my $name = $function->signature->name; 0729 push(@hashKeys, $name); 0730 0731 my $value = $className . "::" . WK_ucfirst($name) . "FuncNum"; 0732 push(@hashValues, $value); 0733 0734 my @specials = (); 0735 push(@specials, "DontDelete") unless $function->signature->extendedAttributes->{"Deletable"}; 0736 push(@specials, "DontEnum") if $function->signature->extendedAttributes->{"DontEnum"}; 0737 push(@specials, "Function"); 0738 my $special = (@specials > 0) ? join("|", @specials) : "0"; 0739 push(@hashSpecials, $special); 0740 0741 my $numParameters = @{$function->parameters}; 0742 push(@hashParameters, $numParameters); 0743 } 0744 0745 $object->GenerateHashTable($hashName, $hashSize, 0746 \@hashKeys, \@hashValues, 0747 \@hashSpecials, \@hashParameters); 0748 0749 push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${interfaceName}Prototype\", nullptr, &${className}PrototypeTable, nullptr };\n\n"); 0750 if ($dataNode->extendedAttributes->{"DoNotCache"}) { 0751 push(@implContent, "JSObject* ${className}Prototype::self()\n"); 0752 push(@implContent, "{\n"); 0753 push(@implContent, " return new ${className}Prototype();\n"); 0754 push(@implContent, "}\n\n"); 0755 } else { 0756 push(@implContent, "JSObject* ${className}Prototype::self(ExecState* exec)\n"); 0757 push(@implContent, "{\n"); 0758 push(@implContent, " return ::cacheGlobalObject<${className}Prototype>(exec, \"[[${className}.prototype]]\");\n"); 0759 push(@implContent, "}\n\n"); 0760 } 0761 if ($numConstants > 0 || $numFunctions > 0) { 0762 push(@implContent, "bool ${className}Prototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n"); 0763 push(@implContent, "{\n"); 0764 if ($numConstants eq 0) { 0765 push(@implContent, " return getStaticFunctionSlot<${className}PrototypeFunction, JSObject>(exec, &${className}PrototypeTable, this, propertyName, slot);\n"); 0766 } elsif ($numFunctions eq 0) { 0767 push(@implContent, " return getStaticValueSlot<${className}Prototype, JSObject>(exec, &${className}PrototypeTable, this, propertyName, slot);\n"); 0768 } else { 0769 push(@implContent, " return getStaticPropertySlot<${className}PrototypeFunction, ${className}Prototype, JSObject>(exec, &${className}PrototypeTable, this, propertyName, slot);\n"); 0770 } 0771 push(@implContent, "}\n\n"); 0772 } 0773 if ($numConstants ne 0) { 0774 push(@implContent, "JSValue* ${className}Prototype::getValueProperty(ExecState*, int token) const\n{\n"); 0775 push(@implContent, " // The token is the numeric value of its associated constant\n"); 0776 push(@implContent, " return jsNumber(token);\n}\n\n"); 0777 } 0778 0779 # - Initialize static ClassInfo object 0780 push(@implContent, "const ClassInfo $className" . "::s_info = { \"$interfaceName\", "); 0781 if ($hasParent) { 0782 push(@implContent, "&" . $parentClassName . "::s_info, "); 0783 } else { 0784 push(@implContent, "nullptr, "); 0785 } 0786 0787 if ($numAttributes > 0) { 0788 push(@implContent, "&${className}Table "); 0789 } else { 0790 push(@implContent, "nullptr "); 0791 } 0792 push(@implContent, ", nullptr };\n\n"); 0793 0794 # Get correct pass/store types respecting PODType flag 0795 my $podType = $dataNode->extendedAttributes->{"PODType"}; 0796 my $passType = $podType ? "JSSVGPODTypeWrapper<$podType>*" : "$implClassName*"; 0797 0798 # Constructor 0799 if ($dataNode->extendedAttributes->{"DoNotCache"}) { 0800 push(@implContent, "${className}::$className($passType impl)\n"); 0801 push(@implContent, " : $parentClassName(impl)\n"); 0802 } else { 0803 my $needsSVGContext = IsSVGTypeNeedingContextParameter($implClassName); 0804 if ($needsSVGContext) { 0805 push(@implContent, "${className}::$className(ExecState* exec, $passType impl, SVGElement* context)\n"); 0806 } else { 0807 push(@implContent, "${className}::$className(ExecState* exec, $passType impl)\n"); 0808 } 0809 0810 if ($hasParent) { 0811 if ($needsSVGContext and $parentClassName =~ /SVG/) { 0812 push(@implContent, " : $parentClassName(exec, impl, context)\n"); 0813 } else { 0814 push(@implContent, " : $parentClassName(exec, impl)\n"); 0815 } 0816 } else { 0817 if ($needsSVGContext) { 0818 push(@implContent, " : m_context(context)\n"); 0819 push(@implContent, " , m_impl(impl)\n"); 0820 } else { 0821 push(@implContent, " : m_impl(impl)\n"); 0822 } 0823 } 0824 } 0825 0826 if ($dataNode->extendedAttributes->{"DoNotCache"}) { 0827 push(@implContent, "{\n setPrototype(${className}Prototype::self());\n}\n\n"); 0828 } else { 0829 push(@implContent, "{\n setPrototype(${className}Prototype::self(exec));\n}\n\n"); 0830 } 0831 0832 # Destructor 0833 if (!$hasParent) { 0834 push(@implContent, "${className}::~$className()\n"); 0835 push(@implContent, "{\n"); 0836 0837 if ($interfaceName eq "Node") { 0838 push(@implContent, " ScriptInterpreter::forgetDOMNodeForDocument(m_impl->document(), m_impl.get());\n"); 0839 } else { 0840 if ($podType) { 0841 my $animatedType = $implClassName; 0842 $animatedType =~ s/SVG/SVGAnimated/; 0843 0844 # Special case for JSSVGNumber 0845 if ($codeGenerator->IsSVGAnimatedType($animatedType) and $podType ne "float") { 0846 push(@implContent, " JSSVGPODTypeWrapperCache<$podType, $animatedType>::forgetWrapper(m_impl.get());\n"); 0847 } 0848 } 0849 push(@implContent, " ScriptInterpreter::forgetDOMObject(m_impl.get());\n"); 0850 } 0851 0852 push(@implContent, "\n}\n\n"); 0853 } 0854 0855 # Document needs a special destructor because it's a special case for caching. It needs 0856 # its own special handling rather than relying on the caching that Node normally does. 0857 if ($interfaceName eq "Document") { 0858 push(@implContent, "${className}::~$className()\n"); 0859 push(@implContent, "{\n ScriptInterpreter::forgetDOMObject(static_cast<${implClassName}*>(impl()));\n}\n\n"); 0860 } 0861 0862 # Attributes 0863 if ($numAttributes ne 0) { 0864 push(@implContent, "bool ${className}::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n"); 0865 push(@implContent, "{\n"); 0866 0867 if ($interfaceName eq "NamedNodeMap" or $interfaceName eq "HTMLCollection") { 0868 push(@implContent, " JSValue* proto = prototype();\n"); 0869 push(@implContent, " if (proto->isObject() && static_cast<JSObject*>(proto)->hasProperty(exec, propertyName))\n"); 0870 push(@implContent, " return false;\n\n"); 0871 } 0872 0873 my $hasNameGetterGeneration = sub { 0874 push(@implContent, " if (canGetItemsForName(exec, static_cast<$implClassName*>(impl()), propertyName)) {\n"); 0875 push(@implContent, " slot.setCustom(this, nameGetter);\n"); 0876 push(@implContent, " return true;\n"); 0877 push(@implContent, " }\n"); 0878 $implIncludes{"AtomicString.h"} = 1; 0879 }; 0880 0881 if ($dataNode->extendedAttributes->{"HasOverridingNameGetter"}) { 0882 &$hasNameGetterGeneration(); 0883 } 0884 0885 my $requiresManualLookup = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasNameGetter"}; 0886 if ($requiresManualLookup) { 0887 push(@implContent, " const HashEntry* entry = Lookup::findEntry(&${className}Table, propertyName);\n"); 0888 push(@implContent, " if (entry) {\n"); 0889 push(@implContent, " slot.setStaticEntry(this, entry, staticValueGetter<$className>);\n"); 0890 push(@implContent, " return true;\n"); 0891 push(@implContent, " }\n"); 0892 } 0893 0894 if ($dataNode->extendedAttributes->{"HasIndexGetter"}) { 0895 push(@implContent, " bool ok;\n"); 0896 push(@implContent, " unsigned index = propertyName.toUInt32(&ok, false);\n"); 0897 push(@implContent, " if (ok && index < static_cast<$implClassName*>(impl())->length()) {\n"); 0898 push(@implContent, " slot.setCustomIndex(this, index, indexGetter);\n"); 0899 push(@implContent, " return true;\n"); 0900 push(@implContent, " }\n"); 0901 } 0902 0903 if ($dataNode->extendedAttributes->{"HasNameGetter"}) { 0904 &$hasNameGetterGeneration(); 0905 } 0906 0907 if ($dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}) { 0908 push(@implContent, " if (customGetOwnPropertySlot(exec, propertyName, slot))\n"); 0909 push(@implContent, " return true;\n"); 0910 } 0911 0912 if ($requiresManualLookup) { 0913 push(@implContent, " return ${parentClassName}::getOwnPropertySlot(exec, propertyName, slot);\n"); 0914 } else { 0915 push(@implContent, " return getStaticValueSlot<$className, $parentClassName>(exec, &${className}Table, this, propertyName, slot);\n"); 0916 } 0917 push(@implContent, "}\n\n"); 0918 0919 push(@implContent, "JSValue* ${className}::getValueProperty(ExecState* exec, int token) const\n{\n"); 0920 0921 push(@implContent, " switch (token) {\n"); 0922 0923 foreach my $attribute (@{$dataNode->attributes}) { 0924 my $name = $attribute->signature->name; 0925 0926 my $implClassNameForValueConversion = ""; 0927 if (!$podType and ($codeGenerator->IsSVGAnimatedType($implClassName) or $attribute->type !~ /^readonly/)) { 0928 $implClassNameForValueConversion = $implClassName; 0929 } 0930 0931 if ($attribute->signature->type =~ /Constructor$/) { 0932 push(@implContent, " case " . $name . "ConstructorAttrNum: {\n"); 0933 } else { 0934 push(@implContent, " case " . WK_ucfirst($name) . "AttrNum: {\n"); 0935 } 0936 0937 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) { 0938 push(@implContent, " if (!isSafeScript(exec))\n"); 0939 push(@implContent, " return jsUndefined();\n"); 0940 } 0941 0942 if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"CustomGetter"}) { 0943 push(@implContent, " return $name(exec);\n"); 0944 } elsif ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) { 0945 $implIncludes{"kjs_dom.h"} = 1; 0946 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(impl());\n\n"); 0947 push(@implContent, " return checkNodeSecurity(exec, imp->$name()) ? " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$name()") . " : jsUndefined();\n"); 0948 } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) { 0949 $implIncludes{"Document.h"} = 1; 0950 $implIncludes{"kjs_dom.h"} = 1; 0951 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(impl());\n\n"); 0952 push(@implContent, " return checkNodeSecurity(exec, imp->contentDocument()) ? " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$name()") . " : jsUndefined();\n"); 0953 } elsif ($attribute->signature->type =~ /Constructor$/) { 0954 my $constructorType = $codeGenerator->StripModule($attribute->signature->type); 0955 $constructorType =~ s/Constructor$//; 0956 push(@implContent, " return JS" . $constructorType . "::getConstructor(exec);\n"); 0957 } elsif (!@{$attribute->getterExceptions}) { 0958 if ($podType) { 0959 push(@implContent, " $podType imp(*impl());\n\n"); 0960 if ($podType eq "float") { # Special case for JSSVGNumber 0961 push(@implContent, " return " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp") . ";\n"); 0962 } else { 0963 push(@implContent, " return " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$name()") . ";\n"); 0964 } 0965 } else { 0966 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(impl());\n\n"); 0967 my $type = $codeGenerator->StripModule($attribute->signature->type); 0968 my $jsType = NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$name()"); 0969 0970 if ($codeGenerator->IsSVGAnimatedType($type)) { 0971 push(@implContent, " RefPtr<$type> obj = $jsType;\n"); 0972 push(@implContent, " return toJS(exec, obj.get(), imp);\n"); 0973 } else { 0974 push(@implContent, " return $jsType;\n"); 0975 } 0976 } 0977 } else { 0978 push(@implContent, " ExceptionCode ec = 0;\n"); 0979 0980 if ($podType) { 0981 push(@implContent, " $podType imp(*impl());\n\n"); 0982 push(@implContent, " KJS::JSValue* result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$name(ec)") . ";\n"); 0983 } else { 0984 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(impl());\n\n"); 0985 push(@implContent, " KJS::JSValue* result = " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$name(ec)") . ";\n"); 0986 } 0987 0988 push(@implContent, " setDOMException(exec, ec);\n"); 0989 push(@implContent, " return result;\n"); 0990 } 0991 push(@implContent, " }\n"); 0992 } 0993 0994 if ($dataNode->extendedAttributes->{"GenerateConstructor"}) { 0995 push(@implContent, " case ConstructorAttrNum:\n"); 0996 push(@implContent, " return getConstructor(exec);\n"); 0997 } 0998 0999 push(@implContent, " }\n"); 1000 push(@implContent, " return nullptr;\n}\n\n"); 1001 1002 # Check if we have any writable attributes 1003 my $hasReadWriteProperties = 0; 1004 foreach my $attribute (@{$dataNode->attributes}) { 1005 $hasReadWriteProperties = 1 if $attribute->type !~ /^readonly/; 1006 } 1007 if ($hasReadWriteProperties) { 1008 push(@implContent, "void ${className}::put(ExecState* exec, const Identifier& propertyName, JSValue* value, int attr)\n"); 1009 push(@implContent, "{\n"); 1010 if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) { 1011 push(@implContent, " bool ok;\n"); 1012 push(@implContent, " unsigned index = propertyName.toUInt32(&ok, false);\n"); 1013 push(@implContent, " if (ok) {\n"); 1014 push(@implContent, " indexSetter(exec, index, value, attr);\n"); 1015 push(@implContent, " return;\n"); 1016 push(@implContent, " }\n"); 1017 } 1018 if ($dataNode->extendedAttributes->{"CustomPutFunction"}) { 1019 push(@implContent, " if (customPut(exec, propertyName, value, attr))\n"); 1020 push(@implContent, " return;\n"); 1021 } 1022 1023 push(@implContent, " lookupPut<$className, $parentClassName>(exec, propertyName, value, attr, &${className}Table, this);\n"); 1024 push(@implContent, "}\n\n"); 1025 1026 push(@implContent, "void ${className}::putValueProperty(ExecState* exec, int token, JSValue* value, int /*attr*/)\n"); 1027 push(@implContent, "{\n"); 1028 1029 push(@implContent, " switch (token) {\n"); 1030 1031 foreach my $attribute (@{$dataNode->attributes}) { 1032 if ($attribute->type !~ /^readonly/) { 1033 my $name = $attribute->signature->name; 1034 1035 if ($attribute->signature->type =~ /Constructor$/) { 1036 push(@implContent, " case " . $name ."ConstructorAttrNum: {\n"); 1037 } else { 1038 push(@implContent, " case " . WK_ucfirst($name) . "AttrNum: {\n"); 1039 } 1040 1041 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) { 1042 push(@implContent, " if (!isSafeScript(exec))\n"); 1043 push(@implContent, " return;\n"); 1044 } 1045 1046 if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"CustomSetter"}) { 1047 push(@implContent, " set" . WK_ucfirst($name) . "(exec, value);\n"); 1048 } elsif ($attribute->signature->type =~ /Constructor$/) { 1049 my $constructorType = $attribute->signature->type; 1050 $constructorType =~ s/Constructor$//; 1051 $implIncludes{"JS" . $constructorType . ".h"} = 1; 1052 push(@implContent, " // Shadowing a built-in constructor\n"); 1053 push(@implContent, " JSObject::put(exec, \"$name\", value);\n"); 1054 } elsif ($attribute->signature->extendedAttributes->{"Replaceable"}) { 1055 push(@implContent, " JSObject::put(exec, \"$name\", value);\n"); 1056 } else { 1057 if ($podType) { 1058 push(@implContent, " $podType imp(*impl());\n\n"); 1059 if ($podType eq "float") { # Special case for JSSVGNumber 1060 push(@implContent, " imp = " . JSValueToNative($attribute->signature, "value") . ";\n"); 1061 } else { 1062 push(@implContent, " imp.set" . WK_ucfirst($name) . "(" . JSValueToNative($attribute->signature, "value") . ");\n"); 1063 } 1064 push(@implContent, " m_impl->commitChange(exec, imp);\n"); 1065 } else { 1066 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(impl());\n\n"); 1067 push(@implContent, " ExceptionCode ec = 0;\n") if @{$attribute->setterExceptions}; 1068 push(@implContent, " imp->set" . WK_ucfirst($name) . "(" . JSValueToNative($attribute->signature, "value")); 1069 push(@implContent, ", ec") if @{$attribute->setterExceptions}; 1070 push(@implContent, ");\n"); 1071 push(@implContent, " setDOMException(exec, ec);\n") if @{$attribute->setterExceptions}; 1072 } 1073 } 1074 push(@implContent, " break;\n"); 1075 push(@implContent, " }\n"); 1076 } 1077 } 1078 push(@implContent, " }\n"); # end switch 1079 1080 if (IsSVGTypeNeedingContextParameter($implClassName)) { 1081 push(@implContent, " if (context())\n"); 1082 push(@implContent, " context()->notifyAttributeChange();\n"); 1083 } 1084 1085 push(@implContent, "}\n\n"); # end function 1086 } 1087 } 1088 1089 if ($dataNode->extendedAttributes->{"GenerateConstructor"}) { 1090 push(@implContent, "JSValue* ${className}::getConstructor(ExecState* exec)\n{\n"); 1091 push(@implContent, " return ::cacheGlobalObject<${className}Constructor>(exec, \"[[${interfaceName}.constructor]]\");\n"); 1092 push(@implContent, "}\n"); 1093 } 1094 1095 # Functions 1096 if ($numFunctions ne 0) { 1097 push(@implContent, "JSValue* ${className}PrototypeFunction::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)\n{\n"); 1098 push(@implContent, " if (!thisObj->inherits(&${className}::s_info))\n"); 1099 push(@implContent, " return throwError(exec, TypeError);\n\n"); 1100 1101 push(@implContent, " $className* castedThisObj = static_cast<$className*>(thisObj);\n"); 1102 if ($podType) { 1103 push(@implContent, " JSSVGPODTypeWrapper<$podType>* wrapper = castedThisObj->impl();\n"); 1104 push(@implContent, " $podType imp(*wrapper);\n\n"); 1105 } else { 1106 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThisObj->impl());\n\n"); 1107 } 1108 1109 push(@implContent, " switch (id) {\n"); 1110 1111 my $hasCustomFunctionsOnly = 1; 1112 1113 foreach my $function (@{$dataNode->functions}) { 1114 push(@implContent, " case ${className}::" . WK_ucfirst($function->signature->name) . "FuncNum: {\n"); 1115 1116 if ($function->signature->extendedAttributes->{"Custom"}) { 1117 push(@implContent, " return castedThisObj->" . $function->signature->name . "(exec, args);\n }\n"); 1118 next; 1119 } 1120 1121 $hasCustomFunctionsOnly = 0; 1122 AddIncludesForType($function->signature->type); 1123 1124 if (@{$function->raisesExceptions}) { 1125 push(@implContent, " ExceptionCode ec = 0;\n"); 1126 } 1127 1128 if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) { 1129 push(@implContent, " if (!checkNodeSecurity(exec, imp->getSVGDocument(" . (@{$function->raisesExceptions} ? "ec" : "") .")))\n"); 1130 push(@implContent, " return jsUndefined();\n"); 1131 $implIncludes{"kjs_dom.h"} = 1; 1132 } 1133 1134 my $paramIndex = 0; 1135 my $functionString = "imp" . ($podType ? "." : "->") . $function->signature->name . "("; 1136 1137 my $numParameters = @{$function->parameters}; 1138 my $hasOptionalArguments = 0; 1139 1140 foreach my $parameter (@{$function->parameters}) { 1141 if (!$hasOptionalArguments && $parameter->extendedAttributes->{"Optional"}) { 1142 push(@implContent, "\n int argsCount = args.size();\n"); 1143 $hasOptionalArguments = 1; 1144 } 1145 1146 if ($hasOptionalArguments) { 1147 push(@implContent, " if (argsCount < " . ($paramIndex + 1) . ") {\n"); 1148 GenerateImplementationFunctionCall($function, $functionString, $paramIndex, " " x 3, $podType, $implClassName); 1149 push(@implContent, " }\n\n"); 1150 } 1151 1152 my $name = $parameter->name; 1153 1154 if ($parameter->type eq "XPathNSResolver") { 1155 push(@implContent, " RefPtr<XPathNSResolver> customResolver;\n"); 1156 push(@implContent, " XPathNSResolver* resolver = toXPathNSResolver(args[$paramIndex]);\n"); 1157 push(@implContent, " if (!resolver) {\n"); 1158 push(@implContent, " customResolver = JSCustomXPathNSResolver::create(exec, args[$paramIndex]);\n"); 1159 push(@implContent, " if (exec->hadException())\n"); 1160 push(@implContent, " return jsUndefined();\n"); 1161 push(@implContent, " resolver = customResolver.get();\n"); 1162 push(@implContent, " }\n"); 1163 } else { 1164 push(@implContent, " bool ${name}Ok;\n") if TypeCanFailConversion($parameter); 1165 push(@implContent, " " . GetNativeTypeFromSignature($parameter) . " $name = " . JSValueToNative($parameter, "args[$paramIndex]", TypeCanFailConversion($parameter) ? "${name}Ok" : undef) . ";\n"); 1166 if (TypeCanFailConversion($parameter)) { 1167 push(@implContent, " if (!${name}Ok) {\n"); 1168 push(@implContent, " setDOMException(exec, DOM::DOMException::TYPE_MISMATCH_ERR);\n"); 1169 push(@implContent, " return jsUndefined();\n }\n"); 1170 } 1171 1172 # If a parameter is "an index", it should throw an INDEX_SIZE_ERR 1173 # exception 1174 if ($parameter->extendedAttributes->{"IsIndex"}) { 1175 $implIncludes{"ExceptionCode.h"} = 1; 1176 push(@implContent, " if ($name < 0) {\n"); 1177 push(@implContent, " setDOMException(exec, DOM::DOMException::INDEX_SIZE_ERR);\n"); 1178 push(@implContent, " return jsUndefined();\n }\n"); 1179 } 1180 } 1181 1182 $functionString .= ", " if $paramIndex; 1183 $functionString .= $name; 1184 1185 $paramIndex++; 1186 } 1187 1188 push(@implContent, "\n"); 1189 GenerateImplementationFunctionCall($function, $functionString, $paramIndex, " " x 2, $podType, $implClassName); 1190 1191 push(@implContent, " }\n"); # end case 1192 } 1193 push(@implContent, " }\n"); # end switch 1194 push(@implContent, " (void)imp;\n") if $hasCustomFunctionsOnly; 1195 push(@implContent, " return nullptr;\n"); 1196 push(@implContent, "}\n"); 1197 } 1198 1199 if ($dataNode->extendedAttributes->{"HasIndexGetter"}) { 1200 push(@implContent, "\nJSValue* ${className}::indexGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot)\n"); 1201 push(@implContent, "{\n"); 1202 push(@implContent, " ${className}* thisObj = static_cast<$className*>(slot.slotBase());\n"); 1203 if (IndexGetterReturnsStrings($implClassName)) { 1204 # TODO $implIncludes{"PlatformString.h"} = 1; 1205 push(@implContent, " return jsStringOrNull(thisObj->impl()->item(slot.index()));\n"); 1206 } else { 1207 push(@implContent, " return toJS(exec, static_cast<$implClassName*>(thisObj->impl())->item(slot.index()));\n"); 1208 } 1209 push(@implContent, "}\n"); 1210 if ($interfaceName eq "HTMLCollection") { 1211 $implIncludes{"JSNode.h"} = 1; 1212 $implIncludes{"Node.h"} = 1; 1213 } 1214 } 1215 1216 if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateToJS"}) and !UsesManualToJSImplementation($implClassName)) { 1217 if ($podType) { 1218 push(@implContent, "KJS::JSValue* toJS(KJS::ExecState* exec, JSSVGPODTypeWrapper<$podType>* obj, SVGElement* context)\n"); 1219 } elsif (IsSVGTypeNeedingContextParameter($implClassName)) { 1220 push(@implContent, "KJS::JSValue* toJS(KJS::ExecState* exec, $passType obj, SVGElement* context)\n"); 1221 } else { 1222 push(@implContent, "KJS::JSValue* toJS(KJS::ExecState* exec, $passType obj)\n"); 1223 } 1224 1225 push(@implContent, "{\n"); 1226 if ($podType) { 1227 push(@implContent, " return KJS::cacheSVGDOMObject<JSSVGPODTypeWrapper<$podType>, $className>(exec, obj, context);\n"); 1228 } elsif (IsSVGTypeNeedingContextParameter($implClassName)) { 1229 push(@implContent, " return KJS::cacheSVGDOMObject<$implClassName, $className>(exec, obj, context);\n"); 1230 } else { 1231 push(@implContent, " return KJS::cacheDOMObject<$implClassName, $className>(exec, obj);\n"); 1232 } 1233 push(@implContent, "}\n"); 1234 } 1235 1236 if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateNativeConverter"}) and !$dataNode->extendedAttributes->{"CustomNativeConverter"}) { 1237 if ($podType) { 1238 push(@implContent, "$podType to${interfaceName}(KJS::JSValue* val)\n"); 1239 } else { 1240 push(@implContent, "$implClassName* to${interfaceName}(KJS::JSValue* val)\n"); 1241 } 1242 1243 push(@implContent, "{\n"); 1244 1245 push(@implContent, " return val->isObject(&${className}::s_info) ? " . ($podType ? "($podType) *" : "") . "static_cast<$className*>(val)->impl() : "); 1246 if ($podType) { 1247 if ($podType ne "float") { 1248 push(@implContent, "$podType();\n}\n"); 1249 } else { 1250 push(@implContent, "0;\n}\n"); 1251 } 1252 } else { 1253 push(@implContent, "nullptr;\n}\n"); 1254 } 1255 } 1256 1257 if ($dataNode->extendedAttributes->{"GenerateNativeConverter"} && $hasParent) { 1258 push(@implContent, "\n$implClassName* ${className}::impl() const\n"); 1259 push(@implContent, "{\n"); 1260 push(@implContent, " return static_cast<$implClassName*>(${parentClassName}::impl());\n"); 1261 push(@implContent, "}\n"); 1262 } 1263 1264 push(@implContent, "\n}\n"); 1265 1266 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditional; 1267 } 1268 1269 sub GenerateImplementationFunctionCall() 1270 { 1271 my $function = shift; 1272 my $functionString = shift; 1273 my $paramIndex = shift; 1274 my $indent = shift; 1275 my $podType = shift; 1276 my $implClassName = shift; 1277 1278 if (@{$function->raisesExceptions}) { 1279 $functionString .= ", " if $paramIndex; 1280 $functionString .= "ec"; 1281 } 1282 $functionString .= ")"; 1283 1284 if ($function->signature->type eq "void") { 1285 push(@implContent, $indent . "$functionString;\n"); 1286 push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions}; 1287 1288 if ($podType) { 1289 push(@implContent, $indent . "wrapper->commitChange(exec, imp);\n\n"); 1290 push(@implContent, $indent . "if (castedThisObj->context())\n"); 1291 push(@implContent, $indent . " castedThisObj->context()->notifyAttributeChange();\n"); 1292 } 1293 1294 push(@implContent, $indent . "return jsUndefined();\n"); 1295 } else { 1296 push(@implContent, "\n" . $indent . "KJS::JSValue* result = " . NativeToJSValue($function->signature, 1, $implClassName, "", $functionString) . ";\n"); 1297 push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions}; 1298 1299 if ($podType) { 1300 push(@implContent, $indent . "wrapper->commitChange(exec, imp);\n\n"); 1301 push(@implContent, $indent . "if (castedThisObj->context())\n"); 1302 push(@implContent, $indent . " castedThisObj->context()->notifyAttributeChange();\n"); 1303 } 1304 1305 push(@implContent, $indent . "return result;\n"); 1306 } 1307 } 1308 1309 sub GetNativeTypeFromSignature 1310 { 1311 my $signature = shift; 1312 my $type = $codeGenerator->StripModule($signature->type); 1313 1314 if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) { 1315 # Special-case index arguments because we need to check that they aren't < 0. 1316 return "int"; 1317 } 1318 1319 return GetNativeType($type); 1320 } 1321 1322 sub GetNativeType 1323 { 1324 my $type = shift; 1325 1326 return "unsigned" if $type eq "unsigned long"; 1327 return $type if $type eq "unsigned short" or $type eq "float" or $type eq "double" or $type eq "AtomicString"; 1328 return "bool" if $type eq "boolean"; 1329 return "int" if $type eq "long"; 1330 return "String" if $type eq "DOMString"; 1331 return "Range::CompareHow" if $type eq "CompareHow"; 1332 return "EventTargetNode*" if $type eq "EventTarget"; 1333 return "FloatRect" if $type eq "SVGRect"; 1334 return "FloatPoint" if $type eq "SVGPoint"; 1335 return "AffineTransform" if $type eq "SVGMatrix"; 1336 return "SVGTransform" if $type eq "SVGTransform"; 1337 return "SVGLength" if $type eq "SVGLength"; 1338 return "float" if $type eq "SVGNumber"; 1339 return "SVGPaint::SVGPaintType" if $type eq "SVGPaintType"; 1340 1341 # Default, assume native type is a pointer with same type name as idl type 1342 return "${type}*"; 1343 } 1344 1345 sub TypeCanFailConversion 1346 { 1347 my $signature = shift; 1348 1349 my $type = $codeGenerator->StripModule($signature->type); 1350 1351 # FIXME: convert to use a hash 1352 1353 return 0 if $type eq "boolean" or 1354 $type eq "float" or 1355 $type eq "double" or 1356 $type eq "AtomicString" or 1357 $type eq "DOMString" or 1358 $type eq "Node" or 1359 $type eq "Element" or 1360 $type eq "DocumentType" or 1361 $type eq "Event" or 1362 $type eq "EventListener" or 1363 $type eq "EventTarget" or 1364 $type eq "Range" or 1365 $type eq "NodeFilter" or 1366 $type eq "DOMWindow" or 1367 $type eq "SQLResultSet" or 1368 $type eq "XPathEvaluator" or 1369 $type eq "XPathNSResolver" or 1370 $type eq "XPathResult" or 1371 $type eq "SVGAngle" or 1372 $type eq "SVGLength" or 1373 $type eq "SVGNumber" or 1374 $type eq "SVGPoint" or 1375 $type eq "SVGTransform" or 1376 $type eq "SVGPathSeg" or 1377 $type eq "SVGMatrix" or 1378 $type eq "SVGRect" or 1379 $type eq "SVGElement" or 1380 $type eq "HTMLElement" or 1381 $type eq "HTMLOptionElement" or 1382 $type eq "unsigned short" or # or can it? 1383 $type eq "CompareHow" or # or can it? 1384 $type eq "SVGPaintType" or # or can it? 1385 $type eq "VoidCallback"; 1386 1387 if ($type eq "unsigned long" or $type eq "long" or $type eq "Attr") { 1388 $implIncludes{"ExceptionCode.h"} = 1; 1389 return 1; 1390 } 1391 1392 die "Don't know whether a JS value can fail conversion to type $type." 1393 } 1394 1395 sub JSValueToNative 1396 { 1397 my $signature = shift; 1398 my $value = shift; 1399 my $okParam = shift; 1400 my $maybeOkParam = $okParam ? ", ${okParam}" : ""; 1401 1402 my $type = $codeGenerator->StripModule($signature->type); 1403 1404 return "$value->toBoolean(exec)" if $type eq "boolean"; 1405 return "$value->toNumber(exec)" if $type eq "double"; 1406 return "$value->toFloat(exec)" if $type eq "float" or $type eq "SVGNumber"; 1407 return "$value->toInt32(exec${maybeOkParam})" if $type eq "unsigned long" or $type eq "long" or $type eq "unsigned short"; 1408 1409 return "static_cast<Range::CompareHow>($value->toInt32(exec))" if $type eq "CompareHow"; 1410 return "static_cast<SVGPaint::SVGPaintType>($value->toInt32(exec))" if $type eq "SVGPaintType"; 1411 1412 return "$value->toString(exec)" if $type eq "AtomicString"; 1413 if ($type eq "DOMString") { 1414 return "valueToStringWithNullCheck(exec, $value)" if $signature->extendedAttributes->{"ConvertNullToNullString"}; 1415 return "valueToStringWithUndefinedOrNullCheck(exec, $value)" if $signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"}; 1416 return "$value->toString(exec).domString()"; 1417 } 1418 1419 if ($type eq "EventTarget") { 1420 $implIncludes{"JSEventTargetNode.h"} = 1; 1421 return "toEventTargetNode($value)"; 1422 } 1423 1424 if ($type eq "Attr") { 1425 $implIncludes{"kjs_dom.h"} = 1; 1426 return "toAttr($value${maybeOkParam})"; 1427 } 1428 1429 if ($type eq "SVGRect") { 1430 $implIncludes{"FloatRect.h"} = 1; 1431 } 1432 1433 if ($type eq "SVGPoint") { 1434 $implIncludes{"FloatPoint.h"} = 1; 1435 } 1436 1437 if ($type eq "VoidCallback") { 1438 $implIncludes{"VoidCallback.h"} = 1; 1439 return "toVoidCallback($value)"; 1440 } 1441 1442 # Default, assume autogenerated type conversion routines 1443 $implIncludes{"JS$type.h"} = 1; 1444 return "to$type($value)"; 1445 } 1446 1447 sub NativeToJSValue 1448 { 1449 my $signature = shift; 1450 my $inFunctionCall = shift; 1451 my $implClassName = shift; 1452 my $implClassNameForValueConversion = shift; 1453 my $value = shift; 1454 1455 my $type = $codeGenerator->StripModule($signature->type); 1456 1457 return "jsBoolean($value)" if $type eq "boolean"; 1458 return "jsNumber($value)" if $codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType" or $type eq "DOMTimeStamp"; 1459 1460 if ($codeGenerator->IsStringType($type)) { 1461 # TODO $implIncludes{"PlatformString.h"} = 1; 1462 my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"}; 1463 if (defined $conv) { 1464 return "jsStringOrNull($value)" if $conv eq "Null"; 1465 return "jsStringOrUndefined($value)" if $conv eq "Undefined"; 1466 return "jsStringOrFalse($value)" if $conv eq "False"; 1467 1468 die "Unknown value for ConvertNullStringTo extended attribute"; 1469 } 1470 return "jsString($value)"; 1471 } 1472 1473 if ($type eq "RGBColor") { 1474 $implIncludes{"kjs_css.h"} = 1; 1475 return "getJSRGBColor(exec, $value)"; 1476 } 1477 1478 if ($codeGenerator->IsPodType($type)) { 1479 $implIncludes{"JS$type.h"} = 1; 1480 1481 my $nativeType = GetNativeType($type); 1482 1483 my $getter = $value; 1484 $getter =~ s/imp->//; 1485 $getter =~ s/\(\)//; 1486 1487 my $setter = "set" . WK_ucfirst($getter); 1488 1489 if ($implClassNameForValueConversion eq "") { 1490 if (IsSVGTypeNeedingContextParameter($implClassName)) { 1491 return "toJS(exec, new JSSVGPODTypeWrapperCreatorReadOnly<$nativeType>($value), castedThisObj->context())" if $inFunctionCall eq 1; 1492 1493 # Special case: SVGZoomEvent - it doesn't have a context, but it's no problem, as there are no readwrite props 1494 return "toJS(exec, new JSSVGPODTypeWrapperCreatorReadOnly<$nativeType>($value), 0)" if $implClassName eq "SVGZoomEvent"; 1495 return "toJS(exec, new JSSVGPODTypeWrapperCreatorReadOnly<$nativeType>($value), context())"; 1496 } else { 1497 return "toJS(exec, new JSSVGPODTypeWrapperCreatorReadOnly<$nativeType>($value), imp)"; 1498 } 1499 } else { # These classes, always have a m_context pointer! 1500 return "toJS(exec, JSSVGPODTypeWrapperCache<$nativeType, $implClassNameForValueConversion>::lookupOrCreateWrapper(imp, &${implClassNameForValueConversion}::$getter, &${implClassNameForValueConversion}::$setter), context())"; 1501 } 1502 } 1503 1504 if ($codeGenerator->IsSVGAnimatedType($type)) { 1505 $value =~ s/\(\)//; 1506 $value .= "Animated()"; 1507 } 1508 1509 if ($type eq "CSSStyleDeclaration") { 1510 $implIncludes{"CSSMutableStyleDeclaration.h"} = 1; 1511 } 1512 1513 if ($type eq "NamedNodeMap") { 1514 $implIncludes{"NamedAttrMap.h"} = 1; 1515 } 1516 1517 if ($type eq "NodeList") { 1518 $implIncludes{"NameNodeList.h"} = 1; 1519 } 1520 1521 if ($type eq "EventTarget") { 1522 $implIncludes{"EventTargetNode.h"} = 1; 1523 $implIncludes{"JSEventTargetNode.h"} = 1; 1524 $implIncludes{"kjs_dom.h"} = 1; 1525 } elsif ($type eq "DOMWindow") { 1526 $implIncludes{"kjs_window.h"} = 1; 1527 } elsif ($type eq "DOMObject") { 1528 $implIncludes{"JSCanvasRenderingContext2D.h"} = 1; 1529 } elsif ($type eq "Clipboard") { 1530 $implIncludes{"kjs_events.h"} = 1; 1531 $implIncludes{"Clipboard.h"} = 1; 1532 } elsif ($type =~ /SVGPathSeg/) { 1533 $implIncludes{"JS$type.h"} = 1; 1534 $joinedName = $type; 1535 $joinedName =~ s/Abs|Rel//; 1536 $implIncludes{"$joinedName.h"} = 1; 1537 } else { 1538 # Default, include header with same name. 1539 $implIncludes{"JS$type.h"} = 1; 1540 $implIncludes{"$type.h"} = 1; 1541 } 1542 1543 return $value if $codeGenerator->IsSVGAnimatedType($type); 1544 1545 if (IsSVGTypeNeedingContextParameter($type)) { 1546 if (IsSVGTypeNeedingContextParameter($implClassName)) { 1547 if ($inFunctionCall eq 1) { 1548 return "toJS(exec, WTF::getPtr($value), castedThisObj->context())"; 1549 } else { 1550 return "toJS(exec, WTF::getPtr($value), context())"; 1551 } 1552 } else { 1553 return "toJS(exec, WTF::getPtr($value), imp)"; 1554 } 1555 } 1556 1557 return "toJS(exec, WTF::getPtr($value))"; 1558 } 1559 1560 sub ceilingToPowerOf2 1561 { 1562 my ($size) = @_; 1563 1564 my $powerOf2 = 1; 1565 while ($size > $powerOf2) { 1566 $powerOf2 <<= 1; 1567 } 1568 1569 return $powerOf2; 1570 } 1571 1572 # Internal Helper 1573 sub GenerateHashTable 1574 { 1575 my $object = shift; 1576 1577 my $name = shift; 1578 my $size = shift; 1579 my $keys = shift; 1580 my $values = shift; 1581 my $specials = shift; 1582 my $parameters = shift; 1583 1584 # Helpers 1585 my @table = (); 1586 my @links = (); 1587 1588 $size = ceilingToPowerOf2($size * 2); 1589 1590 my $maxDepth = 0; 1591 my $collisions = 0; 1592 my $numEntries = $size; 1593 1594 # Collect hashtable information 1595 my $i = 0; 1596 foreach (@{$keys}) { 1597 my $depth = 0; 1598 my $h = $object->GenerateHashValue($_) % $numEntries; 1599 1600 while (defined($table[$h])) { 1601 if (defined($links[$h])) { 1602 $h = $links[$h]; 1603 $depth++; 1604 } else { 1605 $collisions++; 1606 $links[$h] = $size; 1607 $h = $size; 1608 $size++; 1609 } 1610 } 1611 1612 $table[$h] = $i; 1613 1614 $i++; 1615 $maxDepth = $depth if ($depth > $maxDepth); 1616 } 1617 1618 # Ensure table is big enough (in case of undef entries at the end) 1619 if ($#table + 1 < $size) { 1620 $#table = $size - 1; 1621 } 1622 1623 # Start outputing the hashtables 1624 my $nameEntries = "${name}Entries"; 1625 $nameEntries =~ s/:/_/g; 1626 1627 if (($name =~ /Prototype/) or ($name =~ /Constructor/)) { 1628 my $type = $name; 1629 my $implClass; 1630 1631 if ($name =~ /Prototype/) { 1632 $type =~ s/Prototype.*//; 1633 $implClass = $type; $implClass =~ s/Wrapper$//; 1634 push(@implContent, "/* Hash table for prototype */\n"); 1635 } else { 1636 $type =~ s/Constructor.*//; 1637 $implClass = $type; $implClass =~ s/Constructor$//; 1638 push(@implContent, "/* Hash table for constructor */\n"); 1639 } 1640 } else { 1641 push(@implContent, "/* Hash table */\n"); 1642 } 1643 1644 # Dump the hash table 1645 push(@implContent, "\nstatic const HashEntry $nameEntries\[\] =\n\{\n"); 1646 1647 $i = 0; 1648 foreach $entry (@table) { 1649 if (defined($entry)) { 1650 my $key = @$keys[$entry]; 1651 1652 push(@implContent, " \{ \"" . $key . "\""); 1653 push(@implContent, ", " . @$values[$entry]); 1654 push(@implContent, ", " . @$specials[$entry]); 1655 push(@implContent, ", " . @$parameters[$entry]); 1656 push(@implContent, ", "); 1657 1658 if (defined($links[$i])) { 1659 push(@implContent, "&" . $nameEntries . "[$links[$i]]" . " \}"); 1660 } else { 1661 push(@implContent, "nullptr \}"); 1662 } 1663 } else { 1664 push(@implContent, " { nullptr, 0, 0, 0, nullptr }"); 1665 } 1666 1667 push(@implContent, ",") unless($i eq $size - 1); 1668 push(@implContent, "\n"); 1669 1670 $i++; 1671 } 1672 1673 # my $sizeMask = $numEntries - 1; 1674 my $sizeMask = $numEntries; 1675 1676 push(@implContent, "};\n\n"); 1677 push(@implContent, "static const HashTable $name = \n"); 1678 push(@implContent, "{\n 2, $size, $nameEntries, $sizeMask\n};\n\n"); 1679 } 1680 1681 # Internal helper 1682 sub GenerateHashValue 1683 { 1684 my $object = shift; 1685 1686 @chars = split(/ */, $_[0]); 1687 1688 # This hash is designed to work on 16-bit chunks at a time. But since the normal case 1689 # (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they 1690 # were 16-bit chunks, which should give matching results 1691 1692 my $EXP2_32 = 4294967296; 1693 1694 my $hash = 0x9e3779b9; 1695 my $l = scalar @chars; #I wish this was in Ruby --- Maks 1696 my $rem = $l & 1; 1697 $l = $l >> 1; 1698 1699 my $s = 0; 1700 1701 # Main loop 1702 for (; $l > 0; $l--) { 1703 $hash += ord($chars[$s]); 1704 my $tmp = leftShift(ord($chars[$s+1]), 11) ^ $hash; 1705 $hash = (leftShift($hash, 16)% $EXP2_32) ^ $tmp; 1706 $s += 2; 1707 $hash += $hash >> 11; 1708 $hash %= $EXP2_32; 1709 } 1710 1711 # Handle end case 1712 if ($rem != 0) { 1713 $hash += ord($chars[$s]); 1714 $hash ^= (leftShift($hash, 11)% $EXP2_32); 1715 $hash += $hash >> 17; 1716 } 1717 1718 # Force "avalanching" of final 127 bits 1719 $hash ^= leftShift($hash, 3); 1720 $hash += ($hash >> 5); 1721 $hash = ($hash% $EXP2_32); 1722 $hash ^= (leftShift($hash, 2)% $EXP2_32); 1723 $hash += ($hash >> 15); 1724 $hash = $hash% $EXP2_32; 1725 $hash ^= (leftShift($hash, 10)% $EXP2_32); 1726 1727 # this avoids ever returning a hash code of 0, since that is used to 1728 # signal "hash not computed yet", using a value that is likely to be 1729 # effectively the same as 0 when the low bits are masked 1730 $hash = 0x80000000 if ($hash == 0); 1731 1732 return $hash; 1733 } 1734 1735 # Internal helper 1736 sub WriteData 1737 { 1738 if (defined($IMPL)) { 1739 # Write content to file. 1740 print $IMPL @implContentHeader; 1741 1742 foreach my $implInclude (sort keys(%implIncludes)) { 1743 my $checkType = $implInclude; 1744 $checkType =~ s/\.h//; 1745 1746 print $IMPL "#include \"$implInclude\"\n" unless $codeGenerator->IsSVGAnimatedType($checkType); 1747 } 1748 1749 print $IMPL @implContent; 1750 close($IMPL); 1751 undef($IMPL); 1752 1753 @implHeaderContent = (); 1754 @implContent = (); 1755 %implIncludes = (); 1756 } 1757 1758 if (defined($HEADER)) { 1759 # Write content to file. 1760 print $HEADER @headerContent; 1761 close($HEADER); 1762 undef($HEADER); 1763 1764 @headerContent = (); 1765 } 1766 } 1767 1768 sub constructorFor 1769 { 1770 my $className = shift; 1771 my $protoClassName = shift; 1772 my $interfaceName = shift; 1773 my $canConstruct = shift; 1774 1775 my $implContent = << "EOF"; 1776 class ${className}Constructor : public DOMObject { 1777 public: 1778 ${className}Constructor(ExecState* exec) 1779 { 1780 setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype()); 1781 putDirect(exec->propertyNames().prototype, ${protoClassName}::self(exec), None); 1782 } 1783 using KJS::JSObject::getOwnPropertySlot; 1784 virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); 1785 JSValue* getValueProperty(ExecState*, int token) const; 1786 virtual const ClassInfo* classInfo() const { return &s_info; } 1787 static const ClassInfo s_info; 1788 1789 virtual bool implementsHasInstance() const { return true; } 1790 EOF 1791 1792 if ($canConstruct) { 1793 $implContent .= << "EOF"; 1794 virtual bool implementsConstruct() const { return true; } 1795 virtual JSObject* construct(ExecState* exec, const List& args) { return static_cast<JSObject*>(toJS(exec, new $interfaceName)); } 1796 EOF 1797 } 1798 1799 $implContent .= << "EOF"; 1800 }; 1801 1802 const ClassInfo ${className}Constructor::s_info = { "${interfaceName}Constructor", nullptr, &${className}ConstructorTable, nullptr }; 1803 1804 bool ${className}Constructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) 1805 { 1806 return getStaticValueSlot<${className}Constructor, DOMObject>(exec, &${className}ConstructorTable, this, propertyName, slot); 1807 } 1808 1809 JSValue* ${className}Constructor::getValueProperty(ExecState*, int token) const 1810 { 1811 // The token is the numeric value of its associated constant 1812 return jsNumber(token); 1813 } 1814 1815 EOF 1816 1817 return $implContent; 1818 } 1819 1820 sub prototypeFunctionFor 1821 { 1822 my $className = shift; 1823 1824 my $implContent = << "EOF"; 1825 class ${className}PrototypeFunction : public KJS::InternalFunctionImp { 1826 public: 1827 ${className}PrototypeFunction(KJS::ExecState* exec, int i, int len, const KJS::Identifier& name) 1828 : KJS::InternalFunctionImp(static_cast<KJS::FunctionPrototype*>(exec->lexicalInterpreter()->builtinFunctionPrototype()), name) 1829 , id(i) 1830 { 1831 put(exec, exec->propertyNames().length, KJS::jsNumber(len), KJS::DontDelete|KJS::ReadOnly|KJS::DontEnum); 1832 } 1833 virtual KJS::JSValue* callAsFunction(KJS::ExecState*, KJS::JSObject*, const KJS::List&); 1834 1835 private: 1836 int id; 1837 }; 1838 1839 EOF 1840 1841 return $implContent; 1842 } 1843 1844 1;