diff options
Diffstat (limited to 'WebCore/bindings/scripts/CodeGeneratorV8.pm')
-rw-r--r-- | WebCore/bindings/scripts/CodeGeneratorV8.pm | 293 |
1 files changed, 264 insertions, 29 deletions
diff --git a/WebCore/bindings/scripts/CodeGeneratorV8.pm b/WebCore/bindings/scripts/CodeGeneratorV8.pm index 1c5f398..9553b8b 100644 --- a/WebCore/bindings/scripts/CodeGeneratorV8.pm +++ b/WebCore/bindings/scripts/CodeGeneratorV8.pm @@ -99,8 +99,13 @@ sub GenerateInterface my $defines = shift; # Start actual generation - $object->GenerateHeader($dataNode); - $object->GenerateImplementation($dataNode); + if ($dataNode->extendedAttributes->{"Callback"}) { + $object->GenerateCallbackHeader($dataNode); + $object->GenerateCallbackImplementation($dataNode); + } else { + $object->GenerateHeader($dataNode); + $object->GenerateImplementation($dataNode); + } my $name = $dataNode->name; @@ -189,7 +194,13 @@ sub GenerateConditionalString my $node = shift; my $conditional = $node->extendedAttributes->{"Conditional"}; if ($conditional) { - return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; + if ($conditional =~ /&/) { + return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; + } elsif ($conditional =~ /\|/) { + return "ENABLE(" . join(") || ENABLE(", split(/\|/, $conditional)) . ")"; + } else { + return "ENABLE(" . $conditional . ")"; + } } else { return ""; } @@ -226,14 +237,9 @@ sub GenerateHeader $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@allParents, 1); my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"}; - my $conditionalString = GenerateConditionalString($dataNode); # - Add default header template - @headerContent = split("\r", $headerTemplate); - - push(@headerContent, "\n#if ${conditionalString}\n\n") if $conditionalString; - push(@headerContent, "\n#ifndef $className" . "_h"); - push(@headerContent, "\n#define $className" . "_h\n\n"); + push(@headerContent, GenerateHeaderContentHeader($dataNode)); # Get correct pass/store types respecting PODType flag my $podType = $dataNode->extendedAttributes->{"PODType"}; @@ -351,6 +357,7 @@ END push(@headerContent, "}\n\n"); push(@headerContent, "#endif // $className" . "_h\n"); + my $conditionalString = GenerateConditionalString($dataNode); push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString; } @@ -1218,7 +1225,8 @@ END if ($parameter->type eq "SerializedScriptValue") { push(@implContentDecls, "SerializedScriptValue::create(args[$paramIndex], ${parameterName}DidThrow);\n"); - push(@implContentDecls, " if (${parameterName}DidThrow)\n return v8::Undefined();\n"); + push(@implContentDecls, " if (${parameterName}DidThrow)\n"); + push(@implContentDecls, " return v8::Undefined();\n"); } else { push(@implContentDecls, JSValueToNative($parameter, "args[$paramIndex]", BasicTypeCanFailConversion($parameter) ? "${parameterName}Ok" : undef) . ";\n"); @@ -1570,16 +1578,9 @@ sub GenerateImplementation my $implClassName = $interfaceName; my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"}; - my $conditionalString = GenerateConditionalString($dataNode); # - Add default header template - @implContentHeader = split("\r", $headerTemplate); - - push(@implFixedHeader, - "\n#include \"config.h\"\n" . - "#include \"${className}.h\"\n\n"); - - push(@implFixedHeader, "\n#if ${conditionalString}\n\n") if $conditionalString; + push(@implFixedHeader, GenerateImplementationContentHeader($dataNode)); $implIncludes{"RuntimeEnabledFeatures.h"} = 1; $implIncludes{"V8Proxy.h"} = 1; @@ -1780,11 +1781,18 @@ END # In namespace WebCore, add generated implementation for 'CanBeConstructed'. if ($dataNode->extendedAttributes->{"CanBeConstructed"} && !$dataNode->extendedAttributes->{"CustomConstructor"}) { + my $v8ConstructFunction; + my $callWith = $dataNode->extendedAttributes->{"CallWith"}; + if ($callWith and $callWith eq "ScriptExecutionContext") { + $v8ConstructFunction = "constructDOMObjectWithScriptExecutionContext"; + } else { + $v8ConstructFunction = "constructDOMObject"; + } push(@implContent, <<END); v8::Handle<v8::Value> ${className}::constructorCallback(const v8::Arguments& args) { INC_STATS("DOM.${interfaceName}.Contructor"); - return V8Proxy::constructDOMObject<$interfaceName>(args, &info); + return V8Proxy::${v8ConstructFunction}<$interfaceName>(args, &info); } END } @@ -2087,6 +2095,7 @@ END } // namespace WebCore END + my $conditionalString = GenerateConditionalString($dataNode); push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; # We've already added the header for this file in implFixedHeader, so remove @@ -2094,6 +2103,190 @@ END delete $implIncludes{"${className}.h"}; } +sub GenerateHeaderContentHeader +{ + my $dataNode = shift; + my $className = "V8" . $dataNode->name; + my $conditionalString = GenerateConditionalString($dataNode); + + my @headerContentHeader = split("\r", $headerTemplate); + + push(@headerContentHeader, "\n#if ${conditionalString}\n") if $conditionalString; + push(@headerContentHeader, "\n#ifndef ${className}" . "_h"); + push(@headerContentHeader, "\n#define ${className}" . "_h\n\n"); + return @headerContentHeader; +} + +sub GenerateImplementationContentHeader +{ + my $dataNode = shift; + my $className = "V8" . $dataNode->name; + my $conditionalString = GenerateConditionalString($dataNode); + + my @implContentHeader = split("\r", $headerTemplate); + + push(@implContentHeader, "\n#include \"config.h\"\n"); + push(@implContentHeader, "#include \"${className}.h\"\n\n"); + push(@implContentHeader, "#if ${conditionalString}\n\n") if $conditionalString; + return @implContentHeader; +} + +sub GenerateCallbackHeader +{ + my $object = shift; + my $dataNode = shift; + + my $interfaceName = $dataNode->name; + my $className = "V8$interfaceName"; + + + # - Add default header template + push(@headerContent, GenerateHeaderContentHeader($dataNode)); + + if ("$interfaceName.h" lt "WorldContextHandle.h") { + push(@headerContent, "#include \"$interfaceName.h\"\n"); + push(@headerContent, "#include \"WorldContextHandle.h\"\n"); + } else { + push(@headerContent, "#include \"WorldContextHandle.h\"\n"); + push(@headerContent, "#include \"$interfaceName.h\"\n"); + } + push(@headerContent, "#include <v8.h>\n"); + push(@headerContent, "#include <wtf/Forward.h>\n"); + + push(@headerContent, "\nnamespace WebCore {\n\n"); + push(@headerContent, "class Frame;\n\n"); + push(@headerContent, "class $className : public $interfaceName {\n"); + + push(@headerContent, <<END); +public: + static PassRefPtr<${className}> create(v8::Local<v8::Value> value, Frame* frame) + { + ASSERT(value->IsObject()); + return adoptRef(new ${className}(value->ToObject(), frame)); + } + + virtual ~${className}(); + +END + + # Functions + my $numFunctions = @{$dataNode->functions}; + if ($numFunctions > 0) { + push(@headerContent, " // 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 " . GetNativeTypeForCallbacks($function->signature->type) . " " . $function->signature->name . "(ScriptExecutionContext*"); + foreach my $param (@params) { + push(@headerContent, ", " . GetNativeTypeForCallbacks($param->type) . " " . $param->name); + } + + push(@headerContent, ");\n"); + } + } + + push(@headerContent, <<END); + +private: + ${className}(v8::Local<v8::Object>, Frame*); + + v8::Persistent<v8::Object> m_callback; + RefPtr<Frame> m_frame; + WorldContextHandle m_worldContext; +}; + +END + + push(@headerContent, "}\n\n"); + push(@headerContent, "#endif // $className" . "_h\n\n"); + + my $conditionalString = GenerateConditionalString($dataNode); + push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString; +} + +sub GenerateCallbackImplementation +{ + my $object = shift; + my $dataNode = shift; + my $interfaceName = $dataNode->name; + my $className = "V8$interfaceName"; + + # - Add default header template + push(@implFixedHeader, GenerateImplementationContentHeader($dataNode)); + + $implIncludes{"Frame.h"} = 1; + $implIncludes{"ScriptExecutionContext.h"} = 1; + $implIncludes{"V8CustomVoidCallback.h"} = 1; + + push(@implContent, "namespace WebCore {\n\n"); + push(@implContent, <<END); +${className}::${className}(v8::Local<v8::Object> callback, Frame* frame) + : m_callback(v8::Persistent<v8::Object>::New(callback)) + , m_frame(frame) + , m_worldContext(UseCurrentWorld) +{ +} + +${className}::~${className}() +{ + m_callback.Dispose(); +} + +END + + # Functions + my $numFunctions = @{$dataNode->functions}; + if ($numFunctions > 0) { + push(@implContent, "// Functions\n"); + foreach my $function (@{$dataNode->functions}) { + my @params = @{$function->parameters}; + if ($function->signature->extendedAttributes->{"Custom"} || + !(GetNativeTypeForCallbacks($function->signature->type) eq "bool")) { + next; + } + + AddIncludesForType($function->signature->type); + push(@implContent, "\n" . GetNativeTypeForCallbacks($function->signature->type) . " ${className}::" . $function->signature->name . "(ScriptExecutionContext* context"); + + foreach my $param (@params) { + AddIncludesForType($param->type); + push(@implContent, ", " . GetNativeTypeForCallbacks($param->type) . " " . $param->name); + } + + push(@implContent, ")\n"); + push(@implContent, "{\n"); + push(@implContent, " v8::HandleScope handleScope;\n\n"); + push(@implContent, " v8::Handle<v8::Context> v8Context = toV8Context(context, m_worldContext);\n"); + push(@implContent, " if (v8Context.IsEmpty())\n"); + push(@implContent, " return true;\n\n"); + push(@implContent, " v8::Context::Scope scope(v8Context);\n\n"); + push(@implContent, " v8::Handle<v8::Value> argv[] = {\n"); + + my @argvs = (); + foreach my $param (@params) { + my $paramName = $param->name; + push(@argvs, " toV8(${paramName})"); + } + push(@implContent, join(",\n", @argvs)); + + push(@implContent, "\n };\n\n"); + push(@implContent, " RefPtr<Frame> protect(m_frame);\n\n"); + push(@implContent, " bool callbackReturnValue = false;\n"); + push(@implContent, " return !invokeCallback(m_callback, " . scalar(@params). ", argv, callbackReturnValue);\n"); + push(@implContent, "}\n"); + } + } + + push(@implContent, "\n} // namespace WebCore\n\n"); + + my $conditionalString = GenerateConditionalString($dataNode); + push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString; +} + sub GenerateToV8Converters { my $dataNode = shift; @@ -2326,15 +2519,33 @@ sub GenerateFunctionCallString() $functionString = "listImp->${name}("; } - my $first = 1; my $index = 0; + my $hasScriptState = 0; + + my $callWith = $function->signature->extendedAttributes->{"CallWith"}; + if ($callWith) { + my $callWithArg = "COMPILE_ASSERT(false)"; + if ($callWith eq "DynamicFrame") { + $result .= $indent . "Frame* enteredFrame = V8Proxy::retrieveFrameForEnteredContext();\n"; + $result .= $indent . "if (!enteredFrame)\n"; + $result .= $indent . " return v8::Undefined();\n"; + $callWithArg = "enteredFrame"; + } elsif ($callWith eq "ScriptState") { + $result .= $indent . "EmptyScriptState state;\n"; + $callWithArg = "&state"; + $hasScriptState = 1; + } + $functionString .= ", " if $index; + $functionString .= $callWithArg; + $index++; + $numberOfParameters++ + } foreach my $parameter (@{$function->parameters}) { if ($index eq $numberOfParameters) { last; } - if ($first) { $first = 0; } - else { $functionString .= ", "; } + $functionString .= ", " if $index; my $paramName = $parameter->name; my $paramType = $parameter->type; @@ -2353,22 +2564,23 @@ sub GenerateFunctionCallString() } if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) { - $functionString .= ", " if not $first; + $functionString .= ", " if $index; $functionString .= "callStack.get()"; - if ($first) { $first = 0; } + $index++; } if ($function->signature->extendedAttributes->{"NeedsUserGestureCheck"}) { - $functionString .= ", " if not $first; + $functionString .= ", " if $index; # FIXME: We need to pass DOMWrapperWorld as a parameter. # See http://trac.webkit.org/changeset/54182 $functionString .= "processingUserGesture()"; - if ($first) { $first = 0; } + $index++; } if (@{$function->raisesExceptions}) { - $functionString .= ", " if not $first; + $functionString .= ", " if $index; $functionString .= "ec"; + $index++; } $functionString .= ")"; @@ -2381,7 +2593,7 @@ sub GenerateFunctionCallString() $result .= $indent . GetNativeType($returnType, 0) . " result = *imp;\n" . $indent . "$functionString;\n"; } elsif ($returnsListItemPodType) { $result .= $indent . "RefPtr<SVGPODListItem<$nativeReturnType> > result = $functionString;\n"; - } elsif (@{$function->raisesExceptions} or $returnsPodType or $isPodType or IsSVGTypeNeedingContextParameter($returnType)) { + } elsif ($hasScriptState or @{$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 @@ -2390,7 +2602,13 @@ sub GenerateFunctionCallString() } if (@{$function->raisesExceptions}) { - $result .= $indent . "if (UNLIKELY(ec))\n" . $indent . " goto fail;\n"; + $result .= $indent . "if (UNLIKELY(ec))\n"; + $result .= $indent . " goto fail;\n"; + } + + if ($hasScriptState) { + $result .= $indent . "if (state.hadException())\n"; + $result .= $indent . " return throwError(state.exception());\n" } # If the return type is a POD type, separate out the wrapper generation @@ -2537,6 +2755,8 @@ sub GetNativeType # temporary hack return "RefPtr<NodeFilter>" if $type eq "NodeFilter"; + return "RefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValue"; + # necessary as resolvers could be constructed on fly. return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver"; @@ -2546,6 +2766,15 @@ sub GetNativeType return "${type}*"; } +sub GetNativeTypeForCallbacks +{ + my $type = shift; + return "const String&" if $type eq "DOMString"; + + # Callbacks use raw pointers, so pass isParameter = 1 + return GetNativeType($type, 1); +} + sub TranslateParameter { my $signature = shift; @@ -2735,6 +2964,7 @@ sub RequiresCustomSignature } +# FIXME: Sort this array. my %non_wrapper_types = ( 'float' => 1, 'double' => 1, @@ -2749,6 +2979,7 @@ my %non_wrapper_types = ( 'unsigned long long' => 1, 'DOMString' => 1, 'CompareHow' => 1, + 'SerializedScriptValue' => 1, 'SVGAngle' => 1, 'SVGRect' => 1, 'SVGPoint' => 1, @@ -2821,6 +3052,8 @@ sub ReturnNativeToJSValue return "return v8::Integer::NewFromUnsigned($value)" if $nativeType eq "unsigned"; return "return v8DateOrNull($value)" if $type eq "Date"; + # long long and unsigned long long are not representable in ECMAScript. + return "return v8::Number::New(static_cast<double>($value))" if $type eq "long long" or $type eq "unsigned long long"; return "return v8::Number::New($value)" if $codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType"; return "return $value.v8Value()" if $nativeType eq "ScriptValue"; @@ -2833,6 +3066,8 @@ sub ReturnNativeToJSValue die "Unknown value for ConvertNullStringTo extended attribute"; } + $conv = $signature->extendedAttributes->{"ConvertScriptString"}; + return "v8StringOrNull(exec, $value)" if $conv; return "return v8String($value)"; } |