| {##############################################################################} |
| {# 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 = 0; |
| 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 %} |
| {% filter runtime_enabled(not overloads.runtime_enabled_function_all and |
| method.runtime_enabled_function) %} |
| if ({{test}}) { |
| {% if method.is_custom %} |
| {{static_method_name(method.name)}}(args); |
| {% else %} |
| {{static_method_name(method.name, method.overload_index)}}(args); |
| {% endif %} |
| return; |
| } |
| {% endfilter %} |
| {% 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}}"; |
| exception = DartUtilities::coreArgumentErrorException(message); |
| goto fail; |
| } |
| {% endif %} |
| {# Otherwise just report "not enough arguments" #} |
| { |
| const String message = "Not enough arguments (at least {{overloads.minarg}} required)"; |
| exception = DartUtilities::coreArgumentErrorException(message); |
| goto fail; |
| } |
| return; |
| } |
| { |
| const String message = "No function was found that matched the signature provided."; |
| 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 %} |
| {% if cpp_class == "EventTarget" %} |
| {{cpp_class}}* receiver = DartDOMWrapper::receiverToEventTarget(args); |
| {% else %} |
| {{cpp_class}}* /* FIXME(vsm): Remove this. */ ALLOW_UNUSED receiver = DartDOMWrapper::receiver< {{cpp_class}} >(args); |
| {% endif %} |
| {% endif %} |
| {% if method.is_custom_element_callbacks %} |
| CustomElementCallbackDispatcher::CallbackDeliveryScope 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 = 0; |
| {% endif %} |
| { |
| {% if method.is_call_with_script_state %} |
| ScriptState* state = DartUtilities::currentScriptState(); |
| if (!state) { |
| exception = Dart_NewStringFromCString("Failed to retrieve a script state"); |
| goto fail; |
| } |
| {% endif %} |
| {% if method.is_call_with_execution_context %} |
| ExecutionContext* context = DartUtilities::scriptExecutionContext(); |
| if (!context) { |
| exception = Dart_NewStringFromCString("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 %} |
| DartExceptionState 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.hadException()) { |
| exception = es.toDart(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 -%} |
| {{dart_class}}::returnToDart(args, {{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 |
| argument.idl_type != 'Dictionary' 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}} = Dart{{argument.idl_type}}::createWithNullCheck(args, {{argument.arg_index}}, exception); |
| } |
| {% else %}{# argument.is_optional #} |
| {{argument.local_cpp_type}} {{argument.name}} = Dart{{argument.idl_type}}::createWithNullCheck(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_optional and argument.idl_type == 'Dictionary' %} |
| {{argument.local_cpp_type}} {{argument.name}}; |
| if (UNLIKELY(argCount <= {{argument.arg_index}})) { |
| {{argument.name}} = Dictionary(); |
| } else { |
| {{argument.name}} = {{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 (nf == {{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 = 0; |
| {% endif %} |
| { |
| {% if is_constructor_call_with_execution_context %} |
| ExecutionContext* context = DartUtilities::scriptExecutionContext(); |
| if (!context) { |
| exception = Dart_NewStringFromCString("Failed to retrieve a context"); |
| goto fail; |
| } |
| {% endif %} |
| {% if is_constructor_call_with_document or (constructor == named_constructor) %} |
| LocalDOMWindow* domWindow = DartUtilities::domWindowForCurrentIsolate(); |
| if (!domWindow) { |
| exception = Dart_NewStringFromCString("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 %} |
| DartExceptionState es; |
| {% endif %} |
| {{generate_arguments(constructor) | indent(8)}} |
| {{callback_return(constructor, constructor.dart_set_return_value, constructor.cpp_value) | indent(8)}} |
| {% if constructor.has_exception_state %} |
| if (es.hadException()) { |
| exception = es.toDart(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() %} |
| template <typename T> |
| static void convert(const String& idlType, Dart_Handle handle, bool nullable, T& value, Dart_Handle& exception) |
| { |
| value = DartUtilities::TypeConvertor<T>()(handle, exception); |
| } |
| |
| template <typename T> |
| static void convert(const String& idlType, Dart_Handle handle, bool nullable, RefPtr<T>& value, Dart_Handle& exception) |
| { |
| if (Dart_IsNull(handle)) |
| value = nullptr; |
| else |
| exception = Dart_NewStringFromCString("Event initialization unimplemented for non-primitive types"); |
| } |
| |
| template <typename T> |
| static void convert(const String& idlType, Dart_Handle handle, bool nullable, Member<T>& value, Dart_Handle& exception) |
| { |
| if (Dart_IsNull(handle)) |
| value = nullptr; |
| else |
| exception = Dart_NewStringFromCString("Event initialization unimplemented for non-primitive types"); |
| } |
| |
| void initialize{{interface_name}}ForDart({{interface_name}}Init& eventInit, const String& type, const HashMap<String, Dart_Handle>& options, Dart_Handle& exception) |
| { |
| {% if parent_interface %} |
| Dart{{parent_interface}}Internal::initialize{{parent_interface}}ForDart(eventInit, type, options, exception); |
| if (exception) |
| return; |
| {% endif %} |
| |
| {% for attribute in attributes |
| if (attribute.is_initialized_by_event_constructor and |
| not attribute.idl_type == 'any')%} |
| {% set is_nullable = 'true' if attribute.is_nullable else 'false' %} |
| if (options.contains("{{attribute.name}}")) { |
| Dart_Handle option = options.get("{{attribute.name}}"); |
| convert("{{attribute.idl_type}}", option, {{is_nullable}}, eventInit.{{attribute.cpp_name}}, exception); |
| if (exception) |
| return; |
| } |
| {% endfor %} |
| } |
| |
| static void eventConstructorCallback(Dart_NativeArguments args) |
| { |
| Dart_Handle exception = 0; |
| { |
| DartStringAdapter type = DartUtilities::dartToString(args, 0, exception); |
| if (exception) |
| goto fail; |
| |
| Dart_Handle handle = Dart_GetNativeArgument(args, 1); |
| HashMap<String, Dart_Handle> options; |
| DartUtilities::extractMapElements(handle, exception, options); |
| if (exception) |
| goto fail; |
| |
| {{interface_name}}Init eventInit; |
| initialize{{interface_name}}ForDart(eventInit, type, options, exception); |
| if (exception) |
| goto fail; |
| |
| {% if is_constructor_raises_exception %} |
| DartExceptionState es; |
| RefPtrWillBeRawPtr<{{interface_name}}> event = {{interface_name}}::create(type, eventInit, es); |
| if (es.hadException()) { |
| exception = es.toDart(args); |
| goto fail; |
| } |
| {% else %} |
| RefPtrWillBeRawPtr<{{interface_name}}> event = {{interface_name}}::create(type, eventInit); |
| {% endif %} |
| {{dart_class}}::returnToDart(args, event.get()); |
| return; |
| } |
| fail: |
| Dart_ThrowException(exception); |
| ASSERT_NOT_REACHED(); |
| } |
| {% endmacro %} |
| |
| , |
| {##############################################################################} |
| {% macro generate_resolver_constructor(dart_class, class_name, constructor) %} |
| {% for native_entry in constructor.native_entries %} |
| {% set resolver_string = native_entry.resolver_string %} |
| {% 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 == {{constructor.number_of_arguments}} && name == "{{resolver_string}}") { |
| {% else %} |
| if (argumentCount >= {{constructor.number_of_required_arguments}} && argumentCount <= {{constructor.number_of_arguments}} && 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 (nf == {{dart_class}}Internal::{{static_method_name(constructor.name, constructor.overload_index)}}) { |
| return reinterpret_cast<const uint8_t*>("{{resolver_string}}"); |
| } |
| {% endfor %} |
| {% endmacro %} |