mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
411 lines
16 KiB
Plaintext
411 lines
16 KiB
Plaintext
{##############################################################################}
|
|
{# FIXME: We should return a rejected Promise if an error occurs in this
|
|
function when ALL methods in this overload return Promise. In order to do so,
|
|
we must ensure either ALL or NO methods in this overload return Promise #}
|
|
{% macro overload_resolution_method(method) %}
|
|
{% set overloads = method.overloads %}
|
|
{% if method.is_static %}
|
|
{% set offset = 0 %}
|
|
{% else %}
|
|
{% set offset = 1 %}
|
|
{% endif %}
|
|
static void {{static_method_name(overloads.name)}}Dispatcher(Dart_NativeArguments args)
|
|
{
|
|
Dart_Handle exception = nullptr;
|
|
const int argOffset = {{offset}};
|
|
int argCount = Dart_GetNativeArgumentCount(args) - argOffset;
|
|
|
|
{# First resolve by length #}
|
|
{# 2. Initialize argcount to be min(maxarg, n). #}
|
|
switch (std::min({{overloads.maxarg}}, argCount)) {
|
|
{# 3. Remove from S all entries whose type list is not of length argcount. #}
|
|
{% for length, tests_methods in overloads.length_tests_methods %}
|
|
{# 10. If i = d, then: #}
|
|
case {{length}}:
|
|
{# Then resolve by testing argument #}
|
|
{% for test, method in tests_methods %}
|
|
if ({{test}}) {
|
|
{% if method.is_custom %}
|
|
{{static_method_name(method.name)}}(args);
|
|
{% else %}
|
|
{{static_method_name(method.name, method.overload_index)}}(args);
|
|
{% endif %}
|
|
return;
|
|
}
|
|
{% endfor %}
|
|
break;
|
|
{% endfor %}
|
|
default:
|
|
{# Invalid arity, throw error #}
|
|
{# Report full list of valid arities if gaps and above minimum #}
|
|
{% if overloads.valid_arities %}
|
|
if (argCount >= {{overloads.minarg}}) {
|
|
const String message = "Wrong arity, expected one of {{overloads.valid_arities}}";
|
|
// TODO(dart): exception = DartUtilities::coreArgumentErrorException(message);
|
|
goto fail;
|
|
}
|
|
{% endif %}
|
|
{# Otherwise just report "not enough arguments" #}
|
|
{
|
|
const String message = "Not enough arguments (at least {{overloads.minarg}} required)";
|
|
// TODO(dart): exception = DartUtilities::coreArgumentErrorException(message);
|
|
goto fail;
|
|
}
|
|
return;
|
|
}
|
|
{
|
|
const String message = "No function was found that matched the signature provided.";
|
|
// TODO(dart): exception = DartUtilities::coreArgumentErrorException(message);
|
|
goto fail;
|
|
}
|
|
return;
|
|
fail:
|
|
Dart_ThrowException(exception);
|
|
ASSERT_NOT_REACHED();
|
|
}
|
|
{% endmacro %}
|
|
|
|
|
|
{##############################################################################}
|
|
{# arguments_count is normal method.number_of_arguments however for optional #}
|
|
{# arguments then number_of_required_arguments is passed (sans optional). #}
|
|
{# overload in the index if overloaded. #}
|
|
{# interface is specified signals that it's a constructor being called the #}
|
|
{# delegation to the create is emitted.
|
|
{##############################################################################}
|
|
{% macro generate_method(method, arguments_count) %}
|
|
{% set overload_index = method.overload_index %}
|
|
static void {{static_method_name(method.name, overload_index)}}(Dart_NativeArguments args)
|
|
{
|
|
{% if not method.is_static %}
|
|
{{cpp_class}}* /* FIXME(vsm): Remove this. */ ALLOW_UNUSED receiver = GetReceiver<{{cpp_class}}>(args);
|
|
{% endif %}
|
|
{% if method.is_custom_element_callbacks %}
|
|
CustomElementCallbackScope deliveryScope;
|
|
{% endif %}
|
|
{% if arguments_count > 0 or
|
|
method.has_exception_state or
|
|
method.is_call_with_script_state or
|
|
method.is_call_with_execution_context or
|
|
method.is_call_with_script_arguments %}
|
|
Dart_Handle exception = nullptr;
|
|
{% endif %}
|
|
{
|
|
{% if method.is_call_with_script_state %}
|
|
ScriptState* state = DartUtilities::currentScriptState();
|
|
if (!state) {
|
|
exception = ToDart("Failed to retrieve a script state");
|
|
goto fail;
|
|
}
|
|
{% endif %}
|
|
{% if method.is_call_with_execution_context %}
|
|
ExecutionContext* context = DOMDartState::CurrentDocument();
|
|
if (!context) {
|
|
exception = ToDart("Failed to retrieve a context");
|
|
goto fail;
|
|
}
|
|
{% endif %}
|
|
{% if method.is_call_with_script_arguments %}
|
|
{# Last parameter is the customArgument #}
|
|
Dart_Handle customArgument = Dart_GetNativeArgument(args, Dart_GetNativeArgumentCount(args) - 1);
|
|
RefPtr<ScriptArguments> scriptArguments(DartUtilities::createScriptArguments(customArgument, exception));
|
|
if (!scriptArguments)
|
|
goto fail;
|
|
{% endif %}
|
|
{% if method.number_of_arguments != method.number_of_required_arguments %}
|
|
int argCount /* FIXME(vsm): Remove this. */ ALLOW_UNUSED = Dart_GetNativeArgumentCount(args);
|
|
{% endif %}
|
|
{% if method.has_exception_state %}
|
|
ExceptionState es;
|
|
{% endif %}
|
|
{{generate_arguments(method) | indent(8)}}
|
|
{{callback_return(method, method.dart_set_return_value, method.cpp_value)}}
|
|
{% if method.has_exception_state %}
|
|
if (es.had_exception()) {
|
|
exception = es.GetDartException(args, {{method.auto_scope}});
|
|
goto fail;
|
|
}
|
|
|
|
{% endif %}
|
|
return;
|
|
}
|
|
|
|
{% if arguments_count > 0 or method.has_exception_state or method.is_call_with_script_state or method.is_call_with_execution_context or method.is_call_with_script_arguments %}
|
|
fail:
|
|
Dart_ThrowException(exception);
|
|
ASSERT_NOT_REACHED();
|
|
{% endif %}
|
|
}
|
|
{% endmacro %}
|
|
|
|
|
|
{##############################################################################}
|
|
{% macro callback_return(method, dart_set_return_value, cpp_value) %}
|
|
{%- if method.union_arguments -%}
|
|
{{callback_union_return(method) | indent(8)}}
|
|
{%- elif method.idl_type == 'void' -%}
|
|
{{cpp_value}};
|
|
{%- elif method.is_constructor -%}
|
|
DartConverter<{{cpp_class}}*>::SetReturnValue(args, WTF::getPtr({{cpp_value}}), {{method.auto_scope}});
|
|
{%- else -%}
|
|
{{dart_set_return_value}};
|
|
{%- endif -%}
|
|
{% endmacro %}
|
|
|
|
|
|
{##############################################################################}
|
|
{% macro callback_union_return(method, argument_count) %}
|
|
{% set type_index = 0 %}
|
|
{% for union_argument in method.union_arguments %}
|
|
{{method.cpp_type[type_index]}} {{union_argument}};
|
|
{% set type_index = type_index + 1 %}
|
|
{% endfor %}
|
|
{{method.cpp_value}};
|
|
|
|
{% set union_set_result_index = 0 %}
|
|
{% for union_argument in method.union_arguments %}
|
|
if ({{union_argument}}) {
|
|
{{method.dart_set_return_value[union_set_result_index]}};
|
|
return;
|
|
}
|
|
{% set union_set_result_index = union_set_result_index + 1 %}
|
|
{% endfor %}
|
|
{% endmacro %}
|
|
|
|
|
|
{##############################################################################}
|
|
{% macro generate_argument(method, argument) %}
|
|
{# If sequence result is passed as an argument not as function return value. #}
|
|
{% if argument.is_optional and
|
|
not argument.has_default and
|
|
not argument.is_callback_interface %}
|
|
{# Optional arguments without a default value generate an early call with
|
|
fewer arguments if they are omitted. #}
|
|
if (UNLIKELY(argCount <= {{argument.arg_index}})) {
|
|
{{callback_return(method, argument.dart_set_return_value, argument.cpp_value)}}
|
|
if (exception)
|
|
goto fail;
|
|
return;
|
|
}
|
|
{% endif %}
|
|
{% if argument.is_callback_interface %}
|
|
{# Callback functions must be functions:
|
|
http://www.w3.org/TR/WebIDL/#es-callback-function #}
|
|
{% if argument.is_optional %}
|
|
{{argument.local_cpp_type}} {{argument.name}};
|
|
if (argCount > {{argument.arg_index}}) {
|
|
{{argument.name}} = DartConverter<{{argument.implemented_as}}*>::FromArgumentsWithNullCheck(args, {{argument.arg_index}}, exception);
|
|
}
|
|
{% else %}{# argument.is_optional #}
|
|
{{argument.local_cpp_type}} {{argument.name}} = DartConverter<{{argument.implemented_as}}*>::FromArgumentsWithNullCheck(args, {{argument.arg_index}}, exception);
|
|
{% endif %}{# argument.is_optional #}
|
|
{% else %}{# argument.is_callback_interface #}
|
|
{% if argument.is_optional and argument.has_default -%}
|
|
{{argument.local_cpp_type}} {{argument.name}} =
|
|
(argCount <= {{argument.arg_index}}) ? ({{argument.default_value}}) : {{argument.dart_value_to_local_cpp_value}};
|
|
{% elif argument.is_array_or_sequence_type %}
|
|
{{argument.local_cpp_type}} {{argument.name}};
|
|
{{argument.dart_value_to_local_cpp_value}};
|
|
{% else %}
|
|
{{argument.local_cpp_type}} {{argument.name}} = {{argument.dart_value_to_local_cpp_value}};
|
|
{% endif %}
|
|
{% endif %}{# argument.is_callback_interface #}
|
|
if (exception)
|
|
goto fail;
|
|
{% endmacro %}
|
|
|
|
|
|
{######################################}
|
|
{% macro generate_arguments(method) %}
|
|
{%- for argument in method.arguments -%}
|
|
{{generate_argument(method, argument)}}
|
|
{%- endfor -%}
|
|
{% endmacro %}
|
|
|
|
{##############################################################################}
|
|
{% macro static_method_name(name, overload_index) %}
|
|
{% set name = 'constructor' if not name else name -%}
|
|
{% if overload_index -%}
|
|
{{name}}Callback_{{overload_index}}
|
|
{%- else -%}
|
|
{{name}}Callback
|
|
{%- endif %}
|
|
{% endmacro -%}
|
|
|
|
|
|
{##############################################################################}
|
|
{% macro generate_resolver_body(dart_class, class_name, method) %}
|
|
{% for native_entry_group in method.native_entries|groupby('resolver_string') %}
|
|
{% set uses_script_args = method.is_call_with_script_arguments %}
|
|
{% if method.overload_index %}
|
|
{% set method_name = static_method_name(method.name) + "Dispatcher" %}
|
|
{% else %}
|
|
{% set method_name = static_method_name(method.name) %}
|
|
{% endif %}
|
|
{% set resolver_string = native_entry_group.grouper %}
|
|
{% if method.is_custom %}
|
|
// FIXME: we are missing changes from dart.idl so we don't always know how many
|
|
// args custom methods will take so we ignore that check which could hurt perf
|
|
// and security but lets us get everything running quicker.
|
|
if (name == "{{resolver_string}}") {
|
|
*autoSetupScope = {{method.auto_scope}};
|
|
return {{dart_class}}Internal::{{method_name}};
|
|
}
|
|
{% else %}
|
|
{% set args_one_based = method.number_of_arguments %}
|
|
{% set args_required_one_based = method.number_of_required_arguments %}
|
|
{% if not method.is_static %}
|
|
{% set args_one_based = args_one_based + 1 %}
|
|
{% set args_required_one_based = args_required_one_based + 1 %}
|
|
{% endif %}
|
|
|
|
{% if uses_script_args %}
|
|
{# FIXME(vsm): At least one script argument is expected. Generalize? #}
|
|
{% set args_one_based = args_one_based + 1 %}
|
|
{% set args_required_one_based = args_required_one_based + 1 %}
|
|
{% endif %}
|
|
|
|
{% if args_one_based == args_required_one_based %}
|
|
if (argumentCount == {{args_one_based}} && name == "{{resolver_string}}") {
|
|
*autoSetupScope = {{method.auto_scope}};
|
|
return {{dart_class}}Internal::{{method_name}};
|
|
}
|
|
{% else %}
|
|
if (argumentCount >= {{args_required_one_based}} && argumentCount <= {{args_one_based}} && name == "{{resolver_string}}") {
|
|
*autoSetupScope = {{method.auto_scope}};
|
|
return {{dart_class}}Internal::{{method_name}};
|
|
}
|
|
{% endif %}
|
|
{% endif %}
|
|
{% endfor %}
|
|
{% endmacro %}
|
|
|
|
|
|
{##############################################################################}
|
|
{% macro generate_symbolizer_body(dart_class, class_name, method) %}
|
|
{% for native_entry_group in method.native_entries|groupby('resolver_string') %}
|
|
{% set uses_script_args = method.is_call_with_script_arguments %}
|
|
{% if method.overload_index %}
|
|
{% set method_name = static_method_name(method.name) + "Dispatcher" %}
|
|
{% else %}
|
|
{% set method_name = static_method_name(method.name) %}
|
|
{% endif %}
|
|
{% set resolver_string = native_entry_group.grouper %}
|
|
if (native_function == {{dart_class}}Internal::{{method_name}}) {
|
|
return reinterpret_cast<const uint8_t*>("{{resolver_string}}");
|
|
}
|
|
{% endfor %}
|
|
{% endmacro %}
|
|
|
|
|
|
{##############################################################################}
|
|
{% macro generate_constructor(constructor, arguments_count, overload='') %}
|
|
{% if overload == '' %}
|
|
{% set overload_index = constructor.overload_index %}
|
|
{% else %}
|
|
{% set overload_index = overload %}
|
|
{% endif %}
|
|
static void {{static_method_name(constructor.name, overload_index)}}(Dart_NativeArguments args)
|
|
{
|
|
{% if arguments_count > 0 or
|
|
constructor.has_exception_state or
|
|
is_constructor_call_with_execution_context or
|
|
is_constructor_call_with_document or
|
|
(constructor == named_constructor) %}
|
|
Dart_Handle exception = nullptr;
|
|
{% endif %}
|
|
{
|
|
{% if is_constructor_call_with_execution_context %}
|
|
ExecutionContext* context = DOMDartState::CurrentDocument();
|
|
if (!context) {
|
|
exception = ToDart("Failed to retrieve a context");
|
|
goto fail;
|
|
}
|
|
{% endif %}
|
|
{% if is_constructor_call_with_document or (constructor == named_constructor) %}
|
|
LocalDOMWindow* domWindow = DOMDartState::CurrentWindow();
|
|
if (!domWindow) {
|
|
exception = ToDart("Failed to fetch domWindow");
|
|
goto fail;
|
|
}
|
|
Document& document = *domWindow->document();
|
|
{% endif %}
|
|
int argCount /* FIXME(vsm): Remove this. */ ALLOW_UNUSED = Dart_GetNativeArgumentCount(args);
|
|
{% if constructor.has_exception_state %}
|
|
ExceptionState es;
|
|
{% endif %}
|
|
{{generate_arguments(constructor) | indent(8)}}
|
|
{# TODO(iansf): The following line is incorrect if the constructor throws an exception. In that case, we should not call AssociateWithDartWrapper, as the constructor may have returned a nullptr. #}
|
|
{{constructor.cpp_value}}->AssociateWithDartWrapper(args);
|
|
{% if constructor.has_exception_state %}
|
|
if (es.had_exception()) {
|
|
{# TODO(iansf): The following line does not work in the case that an exception was thrown. Investigate why. #}
|
|
exception = es.GetDartException(args, {{constructor.auto_scope}});
|
|
goto fail;
|
|
}
|
|
|
|
{% endif %}
|
|
return;
|
|
}
|
|
|
|
{% if arguments_count > 0 or constructor.has_exception_state or is_constructor_call_with_execution_context or is_constructor_call_with_document or (constructor == named_constructor) %}
|
|
fail:
|
|
Dart_ThrowException(exception);
|
|
ASSERT_NOT_REACHED();
|
|
{% endif %}
|
|
}
|
|
{% endmacro %}
|
|
|
|
|
|
{##############################################################################}
|
|
{% macro generate_event_constructor() %}
|
|
static void eventConstructorCallback(Dart_NativeArguments args)
|
|
{
|
|
Dart_SetReturnValue(args, Dart_Null());
|
|
}
|
|
{% endmacro %}
|
|
|
|
,
|
|
{##############################################################################}
|
|
{% macro generate_resolver_constructor(dart_class, class_name, constructor) %}
|
|
{% for native_entry in constructor.native_entries %}
|
|
{% set resolver_string = native_entry.resolver_string %}
|
|
{% set args_one_based = constructor.number_of_arguments + 1 %}
|
|
{% set args_required_one_based = constructor.number_of_required_arguments + 1 %}
|
|
{% if constructor.overload_index %}
|
|
{% set constructor_name = static_method_name(constructor.name) + "Dispatcher" %}
|
|
{% else %}
|
|
{% set constructor_name = static_method_name(constructor.name) %}
|
|
{% endif %}
|
|
{% if has_custom_constructor %}
|
|
if (name == "{{resolver_string}}") {
|
|
{% elif constructor.number_of_arguments == constructor.number_of_required_arguments %}
|
|
if (argumentCount == {{args_one_based}} && name == "{{resolver_string}}") {
|
|
{% else %}
|
|
if (argumentCount >= {{args_required_one_based}} && argumentCount <= {{args_one_based}} && name == "{{resolver_string}}") {
|
|
{% endif %}
|
|
*autoSetupScope = {{constructor.auto_scope}};
|
|
return {{dart_class}}Internal::{{constructor_name}};
|
|
}
|
|
{% endfor %}
|
|
{% endmacro %}
|
|
|
|
{##############################################################################}
|
|
{% macro generate_resolver_event_constructor(dart_class, class_name) %}
|
|
{% set resolver_string = interface_name + "_constructorCallback" %}
|
|
if (argumentCount == 2 && name == "{{resolver_string}}") {
|
|
*autoSetupScope = 1;
|
|
return {{dart_class}}Internal::eventConstructorCallback;
|
|
}
|
|
{% endmacro %}
|
|
|
|
{##############################################################################}
|
|
{% macro generate_symbolizer_constructor(dart_class, class_name, constructor) %}
|
|
{% for native_entry in constructor.native_entries %}
|
|
{% set resolver_string = native_entry.resolver_string %}
|
|
if (native_function == {{dart_class}}Internal::{{static_method_name(constructor.name, constructor.overload_index)}}) {
|
|
return reinterpret_cast<const uint8_t*>("{{resolver_string}}");
|
|
}
|
|
{% endfor %}
|
|
{% endmacro %}
|