1# Copyright (C) 2013 Google Inc. All rights reserved. 2# 3# Redistribution and use in source and binary forms, with or without 4# modification, are permitted provided that the following conditions are 5# met: 6# 7# * Redistributions of source code must retain the above copyright 8# notice, this list of conditions and the following disclaimer. 9# * Redistributions in binary form must reproduce the above 10# copyright notice, this list of conditions and the following disclaimer 11# in the documentation and/or other materials provided with the 12# distribution. 13# * Neither the name of Google Inc. nor the names of its 14# contributors may be used to endorse or promote products derived from 15# this software without specific prior written permission. 16# 17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29"""Generate template values for a callback interface. 30 31FIXME: Not currently used in build. 32This is a rewrite of the Perl IDL compiler in Python, but is not complete. 33Once it is complete, we will switch all IDL files over to Python at once. 34Until then, please work on the Perl IDL compiler. 35For details, see bug http://crbug.com/239771 36""" 37 38from v8_globals import includes 39import v8_types 40import v8_utilities 41 42CALLBACK_INTERFACE_H_INCLUDES = set([ 43 'bindings/v8/ActiveDOMCallback.h', 44 'bindings/v8/DOMWrapperWorld.h', 45 'bindings/v8/ScopedPersistent.h', 46]) 47CALLBACK_INTERFACE_CPP_INCLUDES = set([ 48 'bindings/v8/V8Binding.h', 49 'bindings/v8/V8Callback.h', 50 'core/dom/ExecutionContext.h', 51 'wtf/Assertions.h', 52]) 53 54 55def cpp_to_v8_conversion(idl_type, name): 56 # FIXME: setting creation_context=v8::Handle<v8::Object>() is wrong, 57 # as toV8 then implicitly uses the current context, which causes leaks 58 # between isolate worlds if a different context should be used. 59 cpp_value_to_v8_value = v8_types.cpp_value_to_v8_value(idl_type, name, 60 isolate='isolate', creation_context='v8::Handle<v8::Object>()') 61 return 'v8::Handle<v8::Value> {name}Handle = {cpp_to_v8};'.format( 62 name=name, cpp_to_v8=cpp_value_to_v8_value) 63 64 65def cpp_type(idl_type): 66 # FIXME: remove this function by making callback types consistent 67 # (always use usual v8_types.cpp_type) 68 if idl_type == 'DOMString': 69 return 'const String&' 70 if idl_type == 'void': 71 return 'void' 72 # Callbacks use raw pointers, so used_as_argument=True 73 usual_cpp_type = v8_types.cpp_type(idl_type, used_as_argument=True) 74 if usual_cpp_type.startswith('Vector'): 75 return 'const %s&' % usual_cpp_type 76 return usual_cpp_type 77 78 79def generate_callback_interface(callback_interface): 80 includes.clear() 81 includes.update(CALLBACK_INTERFACE_CPP_INCLUDES) 82 name = callback_interface.name 83 84 methods = [generate_method(operation) 85 for operation in callback_interface.operations] 86 template_contents = { 87 'conditional_string': v8_utilities.conditional_string(callback_interface), 88 'cpp_class': name, 89 'v8_class': v8_utilities.v8_class_name(callback_interface), 90 'header_includes': CALLBACK_INTERFACE_H_INCLUDES, 91 'methods': methods, 92 } 93 return template_contents 94 95 96def add_includes_for_operation(operation): 97 v8_types.add_includes_for_type(operation.idl_type) 98 for argument in operation.arguments: 99 v8_types.add_includes_for_type(argument.idl_type) 100 101 102def generate_method(operation): 103 extended_attributes = operation.extended_attributes 104 idl_type = operation.idl_type 105 if idl_type not in ['boolean', 'void']: 106 raise Exception('We only support callbacks that return boolean or void values.') 107 is_custom = 'Custom' in extended_attributes 108 if not is_custom: 109 add_includes_for_operation(operation) 110 call_with = extended_attributes.get('CallWith') 111 call_with_this_handle = v8_utilities.extended_attribute_value_contains(call_with, 'ThisValue') 112 contents = { 113 'call_with_this_handle': call_with_this_handle, 114 'custom': is_custom, 115 'name': operation.name, 116 'return_cpp_type': cpp_type(idl_type), 117 'return_idl_type': idl_type, 118 } 119 contents.update(generate_arguments_contents(operation.arguments, call_with_this_handle)) 120 return contents 121 122 123def generate_arguments_contents(arguments, call_with_this_handle): 124 def generate_argument(argument): 125 return { 126 'name': argument.name, 127 'cpp_to_v8_conversion': cpp_to_v8_conversion(argument.idl_type, argument.name), 128 } 129 130 argument_declarations = [ 131 '%s %s' % (cpp_type(argument.idl_type), argument.name) 132 for argument in arguments] 133 if call_with_this_handle: 134 argument_declarations.insert(0, 'ScriptValue thisValue') 135 return { 136 'argument_declarations': argument_declarations, 137 'arguments': [generate_argument(argument) for argument in arguments], 138 'handles': ['%sHandle' % argument.name for argument in arguments], 139 } 140