Changeset 141360 in webkit


Ignore:
Timestamp:
Jan 30, 2013 6:21:05 PM (11 years ago)
Author:
commit-queue@webkit.org
Message:

[V8] Add IDL 'enum' support to CodeGeneratorV8.pm
https://bugs.webkit.org/show_bug.cgi?id=106553

Patch by Nils Barth <nbarth@google.com> on 2013-01-30
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):

Location:
trunk/Source/WebCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r141358 r141360  
     12013-01-30  Nils Barth  <nbarth@google.com>
     2
     3        [V8] Add IDL 'enum' support to CodeGeneratorV8.pm
     4        https://bugs.webkit.org/show_bug.cgi?id=106553
     5
     6        Reviewed by Kentaro Hara.
     7
     8        Add partial support for Web IDL enumerations in V8 bindings
     9
     10        Binding generators currently cannot handle IDL enumerations.
     11        (An enumeration is an DOMString with a limited set of values, thus
     12        treated internally as DOMString, with validation code added in
     13        bindings.)
     14        This adds support for enumerations in V8, adding validation checking
     15        to setters.
     16        It does not add validation checking to operations (no test case), and
     17        does not add support in JSC.
     18
     19        Test: bindings/scripts/test/TestObj.idl (run-bindings-test)
     20
     21        * bindings/scripts/IDLParser.pm:
     22         - Parser assumes all IDL definitions are interfaces; add support for
     23           other definitions
     24         - Parser parses but discards enum definitions; instead, record
     25           parsed data
     26        (Parse): Sort definitions into interfaces and enums.
     27        Remove "@definitions eq (someIdlDocument)" test, as this never
     28        happens (fossil code) -- parseDefinitions returns list of definitions,
     29        never a one-item list consisting of a document (no nested documents).
     30        (unquoteString): new utility function to unquote StringToken (token
     31        itself still quoted)
     32        (parseEnum):
     33        (parseEnumValueList):
     34        (parseEnumValues):
     35        (parseEnumOld):
     36
     37        * bindings/scripts/CodeGenerator.pm:
     38         - Expose parsed enum data to backends (detect enums, list valid
     39           values)
     40         - Enums treated as DOMString type in internal function
     41        (ProcessDocument):
     42        (IsEnumType):
     43        (ValidEnumValues):
     44        (IsRefPtrType):
     45        * bindings/scripts/CodeGeneratorV8.pm:
     46         - Enums treated as DOMString type in internal functions
     47         - Add validation to setter
     48        (GenerateNormalAttrSetter):
     49        (GetNativeType):
     50        (JSValueToNative):
     51        (NativeToJSValue):
     52        (ConvertToV8StringResource):
     53        * bindings/scripts/test/TestObj.idl:
     54         - New enum type and enum variable test for IDL enumeration support
     55        * bindings/scripts/test/V8/V8TestObj.cpp:
     56         - Generated code, desired behavior
     57        (WebCore::TestObjV8Internal::enumAttrAttrGetter):
     58        (TestObjV8Internal):
     59        (WebCore::TestObjV8Internal::enumAttrAttrSetter):
     60        (WebCore):
     61        * bindings/scripts/test/JS/JSTestObj.cpp:
     62         - Generated code, currently incorrect
     63        (WebCore):
     64        (WebCore::jsTestObjEnumAttr):
     65        (WebCore::setJSTestObjEnumAttr):
     66        * bindings/scripts/test/JS/JSTestObj.h:
     67         - Generated code, currently incorrect
     68        (WebCore):
     69
    1702013-01-30  Nico Weber  <thakis@chromium.org>
    271
  • trunk/Source/WebCore/bindings/scripts/CodeGenerator.pm

    r140884 r141360  
    5454my %stringTypeHash = ("DOMString" => 1, "AtomicString" => 1);
    5555
     56my %enumTypeHash = ();
     57
    5658my %nonPointerTypeHash = ("DOMTimeStamp" => 1, "CompareHow" => 1);
    5759
     
    124126    require $ifaceName . ".pm";
    125127
     128    %enumTypeHash = map { $_->name => $_->values } @{$useDocument->enumerations};
     129
    126130    # Dynamically load external code generation perl module
    127131    $codeGenerator = $ifaceName->new($object, $useLayerOnTop, $preprocessor, $writeDependencies, $verbose, $targetIdlFilePath);
     
    351355}
    352356
     357sub IsEnumType
     358{
     359    my $object = shift;
     360    my $type = shift;
     361
     362    return 1 if exists $enumTypeHash{$type};
     363    return 0;
     364}
     365
     366sub ValidEnumValues
     367{
     368    my $object = shift;
     369    my $type = shift;
     370
     371    return @{$enumTypeHash{$type}};
     372}
     373
    353374sub IsNonPointerType
    354375{
     
    398419    return 0 if $object->GetSequenceType($type);
    399420    return 0 if $type eq "DOMString";
     421    return 0 if $object->IsEnumType($type);
    400422
    401423    return 1;
  • trunk/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm

    r141034 r141360  
    11601160    my $attrName = $attribute->signature->name;
    11611161    my $attrExt = $attribute->signature->extendedAttributes;
     1162    my $attrType = $attribute->signature->type;
    11621163
    11631164    my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
     
    12041205END
    12051206    } else {
    1206         my $attrType = $attribute->signature->type;
    12071207        my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
    12081208        if ($reflect && $codeGenerator->InheritsInterface($interface, "Node") && $codeGenerator->IsStringType($attrType)) {
     
    12441244            push(@implContentDecls, "    $nativeType v = $value;\n");
    12451245        }
     1246    }
     1247
     1248    if ($codeGenerator->IsEnumType($attrType)) {
     1249        # setter ignores invalid enumeration values
     1250        my @enumValues = $codeGenerator->ValidEnumValues($attrType);
     1251        my @validEqualities = ();
     1252        foreach my $enumValue (@enumValues) {
     1253            push(@validEqualities, "string == \"$enumValue\"");
     1254        }
     1255        my $enumValidationExpression = join(" || ", @validEqualities);
     1256        push(@implContentDecls, <<END);
     1257    String string = v;
     1258    if (!($enumValidationExpression))
     1259        return;
     1260END
    12461261    }
    12471262
     
    38633878    return "bool" if $type eq "boolean";
    38643879
    3865     return "V8StringResource" if $type eq "DOMString" and $isParameter;
    3866     return "String" if $type eq "DOMString";
     3880    return "V8StringResource" if ($type eq "DOMString" or $codeGenerator->IsEnumType($type)) and $isParameter;
     3881    return "String" if $type eq "DOMString" or $codeGenerator->IsEnumType($type);
    38673882
    38683883    return "Range::CompareHow" if $type eq "CompareHow";
     
    39483963
    39493964    if ($type eq "DOMString") {
     3965        return $value;
     3966    }
     3967
     3968    if ($codeGenerator->IsEnumType($type)) {
    39503969        return $value;
    39513970    }
     
    42274246    return "$value.v8Value()" if $nativeType eq "ScriptValue";
    42284247
    4229     if ($codeGenerator->IsStringType($type)) {
     4248    if ($codeGenerator->IsStringType($type) or $codeGenerator->IsEnumType($type)) {
    42304249        my $conv = $signature->extendedAttributes->{"TreatReturnedNullStringAs"};
    42314250        if (defined $conv) {
     
    43544373
    43554374    die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8StringResource/;
    4356     if ($signature->type eq "DOMString") {
     4375    if ($signature->type eq "DOMString" or $codeGenerator->IsEnumType($signature->type)) {
    43574376        my $macro = "V8TRYCATCH_FOR_V8STRINGRESOURCE";
    43584377        $macro .= "_$suffix" if $suffix;
  • trunk/Source/WebCore/bindings/scripts/IDLParser.pm

    r135547 r141360  
    3636# Used to represent a parsed IDL document
    3737struct( idlDocument => {
    38     interfaces => '@',  # All parsed interfaces
    39     fileName => '$'  # file name
     38    interfaces => '@', # All parsed interfaces
     39    enumerations => '@', # All parsed enumerations
     40    fileName => '$', # file name
    4041});
    4142
     
    8788});
    8889
     90# Used to represent 'enum' definitions
     91struct( domEnum => {
     92    name => '$', # Enumeration identifier
     93    values => '@', # Enumeration values (list of unique strings)
     94});
     95
    8996struct( Token => {
    9097    type => '$', # type of token
     
    166173    die $@ . " in $fileName" if $@;
    167174
    168     die "No document found" unless @definitions;
    169 
    170     my $document;
    171     if ($#definitions == 0 && ref($definitions[0]) eq "idlDocument") {
    172         $document = $definitions[0];
    173     } else {
    174         $document = idlDocument->new();
    175         push(@{$document->interfaces}, @definitions);
    176     }
    177 
     175    die "No definitions founds" unless @definitions;
     176
     177    my $document = idlDocument->new();
    178178    $document->fileName($fileName);
     179    foreach my $definition (@definitions) {
     180        if (ref($definition) eq "domInterface") {
     181            push(@{$document->interfaces}, $definition);
     182        } elsif (ref($definition) eq "domEnum") {
     183            push(@{$document->enumerations}, $definition);
     184        } else {
     185            die "Unrecognized IDL definition kind: \"" . ref($definition) . "\"";
     186        }
     187    }
    179188    return $document;
    180189}
     
    252261    }
    253262    die "Failed in tokenizing at " . $self->{Line};
     263}
     264
     265sub unquoteString
     266{
     267    my $self = shift;
     268    my $quotedString = shift;
     269    if ($quotedString =~ /^"([^"]*)"$/) {
     270        return $1;
     271    }
     272    die "Failed to parse string (" . $quotedString . ") at " . $self->{Line};
    254273}
    255274
     
    633652{
    634653    my $self = shift;
    635     my $extendedAttributeList = shift;
     654    my $extendedAttributeList = shift; # ignored: Extended attributes are not applicable to enumerations
    636655
    637656    my $next = $self->nextToken();
    638657    if ($next->value() eq "enum") {
     658        my $enum = domEnum->new();
    639659        $self->assertTokenValue($self->getToken(), "enum", __LINE__);
    640         $self->assertTokenType($self->getToken(), IdentifierToken);
     660        my $enumNameToken = $self->getToken();
     661        $self->assertTokenType($enumNameToken, IdentifierToken);
     662        $enum->name($enumNameToken->value());
    641663        $self->assertTokenValue($self->getToken(), "{", __LINE__);
    642         $self->parseEnumValueList();
     664        push(@{$enum->values}, @{$self->parseEnumValueList()});
    643665        $self->assertTokenValue($self->getToken(), "}", __LINE__);
    644666        $self->assertTokenValue($self->getToken(), ";", __LINE__);
    645         return;
     667        return $enum;
    646668    }
    647669    $self->assertUnexpectedToken($next->value(), __LINE__);
     
    651673{
    652674    my $self = shift;
     675    my @values = ();
    653676    my $next = $self->nextToken();
    654677    if ($next->type() == StringToken) {
    655         $self->assertTokenType($self->getToken(), StringToken);
    656         $self->parseEnumValues();
    657         return;
    658     }
     678        my $enumValueToken = $self->getToken();
     679        $self->assertTokenType($enumValueToken, StringToken);
     680        my $enumValue = $self->unquoteString($enumValueToken->value());
     681        push(@values, $enumValue);
     682        push(@values, @{$self->parseEnumValues()});
     683        return \@values;
     684    }
     685    # value list must be non-empty
    659686    $self->assertUnexpectedToken($next->value(), __LINE__);
    660687}
     
    663690{
    664691    my $self = shift;
     692    my @values = ();
    665693    my $next = $self->nextToken();
    666694    if ($next->value() eq ",") {
    667695        $self->assertTokenValue($self->getToken(), ",", __LINE__);
    668         $self->assertTokenType($self->getToken(), StringToken);
    669         $self->parseEnumValues();
    670     }
     696        my $enumValueToken = $self->getToken();
     697        $self->assertTokenType($enumValueToken, StringToken);
     698        my $enumValue = $self->unquoteString($enumValueToken->value());
     699        push(@values, $enumValue);
     700        push(@values, @{$self->parseEnumValues()});
     701        return \@values;
     702    }
     703    return \@values; # empty list (end of enumeration-values)
    671704}
    672705
     
    21882221    my $next = $self->nextToken();
    21892222    if ($next->value() eq "enum") {
     2223        my $enum = domEnum->new();
    21902224        $self->assertTokenValue($self->getToken(), "enum", __LINE__);
    2191         $self->parseExtendedAttributeListAllowEmpty();
    2192         $self->assertTokenType($self->getToken(), IdentifierToken);
     2225        my $enumNameToken = $self->getToken();
     2226        $self->assertTokenType($enumNameToken, IdentifierToken);
     2227        $enum->name($enumNameToken->value());
    21932228        $self->assertTokenValue($self->getToken(), "{", __LINE__);
    2194         $self->parseEnumValueList();
     2229        push(@{$enum->values}, @{$self->parseEnumValueList()});
    21952230        $self->assertTokenValue($self->getToken(), "}", __LINE__);
    21962231        $self->assertTokenValue($self->getToken(), ";", __LINE__);
    2197         return;
     2232        return $enum;
    21982233    }
    21992234    $self->assertUnexpectedToken($next->value(), __LINE__);
  • trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp

    r140488 r141360  
    3737#include "JSScriptProfile.h"
    3838#include "JSTestCallback.h"
     39#include "JSTestEnumType.h"
    3940#include "JSTestObj.h"
    4041#include "JSTestSubObj.h"
     
    5152#include "ScriptProfile.h"
    5253#include "SerializedScriptValue.h"
     54#include "TestEnumType.h"
    5355#include "TestObj.h"
    5456#include "bool.h"
     
    8284    { "readOnlyStringAttr", DontDelete | ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjReadOnlyStringAttr), (intptr_t)0, NoIntrinsic },
    8385    { "readOnlyTestObjAttr", DontDelete | ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjReadOnlyTestObjAttr), (intptr_t)0, NoIntrinsic },
     86    { "enumAttr", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjEnumAttr), (intptr_t)setJSTestObjEnumAttr, NoIntrinsic },
    8487    { "shortAttr", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjShortAttr), (intptr_t)setJSTestObjShortAttr, NoIntrinsic },
    8588    { "unsignedShortAttr", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjUnsignedShortAttr), (intptr_t)setJSTestObjUnsignedShortAttr, NoIntrinsic },
     
    442445
    443446
     447JSValue jsTestObjEnumAttr(ExecState* exec, JSValue slotBase, PropertyName)
     448{
     449    JSTestObj* castedThis = jsCast<JSTestObj*>(asObject(slotBase));
     450    UNUSED_PARAM(exec);
     451    TestObj* impl = static_cast<TestObj*>(castedThis->impl());
     452    JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(impl->enumAttr()));
     453    return result;
     454}
     455
     456
    444457JSValue jsTestObjShortAttr(ExecState* exec, JSValue slotBase, PropertyName)
    445458{
     
    978991    UNUSED_PARAM(exec);
    979992    TestObj::setStaticStringAttr(value.isEmpty() ? String() : value.toString(exec)->value(exec));
     993}
     994
     995
     996void setJSTestObjEnumAttr(ExecState* exec, JSObject* thisObject, JSValue value)
     997{
     998    UNUSED_PARAM(exec);
     999    JSTestObj* castedThis = jsCast<JSTestObj*>(thisObject);
     1000    TestObj* impl = static_cast<TestObj*>(castedThis->impl());
     1001    impl->setEnumAttr(toTestEnumType(value));
    9801002}
    9811003
  • trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.h

    r140488 r141360  
    229229void setJSTestObjConstructorStaticStringAttr(JSC::ExecState*, JSC::JSObject*, JSC::JSValue);
    230230JSC::JSValue jsTestObjConstructorTestSubObj(JSC::ExecState*, JSC::JSValue, JSC::PropertyName);
     231JSC::JSValue jsTestObjEnumAttr(JSC::ExecState*, JSC::JSValue, JSC::PropertyName);
     232void setJSTestObjEnumAttr(JSC::ExecState*, JSC::JSObject*, JSC::JSValue);
    231233JSC::JSValue jsTestObjShortAttr(JSC::ExecState*, JSC::JSValue, JSC::PropertyName);
    232234void setJSTestObjShortAttr(JSC::ExecState*, JSC::JSObject*, JSC::JSValue);
  • trunk/Source/WebCore/bindings/scripts/test/TestObj.idl

    r140488 r141360  
    3030// This IDL file is for testing the bindings code generator and for tracking
    3131// changes in its ouput.
     32
     33#if defined(TESTING_JS) || defined(TESTING_V8)
     34enum TestEnumType { "", "EnumValue1", "EnumValue2", "EnumValue3" };
     35#endif
     36
    3237[
    3338    Constructor(in [Callback] TestCallback testCallback),
     
    4247    static attribute DOMString         staticStringAttr;
    4348    static readonly attribute TestSubObjConstructor TestSubObj;
     49    attribute TestEnumType             enumAttr;
    4450#endif
    4551    attribute short                    shortAttr;
  • trunk/Source/WebCore/bindings/scripts/test/V8/V8TestObj.cpp

    r141105 r141360  
    146146}
    147147
     148static v8::Handle<v8::Value> enumAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
     149{
     150    TestObj* imp = V8TestObj::toNative(info.Holder());
     151    return v8String(imp->enumAttr(), info.GetIsolate(), ReturnUnsafeHandle);
     152}
     153
     154static void enumAttrAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
     155{
     156    TestObj* imp = V8TestObj::toNative(info.Holder());
     157    V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, v, value);
     158    String string = v;
     159    if (!(string == "" || string == "EnumValue1" || string == "EnumValue2" || string == "EnumValue3"))
     160        return;
     161    imp->setEnumAttr(v);
     162    return;
     163}
     164
    148165static v8::Handle<v8::Value> shortAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
    149166{
     
    18521869    // Attribute 'TestSubObj' (Type: 'readonly attribute' ExtAttr: '')
    18531870    {"TestSubObj", TestObjV8Internal::TestObjConstructorGetter, 0, &V8TestSubObj::info, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */},
     1871    // Attribute 'enumAttr' (Type: 'attribute' ExtAttr: '')
     1872    {"enumAttr", TestObjV8Internal::enumAttrAttrGetter, TestObjV8Internal::enumAttrAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */},
    18541873    // Attribute 'shortAttr' (Type: 'attribute' ExtAttr: '')
    18551874    {"shortAttr", TestObjV8Internal::shortAttrAttrGetter, TestObjV8Internal::shortAttrAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */},
Note: See TracChangeset for help on using the changeset viewer.