Changeset 211409 in webkit


Ignore:
Timestamp:
Jan 30, 2017 11:17:34 PM (7 years ago)
Author:
Joseph Pecoraro
Message:

[WebIDL] Add support for inherit serializer attribute
https://bugs.webkit.org/show_bug.cgi?id=167274

Reviewed by Darin Adler.

Support for serializer { inherit }, which will be used by Resource Timing.
https://heycam.github.io/webidl/#idl-serializers

  • bindings/scripts/CodeGenerator.pm:

(GetInterfaceForAttribute):
(IsSerializableAttribute):
Determine if an attribute is serializable at generation time so we can
verify types. This allows us to support typedefs. We don't yet support
serializing an attribute that is itself a serializable interface.

  • bindings/scripts/CodeGeneratorJS.pm:

(GenerateSerializerFunction):
(GenerateSerializerAttributesForInterface):
Generate inherited attributes first, then generate our own list.
Explicitly provided attribute names are expected to be serializable,
so produce an error if they are not.

  • bindings/scripts/IDLParser.pm:

(parseSerializationAttributes):
Update parsing of serializer attributes to allow for multiple
special strings. The spec does not precisely define where the
special "attribute" keyword is allowed.

(applyMemberList):
(isSerializableAttribute): Deleted.
Move serializable attribute checking to generation.

  • bindings/scripts/test/JS/JSTestSerialization.cpp:
  • bindings/scripts/test/JS/JSTestSerializationInherit.cpp: Added.
  • bindings/scripts/test/JS/JSTestSerializationInherit.h: Added.
  • bindings/scripts/test/JS/JSTestSerializationInheritFinal.cpp: Added.
  • bindings/scripts/test/JS/JSTestSerializationInheritFinal.h: Added.

The toJSON implementations are the most interesting.

  • bindings/scripts/test/TestSerialization.idl:

Extend this test for typedefed attributes that are serializable.
Change TestNode (a serializable Interface) to TestException (an
unserializable Interface) for expected behavior of an
unserializable attribute.

  • bindings/scripts/test/TestSerializationInherit.idl:

Test for { inherit, attribute }.

  • bindings/scripts/test/TestSerializationInheritFinal.idl:

Test for { inherit, attribute_names... }, and multi-level inherit.

