WebKit之CodeGenerate-JS的perl脚本的分析和学习

来源:互联网 发布:骨关节功能解剖学知乎 编辑:程序博客网 时间:2024/06/06 01:19

##  perl脚本的学习

package CodeGeneratorJS;my $module = "";my $outputDir = "";my $writeDependencies = 0;my @headerContentHeader = ();my @headerContent = ();my %headerIncludes = ();my %headerTrailingIncludes = ();my @implContentHeader = ();my @implContent = ();my %implIncludes = ();my @depsContent = ();my $numCachedAttributes = 0;my $currentCachedAttribute = 0;# Default .h templatemy $headerTemplate = << "EOF";/*    This file is part of the WebKit open source project.    This file has been generated by generate-bindings.pl. DO NOT MODIFY!    This library is free software; you can redistribute it and/or    modify it under the terms of the GNU Library General Public    License as published by the Free Software Foundation; either    version 2 of the License, or (at your option) any later version.    This library is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    Library General Public License for more details.    You should have received a copy of the GNU Library General Public License    along with this library; see the file COPYING.LIB.  If not, write to    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,    Boston, MA 02110-1301, USA.*/EOF# Default constructorsub new{    my $object = shift;    my $reference = { };    $codeGenerator = shift;    $outputDir = shift;    shift; # $outputHeadersDir    shift; # $useLayerOnTop    shift; # $preprocessor    $writeDependencies = shift;    bless($reference, $object);    return $reference;}sub finish{    my $object = shift;    # Commit changes!    $object->WriteData();}sub leftShift($$) {    my ($value, $distance) = @_;    return (($value << $distance) & 0xFFFFFFFF);}# Params: 'domClass' structsub GenerateInterface{    my $object = shift;    my $dataNode = shift;    my $defines = shift;    $codeGenerator->LinkOverloadedFunctions($dataNode);    # Start actual generation    if ($dataNode->extendedAttributes->{"Callback"}) {        $object->GenerateCallbackHeader($dataNode);        $object->GenerateCallbackImplementation($dataNode);    } else {        $object->GenerateHeader($dataNode);        $object->GenerateImplementation($dataNode);    }    my $name = $dataNode->name;    # Open files for writing    my $headerFileName = "$outputDir/JS$name.h";    my $implFileName = "$outputDir/JS$name.cpp";    my $depsFileName = "$outputDir/JS$name.dep";    # Remove old dependency file.    unlink($depsFileName);    open($IMPL, ">$implFileName") || die "Couldn't open file $implFileName";    open($HEADER, ">$headerFileName") || die "Couldn't open file $headerFileName";    if (@depsContent) {        open($DEPS, ">$depsFileName") || die "Couldn't open file $depsFileName";    }}sub GenerateAttributeEventListenerCall{    my $className = shift;    my $implSetterFunctionName = shift;    my $windowEventListener = shift;    my $wrapperObject = $windowEventListener ? "globalObject" : "thisObject";    my @GenerateEventListenerImpl = ();    if ($className eq "JSSVGElementInstance") {        # SVGElementInstances have to create JSEventListeners with the wrapper equal to the correspondingElement        $wrapperObject = "asObject(correspondingElementWrapper)";        push(@GenerateEventListenerImpl, <<END);    JSValue correspondingElementWrapper = toJS(exec, castedThis->globalObject(), imp->correspondingElement());    if (correspondingElementWrapper.isObject())END        # Add leading whitespace to format the imp->set... line correctly        push(@GenerateEventListenerImpl, "    ");    }    push(@GenerateEventListenerImpl, "    imp->set$implSetterFunctionName(createJSAttributeEventListener(exec, value, $wrapperObject));\n");    return @GenerateEventListenerImpl;}sub GenerateEventListenerCall{    my $className = shift;    my $functionName = shift;    my $passRefPtrHandling = ($functionName eq "add") ? "" : ".get()";    $implIncludes{"JSEventListener.h"} = 1;    my @GenerateEventListenerImpl = ();    my $wrapperObject = "castedThis";    if ($className eq "JSSVGElementInstance") {        # SVGElementInstances have to create JSEventListeners with the wrapper equal to the correspondingElement        $wrapperObject = "asObject(correspondingElementWrapper)";        push(@GenerateEventListenerImpl, <<END);    JSValue correspondingElementWrapper = toJS(exec, castedThis->globalObject(), imp->correspondingElement());    if (!correspondingElementWrapper.isObject())        return JSValue::encode(jsUndefined());END    }    push(@GenerateEventListenerImpl, <<END);    JSValue listener = exec->argument(1);    if (!listener.isObject())        return JSValue::encode(jsUndefined());    imp->${functionName}EventListener(ustringToAtomicString(exec->argument(0).toString(exec)), JSEventListener::create(asObject(listener), $wrapperObject, false, currentWorld(exec))$passRefPtrHandling, exec->argument(2).toBoolean(exec));    return JSValue::encode(jsUndefined());END    return @GenerateEventListenerImpl;}# Params: 'idlDocument' structsub GenerateModule{    my $object = shift;    my $dataNode = shift;    $module = $dataNode->module;}sub GetParentClassName{    my $dataNode = shift;    return $dataNode->extendedAttributes->{"LegacyParent"} if $dataNode->extendedAttributes->{"LegacyParent"};    return "JSDOMWrapper" if (@{$dataNode->parents} eq 0);    return "JS" . $codeGenerator->StripModule($dataNode->parents(0));}sub GetVisibleClassName{    my $className = shift;    return "DOMException" if $className eq "DOMCoreException";    return "FormData" if $className eq "DOMFormData";    return "MimeType" if $className eq "DOMMimeType";    return "MimeTypeArray" if $className eq "DOMMimeTypeArray";    return "Plugin" if $className eq "DOMPlugin";    return "PluginArray" if $className eq "DOMPluginArray";        return $className;}sub GetCallbackClassName{    my $className = shift;    return "JSCustomVoidCallback" if $className eq "VoidCallback";    return "JS$className";}sub IndexGetterReturnsStrings{    my $type = shift;    return 1 if $type eq "CSSStyleDeclaration" or $type eq "MediaList" or $type eq "DOMStringList" or $type eq "DOMTokenList" or $type eq "DOMSettableTokenList";    return 0;}sub AddIncludesForType{    my $type = $codeGenerator->StripModule(shift);    my $isCallback = @_ ? shift : 0;    # When we're finished with the one-file-per-class    # reorganization, we won't need these special cases.    if ($codeGenerator->IsPrimitiveType($type) or $codeGenerator->AvoidInclusionOfType($type)        or $type eq "DOMString" or $type eq "DOMObject" or $type eq "Array") {    } elsif ($type =~ /SVGPathSeg/) {        $joinedName = $type;        $joinedName =~ s/Abs|Rel//;        $implIncludes{"${joinedName}.h"} = 1;    } elsif ($type eq "XPathNSResolver") {        $implIncludes{"JSXPathNSResolver.h"} = 1;        $implIncludes{"JSCustomXPathNSResolver.h"} = 1;    } elsif ($isCallback) {        $implIncludes{"JS${type}.h"} = 1;    } else {        # default, include the same named file        $implIncludes{"${type}.h"} = 1;    }    # additional includes (things needed to compile the bindings but not the header)    if ($type eq "CanvasRenderingContext2D") {        $implIncludes{"CanvasGradient.h"} = 1;        $implIncludes{"CanvasPattern.h"} = 1;        $implIncludes{"CanvasStyle.h"} = 1;    }    if ($type eq "CanvasGradient" or $type eq "XPathNSResolver" or $type eq "MessagePort") {        $implIncludes{"PlatformString.h"} = 1;    }    if ($type eq "Document") {        $implIncludes{"NodeFilter.h"} = 1;    }    if ($type eq "MediaQueryListListener") {        $implIncludes{"MediaQueryListListener.h"} = 1;    }}# FIXME: This method will go away once all SVG animated properties are converted to the new scheme.sub AddIncludesForSVGAnimatedType{    my $type = shift;    $type =~ s/SVGAnimated//;    if ($type eq "Point" or $type eq "Rect") {        $implIncludes{"Float$type.h"} = 1;    } elsif ($type eq "String") {        $implIncludes{"PlatformString.h"} = 1;    }}sub IsScriptProfileType{    my $type = shift;    return 1 if ($type eq "ScriptProfileNode");    return 0;}sub AddTypedefForScriptProfileType{    my $type = shift;    (my $jscType = $type) =~ s/Script//;    push(@headerContent, "typedef JSC::$jscType $type;\n\n");}sub AddClassForwardIfNeeded{    my $implClassName = shift;    # SVGAnimatedLength/Number/etc. are typedefs to SVGAnimatedTemplate, so don't use class forwards for them!    unless ($codeGenerator->IsSVGAnimatedType($implClassName) or IsScriptProfileType($implClassName)) {        push(@headerContent, "class $implClassName;\n\n");    # ScriptProfile and ScriptProfileNode are typedefs to JSC::Profile and JSC::ProfileNode.    } elsif (IsScriptProfileType($implClassName)) {        AddTypedefForScriptProfileType($implClassName);    }}sub HashValueForClassAndName{    my $class = shift;    my $name = shift;    # SVG Filter enums live in WebCore namespace (platform/graphics/)    if ($class =~ /^SVGFE*/ or $class =~ /^SVGComponentTransferFunctionElement$/) {        return "WebCore::$name";    }    return "${class}::$name";}sub hashTableAccessor{    my $noStaticTables = shift;    my $className = shift;    if ($noStaticTables) {        return "get${className}Table(exec)";    } else {        return "&${className}Table";    }}sub prototypeHashTableAccessor{    my $noStaticTables = shift;    my $className = shift;    if ($noStaticTables) {        return "get${className}PrototypeTable(exec)";    } else {        return "&${className}PrototypeTable";    }}sub GenerateConditionalStringFromAttributeValue{    my $conditional = shift;    if ($conditional =~ /&/) {        return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";    } elsif ($conditional =~ /\|/) {        return "ENABLE(" . join(") || ENABLE(", split(/\|/, $conditional)) . ")";    } else {        return "ENABLE(" . $conditional . ")";    }}sub GenerateConditionalString{    my $node = shift;    my $conditional = $node->extendedAttributes->{"Conditional"};    if ($conditional) {        return GenerateConditionalStringFromAttributeValue($conditional);    } else {        return "";    }}sub GenerateGetOwnPropertySlotBody{    my ($dataNode, $interfaceName, $className, $implClassName, $hasAttributes, $inlined) = @_;    my $namespaceMaybe = ($inlined ? "JSC::" : "");    my @getOwnPropertySlotImpl = ();    if ($interfaceName eq "NamedNodeMap" or $interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") {        push(@getOwnPropertySlotImpl, "    ${namespaceMaybe}JSValue proto = prototype();\n");        push(@getOwnPropertySlotImpl, "    if (proto.isObject() && static_cast<${namespaceMaybe}JSObject*>(asObject(proto))->hasProperty(exec, propertyName))\n");        push(@getOwnPropertySlotImpl, "        return false;\n\n");    }    my $manualLookupGetterGeneration = sub {        my $requiresManualLookup = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasNameGetter"};        if ($requiresManualLookup) {            push(@getOwnPropertySlotImpl, "    const ${namespaceMaybe}HashEntry* entry = ${className}Table.entry(exec, propertyName);\n");            push(@getOwnPropertySlotImpl, "    if (entry) {\n");            push(@getOwnPropertySlotImpl, "        slot.setCustom(this, entry->propertyGetter());\n");            push(@getOwnPropertySlotImpl, "        return true;\n");            push(@getOwnPropertySlotImpl, "    }\n");        }    };    if (!$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {        &$manualLookupGetterGeneration();    }    if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {        push(@getOwnPropertySlotImpl, "    bool ok;\n");        push(@getOwnPropertySlotImpl, "    unsigned index = propertyName.toUInt32(ok);\n");        # If the item function returns a string then we let the ConvertNullStringTo handle the cases        # where the index is out of range.        if (IndexGetterReturnsStrings($implClassName)) {            push(@getOwnPropertySlotImpl, "    if (ok) {\n");        } else {            push(@getOwnPropertySlotImpl, "    if (ok && index < static_cast<$implClassName*>(impl())->length()) {\n");        }        if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {            push(@getOwnPropertySlotImpl, "        slot.setValue(getByIndex(exec, index));\n");        } else {            push(@getOwnPropertySlotImpl, "        slot.setCustomIndex(this, index, indexGetter);\n");        }        push(@getOwnPropertySlotImpl, "        return true;\n");        push(@getOwnPropertySlotImpl, "    }\n");    }    if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {        push(@getOwnPropertySlotImpl, "    if (canGetItemsForName(exec, static_cast<$implClassName*>(impl()), propertyName)) {\n");        push(@getOwnPropertySlotImpl, "        slot.setCustom(this, nameGetter);\n");        push(@getOwnPropertySlotImpl, "        return true;\n");        push(@getOwnPropertySlotImpl, "    }\n");        if ($inlined) {            $headerIncludes{"wtf/text/AtomicString.h"} = 1;        } else {            $implIncludes{"wtf/text/AtomicString.h"} = 1;        }    }    if ($dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {        &$manualLookupGetterGeneration();    }    if ($dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}) {        push(@getOwnPropertySlotImpl, "    if (getOwnPropertySlotDelegate(exec, propertyName, slot))\n");        push(@getOwnPropertySlotImpl, "        return true;\n");    }    if ($hasAttributes) {        if ($inlined) {            die "Cannot inline if NoStaticTables is set." if ($dataNode->extendedAttributes->{"NoStaticTables"});            push(@getOwnPropertySlotImpl, "    return ${namespaceMaybe}getStaticValueSlot<$className, Base>(exec, s_info.staticPropHashTable, this, propertyName, slot);\n");        } else {            push(@getOwnPropertySlotImpl, "    return ${namespaceMaybe}getStaticValueSlot<$className, Base>(exec, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n");        }    } else {        push(@getOwnPropertySlotImpl, "    return Base::getOwnPropertySlot(exec, propertyName, slot);\n");    }    return @getOwnPropertySlotImpl;}sub GenerateGetOwnPropertyDescriptorBody{    my ($dataNode, $interfaceName, $className, $implClassName, $hasAttributes, $inlined) = @_;        my $namespaceMaybe = ($inlined ? "JSC::" : "");        my @getOwnPropertyDescriptorImpl = ();    if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) {        if ($interfaceName eq "DOMWindow") {            push(@implContent, "    if (!static_cast<$className*>(thisObject)->allowsAccessFrom(exec))\n");        } else {            push(@implContent, "    if (!allowsAccessFromFrame(exec, static_cast<$className*>(thisObject)->impl()->frame()))\n");        }        push(@implContent, "        return false;\n");    }        if ($interfaceName eq "NamedNodeMap" or $interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") {        push(@getOwnPropertyDescriptorImpl, "    ${namespaceMaybe}JSValue proto = prototype();\n");        push(@getOwnPropertyDescriptorImpl, "    if (proto.isObject() && static_cast<${namespaceMaybe}JSObject*>(asObject(proto))->hasProperty(exec, propertyName))\n");        push(@getOwnPropertyDescriptorImpl, "        return false;\n\n");    }        my $manualLookupGetterGeneration = sub {        my $requiresManualLookup = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasNameGetter"};        if ($requiresManualLookup) {            push(@getOwnPropertyDescriptorImpl, "    const ${namespaceMaybe}HashEntry* entry = ${className}Table.entry(exec, propertyName);\n");            push(@getOwnPropertyDescriptorImpl, "    if (entry) {\n");            push(@getOwnPropertyDescriptorImpl, "        PropertySlot slot;\n");            push(@getOwnPropertyDescriptorImpl, "        slot.setCustom(this, entry->propertyGetter());\n");            push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());\n");            push(@getOwnPropertyDescriptorImpl, "        return true;\n");            push(@getOwnPropertyDescriptorImpl, "    }\n");        }    };        if (!$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {        &$manualLookupGetterGeneration();    }        if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {        push(@getOwnPropertyDescriptorImpl, "    bool ok;\n");        push(@getOwnPropertyDescriptorImpl, "    unsigned index = propertyName.toUInt32(ok);\n");        push(@getOwnPropertyDescriptorImpl, "    if (ok && index < static_cast<$implClassName*>(impl())->length()) {\n");        if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {            # Assume that if there's a setter, the index will be writable            if ($dataNode->extendedAttributes->{"HasIndexSetter"} || $dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {                push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(getByIndex(exec, index), ${namespaceMaybe}DontDelete);\n");            } else {                push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(getByIndex(exec, index), ${namespaceMaybe}DontDelete | ${namespaceMaybe}ReadOnly);\n");            }        } else {            push(@getOwnPropertyDescriptorImpl, "        ${namespaceMaybe}PropertySlot slot;\n");            push(@getOwnPropertyDescriptorImpl, "        slot.setCustomIndex(this, index, indexGetter);\n");            # Assume that if there's a setter, the index will be writable            if ($dataNode->extendedAttributes->{"HasIndexSetter"} || $dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {                push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(slot.getValue(exec, propertyName), ${namespaceMaybe}DontDelete);\n");            } else {                push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(slot.getValue(exec, propertyName), ${namespaceMaybe}DontDelete | ${namespaceMaybe}ReadOnly);\n");            }        }        push(@getOwnPropertyDescriptorImpl, "        return true;\n");        push(@getOwnPropertyDescriptorImpl, "    }\n");    }        if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {        push(@getOwnPropertyDescriptorImpl, "    if (canGetItemsForName(exec, static_cast<$implClassName*>(impl()), propertyName)) {\n");        push(@getOwnPropertyDescriptorImpl, "        ${namespaceMaybe}PropertySlot slot;\n");        push(@getOwnPropertyDescriptorImpl, "        slot.setCustom(this, nameGetter);\n");        push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);\n");        push(@getOwnPropertyDescriptorImpl, "        return true;\n");        push(@getOwnPropertyDescriptorImpl, "    }\n");        if ($inlined) {            $headerIncludes{"wtf/text/AtomicString.h"} = 1;        } else {            $implIncludes{"wtf/text/AtomicString.h"} = 1;        }    }        if ($dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {        &$manualLookupGetterGeneration();    }        if ($dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}) {        push(@getOwnPropertyDescriptorImpl, "    if (getOwnPropertyDescriptorDelegate(exec, propertyName, descriptor))\n");        push(@getOwnPropertyDescriptorImpl, "        return true;\n");    }        if ($hasAttributes) {        if ($inlined) {            die "Cannot inline if NoStaticTables is set." if ($dataNode->extendedAttributes->{"NoStaticTables"});            push(@getOwnPropertyDescriptorImpl, "    return ${namespaceMaybe}getStaticValueDescriptor<$className, Base>(exec, s_info.staticPropHashTable, this, propertyName, descriptor);\n");        } else {            push(@getOwnPropertyDescriptorImpl, "    return ${namespaceMaybe}getStaticValueDescriptor<$className, Base>(exec, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");        }    } else {        push(@getOwnPropertyDescriptorImpl, "    return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);\n");    }        return @getOwnPropertyDescriptorImpl;}sub GenerateHeaderContentHeader{    my $dataNode = shift;    my $className = "JS" . $dataNode->name;    my @headerContentHeader = split("\r", $headerTemplate);    # - Add header protection    push(@headerContentHeader, "\n#ifndef $className" . "_h");    push(@headerContentHeader, "\n#define $className" . "_h\n\n");    my $conditionalString = GenerateConditionalString($dataNode);    push(@headerContentHeader, "#if ${conditionalString}\n\n") if $conditionalString;    return @headerContentHeader;}sub GenerateImplementationContentHeader{    my $dataNode = shift;    my $className = "JS" . $dataNode->name;    my @implContentHeader = split("\r", $headerTemplate);    push(@implContentHeader, "\n#include \"config.h\"\n");    my $conditionalString = GenerateConditionalString($dataNode);    push(@implContentHeader, "\n#if ${conditionalString}\n\n") if $conditionalString;    push(@implContentHeader, "#include \"$className.h\"\n\n");    return @implContentHeader;}my %usesToJSNewlyCreated = (    "CDATASection" => 1,    "Element" => 1,    "Node" => 1,    "Text" => 1,    "Touch" => 1,    "TouchList" => 1);sub GenerateHeader{    my $object = shift;    my $dataNode = shift;    my $interfaceName = $dataNode->name;    my $className = "JS$interfaceName";    my $implClassName = $interfaceName;    my @ancestorInterfaceNames = ();    my %structureFlags = ();    # We only support multiple parents with SVG (for now).    if (@{$dataNode->parents} > 1) {        die "A class can't have more than one parent" unless $interfaceName =~ /SVG/;        $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@ancestorInterfaceNames);    }    my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};    my $hasRealParent = @{$dataNode->parents} > 0;    my $hasParent = $hasLegacyParent || $hasRealParent;    my $parentClassName = GetParentClassName($dataNode);    my $eventTarget = $dataNode->extendedAttributes->{"EventTarget"};    my $needsMarkChildren = $dataNode->extendedAttributes->{"CustomMarkFunction"} || $dataNode->extendedAttributes->{"EventTarget"};        # - Add default header template and header protection    push(@headerContentHeader, GenerateHeaderContentHeader($dataNode));    if ($hasParent) {        $headerIncludes{"$parentClassName.h"} = 1;    } else {        $headerIncludes{"JSDOMBinding.h"} = 1;        $headerIncludes{"<runtime/JSGlobalObject.h>"} = 1;        $headerIncludes{"<runtime/ObjectPrototype.h>"} = 1;    }    if ($dataNode->extendedAttributes->{"CustomCall"}) {        $headerIncludes{"<runtime/CallData.h>"} = 1;    }    if ($dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"}) {        $headerIncludes{"<runtime/Lookup.h>"} = 1;        $headerIncludes{"<wtf/AlwaysInline.h>"} = 1;    }    if ($hasParent && $dataNode->extendedAttributes->{"GenerateNativeConverter"}) {        $headerIncludes{"$implClassName.h"} = 1;    }        $headerIncludes{"<runtime/JSObjectWithGlobalObject.h>"} = 1;    $headerIncludes{"SVGElement.h"} = 1 if $className =~ /^JSSVG/;    my $implType = $implClassName;    my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implType);    $implType = $svgNativeType if $svgNativeType;    my $svgPropertyOrListPropertyType;    $svgPropertyOrListPropertyType = $svgPropertyType if $svgPropertyType;    $svgPropertyOrListPropertyType = $svgListPropertyType if $svgListPropertyType;    my $numConstants = @{$dataNode->constants};    my $numAttributes = @{$dataNode->attributes};    my $numFunctions = @{$dataNode->functions};    push(@headerContent, "\nnamespace WebCore {\n\n");    if ($codeGenerator->IsSVGAnimatedType($implClassName)) {        $headerIncludes{"$implClassName.h"} = 1;    } else {        # Implementation class forward declaration        AddClassForwardIfNeeded($implClassName) unless $svgPropertyOrListPropertyType;    }    AddClassForwardIfNeeded("JSDOMWindowShell") if $interfaceName eq "DOMWindow";    # Class declaration    push(@headerContent, "class $className : public $parentClassName {\n");    push(@headerContent, "    typedef $parentClassName Base;\n");    push(@headerContent, "public:\n");    # Constructor    if ($interfaceName eq "DOMWindow") {        push(@headerContent, "    $className(JSC::JSGlobalData&, JSC::Structure*, PassRefPtr<$implType>, JSDOMWindowShell*);\n");    } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {        push(@headerContent, "    $className(JSC::JSGlobalData&, JSC::Structure*, PassRefPtr<$implType>);\n");    } else {        push(@headerContent, "    $className(JSC::Structure*, JSDOMGlobalObject*, PassRefPtr<$implType>);\n");    }    # Prototype    push(@headerContent, "    static JSC::JSObject* createPrototype(JSC::ExecState*, JSC::JSGlobalObject*);\n") unless ($dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"});    $headerTrailingIncludes{"${className}Custom.h"} = 1 if $dataNode->extendedAttributes->{"CustomHeader"};    $implIncludes{"${className}Custom.h"} = 1 if !$dataNode->extendedAttributes->{"CustomHeader"} && ($dataNode->extendedAttributes->{"CustomPutFunction"} || $dataNode->extendedAttributes->{"DelegatingPutFunction"});    my $hasGetter = $numAttributes > 0                  || !($dataNode->extendedAttributes->{"OmitConstructor"}                 || $dataNode->extendedAttributes->{"CustomConstructor"})                 || $dataNode->extendedAttributes->{"HasIndexGetter"}                 || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}                 || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}                 || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}                 || $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}                 || $dataNode->extendedAttributes->{"HasNameGetter"}                 || $dataNode->extendedAttributes->{"HasOverridingNameGetter"};    # Getters    if ($hasGetter) {        push(@headerContent, "    virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);\n");        push(@headerContent, "    virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&);\n");        push(@headerContent, "    virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);\n") if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) && !$dataNode->extendedAttributes->{"HasOverridingNameGetter"};        push(@headerContent, "    bool getOwnPropertySlotDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"};        push(@headerContent, "    bool getOwnPropertyDescriptorDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n") if $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"};        $structureFlags{"JSC::OverridesGetOwnPropertySlot"} = 1;    }    # Check if we have any writable properties    my $hasReadWriteProperties = 0;    foreach (@{$dataNode->attributes}) {        if ($_->type !~ /^readonly\ attribute$/) {            $hasReadWriteProperties = 1;        }    }    my $hasSetter = $hasReadWriteProperties                 || $dataNode->extendedAttributes->{"CustomPutFunction"}                 || $dataNode->extendedAttributes->{"DelegatingPutFunction"}                 || $dataNode->extendedAttributes->{"HasCustomIndexSetter"};    # Getters    if ($hasSetter) {        push(@headerContent, "    virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);\n");        push(@headerContent, "    virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValue);\n") if $dataNode->extendedAttributes->{"HasCustomIndexSetter"};        push(@headerContent, "    bool putDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, JSC::PutPropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingPutFunction"};    }    # Class info    push(@headerContent, "    static const JSC::ClassInfo s_info;\n\n");    # Structure ID    if ($interfaceName eq "DOMWindow") {        $structureFlags{"JSC::ImplementsHasInstance"} = 1;        $structureFlags{"JSC::NeedsThisConversion"} = 1;    }    push(@headerContent,        "    static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)\n" .        "    {\n" .        "        return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);\n" .        "    }\n\n");    # visit function    if ($needsMarkChildren) {        push(@headerContent, "    virtual void visitChildren(JSC::SlotVisitor&);\n\n");        $structureFlags{"JSC::OverridesVisitChildren"} = 1;    }    # Custom pushEventHandlerScope function    push(@headerContent, "    virtual JSC::ScopeChainNode* pushEventHandlerScope(JSC::ExecState*, JSC::ScopeChainNode*) const;\n\n") if $dataNode->extendedAttributes->{"CustomPushEventHandlerScope"};    # Custom call functions    push(@headerContent, "    virtual JSC::CallType getCallData(JSC::CallData&);\n\n") if $dataNode->extendedAttributes->{"CustomCall"};    # Custom deleteProperty function    push(@headerContent, "    virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&);\n") if $dataNode->extendedAttributes->{"CustomDeleteProperty"};    # Custom getPropertyNames function exists on DOMWindow    if ($interfaceName eq "DOMWindow") {        push(@headerContent, "    virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n");        $structureFlags{"JSC::OverridesGetPropertyNames"} = 1;    }    # Custom defineProperty function exists on DOMWindow    push(@headerContent, "    virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&, bool shouldThrow);\n") if $interfaceName eq "DOMWindow";    # Custom getOwnPropertyNames function    if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"} || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {        push(@headerContent, "    virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n");        $structureFlags{"JSC::OverridesGetPropertyNames"} = 1;           }    # Custom defineGetter function    push(@headerContent, "    virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomDefineGetter"};    # Custom defineSetter function    push(@headerContent, "    virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomDefineSetter"};    # Custom lookupGetter function    push(@headerContent, "    virtual JSC::JSValue lookupGetter(JSC::ExecState*, const JSC::Identifier& propertyName);\n") if $dataNode->extendedAttributes->{"CustomLookupGetter"};    # Custom lookupSetter function    push(@headerContent, "    virtual JSC::JSValue lookupSetter(JSC::ExecState*, const JSC::Identifier& propertyName);\n") if $dataNode->extendedAttributes->{"CustomLookupSetter"};    # Override toBoolean to return false for objects that want to 'MasqueradesAsUndefined'.    if ($dataNode->extendedAttributes->{"MasqueradesAsUndefined"}) {        push(@headerContent, "    virtual bool toBoolean(JSC::ExecState*) const { return false; };\n");        $structureFlags{"JSC::MasqueradesAsUndefined"} = 1;    }    # Constructor object getter    push(@headerContent, "    static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*);\n") if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"}));    my $numCustomFunctions = 0;    my $numCustomAttributes = 0;    # Attribute and function enums    if ($numAttributes > 0) {        foreach (@{$dataNode->attributes}) {            my $attribute = $_;            $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"};            $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"CustomGetter"} || $attribute->signature->extendedAttributes->{"JSCCustomGetter"};            $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"CustomSetter"} || $attribute->signature->extendedAttributes->{"JSCCustomSetter"};            if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) {                push(@headerContent, "    static const unsigned " . $attribute->signature->name . "Slot = $numCachedAttributes + Base::AnonymousSlotCount;\n");                $numCachedAttributes++;            }        }    }    if ($numCachedAttributes > 0) {        push(@headerContent, "    using $parentClassName" . "::putAnonymousValue;\n");        push(@headerContent, "    using $parentClassName" . "::getAnonymousValue;\n");    }    if ($numCustomAttributes > 0) {        push(@headerContent, "\n    // Custom attributes\n");        foreach my $attribute (@{$dataNode->attributes}) {            if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"}) {                push(@headerContent, "    JSC::JSValue " . $codeGenerator->WK_lcfirst($attribute->signature->name) . "(JSC::ExecState*) const;\n");                if ($attribute->type !~ /^readonly/) {                    push(@headerContent, "    void set" . $codeGenerator->WK_ucfirst($attribute->signature->name) . "(JSC::ExecState*, JSC::JSValue);\n");                }            } elsif ($attribute->signature->extendedAttributes->{"CustomGetter"} || $attribute->signature->extendedAttributes->{"JSCCustomGetter"}) {                push(@headerContent, "    JSC::JSValue " . $codeGenerator->WK_lcfirst($attribute->signature->name) . "(JSC::ExecState*) const;\n");            } elsif ($attribute->signature->extendedAttributes->{"CustomSetter"} || $attribute->signature->extendedAttributes->{"JSCCustomSetter"}) {                if ($attribute->type !~ /^readonly/) {                    push(@headerContent, "    void set" . $codeGenerator->WK_ucfirst($attribute->signature->name) . "(JSC::ExecState*, JSC::JSValue);\n");                }            }        }    }    foreach my $function (@{$dataNode->functions}) {        $numCustomFunctions++ if $function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"JSCCustom"};    }    if ($numCustomFunctions > 0) {        push(@headerContent, "\n    // Custom functions\n");        foreach my $function (@{$dataNode->functions}) {            if ($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"JSCCustom"}) {                my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementationFunction"} || $codeGenerator->WK_lcfirst($function->signature->name);                push(@headerContent, "    JSC::JSValue " . $functionImplementationName . "(JSC::ExecState*);\n");            }        }    }    if (!$hasParent) {        push(@headerContent, "    $implType* impl() const { return m_impl.get(); }\n\n");        push(@headerContent, "private:\n");        push(@headerContent, "    RefPtr<$implType> m_impl;\n");    } elsif ($dataNode->extendedAttributes->{"GenerateNativeConverter"}) {        push(@headerContent, "    $implClassName* impl() const\n");        push(@headerContent, "    {\n");        push(@headerContent, "        return static_cast<$implClassName*>(Base::impl());\n");        push(@headerContent, "    }\n");    }        # anonymous slots    if ($numCachedAttributes) {        push(@headerContent, "public:\n");        push(@headerContent, "    static const unsigned AnonymousSlotCount = $numCachedAttributes + Base::AnonymousSlotCount;\n");    }    # structure flags    push(@headerContent, "protected:\n");    push(@headerContent, "    static const unsigned StructureFlags = ");    foreach my $structureFlag (keys %structureFlags) {        push(@headerContent, $structureFlag . " | ");    }    push(@headerContent, "Base::StructureFlags;\n");    # Index getter    if ($dataNode->extendedAttributes->{"HasIndexGetter"}) {        push(@headerContent, "    static JSC::JSValue indexGetter(JSC::ExecState*, JSC::JSValue, unsigned);\n");    }    if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {        push(@headerContent, "    JSC::JSValue getByIndex(JSC::ExecState*, unsigned index);\n");            }        # Index setter    if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {        push(@headerContent, "    void indexSetter(JSC::ExecState*, unsigned index, JSC::JSValue);\n");    }    # Name getter    if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {        push(@headerContent, "private:\n");        push(@headerContent, "    static bool canGetItemsForName(JSC::ExecState*, $implClassName*, const JSC::Identifier&);\n");        push(@headerContent, "    static JSC::JSValue nameGetter(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&);\n");    }    push(@headerContent, "};\n\n");    if ($dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"} && !$dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}) {        push(@headerContent, "ALWAYS_INLINE bool ${className}::getOwnPropertySlot(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertySlot& slot)\n");        push(@headerContent, "{\n");        push(@headerContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 1));        push(@headerContent, "}\n\n");        push(@headerContent, "ALWAYS_INLINE bool ${className}::getOwnPropertyDescriptor(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertyDescriptor& descriptor)\n");        push(@headerContent, "{\n");        push(@headerContent, GenerateGetOwnPropertyDescriptorBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 1));        push(@headerContent, "}\n\n");    }    if ($dataNode->extendedAttributes->{"GenerateIsReachable"} ||         $dataNode->extendedAttributes->{"CustomIsReachable"} ||         $dataNode->extendedAttributes->{"CustomFinalize"} ||        $dataNode->extendedAttributes->{"ActiveDOMObject"}) {        push(@headerContent, "class JS${implType}Owner : public JSC::WeakHandleOwner {\n");        push(@headerContent, "    virtual bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::SlotVisitor&);\n");        push(@headerContent, "    virtual void finalize(JSC::Handle<JSC::Unknown>, void* context);\n");        push(@headerContent, "};\n");        push(@headerContent, "\n");        push(@headerContent, "inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld*, $implType*)\n");        push(@headerContent, "{\n");        push(@headerContent, "    DEFINE_STATIC_LOCAL(JS${implType}Owner, js${implType}Owner, ());\n");        push(@headerContent, "    return &js${implType}Owner;\n");        push(@headerContent, "}\n");        push(@headerContent, "\n");        push(@headerContent, "inline void* wrapperContext(DOMWrapperWorld* world, $implType*)\n");        push(@headerContent, "{\n");        push(@headerContent, "    return world;\n");        push(@headerContent, "}\n");        push(@headerContent, "\n");    }    if (!$hasParent || $dataNode->extendedAttributes->{"GenerateToJS"} || $dataNode->extendedAttributes->{"CustomToJS"}) {        push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType*);\n");    }    if (!$hasParent || $dataNode->extendedAttributes->{"GenerateNativeConverter"}) {        if ($interfaceName eq "NodeFilter") {            push(@headerContent, "PassRefPtr<NodeFilter> toNodeFilter(JSC::JSGlobalData&, JSC::JSValue);\n");        } else {            push(@headerContent, "$implType* to${interfaceName}(JSC::JSValue);\n");        }    }    if ($usesToJSNewlyCreated{$interfaceName}) {        push(@headerContent, "JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject*, $interfaceName*);\n");    }        push(@headerContent, "\n");    # Add prototype declaration.    %structureFlags = ();    push(@headerContent, "class ${className}Prototype : public JSC::JSObjectWithGlobalObject {\n");    push(@headerContent, "    typedef JSC::JSObjectWithGlobalObject Base;\n");    push(@headerContent, "public:\n");    if ($interfaceName eq "DOMWindow") {        push(@headerContent, "    void* operator new(size_t);\n");    } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {        push(@headerContent, "    void* operator new(size_t, JSC::JSGlobalData*);\n");    } else {        push(@headerContent, "    static JSC::JSObject* self(JSC::ExecState*, JSC::JSGlobalObject*);\n");    }    push(@headerContent, "    static const JSC::ClassInfo s_info;\n");    if ($numFunctions > 0 || $numConstants > 0 || $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) {        push(@headerContent, "    virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n");        push(@headerContent, "    virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n");        push(@headerContent, "    bool getOwnPropertySlotDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"};        push(@headerContent, "    bool getOwnPropertyDescriptorDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n") if $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"};        $structureFlags{"JSC::OverridesGetOwnPropertySlot"} = 1;    }    if ($dataNode->extendedAttributes->{"CustomMarkFunction"} or $needsMarkChildren) {        $structureFlags{"JSC::OverridesVisitChildren"} = 1;    }    push(@headerContent,        "    static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)\n" .        "    {\n" .        "        return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);\n" .        "    }\n");    if ($dataNode->extendedAttributes->{"DelegatingPrototypePutFunction"}) {        push(@headerContent, "    virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);\n");        push(@headerContent, "    bool putDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, JSC::PutPropertySlot&);\n");    }    # Custom defineGetter function    push(@headerContent, "    virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomPrototypeDefineGetter"};    push(@headerContent, "    ${className}Prototype(JSC::JSGlobalData& globalData, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) : JSC::JSObjectWithGlobalObject(globalData, globalObject, structure) { }\n");    # structure flags    push(@headerContent, "protected:\n");    push(@headerContent, "    static const unsigned StructureFlags = ");    foreach my $structureFlag (keys %structureFlags) {        push(@headerContent, $structureFlag . " | ");    }    push(@headerContent, "Base::StructureFlags;\n");    push(@headerContent, "};\n\n");    # Conditionally emit the constructor object's declaration    if ($dataNode->extendedAttributes->{"CustomConstructFunction"}) {        GenerateConstructorDeclaration(\@headerContent, $className, $dataNode);    }    if ($numFunctions > 0) {        push(@headerContent,"// Functions\n\n");        foreach my $function (@{$dataNode->functions}) {            next if $function->{overloadIndex} && $function->{overloadIndex} > 1;            my $functionName = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($function->signature->name);            push(@headerContent, "JSC::EncodedJSValue JSC_HOST_CALL ${functionName}(JSC::ExecState*);\n");        }    }    if ($numAttributes > 0 || !($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {        push(@headerContent,"// Attributes\n\n");        foreach my $attribute (@{$dataNode->attributes}) {            my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");            push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&);\n");            unless ($attribute->type =~ /readonly/) {                my $setter = "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");                push(@headerContent, "void ${setter}(JSC::ExecState*, JSC::JSObject*, JSC::JSValue);\n");            }        }                if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {            my $getter = "js" . $interfaceName . "Constructor";            push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&);\n");        }        if ($dataNode->extendedAttributes->{"ReplaceableConstructor"}) {            my $constructorFunctionName = "setJS" . $interfaceName . "Constructor";            push(@headerContent, "void ${constructorFunctionName}(JSC::ExecState*, JSC::JSObject*, JSC::JSValue);\n");        }    }    if ($numConstants > 0) {        push(@headerContent,"// Constants\n\n");        foreach my $constant (@{$dataNode->constants}) {            my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);            push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&);\n");        }    }    my $conditionalString = GenerateConditionalString($dataNode);    push(@headerContent, "\n} // namespace WebCore\n\n");    push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;    push(@headerContent, "#endif\n");    # - Generate dependencies.    if ($writeDependencies && @ancestorInterfaceNames) {        push(@depsContent, "$className.h : ", join(" ", map { "$_.idl" } @ancestorInterfaceNames), "\n");        push(@depsContent, map { "$_.idl :\n" } @ancestorInterfaceNames);     }}sub GenerateAttributesHashTable($$){    my ($object, $dataNode) = @_;    # FIXME: These should be functions on $dataNode.    my $interfaceName = $dataNode->name;    my $className = "JS$interfaceName";        # - Add all attributes in a hashtable definition    my $numAttributes = @{$dataNode->attributes};    $numAttributes++ if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"}));    return 0  if !$numAttributes;    my $hashSize = $numAttributes;    my $hashName = $className . "Table";    my @hashKeys = ();    my @hashSpecials = ();    my @hashValue1 = ();    my @hashValue2 = ();    my %conditionals = ();    my @entries = ();    foreach my $attribute (@{$dataNode->attributes}) {        my $name = $attribute->signature->name;        push(@hashKeys, $name);        my @specials = ();        push(@specials, "DontDelete") unless $attribute->signature->extendedAttributes->{"Deletable"};        push(@specials, "DontEnum") if $attribute->signature->extendedAttributes->{"DontEnum"};        push(@specials, "ReadOnly") if $attribute->type =~ /readonly/;        my $special = (@specials > 0) ? join(" | ", @specials) : "0";        push(@hashSpecials, $special);        my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");        push(@hashValue1, $getter);        if ($attribute->type =~ /readonly/) {            push(@hashValue2, "0");        } else {            my $setter = "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");            push(@hashValue2, $setter);        }        my $conditional = $attribute->signature->extendedAttributes->{"Conditional"};        if ($conditional) {            $conditionals{$name} = $conditional;        }    }    if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {        push(@hashKeys, "constructor");        my $getter = "js" . $interfaceName . "Constructor";        push(@hashValue1, $getter);        if ($dataNode->extendedAttributes->{"ReplaceableConstructor"}) {            my $setter = "setJS" . $interfaceName . "Constructor";            push(@hashValue2, $setter);            push(@hashSpecials, "DontEnum | DontDelete");        } else {                        push(@hashValue2, "0");            push(@hashSpecials, "DontEnum | ReadOnly");        }    }    $object->GenerateHashTable($hashName, $hashSize,                               \@hashKeys, \@hashSpecials,                               \@hashValue1, \@hashValue2,                               \%conditionals);    return $numAttributes;}sub GenerateParametersCheckExpression{    my $numParameters = shift;    my $function = shift;    my @andExpression = ();    push(@andExpression, "exec->argumentCount() == $numParameters");    my $parameterIndex = 0;    foreach $parameter (@{$function->parameters}) {        last if $parameterIndex >= $numParameters;        my $value = "exec->argument($parameterIndex)";        my $type = $codeGenerator->StripModule($parameter->type);        # Only DOMString or wrapper types are checked.        # For DOMString, Null, Undefined and any Object are accepted too, as        # these are acceptable values for a DOMString argument (any Object can        # be converted to a string via .toString).        if ($codeGenerator->IsStringType($type)) {            push(@andExpression, "(${value}.isNull() || ${value}.isUndefined() || ${value}.isString() || ${value}.isObject())");        } elsif ($parameter->extendedAttributes->{"Callback"}) {            # For Callbacks only checks if the value is null or object.            push(@andExpression, "(${value}.isNull() || ${value}.isObject())");        } elsif (!IsNativeType($type)) {            push(@andExpression, "(${value}.isNull() || (${value}.isObject() && asObject(${value})->inherits(&JS${type}::s_info)))");        }        $parameterIndex++;    }    my $res = join(" && ", @andExpression);    $res = "($res)" if @andExpression > 1;    return $res;}sub GenerateFunctionParametersCheck{    my $function = shift;    my @orExpression = ();    my $numParameters = 0;    foreach $parameter (@{$function->parameters}) {        if ($parameter->extendedAttributes->{"Optional"}) {            push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));        }        $numParameters++;    }    push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));    return join(" || ", @orExpression);}sub GenerateOverloadedPrototypeFunction{    my $function = shift;    my $dataNode = shift;    my $implClassName = shift;    # Generate code for choosing the correct overload to call. Overloads are    # chosen based on the total number of arguments passed and the type of    # values passed in non-primitive argument slots. When more than a single    # overload is applicable, precedence is given according to the order of    # declaration in the IDL.    my $functionName = "js${implClassName}PrototypeFunction" . $codeGenerator->WK_ucfirst($function->signature->name);    push(@implContent, "EncodedJSValue JSC_HOST_CALL ${functionName}(ExecState* exec)\n");    push(@implContent, <<END);{END    foreach my $overload (@{$function->{overloads}}) {        my $parametersCheck = GenerateFunctionParametersCheck($overload);        push(@implContent, "    if ($parametersCheck)\n");        push(@implContent, "        return ${functionName}$overload->{overloadIndex}(exec);\n");    }    push(@implContent, <<END);    return throwVMTypeError(exec);}END}sub GenerateImplementation{    my ($object, $dataNode) = @_;    my $interfaceName = $dataNode->name;    my $className = "JS$interfaceName";    my $implClassName = $interfaceName;    my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};    my $hasRealParent = @{$dataNode->parents} > 0;    my $hasParent = $hasLegacyParent || $hasRealParent;    my $parentClassName = GetParentClassName($dataNode);    my $visibleClassName = GetVisibleClassName($interfaceName);    my $eventTarget = $dataNode->extendedAttributes->{"EventTarget"};    my $needsMarkChildren = $dataNode->extendedAttributes->{"CustomMarkFunction"} || $dataNode->extendedAttributes->{"EventTarget"};    # - Add default header template    push(@implContentHeader, GenerateImplementationContentHeader($dataNode));    AddIncludesForSVGAnimatedType($interfaceName) if $className =~ /^JSSVGAnimated/;    $implIncludes{"<wtf/GetPtr.h>"} = 1;    $implIncludes{"<runtime/PropertyNameArray.h>"} = 1 if $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"};    AddIncludesForType($interfaceName);    @implContent = ();    push(@implContent, "\nusing namespace JSC;\n\n");    push(@implContent, "namespace WebCore {\n\n");    push(@implContent, "ASSERT_CLASS_FITS_IN_CELL($className);\n\n");    my $numAttributes = GenerateAttributesHashTable($object, $dataNode);    my $numConstants = @{$dataNode->constants};    my $numFunctions = @{$dataNode->functions};    # - Add all constants    if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {        $hashSize = $numConstants;        $hashName = $className . "ConstructorTable";        @hashKeys = ();        @hashValue1 = ();        @hashValue2 = ();        @hashSpecials = ();        # FIXME: we should not need a function for every constant.        foreach my $constant (@{$dataNode->constants}) {            push(@hashKeys, $constant->name);            my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);            push(@hashValue1, $getter);            push(@hashValue2, "0");            push(@hashSpecials, "DontDelete | ReadOnly");        }        $object->GenerateHashTable($hashName, $hashSize,                                   \@hashKeys, \@hashSpecials,                                   \@hashValue1, \@hashValue2);        push(@implContent, $codeGenerator->GenerateCompileTimeCheckForEnumsIfNeeded($dataNode));        my $protoClassName = "${className}Prototype";        GenerateConstructorDeclaration(\@implContent, $className, $dataNode) unless $dataNode->extendedAttributes->{"CustomConstructFunction"};        GenerateConstructorDefinition(\@implContent, $className, $protoClassName, $interfaceName, $visibleClassName, $dataNode);    }    # - Add functions and constants to a hashtable definition    $hashSize = $numFunctions + $numConstants;    $hashName = $className . "PrototypeTable";    @hashKeys = ();    @hashValue1 = ();    @hashValue2 = ();    @hashSpecials = ();    # FIXME: we should not need a function for every constant.    foreach my $constant (@{$dataNode->constants}) {        push(@hashKeys, $constant->name);        my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);        push(@hashValue1, $getter);        push(@hashValue2, "0");        push(@hashSpecials, "DontDelete | ReadOnly");    }    foreach my $function (@{$dataNode->functions}) {        next if $function->{overloadIndex} && $function->{overloadIndex} > 1;        my $name = $function->signature->name;        push(@hashKeys, $name);        my $value = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($name);        push(@hashValue1, $value);        my $numParameters = @{$function->parameters};        push(@hashValue2, $numParameters);        my @specials = ();        push(@specials, "DontDelete") unless $function->signature->extendedAttributes->{"Deletable"};        push(@specials, "DontEnum") if $function->signature->extendedAttributes->{"DontEnum"};        push(@specials, "Function");        my $special = (@specials > 0) ? join(" | ", @specials) : "0";        push(@hashSpecials, $special);    }    $object->GenerateHashTable($hashName, $hashSize,                               \@hashKeys, \@hashSpecials,                               \@hashValue1, \@hashValue2);    if ($dataNode->extendedAttributes->{"NoStaticTables"}) {        push(@implContent, "static const HashTable* get${className}PrototypeTable(ExecState* exec)\n");        push(@implContent, "{\n");        push(@implContent, "    return getHashTableForGlobalData(exec->globalData(), &${className}PrototypeTable);\n");        push(@implContent, "}\n\n");        push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleClassName}Prototype\", &JSC::JSObjectWithGlobalObject::s_info, 0, get${className}PrototypeTable };\n\n");    } else {        push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleClassName}Prototype\", &JSC::JSObjectWithGlobalObject::s_info, &${className}PrototypeTable, 0 };\n\n");    }    if ($interfaceName eq "DOMWindow") {        push(@implContent, "void* ${className}Prototype::operator new(size_t size)\n");        push(@implContent, "{\n");        push(@implContent, "    return JSDOMWindow::commonJSGlobalData()->heap.allocate(size);\n");        push(@implContent, "}\n\n");    } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {        push(@implContent, "void* ${className}Prototype::operator new(size_t size, JSGlobalData* globalData)\n");        push(@implContent, "{\n");        push(@implContent, "    return globalData->heap.allocate(size);\n");        push(@implContent, "}\n\n");    } else {        push(@implContent, "JSObject* ${className}Prototype::self(ExecState* exec, JSGlobalObject* globalObject)\n");        push(@implContent, "{\n");        push(@implContent, "    return getDOMPrototype<${className}>(exec, globalObject);\n");        push(@implContent, "}\n\n");    }    if ($numConstants > 0 || $numFunctions > 0 || $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) {        push(@implContent, "bool ${className}Prototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n");        push(@implContent, "{\n");        if ($dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) {            push(@implContent, "    if (getOwnPropertySlotDelegate(exec, propertyName, slot))\n");            push(@implContent, "        return true;\n");        }        if ($numConstants eq 0 && $numFunctions eq 0) {            push(@implContent, "    return Base::getOwnPropertySlot(exec, propertyName, slot);\n");                } elsif ($numConstants eq 0) {            push(@implContent, "    return getStaticFunctionSlot<JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n");        } elsif ($numFunctions eq 0) {            push(@implContent, "    return getStaticValueSlot<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n");        } else {            push(@implContent, "    return getStaticPropertySlot<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n");        }        push(@implContent, "}\n\n");        push(@implContent, "bool ${className}Prototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\n");        push(@implContent, "{\n");                if ($dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) {            push(@implContent, "    if (getOwnPropertyDescriptorDelegate(exec, propertyName, descriptor))\n");            push(@implContent, "        return true;\n");        }                if ($numConstants eq 0 && $numFunctions eq 0) {            push(@implContent, "    return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);\n");                } elsif ($numConstants eq 0) {            push(@implContent, "    return getStaticFunctionDescriptor<JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");        } elsif ($numFunctions eq 0) {            push(@implContent, "    return getStaticValueDescriptor<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");        } else {            push(@implContent, "    return getStaticPropertyDescriptor<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");        }        push(@implContent, "}\n\n");    }    if ($dataNode->extendedAttributes->{"DelegatingPrototypePutFunction"}) {        push(@implContent, "void ${className}Prototype::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)\n");        push(@implContent, "{\n");        push(@implContent, "    if (putDelegate(exec, propertyName, value, slot))\n");        push(@implContent, "        return;\n");        push(@implContent, "    Base::put(exec, propertyName, value, slot);\n");        push(@implContent, "}\n\n");    }    # - Initialize static ClassInfo object    if ($numAttributes > 0 && $dataNode->extendedAttributes->{"NoStaticTables"}) {        push(@implContent, "static const HashTable* get${className}Table(ExecState* exec)\n");        push(@implContent, "{\n");        push(@implContent, "    return getHashTableForGlobalData(exec->globalData(), &${className}Table);\n");        push(@implContent, "}\n\n");    }    push(@implContent, "const ClassInfo $className" . "::s_info = { \"${visibleClassName}\", &" . $parentClassName . "::s_info, ");    if ($numAttributes > 0 && !$dataNode->extendedAttributes->{"NoStaticTables"}) {        push(@implContent, "&${className}Table");    } else {        push(@implContent, "0");    }    if ($numAttributes > 0 && $dataNode->extendedAttributes->{"NoStaticTables"}) {        push(@implContent, ", get${className}Table ");    } else {        push(@implContent, ", 0 ");    }    push(@implContent, "};\n\n");    my $implType = $implClassName;    my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implType);    $implType = $svgNativeType if $svgNativeType;    my $svgPropertyOrListPropertyType;    $svgPropertyOrListPropertyType = $svgPropertyType if $svgPropertyType;    $svgPropertyOrListPropertyType = $svgListPropertyType if $svgListPropertyType;    # Constructor    if ($interfaceName eq "DOMWindow") {        AddIncludesForType("JSDOMWindowShell");        push(@implContent, "${className}::$className(JSGlobalData& globalData, Structure* structure, PassRefPtr<$implType> impl, JSDOMWindowShell* shell)\n");        push(@implContent, "    : $parentClassName(globalData, structure, impl, shell)\n");    } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {        AddIncludesForType($interfaceName);        push(@implContent, "${className}::$className(JSGlobalData& globalData, Structure* structure, PassRefPtr<$implType> impl)\n");        push(@implContent, "    : $parentClassName(globalData, structure, impl)\n");    } else {        push(@implContent, "${className}::$className(Structure* structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl)\n");        if ($hasParent) {            push(@implContent, "    : $parentClassName(structure, globalObject, impl)\n");        } else {            push(@implContent, "    : $parentClassName(structure, globalObject)\n");            push(@implContent, "    , m_impl(impl)\n");        }    }    push(@implContent, "{\n");    push(@implContent, "    ASSERT(inherits(&s_info));\n");    if ($numCachedAttributes > 0) {        push(@implContent, "    for (unsigned i = Base::AnonymousSlotCount; i < AnonymousSlotCount; i++)\n");        push(@implContent, "        putAnonymousValue(globalObject->globalData(), i, JSValue());\n");    }    push(@implContent, "}\n\n");    if ($needsMarkChildren && !$dataNode->extendedAttributes->{"CustomMarkFunction"}) {        push(@implContent, "void ${className}::visitChildren(SlotVisitor& visitor)\n");        push(@implContent, "{\n");        push(@implContent, "    Base::visitChildren(visitor);\n");        push(@implContent, "    impl()->visitJSEventListeners(visitor);\n");        push(@implContent, "}\n\n");    }    if (!$dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"}) {        push(@implContent, "JSObject* ${className}::createPrototype(ExecState* exec, JSGlobalObject* globalObject)\n");        push(@implContent, "{\n");        if ($hasParent && $parentClassName ne "JSC::DOMNodeFilter") {            push(@implContent, "    return new (exec) ${className}Prototype(exec->globalData(), globalObject, ${className}Prototype::createStructure(exec->globalData(), ${parentClassName}Prototype::self(exec, globalObject)));\n");        } else {            push(@implContent, "    return new (exec) ${className}Prototype(exec->globalData(), globalObject, ${className}Prototype::createStructure(globalObject->globalData(), globalObject->objectPrototype()));\n");        }        push(@implContent, "}\n\n");    }    my $hasGetter = $numAttributes > 0                  || !($dataNode->extendedAttributes->{"OmitConstructor"}                  || $dataNode->extendedAttributes->{"CustomConstructor"})                 || $dataNode->extendedAttributes->{"HasIndexGetter"}                 || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}                 || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}                 || $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}                 || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}                 || $dataNode->extendedAttributes->{"HasNameGetter"}                 || $dataNode->extendedAttributes->{"HasOverridingNameGetter"};    # Attributes    if ($hasGetter) {        if (!$dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"} && !$dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}) {            push(@implContent, "bool ${className}::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n");            push(@implContent, "{\n");            push(@implContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 0));            push(@implContent, "}\n\n");            push(@implContent, "bool ${className}::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\n");            push(@implContent, "{\n");            push(@implContent, GenerateGetOwnPropertyDescriptorBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 0));            push(@implContent, "}\n\n");        }        if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"})                 && !$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {            push(@implContent, "bool ${className}::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)\n");            push(@implContent, "{\n");            push(@implContent, "    if (propertyName < static_cast<$implClassName*>(impl())->length()) {\n");            if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {                push(@implContent, "        slot.setValue(getByIndex(exec, propertyName));\n");            } else {                push(@implContent, "        slot.setCustomIndex(this, propertyName, indexGetter);\n");            }            push(@implContent, "        return true;\n");            push(@implContent, "    }\n");            push(@implContent, "    return getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);\n");            push(@implContent, "}\n\n");        }                if ($numAttributes > 0) {            foreach my $attribute (@{$dataNode->attributes}) {                my $name = $attribute->signature->name;                my $type = $codeGenerator->StripModule($attribute->signature->type);                my $getFunctionName = "js" . $interfaceName .  $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");                my $implGetterFunctionName = $codeGenerator->WK_lcfirst($name);                my $attributeConditionalString = GenerateConditionalString($attribute->signature);                push(@implContent, "#if ${attributeConditionalString}\n") if $attributeConditionalString;                push(@implContent, "JSValue ${getFunctionName}(ExecState* exec, JSValue slotBase, const Identifier&)\n");                push(@implContent, "{\n");                push(@implContent, "    ${className}* castedThis = static_cast<$className*>(asObject(slotBase));\n");                if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} &&                         !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurity"} &&                        !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurityOnGet"}) {                    push(@implContent, "    if (!castedThis->allowsAccessFrom(exec))\n");                    push(@implContent, "        return jsUndefined();\n");                }                if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"} || $attribute->signature->extendedAttributes->{"CustomGetter"} || $attribute->signature->extendedAttributes->{"JSCCustomGetter"}) {                    push(@implContent, "    return castedThis->$implGetterFunctionName(exec);\n");                } elsif ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) {                    $implIncludes{"JSDOMBinding.h"} = 1;                    push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");                    push(@implContent, "    return checkNodeSecurity(exec, imp->$implGetterFunctionName()) ? " . NativeToJSValue($attribute->signature, 0, $implClassName, "imp->$implGetterFunctionName()", "castedThis") . " : jsUndefined();\n");                } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) {                    $implIncludes{"Document.h"} = 1;                    $implIncludes{"JSDOMBinding.h"} = 1;                    push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");                    push(@implContent, "    return checkNodeSecurity(exec, imp->contentDocument()) ? " . NativeToJSValue($attribute->signature, 0, $implClassName, "imp->$implGetterFunctionName()", "castedThis") . " : jsUndefined();\n");                } elsif ($type eq "EventListener") {                    $implIncludes{"EventListener.h"} = 1;                    push(@implContent, "    UNUSED_PARAM(exec);\n");                    push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");                    push(@implContent, "    if (EventListener* listener = imp->$implGetterFunctionName()) {\n");                    push(@implContent, "        if (const JSEventListener* jsListener = JSEventListener::cast(listener)) {\n");                    if ($implClassName eq "Document" || $implClassName eq "WorkerContext" || $implClassName eq "SharedWorkerContext" || $implClassName eq "DedicatedWorkerContext") {                        push(@implContent, "            if (JSObject* jsFunction = jsListener->jsFunction(imp))\n");                    } else {                        push(@implContent, "            if (JSObject* jsFunction = jsListener->jsFunction(imp->scriptExecutionContext()))\n");                    }                    push(@implContent, "                return jsFunction;\n");                    push(@implContent, "        }\n");                    push(@implContent, "    }\n");                    push(@implContent, "    return jsNull();\n");                } elsif ($attribute->signature->type =~ /Constructor$/) {                    my $constructorType = $codeGenerator->StripModule($attribute->signature->type);                    $constructorType =~ s/Constructor$//;                    # Constructor attribute is only used by DOMWindow.idl, so it's correct to pass castedThis as the global object                    # Once JSDOMWrappers have a back-pointer to the globalObject we can pass castedThis->globalObject()                    push(@implContent, "    return JS" . $constructorType . "::getConstructor(exec, castedThis);\n");                } elsif (!@{$attribute->getterExceptions}) {                    push(@implContent, "    UNUSED_PARAM(exec);\n");                    my $cacheIndex = 0;                    if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) {                        $cacheIndex = $currentCachedAttribute;                        $currentCachedAttribute++;                        push(@implContent, "    if (JSValue cachedValue = castedThis->getAnonymousValue(" . $className . "::" . $attribute->signature->name . "Slot))\n");                        push(@implContent, "        return cachedValue;\n");                    }                    if ($svgListPropertyType) {                        push(@implContent, "    JSValue result =  " . NativeToJSValue($attribute->signature, 0, $implClassName, "castedThis->impl()->$implGetterFunctionName()", "castedThis") . ";\n");                    } elsif ($svgPropertyOrListPropertyType) {                        push(@implContent, "    $svgPropertyOrListPropertyType& imp = castedThis->impl()->propertyReference();\n");                        if ($svgPropertyOrListPropertyType eq "float") { # Special case for JSSVGNumber                            push(@implContent, "    JSValue result =  " . NativeToJSValue($attribute->signature, 0, $implClassName, "imp", "castedThis") . ";\n");                        } else {                            push(@implContent, "    JSValue result =  " . NativeToJSValue($attribute->signature, 0, $implClassName, "imp.$implGetterFunctionName()", "castedThis") . ";\n");                        }                    } else {                        my $getterExpression = "imp->" . $codeGenerator->GetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute) . ")";                        my $jsType = NativeToJSValue($attribute->signature, 0, $implClassName, $getterExpression, "castedThis");                        push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");                        if ($codeGenerator->IsSVGAnimatedType($type)) {                            push(@implContent, "    RefPtr<$type> obj = $jsType;\n");                            push(@implContent, "    JSValue result =  toJS(exec, castedThis->globalObject(), obj.get());\n");                        } else {                            push(@implContent, "    JSValue result = $jsType;\n");                        }                    }                                        push(@implContent, "    castedThis->putAnonymousValue(exec->globalData(), " . $className . "::" . $attribute->signature->name . "Slot, result);\n") if ($attribute->signature->extendedAttributes->{"CachedAttribute"});                    push(@implContent, "    return result;\n");                } else {                    push(@implContent, "    ExceptionCode ec = 0;\n");                                        if ($svgPropertyOrListPropertyType) {                        push(@implContent, "    $svgPropertyOrListPropertyType imp(*castedThis->impl());\n");                        push(@implContent, "    JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "imp.$implGetterFunctionName(ec)", "castedThis") . ";\n");                    } else {                        push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");                        push(@implContent, "    JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "imp->$implGetterFunctionName(ec)", "castedThis") . ";\n");                    }                    push(@implContent, "    setDOMException(exec, ec);\n");                    push(@implContent, "    return result;\n");                }                push(@implContent, "}\n\n");                push(@implContent, "#endif\n") if $attributeConditionalString;                push(@implContent, "\n");            }            if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {                my $constructorFunctionName = "js" . $interfaceName . "Constructor";                push(@implContent, "JSValue ${constructorFunctionName}(ExecState* exec, JSValue slotBase, const Identifier&)\n");                push(@implContent, "{\n");                push(@implContent, "    ${className}* domObject = static_cast<$className*>(asObject(slotBase));\n");                if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) {                    push(@implContent, "    if (!domObject->allowsAccessFrom(exec))\n");                    push(@implContent, "        return jsUndefined();\n");                }                push(@implContent, "    return ${className}::getConstructor(exec, domObject->globalObject());\n");                push(@implContent, "}\n\n");            }        }        # Check if we have any writable attributes        my $hasReadWriteProperties = 0;        foreach my $attribute (@{$dataNode->attributes}) {            $hasReadWriteProperties = 1 if $attribute->type !~ /^readonly/;        }        my $hasSetter = $hasReadWriteProperties                     || $dataNode->extendedAttributes->{"DelegatingPutFunction"}                     || $dataNode->extendedAttributes->{"HasCustomIndexSetter"};        if ($hasSetter) {            if (!$dataNode->extendedAttributes->{"CustomPutFunction"}) {                push(@implContent, "void ${className}::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)\n");                push(@implContent, "{\n");                if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {                    push(@implContent, "    bool ok;\n");                    push(@implContent, "    unsigned index = propertyName.toUInt32(ok);\n");                    push(@implContent, "    if (ok) {\n");                    push(@implContent, "        indexSetter(exec, index, value);\n");                    push(@implContent, "        return;\n");                    push(@implContent, "    }\n");                }                if ($dataNode->extendedAttributes->{"DelegatingPutFunction"}) {                    push(@implContent, "    if (putDelegate(exec, propertyName, value, slot))\n");                    push(@implContent, "        return;\n");                }                if ($hasReadWriteProperties) {                    push(@implContent, "    lookupPut<$className, Base>(exec, propertyName, value, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, slot);\n");                } else {                    push(@implContent, "    Base::put(exec, propertyName, value, slot);\n");                }                push(@implContent, "}\n\n");            }            if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {                push(@implContent, "void ${className}::put(ExecState* exec, unsigned propertyName, JSValue value)\n");                push(@implContent, "{\n");                push(@implContent, "    indexSetter(exec, propertyName, value);\n");                push(@implContent, "    return;\n");                push(@implContent, "}\n\n");            }            if ($hasReadWriteProperties) {                foreach my $attribute (@{$dataNode->attributes}) {                    if ($attribute->type !~ /^readonly/) {                        my $name = $attribute->signature->name;                        my $type = $codeGenerator->StripModule($attribute->signature->type);                        my $putFunctionName = "setJS" . $interfaceName .  $codeGenerator->WK_ucfirst($name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");                        my $implSetterFunctionName = $codeGenerator->WK_ucfirst($name);                        my $attributeConditionalString = GenerateConditionalString($attribute->signature);                        push(@implContent, "#if ${attributeConditionalString}\n") if $attributeConditionalString;                        push(@implContent, "void ${putFunctionName}(ExecState* exec, JSObject* thisObject, JSValue value)\n");                        push(@implContent, "{\n");                        if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {                            if ($interfaceName eq "DOMWindow") {                                push(@implContent, "    if (!static_cast<$className*>(thisObject)->allowsAccessFrom(exec))\n");                            } else {                                push(@implContent, "    if (!allowsAccessFromFrame(exec, static_cast<$className*>(thisObject)->impl()->frame()))\n");                            }                            push(@implContent, "        return;\n");                        }                        if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"} || $attribute->signature->extendedAttributes->{"CustomSetter"} || $attribute->signature->extendedAttributes->{"JSCCustomSetter"}) {                            push(@implContent, "    static_cast<$className*>(thisObject)->set$implSetterFunctionName(exec, value);\n");                        } elsif ($type eq "EventListener") {                            $implIncludes{"JSEventListener.h"} = 1;                            push(@implContent, "    UNUSED_PARAM(exec);\n");                            push(@implContent, "    ${className}* castedThis = static_cast<${className}*>(thisObject);\n");                            my $windowEventListener = $attribute->signature->extendedAttributes->{"WindowEventListener"};                            if ($windowEventListener) {                                push(@implContent, "    JSDOMGlobalObject* globalObject = castedThis->globalObject();\n");                            }                            push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");                            if ((($interfaceName eq "DOMWindow") or ($interfaceName eq "WorkerContext")) and $name eq "onerror") {                                $implIncludes{"JSErrorHandler.h"} = 1;                                push(@implContent, "    imp->set$implSetterFunctionName(createJSErrorHandler(exec, value, thisObject));\n");                            } else {                                push(@implContent, GenerateAttributeEventListenerCall($className, $implSetterFunctionName, $windowEventListener));                            }                        } elsif ($attribute->signature->type =~ /Constructor$/) {                            my $constructorType = $attribute->signature->type;                            $constructorType =~ s/Constructor$//;                            if ($constructorType ne "DOMObject") {                                $implIncludes{"JS" . $constructorType . ".h"} = 1;                            }                            push(@implContent, "    // Shadowing a built-in constructor\n");                            if ($interfaceName eq "DOMWindow" && $className eq "JSblah") {                                push(@implContent, "    static_cast<$className*>(thisObject)->putDirect(exec->globalData(), exec->propertyNames().constructor, value);\n");                            } else {                                push(@implContent, "    static_cast<$className*>(thisObject)->putDirect(exec->globalData(), Identifier(exec, \"$name\"), value);\n");                            }                        } elsif ($attribute->signature->extendedAttributes->{"Replaceable"}) {                            push(@implContent, "    // Shadowing a built-in object\n");                            push(@implContent, "    static_cast<$className*>(thisObject)->putDirect(exec->globalData(), Identifier(exec, \"$name\"), value);\n");                        } else {                            push(@implContent, "    $className* castedThis = static_cast<$className*>(thisObject);\n");                            push(@implContent, "    $implType* imp = static_cast<$implType*>(castedThis->impl());\n");                            push(@implContent, "    ExceptionCode ec = 0;\n") if @{$attribute->setterExceptions};                            # If the "StrictTypeChecking" extended attribute is present, and the attribute's type is an                            # interface type, then if the incoming value does not implement that interface, a TypeError                            # is thrown rather than silently passing NULL to the C++ code.                            # Per the Web IDL and ECMAScript specifications, incoming values can always be converted to                            # both strings and numbers, so do not throw TypeError if the attribute is of these types.                            if ($attribute->signature->extendedAttributes->{"StrictTypeChecking"}) {                                $implIncludes{"<runtime/Error.h>"} = 1;                                my $argType = $attribute->signature->type;                                if (!IsNativeType($argType)) {                                    push(@implContent, "    if (!value.isUndefinedOrNull() && !value.inherits(&JS${argType}::s_info)) {\n");                                    push(@implContent, "        throwVMTypeError(exec);\n");                                    push(@implContent, "        return;\n");                                    push(@implContent, "    };\n");                                }                            }                            my $nativeValue = JSValueToNative($attribute->signature, "value");                            if ($svgPropertyOrListPropertyType) {                                if ($svgPropertyType) {                                    push(@implContent, "    if (imp->role() == AnimValRole) {\n");                                    push(@implContent, "        setDOMException(exec, NO_MODIFICATION_ALLOWED_ERR);\n");                                    push(@implContent, "        return;\n");                                    push(@implContent, "    }\n");                                }                                push(@implContent, "    $svgPropertyOrListPropertyType& podImp = imp->propertyReference();\n");                                if ($svgPropertyOrListPropertyType eq "float") { # Special case for JSSVGNumber                                    push(@implContent, "    podImp = $nativeValue;\n");                                } else {                                    push(@implContent, "    podImp.set$implSetterFunctionName($nativeValue");                                    push(@implContent, ", ec") if @{$attribute->setterExceptions};                                    push(@implContent, ");\n");                                    push(@implContent, "    setDOMException(exec, ec);\n") if @{$attribute->setterExceptions};                                }                                if ($svgPropertyType) {                                    if (@{$attribute->setterExceptions}) {                                        push(@implContent, "    if (!ec)\n");                                         push(@implContent, "        imp->commitChange();\n");                                    } else {                                        push(@implContent, "    imp->commitChange();\n");                                    }                                }                            } else {                                my $setterExpressionPrefix = $codeGenerator->SetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute);                                push(@implContent, "    imp->$setterExpressionPrefix$nativeValue");                                push(@implContent, ", ec") if @{$attribute->setterExceptions};                                push(@implContent, ");\n");                                push(@implContent, "    setDOMException(exec, ec);\n") if @{$attribute->setterExceptions};                            }                        }                                                push(@implContent, "}\n\n");                        push(@implContent, "#endif\n") if $attributeConditionalString;                        push(@implContent, "\n");                    }                }            }                        if ($dataNode->extendedAttributes->{"ReplaceableConstructor"}) {                my $constructorFunctionName = "setJS" . $interfaceName . "Constructor";                                push(@implContent, "void ${constructorFunctionName}(ExecState* exec, JSObject* thisObject, JSValue value)\n");                push(@implContent, "{\n");                if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) {                    if ($interfaceName eq "DOMWindow") {                        push(@implContent, "    if (!static_cast<$className*>(thisObject)->allowsAccessFrom(exec))\n");                    } else {                        push(@implContent, "    if (!allowsAccessFromFrame(exec, static_cast<$className*>(thisObject)->impl()->frame()))\n");                    }                    push(@implContent, "        return;\n");                }                push(@implContent, "    // Shadowing a built-in constructor\n");                if ($interfaceName eq "DOMWindow") {                    push(@implContent, "    static_cast<$className*>(thisObject)->putDirect(exec->globalData(), exec->propertyNames().constructor, value);\n");                } else {                    push(@implContent, "    static_cast<$className*>(thisObject)->putDirect(exec->globalData(), Identifier(exec, \"$name\"), value);\n");                }                push(@implContent, "}\n\n");            }                }    }    if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) && !$dataNode->extendedAttributes->{"CustomGetPropertyNames"}) {        push(@implContent, "void ${className}::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)\n");        push(@implContent, "{\n");        if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {            push(@implContent, "    for (unsigned i = 0; i < static_cast<${implClassName}*>(impl())->length(); ++i)\n");            push(@implContent, "        propertyNames.add(Identifier::from(exec, i));\n");        }        push(@implContent, "     Base::getOwnPropertyNames(exec, propertyNames, mode);\n");        push(@implContent, "}\n\n");    }    if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {        push(@implContent, "JSValue ${className}::getConstructor(ExecState* exec, JSGlobalObject* globalObject)\n{\n");        push(@implContent, "    return getDOMConstructor<${className}Constructor>(exec, static_cast<JSDOMGlobalObject*>(globalObject));\n");        push(@implContent, "}\n\n");    }    # Functions    if ($numFunctions > 0) {        foreach my $function (@{$dataNode->functions}) {            AddIncludesForType($function->signature->type);            my $functionName = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($function->signature->name);            if ($function->{overloads} && @{$function->{overloads}} > 1) {                # Append a number to an overloaded method's name to make it unique:                $functionName = $functionName . $function->{overloadIndex};                # Make this function static to avoid compiler warnings, since we                # don't generate a prototype for it in the header.                push(@implContent, "static ");            }                        my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementationFunction"} || $codeGenerator->WK_lcfirst($function->signature->name);            push(@implContent, "EncodedJSValue JSC_HOST_CALL ${functionName}(ExecState* exec)\n");            push(@implContent, "{\n");            $implIncludes{"<runtime/Error.h>"} = 1;            if ($interfaceName eq "DOMWindow") {                push(@implContent, "    $className* castedThis = toJSDOMWindow(exec->hostThisValue().toThisObject(exec));\n");                push(@implContent, "    if (!castedThis)\n");                push(@implContent, "        return throwVMTypeError(exec);\n");            } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {                push(@implContent, "    $className* castedThis = to${className}(exec->hostThisValue().toThisObject(exec));\n");                push(@implContent, "    if (!castedThis)\n");                push(@implContent, "        return throwVMTypeError(exec);\n");            } else {                push(@implContent, "    JSValue thisValue = exec->hostThisValue();\n");                push(@implContent, "    if (!thisValue.inherits(&${className}::s_info))\n");                push(@implContent, "        return throwVMTypeError(exec);\n");                push(@implContent, "    $className* castedThis = static_cast<$className*>(asObject(thisValue));\n");            }            if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} &&                 !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {                push(@implContent, "    if (!castedThis->allowsAccessFrom(exec))\n");                push(@implContent, "        return JSValue::encode(jsUndefined());\n");            }            if ($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"JSCCustom"}) {                push(@implContent, "    return JSValue::encode(castedThis->" . $functionImplementationName . "(exec));\n");            } else {                push(@implContent, "    $implType* imp = static_cast<$implType*>(castedThis->impl());\n");                if ($svgPropertyType) {                    push(@implContent, "    if (imp->role() == AnimValRole) {\n");                    push(@implContent, "        setDOMException(exec, NO_MODIFICATION_ALLOWED_ERR);\n");                    push(@implContent, "        return JSValue::encode(jsUndefined());\n");                    push(@implContent, "    }\n");                    push(@implContent, "    $svgPropertyType& podImp = imp->propertyReference();\n");                }                my $numParameters = @{$function->parameters};                my $requiresAllArguments = $function->signature->extendedAttributes->{"RequiresAllArguments"};                if ($requiresAllArguments) {                    my $numMandatoryParams = @{$function->parameters};                    foreach my $param (reverse(@{$function->parameters})) {                        if ($param->extendedAttributes->{"Optional"}) {                            $numMandatoryParams--;                        } else {                            last;                        }                    }                    push(@implContent, "    if (exec->argumentCount() < $numMandatoryParams)\n");                    if ($requiresAllArguments eq "Raise") {                        push(@implContent, "        return throwVMError(exec, createSyntaxError(exec, \"Not enough arguments\"));\n");                    } else {                        push(@implContent, "        return JSValue::encode(jsUndefined());\n");                    }                }                if (@{$function->raisesExceptions}) {                    push(@implContent, "    ExceptionCode ec = 0;\n");                }                if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) {                    push(@implContent, "    if (!checkNodeSecurity(exec, imp->getSVGDocument(" . (@{$function->raisesExceptions} ? "ec" : "") .")))\n");                    push(@implContent, "        return JSValue::encode(jsUndefined());\n");                    $implIncludes{"JSDOMBinding.h"} = 1;                }                if ($function->signature->name eq "addEventListener") {                    push(@implContent, GenerateEventListenerCall($className, "add"));                } elsif ($function->signature->name eq "removeEventListener") {                    push(@implContent, GenerateEventListenerCall($className, "remove"));                } else {                    my $argsIndex = 0;                    my $paramIndex = 0;                    my $functionString = (($svgPropertyOrListPropertyType and !$svgListPropertyType) ? "podImp." : "imp->") . $functionImplementationName . "(";                    my $hasOptionalArguments = 0;                    if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {                        push(@implContent, "    RefPtr<ScriptArguments> scriptArguments(createScriptArguments(exec, $numParameters));\n");                        push(@implContent, "    size_t maxStackSize = imp->shouldCaptureFullStackTrace() ? ScriptCallStack::maxCallStackSizeToCapture : 1;\n");                        push(@implContent, "    RefPtr<ScriptCallStack> callStack(createScriptCallStack(exec, maxStackSize));\n");                        $implIncludes{"ScriptArguments.h"} = 1;                        $implIncludes{"ScriptCallStack.h"} = 1;                        $implIncludes{"ScriptCallStackFactory.h"} = 1;                    }                    my $callWith = $function->signature->extendedAttributes->{"CallWith"};                    if ($callWith) {                        my $callWithArg = "COMPILE_ASSERT(false)";                        if ($callWith eq "DynamicFrame") {                            push(@implContent, "    Frame* dynamicFrame = toDynamicFrame(exec);\n");                            push(@implContent, "    if (!dynamicFrame)\n");                            push(@implContent, "        return JSValue::encode(jsUndefined());\n");                            $callWithArg = "dynamicFrame";                        } elsif ($callWith eq "ScriptState") {                            $callWithArg = "exec";                        } elsif ($callWith eq "ScriptExecutionContext") {                            push(@implContent, "    ScriptExecutionContext* scriptContext = static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext();\n");                            push(@implContent, "    if (!scriptContext)\n");                            push(@implContent, "        return JSValue::encode(jsUndefined());\n");                            $callWithArg = "scriptContext";                         }                        $functionString .= ", " if $paramIndex;                        $functionString .= $callWithArg;                        $paramIndex++;                    }                    $implIncludes{"ExceptionCode.h"} = 1;                    $implIncludes{"JSDOMBinding.h"} = 1;                    foreach my $parameter (@{$function->parameters}) {                        # Optional callbacks should be treated differently, because they always have a default value (0),                        # and we can reduce the number of overloaded functions that take a different number of parameters.                        if ($parameter->extendedAttributes->{"Optional"} && !$parameter->extendedAttributes->{"Callback"}) {                            # Generate early call if there are enough parameters.                            if (!$hasOptionalArguments) {                                push(@implContent, "\n    int argsCount = exec->argumentCount();\n");                                $hasOptionalArguments = 1;                            }                            push(@implContent, "    if (argsCount <= $argsIndex) {\n");                            GenerateImplementationFunctionCall($function, $functionString, $paramIndex, "    " x 2, $svgPropertyType, $implClassName);                            push(@implContent, "    }\n\n");                        }                        my $name = $parameter->name;                        my $argType = $codeGenerator->StripModule($parameter->type);                        if ($argType eq "XPathNSResolver") {                            push(@implContent, "    RefPtr<XPathNSResolver> customResolver;\n");                            push(@implContent, "    XPathNSResolver* resolver = toXPathNSResolver(exec->argument($argsIndex));\n");                            push(@implContent, "    if (!resolver) {\n");                            push(@implContent, "        customResolver = JSCustomXPathNSResolver::create(exec, exec->argument($argsIndex));\n");                            push(@implContent, "        if (exec->hadException())\n");                            push(@implContent, "            return JSValue::encode(jsUndefined());\n");                            push(@implContent, "        resolver = customResolver.get();\n");                            push(@implContent, "    }\n");                        } elsif ($parameter->extendedAttributes->{"Callback"}) {                            my $callbackClassName = GetCallbackClassName($argType);                            $implIncludes{"$callbackClassName.h"} = 1;                            if ($parameter->extendedAttributes->{"Optional"}) {                                push(@implContent, "    RefPtr<$argType> $name;\n");                                push(@implContent, "    if (exec->argumentCount() > $argsIndex && !exec->argument($argsIndex).isNull() && !exec->argument($argsIndex).isUndefined()) {\n");                                push(@implContent, "        if (!exec->argument($argsIndex).isObject()) {\n");                                push(@implContent, "            setDOMException(exec, TYPE_MISMATCH_ERR);\n");                                push(@implContent, "            return JSValue::encode(jsUndefined());\n");                                push(@implContent, "        }\n");                                push(@implContent, "        $name = ${callbackClassName}::create(asObject(exec->argument($argsIndex)), castedThis->globalObject());\n");                                push(@implContent, "    }\n");                            } else {                                push(@implContent, "    if (exec->argumentCount() <= $argsIndex || !exec->argument($argsIndex).isObject()) {\n");                                push(@implContent, "        setDOMException(exec, TYPE_MISMATCH_ERR);\n");                                push(@implContent, "        return JSValue::encode(jsUndefined());\n");                                push(@implContent, "    }\n");                                push(@implContent, "    RefPtr<$argType> $name = ${callbackClassName}::create(asObject(exec->argument($argsIndex)), castedThis->globalObject());\n");                            }                        } else {                            # If the "StrictTypeChecking" extended attribute is present, and the argument's type is an                            # interface type, then if the incoming value does not implement that interface, a TypeError                            # is thrown rather than silently passing NULL to the C++ code.                            # Per the Web IDL and ECMAScript semantics, incoming values can always be converted to both                            # strings and numbers, so do not throw TypeError if the argument is of these types.                            if ($function->signature->extendedAttributes->{"StrictTypeChecking"}) {                                $implIncludes{"<runtime/Error.h>"} = 1;                                my $argValue = "exec->argument($argsIndex)";                                if (!IsNativeType($argType)) {                                    push(@implContent, "    if (exec->argumentCount() > $argsIndex && !${argValue}.isUndefinedOrNull() && !${argValue}.inherits(&JS${argType}::s_info))\n");                                    push(@implContent, "        return throwVMTypeError(exec);\n");                                }                            }                            push(@implContent, "    " . GetNativeTypeFromSignature($parameter) . " $name(" . JSValueToNative($parameter, "exec->argument($argsIndex)") . ");\n");                            # If a parameter is "an index" and it's negative it should throw an INDEX_SIZE_ERR exception.                            # But this needs to be done in the bindings, because the type is unsigned and the fact that it                            # was negative will be lost by the time we're inside the DOM.                            if ($parameter->extendedAttributes->{"IsIndex"}) {                                push(@implContent, "    if ($name < 0) {\n");                                push(@implContent, "        setDOMException(exec, INDEX_SIZE_ERR);\n");                                push(@implContent, "        return JSValue::encode(jsUndefined());\n");                                push(@implContent, "    }\n");                            }                            # Check if the type conversion succeeded.                            push(@implContent, "    if (exec->hadException())\n");                            push(@implContent, "        return JSValue::encode(jsUndefined());\n");                            if ($codeGenerator->IsSVGTypeNeedingTearOff($argType) and not $implClassName =~ /List$/) {                                push(@implContent, "    if (!$name) {\n");                                push(@implContent, "        setDOMException(exec, TYPE_MISMATCH_ERR);\n");                                push(@implContent, "        return JSValue::encode(jsUndefined());\n");                                push(@implContent, "    }\n");                            }                        }                        $functionString .= ", " if $paramIndex;                        if ($argType eq "NodeFilter") {                            $functionString .= "$name.get()";                        } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($argType) and not $implClassName =~ /List$/) {                            $functionString .= "$name->propertyReference()";                        } else {                            $functionString .= $name;                        }                        $argsIndex++;                        $paramIndex++;                    }                    if ($function->signature->extendedAttributes->{"NeedsUserGestureCheck"}) {                        $functionString .= ", " if $paramIndex;                        $functionString .= "processingUserGesture()";                        $paramIndex++;                    }                    push(@implContent, "\n");                    GenerateImplementationFunctionCall($function, $functionString, $paramIndex, "    ", $svgPropertyType, $implClassName);                }            }            push(@implContent, "}\n\n");            if ($function->{overloads} && @{$function->{overloads}} > 1 && $function->{overloadIndex} == @{$function->{overloads}}) {                # Generate a function dispatching call to the rest of the overloads.                GenerateOverloadedPrototypeFunction($function, $dataNode, $implClassName);            }        }    }    if ($numConstants > 0) {        push(@implContent, "// Constant getters\n\n");        foreach my $constant (@{$dataNode->constants}) {            my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);            # FIXME: this casts into int to match our previous behavior which turned 0xFFFFFFFF in -1 for NodeFilter.SHOW_ALL            push(@implContent, "JSValue ${getter}(ExecState* exec, JSValue, const Identifier&)\n");            push(@implContent, "{\n");            if ($constant->type eq "DOMString") {                push(@implContent, "    return jsStringOrNull(exec, String(" . $constant->value . "));\n");            } else {                push(@implContent, "    UNUSED_PARAM(exec);\n");                push(@implContent, "    return jsNumber(static_cast<int>(" . $constant->value . "));\n");            }            push(@implContent, "}\n\n");        }    }    if ($dataNode->extendedAttributes->{"HasIndexGetter"}) {        push(@implContent, "\nJSValue ${className}::indexGetter(ExecState* exec, JSValue slotBase, unsigned index)\n");        push(@implContent, "{\n");        push(@implContent, "    ${className}* thisObj = static_cast<$className*>(asObject(slotBase));\n");        if (IndexGetterReturnsStrings($implClassName)) {            $implIncludes{"KURL.h"} = 1;            push(@implContent, "    return jsStringOrNull(exec, thisObj->impl()->item(index));\n");        } else {            push(@implContent, "    return toJS(exec, thisObj->globalObject(), static_cast<$implClassName*>(thisObj->impl())->item(index));\n");        }        push(@implContent, "}\n\n");        if ($interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") {            $implIncludes{"JSNode.h"} = 1;            $implIncludes{"Node.h"} = 1;        }    }        if ($dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {        push(@implContent, "\nJSValue ${className}::getByIndex(ExecState*, unsigned index)\n");        push(@implContent, "{\n");        push(@implContent, "    return jsNumber(static_cast<$implClassName*>(impl())->item(index));\n");        push(@implContent, "}\n\n");        if ($interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") {            $implIncludes{"JSNode.h"} = 1;            $implIncludes{"Node.h"} = 1;        }    }    if ($dataNode->extendedAttributes->{"GenerateIsReachable"} || $dataNode->extendedAttributes->{"ActiveDOMObject"}) {        push(@implContent, "static inline bool isObservable(JS${implType}* js${implType})\n");        push(@implContent, "{\n");        push(@implContent, "    if (js${implType}->hasCustomProperties())\n");        push(@implContent, "        return true;\n");        if ($eventTarget) {            push(@implContent, "    if (js${implType}->impl()->hasEventListeners())\n");            push(@implContent, "        return true;\n");        }        push(@implContent, "    return false;\n");        push(@implContent, "}\n\n");        push(@implContent, "bool JS${implType}Owner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)\n");        push(@implContent, "{\n");        push(@implContent, "    JS${implType}* js${implType} = static_cast<JS${implType}*>(handle.get().asCell());\n");        # All ActiveDOMObjects implement hasPendingActivity(), but not all of them        # increment their C++ reference counts when hasPendingActivity() becomes        # true. As a result, ActiveDOMObjects can be prematurely destroyed before        # their pending activities complete. To wallpaper over this bug, JavaScript        # wrappers unconditionally keep ActiveDOMObjects with pending activity alive.        # FIXME: Fix this lifetime issue in the DOM, and move this hasPendingActivity        # check below the isObservable check.        if ($dataNode->extendedAttributes->{"ActiveDOMObject"}) {            push(@implContent, "    if (js${implType}->impl()->hasPendingActivity())\n");            push(@implContent, "        return true;\n");        }        push(@implContent, "    if (!isObservable(js${implType}))\n");        push(@implContent, "        return false;\n");        if ($dataNode->extendedAttributes->{"GenerateIsReachable"}) {            my $rootString;            if ($dataNode->extendedAttributes->{"GenerateIsReachable"} eq "Impl") {                $rootString  = "    ${implType}* root = js${implType}->impl();\n";            } elsif ($dataNode->extendedAttributes->{"GenerateIsReachable"} eq "ImplContext") {                $rootString  = "    WebGLRenderingContext* root = js${implType}->impl()->context();\n";            } elsif ($dataNode->extendedAttributes->{"GenerateIsReachable"} eq "ImplFrame") {                $rootString  = "    Frame* root = js${implType}->impl()->frame();\n";                $rootString .= "    if (!root)\n";                $rootString .= "        return false;\n";            } elsif ($dataNode->extendedAttributes->{"GenerateIsReachable"} eq "ImplDocument") {                $rootString  = "    Document* root = js${implType}->impl()->document();\n";                $rootString .= "    if (!root)\n";                $rootString .= "        return false;\n";            } elsif ($dataNode->extendedAttributes->{"GenerateIsReachable"} eq "ImplElementRoot") {                $rootString  = "    Element* element = js${implType}->impl()->element();\n";                $rootString .= "    if (!element)\n";                $rootString .= "        return false;\n";                $rootString .= "    void* root = WebCore::root(element);\n";            } elsif ($interfaceName eq "CanvasRenderingContext") {                $rootString  = "    void* root = WebCore::root(js${implType}->impl()->canvas());\n";            } elsif ($interfaceName eq "HTMLCollection") {                $rootString  = "    void* root = WebCore::root(js${implType}->impl()->base());\n";            } else {                $rootString  = "    void* root = WebCore::root(js${implType}->impl());\n";            }            push(@implContent, $rootString);            push(@implContent, "    return visitor.containsOpaqueRoot(root);\n");        } else {            push(@implContent, "    UNUSED_PARAM(visitor);\n");            push(@implContent, "    return false;\n");        }        push(@implContent, "}\n\n");    }    if (!$dataNode->extendedAttributes->{"CustomFinalize"} &&        ($dataNode->extendedAttributes->{"GenerateIsReachable"} ||          $dataNode->extendedAttributes->{"CustomIsReachable"} ||         $dataNode->extendedAttributes->{"ActiveDOMObject"})) {        push(@implContent, "void JS${implType}Owner::finalize(JSC::Handle<JSC::Unknown> handle, void* context)\n");        push(@implContent, "{\n");        push(@implContent, "    JS${implType}* js${implType} = static_cast<JS${implType}*>(handle.get().asCell());\n");        push(@implContent, "    DOMWrapperWorld* world = static_cast<DOMWrapperWorld*>(context);\n");        push(@implContent, "    uncacheWrapper(world, js${implType}->impl(), js${implType});\n");        push(@implContent, "}\n\n");    }    if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateToJS"}) and !$dataNode->extendedAttributes->{"CustomToJS"}) {        push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* impl)\n");        push(@implContent, "{\n");        if ($svgPropertyType) {            push(@implContent, "    return wrap<$className, $implType>(exec, globalObject, impl);\n");        } else {            push(@implContent, "    return wrap<$className>(exec, globalObject, impl);\n");        }        push(@implContent, "}\n\n");    }    if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateNativeConverter"}) and !$dataNode->extendedAttributes->{"CustomNativeConverter"}) {        push(@implContent, "$implType* to${interfaceName}(JSC::JSValue value)\n");        push(@implContent, "{\n");        push(@implContent, "    return value.inherits(&${className}::s_info) ? static_cast<$className*>(asObject(value))->impl() : 0");        push(@implContent, ";\n}\n");    }    push(@implContent, "\n}\n");    my $conditionalString = GenerateConditionalString($dataNode);    push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;}sub GenerateCallbackHeader{    my $object = shift;    my $dataNode = shift;    my $interfaceName = $dataNode->name;    my $className = "JS$interfaceName";    # - Add default header template and header protection    push(@headerContentHeader, GenerateHeaderContentHeader($dataNode));    $headerIncludes{"ActiveDOMCallback.h"} = 1;    $headerIncludes{"$interfaceName.h"} = 1;    $headerIncludes{"JSCallbackData.h"} = 1;    $headerIncludes{"<wtf/Forward.h>"} = 1;    push(@headerContent, "\nnamespace WebCore {\n\n");    push(@headerContent, "class $className : public $interfaceName, public ActiveDOMCallback {\n");    push(@headerContent, "public:\n");    # The static create() method.    push(@headerContent, "    static PassRefPtr<$className> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject)\n");    push(@headerContent, "    {\n");    push(@headerContent, "        return adoptRef(new $className(callback, globalObject));\n");    push(@headerContent, "    }\n\n");    # Destructor    push(@headerContent, "    virtual ~$className();\n");    # Functions    my $numFunctions = @{$dataNode->functions};    if ($numFunctions > 0) {        push(@headerContent, "\n    // Functions\n");        foreach my $function (@{$dataNode->functions}) {            my @params = @{$function->parameters};            if (!$function->signature->extendedAttributes->{"Custom"} &&                !(GetNativeType($function->signature->type) eq "bool")) {                push(@headerContent, "    COMPILE_ASSERT(false)");            }            push(@headerContent, "    virtual " . GetNativeType($function->signature->type) . " " . $function->signature->name . "(");            my @args = ();            foreach my $param (@params) {                push(@args, GetNativeType($param->type) . " " . $param->name);            }            push(@headerContent, join(", ", @args));            push(@headerContent, ");\n");        }    }    push(@headerContent, "\nprivate:\n");    # Constructor    push(@headerContent, "    $className(JSC::JSObject* callback, JSDOMGlobalObject*);\n\n");    # Private members    push(@headerContent, "    JSCallbackData* m_data;\n");    push(@headerContent, "};\n\n");    push(@headerContent, "} // namespace WebCore\n\n");    my $conditionalString = GenerateConditionalString($dataNode);    push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;    push(@headerContent, "#endif\n");}sub GenerateCallbackImplementation{    my ($object, $dataNode) = @_;    my $interfaceName = $dataNode->name;    my $className = "JS$interfaceName";    # - Add default header template    push(@implContentHeader, GenerateImplementationContentHeader($dataNode));    $implIncludes{"ScriptExecutionContext.h"} = 1;    $implIncludes{"<runtime/JSLock.h>"} = 1;    $implIncludes{"<wtf/MainThread.h>"} = 1;    @implContent = ();    push(@implContent, "\nusing namespace JSC;\n\n");    push(@implContent, "namespace WebCore {\n\n");    # Constructor    push(@implContent, "${className}::${className}(JSObject* callback, JSDOMGlobalObject* globalObject)\n");    push(@implContent, "    : ActiveDOMCallback(globalObject->scriptExecutionContext())\n");    push(@implContent, "    , m_data(new JSCallbackData(callback, globalObject))\n");    push(@implContent, "{\n");    push(@implContent, "}\n\n");    # Destructor    push(@implContent, "${className}::~${className}()\n");    push(@implContent, "{\n");    push(@implContent, "    ScriptExecutionContext* context = scriptExecutionContext();\n");    push(@implContent, "    // When the context is destroyed, all tasks with a reference to a callback\n");    push(@implContent, "    // should be deleted. So if the context is 0, we are on the context thread.\n");    push(@implContent, "    if (!context || context->isContextThread())\n");    push(@implContent, "        delete m_data;\n");    push(@implContent, "    else\n");    push(@implContent, "        context->postTask(DeleteCallbackDataTask::create(m_data));\n");    push(@implContent, "#ifndef NDEBUG\n");    push(@implContent, "    m_data = 0;\n");    push(@implContent, "#endif\n");    push(@implContent, "}\n");    # Functions    my $numFunctions = @{$dataNode->functions};    if ($numFunctions > 0) {        push(@implContent, "\n// Functions\n");        foreach my $function (@{$dataNode->functions}) {            my @params = @{$function->parameters};            if ($function->signature->extendedAttributes->{"Custom"} ||                !(GetNativeType($function->signature->type) eq "bool")) {                next;            }            AddIncludesForType($function->signature->type);            push(@implContent, "\n" . GetNativeType($function->signature->type) . " ${className}::" . $function->signature->name . "(");            my @args = ();            foreach my $param (@params) {                AddIncludesForType($param->type, 1);                push(@args, GetNativeType($param->type) . " " . $param->name);            }            push(@implContent, join(", ", @args));            push(@implContent, ")\n");            push(@implContent, "{\n");            push(@implContent, "    if (!canInvokeCallback())\n");            push(@implContent, "        return true;\n\n");            push(@implContent, "    RefPtr<$className> protect(this);\n\n");            push(@implContent, "    JSLock lock(SilenceAssertionsOnly);\n\n");            push(@implContent, "    ExecState* exec = m_data->globalObject()->globalExec();\n");            push(@implContent, "    MarkedArgumentBuffer args;\n");            foreach my $param (@params) {                my $paramName = $param->name;                if ($param->type eq "DOMString") {                    push(@implContent, "    args.append(jsString(exec, ${paramName}));\n");                } else {                    push(@implContent, "    args.append(toJS(exec, m_data->globalObject(), ${paramName}));\n");                }            }            push(@implContent, "\n    bool raisedException = false;\n");            push(@implContent, "    m_data->invokeCallback(args, &raisedException);\n");            push(@implContent, "    return !raisedException;\n");            push(@implContent, "}\n");        }    }    push(@implContent, "\n}\n");    my $conditionalString = GenerateConditionalString($dataNode);    push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;}sub GenerateImplementationFunctionCall(){    my $function = shift;    my $functionString = shift;    my $paramIndex = shift;    my $indent = shift;    my $svgPropertyType = shift;    my $implClassName = shift;    if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {        $functionString .= ", " if $paramIndex;        $paramIndex += 2;        $functionString .= "scriptArguments, callStack";    }    if (@{$function->raisesExceptions}) {        $functionString .= ", " if $paramIndex;        $functionString .= "ec";    }    $functionString .= ")";    if ($function->signature->type eq "void") {        push(@implContent, $indent . "$functionString;\n");        push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions};        if ($svgPropertyType) {            if (@{$function->raisesExceptions}) {                push(@implContent, $indent . "if (!ec)\n");                 push(@implContent, $indent . "    imp->commitChange();\n");            } else {                push(@implContent, $indent . "imp->commitChange();\n");            }        }        push(@implContent, $indent . "return JSValue::encode(jsUndefined());\n");    } else {        push(@implContent, "\n" . $indent . "JSC::JSValue result = " . NativeToJSValue($function->signature, 1, $implClassName, $functionString, "castedThis") . ";\n");        push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions};        $callWith = $function->signature->extendedAttributes->{"CallWith"};        if ($callWith and $callWith eq "ScriptState") {            push(@implContent, $indent . "if (exec->hadException())\n");            push(@implContent, $indent . "    return JSValue::encode(jsUndefined());\n");        }        push(@implContent, $indent . "return JSValue::encode(result);\n");    }}sub GetNativeTypeFromSignature{    my $signature = shift;    my $type = $codeGenerator->StripModule($signature->type);    if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) {        # Special-case index arguments because we need to check that they aren't < 0.        return "int";    }    return GetNativeType($type);}my %nativeType = (    "CompareHow" => "Range::CompareHow",    "DOMString" => "const String&",    "DOMObject" => "ScriptValue",    "NodeFilter" => "RefPtr<NodeFilter>",    "SerializedScriptValue" => "RefPtr<SerializedScriptValue>",    "IDBKey" => "RefPtr<IDBKey>",    "boolean" => "bool",    "double" => "double",    "float" => "float",    "short" => "short",    "long" => "int",    "unsigned long" => "unsigned",    "unsigned short" => "unsigned short",    "long long" => "long long",    "unsigned long long" => "unsigned long long",    "MediaQueryListListener" => "RefPtr<MediaQueryListListener>");sub GetNativeType{    my $type = shift;    my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($type);    return "${svgNativeType}*" if $svgNativeType;    return $nativeType{$type} if exists $nativeType{$type};    # For all other types, the native type is a pointer with same type name as the IDL type.    return "${type}*";}sub GetSVGPropertyTypes{    my $implType = shift;    my $svgPropertyType;    my $svgListPropertyType;    my $svgNativeType;    return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $implType =~ /SVG/;        $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implType);    return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $svgNativeType;    # Append space to avoid compilation errors when using  PassRefPtr<$svgNativeType>    $svgNativeType = "$svgNativeType ";    my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implType);    if ($svgNativeType =~ /SVGPropertyTearOff/) {        $svgPropertyType = $svgWrappedNativeType;        $headerIncludes{"$svgWrappedNativeType.h"} = 1;        $headerIncludes{"SVGAnimatedPropertyTearOff.h"} = 1;    } elsif ($svgNativeType =~ /SVGListPropertyTearOff/ or $svgNativeType =~ /SVGStaticListPropertyTearOff/) {        $svgListPropertyType = $svgWrappedNativeType;        $headerIncludes{"$svgWrappedNativeType.h"} = 1;        $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;    } elsif ($svgNativeType =~ /SVGTransformListPropertyTearOff/) {        $svgListPropertyType = $svgWrappedNativeType;        $headerIncludes{"$svgWrappedNativeType.h"} = 1;        $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;        $headerIncludes{"SVGTransformListPropertyTearOff.h"} = 1;    } elsif ($svgNativeType =~ /SVGPathSegListPropertyTearOff/) {        $svgListPropertyType = $svgWrappedNativeType;        $headerIncludes{"$svgWrappedNativeType.h"} = 1;        $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;        $headerIncludes{"SVGPathSegListPropertyTearOff.h"} = 1;    }    return ($svgPropertyType, $svgListPropertyType, $svgNativeType);}sub IsNativeType{    my $type = shift;    return exists $nativeType{$type};}sub JSValueToNative{    my $signature = shift;    my $value = shift;    my $type = $codeGenerator->StripModule($signature->type);    return "$value.toBoolean(exec)" if $type eq "boolean";    return "$value.toNumber(exec)" if $type eq "double";    return "$value.toFloat(exec)" if $type eq "float";    return "$value.toInt32(exec)" if $type eq "long" or $type eq "short";    return "$value.toUInt32(exec)" if $type eq "unsigned long" or $type eq "unsigned short";    return "static_cast<$type>($value.toInteger(exec))" if $type eq "long long" or $type eq "unsigned long long";    return "valueToDate(exec, $value)" if $type eq "Date";    return "static_cast<Range::CompareHow>($value.toInt32(exec))" if $type eq "CompareHow";    if ($type eq "DOMString") {        return "valueToStringWithNullCheck(exec, $value)" if $signature->extendedAttributes->{"ConvertNullToNullString"} || $signature->extendedAttributes->{"Reflect"};        return "valueToStringWithUndefinedOrNullCheck(exec, $value)" if $signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"};        return "ustringToString($value.toString(exec))";    }    if ($type eq "DOMObject") {        return "exec->globalData(), $value";    }    if ($type eq "NodeFilter") {        $implIncludes{"JS$type.h"} = 1;        return "to$type(exec->globalData(), $value)";    }    if ($type eq "MediaQueryListListener") {        $implIncludes{"MediaQueryListListener.h"} = 1;        return "MediaQueryListListener::create(ScriptValue(exec->globalData(), " . $value ."))";    }    if ($type eq "SerializedScriptValue" or $type eq "any") {        $implIncludes{"SerializedScriptValue.h"} = 1;        return "SerializedScriptValue::create(exec, $value)";    }    if ($type eq "IDBKey") {        $implIncludes{"IDBBindingUtilities.h"} = 1;        $implIncludes{"IDBKey.h"} = 1;        return "createIDBKeyFromValue(exec, $value)";    }    $implIncludes{"HTMLOptionElement.h"} = 1 if $type eq "HTMLOptionElement";    $implIncludes{"JSCustomVoidCallback.h"} = 1 if $type eq "VoidCallback";    $implIncludes{"Event.h"} = 1 if $type eq "Event";    # Default, assume autogenerated type conversion routines    $implIncludes{"JS$type.h"} = 1;    return "to$type($value)";}sub NativeToJSValue{    my $signature = shift;    my $inFunctionCall = shift;    my $implClassName = shift;    my $value = shift;    my $thisValue = shift;    my $type = $codeGenerator->StripModule($signature->type);    return "jsBoolean($value)" if $type eq "boolean";    # Need to check Date type before IsPrimitiveType().    if ($type eq "Date") {        return "jsDateOrNull(exec, $value)";    }    if ($signature->extendedAttributes->{"Reflect"} and ($type eq "unsigned long" or $type eq "unsigned short")) {        $value =~ s/getUnsignedIntegralAttribute/getIntegralAttribute/g;        return "jsNumber(std::max(0, " . $value . "))";    }    if ($codeGenerator->IsPrimitiveType($type) or $type eq "DOMTimeStamp") {        return "jsNumber($value)";    }    if ($codeGenerator->IsStringType($type)) {        $implIncludes{"KURL.h"} = 1;        my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"};        if (defined $conv) {            return "jsStringOrNull(exec, $value)" if $conv eq "Null";            return "jsStringOrUndefined(exec, $value)" if $conv eq "Undefined";            return "jsStringOrFalse(exec, $value)" if $conv eq "False";            die "Unknown value for ConvertNullStringTo extended attribute";        }        $conv = $signature->extendedAttributes->{"ConvertScriptString"};        return "jsOwnedStringOrNull(exec, $value)" if $conv;        $implIncludes{"<runtime/JSString.h>"} = 1;        return "jsString(exec, $value)";    }        my $globalObject = "$thisValue->globalObject()";    if ($type eq "CSSStyleDeclaration") {        $implIncludes{"CSSMutableStyleDeclaration.h"} = 1;    }    if ($type eq "NodeList") {        $implIncludes{"NameNodeList.h"} = 1;    }    if ($type eq "DOMObject") {        if ($implClassName eq "Document") {            $implIncludes{"JSCanvasRenderingContext2D.h"} = 1;        } else {            return "$value.jsValue();";        }    } elsif ($type =~ /SVGPathSeg/) {        $implIncludes{"JS$type.h"} = 1;        $joinedName = $type;        $joinedName =~ s/Abs|Rel//;        $implIncludes{"$joinedName.h"} = 1;    } elsif ($type eq "SerializedScriptValue" or $type eq "any") {        $implIncludes{"SerializedScriptValue.h"} = 1;        return "$value ? $value->deserialize(exec, castedThis->globalObject()) : jsNull()";    } else {        # Default, include header with same name.        $implIncludes{"JS$type.h"} = 1;        $implIncludes{"$type.h"} = 1 if not $codeGenerator->AvoidInclusionOfType($type);    }    return $value if $codeGenerator->IsSVGAnimatedType($type);    if ($signature->extendedAttributes->{"ReturnsNew"}) {                return "toJSNewlyCreated(exec, $globalObject, WTF::getPtr($value))";    }    if ($codeGenerator->IsSVGAnimatedType($implClassName)) {        # Convert from abstract SVGProperty to real type, so the right toJS() method can be invoked.        $value = "static_cast<" . GetNativeType($type) . ">($value)";    } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($type) and not $implClassName =~ /List$/) {        my $tearOffType = $codeGenerator->GetSVGTypeNeedingTearOff($type);        if ($codeGenerator->IsSVGTypeWithWritablePropertiesNeedingTearOff($type) and $inFunctionCall eq 0 and not defined $signature->extendedAttributes->{"Immutable"}) {            my $getter = $value;            $getter =~ s/imp\.//;            $getter =~ s/imp->//;            $getter =~ s/\(\)//;            my $updateMethod = "&${implClassName}::update" . $codeGenerator->WK_ucfirst($getter);            my $selfIsTearOffType = $codeGenerator->IsSVGTypeNeedingTearOff($implClassName);            if ($selfIsTearOffType) {                $implIncludes{"SVGStaticPropertyWithParentTearOff.h"} = 1;                $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyWithParentTearOff<$implClassName, /;                if ($value =~ /matrix/ and $implClassName eq "SVGTransform") {                    # SVGTransform offers a matrix() method for internal usage that returns an AffineTransform                    # and a svgMatrix() method returning a SVGMatrix, used for the bindings.                    $value =~ s/matrix/svgMatrix/;                }                $value = "${tearOffType}::create(castedThis->impl(), $value, $updateMethod)";            } else {                $implIncludes{"SVGStaticPropertyTearOff.h"} = 1;                $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyTearOff<$implClassName, /;                $value = "${tearOffType}::create(imp, $value, $updateMethod)";            }        } elsif ($tearOffType =~ /SVGStaticListPropertyTearOff/) {            my $extraImp = "GetOwnerElementForType<$implClassName, IsDerivedFromSVGElement<$implClassName>::value>::ownerElement(imp), ";            $value = "${tearOffType}::create($extraImp$value)";        } elsif (not $tearOffType =~ /SVG(Point|PathSeg)List/) {            $value = "${tearOffType}::create($value)";        }    }    return "toJS(exec, $globalObject, WTF::getPtr($value))";}sub ceilingToPowerOf2{    my ($size) = @_;    my $powerOf2 = 1;    while ($size > $powerOf2) {        $powerOf2 <<= 1;    }    return $powerOf2;}# Internal Helpersub GenerateHashTable{    my $object = shift;    my $name = shift;    my $size = shift;    my $keys = shift;    my $specials = shift;    my $value1 = shift;    my $value2 = shift;    my $conditionals = shift;    # Generate size data for compact' size hash table    my @table = ();    my @links = ();    my $compactSize = ceilingToPowerOf2($size * 2);    my $maxDepth = 0;    my $collisions = 0;    my $numEntries = $compactSize;    my $i = 0;    foreach (@{$keys}) {        my $depth = 0;        my $h = $object->GenerateHashValue($_) % $numEntries;        while (defined($table[$h])) {            if (defined($links[$h])) {                $h = $links[$h];                $depth++;            } else {                $collisions++;                $links[$h] = $compactSize;                $h = $compactSize;                $compactSize++;            }        }        $table[$h] = $i;        $i++;        $maxDepth = $depth if ($depth > $maxDepth);    }    # Start outputing the hashtables    my $nameEntries = "${name}Values";    $nameEntries =~ s/:/_/g;    if (($name =~ /Prototype/) or ($name =~ /Constructor/)) {        my $type = $name;        my $implClass;        if ($name =~ /Prototype/) {            $type =~ s/Prototype.*//;            $implClass = $type; $implClass =~ s/Wrapper$//;            push(@implContent, "/* Hash table for prototype */\n");        } else {            $type =~ s/Constructor.*//;            $implClass = $type; $implClass =~ s/Constructor$//;            push(@implContent, "/* Hash table for constructor */\n");        }    } else {        push(@implContent, "/* Hash table */\n");    }    # Dump the hash table    my $count = scalar @{$keys} + 1;    push(@implContent, "#if ENABLE(JIT)\n");    push(@implContent, "#define THUNK_GENERATOR(generator) , generator\n");    push(@implContent, "#else\n");    push(@implContent, "#define THUNK_GENERATOR(generator)\n");    push(@implContent, "#endif\n");    push(@implContent, "\nstatic const HashTableValue $nameEntries\[$count\] =\n\{\n");    $i = 0;    foreach my $key (@{$keys}) {        my $conditional;        my $targetType;        if ($conditionals) {            $conditional = $conditionals->{$key};        }        if ($conditional) {            my $conditionalString = GenerateConditionalStringFromAttributeValue($conditional);            push(@implContent, "#if ${conditionalString}\n");        }                if ("@$specials[$i]" =~ m/Function/) {            $targetType = "static_cast<NativeFunction>";        } else {            $targetType = "static_cast<PropertySlot::GetValueFunc>";        }        push(@implContent, "    { \"$key\", @$specials[$i], (intptr_t)" . $targetType . "(@$value1[$i]), (intptr_t)@$value2[$i] THUNK_GENERATOR(0) },\n");        if ($conditional) {            push(@implContent, "#endif\n");        }        ++$i;    }    push(@implContent, "    { 0, 0, 0, 0 THUNK_GENERATOR(0) }\n");    push(@implContent, "};\n\n");    push(@implContent, "#undef THUNK_GENERATOR\n");    my $compactSizeMask = $numEntries - 1;    push(@implContent, "static JSC_CONST_HASHTABLE HashTable $name = { $compactSize, $compactSizeMask, $nameEntries, 0 };\n");}# Internal helpersub GenerateHashValue{    my $object = shift;    @chars = split(/ */, $_[0]);    # This hash is designed to work on 16-bit chunks at a time. But since the normal case    # (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they    # were 16-bit chunks, which should give matching results    my $EXP2_32 = 4294967296;    my $hash = 0x9e3779b9;    my $l    = scalar @chars; #I wish this was in Ruby --- Maks    my $rem  = $l & 1;    $l = $l >> 1;    my $s = 0;    # Main loop    for (; $l > 0; $l--) {        $hash   += ord($chars[$s]);        my $tmp = leftShift(ord($chars[$s+1]), 11) ^ $hash;        $hash   = (leftShift($hash, 16)% $EXP2_32) ^ $tmp;        $s += 2;        $hash += $hash >> 11;        $hash %= $EXP2_32;    }    # Handle end case    if ($rem != 0) {        $hash += ord($chars[$s]);        $hash ^= (leftShift($hash, 11)% $EXP2_32);        $hash += $hash >> 17;    }    # Force "avalanching" of final 127 bits    $hash ^= leftShift($hash, 3);    $hash += ($hash >> 5);    $hash = ($hash% $EXP2_32);    $hash ^= (leftShift($hash, 2)% $EXP2_32);    $hash += ($hash >> 15);    $hash = $hash% $EXP2_32;    $hash ^= (leftShift($hash, 10)% $EXP2_32);    # this avoids ever returning a hash code of 0, since that is used to    # signal "hash not computed yet", using a value that is likely to be    # effectively the same as 0 when the low bits are masked    $hash = 0x80000000 if ($hash == 0);    return $hash;}# Internal helpersub WriteData{    if (defined($IMPL)) {        # Write content to file.        print $IMPL @implContentHeader;        my @includes = ();        foreach my $include (keys %implIncludes) {            my $checkType = $include;            $checkType =~ s/\.h//;            next if $codeGenerator->IsSVGAnimatedType($checkType);            $include = "\"$include\"" unless $include =~ /^["<]/; # "            push @includes, $include;        }        foreach my $include (sort @includes) {            print $IMPL "#include $include\n";        }        print $IMPL @implContent;        close($IMPL);        undef($IMPL);        @implContentHeader = ();        @implContent = ();        %implIncludes = ();    }    if (defined($HEADER)) {        # Write content to file.        print $HEADER @headerContentHeader;        my @includes = ();        foreach my $include (keys %headerIncludes) {            $include = "\"$include\"" unless $include =~ /^["<]/; # "            push @includes, $include;        }        foreach my $include (sort @includes) {            print $HEADER "#include $include\n";        }        print $HEADER @headerContent;        @includes = ();        foreach my $include (keys %headerTrailingIncludes) {            $include = "\"$include\"" unless $include =~ /^["<]/; # "            push @includes, $include;        }        foreach my $include (sort @includes) {            print $HEADER "#include $include\n";        }        close($HEADER);        undef($HEADER);        @headerContentHeader = ();        @headerContent = ();        %headerIncludes = ();        %headerTrailingIncludes = ();    }    if (defined($DEPS)) {        # Write dependency file.        print $DEPS @depsContent;        close($DEPS);        undef($DEPS);        @depsContent = ();    }}sub GenerateConstructorDeclaration{    my $outputArray = shift;    my $className = shift;    my $dataNode = shift;    my $constructorClassName = "${className}Constructor";    my $canConstruct = $dataNode->extendedAttributes->{"CanBeConstructed"};    my $callWith = $dataNode->extendedAttributes->{"CallWith"};    push(@$outputArray, "class ${constructorClassName} : public DOMConstructorObject {\n");    push(@$outputArray, "public:\n");    push(@$outputArray, "    ${constructorClassName}(JSC::ExecState*, JSC::Structure*, JSDOMGlobalObject*);\n\n");    push(@$outputArray, "    virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n");    push(@$outputArray, "    virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n");    push(@$outputArray, "    static const JSC::ClassInfo s_info;\n");    push(@$outputArray, "    static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)\n");    push(@$outputArray, "    {\n");    push(@$outputArray, "        return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);\n");    push(@$outputArray, "    }\n");    push(@$outputArray, "protected:\n");    push(@$outputArray, "    static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::ImplementsHasInstance | DOMConstructorObject::StructureFlags;\n");    if ($canConstruct) {        push(@$outputArray, "    static JSC::EncodedJSValue JSC_HOST_CALL construct${className}(JSC::ExecState*);\n");        push(@$outputArray, "    virtual JSC::ConstructType getConstructData(JSC::ConstructData&);\n");    }    push(@$outputArray, "};\n\n");}sub GenerateConstructorDefinition{    my $outputArray = shift;    my $className = shift;    my $protoClassName = shift;    my $interfaceName = shift;    my $visibleClassName = shift;    my $dataNode = shift;    my $constructorClassName = "${className}Constructor";    my $canConstruct = $dataNode->extendedAttributes->{"CanBeConstructed"};    my $customConstructFunction = $dataNode->extendedAttributes->{"CustomConstructFunction"};    my $callWith = $dataNode->extendedAttributes->{"CallWith"};    my $numberOfconstructParameters = $dataNode->extendedAttributes->{"ConstructorParameters"};    push(@$outputArray, "const ClassInfo ${constructorClassName}::s_info = { \"${visibleClassName}Constructor\", &DOMConstructorObject::s_info, &${constructorClassName}Table, 0 };\n\n");    push(@$outputArray, "${constructorClassName}::${constructorClassName}(ExecState* exec, Structure* structure, JSDOMGlobalObject* globalObject)\n");    push(@$outputArray, "    : DOMConstructorObject(structure, globalObject)\n");    push(@$outputArray, "{\n");    push(@$outputArray, "    ASSERT(inherits(&s_info));\n");    if ($interfaceName eq "DOMWindow") {        push(@$outputArray, "    putDirect(exec->globalData(), exec->propertyNames().prototype, globalObject->prototype(), DontDelete | ReadOnly);\n");    } else {        push(@$outputArray, "    putDirect(exec->globalData(), exec->propertyNames().prototype, ${protoClassName}::self(exec, globalObject), DontDelete | ReadOnly);\n");    }    push(@$outputArray, "    putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(${numberOfconstructParameters}), ReadOnly | DontDelete | DontEnum);\n") if $numberOfconstructParameters;    push(@$outputArray, "}\n\n");    push(@$outputArray, "bool ${constructorClassName}::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n");    push(@$outputArray, "{\n");    push(@$outputArray, "    return getStaticValueSlot<${constructorClassName}, JSDOMWrapper>(exec, &${constructorClassName}Table, this, propertyName, slot);\n");    push(@$outputArray, "}\n\n");    push(@$outputArray, "bool ${constructorClassName}::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\n");    push(@$outputArray, "{\n");    push(@$outputArray, "    return getStaticValueDescriptor<${constructorClassName}, JSDOMWrapper>(exec, &${constructorClassName}Table, this, propertyName, descriptor);\n");    push(@$outputArray, "}\n\n");    if ($canConstruct) {        if (!$customConstructFunction) {            push(@$outputArray, "EncodedJSValue JSC_HOST_CALL ${constructorClassName}::construct${className}(ExecState* exec)\n");            push(@$outputArray, "{\n");            my $constructorArg = "";            if ($callWith and $callWith eq "ScriptExecutionContext") {                $constructorArg = "context";                push(@$outputArray, "    ScriptExecutionContext* context = static_cast<${constructorClassName}*>(exec->callee())->scriptExecutionContext();\n");                push(@$outputArray, "    if (!context)\n");                push(@$outputArray, "        return throwVMError(exec, createReferenceError(exec, \"Reference error\"));\n");            }            push(@$outputArray, "    return JSValue::encode(asObject(toJS(exec, static_cast<${constructorClassName}*>(exec->callee())->globalObject(), ${interfaceName}::create(${constructorArg}))));\n");            push(@$outputArray, "}\n\n");        }        push(@$outputArray, "ConstructType ${constructorClassName}::getConstructData(ConstructData& constructData)\n");        push(@$outputArray, "{\n");        push(@$outputArray, "    constructData.native.function = construct${className};\n");        push(@$outputArray, "    return ConstructTypeHost;\n");        push(@$outputArray, "}\n\n");    }}1;


0 0
原创粉丝点击