Diff
Modified: trunk/Source/WebCore/ChangeLog (141359 => 141360)
--- trunk/Source/WebCore/ChangeLog 2013-01-31 02:19:23 UTC (rev 141359)
+++ trunk/Source/WebCore/ChangeLog 2013-01-31 02:21:05 UTC (rev 141360)
@@ -1,3 +1,72 @@
+2013-01-30 Nils Barth <[email protected]>
+
+ [V8] Add IDL 'enum' support to CodeGeneratorV8.pm
+ https://bugs.webkit.org/show_bug.cgi?id=106553
+
+ Reviewed by Kentaro Hara.
+
+ Add partial support for Web IDL enumerations in V8 bindings
+
+ Binding generators currently cannot handle IDL enumerations.
+ (An enumeration is an DOMString with a limited set of values, thus
+ treated internally as DOMString, with validation code added in
+ bindings.)
+ This adds support for enumerations in V8, adding validation checking
+ to setters.
+ It does not add validation checking to operations (no test case), and
+ does not add support in JSC.
+
+ Test: bindings/scripts/test/TestObj.idl (run-bindings-test)
+
+ * bindings/scripts/IDLParser.pm:
+ - Parser assumes all IDL definitions are interfaces; add support for
+ other definitions
+ - Parser parses but discards enum definitions; instead, record
+ parsed data
+ (Parse): Sort definitions into interfaces and enums.
+ Remove "@definitions eq (someIdlDocument)" test, as this never
+ happens (fossil code) -- parseDefinitions returns list of definitions,
+ never a one-item list consisting of a document (no nested documents).
+ (unquoteString): new utility function to unquote StringToken (token
+ itself still quoted)
+ (parseEnum):
+ (parseEnumValueList):
+ (parseEnumValues):
+ (parseEnumOld):
+
+ * bindings/scripts/CodeGenerator.pm:
+ - Expose parsed enum data to backends (detect enums, list valid
+ values)
+ - Enums treated as DOMString type in internal function
+ (ProcessDocument):
+ (IsEnumType):
+ (ValidEnumValues):
+ (IsRefPtrType):
+ * bindings/scripts/CodeGeneratorV8.pm:
+ - Enums treated as DOMString type in internal functions
+ - Add validation to setter
+ (GenerateNormalAttrSetter):
+ (GetNativeType):
+ (JSValueToNative):
+ (NativeToJSValue):
+ (ConvertToV8StringResource):
+ * bindings/scripts/test/TestObj.idl:
+ - New enum type and enum variable test for IDL enumeration support
+ * bindings/scripts/test/V8/V8TestObj.cpp:
+ - Generated code, desired behavior
+ (WebCore::TestObjV8Internal::enumAttrAttrGetter):
+ (TestObjV8Internal):
+ (WebCore::TestObjV8Internal::enumAttrAttrSetter):
+ (WebCore):
+ * bindings/scripts/test/JS/JSTestObj.cpp:
+ - Generated code, currently incorrect
+ (WebCore):
+ (WebCore::jsTestObjEnumAttr):
+ (WebCore::setJSTestObjEnumAttr):
+ * bindings/scripts/test/JS/JSTestObj.h:
+ - Generated code, currently incorrect
+ (WebCore):
+
2013-01-30 Nico Weber <[email protected]>
[chromium] Build webkit with enable_web_intents set to 0.
Modified: trunk/Source/WebCore/bindings/scripts/CodeGenerator.pm (141359 => 141360)
--- trunk/Source/WebCore/bindings/scripts/CodeGenerator.pm 2013-01-31 02:19:23 UTC (rev 141359)
+++ trunk/Source/WebCore/bindings/scripts/CodeGenerator.pm 2013-01-31 02:21:05 UTC (rev 141360)
@@ -53,6 +53,8 @@
my %stringTypeHash = ("DOMString" => 1, "AtomicString" => 1);
+my %enumTypeHash = ();
+
my %nonPointerTypeHash = ("DOMTimeStamp" => 1, "CompareHow" => 1);
my %svgAnimatedTypeHash = ("SVGAnimatedAngle" => 1, "SVGAnimatedBoolean" => 1,
@@ -123,6 +125,8 @@
my $ifaceName = "CodeGenerator" . $useGenerator;
require $ifaceName . ".pm";
+ %enumTypeHash = map { $_->name => $_->values } @{$useDocument->enumerations};
+
# Dynamically load external code generation perl module
$codeGenerator = $ifaceName->new($object, $useLayerOnTop, $preprocessor, $writeDependencies, $verbose, $targetIdlFilePath);
unless (defined($codeGenerator)) {
@@ -350,6 +354,23 @@
return 0;
}
+sub IsEnumType
+{
+ my $object = shift;
+ my $type = shift;
+
+ return 1 if exists $enumTypeHash{$type};
+ return 0;
+}
+
+sub ValidEnumValues
+{
+ my $object = shift;
+ my $type = shift;
+
+ return @{$enumTypeHash{$type}};
+}
+
sub IsNonPointerType
{
my $object = shift;
@@ -397,6 +418,7 @@
return 0 if $object->GetArrayType($type);
return 0 if $object->GetSequenceType($type);
return 0 if $type eq "DOMString";
+ return 0 if $object->IsEnumType($type);
return 1;
}
Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm (141359 => 141360)
--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm 2013-01-31 02:19:23 UTC (rev 141359)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm 2013-01-31 02:21:05 UTC (rev 141360)
@@ -1159,6 +1159,7 @@
my $v8InterfaceName = "V8$interfaceName";
my $attrName = $attribute->signature->name;
my $attrExt = $attribute->signature->extendedAttributes;
+ my $attrType = $attribute->signature->type;
my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
@@ -1203,7 +1204,6 @@
${interfaceName}* imp = ${v8InterfaceName}::toNative(info.Holder());
END
} else {
- my $attrType = $attribute->signature->type;
my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
if ($reflect && $codeGenerator->InheritsInterface($interface, "Node") && $codeGenerator->IsStringType($attrType)) {
# Generate super-compact call for regular attribute setter:
@@ -1245,6 +1245,21 @@
}
}
+ if ($codeGenerator->IsEnumType($attrType)) {
+ # setter ignores invalid enumeration values
+ my @enumValues = $codeGenerator->ValidEnumValues($attrType);
+ my @validEqualities = ();
+ foreach my $enumValue (@enumValues) {
+ push(@validEqualities, "string == \"$enumValue\"");
+ }
+ my $enumValidationExpression = join(" || ", @validEqualities);
+ push(@implContentDecls, <<END);
+ String string = v;
+ if (!($enumValidationExpression))
+ return;
+END
+ }
+
my $result = "v";
my $returnType = $attribute->signature->type;
if ($codeGenerator->IsRefPtrType($returnType) && !$codeGenerator->GetArrayType($returnType)) {
@@ -3862,8 +3877,8 @@
return "unsigned long long" if $type eq "unsigned long long";
return "bool" if $type eq "boolean";
- return "V8StringResource" if $type eq "DOMString" and $isParameter;
- return "String" if $type eq "DOMString";
+ return "V8StringResource" if ($type eq "DOMString" or $codeGenerator->IsEnumType($type)) and $isParameter;
+ return "String" if $type eq "DOMString" or $codeGenerator->IsEnumType($type);
return "Range::CompareHow" if $type eq "CompareHow";
return "DOMTimeStamp" if $type eq "DOMTimeStamp";
@@ -3950,6 +3965,10 @@
return $value;
}
+ if ($codeGenerator->IsEnumType($type)) {
+ return $value;
+ }
+
if ($type eq "SerializedScriptValue") {
AddToImplIncludes("SerializedScriptValue.h");
return "SerializedScriptValue::create($value, $getIsolate)";
@@ -4226,7 +4245,7 @@
return "v8::Number::New($value)" if $codeGenerator->IsPrimitiveType($type);
return "$value.v8Value()" if $nativeType eq "ScriptValue";
- if ($codeGenerator->IsStringType($type)) {
+ if ($codeGenerator->IsStringType($type) or $codeGenerator->IsEnumType($type)) {
my $conv = $signature->extendedAttributes->{"TreatReturnedNullStringAs"};
if (defined $conv) {
return "v8StringOrNull($value, $getIsolate$returnHandleTypeArg)" if $conv eq "Null";
@@ -4353,7 +4372,7 @@
my $suffix = shift;
die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8StringResource/;
- if ($signature->type eq "DOMString") {
+ if ($signature->type eq "DOMString" or $codeGenerator->IsEnumType($signature->type)) {
my $macro = "V8TRYCATCH_FOR_V8STRINGRESOURCE";
$macro .= "_$suffix" if $suffix;
return "$macro($nativeType, $variableName, $value);"
Modified: trunk/Source/WebCore/bindings/scripts/IDLParser.pm (141359 => 141360)
--- trunk/Source/WebCore/bindings/scripts/IDLParser.pm 2013-01-31 02:19:23 UTC (rev 141359)
+++ trunk/Source/WebCore/bindings/scripts/IDLParser.pm 2013-01-31 02:21:05 UTC (rev 141360)
@@ -35,8 +35,9 @@
# Used to represent a parsed IDL document
struct( idlDocument => {
- interfaces => '@', # All parsed interfaces
- fileName => '$' # file name
+ interfaces => '@', # All parsed interfaces
+ enumerations => '@', # All parsed enumerations
+ fileName => '$', # file name
});
# Used to represent 'interface' blocks
@@ -86,6 +87,12 @@
extendedAttributes => '$', # Extended attributes
});
+# Used to represent 'enum' definitions
+struct( domEnum => {
+ name => '$', # Enumeration identifier
+ values => '@', # Enumeration values (list of unique strings)
+});
+
struct( Token => {
type => '$', # type of token
value => '$' # value of token
@@ -165,17 +172,19 @@
};
die $@ . " in $fileName" if $@;
- die "No document found" unless @definitions;
+ die "No definitions founds" unless @definitions;
- my $document;
- if ($#definitions == 0 && ref($definitions[0]) eq "idlDocument") {
- $document = $definitions[0];
- } else {
- $document = idlDocument->new();
- push(@{$document->interfaces}, @definitions);
+ my $document = idlDocument->new();
+ $document->fileName($fileName);
+ foreach my $definition (@definitions) {
+ if (ref($definition) eq "domInterface") {
+ push(@{$document->interfaces}, $definition);
+ } elsif (ref($definition) eq "domEnum") {
+ push(@{$document->enumerations}, $definition);
+ } else {
+ die "Unrecognized IDL definition kind: \"" . ref($definition) . "\"";
+ }
}
-
- $document->fileName($fileName);
return $document;
}
@@ -253,6 +262,16 @@
die "Failed in tokenizing at " . $self->{Line};
}
+sub unquoteString
+{
+ my $self = shift;
+ my $quotedString = shift;
+ if ($quotedString =~ /^"([^"]*)"$/) {
+ return $1;
+ }
+ die "Failed to parse string (" . $quotedString . ") at " . $self->{Line};
+}
+
my $nextAttributeOld_1 = '^(attribute|inherit|readonly)$';
my $nextPrimitiveType_1 = '^(int|long|short|unsigned)$';
my $nextPrimitiveType_2 = '^(double|float|unrestricted)$';
@@ -632,17 +651,20 @@
sub parseEnum
{
my $self = shift;
- my $extendedAttributeList = shift;
+ my $extendedAttributeList = shift; # ignored: Extended attributes are not applicable to enumerations
my $next = $self->nextToken();
if ($next->value() eq "enum") {
+ my $enum = domEnum->new();
$self->assertTokenValue($self->getToken(), "enum", __LINE__);
- $self->assertTokenType($self->getToken(), IdentifierToken);
+ my $enumNameToken = $self->getToken();
+ $self->assertTokenType($enumNameToken, IdentifierToken);
+ $enum->name($enumNameToken->value());
$self->assertTokenValue($self->getToken(), "{", __LINE__);
- $self->parseEnumValueList();
+ push(@{$enum->values}, @{$self->parseEnumValueList()});
$self->assertTokenValue($self->getToken(), "}", __LINE__);
$self->assertTokenValue($self->getToken(), ";", __LINE__);
- return;
+ return $enum;
}
$self->assertUnexpectedToken($next->value(), __LINE__);
}
@@ -650,24 +672,35 @@
sub parseEnumValueList
{
my $self = shift;
+ my @values = ();
my $next = $self->nextToken();
if ($next->type() == StringToken) {
- $self->assertTokenType($self->getToken(), StringToken);
- $self->parseEnumValues();
- return;
+ my $enumValueToken = $self->getToken();
+ $self->assertTokenType($enumValueToken, StringToken);
+ my $enumValue = $self->unquoteString($enumValueToken->value());
+ push(@values, $enumValue);
+ push(@values, @{$self->parseEnumValues()});
+ return \@values;
}
+ # value list must be non-empty
$self->assertUnexpectedToken($next->value(), __LINE__);
}
sub parseEnumValues
{
my $self = shift;
+ my @values = ();
my $next = $self->nextToken();
if ($next->value() eq ",") {
$self->assertTokenValue($self->getToken(), ",", __LINE__);
- $self->assertTokenType($self->getToken(), StringToken);
- $self->parseEnumValues();
+ my $enumValueToken = $self->getToken();
+ $self->assertTokenType($enumValueToken, StringToken);
+ my $enumValue = $self->unquoteString($enumValueToken->value());
+ push(@values, $enumValue);
+ push(@values, @{$self->parseEnumValues()});
+ return \@values;
}
+ return \@values; # empty list (end of enumeration-values)
}
sub parseCallbackRest
@@ -2187,14 +2220,16 @@
my $self = shift;
my $next = $self->nextToken();
if ($next->value() eq "enum") {
+ my $enum = domEnum->new();
$self->assertTokenValue($self->getToken(), "enum", __LINE__);
- $self->parseExtendedAttributeListAllowEmpty();
- $self->assertTokenType($self->getToken(), IdentifierToken);
+ my $enumNameToken = $self->getToken();
+ $self->assertTokenType($enumNameToken, IdentifierToken);
+ $enum->name($enumNameToken->value());
$self->assertTokenValue($self->getToken(), "{", __LINE__);
- $self->parseEnumValueList();
+ push(@{$enum->values}, @{$self->parseEnumValueList()});
$self->assertTokenValue($self->getToken(), "}", __LINE__);
$self->assertTokenValue($self->getToken(), ";", __LINE__);
- return;
+ return $enum;
}
$self->assertUnexpectedToken($next->value(), __LINE__);
}
Modified: trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp (141359 => 141360)
--- trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp 2013-01-31 02:19:23 UTC (rev 141359)
+++ trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp 2013-01-31 02:21:05 UTC (rev 141360)
@@ -36,6 +36,7 @@
#include "JSSVGPoint.h"
#include "JSScriptProfile.h"
#include "JSTestCallback.h"
+#include "JSTestEnumType.h"
#include "JSTestObj.h"
#include "JSTestSubObj.h"
#include "JSa.h"
@@ -50,6 +51,7 @@
#include "ScriptCallStackFactory.h"
#include "ScriptProfile.h"
#include "SerializedScriptValue.h"
+#include "TestEnumType.h"
#include "TestObj.h"
#include "bool.h"
#include <runtime/Error.h>
@@ -81,6 +83,7 @@
{ "readOnlyLongAttr", DontDelete | ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjReadOnlyLongAttr), (intptr_t)0, NoIntrinsic },
{ "readOnlyStringAttr", DontDelete | ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjReadOnlyStringAttr), (intptr_t)0, NoIntrinsic },
{ "readOnlyTestObjAttr", DontDelete | ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjReadOnlyTestObjAttr), (intptr_t)0, NoIntrinsic },
+ { "enumAttr", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjEnumAttr), (intptr_t)setJSTestObjEnumAttr, NoIntrinsic },
{ "shortAttr", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjShortAttr), (intptr_t)setJSTestObjShortAttr, NoIntrinsic },
{ "unsignedShortAttr", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjUnsignedShortAttr), (intptr_t)setJSTestObjUnsignedShortAttr, NoIntrinsic },
{ "longAttr", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjLongAttr), (intptr_t)setJSTestObjLongAttr, NoIntrinsic },
@@ -441,6 +444,16 @@
}
+JSValue jsTestObjEnumAttr(ExecState* exec, JSValue slotBase, PropertyName)
+{
+ JSTestObj* castedThis = jsCast<JSTestObj*>(asObject(slotBase));
+ UNUSED_PARAM(exec);
+ TestObj* impl = static_cast<TestObj*>(castedThis->impl());
+ JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(impl->enumAttr()));
+ return result;
+}
+
+
JSValue jsTestObjShortAttr(ExecState* exec, JSValue slotBase, PropertyName)
{
JSTestObj* castedThis = jsCast<JSTestObj*>(asObject(slotBase));
@@ -980,6 +993,15 @@
}
+void setJSTestObjEnumAttr(ExecState* exec, JSObject* thisObject, JSValue value)
+{
+ UNUSED_PARAM(exec);
+ JSTestObj* castedThis = jsCast<JSTestObj*>(thisObject);
+ TestObj* impl = static_cast<TestObj*>(castedThis->impl());
+ impl->setEnumAttr(toTestEnumType(value));
+}
+
+
void setJSTestObjShortAttr(ExecState* exec, JSObject* thisObject, JSValue value)
{
UNUSED_PARAM(exec);
Modified: trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.h (141359 => 141360)
--- trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.h 2013-01-31 02:19:23 UTC (rev 141359)
+++ trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.h 2013-01-31 02:21:05 UTC (rev 141360)
@@ -228,6 +228,8 @@
JSC::JSValue jsTestObjConstructorStaticStringAttr(JSC::ExecState*, JSC::JSValue, JSC::PropertyName);
void setJSTestObjConstructorStaticStringAttr(JSC::ExecState*, JSC::JSObject*, JSC::JSValue);
JSC::JSValue jsTestObjConstructorTestSubObj(JSC::ExecState*, JSC::JSValue, JSC::PropertyName);
+JSC::JSValue jsTestObjEnumAttr(JSC::ExecState*, JSC::JSValue, JSC::PropertyName);
+void setJSTestObjEnumAttr(JSC::ExecState*, JSC::JSObject*, JSC::JSValue);
JSC::JSValue jsTestObjShortAttr(JSC::ExecState*, JSC::JSValue, JSC::PropertyName);
void setJSTestObjShortAttr(JSC::ExecState*, JSC::JSObject*, JSC::JSValue);
JSC::JSValue jsTestObjUnsignedShortAttr(JSC::ExecState*, JSC::JSValue, JSC::PropertyName);
Modified: trunk/Source/WebCore/bindings/scripts/test/TestObj.idl (141359 => 141360)
--- trunk/Source/WebCore/bindings/scripts/test/TestObj.idl 2013-01-31 02:19:23 UTC (rev 141359)
+++ trunk/Source/WebCore/bindings/scripts/test/TestObj.idl 2013-01-31 02:21:05 UTC (rev 141360)
@@ -29,6 +29,11 @@
// This IDL file is for testing the bindings code generator and for tracking
// changes in its ouput.
+
+#if defined(TESTING_JS) || defined(TESTING_V8)
+enum TestEnumType { "", "EnumValue1", "EnumValue2", "EnumValue3" };
+#endif
+
[
Constructor(in [Callback] TestCallback testCallback),
InterfaceName=TestObject
@@ -41,6 +46,7 @@
static readonly attribute long staticReadOnlyLongAttr;
static attribute DOMString staticStringAttr;
static readonly attribute TestSubObjConstructor TestSubObj;
+ attribute TestEnumType enumAttr;
#endif
attribute short shortAttr;
attribute unsigned short unsignedShortAttr;
Modified: trunk/Source/WebCore/bindings/scripts/test/V8/V8TestObj.cpp (141359 => 141360)
--- trunk/Source/WebCore/bindings/scripts/test/V8/V8TestObj.cpp 2013-01-31 02:19:23 UTC (rev 141359)
+++ trunk/Source/WebCore/bindings/scripts/test/V8/V8TestObj.cpp 2013-01-31 02:21:05 UTC (rev 141360)
@@ -145,6 +145,23 @@
return;
}
+static v8::Handle<v8::Value> enumAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
+{
+ TestObj* imp = V8TestObj::toNative(info.Holder());
+ return v8String(imp->enumAttr(), info.GetIsolate(), ReturnUnsafeHandle);
+}
+
+static void enumAttrAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
+{
+ TestObj* imp = V8TestObj::toNative(info.Holder());
+ V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, v, value);
+ String string = v;
+ if (!(string == "" || string == "EnumValue1" || string == "EnumValue2" || string == "EnumValue3"))
+ return;
+ imp->setEnumAttr(v);
+ return;
+}
+
static v8::Handle<v8::Value> shortAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
{
TestObj* imp = V8TestObj::toNative(info.Holder());
@@ -1851,6 +1868,8 @@
{"staticStringAttr", TestObjV8Internal::staticStringAttrAttrGetter, TestObjV8Internal::staticStringAttrAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */},
// Attribute 'TestSubObj' (Type: 'readonly attribute' ExtAttr: '')
{"TestSubObj", TestObjV8Internal::TestObjConstructorGetter, 0, &V8TestSubObj::info, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */},
+ // Attribute 'enumAttr' (Type: 'attribute' ExtAttr: '')
+ {"enumAttr", TestObjV8Internal::enumAttrAttrGetter, TestObjV8Internal::enumAttrAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */},
// Attribute 'shortAttr' (Type: 'attribute' ExtAttr: '')
{"shortAttr", TestObjV8Internal::shortAttrAttrGetter, TestObjV8Internal::shortAttrAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */},
// Attribute 'unsignedShortAttr' (Type: 'attribute' ExtAttr: '')