Location:
trunk/Source/WebCore
Files:
5 added
6 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r211406 r211409  
     12017-01-30  Joseph Pecoraro  <pecoraro@apple.com>
     2
     3        [WebIDL] Add support for inherit serializer attribute
     4        https://bugs.webkit.org/show_bug.cgi?id=167274
     5
     6        Reviewed by Darin Adler.
     7
     8        Support for serializer { inherit }, which will be used by Resource Timing.
     9        https://heycam.github.io/webidl/#idl-serializers
     10
     11        * bindings/scripts/CodeGenerator.pm:
     12        (GetInterfaceForAttribute):
     13        (IsSerializableAttribute):
     14        Determine if an attribute is serializable at generation time so we can
     15        verify types. This allows us to support typedefs. We don't yet support
     16        serializing an attribute that is itself a serializable interface.
     17
     18        * bindings/scripts/CodeGeneratorJS.pm:
     19        (GenerateSerializerFunction):
     20        (GenerateSerializerAttributesForInterface):
     21        Generate inherited attributes first, then generate our own list.
     22        Explicitly provided attribute names are expected to be serializable,
     23        so produce an error if they are not.
     24
     25        * bindings/scripts/IDLParser.pm:
     26        (parseSerializationAttributes):
     27        Update parsing of serializer attributes to allow for multiple
     28        special strings. The spec does not precisely define where the
     29        special "attribute" keyword is allowed.
     30
     31        (applyMemberList):
     32        (isSerializableAttribute): Deleted.
     33        Move serializable attribute checking to generation.
     34
     35        * bindings/scripts/test/JS/JSTestSerialization.cpp:
     36        * bindings/scripts/test/JS/JSTestSerializationInherit.cpp: Added.
     37        * bindings/scripts/test/JS/JSTestSerializationInherit.h: Added.
     38        * bindings/scripts/test/JS/JSTestSerializationInheritFinal.cpp: Added.
     39        * bindings/scripts/test/JS/JSTestSerializationInheritFinal.h: Added.
     40        The toJSON implementations are the most interesting.
     41
     42        * bindings/scripts/test/TestSerialization.idl:
     43        Extend this test for typedefed attributes that are serializable.
     44        Change TestNode (a serializable Interface) to TestException (an
     45        unserializable Interface) for expected behavior of an
     46        unserializable attribute.
     47
     48        * bindings/scripts/test/TestSerializationInherit.idl:
     49        Test for { inherit, attribute }.
     50
     51        * bindings/scripts/test/TestSerializationInheritFinal.idl:
     52        Test for { inherit, attribute_names... }, and multi-level inherit.
     53
    1542017-01-30  Joseph Pecoraro  <pecoraro@apple.com>
    255
  • trunk/Source/WebCore/bindings/scripts/CodeGenerator.pm

    r211340 r211409  
    315315}
    316316
     317sub GetInterfaceForAttribute
     318{
     319    my ($object, $currentInterface, $attribute) = @_;
     320
     321    return undef unless $object->IsInterfaceType($attribute->type);
     322
     323    return $object->ParseInterface($currentInterface, $attribute->type->name);
     324}
     325
    317326sub GetAttributeFromInterface
    318327{
     
    914923}
    915924
     925sub IsSerializableAttribute
     926{
     927    my ($object, $currentInterface, $attribute) = @_;
     928
     929    # https://heycam.github.io/webidl/#dfn-serializable-type
     930
     931    my $type = $attribute->type;
     932    return 1 if $type->name eq "boolean";
     933    return 1 if $object->IsNumericType($type);
     934    return 1 if $object->IsEnumType($type);
     935    return 1 if $object->IsStringType($type);
     936    return 0 if $type->name eq "EventHandler";
     937
     938    if ($type->isUnion || $object->IsSequenceType($type) || $object->IsDictionaryType($type)) {
     939        die "Serializer for non-primitive types is not currently supported\n";
     940    }
     941
     942    my $interface = GetInterfaceForAttribute($object, $currentInterface, $attribute);
     943    if ($interface && $interface->serializable) {
     944        die "Serializer for non-primitive types is not currently supported\n";
     945    }
     946
     947    return 0;
     948}
     949
    916950sub GetInterfaceExtendedAttributesFromName
    917951{
  • trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm

    r211403 r211409  
    44014401    push(@implContent, "\n");
    44024402
    4403     my @serializedAttributes = ();
    4404     foreach my $attributeName (@{$interface->serializable->attributes}) {
    4405         my $foundAttribute = 0;
    4406         foreach my $attribute (@{$interface->attributes}) {
    4407             if ($attributeName eq $attribute->name) {
    4408                 push @serializedAttributes, $attribute;
    4409                 $foundAttribute = 1;
    4410                 last;
    4411             }
    4412         }
    4413        
    4414         die "Failed to find \"serializer\" attribute \"$attributeName\" in $interfaceName" if !$foundAttribute;
    4415     }
    4416 
    4417     foreach my $attribute (@serializedAttributes) {
    4418         my $name = $attribute->name;
    4419 
    4420         my $getFunctionName = GetAttributeGetterName($interface, $className, $attribute);
    4421         push(@implContent, "    auto ${name}Value = ${getFunctionName}Getter(*state, *thisObject, throwScope);\n");
    4422         push(@implContent, "    ASSERT(!throwScope.exception());\n");
    4423         push(@implContent, "    result->putDirect(vm, Identifier::fromString(&vm, \"${name}\"), ${name}Value);\n");
    4424         push(@implContent, "\n");
    4425     }
     4403    GenerateSerializerAttributesForInterface($interface, $className);
    44264404
    44274405    push(@implContent, "    return JSValue::encode(result);\n");
     
    44334411    push(@implContent, "}\n");
    44344412    push(@implContent, "\n");
     4413}
     4414
     4415sub GenerateSerializerAttributesForInterface
     4416{
     4417    my ($interface, $className) = @_;
     4418
     4419    my $interfaceName = $interface->type->name;
     4420
     4421    if ($interface->serializable->hasInherit) {
     4422        my $parentSerializerInterface = 0;
     4423        $codeGenerator->ForAllParents($interface, sub {
     4424            my $parentInterface = shift;
     4425            if ($parentInterface->serializable && !$parentSerializerInterface) {
     4426                $parentSerializerInterface = $parentInterface;
     4427            }
     4428        }, 0);
     4429
     4430        die "Failed to find parent interface with \"serializer\" for \"inherit\" serializer in $interfaceName\n" if !$parentSerializerInterface;
     4431
     4432        GenerateSerializerAttributesForInterface($parentSerializerInterface, $className);
     4433    }
     4434
     4435    my @serializedAttributes = ();
     4436
     4437    foreach my $attributeName (@{$interface->serializable->attributes}) {
     4438        my $foundAttribute = 0;
     4439        foreach my $attribute (@{$interface->attributes}) {
     4440            if ($attributeName eq $attribute->name) {
     4441                $foundAttribute = 1;
     4442                if ($codeGenerator->IsSerializableAttribute($interface, $attribute)) {
     4443                    push(@serializedAttributes, $attribute);               
     4444                    last;
     4445                }                   
     4446                die "Explicit \"serializer\" attribute \"$attributeName\" is not serializable\n" if !$interface->serializable->hasAttribute;
     4447                last;
     4448            }
     4449        }
     4450       
     4451        die "Failed to find \"serializer\" attribute \"$attributeName\" in $interfaceName\n" if !$foundAttribute;
     4452    }
     4453
     4454    foreach my $attribute (@serializedAttributes) {
     4455        my $name = $attribute->name;
     4456
     4457        my $getFunctionName = GetAttributeGetterName($interface, $className, $attribute);
     4458        push(@implContent, "    auto ${name}Value = ${getFunctionName}Getter(*state, *thisObject, throwScope);\n");
     4459        push(@implContent, "    ASSERT(!throwScope.exception());\n");
     4460        push(@implContent, "    result->putDirect(vm, Identifier::fromString(&vm, \"${name}\"), ${name}Value);\n");
     4461        push(@implContent, "\n");
     4462    }
    44354463}
    44364464
  • trunk/Source/WebCore/bindings/scripts/IDLParser.pm

    r208893 r211409  
    12371237    my $self = shift;
    12381238    my $serializable = shift;
    1239     my $token = $self->getToken();
    1240 
    1241     if ($token->value() eq "getter") {
    1242         $serializable->hasGetter(1);
    1243         die "Serializer getter keyword is not currently supported.";
    1244 
    1245     }
    1246     if ($token->value() eq "inherit") {
    1247         $serializable->hasInherit(1);
    1248         die "Serializer inherit keyword is not currently supported.";
    1249     }
    1250 
    1251     if ($token->value() eq "attribute") {
    1252         $serializable->hasAttribute(1);
    1253         # Attributes will be filled in via applyMemberList()
    1254         return;
    1255     }
    12561239
    12571240    my @attributes = ();
    1258     $self->assertTokenType($token, IdentifierToken);
    1259     push(@attributes, $token->value());
    1260     push(@attributes, @{$self->parseIdentifiers()});
     1241    my @identifiers = $self->parseIdentifierList();
     1242
     1243    for my $identifier (@identifiers) {
     1244        if ($identifier eq "getter") {
     1245            $serializable->hasGetter(1);
     1246            die "Serializer getter keyword is not currently supported.";
     1247        }
     1248
     1249        if ($identifier eq "inherit") {
     1250            $serializable->hasInherit(1);
     1251            next;
     1252        }
     1253
     1254        if ($identifier eq "attribute") {
     1255            $serializable->hasAttribute(1);
     1256            # Attributes will be filled in via applyMemberList()
     1257            next;
     1258        }
     1259
     1260        push(@attributes, $identifier);
     1261    }
     1262
    12611263    $serializable->attributes(\@attributes);
    12621264}
     
    23782380}
    23792381
    2380 sub isSerializableAttribute
    2381 {
    2382     my $attribute = shift;
    2383 
    2384     # FIXME: Need to support more than primitive serializable types.
    2385     # This check may have to move to the code generator, if we don't have enough information
    2386     # here to determine serializability: https://heycam.github.io/webidl/#idl-serializers
    2387     my $serializable_types = '^(\(byte|octet|short|unsigned short|long|unsigned long|long long|unsigned long long|float|unrestricted float|double|unrestricted double|boolean|DOMString|ByteString|USVString)$';
    2388     return $attribute->type->name =~ /$serializable_types/;
    2389 }
    2390 
    23912382sub applyMemberList
    23922383{
     
    24252416        if ($interface->serializable->hasAttribute) {
    24262417            foreach my $attribute (@{$interface->attributes}) {
    2427                 if (isSerializableAttribute($attribute)) {
    2428                     push(@{$interface->serializable->attributes}, $attribute->name);
    2429                 }
     2418                push(@{$interface->serializable->attributes}, $attribute->name);
    24302419            }
    24312420        } elsif ($numSerializerAttributes == 0) {
  • trunk/Source/WebCore/bindings/scripts/test/JS/JSTestSerialization.cpp

    r211403 r211409  
    2828#include "JSDOMExceptionHandling.h"
    2929#include "JSDOMWrapperCache.h"
    30 #include "JSTestNode.h"
     30#include "JSTestException.h"
    3131#include <runtime/FunctionPrototype.h>
    3232#include <runtime/ObjectConstructor.h>
     
    5353JSC::EncodedJSValue jsTestSerializationFifthLongAttribute(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
    5454bool setJSTestSerializationFifthLongAttribute(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
     55JSC::EncodedJSValue jsTestSerializationSixthTypedefAttribute(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
     56bool setJSTestSerializationSixthTypedefAttribute(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
    5557JSC::EncodedJSValue jsTestSerializationConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
    5658bool setJSTestSerializationConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
     
    108110    { "fourthUnrestrictedDoubleAttribute", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestSerializationFourthUnrestrictedDoubleAttribute), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestSerializationFourthUnrestrictedDoubleAttribute) } },
    109111    { "fifthLongAttribute", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestSerializationFifthLongAttribute), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestSerializationFifthLongAttribute) } },
     112    { "sixthTypedefAttribute", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestSerializationSixthTypedefAttribute), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestSerializationSixthTypedefAttribute) } },
    110113    { "toJSON", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestSerializationPrototypeFunctionToJSON), (intptr_t) (0) } },
    111114};
     
    203206    UNUSED_PARAM(state);
    204207    auto& impl = thisObject.wrapped();
    205     JSValue result = toJS<IDLInterface<TestNode>>(state, *thisObject.globalObject(), impl.thirdUnserializableAttribute());
     208    JSValue result = toJS<IDLInterface<TestException>>(state, *thisObject.globalObject(), impl.thirdUnserializableAttribute());
    206209    return result;
    207210}
     
    236239    auto& impl = thisObject.wrapped();
    237240    JSValue result = toJS<IDLLong>(impl.fifthLongAttribute());
     241    return result;
     242}
     243
     244static inline JSValue jsTestSerializationSixthTypedefAttributeGetter(ExecState&, JSTestSerialization&, ThrowScope& throwScope);
     245
     246EncodedJSValue jsTestSerializationSixthTypedefAttribute(ExecState* state, EncodedJSValue thisValue, PropertyName)
     247{
     248    return BindingCaller<JSTestSerialization>::attribute<jsTestSerializationSixthTypedefAttributeGetter>(state, thisValue, "sixthTypedefAttribute");
     249}
     250
     251static inline JSValue jsTestSerializationSixthTypedefAttributeGetter(ExecState& state, JSTestSerialization& thisObject, ThrowScope& throwScope)
     252{
     253    UNUSED_PARAM(throwScope);
     254    UNUSED_PARAM(state);
     255    auto& impl = thisObject.wrapped();
     256    JSValue result = toJS<IDLDouble>(impl.sixthTypedefAttribute());
    238257    return result;
    239258}
     
    313332    UNUSED_PARAM(throwScope);
    314333    auto& impl = thisObject.wrapped();
    315     auto nativeValue = convert<IDLInterface<TestNode>>(state, value, [](JSC::ExecState& state, JSC::ThrowScope& scope) { throwAttributeTypeError(state, scope, "TestSerialization", "thirdUnserializableAttribute", "TestNode"); });
     334    auto nativeValue = convert<IDLInterface<TestException>>(state, value, [](JSC::ExecState& state, JSC::ThrowScope& scope) { throwAttributeTypeError(state, scope, "TestSerialization", "thirdUnserializableAttribute", "TestException"); });
    316335    RETURN_IF_EXCEPTION(throwScope, false);
    317336    impl.setThirdUnserializableAttribute(*nativeValue);
     
    354373    RETURN_IF_EXCEPTION(throwScope, false);
    355374    impl.setFifthLongAttribute(WTFMove(nativeValue));
     375    return true;
     376}
     377
     378
     379static inline bool setJSTestSerializationSixthTypedefAttributeFunction(ExecState&, JSTestSerialization&, JSValue, ThrowScope&);
     380
     381bool setJSTestSerializationSixthTypedefAttribute(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
     382{
     383    return BindingCaller<JSTestSerialization>::setAttribute<setJSTestSerializationSixthTypedefAttributeFunction>(state, thisValue, encodedValue, "sixthTypedefAttribute");
     384}
     385
     386static inline bool setJSTestSerializationSixthTypedefAttributeFunction(ExecState& state, JSTestSerialization& thisObject, JSValue value, ThrowScope& throwScope)
     387{
     388    UNUSED_PARAM(state);
     389    UNUSED_PARAM(throwScope);
     390    auto& impl = thisObject.wrapped();
     391    auto nativeValue = convert<IDLDouble>(state, value);
     392    RETURN_IF_EXCEPTION(throwScope, false);
     393    impl.setSixthTypedefAttribute(WTFMove(nativeValue));
    356394    return true;
    357395}
     
    383421    ASSERT(!throwScope.exception());
    384422    result->putDirect(vm, Identifier::fromString(&vm, "fifthLongAttribute"), fifthLongAttributeValue);
     423
     424    auto sixthTypedefAttributeValue = jsTestSerializationSixthTypedefAttributeGetter(*state, *thisObject, throwScope);
     425    ASSERT(!throwScope.exception());
     426    result->putDirect(vm, Identifier::fromString(&vm, "sixthTypedefAttribute"), sixthTypedefAttributeValue);
    385427
    386428    return JSValue::encode(result);
  • trunk/Source/WebCore/bindings/scripts/test/TestSerialization.idl

    r207378 r211409  
    2424 */
    2525
     26typedef double TestTimeStamp;
     27
    2628interface TestSerialization {
    2729    attribute DOMString             firstStringAttribute;
    2830    attribute long                  secondLongAttribute;
    29     attribute TestNode              thirdUnserializableAttribute;
     31    attribute TestException         thirdUnserializableAttribute;
    3032    attribute unrestricted double   fourthUnrestrictedDoubleAttribute;
    3133    attribute long                  fifthLongAttribute;
     34    attribute TestTimeStamp         sixthTypedefAttribute;
    3235
    3336    serializer = { attribute };
  • trunk/Source/WebCore/bindings/scripts/test/TestSerializationInherit.idl

    r211408 r211409  
    11/*
    2  * Copyright (C) 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2424 */
    2525
    26 interface TestSerialization {
    27     attribute DOMString             firstStringAttribute;
    28     attribute long                  secondLongAttribute;
    29     attribute TestNode              thirdUnserializableAttribute;
    30     attribute unrestricted double   fourthUnrestrictedDoubleAttribute;
    31     attribute long                  fifthLongAttribute;
     26interface TestSerializationInherit : TestSerialization {
     27    attribute long                  inheritLongAttribute;
    3228
    33     serializer = { attribute };
     29    serializer = { inherit, attribute };
    3430};
  • trunk/Source/WebCore/bindings/scripts/test/TestSerializationInheritFinal.idl

    r211408 r211409  
    11/*
    2  * Copyright (C) 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2424 */
    2525
    26 interface TestSerialization {
    27     attribute DOMString             firstStringAttribute;
    28     attribute long                  secondLongAttribute;
    29     attribute TestNode              thirdUnserializableAttribute;
    30     attribute unrestricted double   fourthUnrestrictedDoubleAttribute;
    31     attribute long                  fifthLongAttribute;
     26interface TestSerializationInheritFinal : TestSerializationInherit {
     27    attribute long                  finalLongAttributeFoo;
     28    attribute long                  finalLongAttributeBar;
    3229
    33     serializer = { attribute };
     30    serializer = { inherit, finalLongAttributeBar };
    3431};
Note: See TracChangeset for help on using the changeset viewer.