diff options
Diffstat (limited to 'src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorV8.pm')
-rw-r--r-- | src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorV8.pm | 463 |
1 files changed, 274 insertions, 189 deletions
diff --git a/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorV8.pm b/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorV8.pm index 7f1508ba5b..95b2aa2fb9 100644 --- a/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorV8.pm +++ b/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorV8.pm @@ -215,7 +215,6 @@ sub AddClassForwardIfNeeded sub GetImplementationFileName { my $iface = shift; - return "HTMLCollection.h" if $iface eq "HTMLAllCollection"; return "Event.h" if $iface eq "DOMTimeStamp"; return "NamedAttrMap.h" if $iface eq "NamedNodeMap"; return "NameNodeList.h" if $iface eq "NodeList"; @@ -307,7 +306,7 @@ sub GenerateSetDOMException my $indent = shift; my $result = ""; - $result .= $indent . "if (ec) {\n"; + $result .= $indent . "if (UNLIKELY(ec)) {\n"; $result .= $indent . " V8Proxy::setDOMException(ec);\n"; $result .= $indent . " return v8::Handle<v8::Value>();\n"; $result .= $indent . "}\n"; @@ -326,10 +325,26 @@ sub IsNodeSubType return 0; } -sub RequiresCustomEventListenerAccessors +sub GetHiddenDependencyIndex { my $dataNode = shift; - return !IsNodeSubType($dataNode) && $dataNode->name ne "SVGElementInstance"; + my $attribute = shift; + my $name = $dataNode->name; + return "V8Custom::kNodeEventListenerCacheIndex" if IsNodeSubType($dataNode); + return "V8Custom::kSVGElementInstanceEventListenerCacheIndex" if $name eq "SVGElementInstance"; + return "V8Custom::kAbstractWorkerRequestCacheIndex" if $name eq "AbstractWorker"; + return "V8Custom::kWorkerRequestCacheIndex" if $name eq "Worker"; + return "V8Custom::kDedicatedWorkerContextRequestCacheIndex" if $name eq "DedicatedWorkerContext"; + return "V8Custom::kWorkerContextRequestCacheIndex" if $name eq "WorkerContext"; + return "V8Custom::kWorkerContextRequestCacheIndex" if $name eq "SharedWorkerContext"; + return "V8Custom::kMessagePortRequestCacheIndex" if $name eq "MessagePort"; + return "V8Custom::kWebSocketCacheIndex" if $name eq "WebSocket"; + return "V8Custom::kXMLHttpRequestCacheIndex" if $name eq "XMLHttpRequest"; + return "V8Custom::kXMLHttpRequestCacheIndex" if $name eq "XMLHttpRequestUpload"; + return "V8Custom::kDOMApplicationCacheCacheIndex" if $name eq "DOMApplicationCache"; + return "V8Custom::kNotificationRequestCacheIndex" if $name eq "Notification"; + return "V8Custom::kDOMWindowEventListenerCacheIndex" if $name eq "DOMWindow"; + die "Unexpected name " . $name . " when generating " . $attribute; } sub HolderToNative @@ -444,6 +459,7 @@ sub GenerateNormalAttrGetter my $dataNode = shift; my $classIndex = shift; my $implClassName = shift; + my $interfaceName = shift; my $attrExt = $attribute->signature->extendedAttributes; @@ -500,11 +516,17 @@ END } } elsif ($attrExt->{"v8OnProto"} || $attrExt->{"V8DisallowShadowing"}) { + if ($classIndex eq "DOMWINDOW") { + push(@implContentDecls, <<END); + v8::Handle<v8::Object> holder = info.Holder(); +END + } else { # perform lookup first push(@implContentDecls, <<END); v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::$classIndex, info.This()); if (holder.IsEmpty()) return v8::Undefined(); END + } HolderToNative($dataNode, $implClassName, $classIndex); } else { push(@implContentDecls, <<END); @@ -540,10 +562,11 @@ END my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"}; if ($reflect || $reflectURL) { - $implIncludes{"HTMLNames.h"} = 1; my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL); + my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName); + $implIncludes{"${namespace}.h"} = 1; my $getAttributeFunctionName = $reflectURL ? "getURLAttribute" : "getAttribute"; - $getterString = "imp->$getAttributeFunctionName(HTMLNames::${contentAttributeName}Attr"; + $getterString = "imp->$getAttributeFunctionName(${namespace}::${contentAttributeName}Attr"; } else { $getterString = "imp->$getterFunc("; } @@ -594,15 +617,21 @@ END } } else { - push(@implContentDecls, " $nativeType v = "); - - push(@implContentDecls, "$getterString;\n"); + if ($attribute->signature->type eq "EventListener" && $dataNode->name eq "DOMWindow") { + push(@implContentDecls, " if (!imp->document())\n"); + push(@implContentDecls, " return v8::Undefined();\n"); + } if ($useExceptions) { + push(@implContentDecls, " $nativeType v = "); + push(@implContentDecls, "$getterString;\n"); push(@implContentDecls, GenerateSetDOMException(" ")); + $result = "v"; + $result .= ".release()" if (IsRefPtrType($returnType)); + } else { + # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary + $result = $getterString; } - - $result = "v"; } if (IsSVGTypeNeedingContextParameter($attrType) && !$skipContext) { @@ -618,7 +647,6 @@ END my $classIndex = uc($attrType); push(@implContentDecls, " return V8DOMWrapper::convertToV8Object(V8ClassIndex::$classIndex, wrapper.release());\n"); } else { - $result .= ".release()" if (IsRefPtrType($attrType)); push(@implContentDecls, " " . ReturnNativeToJSValue($attribute->signature, $result, " ").";\n"); } @@ -651,6 +679,7 @@ sub GenerateNormalAttrSetter my $dataNode = shift; my $classIndex = shift; my $implClassName = shift; + my $interfaceName = shift; my $attrExt = $attribute->signature->extendedAttributes; @@ -672,11 +701,17 @@ sub GenerateNormalAttrSetter push(@implContentDecls, " $implClassName* imp = &imp_instance;\n"); } elsif ($attrExt->{"v8OnProto"}) { + if ($classIndex eq "DOMWINDOW") { + push(@implContentDecls, <<END); + v8::Handle<v8::Object> holder = info.Holder(); +END + } else { # perform lookup first push(@implContentDecls, <<END); v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::$classIndex, info.This()); - if (holder.IsEmpty()) return v8::Undefined(); + if (holder.IsEmpty()) return; END + } HolderToNative($dataNode, $implClassName, $classIndex); } else { push(@implContentDecls, <<END); @@ -687,7 +722,11 @@ END my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0); if ($attribute->signature->type eq "EventListener") { - push(@implContentDecls, " $nativeType v = V8DOMWrapper::getEventListener(imp, value, true, false);\n"); + if ($dataNode->name eq "DOMWindow") { + push(@implContentDecls, " if (!imp->document())\n"); + push(@implContentDecls, " return;\n"); + } + push(@implContentDecls, " $nativeType v = V8DOMWrapper::getEventListener(imp, value, true, ListenerFindOrCreate);\n"); } else { push(@implContentDecls, " $nativeType v = " . JSValueToNative($attribute->signature, "value") . ";\n"); } @@ -719,20 +758,24 @@ END my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"}; if ($reflect || $reflectURL) { - $implIncludes{"HTMLNames.h"} = 1; my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL); - push(@implContentDecls, " imp->setAttribute(HTMLNames::${contentAttributeName}Attr, $result"); + my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName); + $implIncludes{"${namespace}.h"} = 1; + push(@implContentDecls, " imp->setAttribute(${namespace}::${contentAttributeName}Attr, $result"); } elsif ($attribute->signature->type eq "EventListener") { $implIncludes{"V8AbstractEventListener.h"} = 1; $implIncludes{"V8CustomBinding.h"} = 1; + $cacheIndex = GetHiddenDependencyIndex($dataNode, $attrName); push(@implContentDecls, " $nativeType old = imp->$attrName();\n"); - push(@implContentDecls, " if (old && static_cast<V8AbstractEventListener*>(old.get())->isObjectListener()) {\n"); - push(@implContentDecls, " v8::Local<v8::Object> oldListener = static_cast<V8AbstractEventListener*>(old.get())->getListenerObject();\n"); - push(@implContentDecls, " removeHiddenDependency(holder, oldListener, V8Custom::kNodeEventListenerCacheIndex);\n"); + push(@implContentDecls, " V8AbstractEventListener* oldListener = old ? V8AbstractEventListener::cast(old.get()) : 0;\n"); + push(@implContentDecls, " if (oldListener) {\n"); + push(@implContentDecls, " v8::Local<v8::Object> oldListenerObject = oldListener->getExistingListenerObject();\n"); + push(@implContentDecls, " if (!oldListenerObject.IsEmpty())\n"); + push(@implContentDecls, " removeHiddenDependency(holder, oldListenerObject, $cacheIndex);\n"); push(@implContentDecls, " }\n"); push(@implContentDecls, " imp->set$implSetterFunctionName($result);\n"); push(@implContentDecls, " if ($result)\n"); - push(@implContentDecls, " createHiddenDependency(holder, value, V8Custom::kNodeEventListenerCacheIndex"); + push(@implContentDecls, " createHiddenDependency(holder, value, $cacheIndex"); } else { push(@implContentDecls, " imp->set$implSetterFunctionName(" . $result); } @@ -741,7 +784,8 @@ END } if ($useExceptions) { - push(@implContentDecls, " V8Proxy::setDOMException(ec);\n"); + push(@implContentDecls, " if (UNLIKELY(ec))\n"); + push(@implContentDecls, " V8Proxy::setDOMException(ec);\n"); } if ($isPodType) { @@ -874,7 +918,7 @@ END if (TypeCanFailConversion($parameter)) { $implIncludes{"ExceptionCode.h"} = 1; push(@implContentDecls, -" if (!$parameterName" . (BasicTypeCanFailConversion($parameter) ? "Ok" : "") . ") {\n" . +" if (UNLIKELY(!$parameterName" . (BasicTypeCanFailConversion($parameter) ? "Ok" : "") . ")) {\n" . " V8Proxy::setDOMException(TYPE_MISMATCH_ERR);\n" . " return v8::Handle<v8::Value>();\n" . " }\n"); @@ -883,7 +927,7 @@ END if ($parameter->extendedAttributes->{"IsIndex"}) { $implIncludes{"ExceptionCode.h"} = 1; push(@implContentDecls, -" if ($parameterName < 0) {\n" . +" if (UNLIKELY($parameterName < 0)) {\n" . " V8Proxy::setDOMException(INDEX_SIZE_ERR);\n" . " return v8::Handle<v8::Value>();\n" . " }\n"); @@ -905,142 +949,134 @@ sub GenerateBatchedAttributeData my $attributes = shift; foreach my $attribute (@$attributes) { - my $attrName = $attribute->signature->name; - my $attrExt = $attribute->signature->extendedAttributes; - - my $accessControl = "v8::DEFAULT"; - if ($attrExt->{"DoNotCheckDomainSecurityOnGet"}) { - $accessControl = "v8::ALL_CAN_READ"; - } elsif ($attrExt->{"DoNotCheckDomainSecurityOnSet"}) { - $accessControl = "v8::ALL_CAN_WRITE"; - } elsif ($attrExt->{"DoNotCheckDomainSecurity"}) { - $accessControl = "v8::ALL_CAN_READ"; - if (!($attribute->type =~ /^readonly/) && !($attrExt->{"V8ReadOnly"})) { - $accessControl .= "|v8::ALL_CAN_WRITE"; - } - } - if ($attrExt->{"V8DisallowShadowing"}) { - $accessControl .= "|v8::PROHIBITS_OVERWRITING"; - } - $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")"; - - my $customAccessor = - $attrExt->{"Custom"} || - $attrExt->{"CustomSetter"} || - $attrExt->{"CustomGetter"} || - $attrExt->{"V8Custom"} || - $attrExt->{"V8CustomSetter"} || - $attrExt->{"V8CustomGetter"} || - ""; - if ($customAccessor eq 1) { - # use the naming convension, interface + (capitalize) attr name - $customAccessor = $interfaceName . $codeGenerator->WK_ucfirst($attrName); - } + my $conditionalString = GenerateConditionalString($attribute->signature); + push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString; + GenerateSingleBatchedAttribute($interfaceName, $attribute, ",", ""); + push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; + } +} - my $getter; - my $setter; - my $propAttr = "v8::None"; - my $hasCustomSetter = 0; +sub GenerateSingleBatchedAttribute +{ + my $interfaceName = shift; + my $attribute = shift; + my $delimiter = shift; + my $indent = shift; + my $attrName = $attribute->signature->name; + my $attrExt = $attribute->signature->extendedAttributes; - # Check attributes. - if ($attrExt->{"DontEnum"}) { - $propAttr .= "|v8::DontEnum"; - } - if ($attrExt->{"V8DisallowShadowing"}) { - $propAttr .= "|v8::DontDelete"; + my $accessControl = "v8::DEFAULT"; + if ($attrExt->{"DoNotCheckDomainSecurityOnGet"}) { + $accessControl = "v8::ALL_CAN_READ"; + } elsif ($attrExt->{"DoNotCheckDomainSecurityOnSet"}) { + $accessControl = "v8::ALL_CAN_WRITE"; + } elsif ($attrExt->{"DoNotCheckDomainSecurity"}) { + $accessControl = "v8::ALL_CAN_READ"; + if (!($attribute->type =~ /^readonly/) && !($attrExt->{"V8ReadOnly"})) { + $accessControl .= "|v8::ALL_CAN_WRITE"; } + } + if ($attrExt->{"V8DisallowShadowing"}) { + $accessControl .= "|v8::PROHIBITS_OVERWRITING"; + } + $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")"; + + my $customAccessor = + $attrExt->{"Custom"} || + $attrExt->{"CustomSetter"} || + $attrExt->{"CustomGetter"} || + $attrExt->{"V8Custom"} || + $attrExt->{"V8CustomSetter"} || + $attrExt->{"V8CustomGetter"} || + ""; + if ($customAccessor eq 1) { + # use the naming convension, interface + (capitalize) attr name + $customAccessor = $interfaceName . $codeGenerator->WK_ucfirst($attrName); + } + + my $getter; + my $setter; + my $propAttr = "v8::None"; + my $hasCustomSetter = 0; + + # Check attributes. + if ($attrExt->{"DontEnum"}) { + $propAttr .= "|v8::DontEnum"; + } + if ($attrExt->{"V8DisallowShadowing"}) { + $propAttr .= "|v8::DontDelete"; + } - my $on_proto = "0 /* on instance */"; - my $data = "V8ClassIndex::INVALID_CLASS_INDEX /* no data */"; + my $on_proto = "0 /* on instance */"; + my $data = "V8ClassIndex::INVALID_CLASS_INDEX /* no data */"; - # Constructor - if ($attribute->signature->type =~ /Constructor$/) { - my $constructorType = $codeGenerator->StripModule($attribute->signature->type); - $constructorType =~ s/Constructor$//; - my $constructorIndex = uc($constructorType); + # Constructor + if ($attribute->signature->type =~ /Constructor$/) { + my $constructorType = $codeGenerator->StripModule($attribute->signature->type); + $constructorType =~ s/Constructor$//; + my $constructorIndex = uc($constructorType); + if ($customAccessor) { + $getter = "V8Custom::v8${customAccessor}AccessorGetter"; + } else { $data = "V8ClassIndex::${constructorIndex}"; $getter = "${interfaceName}Internal::${interfaceName}ConstructorGetter"; - $setter = "0"; - $propAttr = "v8::ReadOnly"; - - # EventListeners - } elsif ($attribute->signature->type eq "EventListener" && RequiresCustomEventListenerAccessors($dataNode)) { - if ($interfaceName eq "DOMWindow") { - $getter = "V8Custom::v8DOMWindowEventHandlerAccessorGetter"; - $setter = "V8Custom::v8DOMWindowEventHandlerAccessorSetter"; - } elsif ($interfaceName eq "DOMApplicationCache") { - $getter = "V8Custom::v8DOMApplicationCacheEventHandlerAccessorGetter"; - $setter = "V8Custom::v8DOMApplicationCacheEventHandlerAccessorSetter"; - } elsif ($interfaceName eq "Notification") { - $getter = "V8Custom::v8NotificationEventHandlerAccessorGetter"; - $setter = "V8Custom::v8NotificationEventHandlerAccessorSetter"; - } else { - $getter = "V8Custom::v8${customAccessor}AccessorGetter"; - if ($interfaceName eq "WorkerContext" and $attrName eq "self") { - $setter = "0"; - $propAttr = "v8::ReadOnly"; - } else { - $setter = "V8Custom::v8${customAccessor}AccessorSetter"; - } - } - } else { - # Default Getter and Setter - $getter = "${interfaceName}Internal::${attrName}AttrGetter"; - $setter = "${interfaceName}Internal::${attrName}AttrSetter"; - - # Custom Setter - if ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) { - $hasCustomSetter = 1; - $setter = "V8Custom::v8${customAccessor}AccessorSetter"; - } - - # Custom Getter - if ($attrExt->{"CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) { - $getter = "V8Custom::v8${customAccessor}AccessorGetter"; - } } + $setter = "0"; + $propAttr = "v8::ReadOnly"; - # Replaceable - if ($attrExt->{"Replaceable"} && !$hasCustomSetter) { - $setter = "0"; - # Handle the special case of window.top being marked as Replaceable. - # FIXME: Investigate whether we could treat window.top as replaceable - # and allow shadowing without it being a security hole. - if (!($interfaceName eq "DOMWindow" and $attrName eq "top")) { - $propAttr .= "|v8::ReadOnly"; - } + } else { + # Default Getter and Setter + $getter = "${interfaceName}Internal::${attrName}AttrGetter"; + $setter = "${interfaceName}Internal::${attrName}AttrSetter"; + + # Custom Setter + if ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) { + $hasCustomSetter = 1; + $setter = "V8Custom::v8${customAccessor}AccessorSetter"; } - # Read only attributes - if ($attribute->type =~ /^readonly/ || $attrExt->{"V8ReadOnly"}) { - $setter = "0"; + # Custom Getter + if ($attrExt->{"CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) { + $getter = "V8Custom::v8${customAccessor}AccessorGetter"; } + } - # An accessor can be installed on the proto - if ($attrExt->{"v8OnProto"}) { - $on_proto = "1 /* on proto */"; + # Replaceable + if ($attrExt->{"Replaceable"} && !$hasCustomSetter) { + $setter = "0"; + # Handle the special case of window.top being marked as Replaceable. + # FIXME: Investigate whether we could treat window.top as replaceable + # and allow shadowing without it being a security hole. + if (!($interfaceName eq "DOMWindow" and $attrName eq "top")) { + $propAttr .= "|v8::ReadOnly"; } + } - my $commentInfo = "Attribute '$attrName' (Type: '" . $attribute->type . - "' ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')"; - - my $conditionalString = GenerateConditionalString($attribute->signature); - push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString; + # Read only attributes + if ($attribute->type =~ /^readonly/ || $attrExt->{"V8ReadOnly"}) { + $setter = "0"; + } - push(@implContent, <<END); - // $commentInfo - { "$attrName", - $getter, - $setter, - $data, - $accessControl, - static_cast<v8::PropertyAttribute>($propAttr), - $on_proto }, -END - push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; + # An accessor can be installed on the proto + if ($attrExt->{"v8OnProto"}) { + $on_proto = "1 /* on proto */"; } -} + my $commentInfo = "Attribute '$attrName' (Type: '" . $attribute->type . + "' ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')"; + + push(@implContent, $indent . " {\n"); + push(@implContent, $indent . " \/\/ $commentInfo\n"); + push(@implContent, $indent . " \"$attrName\",\n"); + push(@implContent, $indent . " $getter,\n"); + push(@implContent, $indent . " $setter,\n"); + push(@implContent, $indent . " $data,\n"); + push(@implContent, $indent . " $accessControl,\n"); + push(@implContent, $indent . " static_cast<v8::PropertyAttribute>($propAttr),\n"); + push(@implContent, $indent . " $on_proto\n"); + push(@implContent, $indent . " }" . $delimiter . "\n"); +END +} sub GenerateImplementation { @@ -1088,20 +1124,16 @@ sub GenerateImplementation # Generate special code for the constructor attributes. if ($attrType =~ /Constructor$/) { - $hasConstructors = 1; + if ($attribute->signature->extendedAttributes->{"CustomGetter"}) { + $implIncludes{"V8CustomBinding.h"} = 1; + } else { + $hasConstructors = 1; + } next; } - # Make EventListeners custom for some types. - # FIXME: make the perl code capable of generating the - # event setters/getters. For now, WebKit has started removing the - # [Custom] attribute, so just automatically insert it to avoid forking - # other files. This should be okay because we can't generate stubs - # for any event getter/setters anyway. - if ($attrType eq "EventListener" && RequiresCustomEventListenerAccessors($dataNode)) { - $attribute->signature->extendedAttributes->{"Custom"} = 1; - $implIncludes{"V8CustomBinding.h"} = 1; - next; + if ($attrType eq "EventListener" && $interfaceName eq "DOMWindow") { + $attribute->signature->extendedAttributes->{"v8OnProto"} = 1; } # Do not generate accessor if this is a custom attribute. The @@ -1117,7 +1149,7 @@ sub GenerateImplementation if ($attribute->signature->extendedAttributes->{"CustomGetter"}) { $implIncludes{"V8CustomBinding.h"} = 1; } else { - GenerateNormalAttrGetter($attribute, $dataNode, $classIndex, $implClassName); + GenerateNormalAttrGetter($attribute, $dataNode, $classIndex, $implClassName, $interfaceName); } if ($attribute->signature->extendedAttributes->{"CustomSetter"} || $attribute->signature->extendedAttributes->{"V8CustomSetter"}) { @@ -1126,7 +1158,7 @@ sub GenerateImplementation $dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"} || die "Replaceable attribute can only be used in interface that defines ExtendsDOMGlobalObject attribute!"; # GenerateReplaceableAttrSetter($implClassName); } elsif ($attribute->type !~ /^readonly/ && !$attribute->signature->extendedAttributes->{"V8ReadOnly"}) { - GenerateNormalAttrSetter($attribute, $dataNode, $classIndex, $implClassName); + GenerateNormalAttrSetter($attribute, $dataNode, $classIndex, $implClassName, $interfaceName); } } @@ -1157,20 +1189,24 @@ sub GenerateImplementation # For the DOMWindow interface we partition the attributes into the # ones that disallows shadowing and the rest. - my @disallows_shadowing; + my @disallowsShadowing; + # Also separate out attributes that are enabled at runtime so we can process them specially. + my @enabledAtRuntime; my @normal; - if ($interfaceName eq "DOMWindow") { - foreach my $attribute (@$attributes) { - if ($attribute->signature->extendedAttributes->{"V8DisallowShadowing"}) { - push(@disallows_shadowing, $attribute); - } else { - push(@normal, $attribute); - } + foreach my $attribute (@$attributes) { + if ($interfaceName eq "DOMWindow" && $attribute->signature->extendedAttributes->{"V8DisallowShadowing"}) { + push(@disallowsShadowing, $attribute); + } elsif ($attribute->signature->extendedAttributes->{"EnabledAtRuntime"}) { + push(@enabledAtRuntime, $attribute); + } else { + push(@normal, $attribute); } - # Put the attributes that disallow shadowing on the shadow object. - $attributes = \@normal; + } + $attributes = \@normal; + # Put the attributes that disallow shadowing on the shadow object. + if (@disallowsShadowing) { push(@implContent, "static const BatchedAttribute shadow_attrs[] = {\n"); - GenerateBatchedAttributeData($dataNode, \@disallows_shadowing); + GenerateBatchedAttributeData($dataNode, \@disallowsShadowing); push(@implContent, "};\n"); } @@ -1252,6 +1288,21 @@ END END } + # Setup the enable-at-runtime attrs if we have them + foreach my $runtime_attr (@enabledAtRuntime) { + $enable_function = $interfaceName . $codeGenerator->WK_ucfirst($runtime_attr->signature->name); + my $conditionalString = GenerateConditionalString($runtime_attr->signature); + push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString; + push(@implContent, " if (V8Custom::v8${enable_function}Enabled()) {\n"); + push(@implContent, " static const BatchedAttribute attrData =\\\n"); + GenerateSingleBatchedAttribute($interfaceName, $runtime_attr, ";", " "); + push(@implContent, <<END); + configureAttribute(instance, proto, attrData); + } +END + push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; + } + # Define our functions with Set() or SetAccessor() foreach my $function (@{$dataNode->functions}) { my $attrExt = $function->signature->extendedAttributes; @@ -1272,6 +1323,13 @@ END $template = "instance"; } + my $conditional = ""; + if ($attrExt->{"EnabledAtRuntime"}) { + # Only call Set()/SetAccessor() if this method should be enabled + $enable_function = $interfaceName . $codeGenerator->WK_ucfirst($function->signature->name); + $conditional = "if (V8Custom::v8${enable_function}Enabled())\n"; + } + if ($attrExt->{"DoNotCheckDomainSecurity"} && ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) { # Mark the accessor as ReadOnly and set it on the proto object so @@ -1292,7 +1350,7 @@ END push(@implContent, <<END); // $commentInfo - $template->SetAccessor( + $conditional $template->SetAccessor( v8::String::New("$name"), ${interfaceName}Internal::${name}AttrGetter, 0, @@ -1320,7 +1378,7 @@ END push(@implContent, <<END); // $commentInfo - ${template}->Set( + $conditional ${template}->Set( v8::String::New("$name"), $templateFunction, static_cast<v8::PropertyAttribute>($property_attributes)); @@ -1338,7 +1396,7 @@ END } # Set the class name. This is used when printing objects. - push(@implContent, " desc->SetClassName(v8::String::New(\"" . GetClassName(${interfaceName}) . "\"));\n"); + push(@implContent, " desc->SetClassName(v8::String::New(\"${interfaceName}\"));\n"); if ($has_constants) { push(@implContent, <<END); @@ -1456,7 +1514,7 @@ sub GenerateFunctionCallString() $paramName = "SVGPODListItem<" . GetNativeType($paramType, 1) . ">::copy($paramName)"; } - if ($parameter->type eq "NodeFilter") { + if ($parameter->type eq "NodeFilter" || $parameter->type eq "XPathNSResolver") { $functionString .= "$paramName.get()"; } else { $functionString .= $paramName; @@ -1480,6 +1538,9 @@ sub GenerateFunctionCallString() } $functionString .= ")"; + my $return = "result"; + my $returnIsRef = IsRefPtrType($returnType); + if ($nodeToReturn) { # Special case for insertBefore, replaceChild, removeChild and # appendChild functions from Node. @@ -1500,16 +1561,18 @@ sub GenerateFunctionCallString() $indent . "$functionString;\n"; } elsif ($returnsListItemPodType) { $result .= $indent . "RefPtr<SVGPODListItem<$nativeReturnType> > result = $functionString;\n"; - } else { + } elsif (@{$function->raisesExceptions} or $returnsPodType or $isPodType or IsSVGTypeNeedingContextParameter($returnType)) { $result .= $indent . $nativeReturnType . " result = $functionString;\n"; + } else { + # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary + $return = $functionString; + $returnIsRef = 0; } if (@{$function->raisesExceptions}) { $result .= GenerateSetDOMException($indent); } - my $return = "result"; - # If the return type is a POD type, separate out the wrapper generation if ($returnsListItemPodType) { $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = "; @@ -1552,7 +1615,7 @@ sub GenerateFunctionCallString() my $classIndex = uc($returnType); $result .= $indent . "return V8DOMWrapper::convertToV8Object(V8ClassIndex::$classIndex, wrapper.release());\n"; } else { - $return .= ".release()" if (IsRefPtrType($returnType)); + $return .= ".release()" if ($returnIsRef); $result .= $indent . ReturnNativeToJSValue($function->signature, $return, $indent) . ";\n"; } @@ -1560,15 +1623,6 @@ sub GenerateFunctionCallString() } -# Get the class name used for printing javascript DOM-object wrappers. -sub GetClassName -{ - my $type = shift; - return "HTMLCollection" if $type eq "HTMLAllCollection"; - return $type; -} - - sub GetTypeFromSignature { my $signature = shift; @@ -1601,6 +1655,7 @@ sub IsRefPtrType { my $type = shift; return 1 if $type eq "Attr"; + return 1 if $type eq "CanvasActiveInfo"; return 1 if $type eq "CanvasArray"; return 1 if $type eq "CanvasArrayBuffer"; return 1 if $type eq "CanvasBooleanArray"; @@ -1645,6 +1700,7 @@ sub IsRefPtrType return 1 if $type eq "EventListener"; return 1 if $type eq "FileList"; return 1 if $type eq "HTMLCollection"; + return 1 if $type eq "HTMLAllCollection"; return 1 if $type eq "HTMLDocument"; return 1 if $type eq "HTMLElement"; return 1 if $type eq "HTMLOptionsCollection"; @@ -1738,6 +1794,9 @@ sub GetNativeType # temporary hack return "RefPtr<NodeFilter>" if $type eq "NodeFilter"; + # necessary as resolvers could be constructed on fly. + return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver"; + return "RefPtr<${type}>" if IsRefPtrType($type) and not $isParameter; # Default, assume native type is a pointer with same type name as idl type @@ -1873,6 +1932,11 @@ sub JSValueToNative return "toWebCoreString($value)"; } + if ($type eq "SerializedScriptValue") { + $implIncludes{"SerializedScriptValue.h"} = 1; + return "SerializedScriptValue::create($value)"; + } + if ($type eq "NodeFilter") { return "V8DOMWrapper::wrapNativeNodeFilter($value)"; } @@ -1894,6 +1958,10 @@ sub JSValueToNative return "V8Node::HasInstance($value) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast($value)) : 0"; } + if ($type eq "XPathNSResolver") { + return "V8DOMWrapper::getXPathNSResolver($value)"; + } + AddIncludesForType($type); # $implIncludes{"$type.h"} = 1 unless AvoidInclusionOfType($type); @@ -1945,10 +2013,16 @@ sub CreateCustomSignature if ($first) { $first = 0; } else { $result .= ", "; } if (IsWrapperType($parameter->type)) { - my $type = $parameter->type; - my $header = GetV8HeaderName($type); - $implIncludes{$header} = 1; - $result .= "V8${type}::GetRawTemplate()"; + if ($parameter->type eq "XPathNSResolver") { + # Special case for XPathNSResolver. All other browsers accepts a callable, + # so, even though it's against IDL, accept objects here. + $result .= "v8::Handle<v8::FunctionTemplate>()"; + } else { + my $type = $parameter->type; + my $header = GetV8HeaderName($type); + $implIncludes{$header} = 1; + $result .= "V8${type}::GetRawTemplate()"; + } } else { $result .= "v8::Handle<v8::FunctionTemplate>()"; } @@ -2053,7 +2127,9 @@ sub ReturnNativeToJSValue # For all the types where we use 'int' as the representation type, # we use Integer::New which has a fast Smi conversion check. - return "return v8::Integer::New($value)" if GetNativeType($type) eq "int"; + my $nativeType = GetNativeType($type); + return "return v8::Integer::New($value)" if $nativeType eq "int"; + return "return v8::Integer::NewFromUnsigned($value)" if $nativeType eq "unsigned"; return "return v8::Number::New($value)" if $codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType"; @@ -2076,7 +2152,11 @@ sub ReturnNativeToJSValue # special case for non-DOM node interfaces if (IsDOMNodeType($type)) { - return "return V8DOMWrapper::convertNodeToV8Object($value)"; + if ($signature->extendedAttributes->{"ReturnsNew"}) { + return "return V8DOMWrapper::convertNewNodeToV8Object($value)"; + } else { + return "return V8DOMWrapper::convertNodeToV8Object($value)"; + } } if ($type eq "EventTarget" or $type eq "SVGElementInstance") { @@ -2088,7 +2168,12 @@ sub ReturnNativeToJSValue } if ($type eq "EventListener") { - return "return V8DOMWrapper::convertEventListenerToV8Object($value)"; + return "return V8DOMWrapper::convertEventListenerToV8Object(imp->scriptExecutionContext(), $value)"; + } + + if ($type eq "SerializedScriptValue") { + $implIncludes{"$type.h"} = 1; + return "return v8String($value->toString())"; } if ($type eq "DedicatedWorkerContext" or $type eq "WorkerContext" or $type eq "SharedWorkerContext") { |