2 # Copyright (C) 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3 # Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
4 # Copyright (C) 2006, 2007 Samuel Weinig <sam@webkit.org>
5 # Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
6 # Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
8 # This library is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU Library General Public
10 # License as published by the Free Software Foundation; either
11 # version 2 of the License, or (at your option) any later version.
13 # This library is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 # Library General Public License for more details.
18 # You should have received a copy of the GNU Library General Public License
19 # aint with this library; see the file COPYING.LIB. If not, write to
20 # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 # Boston, MA 02110-1301, USA.
23 package CodeGeneratorJS;
30 my @headerContentHeader = ();
31 my @headerContent = ();
32 my %headerIncludes = ();
34 my @implContentHeader = ();
36 my %implIncludes = ();
37 my %implKJSIncludes = ();
40 my $headerTemplate = << "EOF";
42 This file is part of the WebKit open source project.
43 This file has been generated by generate-bindings.pl. DO NOT MODIFY!
45 This library is free software; you can redistribute it and/or
46 modify it under the terms of the GNU Library General Public
47 License as published by the Free Software Foundation; either
48 version 2 of the License, or (at your option) any later version.
50 This library is distributed in the hope that it will be useful,
51 but WITHOUT ANY WARRANTY; without even the implied warranty of
52 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
53 Library General Public License for more details.
55 You should have received a copy of the GNU Library General Public License
56 along with this library; see the file COPYING.LIB. If not, write to
57 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
58 Boston, MA 02110-1301, USA.
68 $codeGenerator = shift;
71 bless($reference, $object);
84 my ($value, $distance) = @_;
85 return (($value << $distance) & 0xFFFFFFFF);
88 # Params: 'domClass' struct
95 # Start actual generation
96 $object->GenerateHeader($dataNode);
97 $object->GenerateImplementation($dataNode);
99 my $name = $dataNode->name;
101 # Open files for writing
102 my $headerFileName = "$outputDir/JS$name.h";
103 my $implFileName = "$outputDir/JS$name.cpp";
105 open($IMPL, ">$implFileName") || die "Couldn't open file $implFileName";
106 open($HEADER, ">$headerFileName") || die "Couldn't open file $headerFileName";
109 # Params: 'idlDocument' struct
113 my $dataNode = shift;
115 $module = $dataNode->module;
118 sub GetParentClassName
120 my $dataNode = shift;
122 return $dataNode->extendedAttributes->{"LegacyParent"} if $dataNode->extendedAttributes->{"LegacyParent"};
123 return "DOMObject" if @{$dataNode->parents} eq 0;
124 return "JS" . $codeGenerator->StripModule($dataNode->parents(0));
127 sub GetVisibleClassName
129 my $className = shift;
131 return "DOMException" if $className eq "DOMCoreException";
135 sub AvoidInclusionOfType
139 # Special case: SVGRect.h / SVGPoint.h / SVGNumber.h / SVGMatrix.h do not exist.
140 return 1 if $type eq "SVGRect" or $type eq "SVGPoint" or $type eq "SVGNumber" or $type eq "SVGMatrix";
144 sub UsesManualToJSImplementation
148 return 1 if $type eq "Node" or $type eq "Document" or $type eq "HTMLCollection" or $type eq "SVGPathSeg" or $type eq "StyleSheet" or $type eq "CSSRule" or $type eq "CSSValue" or $type eq "Event" or $type eq "CanvasPixelArray" or $type eq "Element" or $type eq "Text";
152 sub IndexGetterReturnsStrings
156 return 1 if $type eq "CSSStyleDeclaration" or $type eq "MediaList" or $type eq "CSSVariablesDeclaration";
160 sub CreateSVGContextInterfaceName
164 return $type if $codeGenerator->IsSVGAnimatedType($type);
165 return "SVGPathSeg" if $type =~ /^SVGPathSeg/ and $type ne "SVGPathSegList";
170 sub AddIncludesForType
172 my $type = $codeGenerator->StripModule(shift);
174 # When we're finished with the one-file-per-class
175 # reorganization, we won't need these special cases.
176 if ($codeGenerator->IsPrimitiveType($type) or AvoidInclusionOfType($type)
177 or $type eq "DOMString" or $type eq "DOMObject" or $type eq "RGBColor") {
178 } elsif ($type =~ /SVGPathSeg/) {
180 $joinedName =~ s/Abs|Rel//;
181 $implIncludes{"${joinedName}.h"} = 1;
182 } elsif ($type eq "XPathNSResolver") {
183 $implIncludes{"JSXPathNSResolver.h"} = 1;
184 $implIncludes{"JSCustomXPathNSResolver.h"} = 1;
186 # default, include the same named file
187 $implIncludes{"${type}.h"} = 1;
190 # additional includes (things needed to compile the bindings but not the header)
192 if ($type eq "CanvasRenderingContext2D") {
193 $implIncludes{"CanvasGradient.h"} = 1;
194 $implIncludes{"CanvasPattern.h"} = 1;
195 $implIncludes{"CanvasStyle.h"} = 1;
198 if ($type eq "CanvasGradient" or $type eq "XPathNSResolver") {
199 $implIncludes{"PlatformString.h"} = 1;
202 if ($type eq "Document") {
203 $implIncludes{"NodeFilter.h"} = 1;
207 sub AddIncludesForSVGAnimatedType
210 $type =~ s/SVGAnimated//;
212 if ($type eq "Point" or $type eq "Rect") {
213 $implIncludes{"Float$type.h"} = 1;
214 } elsif ($type eq "String") {
215 $implIncludes{"PlatformString.h"} = 1;
219 sub AddClassForwardIfNeeded
221 my $implClassName = shift;
223 # SVGAnimatedLength/Number/etc.. are typedefs to SVGAnimtatedTemplate, so don't use class forwards for them!
224 push(@headerContent, "class $implClassName;\n\n") unless $codeGenerator->IsSVGAnimatedType($implClassName);
227 sub IsSVGTypeNeedingContextParameter
229 my $implClassName = shift;
231 if ($implClassName =~ /SVG/ and not $implClassName =~ /Element/) {
232 return 1 unless $implClassName =~ /SVGPaint/ or $implClassName =~ /SVGColor/ or $implClassName =~ /SVGDocument/;
238 sub HashValueForClassAndName
243 # SVG Filter enums live in WebCore namespace (platform/graphics/)
244 if ($class =~ /^SVGFE*/ or $class =~ /^SVGComponentTransferFunctionElement$/) {
245 return "WebCore::$name";
248 return "${class}::$name";
251 sub GenerateGetOwnPropertySlotBody
253 my ($dataNode, $interfaceName, $className, $implClassName, $hasAttributes, $inlined) = @_;
255 my $namespaceMaybe = ($inlined ? "JSC::" : "");
257 my @getOwnPropertySlotImpl = ();
259 if ($interfaceName eq "NamedNodeMap" or $interfaceName eq "HTMLCollection") {
260 push(@getOwnPropertySlotImpl, " ${namespaceMaybe}JSValue* proto = prototype();\n");
261 push(@getOwnPropertySlotImpl, " if (proto->isObject() && static_cast<${namespaceMaybe}JSObject*>(proto)->hasProperty(exec, propertyName))\n");
262 push(@getOwnPropertySlotImpl, " return false;\n\n");
265 my $hasNameGetterGeneration = sub {
266 push(@getOwnPropertySlotImpl, " if (canGetItemsForName(exec, static_cast<$implClassName*>(impl()), propertyName)) {\n");
267 push(@getOwnPropertySlotImpl, " slot.setCustom(this, nameGetter);\n");
268 push(@getOwnPropertySlotImpl, " return true;\n");
269 push(@getOwnPropertySlotImpl, " }\n");
271 $headerIncludes{"AtomicString.h"} = 1;
273 $implIncludes{"AtomicString.h"} = 1;
277 if ($dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
278 &$hasNameGetterGeneration();
281 my $requiresManualLookup = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasNameGetter"};
282 if ($requiresManualLookup) {
283 push(@getOwnPropertySlotImpl, " const ${namespaceMaybe}HashEntry* entry = ${className}Table.entry(exec, propertyName);\n");
284 push(@getOwnPropertySlotImpl, " if (entry) {\n");
285 push(@getOwnPropertySlotImpl, " slot.setStaticEntry(this, entry, staticValueGetter<$className>);\n");
286 push(@getOwnPropertySlotImpl, " return true;\n");
287 push(@getOwnPropertySlotImpl, " }\n");
290 if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}) {
291 push(@getOwnPropertySlotImpl, " bool ok;\n");
292 push(@getOwnPropertySlotImpl, " unsigned index = propertyName.toUInt32(&ok, false);\n");
293 push(@getOwnPropertySlotImpl, " if (ok && index < static_cast<$implClassName*>(impl())->length()) {\n");
294 if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"}) {
295 push(@getOwnPropertySlotImpl, " slot.setValue(getByIndex(exec, index));\n");
297 push(@getOwnPropertySlotImpl, " slot.setCustomIndex(this, index, indexGetter);\n");
299 push(@getOwnPropertySlotImpl, " return true;\n");
300 push(@getOwnPropertySlotImpl, " }\n");
303 if ($dataNode->extendedAttributes->{"HasNameGetter"}) {
304 &$hasNameGetterGeneration();
307 if ($dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}) {
308 push(@getOwnPropertySlotImpl, " if (customGetOwnPropertySlot(exec, propertyName, slot))\n");
309 push(@getOwnPropertySlotImpl, " return true;\n");
312 if ($hasAttributes) {
314 push(@getOwnPropertySlotImpl, " return ${namespaceMaybe}getStaticValueSlot<$className, Base>(exec, s_info.staticPropHashTable, this, propertyName, slot);\n");
316 push(@getOwnPropertySlotImpl, " return ${namespaceMaybe}getStaticValueSlot<$className, Base>(exec, &${className}Table, this, propertyName, slot);\n");
319 push(@getOwnPropertySlotImpl, " return Base::getOwnPropertySlot(exec, propertyName, slot);\n");
322 return @getOwnPropertySlotImpl;
328 my $dataNode = shift;
330 my $interfaceName = $dataNode->name;
331 my $className = "JS$interfaceName";
332 my $implClassName = $interfaceName;
334 # We only support multiple parents with SVG (for now).
335 if (@{$dataNode->parents} > 1) {
336 die "A class can't have more than one parent" unless $interfaceName =~ /SVG/;
337 $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode);
340 my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
341 my $hasRealParent = @{$dataNode->parents} > 0;
342 my $hasParent = $hasLegacyParent || $hasRealParent;
343 my $parentClassName = GetParentClassName($dataNode);
344 my $conditional = $dataNode->extendedAttributes->{"Conditional"};
346 # - Add default header template
347 @headerContentHeader = split("\r", $headerTemplate);
349 # - Add header protection
350 push(@headerContentHeader, "\n#ifndef $className" . "_h");
351 push(@headerContentHeader, "\n#define $className" . "_h\n\n");
353 my $conditionalString;
355 $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
356 push(@headerContentHeader, "\n#if ${conditionalString}\n\n");
360 push(@headerContentHeader, "#include \"$parentClassName.h\"\n");
362 push(@headerContentHeader, "#include \"JSDOMBinding.h\"\n");
363 push(@headerContentHeader, "#include <kjs/JSGlobalObject.h>\n");
364 push(@headerContentHeader, "#include <kjs/ObjectPrototype.h>\n");
366 if ($interfaceName eq "Node") {
367 push(@headerContentHeader, "#include \"EventTargetNode.h\"\n");
370 if ($dataNode->extendedAttributes->{"CustomCall"}) {
371 push(@headerContentHeader, "#include <kjs/CallData.h>\n");
374 if ($dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"}) {
375 push(@headerContentHeader, "#include <kjs/lookup.h>\n");
376 push(@headerContentHeader, "#include <wtf/AlwaysInline.h>\n");
379 if ($hasParent && $dataNode->extendedAttributes->{"GenerateNativeConverter"}) {
380 push(@headerContentHeader, "#include \"${implClassName}.h\"");
383 # Get correct pass/store types respecting PODType flag
384 my $podType = $dataNode->extendedAttributes->{"PODType"};
385 my $implType = $podType ? "JSSVGPODTypeWrapper<$podType> " : $implClassName;
386 push(@headerContentHeader, "#include \"$podType.h\"\n") if $podType and $podType ne "float";
388 push(@headerContentHeader, "#include \"JSSVGPODTypeWrapper.h\"\n") if $podType;
390 my $numConstants = @{$dataNode->constants};
391 my $numAttributes = @{$dataNode->attributes};
392 my $numFunctions = @{$dataNode->functions};
394 push(@headerContent, "\nnamespace WebCore {\n\n");
396 # Implementation class forward declaration
397 AddClassForwardIfNeeded($implClassName) unless $podType;
398 AddClassForwardIfNeeded("JSDOMWindowShell") if $interfaceName eq "DOMWindow";
401 push(@headerContent, "class $className : public $parentClassName {\n");
402 push(@headerContent, " typedef $parentClassName Base;\n");
403 push(@headerContent, "public:\n");
406 if ($interfaceName eq "DOMWindow") {
407 push(@headerContent, " $className(PassRefPtr<JSC::StructureID>, PassRefPtr<$implType>, JSDOMWindowShell*);\n");
408 } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
409 push(@headerContent, " $className(PassRefPtr<JSC::StructureID>, PassRefPtr<$implType>, SVGElement* context);\n");
411 push(@headerContent, " $className(PassRefPtr<JSC::StructureID>, PassRefPtr<$implType>);\n");
415 push(@headerContent, " virtual ~$className();\n") if (!$hasParent or $interfaceName eq "Document");
418 push(@headerContent, " static JSC::JSObject* createPrototype(JSC::ExecState*);\n") if $interfaceName ne "DOMWindow";
420 $implIncludes{"${className}Custom.h"} = 1 if $dataNode->extendedAttributes->{"CustomHeader"} || $dataNode->extendedAttributes->{"CustomPutFunction"};
422 my $hasGetter = $numAttributes > 0
423 || $dataNode->extendedAttributes->{"GenerateConstructor"}
424 || $dataNode->extendedAttributes->{"HasIndexGetter"}
425 || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}
426 || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}
427 || $dataNode->extendedAttributes->{"HasNameGetter"}
428 || $dataNode->extendedAttributes->{"HasOverridingNameGetter"};
432 push(@headerContent, " virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);\n");
433 push(@headerContent, " virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);\n") if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}) && !$dataNode->extendedAttributes->{"HasOverridingNameGetter"};
434 push(@headerContent, " JSC::JSValue* getValueProperty(JSC::ExecState*, int token) const;\n") if $numAttributes > 0 || $dataNode->extendedAttributes->{"GenerateConstructor"};
435 push(@headerContent, " bool customGetOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n") if $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
438 # Check if we have any writable properties
439 my $hasReadWriteProperties = 0;
440 foreach (@{$dataNode->attributes}) {
441 if ($_->type !~ /^readonly\ attribute$/) {
442 $hasReadWriteProperties = 1;
446 my $hasSetter = $hasReadWriteProperties
447 || $dataNode->extendedAttributes->{"CustomPutFunction"}
448 || $dataNode->extendedAttributes->{"HasCustomIndexSetter"};
452 push(@headerContent, " virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue*, JSC::PutPropertySlot&);\n");
453 push(@headerContent, " virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValue*);\n") if $dataNode->extendedAttributes->{"HasCustomIndexSetter"};
454 push(@headerContent, " void putValueProperty(JSC::ExecState*, int, JSC::JSValue*);\n") if $hasReadWriteProperties;
455 push(@headerContent, " bool customPut(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue*, JSC::PutPropertySlot&);\n") if $dataNode->extendedAttributes->{"CustomPutFunction"};
459 push(@headerContent, " virtual const JSC::ClassInfo* classInfo() const { return &s_info; }\n");
460 push(@headerContent, " static const JSC::ClassInfo s_info;\n\n");
462 # Custom mark function
463 push(@headerContent, " virtual void mark();\n\n") if $dataNode->extendedAttributes->{"CustomMarkFunction"};
465 # Custom pushEventHandlerScope function
466 push(@headerContent, " virtual void pushEventHandlerScope(JSC::ExecState*, JSC::ScopeChain&) const;\n\n") if $dataNode->extendedAttributes->{"CustomPushEventHandlerScope"};
468 # Custom call functions
469 push(@headerContent, " virtual JSC::CallType getCallData(JSC::CallData&);\n\n") if $dataNode->extendedAttributes->{"CustomCall"};
471 # Custom deleteProperty function
472 push(@headerContent, " virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&);\n") if $dataNode->extendedAttributes->{"CustomDeleteProperty"};
474 # Custom getPropertyNames function
475 push(@headerContent, " virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);\n") if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"} || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"});
476 push(@headerContent, " bool customGetPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);\n") if $dataNode->extendedAttributes->{"CustomGetPropertyNames"};
478 # Custom getPropertyAttributes function
479 push(@headerContent, " virtual bool getPropertyAttributes(JSC::ExecState*, const JSC::Identifier&, unsigned& attributes) const;\n") if $dataNode->extendedAttributes->{"CustomGetPropertyAttributes"};
481 # Custom defineGetter function
482 push(@headerContent, " virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction);\n") if $dataNode->extendedAttributes->{"CustomDefineGetter"};
484 # Custom defineSetter function
485 push(@headerContent, " virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction);\n") if $dataNode->extendedAttributes->{"CustomDefineSetter"};
487 # Custom lookupGetter function
488 push(@headerContent, " virtual JSC::JSValue* lookupGetter(JSC::ExecState*, const JSC::Identifier& propertyName);\n") if $dataNode->extendedAttributes->{"CustomLookupGetter"};
490 # Custom lookupSetter function
491 push(@headerContent, " virtual JSC::JSValue* lookupSetter(JSC::ExecState*, const JSC::Identifier& propertyName);\n") if $dataNode->extendedAttributes->{"CustomLookupSetter"};
493 # Constructor object getter
494 push(@headerContent, " static JSC::JSValue* getConstructor(JSC::ExecState*);\n") if $dataNode->extendedAttributes->{"GenerateConstructor"};
496 my $numCustomFunctions = 0;
497 my $numCustomAttributes = 0;
499 # Attribute and function enums
500 my $hasAttrEnum = ($numAttributes > 0) || $dataNode->extendedAttributes->{"GenerateConstructor"};
501 push(@headerContent, " enum {\n") if ($hasAttrEnum);
503 if ($numAttributes > 0) {
504 push(@headerContent, " // Attributes\n ");
507 foreach (@{$dataNode->attributes}) {
510 $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"Custom"};
511 $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"CustomGetter"};
512 $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"CustomSetter"};
515 if ((($i % 4) eq 0) and ($i ne 0)) {
516 push(@headerContent, "\n ");
519 my $value = $codeGenerator->WK_ucfirst($attribute->signature->name)
520 . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "")
522 $value .= ", " if (($i < $numAttributes - 1) or (($i eq $numAttributes - 1) and (($numFunctions ne 0) or $dataNode->extendedAttributes->{"GenerateConstructor"})));
523 push(@headerContent, $value);
527 if ($dataNode->extendedAttributes->{"GenerateConstructor"}) {
528 push(@headerContent, "\n\n") if $numAttributes > 0;
529 push(@headerContent, " // The Constructor Attribute\n");
530 push(@headerContent, " ConstructorAttrNum");
533 push(@headerContent, "\n };\n") if ($hasAttrEnum);
535 if ($numCustomAttributes > 0) {
536 push(@headerContent, "\n // Custom attributes\n");
538 foreach my $attribute (@{$dataNode->attributes}) {
539 if ($attribute->signature->extendedAttributes->{"Custom"}) {
540 push(@headerContent, " JSC::JSValue* " . $codeGenerator->WK_lcfirst($attribute->signature->name) . "(JSC::ExecState*) const;\n");
541 if ($attribute->type !~ /^readonly/) {
542 push(@headerContent, " void set" . $codeGenerator->WK_ucfirst($attribute->signature->name) . "(JSC::ExecState*, JSC::JSValue*);\n");
544 } elsif ($attribute->signature->extendedAttributes->{"CustomGetter"}) {
545 push(@headerContent, " JSC::JSValue* " . $codeGenerator->WK_lcfirst($attribute->signature->name) . "(JSC::ExecState*) const;\n");
546 } elsif ($attribute->signature->extendedAttributes->{"CustomSetter"}) {
547 if ($attribute->type !~ /^readonly/) {
548 push(@headerContent, " void set" . $codeGenerator->WK_ucfirst($attribute->signature->name) . "(JSC::ExecState*, JSC::JSValue*);\n");
554 foreach my $function (@{$dataNode->functions}) {
555 $numCustomFunctions++ if $function->signature->extendedAttributes->{"Custom"};
558 if ($numCustomFunctions > 0) {
559 push(@headerContent, "\n // Custom functions\n");
560 foreach my $function (@{$dataNode->functions}) {
561 if ($function->signature->extendedAttributes->{"Custom"}) {
562 my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementationFunction"} || $codeGenerator->WK_lcfirst($function->signature->name);
563 push(@headerContent, " JSC::JSValue* " . $functionImplementationName . "(JSC::ExecState*, const JSC::ArgList&);\n");
570 push(@headerContent, " JSSVGPODTypeWrapper<$podType>* impl() const { return m_impl.get(); }\n");
571 push(@headerContent, " SVGElement* context() const { return m_context.get(); }\n\n");
572 push(@headerContent, "private:\n");
573 push(@headerContent, " RefPtr<SVGElement> m_context;\n");
574 push(@headerContent, " RefPtr<JSSVGPODTypeWrapper<$podType> > m_impl;\n");
575 } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
576 push(@headerContent, " $implClassName* impl() const { return m_impl.get(); }\n");
577 push(@headerContent, " SVGElement* context() const { return m_context.get(); }\n\n");
578 push(@headerContent, "private:\n");
579 push(@headerContent, " RefPtr<SVGElement> m_context;\n");
580 push(@headerContent, " RefPtr<$implClassName > m_impl;\n");
582 push(@headerContent, " $implClassName* impl() const { return m_impl.get(); }\n\n");
583 push(@headerContent, "private:\n");
584 push(@headerContent, " RefPtr<$implClassName> m_impl;\n");
586 } elsif ($dataNode->extendedAttributes->{"GenerateNativeConverter"}) {
587 push(@headerContent, " $implClassName* impl() const\n");
588 push(@headerContent, " {\n");
589 push(@headerContent, " return static_cast<$implClassName*>(Base::impl());\n");
590 push(@headerContent, " }\n");
594 if ($dataNode->extendedAttributes->{"HasIndexGetter"}) {
595 push(@headerContent, " static JSC::JSValue* indexGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n");
597 if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"}) {
598 push(@headerContent, " JSC::JSValue* getByIndex(JSC::ExecState*, unsigned index);\n");
602 if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
603 push(@headerContent, " void indexSetter(JSC::ExecState*, unsigned index, JSC::JSValue*);\n");
606 if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
607 push(@headerContent, "private:\n");
608 push(@headerContent, " static bool canGetItemsForName(JSC::ExecState*, $implClassName*, const JSC::Identifier&);\n");
609 push(@headerContent, " static JSC::JSValue* nameGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n");
612 push(@headerContent, "};\n\n");
614 if ($dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"}) {
615 push(@headerContent, "ALWAYS_INLINE bool ${className}::getOwnPropertySlot(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertySlot& slot)\n");
616 push(@headerContent, "{\n");
617 push(@headerContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 1));
618 push(@headerContent, "}\n\n");
621 if (!$hasParent || $dataNode->extendedAttributes->{"GenerateToJS"}) {
623 push(@headerContent, "JSC::JSValue* toJS(JSC::ExecState*, JSSVGPODTypeWrapper<$podType>*, SVGElement* context);\n");
624 } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
625 push(@headerContent, "JSC::JSValue* toJS(JSC::ExecState*, $implType*, SVGElement* context);\n");
627 push(@headerContent, "JSC::JSValue* toJS(JSC::ExecState*, $implType*);\n");
629 if ($interfaceName eq "Node") {
630 # Resolve ambiguity with EventTarget that otherwise exists.
631 push(@headerContent, "inline JSC::JSValue* toJS(JSC::ExecState* exec, EventTargetNode* node) { return toJS(exec, static_cast<Node*>(node)); }\n");
634 if (!$hasParent || $dataNode->extendedAttributes->{"GenerateNativeConverter"}) {
636 push(@headerContent, "$podType to${interfaceName}(JSC::JSValue*);\n");
637 } elsif ($interfaceName eq "NodeFilter") {
638 push(@headerContent, "PassRefPtr<NodeFilter> toNodeFilter(JSC::JSValue*);\n");
640 push(@headerContent, "$implClassName* to${interfaceName}(JSC::JSValue*);\n");
642 if ($interfaceName eq "Node" or $interfaceName eq "Element" or $interfaceName eq "Text") {
643 push(@headerContent, "JSC::JSValue* toJSNewlyCreated(JSC::ExecState*, $interfaceName*);\n");
646 push(@headerContent, "\n");
648 # Add prototype declaration.
649 push(@headerContent, "class ${className}Prototype : public JSC::JSObject {\n");
650 push(@headerContent, "public:\n");
651 if ($interfaceName eq "DOMWindow") {
652 push(@headerContent, " void* operator new(size_t);\n");
654 push(@headerContent, " static JSC::JSObject* self(JSC::ExecState*);\n");
656 push(@headerContent, " virtual const JSC::ClassInfo* classInfo() const { return &s_info; }\n");
657 push(@headerContent, " static const JSC::ClassInfo s_info;\n");
658 if ($numFunctions > 0 || $numConstants > 0) {
659 push(@headerContent, " virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n");
661 if ($numConstants ne 0) {
662 push(@headerContent, " JSC::JSValue* getValueProperty(JSC::ExecState*, int token) const;\n");
664 push(@headerContent, " ${className}Prototype(PassRefPtr<JSC::StructureID> structure) : JSC::JSObject(structure) { }\n");
666 push(@headerContent, "};\n\n");
668 if ($numFunctions > 0) {
669 push(@headerContent,"// Functions\n\n");
670 foreach my $function (@{$dataNode->functions}) {
671 my $functionName = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($function->signature->name);
672 push(@headerContent, "JSC::JSValue* ${functionName}(JSC::ExecState*, JSC::JSObject*, JSC::JSValue*, const JSC::ArgList&);\n");
676 push(@headerContent, "\n} // namespace WebCore\n\n");
677 push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditional;
678 push(@headerContent, "#endif\n");
681 sub GenerateImplementation
683 my ($object, $dataNode) = @_;
685 my $interfaceName = $dataNode->name;
686 my $className = "JS$interfaceName";
687 my $implClassName = $interfaceName;
689 my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
690 my $hasRealParent = @{$dataNode->parents} > 0;
691 my $hasParent = $hasLegacyParent || $hasRealParent;
692 my $parentClassName = GetParentClassName($dataNode);
693 my $conditional = $dataNode->extendedAttributes->{"Conditional"};
694 my $visibleClassName = GetVisibleClassName($interfaceName);
696 # - Add default header template
697 @implContentHeader = split("\r", $headerTemplate);
698 push(@implContentHeader, "\n#include \"config.h\"\n\n");
699 my $conditionalString;
701 $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
702 push(@implContentHeader, "\n#if ${conditionalString}\n\n");
705 if ($className =~ /^JSSVG/) {
706 push(@implContentHeader, "#include \"SVGElement.h\"\n");
708 if ($className =~ /^JSSVGAnimated/) {
709 AddIncludesForSVGAnimatedType($interfaceName);
713 push(@implContentHeader, "#include \"$className.h\"\n\n");
714 push(@implContentHeader, "#include <wtf/GetPtr.h>\n\n");
716 push(@implContentHeader, "#include <kjs/PropertyNameArray.h>\n") if $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"};
718 AddIncludesForType($interfaceName);
722 push(@implContent, "\nusing namespace JSC;\n\n");
723 push(@implContent, "namespace WebCore {\n\n");
725 push(@implContent, "ASSERT_CLASS_FITS_IN_CELL($className)\n\n");
727 # - Add all attributes in a hashtable definition
728 my $numAttributes = @{$dataNode->attributes};
729 $numAttributes++ if $dataNode->extendedAttributes->{"GenerateConstructor"};
731 if ($numAttributes > 0) {
732 my $hashName = $className . "Table";
734 my @hashKeys = (); # ie. 'insertBefore'
735 my @hashValues = (); # ie. 'JSNode::InsertBefore'
736 my @hashSpecials = (); # ie. 'DontDelete|Function'
737 my @hashParameters = (); # ie. '2'
739 foreach my $attribute (@{$dataNode->attributes}) {
740 my $name = $attribute->signature->name;
741 push(@hashKeys, $name);
743 my $value = $className . "::" . $codeGenerator->WK_ucfirst($attribute->signature->name)
744 . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "")
746 push(@hashValues, $value);
749 push(@specials, "DontDelete") unless $attribute->signature->extendedAttributes->{"Deletable"};
750 push(@specials, "DontEnum") if $attribute->signature->extendedAttributes->{"DontEnum"};
751 push(@specials, "ReadOnly") if $attribute->type =~ /readonly/;
752 my $special = (@specials > 0) ? join("|", @specials) : "0";
753 push(@hashSpecials, $special);
755 my $numParameters = "0";
756 push(@hashParameters, $numParameters);
759 if ($dataNode->extendedAttributes->{"GenerateConstructor"}) {
760 push(@hashKeys, "constructor");
761 push(@hashValues, $className . "::ConstructorAttrNum");
762 push(@hashSpecials, "DontEnum");
763 push(@hashParameters, "0");
766 $object->GenerateHashTable($hashName,
767 \@hashKeys, \@hashValues,
768 \@hashSpecials, \@hashParameters);
771 my $numConstants = @{$dataNode->constants};
772 my $numFunctions = @{$dataNode->functions};
774 # - Add all constants
775 if ($dataNode->extendedAttributes->{"GenerateConstructor"}) {
776 $hashName = $className . "ConstructorTable";
781 @hashParameters = ();
783 foreach my $constant (@{$dataNode->constants}) {
784 my $name = $constant->name;
785 push(@hashKeys, $name);
787 my $value = $constant->value;
788 push(@hashValues, $value);
790 my $special = "DontDelete|ReadOnly";
791 push(@hashSpecials, $special);
793 my $numParameters = 0;
794 push(@hashParameters, $numParameters);
797 $object->GenerateHashTable($hashName,
798 \@hashKeys, \@hashValues,
799 \@hashSpecials, \@hashParameters);
802 $protoClassName = "${className}Prototype";
804 push(@implContent, constructorFor($className, $protoClassName, $interfaceName, $visibleClassName, $dataNode->extendedAttributes->{"CanBeConstructed"}));
807 # - Add functions and constants to a hashtable definition
808 $hashName = $className . "PrototypeTable";
813 @hashParameters = ();
815 foreach my $constant (@{$dataNode->constants}) {
816 my $name = $constant->name;
817 push(@hashKeys, $name);
819 my $value = $constant->value;
820 push(@hashValues, $value);
822 my $special = "DontDelete|ReadOnly";
823 push(@hashSpecials, $special);
825 my $numParameters = 0;
826 push(@hashParameters, $numParameters);
829 foreach my $function (@{$dataNode->functions}) {
830 my $name = $function->signature->name;
831 push(@hashKeys, $name);
833 my $value = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($name);
834 push(@hashValues, $value);
837 push(@specials, "DontDelete") unless $function->signature->extendedAttributes->{"Deletable"};
838 push(@specials, "DontEnum") if $function->signature->extendedAttributes->{"DontEnum"};
839 push(@specials, "Function");
840 my $special = (@specials > 0) ? join("|", @specials) : "0";
841 push(@hashSpecials, $special);
843 my $numParameters = @{$function->parameters};
844 push(@hashParameters, $numParameters);
847 $object->GenerateHashTable($hashName,
848 \@hashKeys, \@hashValues,
849 \@hashSpecials, \@hashParameters);
851 push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleClassName}Prototype\", 0, &${className}PrototypeTable, 0 };\n\n");
852 if ($interfaceName ne "DOMWindow") {
853 push(@implContent, "JSObject* ${className}Prototype::self(ExecState* exec)\n");
854 push(@implContent, "{\n");
855 push(@implContent, " return getDOMPrototype<${className}>(exec);\n");
856 push(@implContent, "}\n\n");
858 if ($interfaceName eq "DOMWindow") {
859 push(@implContent, "void* ${className}Prototype::operator new(size_t size)\n");
860 push(@implContent, "{\n");
861 push(@implContent, " return JSDOMWindow::commonJSGlobalData()->heap->allocate(size);\n");
862 push(@implContent, "}\n\n");
864 if ($numConstants > 0 || $numFunctions > 0) {
865 push(@implContent, "bool ${className}Prototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n");
866 push(@implContent, "{\n");
867 if ($numConstants eq 0) {
868 push(@implContent, " return getStaticFunctionSlot<JSObject>(exec, &${className}PrototypeTable, this, propertyName, slot);\n");
869 } elsif ($numFunctions eq 0) {
870 push(@implContent, " return getStaticValueSlot<${className}Prototype, JSObject>(exec, &${className}PrototypeTable, this, propertyName, slot);\n");
872 push(@implContent, " return getStaticPropertySlot<${className}Prototype, JSObject>(exec, &${className}PrototypeTable, this, propertyName, slot);\n");
874 push(@implContent, "}\n\n");
876 if ($numConstants ne 0) {
877 $implKJSInclude{"JSNumberCell.h"} = 1;
878 push(@implContent, "JSValue* ${className}Prototype::getValueProperty(ExecState* exec, int token) const\n{\n");
879 push(@implContent, " // The token is the numeric value of its associated constant\n");
880 push(@implContent, " return jsNumber(exec, token);\n}\n\n");
883 # - Initialize static ClassInfo object
884 push(@implContent, "const ClassInfo $className" . "::s_info = { \"${visibleClassName}\", ");
886 push(@implContent, "&" . $parentClassName . "::s_info, ");
888 push(@implContent, "0, ");
891 if ($numAttributes > 0) {
892 push(@implContent, "&${className}Table ");
894 push(@implContent, "0 ");
896 push(@implContent, ", 0 ");
897 push(@implContent, "};\n\n");
899 # Get correct pass/store types respecting PODType flag
900 my $podType = $dataNode->extendedAttributes->{"PODType"};
901 my $implType = $podType ? "JSSVGPODTypeWrapper<$podType> " : $implClassName;
903 my $needsSVGContext = IsSVGTypeNeedingContextParameter($implClassName);
904 my $parentNeedsSVGContext = ($needsSVGContext and $parentClassName =~ /SVG/);
907 if ($interfaceName eq "DOMWindow") {
908 AddIncludesForType("JSDOMWindowShell");
909 push(@implContent, "${className}::$className(PassRefPtr<StructureID> structure, PassRefPtr<$implType> impl, JSDOMWindowShell* shell)\n");
910 push(@implContent, " : $parentClassName(structure, impl, shell)\n");
912 push(@implContent, "${className}::$className(PassRefPtr<StructureID> structure, PassRefPtr<$implType> impl" . ($needsSVGContext ? ", SVGElement* context" : "") . ")\n");
914 push(@implContent, " : $parentClassName(structure, impl" . ($parentNeedsSVGContext ? ", context" : "") . ")\n");
916 push(@implContent, " : $parentClassName(structure)\n");
917 push(@implContent, " , m_context(context)\n") if $needsSVGContext;
918 push(@implContent, " , m_impl(impl)\n");
921 push(@implContent, "{\n");
922 push(@implContent, "}\n\n");
926 push(@implContent, "${className}::~$className()\n");
927 push(@implContent, "{\n");
929 if ($interfaceName eq "Node") {
930 push(@implContent, " forgetDOMNode(m_impl->document(), m_impl.get());\n");
933 my $animatedType = $implClassName;
934 $animatedType =~ s/SVG/SVGAnimated/;
936 # Special case for JSSVGNumber
937 if ($codeGenerator->IsSVGAnimatedType($animatedType) and $podType ne "float") {
938 push(@implContent, " JSSVGDynamicPODTypeWrapperCache<$podType, $animatedType>::forgetWrapper(m_impl.get());\n");
941 push(@implContent, " forgetDOMObject(m_impl.get());\n");
944 push(@implContent, "\n}\n\n");
947 # Document needs a special destructor because it's a special case for caching. It needs
948 # its own special handling rather than relying on the caching that Node normally does.
949 if ($interfaceName eq "Document") {
950 push(@implContent, "${className}::~$className()\n");
951 push(@implContent, "{\n forgetDOMObject(static_cast<${implClassName}*>(impl()));\n}\n\n");
954 if ($interfaceName ne "DOMWindow") {
955 push(@implContent, "JSObject* ${className}::createPrototype(ExecState* exec)\n");
956 push(@implContent, "{\n");
957 if ($hasParent && $parentClassName ne "JSC::DOMNodeFilter") {
958 push(@implContent, " return new (exec) ${className}Prototype(${className}Prototype::createStructureID(${parentClassName}Prototype::self(exec)));\n");
960 push(@implContent, " return new (exec) ${className}Prototype(${className}Prototype::createStructureID(exec->lexicalGlobalObject()->objectPrototype()));\n");
962 push(@implContent, "}\n\n");
965 my $hasGetter = $numAttributes > 0
966 || $dataNode->extendedAttributes->{"GenerateConstructor"}
967 || $dataNode->extendedAttributes->{"HasIndexGetter"}
968 || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}
969 || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}
970 || $dataNode->extendedAttributes->{"HasNameGetter"}
971 || $dataNode->extendedAttributes->{"HasOverridingNameGetter"};
975 if (!$dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"}) {
976 push(@implContent, "bool ${className}::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n");
977 push(@implContent, "{\n");
978 push(@implContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 0));
979 push(@implContent, "}\n\n");
982 if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"})
983 && !$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
984 push(@implContent, "bool ${className}::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)\n");
985 push(@implContent, "{\n");
986 push(@implContent, " if (propertyName < static_cast<$implClassName*>(impl())->length()) {\n");
987 if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"}) {
988 push(@implContent, " slot.setValue(getByIndex(exec, propertyName));\n");
990 push(@implContent, " slot.setCustomIndex(this, propertyName, indexGetter);\n");
992 push(@implContent, " return true;\n");
993 push(@implContent, " }\n");
994 push(@implContent, " return getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);\n");
995 push(@implContent, "}\n\n");
998 if ($numAttributes > 0) {
999 push(@implContent, "JSValue* ${className}::getValueProperty(ExecState* exec, int token) const\n");
1000 push(@implContent, "{\n");
1002 push(@implContent, " switch (token) {\n");
1004 foreach my $attribute (@{$dataNode->attributes}) {
1005 my $getterFunctionName = $codeGenerator->WK_lcfirst($attribute->signature->name);
1007 my $implClassNameForValueConversion = "";
1008 if (!$podType and ($codeGenerator->IsSVGAnimatedType($implClassName) or $attribute->type !~ /^readonly/)) {
1009 $implClassNameForValueConversion = $implClassName;
1012 push(@implContent, " case " . $codeGenerator->WK_ucfirst($attribute->signature->name)
1013 . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "")
1016 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} &&
1017 !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurity"} &&
1018 !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurityOnGet"}) {
1019 push(@implContent, " if (!allowsAccessFrom(exec))\n");
1020 push(@implContent, " return jsUndefined();\n");
1023 if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"CustomGetter"}) {
1024 push(@implContent, " return $getterFunctionName(exec);\n");
1025 } elsif ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) {
1026 $implIncludes{"JSDOMBinding.h"} = 1;
1027 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(impl());\n");
1028 push(@implContent, " return checkNodeSecurity(exec, imp->$getterFunctionName()) ? " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$getterFunctionName()") . " : jsUndefined();\n");
1029 } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) {
1030 $implIncludes{"Document.h"} = 1;
1031 $implIncludes{"JSDOMBinding.h"} = 1;
1032 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(impl());\n");
1033 push(@implContent, " return checkNodeSecurity(exec, imp->contentDocument()) ? " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$getterFunctionName()") . " : jsUndefined();\n");
1034 } elsif ($attribute->signature->type =~ /Constructor$/) {
1035 my $constructorType = $codeGenerator->StripModule($attribute->signature->type);
1036 $constructorType =~ s/Constructor$//;
1037 push(@implContent, " return JS" . $constructorType . "::getConstructor(exec);\n");
1038 } elsif (!@{$attribute->getterExceptions}) {
1040 push(@implContent, " $podType imp(*impl());\n");
1041 if ($podType eq "float") { # Special case for JSSVGNumber
1042 push(@implContent, " return " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp") . ";\n");
1044 push(@implContent, " return " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$getterFunctionName()") . ";\n");
1047 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(impl());\n");
1048 my $type = $codeGenerator->StripModule($attribute->signature->type);
1049 my $jsType = NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$getterFunctionName()");
1050 if ($codeGenerator->IsSVGAnimatedType($type)) {
1051 push(@implContent, " RefPtr<$type> obj = $jsType;\n");
1052 push(@implContent, " return toJS(exec, obj.get(), imp);\n");
1054 push(@implContent, " return $jsType;\n");
1058 push(@implContent, " ExceptionCode ec = 0;\n");
1061 push(@implContent, " $podType imp(*impl());\n");
1062 push(@implContent, " JSC::JSValue* result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$getterFunctionName(ec)") . ";\n");
1064 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(impl());\n");
1065 push(@implContent, " JSC::JSValue* result = " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$getterFunctionName(ec)") . ";\n");
1068 push(@implContent, " setDOMException(exec, ec);\n");
1069 push(@implContent, " return result;\n");
1071 push(@implContent, " }\n");
1074 if ($dataNode->extendedAttributes->{"GenerateConstructor"}) {
1075 push(@implContent, " case ConstructorAttrNum:\n");
1076 push(@implContent, " return getConstructor(exec);\n");
1079 push(@implContent, " }\n");
1080 push(@implContent, " return 0;\n");
1081 push(@implContent, "}\n\n");
1084 # Check if we have any writable attributes
1085 my $hasReadWriteProperties = 0;
1086 foreach my $attribute (@{$dataNode->attributes}) {
1087 $hasReadWriteProperties = 1 if $attribute->type !~ /^readonly/;
1090 my $hasSetter = $hasReadWriteProperties
1091 || $dataNode->extendedAttributes->{"CustomPutFunction"}
1092 || $dataNode->extendedAttributes->{"HasCustomIndexSetter"};
1095 push(@implContent, "void ${className}::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot)\n");
1096 push(@implContent, "{\n");
1097 if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
1098 push(@implContent, " bool ok;\n");
1099 push(@implContent, " unsigned index = propertyName.toUInt32(&ok, false);\n");
1100 push(@implContent, " if (ok) {\n");
1101 push(@implContent, " indexSetter(exec, index, value);\n");
1102 push(@implContent, " return;\n");
1103 push(@implContent, " }\n");
1105 if ($dataNode->extendedAttributes->{"CustomPutFunction"}) {
1106 push(@implContent, " if (customPut(exec, propertyName, value, slot))\n");
1107 push(@implContent, " return;\n");
1110 if ($hasReadWriteProperties) {
1111 push(@implContent, " lookupPut<$className, Base>(exec, propertyName, value, &${className}Table, this, slot);\n");
1113 push(@implContent, " Base::put(exec, propertyName, value, slot);\n");
1115 push(@implContent, "}\n\n");
1117 if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
1118 push(@implContent, "void ${className}::put(ExecState* exec, unsigned propertyName, JSValue* value)\n");
1119 push(@implContent, "{\n");
1120 push(@implContent, " indexSetter(exec, propertyName, value);\n");
1121 push(@implContent, " return;\n");
1122 push(@implContent, "}\n\n");
1125 if ($hasReadWriteProperties) {
1126 push(@implContent, "void ${className}::putValueProperty(ExecState* exec, int token, JSValue* value)\n");
1127 push(@implContent, "{\n");
1129 push(@implContent, " switch (token) {\n");
1131 foreach my $attribute (@{$dataNode->attributes}) {
1132 if ($attribute->type !~ /^readonly/) {
1133 my $name = $attribute->signature->name;
1134 my $setterFunctionName = $codeGenerator->WK_ucfirst($name);
1136 push(@implContent, " case " . $codeGenerator->WK_ucfirst($attribute->signature->name)
1137 . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "")
1140 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
1141 if ($interfaceName eq "DOMWindow") {
1142 push(@implContent, " if (!allowsAccessFrom(exec))\n");
1144 push(@implContent, " if (!allowsAccessFromFrame(exec, impl()->frame()))\n");
1146 push(@implContent, " return;\n");
1149 if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"CustomSetter"}) {
1150 push(@implContent, " set$setterFunctionName(exec, value);\n");
1151 } elsif ($attribute->signature->type =~ /Constructor$/) {
1152 my $constructorType = $attribute->signature->type;
1153 $constructorType =~ s/Constructor$//;
1154 $implIncludes{"JS" . $constructorType . ".h"} = 1;
1155 push(@implContent, " // Shadowing a built-in constructor\n");
1156 push(@implContent, " putDirect(Identifier(exec, \"$name\"), value);\n");
1157 } elsif ($attribute->signature->extendedAttributes->{"Replaceable"}) {
1158 push(@implContent, " putDirect(Identifier(exec, \"$name\"), value);\n");
1161 push(@implContent, " $podType imp(*impl());\n");
1162 if ($podType eq "float") { # Special case for JSSVGNumber
1163 push(@implContent, " imp = " . JSValueToNative($attribute->signature, "value") . ";\n");
1165 push(@implContent, " imp.set$setterFunctionName(" . JSValueToNative($attribute->signature, "value") . ");\n");
1167 push(@implContent, " m_impl->commitChange(imp, context());\n");
1169 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(impl());\n");
1170 push(@implContent, " ExceptionCode ec = 0;\n") if @{$attribute->setterExceptions};
1171 push(@implContent, " imp->set$setterFunctionName(" . JSValueToNative($attribute->signature, "value"));
1172 push(@implContent, ", ec") if @{$attribute->setterExceptions};
1173 push(@implContent, ");\n");
1174 push(@implContent, " setDOMException(exec, ec);\n") if @{$attribute->setterExceptions};
1176 if (IsSVGTypeNeedingContextParameter($implClassName)) {
1177 push(@implContent, " if (context())\n");
1178 push(@implContent, " context()->svgAttributeChanged(impl()->associatedAttributeName());\n");
1182 push(@implContent, " break;\n");
1183 push(@implContent, " }\n");
1186 push(@implContent, " }\n"); # end switch
1187 push(@implContent, "}\n\n"); # end function
1192 if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"} || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}) {
1193 push(@implContent, "void ${className}::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)\n");
1194 push(@implContent, "{\n");
1195 if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"}) {
1196 push(@implContent, " if (customGetPropertyNames(exec, propertyNames))\n");
1197 push(@implContent, " return;\n");
1199 if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}) {
1200 push(@implContent, " for (unsigned i = 0; i < static_cast<${implClassName}*>(impl())->length(); ++i)\n");
1201 push(@implContent, " propertyNames.add(Identifier::from(exec, i));\n");
1203 push(@implContent, " Base::getPropertyNames(exec, propertyNames);\n");
1204 push(@implContent, "}\n\n");
1207 if ($dataNode->extendedAttributes->{"GenerateConstructor"}) {
1208 push(@implContent, "JSValue* ${className}::getConstructor(ExecState* exec)\n{\n");
1209 push(@implContent, " return getDOMConstructor<${className}Constructor>(exec);\n");
1210 push(@implContent, "}\n\n");
1214 if ($numFunctions > 0) {
1215 foreach my $function (@{$dataNode->functions}) {
1216 AddIncludesForType($function->signature->type);
1218 my $functionName = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($function->signature->name);
1219 my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementationFunction"} || $codeGenerator->WK_lcfirst($function->signature->name);
1221 push(@implContent, "JSValue* ${functionName}(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)\n");
1222 push(@implContent, "{\n");
1224 $implKJSInclude{"Error.h"} = 1;
1226 if ($interfaceName eq "DOMWindow") {
1227 push(@implContent, " $className* castedThisObj = toJSDOMWindow(thisValue);\n");
1228 push(@implContent, " if (!castedThisObj)\n");
1229 push(@implContent, " return throwError(exec, TypeError);\n");
1231 push(@implContent, " if (!thisValue->isObject(&${className}::s_info))\n");
1232 push(@implContent, " return throwError(exec, TypeError);\n");
1233 push(@implContent, " $className* castedThisObj = static_cast<$className*>(thisValue);\n");
1236 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} &&
1237 !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
1238 push(@implContent, " if (!castedThisObj->allowsAccessFrom(exec))\n");
1239 push(@implContent, " return jsUndefined();\n");
1242 if ($function->signature->extendedAttributes->{"Custom"}) {
1243 push(@implContent, " return castedThisObj->" . $functionImplementationName . "(exec, args);\n");
1246 push(@implContent, " JSSVGPODTypeWrapper<$podType>* wrapper = castedThisObj->impl();\n");
1247 push(@implContent, " $podType imp(*wrapper);\n");
1249 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThisObj->impl());\n");
1252 my $numParameters = @{$function->parameters};
1254 if ($function->signature->extendedAttributes->{"RequiresAllArguments"}) {
1255 push(@implContent, " if (args.size() < $numParameters)\n");
1256 push(@implContent, " return jsUndefined();\n");
1259 if (@{$function->raisesExceptions}) {
1260 push(@implContent, " ExceptionCode ec = 0;\n");
1263 if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) {
1264 push(@implContent, " if (!checkNodeSecurity(exec, imp->getSVGDocument(" . (@{$function->raisesExceptions} ? "ec" : "") .")))\n");
1265 push(@implContent, " return jsUndefined();\n");
1266 $implIncludes{"JSDOMBinding.h"} = 1;
1270 my $functionString = "imp" . ($podType ? "." : "->") . $functionImplementationName . "(";
1272 my $hasOptionalArguments = 0;
1274 foreach my $parameter (@{$function->parameters}) {
1275 if (!$hasOptionalArguments && $parameter->extendedAttributes->{"Optional"}) {
1276 push(@implContent, "\n int argsCount = args.size();\n");
1277 $hasOptionalArguments = 1;
1280 if ($hasOptionalArguments) {
1281 push(@implContent, " if (argsCount < " . ($paramIndex + 1) . ") {\n");
1282 GenerateImplementationFunctionCall($function, $functionString, $paramIndex, " " x 2, $podType, $implClassName);
1283 push(@implContent, " }\n\n");
1286 my $name = $parameter->name;
1288 if ($parameter->type eq "XPathNSResolver") {
1289 push(@implContent, " RefPtr<XPathNSResolver> customResolver;\n");
1290 push(@implContent, " XPathNSResolver* resolver = toXPathNSResolver(args.at(exec, $paramIndex));\n");
1291 push(@implContent, " if (!resolver) {\n");
1292 push(@implContent, " customResolver = JSCustomXPathNSResolver::create(exec, args.at(exec, $paramIndex));\n");
1293 push(@implContent, " if (exec->hadException())\n");
1294 push(@implContent, " return jsUndefined();\n");
1295 push(@implContent, " resolver = customResolver.get();\n");
1296 push(@implContent, " }\n");
1298 push(@implContent, " " . GetNativeTypeFromSignature($parameter) . " $name = " . JSValueToNative($parameter, "args.at(exec, $paramIndex)") . ";\n");
1300 # If a parameter is "an index" and it's negative it should throw an INDEX_SIZE_ERR exception.
1301 # But this needs to be done in the bindings, because the type is unsigned and the fact that it
1302 # was negative will be lost by the time we're inside the DOM.
1303 if ($parameter->extendedAttributes->{"IsIndex"}) {
1304 $implIncludes{"ExceptionCode.h"} = 1;
1305 push(@implContent, " if ($name < 0) {\n");
1306 push(@implContent, " setDOMException(exec, INDEX_SIZE_ERR);\n");
1307 push(@implContent, " return jsUndefined();\n");
1308 push(@implContent, " }\n");
1312 $functionString .= ", " if $paramIndex;
1314 if ($parameter->type eq "NodeFilter") {
1315 $functionString .= "$name.get()";
1317 $functionString .= $name;
1323 push(@implContent, "\n");
1324 GenerateImplementationFunctionCall($function, $functionString, $paramIndex, " ", $podType, $implClassName);
1326 push(@implContent, "}\n\n");
1330 if ($dataNode->extendedAttributes->{"HasIndexGetter"}) {
1331 push(@implContent, "\nJSValue* ${className}::indexGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)\n");
1332 push(@implContent, "{\n");
1333 push(@implContent, " ${className}* thisObj = static_cast<$className*>(slot.slotBase());\n");
1334 if (IndexGetterReturnsStrings($implClassName)) {
1335 $implIncludes{"KURL.h"} = 1;
1336 push(@implContent, " return jsStringOrNull(exec, thisObj->impl()->item(slot.index()));\n");
1338 push(@implContent, " return toJS(exec, static_cast<$implClassName*>(thisObj->impl())->item(slot.index()));\n");
1340 push(@implContent, "}\n");
1341 if ($interfaceName eq "HTMLCollection") {
1342 $implIncludes{"JSNode.h"} = 1;
1343 $implIncludes{"Node.h"} = 1;
1347 if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateToJS"}) and !UsesManualToJSImplementation($implClassName)) {
1349 push(@implContent, "JSC::JSValue* toJS(JSC::ExecState* exec, JSSVGPODTypeWrapper<$podType>* object, SVGElement* context)\n");
1350 } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
1351 push(@implContent, "JSC::JSValue* toJS(JSC::ExecState* exec, $implType* object, SVGElement* context)\n");
1353 push(@implContent, "JSC::JSValue* toJS(JSC::ExecState* exec, $implType* object)\n");
1356 push(@implContent, "{\n");
1358 push(@implContent, " return getDOMObjectWrapper<$className, JSSVGPODTypeWrapper<$podType> >(exec, object, context);\n");
1359 } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
1360 push(@implContent, " return getDOMObjectWrapper<$className>(exec, object, context);\n");
1362 push(@implContent, " return getDOMObjectWrapper<$className>(exec, object);\n");
1364 push(@implContent, "}\n");
1367 if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateNativeConverter"}) and !$dataNode->extendedAttributes->{"CustomNativeConverter"}) {
1369 push(@implContent, "$podType to${interfaceName}(JSC::JSValue* val)\n");
1371 push(@implContent, "$implClassName* to${interfaceName}(JSC::JSValue* val)\n");
1374 push(@implContent, "{\n");
1376 push(@implContent, " return val->isObject(&${className}::s_info) ? " . ($podType ? "($podType) *" : "") . "static_cast<$className*>(val)->impl() : ");
1377 if ($podType and $podType ne "float") {
1378 push(@implContent, "$podType();\n}\n");
1380 push(@implContent, "0;\n}\n");
1384 push(@implContent, "\n}\n");
1386 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditional;
1389 sub GenerateImplementationFunctionCall()
1391 my $function = shift;
1392 my $functionString = shift;
1393 my $paramIndex = shift;
1395 my $podType = shift;
1396 my $implClassName = shift;
1398 if (@{$function->raisesExceptions}) {
1399 $functionString .= ", " if $paramIndex;
1400 $functionString .= "ec";
1402 $functionString .= ")";
1404 if ($function->signature->type eq "void") {
1405 push(@implContent, $indent . "$functionString;\n");
1406 push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions};
1409 push(@implContent, $indent . "wrapper->commitChange(imp, castedThisObj->context());\n");
1412 push(@implContent, $indent . "return jsUndefined();\n");
1414 push(@implContent, "\n" . $indent . "JSC::JSValue* result = " . NativeToJSValue($function->signature, 1, $implClassName, "", $functionString) . ";\n");
1415 push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions};
1418 push(@implContent, $indent . "wrapper->commitChange(imp, castedThisObj->context());\n");
1421 push(@implContent, $indent . "return result;\n");
1425 sub GetNativeTypeFromSignature
1427 my $signature = shift;
1428 my $type = $codeGenerator->StripModule($signature->type);
1430 if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) {
1431 # Special-case index arguments because we need to check that they aren't < 0.
1435 return GetNativeType($type);
1439 "CompareHow" => "Range::CompareHow",
1440 "DOMString" => "const UString&",
1441 "EventTarget" => "EventTargetNode*",
1442 "NodeFilter" => "RefPtr<NodeFilter>",
1443 "SVGLength" => "SVGLength",
1444 "SVGMatrix" => "AffineTransform",
1445 "SVGNumber" => "float",
1446 "SVGPaintType" => "SVGPaint::SVGPaintType",
1447 "SVGPoint" => "FloatPoint",
1448 "SVGRect" => "FloatRect",
1449 "SVGTransform" => "SVGTransform",
1450 "boolean" => "bool",
1451 "double" => "double",
1454 "unsigned long" => "unsigned",
1455 "unsigned short" => "unsigned short",
1462 return $nativeType{$type} if exists $nativeType{$type};
1464 # For all other types, the native type is a pointer with same type name as the IDL type.
1470 my $signature = shift;
1473 my $type = $codeGenerator->StripModule($signature->type);
1475 return "$value->toBoolean(exec)" if $type eq "boolean";
1476 return "$value->toNumber(exec)" if $type eq "double";
1477 return "$value->toFloat(exec)" if $type eq "float" or $type eq "SVGNumber";
1478 return "$value->toInt32(exec)" if $type eq "unsigned long" or $type eq "long" or $type eq "unsigned short";
1480 return "static_cast<Range::CompareHow>($value->toInt32(exec))" if $type eq "CompareHow";
1481 return "static_cast<SVGPaint::SVGPaintType>($value->toInt32(exec))" if $type eq "SVGPaintType";
1483 if ($type eq "DOMString") {
1484 return "valueToStringWithNullCheck(exec, $value)" if $signature->extendedAttributes->{"ConvertNullToNullString"};
1485 return "valueToStringWithUndefinedOrNullCheck(exec, $value)" if $signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"};
1486 return "$value->toString(exec)";
1489 if ($type eq "EventTarget") {
1490 $implIncludes{"JSEventTargetNode.h"} = 1;
1491 return "toEventTargetNode($value)";
1494 $implIncludes{"FloatPoint.h"} = 1 if $type eq "SVGPoint";
1495 $implIncludes{"FloatRect.h"} = 1 if $type eq "SVGRect";
1496 $implIncludes{"HTMLOptionElement.h"} = 1 if $type eq "HTMLOptionElement";
1497 $implIncludes{"JSCustomVoidCallback.h"} = 1 if $type eq "VoidCallback";
1499 # Default, assume autogenerated type conversion routines
1500 $implIncludes{"JS$type.h"} = 1;
1501 return "to$type($value)";
1506 my $signature = shift;
1507 my $inFunctionCall = shift;
1508 my $implClassName = shift;
1509 my $implClassNameForValueConversion = shift;
1512 my $type = $codeGenerator->StripModule($signature->type);
1514 return "jsBoolean($value)" if $type eq "boolean";
1516 if ($codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType" or $type eq "DOMTimeStamp") {
1517 $implKJSInclude{"JSNumberCell.h"} = 1;
1518 return "jsNumber(exec, $value)";
1521 if ($codeGenerator->IsStringType($type)) {
1522 $implIncludes{"KURL.h"} = 1;
1523 my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"};
1524 if (defined $conv) {
1525 return "jsStringOrNull(exec, $value)" if $conv eq "Null";
1526 return "jsStringOrUndefined(exec, $value)" if $conv eq "Undefined";
1527 return "jsStringOrFalse(exec, $value)" if $conv eq "False";
1529 die "Unknown value for ConvertNullStringTo extended attribute";
1531 $implKJSInclude{"JSString.h"} = 1;
1532 return "jsString(exec, $value)";
1535 if ($type eq "RGBColor") {
1536 $implIncludes{"JS$type.h"} = 1;
1537 return "getJSRGBColor(exec, $value)";
1540 if ($codeGenerator->IsPodType($type)) {
1541 $implIncludes{"JS$type.h"} = 1;
1543 my $nativeType = GetNativeType($type);
1545 my $getter = $value;
1546 $getter =~ s/imp->//;
1547 $getter =~ s/\(\)//;
1549 my $setter = "set" . $codeGenerator->WK_ucfirst($getter);
1551 # Function calls will never return 'modifyable' POD types (ie. SVGRect getBBox()) - no need to keep track changes to the returned SVGRect
1552 if ($inFunctionCall eq 0
1553 and not $codeGenerator->IsSVGAnimatedType($implClassName)
1554 and $codeGenerator->IsPodTypeWithWriteableProperties($type)
1555 and not defined $signature->extendedAttributes->{"Immutable"}) {
1556 if ($codeGenerator->IsPodType($implClassName)) {
1557 return "toJS(exec, JSSVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($value, impl()).get(), context())";
1559 return "toJS(exec, JSSVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName>::create(imp, &${implClassName}::$getter, &${implClassName}::$setter).get(), imp)";
1563 if ($implClassNameForValueConversion eq "") {
1564 if (IsSVGTypeNeedingContextParameter($implClassName)) {
1565 return "toJS(exec, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), castedThisObj->context())" if $inFunctionCall eq 1;
1567 # Special case: SVGZoomEvent - it doesn't have a context, but it's no problem, as there are no readwrite props
1568 return "toJS(exec, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), 0)" if $implClassName eq "SVGZoomEvent";
1569 return "toJS(exec, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), context())";
1571 return "toJS(exec, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), imp)";
1573 } else { # These classes, always have a m_context pointer!
1574 return "toJS(exec, JSSVGDynamicPODTypeWrapperCache<$nativeType, $implClassNameForValueConversion>::lookupOrCreateWrapper(imp, &${implClassNameForValueConversion}::$getter, &${implClassNameForValueConversion}::$setter).get(), context())";
1578 if ($codeGenerator->IsSVGAnimatedType($type)) {
1580 $value .= "Animated()";
1583 if ($type eq "CSSStyleDeclaration") {
1584 $implIncludes{"CSSMutableStyleDeclaration.h"} = 1;
1587 if ($type eq "NamedNodeMap") {
1588 $implIncludes{"NamedAttrMap.h"} = 1;
1591 if ($type eq "NodeList") {
1592 $implIncludes{"NameNodeList.h"} = 1;
1595 if ($type eq "EventTarget") {
1596 $implIncludes{"EventTargetNode.h"} = 1;
1597 $implIncludes{"JSEventTargetNode.h"} = 1;
1598 } elsif ($type eq "DOMObject") {
1599 $implIncludes{"JSCanvasRenderingContext2D.h"} = 1;
1600 } elsif ($type =~ /SVGPathSeg/) {
1601 $implIncludes{"JS$type.h"} = 1;
1602 $joinedName = $type;
1603 $joinedName =~ s/Abs|Rel//;
1604 $implIncludes{"$joinedName.h"} = 1;
1606 # Default, include header with same name.
1607 $implIncludes{"JS$type.h"} = 1;
1608 $implIncludes{"$type.h"} = 1;
1611 return $value if $codeGenerator->IsSVGAnimatedType($type);
1613 if (IsSVGTypeNeedingContextParameter($type)) {
1614 if (IsSVGTypeNeedingContextParameter($implClassName)) {
1615 if ($inFunctionCall eq 1) {
1616 return "toJS(exec, WTF::getPtr($value), castedThisObj->context())";
1618 return "toJS(exec, WTF::getPtr($value), context())";
1621 return "toJS(exec, WTF::getPtr($value), imp)";
1625 if ($signature->extendedAttributes->{"ReturnsNew"}) {
1626 return "toJSNewlyCreated(exec, WTF::getPtr($value))";
1629 return "toJS(exec, WTF::getPtr($value))";
1632 sub ceilingToPowerOf2
1637 while ($size > $powerOf2) {
1645 sub GenerateHashTable
1652 my $specials = shift;
1653 my $parameters = shift;
1656 foreach my $key (@{$keys}) {
1657 push @hashes, $object->GenerateHashValue($key);
1660 # Collect hashtable information
1663 for ($size = ceilingToPowerOf2(scalar @{$keys}); ; $size += $size) {
1666 foreach my $hash (@hashes) {
1667 my $h = $hash % $size;
1668 next tableSizeLoop if defined $table[$h];
1674 # Start outputing the hashtables
1675 my $nameEntries = "${name}Values";
1676 $nameEntries =~ s/:/_/g;
1678 if (($name =~ /Prototype/) or ($name =~ /Constructor/)) {
1682 if ($name =~ /Prototype/) {
1683 $type =~ s/Prototype.*//;
1684 $implClass = $type; $implClass =~ s/Wrapper$//;
1685 push(@implContent, "/* Hash table for prototype */\n");
1687 $type =~ s/Constructor.*//;
1688 $implClass = $type; $implClass =~ s/Constructor$//;
1689 push(@implContent, "/* Hash table for constructor */\n");
1692 push(@implContent, "/* Hash table */\n");
1695 # Dump the hash table
1696 my $count = scalar @{$keys} + 1;
1697 push(@implContent, "\nstatic const HashTableValue $nameEntries\[$count\] =\n\{\n");
1699 foreach my $key (@{$keys}) {
1700 push(@implContent, " { \"$key\", (intptr_t)@$values[$i], @$specials[$i], @$parameters[$i] },\n");
1703 push(@implContent, " { 0, 0, 0, 0 }\n");
1704 push(@implContent, "};\n\n");
1705 my $sizeMask = $size - 1;
1706 push(@implContent, "static const HashTable $name = { $sizeMask, $nameEntries, 0 };\n\n");
1710 sub GenerateHashValue
1714 @chars = split(/ */, $_[0]);
1716 # This hash is designed to work on 16-bit chunks at a time. But since the normal case
1717 # (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they
1718 # were 16-bit chunks, which should give matching results
1720 my $EXP2_32 = 4294967296;
1722 my $hash = 0x9e3779b9;
1723 my $l = scalar @chars; #I wish this was in Ruby --- Maks
1730 for (; $l > 0; $l--) {
1731 $hash += ord($chars[$s]);
1732 my $tmp = leftShift(ord($chars[$s+1]), 11) ^ $hash;
1733 $hash = (leftShift($hash, 16)% $EXP2_32) ^ $tmp;
1735 $hash += $hash >> 11;
1741 $hash += ord($chars[$s]);
1742 $hash ^= (leftShift($hash, 11)% $EXP2_32);
1743 $hash += $hash >> 17;
1746 # Force "avalanching" of final 127 bits
1747 $hash ^= leftShift($hash, 3);
1748 $hash += ($hash >> 5);
1749 $hash = ($hash% $EXP2_32);
1750 $hash ^= (leftShift($hash, 2)% $EXP2_32);
1751 $hash += ($hash >> 15);
1752 $hash = $hash% $EXP2_32;
1753 $hash ^= (leftShift($hash, 10)% $EXP2_32);
1755 # this avoids ever returning a hash code of 0, since that is used to
1756 # signal "hash not computed yet", using a value that is likely to be
1757 # effectively the same as 0 when the low bits are masked
1758 $hash = 0x80000000 if ($hash == 0);
1766 if (defined($IMPL)) {
1767 # Write content to file.
1768 print $IMPL @implContentHeader;
1770 foreach my $implInclude (sort keys(%implIncludes)) {
1771 my $checkType = $implInclude;
1772 $checkType =~ s/\.h//;
1774 print $IMPL "#include \"$implInclude\"\n" unless $codeGenerator->IsSVGAnimatedType($checkType);
1779 foreach my $implKJSInclude (sort keys(%implKJSInclude)) {
1780 print $IMPL "#include <kjs/$implKJSInclude>\n";
1783 print $IMPL @implContent;
1787 @implContentHeader = ();
1790 %implKJSIncludes = ();
1793 if (defined($HEADER)) {
1794 # Write content to file.
1795 print $HEADER @headerContentHeader;
1797 foreach my $headerInclude (sort keys(%headerIncludes)) {
1798 print $HEADER "#include \"$headerInclude\"\n";
1801 print $HEADER @headerContent;
1805 @headerContentHeader = ();
1806 @headerContent = ();
1807 %headerIncludes = ();
1813 my $className = shift;
1814 my $protoClassName = shift;
1815 my $interfaceName = shift;
1816 my $visibleClassName = shift;
1817 my $canConstruct = shift;
1819 my $implContent = << "EOF";
1820 class ${className}Constructor : public DOMObject {
1822 ${className}Constructor(ExecState* exec)
1823 : DOMObject(${className}Constructor::createStructureID(exec->lexicalGlobalObject()->objectPrototype()))
1825 putDirect(exec->propertyNames().prototype, ${protoClassName}::self(exec), None);
1827 virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
1828 JSValue* getValueProperty(ExecState*, int token) const;
1829 virtual const ClassInfo* classInfo() const { return &s_info; }
1830 static const ClassInfo s_info;
1832 static PassRefPtr<StructureID> createStructureID(JSValue* proto)
1834 return StructureID::create(proto, TypeInfo(ObjectType, ImplementsHasInstance));
1838 if ($canConstruct) {
1839 $implContent .= << "EOF";
1840 static JSObject* construct(ExecState* exec, JSObject*, const ArgList&)
1842 return static_cast<JSObject*>(toJS(exec, ${interfaceName}::create()));
1844 virtual ConstructType getConstructData(ConstructData& constructData)
1846 constructData.native.function = construct;
1847 return ConstructTypeHost;
1852 $implContent .= << "EOF";
1855 const ClassInfo ${className}Constructor::s_info = { "${visibleClassName}Constructor", 0, &${className}ConstructorTable, 0 };
1857 bool ${className}Constructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
1859 return getStaticValueSlot<${className}Constructor, DOMObject>(exec, &${className}ConstructorTable, this, propertyName, slot);
1862 JSValue* ${className}Constructor::getValueProperty(ExecState* exec, int token) const
1864 // The token is the numeric value of its associated constant
1865 return jsNumber(exec, token);
1870 $implKJSInclude{"JSNumberCell.h"} = 1;
1872 return $implContent;