summaryrefslogtreecommitdiffstats
path: root/WebCore/bindings/scripts/CodeGeneratorV8.pm
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/bindings/scripts/CodeGeneratorV8.pm')
-rw-r--r--WebCore/bindings/scripts/CodeGeneratorV8.pm293
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)";
}