[WebIDL] Remove some unnecessary specialization for enum types
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 23 May 2017 16:30:37 +0000 (16:30 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 23 May 2017 16:30:37 +0000 (16:30 +0000)
https://bugs.webkit.org/show_bug.cgi?id=172482

Patch by Sam Weinig <sam@webkit.org> on 2017-05-23
Reviewed by Chris Dumez.

Source/WebCore:

- Removes convertEnumeration template function and generated specialization.
  convert<IDLEnumeration<T>> now does the entire check, and can have specialized
  exceptions.
- Treats enums more like all other types, removing enum specific code in the
  generator.

Also fixes some order of exception bugs as the convertEnumeration<T> implementations
were not correctly catching exceptions thrown in parseEnumeration<T>.

* bindings/js/JSDOMConvertEnumeration.h:
(WebCore::Converter<IDLEnumeration<T>>::convert):
Remove convertEnumeration and move implementation to convert. Add ExceptionThrower
parameter to retain argument conversion exception specialization and allow future
specialization for other contexts.

* bindings/js/JSSubtleCryptoCustom.cpp:
(WebCore::jsSubtleCryptoFunctionImportKeyPromise):
(WebCore::jsSubtleCryptoFunctionExportKeyPromise):
(WebCore::jsSubtleCryptoFunctionWrapKeyPromise):
(WebCore::jsSubtleCryptoFunctionUnwrapKeyPromise):
Switch from convertEnumeration<T> to convert<IDLEnumeration<T>>.

* bindings/scripts/CodeGeneratorJS.pm:
(GetArgumentExceptionFunction):
Add (really move from GenerateParametersCheck) enum specific argument conversion exception.

(PassArgumentExpression):
Allow the enum specific code for attributes to remain by explicitly checking the context.
Attribute setters use parseEnumeration<T> explicitly, as WebIDL mandates slightly different
behavior, specially that they don't throw.

(GenerateEnumerationImplementationContent):
(GenerateEnumerationHeaderContent):
Remove convertEnumeration<T>.

(GenerateParametersCheck):
Remove entire branch devoted to enums. The main parameter check is now mature enough
to handle them.

(JSValueToNative):
Like in PassArgumentExpression, we need to retain the specialize behavior for attributes.
Before, JSValueToNative was only called for enums with a context of IDLAttribute or IDLDictionaryMember,
but now that we use if IDLArguments as well, it makes more sense to make this check in terms
of the odd man out, IDLAttribute.

* bindings/scripts/test/JS/JSTestCallbackInterface.cpp:
* bindings/scripts/test/JS/JSTestCallbackInterface.h:
* bindings/scripts/test/JS/JSTestObj.cpp:
* bindings/scripts/test/JS/JSTestObj.h:
* bindings/scripts/test/JS/JSTestStandaloneDictionary.cpp:
* bindings/scripts/test/JS/JSTestStandaloneDictionary.h:
* bindings/scripts/test/JS/JSTestStandaloneEnumeration.cpp:
* bindings/scripts/test/JS/JSTestStandaloneEnumeration.h:
Update test results.

LayoutTests:

* crypto/subtle/import-key-malformed-parameters-expected.txt:
* fast/files/blob-constructor-expected.txt:
* fast/files/script-tests/blob-constructor.js:
Update test and results for improved order of exceptions. In this case, the conversion
to String throws before the failure to parse the enumeration (which is what the
plain TypeError was).

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@217281 268f45cc-cd09-0410-ab3c-d52691b4dbfc

16 files changed:
LayoutTests/ChangeLog
LayoutTests/crypto/subtle/import-key-malformed-parameters-expected.txt
LayoutTests/fast/files/blob-constructor-expected.txt
LayoutTests/fast/files/script-tests/blob-constructor.js
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/JSDOMConvertEnumeration.h
Source/WebCore/bindings/js/JSSubtleCryptoCustom.cpp
Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
Source/WebCore/bindings/scripts/test/JS/JSTestCallbackInterface.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestCallbackInterface.h
Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestObj.h
Source/WebCore/bindings/scripts/test/JS/JSTestStandaloneDictionary.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestStandaloneDictionary.h
Source/WebCore/bindings/scripts/test/JS/JSTestStandaloneEnumeration.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestStandaloneEnumeration.h

index e4c075d..a14deca 100644 (file)
@@ -1,3 +1,17 @@
+2017-05-23  Sam Weinig  <sam@webkit.org>
+
+        [WebIDL] Remove some unnecessary specialization for enum types
+        https://bugs.webkit.org/show_bug.cgi?id=172482
+
+        Reviewed by Chris Dumez.
+
+        * crypto/subtle/import-key-malformed-parameters-expected.txt:
+        * fast/files/blob-constructor-expected.txt:
+        * fast/files/script-tests/blob-constructor.js:
+        Update test and results for improved order of exceptions. In this case, the conversion
+        to String throws before the failure to parse the enumeration (which is what the
+        plain TypeError was).
+
 2017-05-23  Emilio Cobos Ãlvarez  <ecobos@igalia.com>
 
         Import the css-display-3 css tests.
index 0ba56e6..37ebd28 100644 (file)
@@ -12,7 +12,7 @@ PASS crypto.subtle.importKey(1, rawKey, "aes-cbc", extractable, ["encrypt", "dec
 PASS crypto.subtle.importKey(true, rawKey, "aes-cbc", extractable, ["encrypt", "decrypt", "wrapKey", "unwrapKey"]) rejected promise  with TypeError: Type error.
 PASS crypto.subtle.importKey(null, rawKey, "aes-cbc", extractable, ["encrypt", "decrypt", "wrapKey", "unwrapKey"]) rejected promise  with TypeError: Type error.
 PASS crypto.subtle.importKey(undefined, rawKey, "aes-cbc", extractable, ["encrypt", "decrypt", "wrapKey", "unwrapKey"]) rejected promise  with TypeError: Type error.
-PASS crypto.subtle.importKey(Symbol(), rawKey, "aes-cbc", extractable, ["encrypt", "decrypt", "wrapKey", "unwrapKey"]) rejected promise  with TypeError: Type error.
+PASS crypto.subtle.importKey(Symbol(), rawKey, "aes-cbc", extractable, ["encrypt", "decrypt", "wrapKey", "unwrapKey"]) rejected promise  with TypeError: Cannot convert a symbol to a string.
 PASS crypto.subtle.importKey({ }, rawKey, "aes-cbc", extractable, ["encrypt", "decrypt", "wrapKey", "unwrapKey"]) rejected promise  with TypeError: Type error.
 PASS crypto.subtle.importKey("foo", rawKey, "aes-cbc", extractable, ["encrypt", "decrypt", "wrapKey", "unwrapKey"]) rejected promise  with TypeError: Type error.
 PASS crypto.subtle.importKey("raw", jwkKey, "aes-cbc", extractable, ["encrypt", "decrypt", "wrapKey", "unwrapKey"]) rejected promise  with TypeError: Type error.
index 6f5bdd1..7b97f0a 100644 (file)
@@ -25,10 +25,10 @@ PASS (new Blob([toStringingObj])).size is 8
 PASS new Blob([throwingObj]) threw exception Error.
 PASS (new Blob([], {unknownKey:'value'})) instanceof window.Blob is true
 PASS new Blob([], {endings:'illegalValue'}) threw exception TypeError: Type error.
-PASS new Blob([], {endings:throwingObj}) threw exception TypeError: Type error.
+PASS new Blob([], {endings:throwingObj}) threw exception Error.
 PASS new Blob([], {type:throwingObj}) threw exception Error.
-PASS new Blob([], {endings:throwingObj1, type:throwingObj2}) threw exception TypeError: Type error.
-PASS new Blob([], {type:throwingObj2, endings:throwingObj1}) threw exception TypeError: Type error.
+PASS new Blob([], {endings:throwingObj1, type:throwingObj2}) threw exception Error 1.
+PASS new Blob([], {type:throwingObj2, endings:throwingObj1}) threw exception Error 1.
 PASS new Blob([], {type:throwingObj2, endings:'illegal'}) threw exception TypeError: Type error.
 PASS (new Blob([], null)) instanceof window.Blob is true
 PASS (new Blob([], undefined)) instanceof window.Blob is true
index 563c2d3..1b3b235 100644 (file)
@@ -35,14 +35,14 @@ shouldThrow("new Blob([throwingObj])", "'Error'");
 // Test some invalid property bags
 shouldBeTrue("(new Blob([], {unknownKey:'value'})) instanceof window.Blob");    // Ignore invalid keys
 shouldThrow("new Blob([], {endings:'illegalValue'})", "'TypeError: Type error'");
-shouldThrow("new Blob([], {endings:throwingObj})", "'TypeError: Type error'");
+shouldThrow("new Blob([], {endings:throwingObj})", "'Error'");
 shouldThrow("new Blob([], {type:throwingObj})", "'Error'");
 
 // Test that order of property bag evaluation is lexigraphical
 var throwingObj1 = { toString: function() { throw "Error 1"; } };
 var throwingObj2 = { toString: function() { throw "Error 2"; } };
-shouldThrow("new Blob([], {endings:throwingObj1, type:throwingObj2})", "'TypeError: Type error'");
-shouldThrow("new Blob([], {type:throwingObj2, endings:throwingObj1})", "'TypeError: Type error'");
+shouldThrow("new Blob([], {endings:throwingObj1, type:throwingObj2})", "'Error 1'");
+shouldThrow("new Blob([], {type:throwingObj2, endings:throwingObj1})", "'Error 1'");
 shouldThrow("new Blob([], {type:throwingObj2, endings:'illegal'})", "'TypeError: Type error'");
 
 // Test various non-object literals being used as property bags
index 1357d4a..9a736b6 100644 (file)
@@ -1,3 +1,65 @@
+2017-05-23  Sam Weinig  <sam@webkit.org>
+
+        [WebIDL] Remove some unnecessary specialization for enum types
+        https://bugs.webkit.org/show_bug.cgi?id=172482
+
+        Reviewed by Chris Dumez.
+
+        - Removes convertEnumeration template function and generated specialization.
+          convert<IDLEnumeration<T>> now does the entire check, and can have specialized
+          exceptions.
+        - Treats enums more like all other types, removing enum specific code in the
+          generator.
+
+        Also fixes some order of exception bugs as the convertEnumeration<T> implementations
+        were not correctly catching exceptions thrown in parseEnumeration<T>.
+
+        * bindings/js/JSDOMConvertEnumeration.h:
+        (WebCore::Converter<IDLEnumeration<T>>::convert):
+        Remove convertEnumeration and move implementation to convert. Add ExceptionThrower
+        parameter to retain argument conversion exception specialization and allow future
+        specialization for other contexts.
+
+        * bindings/js/JSSubtleCryptoCustom.cpp:
+        (WebCore::jsSubtleCryptoFunctionImportKeyPromise):
+        (WebCore::jsSubtleCryptoFunctionExportKeyPromise):
+        (WebCore::jsSubtleCryptoFunctionWrapKeyPromise):
+        (WebCore::jsSubtleCryptoFunctionUnwrapKeyPromise):
+        Switch from convertEnumeration<T> to convert<IDLEnumeration<T>>.
+
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GetArgumentExceptionFunction):
+        Add (really move from GenerateParametersCheck) enum specific argument conversion exception.
+
+        (PassArgumentExpression):
+        Allow the enum specific code for attributes to remain by explicitly checking the context.
+        Attribute setters use parseEnumeration<T> explicitly, as WebIDL mandates slightly different
+        behavior, specially that they don't throw.
+
+        (GenerateEnumerationImplementationContent):
+        (GenerateEnumerationHeaderContent):
+        Remove convertEnumeration<T>.
+
+        (GenerateParametersCheck):
+        Remove entire branch devoted to enums. The main parameter check is now mature enough
+        to handle them.
+
+        (JSValueToNative):
+        Like in PassArgumentExpression, we need to retain the specialize behavior for attributes.
+        Before, JSValueToNative was only called for enums with a context of IDLAttribute or IDLDictionaryMember,
+        but now that we use if IDLArguments as well, it makes more sense to make this check in terms
+        of the odd man out, IDLAttribute.
+
+        * bindings/scripts/test/JS/JSTestCallbackInterface.cpp:
+        * bindings/scripts/test/JS/JSTestCallbackInterface.h:
+        * bindings/scripts/test/JS/JSTestObj.cpp:
+        * bindings/scripts/test/JS/JSTestObj.h:
+        * bindings/scripts/test/JS/JSTestStandaloneDictionary.cpp:
+        * bindings/scripts/test/JS/JSTestStandaloneDictionary.h:
+        * bindings/scripts/test/JS/JSTestStandaloneEnumeration.cpp:
+        * bindings/scripts/test/JS/JSTestStandaloneEnumeration.h:
+        Update test results.
+
 2017-05-23  Romain Bellessort  <romain.bellessort@crf.canon.fr>
 
         [Readable Streams API] Align respondInClosedState with spec
index ec43133..4316aa0 100644 (file)
@@ -32,7 +32,6 @@ namespace WebCore {
 
 // Specialized by generated code for IDL enumeration conversion.
 template<typename T> std::optional<T> parseEnumeration(JSC::ExecState&, JSC::JSValue);
-template<typename T> T convertEnumeration(JSC::ExecState&, JSC::JSValue);
 template<typename T> const char* expectedEnumerationValues();
 
 // Specialized by generated code for IDL enumeration conversion.
@@ -40,9 +39,20 @@ template<typename T> JSC::JSString* convertEnumerationToJS(JSC::ExecState&, T);
 
 
 template<typename T> struct Converter<IDLEnumeration<T>> : DefaultConverter<IDLEnumeration<T>> {
-    static T convert(JSC::ExecState& state, JSC::JSValue value)
+    template<typename ExceptionThrower = DefaultExceptionThrower>
+    static T convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower())
     {
-        return convertEnumeration<T>(state, value);
+        auto& vm = state.vm();
+        auto throwScope = DECLARE_THROW_SCOPE(vm);
+
+        auto result = parseEnumeration<T>(state, value);
+        RETURN_IF_EXCEPTION(throwScope, { });
+
+        if (UNLIKELY(!result)) {
+            exceptionThrower(state, throwScope);
+            return { };
+        }
+        return result.value();
     }
 };
 
index 410de76..555ea67 100644 (file)
@@ -938,7 +938,7 @@ static void jsSubtleCryptoFunctionImportKeyPromise(ExecState& state, Ref<Deferre
         return;
     }
 
-    auto format = convertEnumeration<SubtleCrypto::KeyFormat>(state, state.uncheckedArgument(0));
+    auto format = convert<IDLEnumeration<SubtleCrypto::KeyFormat>>(state, state.uncheckedArgument(0));
     RETURN_IF_EXCEPTION(scope, void());
 
     auto keyData = toKeyData(state, format, state.uncheckedArgument(1));
@@ -986,7 +986,7 @@ static void jsSubtleCryptoFunctionExportKeyPromise(ExecState& state, Ref<Deferre
         return;
     }
 
-    auto format = convertEnumeration<SubtleCrypto::KeyFormat>(state, state.uncheckedArgument(0));
+    auto format = convert<IDLEnumeration<SubtleCrypto::KeyFormat>>(state, state.uncheckedArgument(0));
     RETURN_IF_EXCEPTION(scope, void());
 
     auto key = toCryptoKey(state, state.uncheckedArgument(1));
@@ -1041,7 +1041,7 @@ static void jsSubtleCryptoFunctionWrapKeyPromise(ExecState& state, Ref<DeferredP
         return;
     }
 
-    auto format = convertEnumeration<SubtleCrypto::KeyFormat>(state, state.uncheckedArgument(0));
+    auto format = convert<IDLEnumeration<SubtleCrypto::KeyFormat>>(state, state.uncheckedArgument(0));
     RETURN_IF_EXCEPTION(scope, void());
 
     auto key = toCryptoKey(state, state.uncheckedArgument(1));
@@ -1148,7 +1148,7 @@ static void jsSubtleCryptoFunctionUnwrapKeyPromise(ExecState& state, Ref<Deferre
         return;
     }
 
-    auto format = convertEnumeration<SubtleCrypto::KeyFormat>(state, state.uncheckedArgument(0));
+    auto format = convert<IDLEnumeration<SubtleCrypto::KeyFormat>>(state, state.uncheckedArgument(0));
     RETURN_IF_EXCEPTION(scope, void());
 
     auto wrappedKey = toVector(state, state.uncheckedArgument(1));
index 3fc6fc1..496c8e0 100644 (file)
@@ -838,6 +838,11 @@ sub GetArgumentExceptionFunction
         return "throwArgumentTypeError(state, scope, ${argumentIndex}, \"${name}\", \"${visibleInterfaceName}\", ${quotedFunctionName}, \"${typeName}\");";
     }
 
+    if ($codeGenerator->IsEnumType($argument->type)) {
+        my $className = GetEnumerationClassName($argument->type, $interface);
+        return "throwArgumentMustBeEnumError(state, scope, ${argumentIndex}, \"${name}\", \"${visibleInterfaceName}\", ${quotedFunctionName}, expectedEnumerationValues<${className}>());";
+    }
+
     return undef;
 }
 
