| {##############################################################################} |
| {# 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)}} |
| {{constructor.cpp_value}}->AssociateWithDartWrapper(args); |
| {% if constructor.has_exception_state %} |
| if (es.had_exception()) { |
| 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 %} |