| OLD | NEW |
| (Empty) |
| 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 attributes. | |
| 30 | |
| 31 Extends IdlType with property |constructor_type_name|. | |
| 32 | |
| 33 Design doc: http://www.chromium.org/developers/design-documents/idl-compiler | |
| 34 """ | |
| 35 | |
| 36 import idl_types | |
| 37 from idl_types import inherits_interface | |
| 38 from v8_globals import includes, interfaces | |
| 39 import v8_types | |
| 40 import v8_utilities | |
| 41 from v8_utilities import (capitalize, cpp_name, has_extended_attribute, | |
| 42 has_extended_attribute_value, scoped_name, strip_suffi
x, | |
| 43 uncapitalize, extended_attribute_value_as_list) | |
| 44 | |
| 45 | |
| 46 def attribute_context(interface, attribute): | |
| 47 idl_type = attribute.idl_type | |
| 48 base_idl_type = idl_type.base_type | |
| 49 extended_attributes = attribute.extended_attributes | |
| 50 | |
| 51 idl_type.add_includes_for_type() | |
| 52 | |
| 53 # [CustomElementCallbacks], [Reflect] | |
| 54 is_custom_element_callbacks = 'CustomElementCallbacks' in extended_attribute
s | |
| 55 is_reflect = 'Reflect' in extended_attributes | |
| 56 if is_custom_element_callbacks or is_reflect: | |
| 57 includes.add('core/dom/custom/CustomElementProcessingStack.h') | |
| 58 # [TypeChecking] | |
| 59 has_type_checking_unrestricted = ( | |
| 60 (has_extended_attribute_value(interface, 'TypeChecking', 'Unrestricted')
or | |
| 61 has_extended_attribute_value(attribute, 'TypeChecking', 'Unrestricted')
) and | |
| 62 idl_type.name in ('Float', 'Double')) | |
| 63 | |
| 64 if (base_idl_type == 'EventHandler' and | |
| 65 interface.name in ['Window'] and | |
| 66 attribute.name == 'onerror'): | |
| 67 includes.add('bindings/core/v8/V8ErrorHandler.h') | |
| 68 | |
| 69 context = { | |
| 70 'argument_cpp_type': idl_type.cpp_type_args(used_as_rvalue_type=True), | |
| 71 'cached_attribute_validation_method': extended_attributes.get('CachedAtt
ribute'), | |
| 72 'constructor_type': idl_type.constructor_type_name | |
| 73 if is_constructor_attribute(attribute) else None, | |
| 74 'cpp_name': cpp_name(attribute), | |
| 75 'cpp_type': idl_type.cpp_type, | |
| 76 'cpp_type_initializer': idl_type.cpp_type_initializer, | |
| 77 'enum_validation_expression': idl_type.enum_validation_expression, | |
| 78 'exposed_test': v8_utilities.exposed(attribute, interface), # [Exposed] | |
| 79 'has_custom_getter': has_custom_getter(attribute), | |
| 80 'has_custom_setter': has_custom_setter(attribute), | |
| 81 'has_type_checking_unrestricted': has_type_checking_unrestricted, | |
| 82 'idl_type': str(idl_type), # need trailing [] on array for Dictionary::
ConversionContext::setConversionType | |
| 83 'is_call_with_execution_context': v8_utilities.has_extended_attribute_va
lue(attribute, 'CallWith', 'ExecutionContext'), | |
| 84 'is_call_with_script_state': v8_utilities.has_extended_attribute_value(a
ttribute, 'CallWith', 'ScriptState'), | |
| 85 'is_custom_element_callbacks': is_custom_element_callbacks, | |
| 86 'is_getter_raises_exception': # [RaisesException] | |
| 87 'RaisesException' in extended_attributes and | |
| 88 extended_attributes['RaisesException'] in (None, 'Getter'), | |
| 89 'is_initialized_by_event_constructor': | |
| 90 'InitializedByEventConstructor' in extended_attributes, | |
| 91 'is_keep_alive_for_gc': is_keep_alive_for_gc(interface, attribute), | |
| 92 'is_nullable': idl_type.is_nullable, | |
| 93 'is_explicit_nullable': idl_type.is_explicit_nullable, | |
| 94 'is_partial_interface_member': | |
| 95 'PartialInterfaceImplementedAs' in extended_attributes, | |
| 96 'is_read_only': attribute.is_read_only, | |
| 97 'is_reflect': is_reflect, | |
| 98 'is_replaceable': 'Replaceable' in attribute.extended_attributes, | |
| 99 'is_static': attribute.is_static, | |
| 100 'is_url': 'URL' in extended_attributes, | |
| 101 'name': attribute.name, | |
| 102 'put_forwards': 'PutForwards' in extended_attributes, | |
| 103 'reflect_empty': extended_attributes.get('ReflectEmpty'), | |
| 104 'reflect_invalid': extended_attributes.get('ReflectInvalid', ''), | |
| 105 'reflect_missing': extended_attributes.get('ReflectMissing'), | |
| 106 'reflect_only': extended_attribute_value_as_list(attribute, 'ReflectOnly
'), | |
| 107 'setter_callback': setter_callback_name(interface, attribute), | |
| 108 } | |
| 109 | |
| 110 if is_constructor_attribute(attribute): | |
| 111 constructor_getter_context(interface, attribute, context) | |
| 112 return context | |
| 113 if not has_custom_getter(attribute): | |
| 114 getter_context(interface, attribute, context) | |
| 115 if (not has_custom_setter(attribute) and | |
| 116 (not attribute.is_read_only or 'PutForwards' in extended_attributes)): | |
| 117 setter_context(interface, attribute, context) | |
| 118 | |
| 119 return context | |
| 120 | |
| 121 | |
| 122 ################################################################################ | |
| 123 # Getter | |
| 124 ################################################################################ | |
| 125 | |
| 126 def getter_context(interface, attribute, context): | |
| 127 cpp_value = getter_expression(interface, attribute, context) | |
| 128 | |
| 129 context.update({ | |
| 130 'cpp_value': cpp_value, | |
| 131 }) | |
| 132 | |
| 133 | |
| 134 def getter_expression(interface, attribute, context): | |
| 135 arguments = [] | |
| 136 this_getter_base_name = getter_base_name(interface, attribute, arguments) | |
| 137 getter_name = scoped_name(interface, attribute, this_getter_base_name) | |
| 138 | |
| 139 arguments.extend(v8_utilities.call_with_arguments( | |
| 140 attribute.extended_attributes.get('CallWith'))) | |
| 141 # Members of IDL partial interface definitions are implemented in C++ as | |
| 142 # static member functions, which for instance members (non-static members) | |
| 143 # take *impl as their first argument | |
| 144 if ('PartialInterfaceImplementedAs' in attribute.extended_attributes and | |
| 145 not attribute.is_static): | |
| 146 arguments.append('*impl') | |
| 147 if attribute.idl_type.is_explicit_nullable: | |
| 148 arguments.append('isNull') | |
| 149 if context['is_getter_raises_exception']: | |
| 150 arguments.append('exceptionState') | |
| 151 return '%s(%s)' % (getter_name, ', '.join(arguments)) | |
| 152 | |
| 153 | |
| 154 CONTENT_ATTRIBUTE_GETTER_NAMES = { | |
| 155 'boolean': 'hasAttribute', | |
| 156 'long': 'getIntegralAttribute', | |
| 157 'unsigned long': 'getUnsignedIntegralAttribute', | |
| 158 } | |
| 159 | |
| 160 | |
| 161 def getter_base_name(interface, attribute, arguments): | |
| 162 extended_attributes = attribute.extended_attributes | |
| 163 | |
| 164 if 'Reflect' not in extended_attributes: | |
| 165 return uncapitalize(cpp_name(attribute)) | |
| 166 | |
| 167 content_attribute_name = extended_attributes['Reflect'] or attribute.name.lo
wer() | |
| 168 if content_attribute_name in ['class', 'id']: | |
| 169 # Special-case for performance optimization. | |
| 170 return 'get%sAttribute' % content_attribute_name.capitalize() | |
| 171 | |
| 172 arguments.append(scoped_content_attribute_name(interface, attribute)) | |
| 173 | |
| 174 base_idl_type = attribute.idl_type.base_type | |
| 175 if base_idl_type in CONTENT_ATTRIBUTE_GETTER_NAMES: | |
| 176 return CONTENT_ATTRIBUTE_GETTER_NAMES[base_idl_type] | |
| 177 if 'URL' in attribute.extended_attributes: | |
| 178 return 'getURLAttribute' | |
| 179 return 'getAttribute' | |
| 180 | |
| 181 | |
| 182 def is_keep_alive_for_gc(interface, attribute): | |
| 183 idl_type = attribute.idl_type | |
| 184 base_idl_type = idl_type.base_type | |
| 185 extended_attributes = attribute.extended_attributes | |
| 186 return ( | |
| 187 # For readonly attributes, for performance reasons we keep the attribute | |
| 188 # wrapper alive while the owner wrapper is alive, because the attribute | |
| 189 # never changes. | |
| 190 (attribute.is_read_only and | |
| 191 idl_type.is_wrapper_type and | |
| 192 # There are some exceptions, however: | |
| 193 not( | |
| 194 # Node lifetime is managed by object grouping. | |
| 195 inherits_interface(interface.name, 'Node') or | |
| 196 inherits_interface(base_idl_type, 'Node') or | |
| 197 # A self-reference is unnecessary. | |
| 198 attribute.name == 'self' or | |
| 199 # FIXME: Remove these hard-coded hacks. | |
| 200 base_idl_type in ['EventTarget', 'Window'] or | |
| 201 base_idl_type.startswith('HTML')))) | |
| 202 | |
| 203 | |
| 204 ################################################################################ | |
| 205 # Setter | |
| 206 ################################################################################ | |
| 207 | |
| 208 def setter_context(interface, attribute, context): | |
| 209 if 'PutForwards' in attribute.extended_attributes: | |
| 210 # Use target interface and attribute in place of original interface and | |
| 211 # attribute from this point onwards. | |
| 212 target_interface_name = attribute.idl_type.base_type | |
| 213 target_attribute_name = attribute.extended_attributes['PutForwards'] | |
| 214 interface = interfaces[target_interface_name] | |
| 215 try: | |
| 216 attribute = next(candidate | |
| 217 for candidate in interface.attributes | |
| 218 if candidate.name == target_attribute_name) | |
| 219 except StopIteration: | |
| 220 raise Exception('[PutForward] target not found:\n' | |
| 221 'Attribute "%s" is not present in interface "%s"' % | |
| 222 (target_attribute_name, target_interface_name)) | |
| 223 | |
| 224 extended_attributes = attribute.extended_attributes | |
| 225 idl_type = attribute.idl_type | |
| 226 | |
| 227 # [RaisesException], [RaisesException=Setter] | |
| 228 is_setter_raises_exception = ( | |
| 229 'RaisesException' in extended_attributes and | |
| 230 extended_attributes['RaisesException'] in [None, 'Setter']) | |
| 231 # [TypeChecking=Interface] | |
| 232 has_type_checking_interface = ( | |
| 233 (has_extended_attribute_value(interface, 'TypeChecking', 'Interface') or | |
| 234 has_extended_attribute_value(attribute, 'TypeChecking', 'Interface')) a
nd | |
| 235 idl_type.is_wrapper_type) | |
| 236 | |
| 237 context.update({ | |
| 238 'has_setter_exception_state': | |
| 239 is_setter_raises_exception or has_type_checking_interface or | |
| 240 context['has_type_checking_unrestricted'] or | |
| 241 idl_type.may_raise_exception_on_conversion, | |
| 242 'has_type_checking_interface': has_type_checking_interface, | |
| 243 'is_setter_call_with_execution_context': v8_utilities.has_extended_attri
bute_value( | |
| 244 attribute, 'SetterCallWith', 'ExecutionContext'), | |
| 245 'is_setter_raises_exception': is_setter_raises_exception, | |
| 246 }) | |
| 247 | |
| 248 | |
| 249 CONTENT_ATTRIBUTE_SETTER_NAMES = { | |
| 250 'boolean': 'setBooleanAttribute', | |
| 251 'long': 'setIntegralAttribute', | |
| 252 'unsigned long': 'setUnsignedIntegralAttribute', | |
| 253 } | |
| 254 | |
| 255 | |
| 256 def setter_base_name(interface, attribute, arguments): | |
| 257 if 'Reflect' not in attribute.extended_attributes: | |
| 258 return 'set%s' % capitalize(cpp_name(attribute)) | |
| 259 arguments.append(scoped_content_attribute_name(interface, attribute)) | |
| 260 | |
| 261 base_idl_type = attribute.idl_type.base_type | |
| 262 if base_idl_type in CONTENT_ATTRIBUTE_SETTER_NAMES: | |
| 263 return CONTENT_ATTRIBUTE_SETTER_NAMES[base_idl_type] | |
| 264 return 'setAttribute' | |
| 265 | |
| 266 | |
| 267 def scoped_content_attribute_name(interface, attribute): | |
| 268 content_attribute_name = attribute.extended_attributes['Reflect'] or attribu
te.name.lower() | |
| 269 namespace = 'HTMLNames' | |
| 270 includes.add('gen/sky/core/%s.h' % namespace) | |
| 271 return '%s::%sAttr' % (namespace, content_attribute_name) | |
| 272 | |
| 273 | |
| 274 ################################################################################ | |
| 275 # Attribute configuration | |
| 276 ################################################################################ | |
| 277 | |
| 278 # [Replaceable] | |
| 279 def setter_callback_name(interface, attribute): | |
| 280 cpp_class_name = cpp_name(interface) | |
| 281 extended_attributes = attribute.extended_attributes | |
| 282 if (('Replaceable' in extended_attributes and | |
| 283 'PutForwards' not in extended_attributes) or | |
| 284 is_constructor_attribute(attribute)): | |
| 285 return '{0}V8Internal::{0}ForceSetAttributeOnThisCallback'.format(cpp_cl
ass_name) | |
| 286 if attribute.is_read_only and 'PutForwards' not in extended_attributes: | |
| 287 return '0' | |
| 288 return '%sV8Internal::%sAttributeSetterCallback' % (cpp_class_name, attribut
e.name) | |
| 289 | |
| 290 | |
| 291 # [Custom], [Custom=Getter] | |
| 292 def has_custom_getter(attribute): | |
| 293 extended_attributes = attribute.extended_attributes | |
| 294 return ('Custom' in extended_attributes and | |
| 295 extended_attributes['Custom'] in [None, 'Getter']) | |
| 296 | |
| 297 | |
| 298 # [Custom], [Custom=Setter] | |
| 299 def has_custom_setter(attribute): | |
| 300 extended_attributes = attribute.extended_attributes | |
| 301 return (not attribute.is_read_only and | |
| 302 'Custom' in extended_attributes and | |
| 303 extended_attributes['Custom'] in [None, 'Setter']) | |
| 304 | |
| 305 | |
| 306 ################################################################################ | |
| 307 # Constructors | |
| 308 ################################################################################ | |
| 309 | |
| 310 idl_types.IdlType.constructor_type_name = property( | |
| 311 # FIXME: replace this with a [ConstructorAttribute] extended attribute | |
| 312 lambda self: strip_suffix(self.base_type, 'Constructor')) | |
| 313 | |
| 314 | |
| 315 def is_constructor_attribute(attribute): | |
| 316 # FIXME: replace this with [ConstructorAttribute] extended attribute | |
| 317 return attribute.idl_type.name.endswith('Constructor') | |
| OLD | NEW |