Commit 2469bf5b authored by jl@opera.com's avatar jl@opera.com

IDL: Improve overload resolution for methods with variadic arguments

When calculating "optionality list" for a method (as part of calculating
the effective overload set), treat variadic arguments as optional instead
as required.

WebIDL defines the optionality list as a list of "required", "optional"
and "variadic", whereas we implement it as a list of booleans. A list of
booleans is enough to achieve correct behavior, assuming both "optional"
and "variadic" are considered to be optional (true).

BUG=293561

Review URL: https://codereview.chromium.org/723013003

git-svn-id: svn://svn.chromium.org/blink/trunk@185289 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 38a81a20
......@@ -636,8 +636,9 @@ def effective_overload_set(F):
# if X’s argument at index i is a final, variadic argument, “optional”
# if the argument is optional, and “required” otherwise.
# (“optionality list”)
# (We’re just using a boolean for optional vs. required.)
o = tuple(argument['is_optional'] for argument in arguments)
# (We’re just using a boolean for optional/variadic vs. required.)
o = tuple(argument['is_optional'] or argument['is_variadic']
for argument in arguments)
# 4. Add to S the tuple <X, t0..n−1, o0..n−1>.
S.append((X, t, o))
# 5. If X is declared to be variadic, then:
......
......@@ -235,6 +235,7 @@ def argument_context(interface, method, argument, index):
'is_dictionary': idl_type.is_dictionary or idl_type.base_type == 'Dictionary',
'is_nullable': idl_type.is_nullable,
'is_optional': argument.is_optional,
'is_variadic': argument.is_variadic,
'is_variadic_wrapper_type': is_variadic_wrapper_type,
'is_wrapper_type': idl_type.is_wrapper_type,
'name': argument.name,
......
......@@ -450,6 +450,8 @@ interface TestObject {
void overloadedMethodJ(TestDictionary testDictionaryArg);
void overloadedMethodK(Function functionArg);
void overloadedMethodK(DOMString stringArg);
void overloadedMethodL(long longArg, any... restArgs);
void overloadedMethodL(DOMString stringArg, any... restArgs);
Promise promiseOverloadMethod();
Promise promiseOverloadMethod(Window arg1, double arg2);
......
......@@ -8323,6 +8323,80 @@ static void overloadedMethodKMethodCallback(const v8::FunctionCallbackInfo<v8::V
TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8Execution");
}
static void overloadedMethodL1Method(const v8::FunctionCallbackInfo<v8::Value>& info)
{
ExceptionState exceptionState(ExceptionState::ExecutionContext, "overloadedMethodL", "TestObject", info.Holder(), info.GetIsolate());
TestObject* impl = V8TestObject::toImpl(info.Holder());
int longArg;
Vector<ScriptValue> restArgs;
{
TONATIVE_VOID_EXCEPTIONSTATE_INTERNAL(longArg, toInt32(info[0], exceptionState), exceptionState);
TONATIVE_VOID_EXCEPTIONSTATE_INTERNAL(restArgs, toImplArguments<ScriptValue>(info, 1, exceptionState), exceptionState);
}
impl->overloadedMethodL(longArg, restArgs);
}
static void overloadedMethodL2Method(const v8::FunctionCallbackInfo<v8::Value>& info)
{
ExceptionState exceptionState(ExceptionState::ExecutionContext, "overloadedMethodL", "TestObject", info.Holder(), info.GetIsolate());
TestObject* impl = V8TestObject::toImpl(info.Holder());
V8StringResource<> stringArg;
Vector<ScriptValue> restArgs;
{
TOSTRING_VOID_INTERNAL(stringArg, info[0]);
TONATIVE_VOID_EXCEPTIONSTATE_INTERNAL(restArgs, toImplArguments<ScriptValue>(info, 1, exceptionState), exceptionState);
}
impl->overloadedMethodL(stringArg, restArgs);
}
static void overloadedMethodLMethod(const v8::FunctionCallbackInfo<v8::Value>& info)
{
ExceptionState exceptionState(ExceptionState::ExecutionContext, "overloadedMethodL", "TestObject", info.Holder(), info.GetIsolate());
switch (std::min(2, info.Length())) {
case 1:
if (info[0]->IsNumber()) {
overloadedMethodL1Method(info);
return;
}
if (true) {
overloadedMethodL2Method(info);
return;
}
if (true) {
overloadedMethodL1Method(info);
return;
}
break;
case 2:
if (info[0]->IsNumber()) {
overloadedMethodL1Method(info);
return;
}
if (true) {
overloadedMethodL2Method(info);
return;
}
if (true) {
overloadedMethodL1Method(info);
return;
}
break;
default:
exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(1, info.Length()));
exceptionState.throwIfNeeded();
return;
}
exceptionState.throwTypeError("No function was found that matched the signature provided.");
exceptionState.throwIfNeeded();
}
static void overloadedMethodLMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
{
TRACE_EVENT_SET_SAMPLING_STATE("blink", "DOMMethod");
TestObjectV8Internal::overloadedMethodLMethod(info);
TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8Execution");
}
static void promiseOverloadMethod1Method(const v8::FunctionCallbackInfo<v8::Value>& info)
{
TestObject* impl = V8TestObject::toImpl(info.Holder());
......@@ -10732,6 +10806,7 @@ static const V8DOMConfiguration::MethodConfiguration V8TestObjectMethods[] = {
{"overloadedMethodI", TestObjectV8Internal::overloadedMethodIMethodCallback, 0, 1, V8DOMConfiguration::ExposedToAllScripts},
{"overloadedMethodJ", TestObjectV8Internal::overloadedMethodJMethodCallback, 0, 1, V8DOMConfiguration::ExposedToAllScripts},
{"overloadedMethodK", TestObjectV8Internal::overloadedMethodKMethodCallback, 0, 1, V8DOMConfiguration::ExposedToAllScripts},
{"overloadedMethodL", TestObjectV8Internal::overloadedMethodLMethodCallback, 0, 1, V8DOMConfiguration::ExposedToAllScripts},
{"promiseOverloadMethod", TestObjectV8Internal::promiseOverloadMethodMethodCallback, 0, 0, V8DOMConfiguration::ExposedToAllScripts},
{"overloadedPerWorldBindingsMethod", TestObjectV8Internal::overloadedPerWorldBindingsMethodMethodCallback, TestObjectV8Internal::overloadedPerWorldBindingsMethodMethodCallbackForMainWorld, 0, V8DOMConfiguration::ExposedToAllScripts},
{"voidMethodClampUnsignedShortArg", TestObjectV8Internal::voidMethodClampUnsignedShortArgMethodCallback, 0, 1, V8DOMConfiguration::ExposedToAllScripts},
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment