# Copyright (C) 2013 Google Inc. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Generate template values for methods. Extends IdlType and IdlUnionType with property |union_arguments|. Design doc: http://www.chromium.org/developers/design-documents/idl-compiler """ from idl_types import inherits_interface import dart_types from dart_utilities import DartUtilities from v8_globals import includes import v8_methods def method_context(interface, method): context = v8_methods.method_context(interface, method) arguments = method.arguments extended_attributes = method.extended_attributes idl_type = method.idl_type # idl_type.add_includes_for_type() this_cpp_value = cpp_value(interface, method, len(arguments)) if context['is_call_with_script_state']: includes.add('bindings/core/dart/DartScriptState.h') if idl_type.union_arguments and len(idl_type.union_arguments) > 0: this_cpp_type = [] for cpp_type in idl_type.member_types: this_cpp_type.append("RefPtr<%s>" % cpp_type) else: this_cpp_type = idl_type.cpp_type is_auto_scope = not 'DartNoAutoScope' in extended_attributes arguments_data = [argument_context(interface, method, argument, index) for index, argument in enumerate(arguments)] union_arguments = [] if idl_type.union_arguments: union_arguments.extend([union_arg['cpp_value'] for union_arg in idl_type.union_arguments]) is_custom = 'Custom' in extended_attributes or 'DartCustom' in extended_attributes context.update({ 'arguments': arguments_data, 'cpp_type': this_cpp_type, 'cpp_value': this_cpp_value, 'dart_type': dart_types.idl_type_to_dart_type(idl_type), 'dart_name': extended_attributes.get('DartName'), 'has_exception_state': context['is_raises_exception'] or any(argument for argument in arguments if argument.idl_type.name == 'SerializedScriptValue' or argument.idl_type.is_integer_type), 'is_auto_scope': is_auto_scope, 'auto_scope': DartUtilities.bool_to_cpp(is_auto_scope), 'is_custom': is_custom, 'is_custom_dart': 'DartCustom' in extended_attributes, 'is_custom_dart_new': DartUtilities.has_extended_attribute_value(method, 'DartCustom', 'New'), # FIXME(terry): DartStrictTypeChecking no longer supported; TypeChecking is # new extended attribute. 'is_strict_type_checking': 'DartStrictTypeChecking' in extended_attributes or 'DartStrictTypeChecking' in interface.extended_attributes, 'union_arguments': union_arguments, 'dart_set_return_value': dart_set_return_value(interface.name, method, this_cpp_value), }) return context def argument_context(interface, method, argument, index): context = v8_methods.argument_context(interface, method, argument, index) extended_attributes = argument.extended_attributes idl_type = argument.idl_type this_cpp_value = cpp_value(interface, method, index) auto_scope = not 'DartNoAutoScope' in extended_attributes arg_index = index + 1 if not method.is_static else index preprocessed_type = str(idl_type.preprocessed_type) local_cpp_type = idl_type.cpp_type_args(argument.extended_attributes, raw_type=True) default_value = argument.default_cpp_value if context['has_default']: default_value = (argument.default_cpp_value or dart_types.default_cpp_value_for_cpp_type(idl_type)) dart_type = dart_types.idl_type_to_dart_type(idl_type) dart_default_value = dart_types.dart_default_value(dart_type, argument) context.update({ 'cpp_type': idl_type.cpp_type_args(extended_attributes=extended_attributes, raw_type=True, used_in_cpp_sequence=False), 'dart_type': dart_type, 'implemented_as': idl_type.implemented_as, 'cpp_value': this_cpp_value, 'local_cpp_type': local_cpp_type, # FIXME: check that the default value's type is compatible with the argument's 'default_value': default_value, 'is_named': 'Named' in extended_attributes, 'dart_default_value': dart_default_value, 'enum_validation_expression': idl_type.enum_validation_expression, 'preprocessed_type': preprocessed_type, 'is_array_or_sequence_type': not not idl_type.native_array_element_type, 'is_strict_type_checking': 'DartStrictTypeChecking' in extended_attributes, 'dart_set_return_value_for_main_world': dart_set_return_value(interface.name, method, this_cpp_value, for_main_world=True), 'dart_set_return_value': dart_set_return_value(interface.name, method, this_cpp_value), 'arg_index': arg_index, 'dart_value_to_local_cpp_value': dart_value_to_local_cpp_value(interface, context['has_type_checking_interface'], argument, arg_index, auto_scope), }) return context ################################################################################ # Value handling ################################################################################ def cpp_value(interface, method, number_of_arguments): def cpp_argument(argument): argument_name = dart_types.check_reserved_name(argument.name) idl_type = argument.idl_type if idl_type.is_typed_array_type: return '%s.get()' % argument_name # TODO(eseidel): This should check cpp_type.endswith('Handle') if idl_type.name == 'MojoDataPipeConsumer': return '%s.Pass()' % argument_name if idl_type.is_callback_interface: return '%s.release()' % argument_name return argument_name # Truncate omitted optional arguments arguments = method.arguments[:number_of_arguments] if method.is_constructor: call_with_values = interface.extended_attributes.get('ConstructorCallWith') else: call_with_values = method.extended_attributes.get('CallWith') cpp_arguments = DartUtilities.call_with_arguments(call_with_values) if ('PartialInterfaceImplementedAs' in method.extended_attributes and not method.is_static): cpp_arguments.append('*receiver') cpp_arguments.extend(cpp_argument(argument) for argument in arguments) this_union_arguments = method.idl_type and method.idl_type.union_arguments if this_union_arguments: cpp_arguments.extend([member_argument['cpp_value'] for member_argument in this_union_arguments]) if ('RaisesException' in method.extended_attributes or (method.is_constructor and DartUtilities.has_extended_attribute_value(interface, 'RaisesException', 'Constructor'))): cpp_arguments.append('es') if method.name == 'Constructor': base_name = 'create' elif method.name == 'NamedConstructor': base_name = 'createForJSConstructor' else: base_name = DartUtilities.cpp_name(method) cpp_method_name = DartUtilities.scoped_name(interface, method, base_name) return '%s(%s)' % (cpp_method_name, ', '.join(cpp_arguments)) def dart_set_return_value(interface_name, method, cpp_value, for_main_world=False): idl_type = method.idl_type extended_attributes = method.extended_attributes if not idl_type or idl_type.name == 'void': # Constructors and void methods don't have a return type return None release = False if idl_type.is_union_type: release = idl_type.release # [CallWith=ScriptState], [RaisesException] # TODO(terry): Disable ScriptState temporarily need to handle. # if (has_extended_attribute_value(method, 'CallWith', 'ScriptState') or # 'RaisesException' in extended_attributes or # idl_type.is_union_type): # cpp_value = 'result' # use local variable for value # release = idl_type.release auto_scope = not 'DartNoAutoScope' in extended_attributes script_wrappable = 'impl' if inherits_interface(interface_name, 'Node') else '' return idl_type.dart_set_return_value(cpp_value, extended_attributes, script_wrappable=script_wrappable, release=release, for_main_world=for_main_world, auto_scope=auto_scope) def dart_value_to_local_cpp_value(interface, has_type_checking_interface, argument, index, auto_scope=True): extended_attributes = argument.extended_attributes idl_type = argument.idl_type name = argument.name # TODO(ianh): why don't we need to null-check everything? # https://github.com/domokit/mojo/issues/280 null_check = ((argument.is_optional and idl_type.is_callback_interface) or (argument.default_value and argument.default_value.is_null)) return idl_type.dart_value_to_local_cpp_value( extended_attributes, name, null_check, has_type_checking_interface, index=index, auto_scope=auto_scope)