Changeset 207705 in webkit


Ignore:
Timestamp:
Oct 21, 2016 10:27:25 PM (8 years ago)
Author:
Chris Dumez
Message:

[Web ID] Overload resolution is wrong if one of the types is a nullable union
https://bugs.webkit.org/show_bug.cgi?id=163816

Reviewed by Alex Christensen.

Overload resolution was wrong if one of the types was a nullable union. This
is because we never considered the union type itself, only its subtypes.
Therefore, we checked if any of the union's subtypes were nullable but we
failed to check if the union itself was nullable.

See:

No new tests, extended bindings tests.

  • bindings/scripts/CodeGeneratorJS.pm:

(GetOverloadThatMatchesIgnoringUnionSubtypes):
(GenerateOverloadedFunctionOrConstructor):

  • bindings/scripts/test/JS/JSTestObj.cpp:

(WebCore::jsTestObjPrototypeFunctionOverloadWithNullableUnion1):
(WebCore::jsTestObjPrototypeFunctionOverloadWithNullableUnion1Caller):
(WebCore::jsTestObjPrototypeFunctionOverloadWithNullableUnion2):
(WebCore::jsTestObjPrototypeFunctionOverloadWithNullableUnion2Caller):
(WebCore::jsTestObjPrototypeFunctionOverloadWithNullableUnion):
(WebCore::jsTestObjPrototypeFunctionOverloadWithOptionalUnion1):
(WebCore::jsTestObjPrototypeFunctionOverloadWithOptionalUnion1Caller):
(WebCore::jsTestObjPrototypeFunctionOverloadWithOptionalUnion2):
(WebCore::jsTestObjPrototypeFunctionOverloadWithOptionalUnion2Caller):
(WebCore::jsTestObjPrototypeFunctionOverloadWithOptionalUnion):

  • bindings/scripts/test/TestObj.idl:
Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r207704 r207705  
     12016-10-21  Chris Dumez  <cdumez@apple.com>
     2
     3        [Web ID] Overload resolution is wrong if one of the types is a nullable union
     4        https://bugs.webkit.org/show_bug.cgi?id=163816
     5
     6        Reviewed by Alex Christensen.
     7
     8        Overload resolution was wrong if one of the types was a nullable union. This
     9        is because we never considered the union type itself, only its subtypes.
     10        Therefore, we checked if any of the union's subtypes were nullable but we
     11        failed to check if the union itself was nullable.
     12
     13        See:
     14        - https://heycam.github.io/webidl/#es-overloads (Step 11.3.)
     15
     16        No new tests, extended bindings tests.
     17
     18        * bindings/scripts/CodeGeneratorJS.pm:
     19        (GetOverloadThatMatchesIgnoringUnionSubtypes):
     20        (GenerateOverloadedFunctionOrConstructor):
     21        * bindings/scripts/test/JS/JSTestObj.cpp:
     22        (WebCore::jsTestObjPrototypeFunctionOverloadWithNullableUnion1):
     23        (WebCore::jsTestObjPrototypeFunctionOverloadWithNullableUnion1Caller):
     24        (WebCore::jsTestObjPrototypeFunctionOverloadWithNullableUnion2):
     25        (WebCore::jsTestObjPrototypeFunctionOverloadWithNullableUnion2Caller):
     26        (WebCore::jsTestObjPrototypeFunctionOverloadWithNullableUnion):
     27        (WebCore::jsTestObjPrototypeFunctionOverloadWithOptionalUnion1):
     28        (WebCore::jsTestObjPrototypeFunctionOverloadWithOptionalUnion1Caller):
     29        (WebCore::jsTestObjPrototypeFunctionOverloadWithOptionalUnion2):
     30        (WebCore::jsTestObjPrototypeFunctionOverloadWithOptionalUnion2Caller):
     31        (WebCore::jsTestObjPrototypeFunctionOverloadWithOptionalUnion):
     32        * bindings/scripts/test/TestObj.idl:
     33
    1342016-10-21  Eric Carlson  <eric.carlson@apple.com>
    235
  • trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm

    r207674 r207705  
    20382038}
    20392039
     2040sub GetOverloadThatMatchesIgnoringUnionSubtypes
     2041{
     2042    my ($S, $parameterIndex, $matches) = @_;
     2043
     2044    for my $tuple (@{$S}) {
     2045        my $idlType = @{@{$tuple}[1]}[$parameterIndex];
     2046        my $optionality = @{@{$tuple}[2]}[$parameterIndex];
     2047        return @{$tuple}[0] if $matches->($idlType, $optionality);
     2048    }
     2049}
     2050
    20402051sub getConditionalForFunctionConsideringOverloads
    20412052{
     
    20872098        return $idlType->name eq "Dictionary" || $codeGenerator->IsDictionaryType($idlType->name);
    20882099    };
    2089     my $isNullableOrDictionaryParameter = sub {
     2100    my $isNullableOrDictionaryParameterOrUnionContainingOne = sub {
    20902101        my ($idlType, $optionality) = @_;
    2091         return $idlType->isNullable || &$isDictionaryParameter($idlType, $optionality);
     2102        return 1 if $idlType->isNullable;
     2103        if ($idlType->isUnion) {
     2104            for my $idlSubtype (GetFlattenedMemberTypes($idlType)) {
     2105                return 1 if $idlType->isNullable || &$isDictionaryParameter($idlSubtype, $optionality);
     2106            }
     2107            return 0;
     2108        } else {
     2109            return &$isDictionaryParameter($idlType, $optionality);
     2110        }
    20922111    };
    20932112    my $isRegExpOrObjectParameter = sub {
     
    21632182            push(@implContent, "        JSValue distinguishingArg = state->uncheckedArgument($d);\n");
    21642183
    2165             my $overload = GetOverloadThatMatches($S, $d, \&$isOptionalParameter);
     2184            my $overload = GetOverloadThatMatchesIgnoringUnionSubtypes($S, $d, \&$isOptionalParameter);
    21662185            &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isUndefined()");
    21672186
    2168             $overload = GetOverloadThatMatches($S, $d, \&$isNullableOrDictionaryParameter);
     2187            $overload = GetOverloadThatMatchesIgnoringUnionSubtypes($S, $d, \&$isNullableOrDictionaryParameterOrUnionContainingOne);
    21692188            &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isUndefinedOrNull()");
    21702189
  • trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp

    r207674 r207705  
    961961JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionOverloadedMethodWith2DistinguishingUnions(JSC::ExecState*);
    962962JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionOverloadedMethodWithNonDistinguishingUnion(JSC::ExecState*);
     963JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionOverloadWithNullableUnion(JSC::ExecState*);
     964JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionOverloadWithOptionalUnion(JSC::ExecState*);
    963965JSC::EncodedJSValue JSC_HOST_CALL jsTestObjConstructorFunctionClassMethod(JSC::ExecState*);
    964966JSC::EncodedJSValue JSC_HOST_CALL jsTestObjConstructorFunctionClassMethodWithOptional(JSC::ExecState*);
     
    15821584    { "overloadedMethodWith2DistinguishingUnions", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionOverloadedMethodWith2DistinguishingUnions), (intptr_t) (1) } },
    15831585    { "overloadedMethodWithNonDistinguishingUnion", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionOverloadedMethodWithNonDistinguishingUnion), (intptr_t) (2) } },
     1586    { "overloadWithNullableUnion", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionOverloadWithNullableUnion), (intptr_t) (1) } },
     1587    { "overloadWithOptionalUnion", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionOverloadWithOptionalUnion), (intptr_t) (0) } },
    15841588    { "classMethodWithClamp", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionClassMethodWithClamp), (intptr_t) (2) } },
    15851589    { "classMethodWithEnforceRange", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionClassMethodWithEnforceRange), (intptr_t) (2) } },
     
    70317035}
    70327036
     7037static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadWithNullableUnion1Caller(JSC::ExecState*, JSTestObj*, JSC::ThrowScope&);
     7038
     7039static inline EncodedJSValue jsTestObjPrototypeFunctionOverloadWithNullableUnion1(ExecState* state)
     7040{
     7041    return BindingCaller<JSTestObj>::callOperation<jsTestObjPrototypeFunctionOverloadWithNullableUnion1Caller>(state, "overloadWithNullableUnion");
     7042}
     7043
     7044static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadWithNullableUnion1Caller(JSC::ExecState* state, JSTestObj* castedThis, JSC::ThrowScope& throwScope)
     7045{
     7046    UNUSED_PARAM(state);
     7047    UNUSED_PARAM(throwScope);
     7048    auto& impl = castedThis->wrapped();
     7049    if (UNLIKELY(state->argumentCount() < 1))
     7050        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
     7051    auto objectOrNode = convert<IDLNullable<IDLUnion<IDLInterface<TestObj>, IDLInterface<TestNode>>>>(*state, state->uncheckedArgument(0));
     7052    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
     7053    impl.overloadWithNullableUnion(WTFMove(objectOrNode));
     7054    return JSValue::encode(jsUndefined());
     7055}
     7056
     7057static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadWithNullableUnion2Caller(JSC::ExecState*, JSTestObj*, JSC::ThrowScope&);
     7058
     7059static inline EncodedJSValue jsTestObjPrototypeFunctionOverloadWithNullableUnion2(ExecState* state)
     7060{
     7061    return BindingCaller<JSTestObj>::callOperation<jsTestObjPrototypeFunctionOverloadWithNullableUnion2Caller>(state, "overloadWithNullableUnion");
     7062}
     7063
     7064static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadWithNullableUnion2Caller(JSC::ExecState* state, JSTestObj* castedThis, JSC::ThrowScope& throwScope)
     7065{
     7066    UNUSED_PARAM(state);
     7067    UNUSED_PARAM(throwScope);
     7068    auto& impl = castedThis->wrapped();
     7069    if (UNLIKELY(state->argumentCount() < 1))
     7070        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
     7071    auto index = convert<IDLLong>(*state, state->uncheckedArgument(0), NormalConversion);
     7072    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
     7073    impl.overloadWithNullableUnion(WTFMove(index));
     7074    return JSValue::encode(jsUndefined());
     7075}
     7076
     7077EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionOverloadWithNullableUnion(ExecState* state)
     7078{
     7079    VM& vm = state->vm();
     7080    auto throwScope = DECLARE_THROW_SCOPE(vm);
     7081    UNUSED_PARAM(throwScope);
     7082    size_t argsCount = std::min<size_t>(1, state->argumentCount());
     7083    if (argsCount == 1) {
     7084        JSValue distinguishingArg = state->uncheckedArgument(0);
     7085        if (distinguishingArg.isUndefinedOrNull())
     7086            return jsTestObjPrototypeFunctionOverloadWithNullableUnion1(state);
     7087        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(JSTestObj::info()))
     7088            return jsTestObjPrototypeFunctionOverloadWithNullableUnion1(state);
     7089        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(JSTestNode::info()))
     7090            return jsTestObjPrototypeFunctionOverloadWithNullableUnion1(state);
     7091        if (distinguishingArg.isNumber())
     7092            return jsTestObjPrototypeFunctionOverloadWithNullableUnion2(state);
     7093        return jsTestObjPrototypeFunctionOverloadWithNullableUnion2(state);
     7094    }
     7095    return argsCount < 1 ? throwVMError(state, throwScope, createNotEnoughArgumentsError(state)) : throwVMTypeError(state, throwScope);
     7096}
     7097
     7098static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadWithOptionalUnion1Caller(JSC::ExecState*, JSTestObj*, JSC::ThrowScope&);
     7099
     7100static inline EncodedJSValue jsTestObjPrototypeFunctionOverloadWithOptionalUnion1(ExecState* state)
     7101{
     7102    return BindingCaller<JSTestObj>::callOperation<jsTestObjPrototypeFunctionOverloadWithOptionalUnion1Caller>(state, "overloadWithOptionalUnion");
     7103}
     7104
     7105static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadWithOptionalUnion1Caller(JSC::ExecState* state, JSTestObj* castedThis, JSC::ThrowScope& throwScope)
     7106{
     7107    UNUSED_PARAM(state);
     7108    UNUSED_PARAM(throwScope);
     7109    auto& impl = castedThis->wrapped();
     7110    auto objectOrNode = state->argument(0).isUndefined() ? true : convert<IDLUnion<IDLDOMString, IDLBoolean>>(*state, state->uncheckedArgument(0));
     7111    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
     7112    impl.overloadWithOptionalUnion(WTFMove(objectOrNode));
     7113    return JSValue::encode(jsUndefined());
     7114}
     7115
     7116static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadWithOptionalUnion2Caller(JSC::ExecState*, JSTestObj*, JSC::ThrowScope&);
     7117
     7118static inline EncodedJSValue jsTestObjPrototypeFunctionOverloadWithOptionalUnion2(ExecState* state)
     7119{
     7120    return BindingCaller<JSTestObj>::callOperation<jsTestObjPrototypeFunctionOverloadWithOptionalUnion2Caller>(state, "overloadWithOptionalUnion");
     7121}
     7122
     7123static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadWithOptionalUnion2Caller(JSC::ExecState* state, JSTestObj* castedThis, JSC::ThrowScope& throwScope)
     7124{
     7125    UNUSED_PARAM(state);
     7126    UNUSED_PARAM(throwScope);
     7127    auto& impl = castedThis->wrapped();
     7128    if (UNLIKELY(state->argumentCount() < 1))
     7129        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
     7130    auto index = convert<IDLLong>(*state, state->uncheckedArgument(0), NormalConversion);
     7131    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
     7132    impl.overloadWithOptionalUnion(WTFMove(index));
     7133    return JSValue::encode(jsUndefined());
     7134}
     7135
     7136EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionOverloadWithOptionalUnion(ExecState* state)
     7137{
     7138    VM& vm = state->vm();
     7139    auto throwScope = DECLARE_THROW_SCOPE(vm);
     7140    UNUSED_PARAM(throwScope);
     7141    size_t argsCount = std::min<size_t>(1, state->argumentCount());
     7142    if (argsCount == 0) {
     7143        return jsTestObjPrototypeFunctionOverloadWithOptionalUnion1(state);
     7144    }
     7145    if (argsCount == 1) {
     7146        JSValue distinguishingArg = state->uncheckedArgument(0);
     7147        if (distinguishingArg.isUndefined())
     7148            return jsTestObjPrototypeFunctionOverloadWithOptionalUnion1(state);
     7149        if (distinguishingArg.isBoolean())
     7150            return jsTestObjPrototypeFunctionOverloadWithOptionalUnion1(state);
     7151        if (distinguishingArg.isNumber())
     7152            return jsTestObjPrototypeFunctionOverloadWithOptionalUnion2(state);
     7153        return jsTestObjPrototypeFunctionOverloadWithOptionalUnion1(state);
     7154    }
     7155    return throwVMTypeError(state, throwScope);
     7156}
     7157
    70337158EncodedJSValue JSC_HOST_CALL jsTestObjConstructorFunctionClassMethod(ExecState* state)
    70347159{
  • trunk/Source/WebCore/bindings/scripts/test/TestObj.idl

    r207674 r207705  
    308308    void overloadedMethodWithNonDistinguishingUnion((TestObj or TestNode) objectOrNode, TestObj object);
    309309    void overloadedMethodWithNonDistinguishingUnion((TestObj or TestNode) objectOrNode, TestNode node);
     310
     311    void overloadWithNullableUnion((TestObj or TestNode)? objectOrNode);
     312    void overloadWithNullableUnion(long index);
     313
     314    void overloadWithOptionalUnion(optional (DOMString or boolean) objectOrNode = true);
     315    void overloadWithOptionalUnion(long index);
    310316#endif
    311317
Note: See TracChangeset for help on using the changeset viewer.