@@ -877,7 +882,7 @@ sub PassArgumentExpression
 
     my $type = $context->type;
 
-    return "${name}.value()" if $codeGenerator->IsEnumType($type);
+    return "${name}.value()" if $codeGenerator->IsEnumType($type) && ref($context) eq "IDLAttribute";
     return "WTFMove(${name})" if $type->isNullable;
     
     if ($codeGenerator->IsTypedArrayType($type)) {
@@ -1361,18 +1366,6 @@ sub GenerateEnumerationImplementationContent
     $result .= "    return std::nullopt;\n";
     $result .= "}\n\n";
 
-    $result .= "template<> $className convertEnumeration<$className>(ExecState& state, JSValue value)\n";
-    $result .= "{\n";
-    $result .= "    VM& vm = state.vm();\n";
-    $result .= "    auto throwScope = DECLARE_THROW_SCOPE(vm);\n";
-    $result .= "    auto result = parseEnumeration<$className>(state, value);\n";
-    $result .= "    if (UNLIKELY(!result)) {\n";
-    $result .= "        throwTypeError(&state, throwScope);\n";
-    $result .= "        return { };\n";
-    $result .= "    }\n";
-    $result .= "    return result.value();\n";
-    $result .= "}\n\n";
-
     $result .= "template<> const char* expectedEnumerationValues<$className>()\n";
     $result .= "{\n";
     $result .= "    return \"\\\"" . join ("\\\", \\\"", @{$enumeration->values}) . "\\\"\";\n";
@@ -1413,7 +1406,6 @@ sub GenerateEnumerationHeaderContent
 
     $result .= "template<> ${exportMacro}JSC::JSString* convertEnumerationToJS(JSC::ExecState&, $className);\n\n";
     $result .= "template<> ${exportMacro}std::optional<$className> parseEnumeration<$className>(JSC::ExecState&, JSC::JSValue);\n";
-    $result .= "template<> ${exportMacro}$className convertEnumeration<$className>(JSC::ExecState&, JSC::JSValue);\n";
     $result .= "template<> ${exportMacro}const char* expectedEnumerationValues<$className>();\n\n";
     $result .= "#endif\n\n" if $conditionalString;
     
@@ -4894,47 +4886,6 @@ sub GenerateParametersCheck
             push(@$outputArray, "    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());\n");
 
             $value = "WTFMove(${name}.arguments.value())";
-
-        } elsif ($codeGenerator->IsEnumType($type)) {
-            AddToImplIncludes("<runtime/Error.h>", $conditional);
-
-            my $className = GetEnumerationClassName($type, $interface);
-            my $nativeType = $className;
-            my $optionalValue = "optionalValue";
-            my $defineOptionalValue = "auto optionalValue";
-            my $indent = "";
-
-            die "Variadic argument is already handled here" if $argument->isVariadic;
-            my $argumentLookupMethod = $argument->isOptional ? "argument" : "uncheckedArgument";
-
-            if ($argument->isOptional && !defined($argument->default)) {
-                $nativeType = "std::optional<$className>";
-                $optionalValue = $name;
-                $defineOptionalValue = $name;
-            }
-
-            push(@$outputArray, "    auto ${name}Value = state->$argumentLookupMethod($argumentIndex);\n");
-            push(@$outputArray, "    $nativeType $name;\n");
-
-            if ($argument->isOptional) {
-                if (!defined $argument->default) {
-                    push(@$outputArray, "    if (!${name}Value.isUndefined()) {\n");
-                } else {
-                    push(@$outputArray, "    if (${name}Value.isUndefined())\n");
-                    push(@$outputArray, "        $name = " . GenerateDefaultValue($interface, $argument, $argument->type, $argument->default) . ";\n");
-                    push(@$outputArray, "    else {\n");
-                }
-                $indent = "    ";
-            }
-
-            $implIncludes{"JS$className.h"} = 1 if $codeGenerator->IsExternalEnumType($type);
-            push(@$outputArray, "$indent    $defineOptionalValue = parseEnumeration<$className>(*state, ${name}Value);\n");
-            push(@$outputArray, "$indent    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());\n");
-            push(@$outputArray, "$indent    if (UNLIKELY(!$optionalValue))\n");
-            push(@$outputArray, "$indent        return throwArgumentMustBeEnumError(*state, throwScope, $argumentIndex, \"$name\", \"$visibleInterfaceName\", $quotedFunctionName, expectedEnumerationValues<$className>());\n");
-            push(@$outputArray, "$indent    $name = optionalValue.value();\n") if $optionalValue ne $name;
-
-            push(@$outputArray, "    }\n") if $indent ne "";
         } else {
             my $argumentLookupForConversion;
             my $optionalCheck;
@@ -5687,9 +5638,7 @@ sub JSValueToNative
 
     AddToImplIncludesForIDLType($type, $conditional);
 
-    # parseEnumeration<> returns a std::optional. For dictionary members we need convert<IDLEnumeration>() which guarantee
-    # the enum, or throws a TypeError. Bypass this check for IDLDictionaryMembers.
-    if ($codeGenerator->IsEnumType($type) && ref($context) ne "IDLDictionaryMember") {
+    if ($codeGenerator->IsEnumType($type) && ref($context) eq "IDLAttribute") {
         return ("parseEnumeration<" . GetEnumerationClassName($type, $interface) . ">($stateReference, $value)", 1);
     }
 
index d90aa1a..ce369d4 100644 (file)
@@ -61,18 +61,6 @@ template<> std::optional<TestCallbackInterface::Enum> parseEnumeration<TestCallb
     return std::nullopt;
 }
 
-template<> TestCallbackInterface::Enum convertEnumeration<TestCallbackInterface::Enum>(ExecState& state, JSValue value)
-{
-    VM& vm = state.vm();
-    auto throwScope = DECLARE_THROW_SCOPE(vm);
-    auto result = parseEnumeration<TestCallbackInterface::Enum>(state, value);
-    if (UNLIKELY(!result)) {
-        throwTypeError(&state, throwScope);
-        return { };
-    }
-    return result.value();
-}
-
 template<> const char* expectedEnumerationValues<TestCallbackInterface::Enum>()
 {
     return "\"value1\", \"value2\"";
index 33bad26..8e7d153 100644 (file)
@@ -68,7 +68,6 @@ inline JSC::JSValue toJS(TestCallbackInterface* impl) { return impl ? toJS(*impl
 template<> JSC::JSString* convertEnumerationToJS(JSC::ExecState&, TestCallbackInterface::Enum);
 
 template<> std::optional<TestCallbackInterface::Enum> parseEnumeration<TestCallbackInterface::Enum>(JSC::ExecState&, JSC::JSValue);
-template<> TestCallbackInterface::Enum convertEnumeration<TestCallbackInterface::Enum>(JSC::ExecState&, JSC::JSValue);
 template<> const char* expectedEnumerationValues<TestCallbackInterface::Enum>();
 
 template<> TestCallbackInterface::Dictionary convertDictionary<TestCallbackInterface::Dictionary>(JSC::ExecState&, JSC::JSValue);
index 8f7de37..f9bb5ad 100644 (file)
@@ -124,18 +124,6 @@ template<> std::optional<TestObj::EnumType> parseEnumeration<TestObj::EnumType>(
     return std::nullopt;
 }
 
-template<> TestObj::EnumType convertEnumeration<TestObj::EnumType>(ExecState& state, JSValue value)
-{
-    VM& vm = state.vm();
-    auto throwScope = DECLARE_THROW_SCOPE(vm);
-    auto result = parseEnumeration<TestObj::EnumType>(state, value);
-    if (UNLIKELY(!result)) {
-        throwTypeError(&state, throwScope);
-        return { };
-    }
-    return result.value();
-}
-
 template<> const char* expectedEnumerationValues<TestObj::EnumType>()
 {
     return "\"\", \"enumValue1\", \"EnumValue2\", \"EnumValue3\"";
@@ -171,18 +159,6 @@ template<> std::optional<TestObj::Optional> parseEnumeration<TestObj::Optional>(
     return std::nullopt;
 }
 
-template<> TestObj::Optional convertEnumeration<TestObj::Optional>(ExecState& state, JSValue value)
-{
-    VM& vm = state.vm();
-    auto throwScope = DECLARE_THROW_SCOPE(vm);
-    auto result = parseEnumeration<TestObj::Optional>(state, value);
-    if (UNLIKELY(!result)) {
-        throwTypeError(&state, throwScope);
-        return { };
-    }
-    return result.value();
-}
-
 template<> const char* expectedEnumerationValues<TestObj::Optional>()
 {
     return "\"\", \"OptionalValue1\", \"OptionalValue2\", \"OptionalValue3\"";
@@ -210,18 +186,6 @@ template<> std::optional<AlternateEnumName> parseEnumeration<AlternateEnumName>(
     return std::nullopt;
 }
 
-template<> AlternateEnumName convertEnumeration<AlternateEnumName>(ExecState& state, JSValue value)
-{
-    VM& vm = state.vm();
-    auto throwScope = DECLARE_THROW_SCOPE(vm);
-    auto result = parseEnumeration<AlternateEnumName>(state, value);
-    if (UNLIKELY(!result)) {
-        throwTypeError(&state, throwScope);
-        return { };
-    }
-    return result.value();
-}
-
 template<> const char* expectedEnumerationValues<AlternateEnumName>()
 {
     return "\"enumValue1\", \"EnumValue2\"";
@@ -247,18 +211,6 @@ template<> std::optional<TestObj::EnumA> parseEnumeration<TestObj::EnumA>(ExecSt
     return std::nullopt;
 }
 
-template<> TestObj::EnumA convertEnumeration<TestObj::EnumA>(ExecState& state, JSValue value)
-{
-    VM& vm = state.vm();
-    auto throwScope = DECLARE_THROW_SCOPE(vm);
-    auto result = parseEnumeration<TestObj::EnumA>(state, value);
-    if (UNLIKELY(!result)) {
-        throwTypeError(&state, throwScope);
-        return { };
-    }
-    return result.value();
-}
-
 template<> const char* expectedEnumerationValues<TestObj::EnumA>()
 {
     return "\"A\"";
@@ -286,18 +238,6 @@ template<> std::optional<TestObj::EnumB> parseEnumeration<TestObj::EnumB>(ExecSt
     return std::nullopt;
 }
 
-template<> TestObj::EnumB convertEnumeration<TestObj::EnumB>(ExecState& state, JSValue value)
-{
-    VM& vm = state.vm();
-    auto throwScope = DECLARE_THROW_SCOPE(vm);
-    auto result = parseEnumeration<TestObj::EnumB>(state, value);
-    if (UNLIKELY(!result)) {
-        throwTypeError(&state, throwScope);
-        return { };
-    }
-    return result.value();
-}
-
 template<> const char* expectedEnumerationValues<TestObj::EnumB>()
 {
     return "\"B\"";
@@ -325,18 +265,6 @@ template<> std::optional<TestObj::EnumC> parseEnumeration<TestObj::EnumC>(ExecSt
     return std::nullopt;
 }
 
-template<> TestObj::EnumC convertEnumeration<TestObj::EnumC>(ExecState& state, JSValue value)
-{
-    VM& vm = state.vm();
-    auto throwScope = DECLARE_THROW_SCOPE(vm);
-    auto result = parseEnumeration<TestObj::EnumC>(state, value);
-    if (UNLIKELY(!result)) {
-        throwTypeError(&state, throwScope);
-        return { };
-    }
-    return result.value();
-}
-
 template<> const char* expectedEnumerationValues<TestObj::EnumC>()
 {
     return "\"C\"";
@@ -366,18 +294,6 @@ template<> std::optional<TestObj::Kind> parseEnumeration<TestObj::Kind>(ExecStat
     return std::nullopt;
 }
 
-template<> TestObj::Kind convertEnumeration<TestObj::Kind>(ExecState& state, JSValue value)
-{
-    VM& vm = state.vm();
-    auto throwScope = DECLARE_THROW_SCOPE(vm);
-    auto result = parseEnumeration<TestObj::Kind>(state, value);
-    if (UNLIKELY(!result)) {
-        throwTypeError(&state, throwScope);
-        return { };
-    }
-    return result.value();
-}
-
 template<> const char* expectedEnumerationValues<TestObj::Kind>()
 {
     return "\"quick\", \"dead\"";
@@ -405,18 +321,6 @@ template<> std::optional<TestObj::Size> parseEnumeration<TestObj::Size>(ExecStat
     return std::nullopt;
 }
 
-template<> TestObj::Size convertEnumeration<TestObj::Size>(ExecState& state, JSValue value)
-{
-    VM& vm = state.vm();
-    auto throwScope = DECLARE_THROW_SCOPE(vm);
-    auto result = parseEnumeration<TestObj::Size>(state, value);
-    if (UNLIKELY(!result)) {
-        throwTypeError(&state, throwScope);
-        return { };
-    }
-    return result.value();
-}
-
 template<> const char* expectedEnumerationValues<TestObj::Size>()
 {
     return "\"small\", \"much-much-larger\"";
@@ -444,18 +348,6 @@ template<> std::optional<TestObj::Confidence> parseEnumeration<TestObj::Confiden
     return std::nullopt;
 }
 
-template<> TestObj::Confidence convertEnumeration<TestObj::Confidence>(ExecState& state, JSValue value)
-{
-    VM& vm = state.vm();
-    auto throwScope = DECLARE_THROW_SCOPE(vm);
-    auto result = parseEnumeration<TestObj::Confidence>(state, value);
-    if (UNLIKELY(!result)) {
-        throwTypeError(&state, throwScope);
-        return { };
-    }
-    return result.value();
-}
-
 template<> const char* expectedEnumerationValues<TestObj::Confidence>()
 {
     return "\"high\", \"kinda-low\"";
@@ -5746,14 +5638,9 @@ static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionMethodWithEnumArgCal
     auto& impl = castedThis->wrapped();
     if (UNLIKELY(state->argumentCount() < 1))
         return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
-    auto enumArgValue = state->uncheckedArgument(0);
-    TestObj::EnumType enumArg;
-    auto optionalValue = parseEnumeration<TestObj::EnumType>(*state, enumArgValue);
+    auto enumArg = convert<IDLEnumeration<TestObj::EnumType>>(*state, state->uncheckedArgument(0), [](JSC::ExecState& state, JSC::ThrowScope& scope) { throwArgumentMustBeEnumError(state, scope, 0, "enumArg", "TestObject", "methodWithEnumArg", expectedEnumerationValues<TestObj::EnumType>()); });
     RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
-    if (UNLIKELY(!optionalValue))
-        return throwArgumentMustBeEnumError(*state, throwScope, 0, "enumArg", "TestObject", "methodWithEnumArg", expectedEnumerationValues<TestObj::EnumType>());
-    enumArg = optionalValue.value();
-    impl.methodWithEnumArg(enumArg);
+    impl.methodWithEnumArg(WTFMove(enumArg));
     return JSValue::encode(jsUndefined());
 }
 
@@ -5771,14 +5658,9 @@ static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionMethodWithStandalone
     auto& impl = castedThis->wrapped();
     if (UNLIKELY(state->argumentCount() < 1))
         return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
-    auto enumArgValue = state->uncheckedArgument(0);
-    TestStandaloneEnumeration enumArg;
-    auto optionalValue = parseEnumeration<TestStandaloneEnumeration>(*state, enumArgValue);
+    auto enumArg = convert<IDLEnumeration<TestStandaloneEnumeration>>(*state, state->uncheckedArgument(0), [](JSC::ExecState& state, JSC::ThrowScope& scope) { throwArgumentMustBeEnumError(state, scope, 0, "enumArg", "TestObject", "methodWithStandaloneEnumArg", expectedEnumerationValues<TestStandaloneEnumeration>()); });
     RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
-    if (UNLIKELY(!optionalValue))
-        return throwArgumentMustBeEnumError(*state, throwScope, 0, "enumArg", "TestObject", "methodWithStandaloneEnumArg", expectedEnumerationValues<TestStandaloneEnumeration>());
-    enumArg = optionalValue.value();
-    impl.methodWithStandaloneEnumArg(enumArg);
+    impl.methodWithStandaloneEnumArg(WTFMove(enumArg));
     return JSValue::encode(jsUndefined());
 }
 
@@ -5794,15 +5676,9 @@ static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionMethodWithOptionalEn
     UNUSED_PARAM(state);
     UNUSED_PARAM(throwScope);
     auto& impl = castedThis->wrapped();
-    auto enumArgValue = state->argument(0);
-    std::optional<TestObj::EnumType> enumArg;
-    if (!enumArgValue.isUndefined()) {
-        enumArg = parseEnumeration<TestObj::EnumType>(*state, enumArgValue);
-        RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
-        if (UNLIKELY(!enumArg))
-            return throwArgumentMustBeEnumError(*state, throwScope, 0, "enumArg", "TestObject", "methodWithOptionalEnumArg", expectedEnumerationValues<TestObj::EnumType>());
-    }
-    impl.methodWithOptionalEnumArg(enumArg);
+    auto enumArg = state->argument(0).isUndefined() ? std::optional<Converter<IDLEnumeration<TestObj::EnumType>>::ReturnType>() : std::optional<Converter<IDLEnumeration<TestObj::EnumType>>::ReturnType>(convert<IDLEnumeration<TestObj::EnumType>>(*state, state->uncheckedArgument(0), [](JSC::ExecState& state, JSC::ThrowScope& scope) { throwArgumentMustBeEnumError(state, scope, 0, "enumArg", "TestObject", "methodWithOptionalEnumArg", expectedEnumerationValues<TestObj::EnumType>()); }));
+    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+    impl.methodWithOptionalEnumArg(WTFMove(enumArg));
     return JSValue::encode(jsUndefined());
 }
 
@@ -5818,18 +5694,9 @@ static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionMethodWithOptionalEn
     UNUSED_PARAM(state);
     UNUSED_PARAM(throwScope);
     auto& impl = castedThis->wrapped();
-    auto enumArgValue = state->argument(0);
-    TestObj::EnumType enumArg;
-    if (enumArgValue.isUndefined())
-        enumArg = TestObj::EnumType::EnumValue1;
-    else {
-        auto optionalValue = parseEnumeration<TestObj::EnumType>(*state, enumArgValue);
-        RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
-        if (UNLIKELY(!optionalValue))
-            return throwArgumentMustBeEnumError(*state, throwScope, 0, "enumArg", "TestObject", "methodWithOptionalEnumArgAndDefaultValue", expectedEnumerationValues<TestObj::EnumType>());
-        enumArg = optionalValue.value();
-    }
-    impl.methodWithOptionalEnumArgAndDefaultValue(enumArg);
+    auto enumArg = state->argument(0).isUndefined() ? TestObj::EnumType::EnumValue1 : convert<IDLEnumeration<TestObj::EnumType>>(*state, state->uncheckedArgument(0), [](JSC::ExecState& state, JSC::ThrowScope& scope) { throwArgumentMustBeEnumError(state, scope, 0, "enumArg", "TestObject", "methodWithOptionalEnumArgAndDefaultValue", expectedEnumerationValues<TestObj::EnumType>()); });
+    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+    impl.methodWithOptionalEnumArgAndDefaultValue(WTFMove(enumArg));
     return JSValue::encode(jsUndefined());
 }
 
index 8fc59d3..47556bd 100644 (file)
@@ -108,19 +108,16 @@ template<> struct JSDOMWrapperConverterTraits<TestObj> {
 template<> JSC::JSString* convertEnumerationToJS(JSC::ExecState&, TestObj::EnumType);
 
 template<> std::optional<TestObj::EnumType> parseEnumeration<TestObj::EnumType>(JSC::ExecState&, JSC::JSValue);
-template<> TestObj::EnumType convertEnumeration<TestObj::EnumType>(JSC::ExecState&, JSC::JSValue);
 template<> const char* expectedEnumerationValues<TestObj::EnumType>();
 
 template<> JSC::JSString* convertEnumerationToJS(JSC::ExecState&, TestObj::Optional);
 
 template<> std::optional<TestObj::Optional> parseEnumeration<TestObj::Optional>(JSC::ExecState&, JSC::JSValue);
-template<> TestObj::Optional convertEnumeration<TestObj::Optional>(JSC::ExecState&, JSC::JSValue);
 template<> const char* expectedEnumerationValues<TestObj::Optional>();
 
 template<> JSC::JSString* convertEnumerationToJS(JSC::ExecState&, AlternateEnumName);
 
 template<> std::optional<AlternateEnumName> parseEnumeration<AlternateEnumName>(JSC::ExecState&, JSC::JSValue);
-template<> AlternateEnumName convertEnumeration<AlternateEnumName>(JSC::ExecState&, JSC::JSValue);
 template<> const char* expectedEnumerationValues<AlternateEnumName>();
 
 #if ENABLE(Condition1)
@@ -128,7 +125,6 @@ template<> const char* expectedEnumerationValues<AlternateEnumName>();
 template<> JSC::JSString* convertEnumerationToJS(JSC::ExecState&, TestObj::EnumA);
 
 template<> std::optional<TestObj::EnumA> parseEnumeration<TestObj::EnumA>(JSC::ExecState&, JSC::JSValue);
-template<> TestObj::EnumA convertEnumeration<TestObj::EnumA>(JSC::ExecState&, JSC::JSValue);
 template<> const char* expectedEnumerationValues<TestObj::EnumA>();
 
 #endif
@@ -138,7 +134,6 @@ template<> const char* expectedEnumerationValues<TestObj::EnumA>();
 template<> JSC::JSString* convertEnumerationToJS(JSC::ExecState&, TestObj::EnumB);
 
 template<> std::optional<TestObj::EnumB> parseEnumeration<TestObj::EnumB>(JSC::ExecState&, JSC::JSValue);
-template<> TestObj::EnumB convertEnumeration<TestObj::EnumB>(JSC::ExecState&, JSC::JSValue);
 template<> const char* expectedEnumerationValues<TestObj::EnumB>();
 
 #endif
@@ -148,7 +143,6 @@ template<> const char* expectedEnumerationValues<TestObj::EnumB>();
 template<> JSC::JSString* convertEnumerationToJS(JSC::ExecState&, TestObj::EnumC);
 
 template<> std::optional<TestObj::EnumC> parseEnumeration<TestObj::EnumC>(JSC::ExecState&, JSC::JSValue);
-template<> TestObj::EnumC convertEnumeration<TestObj::EnumC>(JSC::ExecState&, JSC::JSValue);
 template<> const char* expectedEnumerationValues<TestObj::EnumC>();
 
 #endif
@@ -156,19 +150,16 @@ template<> const char* expectedEnumerationValues<TestObj::EnumC>();
 template<> JSC::JSString* convertEnumerationToJS(JSC::ExecState&, TestObj::Kind);
 
 template<> std::optional<TestObj::Kind> parseEnumeration<TestObj::Kind>(JSC::ExecState&, JSC::JSValue);
-template<> TestObj::Kind convertEnumeration<TestObj::Kind>(JSC::ExecState&, JSC::JSValue);
 template<> const char* expectedEnumerationValues<TestObj::Kind>();
 
 template<> JSC::JSString* convertEnumerationToJS(JSC::ExecState&, TestObj::Size);
 
 template<> std::optional<TestObj::Size> parseEnumeration<TestObj::Size>(JSC::ExecState&, JSC::JSValue);
-template<> TestObj::Size convertEnumeration<TestObj::Size>(JSC::ExecState&, JSC::JSValue);
 template<> const char* expectedEnumerationValues<TestObj::Size>();
 
 template<> JSC::JSString* convertEnumerationToJS(JSC::ExecState&, TestObj::Confidence);
 
 template<> std::optional<TestObj::Confidence> parseEnumeration<TestObj::Confidence>(JSC::ExecState&, JSC::JSValue);
-template<> TestObj::Confidence convertEnumeration<TestObj::Confidence>(JSC::ExecState&, JSC::JSValue);
 template<> const char* expectedEnumerationValues<TestObj::Confidence>();
 
 template<> TestObj::Dictionary convertDictionary<TestObj::Dictionary>(JSC::ExecState&, JSC::JSValue);
index 5f406c2..d7c4f02 100644 (file)
@@ -86,18 +86,6 @@ template<> std::optional<TestStandaloneDictionary::EnumInStandaloneDictionaryFil
     return std::nullopt;
 }
 
-template<> TestStandaloneDictionary::EnumInStandaloneDictionaryFile convertEnumeration<TestStandaloneDictionary::EnumInStandaloneDictionaryFile>(ExecState& state, JSValue value)
-{
-    VM& vm = state.vm();
-    auto throwScope = DECLARE_THROW_SCOPE(vm);
-    auto result = parseEnumeration<TestStandaloneDictionary::EnumInStandaloneDictionaryFile>(state, value);
-    if (UNLIKELY(!result)) {
-        throwTypeError(&state, throwScope);
-        return { };
-    }
-    return result.value();
-}
-
 template<> const char* expectedEnumerationValues<TestStandaloneDictionary::EnumInStandaloneDictionaryFile>()
 {
     return "\"enumValue1\", \"enumValue2\"";
index 32a81b6..86633a7 100644 (file)
@@ -32,7 +32,6 @@ template<> DictionaryImplName convertDictionary<DictionaryImplName>(JSC::ExecSta
 template<> JSC::JSString* convertEnumerationToJS(JSC::ExecState&, TestStandaloneDictionary::EnumInStandaloneDictionaryFile);
 
 template<> std::optional<TestStandaloneDictionary::EnumInStandaloneDictionaryFile> parseEnumeration<TestStandaloneDictionary::EnumInStandaloneDictionaryFile>(JSC::ExecState&, JSC::JSValue);
-template<> TestStandaloneDictionary::EnumInStandaloneDictionaryFile convertEnumeration<TestStandaloneDictionary::EnumInStandaloneDictionaryFile>(JSC::ExecState&, JSC::JSValue);
 template<> const char* expectedEnumerationValues<TestStandaloneDictionary::EnumInStandaloneDictionaryFile>();
 
 } // namespace WebCore
index a1886a7..6df7ec5 100644 (file)
@@ -53,18 +53,6 @@ template<> std::optional<TestStandaloneEnumeration> parseEnumeration<TestStandal
     return std::nullopt;
 }
 
-template<> TestStandaloneEnumeration convertEnumeration<TestStandaloneEnumeration>(ExecState& state, JSValue value)
-{
-    VM& vm = state.vm();
-    auto throwScope = DECLARE_THROW_SCOPE(vm);
-    auto result = parseEnumeration<TestStandaloneEnumeration>(state, value);
-    if (UNLIKELY(!result)) {
-        throwTypeError(&state, throwScope);
-        return { };
-    }
-    return result.value();
-}
-
 template<> const char* expectedEnumerationValues<TestStandaloneEnumeration>()
 {
     return "\"enumValue1\", \"enumValue2\"";
index 80622ad..0bd763a 100644 (file)
@@ -30,7 +30,6 @@ namespace WebCore {
 template<> JSC::JSString* convertEnumerationToJS(JSC::ExecState&, TestStandaloneEnumeration);
 
 template<> std::optional<TestStandaloneEnumeration> parseEnumeration<TestStandaloneEnumeration>(JSC::ExecState&, JSC::JSValue);
-template<> TestStandaloneEnumeration convertEnumeration<TestStandaloneEnumeration>(JSC::ExecState&, JSC::JSValue);
 template<> const char* expectedEnumerationValues<TestStandaloneEnumeration>();
 
 } // namespace WebCore