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 FIXME: rename "parameter/parameters": |
| 32 "template parameters" is easily confused with "function parameters" |
| 33 Also, "parameter*s*", not "parameter". |
| 34 """ |
| 35 |
| 36 import v8_types |
| 37 from v8_types import cpp_type, v8_type |
| 38 from v8_utilities import generate_conditional_string, implemented_as_cpp_name, u
ncapitalize |
| 39 import v8_values |
| 40 |
| 41 # WIP |
| 42 import re |
| 43 |
| 44 from code_generator_idl_reader import inherits_interface, implemented_as_from_im
plemented_by |
| 45 from v8_includes import * |
| 46 from v8_types import * |
| 47 from v8_utilities import capitalize, runtime_enable_function_name, strip_suffix |
| 48 from v8_utilities import ACTIVITY_LOGGING_INCLUDES, get_call_with_parameter, get
_custom_element_invocation_scope_parameter, get_feature_observation_parameter, g
et_deprecation_notification_parameter, has_activity_logging |
| 49 from v8_values import get_js_value_to_native_statement, get_native_to_js_value_s
tatement, get_pass_owner_expression |
| 50 |
| 51 |
| 52 def generate_attributes(interface): |
| 53 def generate_attribute(attribute): |
| 54 attribute_contents, attribute_includes = generate_attribute_and_includes
(interface, attribute) |
| 55 includes.update(attribute_includes) |
| 56 return attribute_contents |
| 57 |
| 58 includes = set() |
| 59 contents = generate_attributes_common(interface) |
| 60 contents['attributes'] = [generate_attribute(attribute) for attribute in int
erface.attributes] |
| 61 return contents, includes |
| 62 |
| 63 |
| 64 def generate_attributes_common(interface): |
| 65 attributes = interface.attributes |
| 66 v8_class_name = v8_types.get_v8_class_name(interface) |
| 67 return { |
| 68 # Size 0 constant array is not allowed in VC++ |
| 69 # FIXME: rename Attrs to Attributes |
| 70 'number_of_attributes': 'WTF_ARRAY_LENGTH(%sAttrs)' % v8_class_name if a
ttributes else '0', |
| 71 'attribute_templates': v8_class_name + 'Attrs' if attributes else '0', |
| 72 } |
| 73 |
| 74 |
| 75 def generate_attribute_and_includes(interface, attribute): |
| 76 data_type = attribute.data_type |
| 77 # FIXME: need to check should_keep_attribute_alive, but for now sufficient |
| 78 # to check if primitive. |
| 79 should_keep_attribute_alive = not v8_types.primitive_type(data_type) |
| 80 # FIXME: eliminate should_keep_attribute_alive |
| 81 if should_keep_attribute_alive: |
| 82 return_js_value_statement = None # unused |
| 83 includes = includes_for_type(data_type) |
| 84 includes.add('bindings/v8/V8HiddenPropertyName.h') |
| 85 else: |
| 86 cpp_value = getter_expression(interface, attribute) |
| 87 return_js_value_statement = v8_values.cpp_value_to_js_value_return(data_
type, cpp_value, callback_info='info') |
| 88 includes = [] |
| 89 contents = { |
| 90 'name': attribute.name, |
| 91 'conditional_string': generate_conditional_string(attribute), |
| 92 'cpp_method_name': implemented_as_cpp_name(attribute), |
| 93 'cpp_type': cpp_type(data_type, pointer_type='RefPtr'), |
| 94 'should_keep_attribute_alive': should_keep_attribute_alive, |
| 95 'return_js_value_statement': return_js_value_statement, |
| 96 'v8_type': v8_type(data_type), |
| 97 } |
| 98 return contents, includes |
| 99 |
| 100 |
| 101 def getter_expression(interface, attribute): |
| 102 # FIXME: very incomplete |
| 103 return 'imp->%s()' % uncapitalize(attribute.name) |
| 104 |
| 105 |
| 106 ################################################################################ |
| 107 # WIP |
| 108 ################################################################################ |
| 109 |
| 110 |
| 111 def generate_attributes_wip(interface): |
| 112 def generate_attribute(attribute): |
| 113 attribute_contents, attribute_includes = generate_attribute_and_includes
_wip(interface, attribute) |
| 114 includes.extend(attribute_includes) |
| 115 return attribute_contents |
| 116 |
| 117 includes = [] |
| 118 contents = [generate_attribute(attribute) for attribute in interface.attribu
tes] |
| 119 return contents, includes |
| 120 |
| 121 |
| 122 def generate_attribute_and_includes_wip(interface, attribute): |
| 123 cpp_class_name = implemented_as_cpp_name(interface) |
| 124 per_world_bindings = 'PerWorldBindings' in attribute.extended_attributes |
| 125 for_main_world_suffixes = [''] |
| 126 if per_world_bindings: |
| 127 for_main_world_suffixes.append('ForMainWorld') |
| 128 |
| 129 includes = [] |
| 130 # print |
| 131 # print '#'*30 |
| 132 # print '[get_attribute_parameter] ', attribute.data_type, attribute.name |
| 133 |
| 134 check_security_for_node = 'CheckSecurityForNode' in attribute.extended_attri
butes |
| 135 if check_security_for_node: |
| 136 includes.append('bindings/v8/BindingSecurity.h') |
| 137 if attribute.data_type == 'SerializedScriptValue': |
| 138 includes.append('bindings/v8/SerializedScriptValue.h') |
| 139 |
| 140 getter_activity_logging = set() |
| 141 for for_main_world_suffix in for_main_world_suffixes: |
| 142 if has_activity_logging(for_main_world_suffix, attribute.extended_attrib
utes, 'Getter'): |
| 143 getter_activity_logging.add(for_main_world_suffix) |
| 144 includes += ACTIVITY_LOGGING_INCLUDES |
| 145 |
| 146 custom_element_invocation_scope_parameter, custom_element_invocation_scope_i
ncludes = get_custom_element_invocation_scope_parameter(attribute) |
| 147 includes += custom_element_invocation_scope_includes |
| 148 # print '[[]]', custom_element_invocation_scope_parameter |
| 149 |
| 150 enable_function = runtime_enable_function_name(attribute) |
| 151 |
| 152 replaceable = 'Replaceable' in attribute.extended_attributes |
| 153 custom_getter = has_custom_getter(attribute) |
| 154 custom_setter = has_custom_setter(attribute) |
| 155 has_replaceable = not custom_setter and replaceable |
| 156 has_normal_setter = (custom_setter or not has_replaceable) and not is_read_o
nly(attribute) |
| 157 |
| 158 should_keep_attribute_alive = get_should_keep_attribute_alive(interface, att
ribute) |
| 159 # print '[] should_keep_attribute_alive', should_keep_attribute_alive |
| 160 |
| 161 native_type = '' |
| 162 array_type = '' |
| 163 if not custom_getter: |
| 164 native_type = get_native_type(attribute.data_type, extended_attributes=a
ttribute.extended_attributes) |
| 165 # currently array_type is always False |
| 166 array_type = get_array_type(native_type) |
| 167 if should_keep_attribute_alive: |
| 168 if array_type: |
| 169 includes.append('V8%s.h' % array_type) |
| 170 else: |
| 171 includes += get_includes_for_type(attribute.data_type) |
| 172 includes.append('bindings/v8/V8HiddenPropertyName.h') |
| 173 if (setter_use_exception(attribute) and not custom_setter) or getter_use
_exception(attribute): |
| 174 includes.append('bindings/v8/ExceptionState.h') |
| 175 |
| 176 batched_attribute, batched_attribute_includes = generate_batched_attribute(i
nterface, attribute, ',') |
| 177 includes += batched_attribute_includes |
| 178 |
| 179 enabled_at_runtime = False |
| 180 enabled_per_context = False |
| 181 if interface.name == 'Window' and 'Unforgeable' in attribute.extended_attrib
utes: |
| 182 pass |
| 183 elif 'EnabledPerContext' in attribute.extended_attributes: |
| 184 enabled_per_context = True |
| 185 elif 'EnabledAtRuntime' in attribute.extended_attributes: |
| 186 enabled_at_runtime = True |
| 187 else: |
| 188 pass |
| 189 |
| 190 if enabled_at_runtime: |
| 191 batched_attribute, batched_attribute_includes = generate_batched_attribu
te(interface, attribute, ';') |
| 192 includes += batched_attribute_includes |
| 193 |
| 194 compact_getter = 'Reflect' in attribute.extended_attributes and 'URL' not in
attribute.extended_attributes and inherits_interface(interface, 'Node') and att
ribute.data_type == 'DOMString' |
| 195 compact_setter = 'Reflect' in attribute.extended_attributes and inherits_int
erface(interface, 'Node') and attribute.data_type == 'DOMString' |
| 196 compact_setter_namespace = '' |
| 197 compact_setter_content_attribute_name = '' |
| 198 if compact_setter: |
| 199 compact_setter_content_attribute_name = attribute.name.lower() |
| 200 if attribute.extended_attributes.get('Reflect'): |
| 201 compact_setter_content_attribute_name = attribute.extended_attribute
s.get('Reflect') |
| 202 compact_setter_namespace = namespace_for_attribute_name(interface.name,
compact_setter_content_attribute_name) |
| 203 includes.append('%s.h' % compact_setter_namespace) |
| 204 |
| 205 feature_observation_parameter, feature_observation_includes = get_feature_ob
servation_parameter(interface) |
| 206 includes += feature_observation_includes |
| 207 deprecation_notification_parameter, deprecation_notification_includes = get_
deprecation_notification_parameter(attribute) |
| 208 includes += deprecation_notification_includes |
| 209 |
| 210 getter_function = '' |
| 211 event_listener_setter_function_name = '' |
| 212 event_listener_setter_function_name_not_inherits_node = '' |
| 213 not_inherits_node = False |
| 214 if attribute.data_type == 'EventListener': |
| 215 # FIXME: Pass the main world ID for main-world-only getters. |
| 216 includes.append('bindings/v8/V8AbstractEventListener.h') |
| 217 includes.append('bindings/v8/V8EventListenerList.h') |
| 218 getter_function = uncapitalize(attribute.name) |
| 219 event_listener_setter_function_name = capitalize(attribute.name) |
| 220 not_inherits_node = not inherits_interface(interface, 'Node') |
| 221 if not_inherits_node: |
| 222 event_listener_setter_function_name_not_inherits_node = implemented_
as_cpp_name(attribute) |
| 223 event_listener_on_error = (interface.name == 'Window' or interface.name
== 'WorkerGlobalScope') and attribute.name == 'onerror' |
| 224 if event_listener_on_error: |
| 225 includes.append('bindings/v8/V8ErrorHandler.h') |
| 226 |
| 227 svg_animated_type = is_svg_animated_type(interface.name) |
| 228 svg_type_needing_tear_off = get_svg_type_needing_tear_off(attribute.data_typ
e) |
| 229 |
| 230 ##################### Getter |
| 231 getter_native_value_expression, getter_function_call_parameter, getter_inclu
des = get_attribute_function_call_expression(interface, attribute) |
| 232 includes += getter_includes |
| 233 # print '[]', getter_native_value_expression |
| 234 |
| 235 tear_off_and_not_list = svg_type_needing_tear_off and not interface.name.end
swith('List') |
| 236 |
| 237 wrapped_value = '' |
| 238 return_js_value_statements = {} |
| 239 assign_native_value_to_local_variable_statement = '' |
| 240 if not custom_getter: |
| 241 if (svg_animated_type or interface.name == 'SVGViewSpec') and svg_type_n
eeding_tear_off: |
| 242 includes.append('V8%s.h' % attribute.data_type) |
| 243 elif tear_off_and_not_list: |
| 244 includes.append('V8%s.h' % attribute.data_type) |
| 245 includes.append('core/svg/properties/SVGPropertyTearOff.h') |
| 246 if svg_type_with_writable_properties_needing_tear_off(attribute.data
_type) and 'Immutable' not in attribute.extended_attributes: |
| 247 getter = getter_native_value_expression |
| 248 getter = getter.replace('imp->', '') |
| 249 getter = getter.replace('\(\)', '') |
| 250 |
| 251 update_method = '&%s::update%s' % (cpp_class_name, capitalize(ge
tter)) |
| 252 |
| 253 self_is_tear_off_type = get_svg_type_needing_tear_off(interface.
name) |
| 254 if self_is_tear_off_type: |
| 255 includes.append('core/svg/properties/SVGStaticPropertyWithPa
rentTearOff.h') |
| 256 svg_type_needing_tear_off = svg_type_needing_tear_off.replac
e('SVGPropertyTearOff<', 'SVGStaticPropertyWithParentTearOff<%s, ' % cpp_class_n
ame) |
| 257 wrapped_value = 'WTF::getPtr(%s::create(wrapper, %s, %s))' %
(svg_type_needing_tear_off, getter_native_value_expression, update_method) |
| 258 else: |
| 259 includes.append('core/svg/properties/SVGStaticPropertyTearOf
f.h') |
| 260 svg_type_needing_tear_off = svg_type_needing_tear_off.replac
e('SVGPropertyTearOff<', 'SVGStaticPropertyTearOff<%s, ' % cpp_class_name) |
| 261 wrapped_value = 'WTF::getPtr(%s::create(imp, %s, %s))' % (sv
g_type_needing_tear_off, getter_native_value_expression, update_method) |
| 262 elif 'SVGStaticListPropertyTearOff' in svg_type_needing_tear_off: |
| 263 wrapped_value = 'WTF::getPtr(%s::create(imp, %s))' % (svg_type_n
eeding_tear_off, getter_native_value_expression) |
| 264 elif re.search('SVG(Point|PathSeg)List', svg_type_needing_tear_off): |
| 265 wrapped_value = 'WTF::getPtr(%s)' % getter_native_value_expressi
on |
| 266 else: |
| 267 wrapped_value = 'WTF::getPtr(%s::create(%s))' % (svg_type_needin
g_tear_off, getter_native_value_expression) |
| 268 elif attribute.data_type == 'SerializedScriptValue' and 'CachedAttribute
' in attribute.extended_attributes: |
| 269 pass |
| 270 elif attribute.data_type == 'EventListener': |
| 271 pass |
| 272 else: |
| 273 original_getter_native_value_expression = getter_native_value_expres
sion |
| 274 # Fix amigious conversion problem, by casting to the base type first
($getterString returns a type that inherits from SVGAnimatedEnumeration, not th
e base class directly). |
| 275 if attribute.data_type == 'SVGAnimatedEnumeration': |
| 276 getter_native_value_expression = 'static_pointer_cast<SVGAnimate
dEnumeration>(%s)' % getter_native_value_expression |
| 277 |
| 278 # print '[get_attribute_parameter] native_type', native_type |
| 279 if attribute.is_nullable or getter_use_exception(attribute): |
| 280 # used in local variable type |
| 281 assign_native_value_to_local_variable_statement = '%s v = %s;' %
(native_type, getter_native_value_expression) |
| 282 getter_native_value_expression = get_pass_owner_expression(attri
bute.data_type, 'v') |
| 283 |
| 284 for for_main_world_suffix in for_main_world_suffixes: |
| 285 if attribute.data_type != 'EventListener': |
| 286 return_js_value_statement, native_to_js_value_includes = get
_native_to_js_value_statement(attribute.data_type, attribute.extended_attributes
, getter_native_value_expression, creation_context='info.Holder()', isolate='inf
o.GetIsolate()', callback_info='info', script_wrappable='imp', for_main_world_su
ffix=for_main_world_suffix, used_as_return_value=True) |
| 287 return_js_value_statements[for_main_world_suffix] = return_j
s_value_statement |
| 288 if should_keep_attribute_alive: |
| 289 assign_native_value_to_local_variable_statement = '%s v
= %s;' % (native_type, original_getter_native_value_expression) |
| 290 getter_native_value_expression = original_getter_native_
value_expression |
| 291 else: |
| 292 includes += native_to_js_value_includes |
| 293 |
| 294 ##################### Setter |
| 295 # native to JS (getter) |
| 296 assign_js_value_to_local_variable_statement = '' |
| 297 setter_native_value_expression = '' |
| 298 set_value_statement = '' |
| 299 setter_activity_logging = set() |
| 300 setter_function_call_parameter = {} |
| 301 if has_normal_setter: |
| 302 for for_main_world_suffix in for_main_world_suffixes: |
| 303 if has_activity_logging(for_main_world_suffix, attribute.extended_at
tributes, 'Setter'): |
| 304 setter_activity_logging.add(for_main_world_suffix) |
| 305 includes += ACTIVITY_LOGGING_INCLUDES |
| 306 |
| 307 # JS to native (setter) |
| 308 if attribute.data_type != 'EventListener': |
| 309 assign_js_value_to_local_variable_statement, js_value_to_native_incl
udes = get_js_value_to_native_statement(attribute.data_type, attribute.extended_
attributes, 'value', 'v', 'info.GetIsolate()') |
| 310 includes += js_value_to_native_includes |
| 311 |
| 312 setter_native_value_expression = 'v' |
| 313 if is_ref_ptr_type(attribute.data_type) and not get_array_type(attribute
.data_type): |
| 314 setter_native_value_expression = 'WTF::getPtr(%s)' % setter_native_v
alue_expression |
| 315 |
| 316 # set native value statement |
| 317 setter_native_value_expression, setter_function_call_parameter, setter_i
ncludes = get_attribute_function_call_expression(interface, attribute, is_setter
=True, setter_native_value_expression=setter_native_value_expression) |
| 318 includes += setter_includes |
| 319 |
| 320 set_value_statement = '%s;' % setter_native_value_expression |
| 321 # print '[attribute] set_value_statement', set_value_statement |
| 322 |
| 323 is_normal = False |
| 324 if interface.name == 'Window' and 'Unforgeable' in attribute.extended_attrib
utes: |
| 325 pass |
| 326 elif 'EnabledAtRuntime' in attribute.extended_attributes or 'EnabledPerConte
xt' in attribute.extended_attributes: |
| 327 pass |
| 328 else: |
| 329 is_normal = True |
| 330 |
| 331 parameter = { |
| 332 'name': attribute.name, |
| 333 'type': attribute.data_type, |
| 334 'is_static': attribute.is_static, |
| 335 'is_normal': is_normal, |
| 336 'native_type': native_type, |
| 337 'svg_animated_type': svg_animated_type, |
| 338 'svg_type_needing_tear_off': svg_type_needing_tear_off, |
| 339 'tear_off_and_not_list': tear_off_and_not_list, |
| 340 'check_security_for_node': check_security_for_node, |
| 341 'enable_function': enable_function, |
| 342 |
| 343 # EventListner hack |
| 344 'getter_function': getter_function, |
| 345 'event_listener_setter_function_name': event_listener_setter_function_na
me, |
| 346 'event_listener_setter_function_name_not_inherits_node': event_listener_
setter_function_name_not_inherits_node, |
| 347 'not_inherits_node': not_inherits_node, |
| 348 |
| 349 'getter_native_value_expression': getter_native_value_expression, |
| 350 'setter_native_value_expression': setter_native_value_expression, |
| 351 'return_js_value_statements': return_js_value_statements, |
| 352 'set_value_statement': set_value_statement, |
| 353 'conditional_string': generate_conditional_string(attribute), |
| 354 'batched_attribute': batched_attribute, |
| 355 'getter_use_exceptions': getter_use_exception(attribute), |
| 356 'setter_use_exceptions': setter_use_exception(attribute), |
| 357 'is_nullable': attribute.is_nullable, |
| 358 'assign_native_value_to_local_variable_statement': assign_native_value_t
o_local_variable_statement, |
| 359 'assign_js_value_to_local_variable_statement': assign_js_value_to_local_
variable_statement, |
| 360 'has_replaceable': has_replaceable, |
| 361 'has_normal_setter': has_normal_setter, |
| 362 'has_custom_getter': custom_getter, |
| 363 'has_custom_setter': custom_setter, |
| 364 'per_world_bindings': per_world_bindings, |
| 365 'for_main_world_suffixes': for_main_world_suffixes, |
| 366 'should_keep_attribute_alive': should_keep_attribute_alive, |
| 367 'array_type': array_type, |
| 368 'getter_activity_logging': getter_activity_logging, |
| 369 'setter_activity_logging': setter_activity_logging, |
| 370 'enabled_at_runtime': enabled_at_runtime, |
| 371 'enabled_per_context': enabled_per_context, |
| 372 'compact_getter': compact_getter, |
| 373 'compact_setter': compact_setter, |
| 374 'compact_setter_namespace': compact_setter_namespace, |
| 375 'compact_setter_content_attribute_name': compact_setter_content_attribut
e_name, |
| 376 'cached_attribute': 'CachedAttribute' in attribute.extended_attributes, |
| 377 'wrapped_value': wrapped_value, |
| 378 'cpp_name': implemented_as_cpp_name(attribute), |
| 379 'initialized_by_event_constructor': 'InitializedByEventConstructor' in a
ttribute.extended_attributes, |
| 380 'setter': 'setSerialized' + capitalize(attribute.name), |
| 381 } |
| 382 parameter.update(feature_observation_parameter) |
| 383 parameter.update(deprecation_notification_parameter) |
| 384 parameter.update(custom_element_invocation_scope_parameter) |
| 385 parameter.update(getter_function_call_parameter) |
| 386 parameter.update(setter_function_call_parameter) |
| 387 return parameter, includes |
| 388 |
| 389 |
| 390 def generate_batched_attribute(interface, attribute, delimiter, indent=''): |
| 391 # GenerateSingleBatchedAttribute in perl |
| 392 cpp_class_name = implemented_as_cpp_name(interface) |
| 393 v8_class_name = get_v8_class_name(interface) |
| 394 is_constructor = attribute.data_type.endswith('Constructor') |
| 395 # print '[--]', attribute.name, attribute.data_type, is_constructor |
| 396 includes = [] |
| 397 |
| 398 access_control = 'v8::DEFAULT' |
| 399 if attribute.extended_attributes.get('DoNotCheckSecurityOnGetter'): |
| 400 access_control = 'v8::ALL_CAN_READ' |
| 401 elif attribute.extended_attributes.get('DoNotCheckSecurityOnSetter'): |
| 402 access_control = 'v8::ALL_CAN_WRITE' |
| 403 elif attribute.extended_attributes.get('DoNotCheckSecurity'): |
| 404 access_control = 'v8::ALL_CAN_READ' |
| 405 if not is_read_only(attribute): |
| 406 access_control += ' | v8::ALL_CAN_WRITE' |
| 407 if attribute.extended_attributes.get('Unforgeable'): |
| 408 access_control += ' | v8::PROHIBITS_OVERWRITING' |
| 409 access_control = 'static_cast<v8::AccessControl>(%s)' % access_control |
| 410 |
| 411 prop_attr = 'v8::None' |
| 412 # Check attributes. |
| 413 # As per Web IDL specification, constructor properties on the ECMAScript glo
bal object should be |
| 414 # configurable and should not be enumerable. |
| 415 if 'NotEnumerable' in attribute.extended_attributes or is_constructor: |
| 416 prop_attr += ' | v8::DontEnum' |
| 417 if 'Unforgeable' in attribute.extended_attributes and not is_constructor: |
| 418 prop_attr += ' | v8::DontDelete' |
| 419 |
| 420 on_proto = '0 /* on instance */' |
| 421 if is_constructor: |
| 422 constructor_type = strip_suffix(attribute.data_type, 'Constructor') |
| 423 # $constructorType ~= /Constructor$/ indicates that it is NamedConstruct
or. |
| 424 # We do not generate the header file for NamedConstructor of class XXXX, |
| 425 # since we generate the NamedConstructor declaration into the header fil
e of class XXXX. |
| 426 # FIXME: We just stripped the 'Constructor' suffix! |
| 427 if not constructor_type.endswith('Constructor') or attribute.extended_at
tributes.get('CustomConstructor'): |
| 428 includes.append('V8%s.h' % constructor_type) |
| 429 getter = '%sV8Internal::%sConstructorGetter' % (cpp_class_name, cpp_clas
s_name) |
| 430 setter = '%sV8Internal::%sReplaceableAttrSetterCallback' % (cpp_class_na
me, cpp_class_name) |
| 431 getter_for_main_world = '0' |
| 432 setter_for_main_world = '0' |
| 433 data = '&V8${constructorType}::info' |
| 434 else: |
| 435 # Default Getter and Setter |
| 436 getter = '%sV8Internal::%sAttrGetterCallback' % (cpp_class_name, attribu
te.name) |
| 437 setter = '%sV8Internal::%sAttrSetterCallback' % (cpp_class_name, attribu
te.name) |
| 438 getter_for_main_world = getter + 'ForMainWorld' |
| 439 setter_for_main_world = setter + 'ForMainWorld' |
| 440 data = '0 /* no data */' |
| 441 if not has_custom_setter(attribute) and attribute.extended_attributes.ge
t('Replaceable'): |
| 442 setter = '%sV8Internal::%sReplaceableAttrSetterCallback' % (cpp_clas
s_name, cpp_class_name) |
| 443 setter_for_main_world = '0' |
| 444 # Read only attributes |
| 445 if is_read_only(attribute): |
| 446 setter = '0' |
| 447 setter_for_main_world = '0' |
| 448 if 'PerWorldBindings' not in attribute.extended_attributes: |
| 449 getter_for_main_world = '0' |
| 450 setter_for_main_world = '0' |
| 451 |
| 452 # An accessor can be installed on the proto |
| 453 if attribute.extended_attributes.get('OnProto'): |
| 454 on_proto = '1 /* on proto */' |
| 455 |
| 456 code = ( |
| 457 '{"%s", %s, %s, %s, %s, %s, %s, static_cast<v8::PropertyAttribute>(%s),
%s}%s' % |
| 458 (attribute.name, getter, setter, getter_for_main_world, setter_for_main_
world, data, access_control, prop_attr, on_proto, delimiter)) |
| 459 return code, includes |
| 460 |
| 461 |
| 462 # Auxiliary functions |
| 463 |
| 464 |
| 465 def get_should_keep_attribute_alive(interface, attribute): |
| 466 return ( |
| 467 'KeepAttributeAliveForGC' in attribute.extended_attributes or |
| 468 # Basically, for readonly or replaceable attributes, we have to |
| 469 # guarantee that JS wrappers don't get garbage-collected prematually |
| 470 # when their lifetime is strongly tied to their owner. |
| 471 ((is_wrapper_type(attribute.data_type) and |
| 472 (is_read_only(attribute) or |
| 473 'Replaceable' in attribute.extended_attributes)) and |
| 474 # However, there are a couple of exceptions. |
| 475 not( |
| 476 # Node lifetime is managed by object grouping. |
| 477 inherits_interface(interface, 'Node') or |
| 478 is_dom_node_type(attribute.data_type) or |
| 479 # To avoid adding a reference to itself. |
| 480 # FIXME: Introduce [DoNotKeepAttributeAliveForGC] and remove |
| 481 # this hack of depending on the attribute name. |
| 482 attribute.name == 'self' or |
| 483 # FIXME: Remove these hard-coded hacks. |
| 484 attribute.data_type in ['EventTarget', 'SerializedScriptValue', 'Win
dow'] or |
| 485 'SVG' in attribute.data_type or |
| 486 'HTML' in attribute.data_type))) |
| 487 |
| 488 |
| 489 def get_attribute_function_call_expression(interface, attribute, is_setter=False
, setter_native_value_expression=None): |
| 490 """ |
| 491 @return function_call_expression, includes |
| 492 """ |
| 493 # GetterExpression / SetterExpression in perl |
| 494 includes = [] |
| 495 arguments = [] |
| 496 interface_name = interface.name |
| 497 cpp_class_name = implemented_as_cpp_name(interface) |
| 498 content_attribute_name, additional_includes = get_content_attribute_name(int
erface_name, attribute) |
| 499 includes += additional_includes |
| 500 |
| 501 function_name = '' |
| 502 if is_setter: |
| 503 if content_attribute_name: |
| 504 if attribute.data_type == 'boolean': |
| 505 function_name = 'setBooleanAttribute' |
| 506 elif attribute.data_type == 'long': |
| 507 function_name = 'setIntegralAttribute' |
| 508 elif attribute.data_type == 'unsigned long': |
| 509 function_name = 'setUnsignedIntegralAttribute' |
| 510 else: |
| 511 function_name = 'setAttribute' |
| 512 else: |
| 513 function_name = 'set' + capitalize(implemented_as_cpp_name(attribute
)) |
| 514 else: |
| 515 if content_attribute_name: |
| 516 if 'URL' in attribute.extended_attributes: |
| 517 function_name = 'getURLAttribute' |
| 518 elif attribute.data_type == 'boolean': |
| 519 function_name = 'fastHasAttribute' |
| 520 elif attribute.data_type == 'long': |
| 521 function_name = 'getIntegralAttribute' |
| 522 elif attribute.data_type == 'unsigned long': |
| 523 function_name = 'getUnsignedIntegralAttribute' |
| 524 elif content_attribute_name == 'WebCore::HTMLNames::idAttr': |
| 525 function_name = 'getIdAttribute' |
| 526 content_attribute_name = '' |
| 527 elif content_attribute_name == 'WebCore::HTMLNames::nameAttr': |
| 528 function_name = 'getNameAttribute' |
| 529 content_attribute_name = '' |
| 530 elif content_attribute_name == 'WebCore::HTMLNames::classAttr': |
| 531 function_name = 'getClassAttribute' |
| 532 content_attribute_name = '' |
| 533 elif is_svg_animated_type(attribute.data_type): |
| 534 # We cannot use fast attributes for animated SVG types. |
| 535 function_name = 'getAttribute' |
| 536 else: |
| 537 function_name = 'fastGetAttribute' |
| 538 else: |
| 539 function_name = uncapitalize(implemented_as_cpp_name(attribute)) |
| 540 # print '[[]]', function_name |
| 541 if content_attribute_name: |
| 542 arguments.append(content_attribute_name) |
| 543 |
| 544 implemented_by = attribute.extended_attributes.get('ImplementedBy') |
| 545 if implemented_by: |
| 546 implemented_by_cpp_name = implemented_as_from_implemented_by(implemented
_by) |
| 547 includes += header_files_for_interface(implemented_by, implemented_by_cp
p_name) |
| 548 if not attribute.is_static: |
| 549 arguments = ['imp'] + arguments |
| 550 function_name = '%s::%s' % (implemented_by_cpp_name, function_name) |
| 551 elif attribute.is_static: |
| 552 function_name = '%s::%s' % (cpp_class_name, function_name) |
| 553 else: |
| 554 function_name = 'imp->%s' % function_name |
| 555 |
| 556 if is_setter: |
| 557 arguments.append(setter_native_value_expression) |
| 558 if setter_use_exception(attribute): |
| 559 arguments.append('es') |
| 560 call_with = attribute.extended_attributes.get('SetterCallWith') or attri
bute.extended_attributes.get('CallWith') |
| 561 else: |
| 562 if attribute.is_nullable: |
| 563 arguments.append('isNull') |
| 564 if getter_use_exception(attribute): |
| 565 arguments.append('es') |
| 566 call_with = attribute.extended_attributes.get('CallWith') |
| 567 |
| 568 call_with_arguments, call_with_parameter, call_with_includes = get_call_with
_parameter(call_with) |
| 569 includes += call_with_includes |
| 570 arguments = call_with_arguments + arguments |
| 571 |
| 572 function_call_expression = '%s(%s)' % (function_name, ', '.join(arguments)) |
| 573 return function_call_expression, call_with_parameter, includes |
| 574 |
| 575 |
| 576 def get_custom_element_invocation_scope_parameter(interface_or_attribute_or_func
tion): |
| 577 # print '[[]]', interface_or_attribute_or_function.extended_attributes |
| 578 custom_element_invocation_scope = has_extended_attribute(interface_or_attrib
ute_or_function, ['DeliverCustomElementCallbacks', 'Reflect']) |
| 579 parameter = { |
| 580 'custom_element_invocation_scope': custom_element_invocation_scope, |
| 581 } |
| 582 if custom_element_invocation_scope: |
| 583 includes = ['core/dom/CustomElementCallbackDispatcher.h'] |
| 584 else: |
| 585 includes = [] |
| 586 return parameter, includes |
| 587 |
| 588 |
| 589 def has_extended_attribute(item, extended_attribute_list): |
| 590 # FIXME: useful function, use widely |
| 591 return any([extended_attribute in item.extended_attributes |
| 592 for extended_attribute in extended_attribute_list]) |
| 593 |
| 594 |
| 595 def getter_use_exception(attribute): |
| 596 return has_extended_attribute(attribute, ['GetterRaisesException', 'RaisesEx
ception']) |
| 597 |
| 598 |
| 599 def setter_use_exception(attribute): |
| 600 return has_extended_attribute(attribute, ['SetterRaisesException', 'RaisesEx
ception']) |
| 601 |
| 602 |
| 603 def namespace_for_attribute_name(interface_name, attribute_name): |
| 604 if (interface_name.startswith('SVG') and |
| 605 attribute_name not in SVG_ATTRIBUTES_IN_HTML): |
| 606 return 'SVGNames' |
| 607 return 'HTMLNames' |
| 608 |
| 609 |
| 610 def get_content_attribute_name(interface_name, attribute): |
| 611 if 'Reflect' not in attribute.extended_attributes: |
| 612 return None, [] |
| 613 default_content_attribute_name = implemented_as_cpp_name(attribute).lower() |
| 614 content_attribute_name = attribute.extended_attributes['Reflect'] or default
_content_attribute_name |
| 615 namespace = namespace_for_attribute_name(interface_name, content_attribute_n
ame) |
| 616 scoped_name = 'WebCore::%s::%sAttr' % (namespace, content_attribute_name) |
| 617 includes = [namespace + '.h'] |
| 618 return scoped_name, includes |
OLD | NEW |