Changeset 207674 in webkit
- Timestamp:
- Oct 21, 2016 9:12:10 AM (8 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r207672 r207674 1 2016-10-21 Chris Dumez <cdumez@apple.com> 2 3 [Web IDL] Support unions in our overload resolution algorithm 4 https://bugs.webkit.org/show_bug.cgi?id=163764 5 6 Reviewed by Darin Adler. 7 8 Support unions in our overload resolution algorithm as per: 9 - https://heycam.github.io/webidl/#es-overloads 10 - https://heycam.github.io/webidl/#dfn-distinguishable 11 12 * bindings/scripts/CodeGeneratorJS.pm: 13 (IsIDLTypeDistinguishableWithUnionForOverloadResolution): 14 (AreTypesDistinguishableForOverloadResolution): 15 (GetOverloadThatMatches): 16 (GenerateOverloadedFunctionOrConstructor): 17 * bindings/scripts/test/JS/JSTestObj.cpp: 18 * bindings/scripts/test/TestObj.idl: 19 1 20 2016-10-21 Chris Dumez <cdumez@apple.com> 2 21 -
trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
r207651 r207674 1946 1946 } 1947 1947 1948 sub IsIDLTypeDistinguishableWithUnionForOverloadResolution 1949 { 1950 my ($idlType, $unionSubtypes) = @_; 1951 1952 assert("First type should not be a union") if $idlType->isUnion; 1953 for my $unionSubType (@$unionSubtypes) { 1954 return 0 unless AreTypesDistinguishableForOverloadResolution($idlType, $unionSubType); 1955 } 1956 return 1; 1957 } 1958 1948 1959 # Determines if two types are distinguishable in the context of overload resolution, 1949 1960 # according to the Web IDL specification: … … 1961 1972 return $codeGenerator->IsFunctionOnlyCallbackInterface($type) || &$isDictionary($type); 1962 1973 }; 1963 1964 # FIXME: Add support for union types. 1965 # idlTypeA and idlTypeB are distinguishable if: 1974 1975 # FIXME: The WebIDL mandates this but this currently does not work because some of our IDL is wrong. 1976 # return 0 if $idlTypeA->isNullable && $idlTypeB->isNullable; 1977 1978 # Union types: idlTypeA and idlTypeB are distinguishable if: 1979 # - Both types are either a union type or nullable union type, and each member type of the one is 1980 # distinguishable with each member type of the other. 1966 1981 # - One type is a union type or nullable union type, the other is neither a union type nor a nullable 1967 1982 # union type, and each member type of the first is distinguishable with the second. 1968 # - Both types are either a union type or nullable union type, and each member type of the one is 1969 # distinguishable with each member type of the other. 1970 1971 # FIXME: The WebIDL mandates this but this currently does not work because some of our IDL is wrong. 1972 # return 0 if $idlTypeA->isNullable && $idlTypeB->isNullable; 1983 if ($idlTypeA->isUnion && $idlTypeB->isUnion) { 1984 for my $unionASubType (@{$idlTypeA->subtypes}) { 1985 return 0 unless IsIDLTypeDistinguishableWithUnionForOverloadResolution($unionASubType, $idlTypeB->subtypes); 1986 } 1987 return 1; 1988 } elsif ($idlTypeA->isUnion) { 1989 return IsIDLTypeDistinguishableWithUnionForOverloadResolution($idlTypeB, $idlTypeA->subtypes); 1990 } elsif ($idlTypeB->isUnion) { 1991 return IsIDLTypeDistinguishableWithUnionForOverloadResolution($idlTypeA, $idlTypeB->subtypes); 1992 } 1973 1993 1974 1994 return 0 if $idlTypeA->name eq $idlTypeB->name; … … 2008 2028 my $idlType = @{@{$tuple}[1]}[$parameterIndex]; 2009 2029 my $optionality = @{@{$tuple}[2]}[$parameterIndex]; 2010 return @{$tuple}[0] if $matches->($idlType, $optionality); 2030 if ($idlType->isUnion) { 2031 for my $idlSubtype (GetFlattenedMemberTypes($idlType)) { 2032 return @{$tuple}[0] if $matches->($idlSubtype, $optionality); 2033 } 2034 } else { 2035 return @{$tuple}[0] if $matches->($idlType, $optionality); 2036 } 2011 2037 } 2012 2038 } … … 2146 2172 my $overload = @{$tuple}[0]; 2147 2173 my $idlType = @{@{$tuple}[1]}[$d]; 2148 my $type = $idlType->name; 2149 if ($codeGenerator->IsWrapperType($type) || $codeGenerator->IsTypedArrayType($type)) { 2150 if ($type eq "DOMWindow") { 2151 AddToImplIncludes("JSDOMWindowShell.h"); 2152 &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isObject() && (asObject(distinguishingArg)->inherits(JSDOMWindowShell::info()) || asObject(distinguishingArg)->inherits(JSDOMWindow::info()))"); 2153 } else { 2154 &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(JS${type}::info())"); 2174 2175 my @idlSubtypes = $idlType->isUnion ? GetFlattenedMemberTypes($idlType) : ( $idlType ); 2176 for my $idlSubtype (@idlSubtypes) { 2177 my $type = $idlSubtype->name; 2178 if ($codeGenerator->IsWrapperType($type) || $codeGenerator->IsTypedArrayType($type)) { 2179 if ($type eq "DOMWindow") { 2180 AddToImplIncludes("JSDOMWindowShell.h"); 2181 &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isObject() && (asObject(distinguishingArg)->inherits(JSDOMWindowShell::info()) || asObject(distinguishingArg)->inherits(JSDOMWindow::info()))"); 2182 } else { 2183 &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(JS${type}::info())"); 2184 } 2155 2185 } 2156 2186 } -
trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp
r207575 r207674 49 49 #include "JSTestCallback.h" 50 50 #include "JSTestCallbackFunction.h" 51 #include "JSTestInterface.h" 51 52 #include "JSTestNode.h" 52 53 #include "JSTestObj.h" … … 957 958 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionOverloadedMethod(JSC::ExecState*); 958 959 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionOverloadedMethodWithOptionalParameter(JSC::ExecState*); 960 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionOverloadedMethodWithDistinguishingUnion(JSC::ExecState*); 961 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionOverloadedMethodWith2DistinguishingUnions(JSC::ExecState*); 962 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionOverloadedMethodWithNonDistinguishingUnion(JSC::ExecState*); 959 963 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjConstructorFunctionClassMethod(JSC::ExecState*); 960 964 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjConstructorFunctionClassMethodWithOptional(JSC::ExecState*); … … 1575 1579 { "overloadedMethod", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionOverloadedMethod), (intptr_t) (0) } }, 1576 1580 { "overloadedMethodWithOptionalParameter", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionOverloadedMethodWithOptionalParameter), (intptr_t) (1) } }, 1581 { "overloadedMethodWithDistinguishingUnion", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionOverloadedMethodWithDistinguishingUnion), (intptr_t) (1) } }, 1582 { "overloadedMethodWith2DistinguishingUnions", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionOverloadedMethodWith2DistinguishingUnions), (intptr_t) (1) } }, 1583 { "overloadedMethodWithNonDistinguishingUnion", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionOverloadedMethodWithNonDistinguishingUnion), (intptr_t) (2) } }, 1577 1584 { "classMethodWithClamp", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionClassMethodWithClamp), (intptr_t) (2) } }, 1578 1585 { "classMethodWithEnforceRange", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionClassMethodWithEnforceRange), (intptr_t) (2) } }, … … 6842 6849 } 6843 6850 6851 static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodWithDistinguishingUnion1Caller(JSC::ExecState*, JSTestObj*, JSC::ThrowScope&); 6852 6853 static inline EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodWithDistinguishingUnion1(ExecState* state) 6854 { 6855 return BindingCaller<JSTestObj>::callOperation<jsTestObjPrototypeFunctionOverloadedMethodWithDistinguishingUnion1Caller>(state, "overloadedMethodWithDistinguishingUnion"); 6856 } 6857 6858 static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodWithDistinguishingUnion1Caller(JSC::ExecState* state, JSTestObj* castedThis, JSC::ThrowScope& throwScope) 6859 { 6860 UNUSED_PARAM(state); 6861 UNUSED_PARAM(throwScope); 6862 auto& impl = castedThis->wrapped(); 6863 if (UNLIKELY(state->argumentCount() < 1)) 6864 return throwVMError(state, throwScope, createNotEnoughArgumentsError(state)); 6865 auto objectOrNode = convert<IDLUnion<IDLInterface<TestObj>, IDLInterface<TestNode>>>(*state, state->uncheckedArgument(0)); 6866 RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); 6867 impl.overloadedMethodWithDistinguishingUnion(WTFMove(objectOrNode)); 6868 return JSValue::encode(jsUndefined()); 6869 } 6870 6871 static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodWithDistinguishingUnion2Caller(JSC::ExecState*, JSTestObj*, JSC::ThrowScope&); 6872 6873 static inline EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodWithDistinguishingUnion2(ExecState* state) 6874 { 6875 return BindingCaller<JSTestObj>::callOperation<jsTestObjPrototypeFunctionOverloadedMethodWithDistinguishingUnion2Caller>(state, "overloadedMethodWithDistinguishingUnion"); 6876 } 6877 6878 static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodWithDistinguishingUnion2Caller(JSC::ExecState* state, JSTestObj* castedThis, JSC::ThrowScope& throwScope) 6879 { 6880 UNUSED_PARAM(state); 6881 UNUSED_PARAM(throwScope); 6882 auto& impl = castedThis->wrapped(); 6883 if (UNLIKELY(state->argumentCount() < 1)) 6884 return throwVMError(state, throwScope, createNotEnoughArgumentsError(state)); 6885 auto value = convert<IDLLong>(*state, state->uncheckedArgument(0), NormalConversion); 6886 RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); 6887 impl.overloadedMethodWithDistinguishingUnion(WTFMove(value)); 6888 return JSValue::encode(jsUndefined()); 6889 } 6890 6891 EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionOverloadedMethodWithDistinguishingUnion(ExecState* state) 6892 { 6893 VM& vm = state->vm(); 6894 auto throwScope = DECLARE_THROW_SCOPE(vm); 6895 UNUSED_PARAM(throwScope); 6896 size_t argsCount = std::min<size_t>(1, state->argumentCount()); 6897 if (argsCount == 1) { 6898 JSValue distinguishingArg = state->uncheckedArgument(0); 6899 if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(JSTestObj::info())) 6900 return jsTestObjPrototypeFunctionOverloadedMethodWithDistinguishingUnion1(state); 6901 if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(JSTestNode::info())) 6902 return jsTestObjPrototypeFunctionOverloadedMethodWithDistinguishingUnion1(state); 6903 if (distinguishingArg.isNumber()) 6904 return jsTestObjPrototypeFunctionOverloadedMethodWithDistinguishingUnion2(state); 6905 return jsTestObjPrototypeFunctionOverloadedMethodWithDistinguishingUnion2(state); 6906 } 6907 return argsCount < 1 ? throwVMError(state, throwScope, createNotEnoughArgumentsError(state)) : throwVMTypeError(state, throwScope); 6908 } 6909 6910 static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodWith2DistinguishingUnions1Caller(JSC::ExecState*, JSTestObj*, JSC::ThrowScope&); 6911 6912 static inline EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodWith2DistinguishingUnions1(ExecState* state) 6913 { 6914 return BindingCaller<JSTestObj>::callOperation<jsTestObjPrototypeFunctionOverloadedMethodWith2DistinguishingUnions1Caller>(state, "overloadedMethodWith2DistinguishingUnions"); 6915 } 6916 6917 static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodWith2DistinguishingUnions1Caller(JSC::ExecState* state, JSTestObj* castedThis, JSC::ThrowScope& throwScope) 6918 { 6919 UNUSED_PARAM(state); 6920 UNUSED_PARAM(throwScope); 6921 auto& impl = castedThis->wrapped(); 6922 if (UNLIKELY(state->argumentCount() < 1)) 6923 return throwVMError(state, throwScope, createNotEnoughArgumentsError(state)); 6924 auto objectOrNode = convert<IDLUnion<IDLInterface<TestObj>, IDLInterface<TestNode>>>(*state, state->uncheckedArgument(0)); 6925 RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); 6926 impl.overloadedMethodWith2DistinguishingUnions(WTFMove(objectOrNode)); 6927 return JSValue::encode(jsUndefined()); 6928 } 6929 6930 static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodWith2DistinguishingUnions2Caller(JSC::ExecState*, JSTestObj*, JSC::ThrowScope&); 6931 6932 static inline EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodWith2DistinguishingUnions2(ExecState* state) 6933 { 6934 return BindingCaller<JSTestObj>::callOperation<jsTestObjPrototypeFunctionOverloadedMethodWith2DistinguishingUnions2Caller>(state, "overloadedMethodWith2DistinguishingUnions"); 6935 } 6936 6937 static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodWith2DistinguishingUnions2Caller(JSC::ExecState* state, JSTestObj* castedThis, JSC::ThrowScope& throwScope) 6938 { 6939 UNUSED_PARAM(state); 6940 UNUSED_PARAM(throwScope); 6941 auto& impl = castedThis->wrapped(); 6942 if (UNLIKELY(state->argumentCount() < 1)) 6943 return throwVMError(state, throwScope, createNotEnoughArgumentsError(state)); 6944 auto value = convert<IDLUnion<IDLInterface<TestInterface>, IDLDOMString, IDLLong>>(*state, state->uncheckedArgument(0)); 6945 RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); 6946 impl.overloadedMethodWith2DistinguishingUnions(WTFMove(value)); 6947 return JSValue::encode(jsUndefined()); 6948 } 6949 6950 EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionOverloadedMethodWith2DistinguishingUnions(ExecState* state) 6951 { 6952 VM& vm = state->vm(); 6953 auto throwScope = DECLARE_THROW_SCOPE(vm); 6954 UNUSED_PARAM(throwScope); 6955 size_t argsCount = std::min<size_t>(1, state->argumentCount()); 6956 if (argsCount == 1) { 6957 JSValue distinguishingArg = state->uncheckedArgument(0); 6958 if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(JSTestObj::info())) 6959 return jsTestObjPrototypeFunctionOverloadedMethodWith2DistinguishingUnions1(state); 6960 if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(JSTestNode::info())) 6961 return jsTestObjPrototypeFunctionOverloadedMethodWith2DistinguishingUnions1(state); 6962 if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(JSTestInterface::info())) 6963 return jsTestObjPrototypeFunctionOverloadedMethodWith2DistinguishingUnions2(state); 6964 if (distinguishingArg.isNumber()) 6965 return jsTestObjPrototypeFunctionOverloadedMethodWith2DistinguishingUnions2(state); 6966 return jsTestObjPrototypeFunctionOverloadedMethodWith2DistinguishingUnions2(state); 6967 } 6968 return argsCount < 1 ? throwVMError(state, throwScope, createNotEnoughArgumentsError(state)) : throwVMTypeError(state, throwScope); 6969 } 6970 6971 static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodWithNonDistinguishingUnion1Caller(JSC::ExecState*, JSTestObj*, JSC::ThrowScope&); 6972 6973 static inline EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodWithNonDistinguishingUnion1(ExecState* state) 6974 { 6975 return BindingCaller<JSTestObj>::callOperation<jsTestObjPrototypeFunctionOverloadedMethodWithNonDistinguishingUnion1Caller>(state, "overloadedMethodWithNonDistinguishingUnion"); 6976 } 6977 6978 static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodWithNonDistinguishingUnion1Caller(JSC::ExecState* state, JSTestObj* castedThis, JSC::ThrowScope& throwScope) 6979 { 6980 UNUSED_PARAM(state); 6981 UNUSED_PARAM(throwScope); 6982 auto& impl = castedThis->wrapped(); 6983 if (UNLIKELY(state->argumentCount() < 2)) 6984 return throwVMError(state, throwScope, createNotEnoughArgumentsError(state)); 6985 auto objectOrNode = convert<IDLUnion<IDLInterface<TestObj>, IDLInterface<TestNode>>>(*state, state->uncheckedArgument(0)); 6986 RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); 6987 auto object = JSTestObj::toWrapped(state->uncheckedArgument(1)); 6988 if (UNLIKELY(!object)) 6989 return throwArgumentTypeError(*state, throwScope, 1, "object", "TestObject", "overloadedMethodWithNonDistinguishingUnion", "TestObj"); 6990 impl.overloadedMethodWithNonDistinguishingUnion(WTFMove(objectOrNode), *object); 6991 return JSValue::encode(jsUndefined()); 6992 } 6993 6994 static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodWithNonDistinguishingUnion2Caller(JSC::ExecState*, JSTestObj*, JSC::ThrowScope&); 6995 6996 static inline EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodWithNonDistinguishingUnion2(ExecState* state) 6997 { 6998 return BindingCaller<JSTestObj>::callOperation<jsTestObjPrototypeFunctionOverloadedMethodWithNonDistinguishingUnion2Caller>(state, "overloadedMethodWithNonDistinguishingUnion"); 6999 } 7000 7001 static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodWithNonDistinguishingUnion2Caller(JSC::ExecState* state, JSTestObj* castedThis, JSC::ThrowScope& throwScope) 7002 { 7003 UNUSED_PARAM(state); 7004 UNUSED_PARAM(throwScope); 7005 auto& impl = castedThis->wrapped(); 7006 if (UNLIKELY(state->argumentCount() < 2)) 7007 return throwVMError(state, throwScope, createNotEnoughArgumentsError(state)); 7008 auto objectOrNode = convert<IDLUnion<IDLInterface<TestObj>, IDLInterface<TestNode>>>(*state, state->uncheckedArgument(0)); 7009 RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); 7010 auto node = JSTestNode::toWrapped(state->uncheckedArgument(1)); 7011 if (UNLIKELY(!node)) 7012 return throwArgumentTypeError(*state, throwScope, 1, "node", "TestObject", "overloadedMethodWithNonDistinguishingUnion", "TestNode"); 7013 impl.overloadedMethodWithNonDistinguishingUnion(WTFMove(objectOrNode), *node); 7014 return JSValue::encode(jsUndefined()); 7015 } 7016 7017 EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionOverloadedMethodWithNonDistinguishingUnion(ExecState* state) 7018 { 7019 VM& vm = state->vm(); 7020 auto throwScope = DECLARE_THROW_SCOPE(vm); 7021 UNUSED_PARAM(throwScope); 7022 size_t argsCount = std::min<size_t>(2, state->argumentCount()); 7023 if (argsCount == 2) { 7024 JSValue distinguishingArg = state->uncheckedArgument(1); 7025 if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(JSTestObj::info())) 7026 return jsTestObjPrototypeFunctionOverloadedMethodWithNonDistinguishingUnion1(state); 7027 if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(JSTestNode::info())) 7028 return jsTestObjPrototypeFunctionOverloadedMethodWithNonDistinguishingUnion2(state); 7029 } 7030 return argsCount < 2 ? throwVMError(state, throwScope, createNotEnoughArgumentsError(state)) : throwVMTypeError(state, throwScope); 7031 } 7032 6844 7033 EncodedJSValue JSC_HOST_CALL jsTestObjConstructorFunctionClassMethod(ExecState* state) 6845 7034 { -
trunk/Source/WebCore/bindings/scripts/test/TestObj.idl
r207462 r207674 299 299 void overloadedMethodWithOptionalParameter(DOMString strArg, optional TestObj? objArg = null); 300 300 void overloadedMethodWithOptionalParameter(TestObj? objArg, optional long longArg); 301 302 void overloadedMethodWithDistinguishingUnion((TestObj or TestNode) objectOrNode); 303 void overloadedMethodWithDistinguishingUnion(long value); 304 305 void overloadedMethodWith2DistinguishingUnions((TestObj or TestNode) objectOrNode); 306 void overloadedMethodWith2DistinguishingUnions((TestInterface or DOMString or long) value); 307 308 void overloadedMethodWithNonDistinguishingUnion((TestObj or TestNode) objectOrNode, TestObj object); 309 void overloadedMethodWithNonDistinguishingUnion((TestObj or TestNode) objectOrNode, TestNode node); 301 310 #endif 302 311
Note: See TracChangeset
for help on using the changeset viewer.