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 methods. 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 41from v8_utilities import has_extended_attribute_value 42 43 44def generate_method(interface, method): 45 arguments = method.arguments 46 extended_attributes = method.extended_attributes 47 idl_type = method.idl_type 48 is_static = method.is_static 49 name = method.name 50 51 this_cpp_value = cpp_value(interface, method, len(arguments)) 52 this_custom_signature = custom_signature(method, arguments) 53 54 def function_template(): 55 if is_static: 56 return 'functionTemplate' 57 if 'Unforgeable' in extended_attributes: 58 return 'instanceTemplate' 59 return 'prototypeTemplate' 60 61 def signature(): 62 if this_custom_signature: 63 return name + 'Signature' 64 if is_static or 'DoNotCheckSignature' in extended_attributes: 65 return 'v8::Local<v8::Signature>()' 66 return 'defaultSignature' 67 68 is_call_with_script_arguments = has_extended_attribute_value(method, 'CallWith', 'ScriptArguments') 69 if is_call_with_script_arguments: 70 includes.update(['bindings/v8/ScriptCallStackFactory.h', 71 'core/inspector/ScriptArguments.h']) 72 is_call_with_script_state = has_extended_attribute_value(method, 'CallWith', 'ScriptState') 73 if is_call_with_script_state: 74 includes.add('bindings/v8/ScriptState.h') 75 is_check_security_for_node = 'CheckSecurity' in extended_attributes 76 if is_check_security_for_node: 77 includes.add('bindings/v8/BindingSecurity.h') 78 is_custom_element_callbacks = 'CustomElementCallbacks' in extended_attributes 79 if is_custom_element_callbacks: 80 includes.add('core/dom/custom/CustomElementCallbackDispatcher.h') 81 82 contents = { 83 'activity_logging_world_list': v8_utilities.activity_logging_world_list(method), # [ActivityLogging] 84 'arguments': [generate_argument(interface, method, argument, index) 85 for index, argument in enumerate(arguments)], 86 'conditional_string': v8_utilities.conditional_string(method), 87 'cpp_type': v8_types.cpp_type(idl_type), 88 'cpp_value': this_cpp_value, 89 'custom_signature': this_custom_signature, 90 'deprecate_as': v8_utilities.deprecate_as(method), # [DeprecateAs] 91 'do_not_check_signature': not(this_custom_signature or is_static or 92 v8_utilities.has_extended_attribute(method, 93 ['DoNotCheckSecurity', 'DoNotCheckSignature', 'NotEnumerable', 94 'ReadOnly', 'RuntimeEnabled', 'Unforgeable'])), 95 'function_template': function_template(), 96 'idl_type': idl_type, 97 'is_call_with_execution_context': has_extended_attribute_value(method, 'CallWith', 'ExecutionContext'), 98 'is_call_with_script_arguments': is_call_with_script_arguments, 99 'is_call_with_script_state': is_call_with_script_state, 100 'is_check_security_for_frame': ( 101 'CheckSecurity' in interface.extended_attributes and 102 'DoNotCheckSecurity' not in extended_attributes), 103 'is_check_security_for_node': is_check_security_for_node, 104 'is_custom': 'Custom' in extended_attributes, 105 'is_custom_element_callbacks': is_custom_element_callbacks, 106 'is_do_not_check_security': 'DoNotCheckSecurity' in extended_attributes, 107 'is_per_world_bindings': 'PerWorldBindings' in extended_attributes, 108 'is_raises_exception': 'RaisesException' in extended_attributes, 109 'is_read_only': 'ReadOnly' in extended_attributes, 110 'is_static': is_static, 111 'is_strict_type_checking': 'StrictTypeChecking' in extended_attributes, 112 'is_variadic': arguments and arguments[-1].is_variadic, 113 'measure_as': v8_utilities.measure_as(method), # [MeasureAs] 114 'name': name, 115 'number_of_arguments': len(arguments), 116 'number_of_required_arguments': len([ 117 argument for argument in arguments 118 if not (argument.is_optional or argument.is_variadic)]), 119 'number_of_required_or_variadic_arguments': len([ 120 argument for argument in arguments 121 if not argument.is_optional]), 122 'per_context_enabled_function': v8_utilities.per_context_enabled_function_name(method), # [PerContextEnabled] 123 'property_attributes': property_attributes(method), 124 'runtime_enabled_function': v8_utilities.runtime_enabled_function_name(method), # [RuntimeEnabled] 125 'signature': signature(), 126 'v8_set_return_value': v8_set_return_value(method, this_cpp_value), 127 'world_suffixes': ['', 'ForMainWorld'] if 'PerWorldBindings' in extended_attributes else [''], # [PerWorldBindings] 128 } 129 return contents 130 131 132def generate_argument(interface, method, argument, index): 133 extended_attributes = argument.extended_attributes 134 idl_type = argument.idl_type 135 this_cpp_value = cpp_value(interface, method, index) 136 return { 137 'cpp_type': v8_types.cpp_type(idl_type), 138 'cpp_value': this_cpp_value, 139 'enum_validation_expression': v8_utilities.enum_validation_expression(idl_type), 140 'has_default': 'Default' in extended_attributes, 141 'idl_type': idl_type, 142 'index': index, 143 'is_clamp': 'Clamp' in extended_attributes, 144 'is_nullable': argument.is_nullable, 145 'is_optional': argument.is_optional, 146 'is_strict_type_checking': 'StrictTypeChecking' in extended_attributes, 147 'is_variadic_wrapper_type': argument.is_variadic and v8_types.is_wrapper_type(idl_type), 148 'is_wrapper_type': v8_types.is_wrapper_type(idl_type), 149 'name': argument.name, 150 'v8_set_return_value': v8_set_return_value(method, this_cpp_value), 151 'v8_value_to_local_cpp_value': v8_value_to_local_cpp_value(argument, index), 152 } 153 154 155def cpp_value(interface, method, number_of_arguments): 156 def cpp_argument(argument): 157 if argument.idl_type in ['NodeFilter', 'XPathNSResolver']: 158 # FIXME: remove this special case 159 return '%s.release()' % argument.name 160 return argument.name 161 162 # Truncate omitted optional arguments 163 arguments = method.arguments[:number_of_arguments] 164 cpp_arguments = v8_utilities.call_with_arguments(method) 165 cpp_arguments.extend(cpp_argument(argument) for argument in arguments) 166 if 'RaisesException' in method.extended_attributes: 167 cpp_arguments.append('exceptionState') 168 169 cpp_method_name = v8_utilities.scoped_name(interface, method, v8_utilities.cpp_name(method)) 170 return '%s(%s)' % (cpp_method_name, ', '.join(cpp_arguments)) 171 172 173def v8_set_return_value(method, cpp_value): 174 idl_type = method.idl_type 175 if idl_type == 'void': 176 return None 177 # [CallWith=ScriptState] 178 if has_extended_attribute_value(method, 'CallWith', 'ScriptState'): 179 cpp_value = 'result' # use local variable for value 180 return v8_types.v8_set_return_value(idl_type, cpp_value, method.extended_attributes) 181 182 183def custom_signature(method, arguments): 184 def argument_template(argument): 185 idl_type = argument.idl_type 186 if (v8_types.is_wrapper_type(idl_type) and 187 not v8_types.is_typed_array_type(idl_type) and 188 # Compatibility: all other browsers accepts a callable for 189 # XPathNSResolver, despite it being against spec. 190 not idl_type == 'XPathNSResolver'): 191 return 'V8PerIsolateData::from(isolate)->rawDOMTemplate(&V8{idl_type}::wrapperTypeInfo, currentWorldType)'.format(idl_type=idl_type) 192 return 'v8::Handle<v8::FunctionTemplate>()' 193 194 if (any(argument.is_optional and 195 'Default' not in argument.extended_attributes 196 for argument in arguments) or 197 all(not v8_types.is_wrapper_type(argument.idl_type) 198 for argument in arguments) or 199 # For [StrictTypeChecking], type checking is done in the generated code 200 'StrictTypeChecking' in method.extended_attributes): 201 return None 202 return ', '.join([argument_template(argument) for argument in arguments]) 203 204 205# [NotEnumerable] 206def property_attributes(method): 207 extended_attributes = method.extended_attributes 208 property_attributes_list = [] 209 if 'NotEnumerable' in extended_attributes: 210 property_attributes_list.append('v8::DontEnum') 211 if 'ReadOnly' in extended_attributes: 212 property_attributes_list.append('v8::ReadOnly') 213 if property_attributes_list: 214 property_attributes_list.insert(0, 'v8::DontDelete') 215 return property_attributes_list 216 217 218def v8_value_to_local_cpp_value(argument, index): 219 extended_attributes = argument.extended_attributes 220 idl_type = argument.idl_type 221 name = argument.name 222 if argument.is_variadic: 223 return 'V8TRYCATCH_VOID(Vector<{cpp_type}>, {name}, toNativeArguments<{cpp_type}>(info, {index}))'.format( 224 cpp_type=v8_types.cpp_type(idl_type), name=name, index=index) 225 # [Default=NullString] 226 if (argument.is_optional and idl_type == 'DOMString' and 227 extended_attributes.get('Default') == 'NullString'): 228 v8_value = 'argumentOrNull(info, %s)' % index 229 else: 230 v8_value = 'info[%s]' % index 231 return v8_types.v8_value_to_local_cpp_value( 232 idl_type, argument.extended_attributes, v8_value, name, index=index) 233