Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(410)

Side by Side Diff: Source/bindings/scripts/v8_interface.py

Issue 618373003: [bindings] partial interfaces should not violate componentization (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Added --target-component instead of --genearte-partial Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 # Copyright (C) 2013 Google Inc. All rights reserved. 1 # Copyright (C) 2013 Google Inc. All rights reserved.
2 # coding=utf-8 2 # coding=utf-8
3 # 3 #
4 # Redistribution and use in source and binary forms, with or without 4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are 5 # modification, are permitted provided that the following conditions are
6 # met: 6 # met:
7 # 7 #
8 # * Redistributions of source code must retain the above copyright 8 # * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer. 9 # notice, this list of conditions and the following disclaimer.
10 # * Redistributions in binary form must reproduce the above 10 # * Redistributions in binary form must reproduce the above
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 'wtf/GetPtr.h', 70 'wtf/GetPtr.h',
71 'wtf/RefPtr.h', 71 'wtf/RefPtr.h',
72 ]) 72 ])
73 73
74 74
75 def interface_context(interface): 75 def interface_context(interface):
76 includes.clear() 76 includes.clear()
77 includes.update(INTERFACE_CPP_INCLUDES) 77 includes.update(INTERFACE_CPP_INCLUDES)
78 header_includes = set(INTERFACE_H_INCLUDES) 78 header_includes = set(INTERFACE_H_INCLUDES)
79 79
80 parent_interface = interface.parent 80 if interface.is_partial:
81 if parent_interface: 81 # A partial interface definition cannot specify that the interface inher its
82 header_includes.update(v8_types.includes_for_interface(parent_interface) ) 82 # from another interface. Inheritance must be specified on the original interface
83 # definition.
84 parent_interface = None
bashi 2014/10/15 05:29:23 nit: you can omit this.
85 is_audio_buffer = False
bashi 2014/10/15 05:29:23 unused?
tasak 2014/10/15 11:24:18 Done.
86 is_document = False
87 is_event_target = False
bashi 2014/10/15 05:29:23 nit: you can omit assigning False.
tasak 2014/10/15 11:24:18 I saw the following errors: 'is_document': is_
bashi 2014/10/17 02:23:24 BTW, shouldn't we raise an exception rather than a
88 # partial interface needs the definition of its original interface.
89 includes.add('bindings/core/v8/V8%s.h' % interface.name)
90 else:
91 parent_interface = interface.parent
92 if parent_interface:
93 header_includes.update(v8_types.includes_for_interface(parent_interf ace))
94 is_document = inherits_interface(interface.name, 'Document')
95 is_event_target = inherits_interface(interface.name, 'EventTarget')
96
83 extended_attributes = interface.extended_attributes 97 extended_attributes = interface.extended_attributes
84 98
85 # [ActiveDOMObject] 99 # [ActiveDOMObject]
86 is_active_dom_object = 'ActiveDOMObject' in extended_attributes 100 is_active_dom_object = 'ActiveDOMObject' in extended_attributes
87 101
88 # [CheckSecurity] 102 # [CheckSecurity]
89 is_check_security = 'CheckSecurity' in extended_attributes 103 is_check_security = 'CheckSecurity' in extended_attributes
90 if is_check_security: 104 if is_check_security:
91 includes.add('bindings/core/v8/BindingSecurity.h') 105 includes.add('bindings/core/v8/BindingSecurity.h')
92 106
93 # [DependentLifetime] 107 # [DependentLifetime]
94 is_dependent_lifetime = 'DependentLifetime' in extended_attributes 108 is_dependent_lifetime = 'DependentLifetime' in extended_attributes
95 109
96 # [Iterable] 110 # [Iterable]
97 iterator_method = None 111 iterator_method = None
98 if 'Iterable' in extended_attributes: 112 # FIXME: support Iterable in partial interfaces. However, we don't
113 # need to support iterator overloads between interface and
114 # partial interface definitions.
115 # http://heycam.github.io/webidl/#idl-overloading
116 if 'Iterable' in extended_attributes and not interface.is_partial:
99 iterator_operation = IdlOperation(interface.idl_name) 117 iterator_operation = IdlOperation(interface.idl_name)
100 iterator_operation.name = 'iterator' 118 iterator_operation.name = 'iterator'
101 iterator_operation.idl_type = IdlType('Iterator') 119 iterator_operation.idl_type = IdlType('Iterator')
102 iterator_operation.extended_attributes['RaisesException'] = None 120 iterator_operation.extended_attributes['RaisesException'] = None
103 iterator_operation.extended_attributes['CallWith'] = 'ScriptState' 121 iterator_operation.extended_attributes['CallWith'] = 'ScriptState'
104 iterator_method = v8_methods.method_context(interface, 122 iterator_method = v8_methods.method_context(interface,
105 iterator_operation) 123 iterator_operation)
106 124
107 # [MeasureAs] 125 # [MeasureAs]
108 is_measure_as = 'MeasureAs' in extended_attributes 126 is_measure_as = 'MeasureAs' in extended_attributes
(...skipping 26 matching lines...) Expand all
135 # [Custom=Wrap], [SetWrapperReferenceFrom] 153 # [Custom=Wrap], [SetWrapperReferenceFrom]
136 has_visit_dom_wrapper = ( 154 has_visit_dom_wrapper = (
137 has_extended_attribute_value(interface, 'Custom', 'VisitDOMWrapper') or 155 has_extended_attribute_value(interface, 'Custom', 'VisitDOMWrapper') or
138 reachable_node_function or 156 reachable_node_function or
139 set_wrapper_reference_to_list) 157 set_wrapper_reference_to_list)
140 158
141 this_gc_type = gc_type(interface) 159 this_gc_type = gc_type(interface)
142 160
143 wrapper_class_id = ('NodeClassId' if inherits_interface(interface.name, 'Nod e') else 'ObjectClassId') 161 wrapper_class_id = ('NodeClassId' if inherits_interface(interface.name, 'Nod e') else 'ObjectClassId')
144 162
163 v8_class_name = v8_utilities.v8_class_name(interface)
164 cpp_class_name = cpp_name(interface)
165
145 context = { 166 context = {
146 'conditional_string': conditional_string(interface), # [Conditional] 167 'conditional_string': conditional_string(interface), # [Conditional]
147 'cpp_class': cpp_name(interface), 168 'cpp_class': cpp_class_name,
169 'actual_cpp_class': cpp_class_name + 'Partial' if interface.is_partial e lse cpp_class_name,
148 'gc_type': this_gc_type, 170 'gc_type': this_gc_type,
149 # FIXME: Remove 'EventTarget' special handling, http://crbug.com/383699 171 # FIXME: Remove 'EventTarget' special handling, http://crbug.com/383699
150 'has_access_check_callbacks': (is_check_security and 172 'has_access_check_callbacks': (is_check_security and
151 interface.name != 'Window' and 173 interface.name != 'Window' and
152 interface.name != 'EventTarget'), 174 interface.name != 'EventTarget'),
153 'has_custom_legacy_call_as_function': has_extended_attribute_value(inter face, 'Custom', 'LegacyCallAsFunction'), # [Custom=LegacyCallAsFunction] 175 'has_custom_legacy_call_as_function': has_extended_attribute_value(inter face, 'Custom', 'LegacyCallAsFunction'), # [Custom=LegacyCallAsFunction]
154 'has_custom_to_v8': has_extended_attribute_value(interface, 'Custom', 'T oV8'), # [Custom=ToV8] 176 'has_custom_to_v8': has_extended_attribute_value(interface, 'Custom', 'T oV8'), # [Custom=ToV8]
155 'has_custom_wrap': has_extended_attribute_value(interface, 'Custom', 'Wr ap'), # [Custom=Wrap] 177 'has_custom_wrap': has_extended_attribute_value(interface, 'Custom', 'Wr ap'), # [Custom=Wrap]
156 'has_visit_dom_wrapper': has_visit_dom_wrapper, 178 'has_visit_dom_wrapper': has_visit_dom_wrapper,
157 'header_includes': header_includes, 179 'header_includes': header_includes,
158 'interface_name': interface.name, 180 'interface_name': interface.name,
159 'is_active_dom_object': is_active_dom_object, 181 'is_active_dom_object': is_active_dom_object,
160 'is_check_security': is_check_security, 182 'is_check_security': is_check_security,
161 'is_dependent_lifetime': is_dependent_lifetime, 183 'is_dependent_lifetime': is_dependent_lifetime,
162 'is_event_target': inherits_interface(interface.name, 'EventTarget'), 184 'is_document': is_document,
185 'is_event_target': is_event_target,
163 'is_exception': interface.is_exception, 186 'is_exception': interface.is_exception,
164 'is_node': inherits_interface(interface.name, 'Node'), 187 'is_node': inherits_interface(interface.name, 'Node'),
165 'is_script_wrappable': is_script_wrappable, 188 'is_script_wrappable': is_script_wrappable,
166 'iterator_method': iterator_method, 189 'iterator_method': iterator_method,
167 'lifetime': 'Dependent' 190 'lifetime': 'Dependent'
168 if (has_visit_dom_wrapper or 191 if (has_visit_dom_wrapper or
169 is_active_dom_object or 192 is_active_dom_object or
170 is_dependent_lifetime) 193 is_dependent_lifetime)
171 else 'Independent', 194 else 'Independent',
195 'is_partial': interface.is_partial,
196 'has_partial_interface': len(interface.partial_interfaces) > 0,
172 'measure_as': v8_utilities.measure_as(interface), # [MeasureAs] 197 'measure_as': v8_utilities.measure_as(interface), # [MeasureAs]
173 'parent_interface': parent_interface, 198 'parent_interface': parent_interface,
174 'pass_cpp_type': cpp_template_type( 199 'pass_cpp_type': cpp_template_type(
175 cpp_ptr_type('PassRefPtr', 'RawPtr', this_gc_type), 200 cpp_ptr_type('PassRefPtr', 'RawPtr', this_gc_type),
176 cpp_name(interface)), 201 cpp_name(interface)),
177 'reachable_node_function': reachable_node_function, 202 'reachable_node_function': reachable_node_function,
178 'runtime_enabled_function': runtime_enabled_function_name(interface), # [RuntimeEnabled] 203 'runtime_enabled_function': runtime_enabled_function_name(interface), # [RuntimeEnabled]
179 'set_wrapper_reference_to_list': set_wrapper_reference_to_list, 204 'set_wrapper_reference_to_list': set_wrapper_reference_to_list,
180 'v8_class': v8_utilities.v8_class_name(interface), 205 'v8_class': v8_class_name,
206 'actual_v8_class': v8_class_name + 'Partial' if interface.is_partial els e v8_class_name,
bashi 2014/10/15 05:29:23 nit: alphabetical order. (I'd like to call this |v
tasak 2014/10/15 11:24:18 Done. I would like to call. However, if a given in
bashi 2014/10/17 02:23:24 Acknowledged.
181 'wrapper_class_id': wrapper_class_id, 207 'wrapper_class_id': wrapper_class_id,
182 } 208 }
183 209
184 # Constructors 210 # Constructors
185 constructors = [constructor_context(interface, constructor) 211 update_interface_constructor_context(interface, context)
186 for constructor in interface.constructors
187 # FIXME: shouldn't put named constructors with constructors
188 # (currently needed for Perl compatibility)
189 # Handle named constructors separately
190 if constructor.name == 'Constructor']
191 if len(constructors) > 1:
192 context['constructor_overloads'] = overloads_context(constructors)
193
194 # [CustomConstructor]
195 custom_constructors = [{ # Only needed for computing interface length
196 'number_of_required_arguments':
197 number_of_required_arguments(constructor),
198 } for constructor in interface.custom_constructors]
199
200 # [EventConstructor]
201 has_event_constructor = 'EventConstructor' in extended_attributes
202 any_type_attributes = [attribute for attribute in interface.attributes
203 if attribute.idl_type.name == 'Any']
204 if has_event_constructor:
205 includes.add('bindings/core/v8/Dictionary.h')
206 if any_type_attributes:
207 includes.add('bindings/core/v8/SerializedScriptValue.h')
208
209 # [NamedConstructor]
210 named_constructor = named_constructor_context(interface)
211
212 if (constructors or custom_constructors or has_event_constructor or
213 named_constructor):
214 includes.add('bindings/core/v8/V8ObjectConstructor.h')
215 includes.add('core/frame/LocalDOMWindow.h')
216
217 context.update({
218 'any_type_attributes': any_type_attributes,
219 'constructors': constructors,
220 'has_custom_constructor': bool(custom_constructors),
221 'has_event_constructor': has_event_constructor,
222 'interface_length':
223 interface_length(interface, constructors + custom_constructors),
224 'is_constructor_raises_exception': extended_attributes.get('RaisesExcept ion') == 'Constructor', # [RaisesException=Constructor]
225 'named_constructor': named_constructor,
226 })
227 212
228 constants = [constant_context(constant) for constant in interface.constants] 213 constants = [constant_context(constant) for constant in interface.constants]
229 214
230 special_getter_constants = [] 215 special_getter_constants = []
231 runtime_enabled_constants = [] 216 runtime_enabled_constants = []
232 constant_configuration_constants = [] 217 constant_configuration_constants = []
233 218
234 for constant in constants: 219 for constant in constants:
235 if constant['measure_as'] or constant['deprecate_as']: 220 if constant['measure_as'] or constant['deprecate_as']:
236 special_getter_constants.append(constant) 221 special_getter_constants.append(constant)
(...skipping 27 matching lines...) Expand all
264 attribute['runtime_enabled_function'] or 249 attribute['runtime_enabled_function'] or
265 attribute['per_context_enabled_function']) 250 attribute['per_context_enabled_function'])
266 and attribute['should_be_exposed_to_script'] 251 and attribute['should_be_exposed_to_script']
267 for attribute in attributes), 252 for attribute in attributes),
268 'has_conditional_attributes': any(attribute['per_context_enabled_functio n'] or attribute['exposed_test'] for attribute in attributes), 253 'has_conditional_attributes': any(attribute['per_context_enabled_functio n'] or attribute['exposed_test'] for attribute in attributes),
269 'has_constructor_attributes': any(attribute['constructor_type'] for attr ibute in attributes), 254 'has_constructor_attributes': any(attribute['constructor_type'] for attr ibute in attributes),
270 'has_replaceable_attributes': any(attribute['is_replaceable'] for attrib ute in attributes), 255 'has_replaceable_attributes': any(attribute['is_replaceable'] for attrib ute in attributes),
271 }) 256 })
272 257
273 # Methods 258 # Methods
274 methods = [v8_methods.method_context(interface, method) 259 methods = []
275 for method in interface.operations 260 if interface.original_interface:
276 if method.name] # Skip anonymous special operations (methods) 261 for operation in interface.original_interface.operations:
277 compute_method_overloads_context(methods) 262 if not operation.name:
263 continue
264 method = v8_methods.method_context(interface, operation)
bashi 2014/10/15 05:29:23 How about adding an optional argument |is_visible|
tasak 2014/10/15 11:24:19 Done.
265 method['visible'] = False
266 methods.append(method)
267 methods.extend([v8_methods.method_context(interface, method)
268 for method in interface.operations
269 if method.name]) # Skip anonymous special operations (metho ds)
270 if interface.partial_interfaces:
271 assert len(interface.partial_interfaces) == len(set(interface.partial_in terfaces))
272 for partial_interface in interface.partial_interfaces:
273 for operation in partial_interface.operations:
274 if not operation.name:
275 continue
276 partial_method = v8_methods.method_context(interface, operation)
277 partial_method['visible'] = False
278 methods.append(partial_method)
279 compute_method_overloads_context(interface, methods)
278 280
279 # Stringifier 281 # Stringifier
280 if interface.stringifier: 282 if interface.stringifier:
281 stringifier = interface.stringifier 283 stringifier = interface.stringifier
282 method = IdlOperation(interface.idl_name) 284 method = IdlOperation(interface.idl_name)
283 method.name = 'toString' 285 method.name = 'toString'
284 method.idl_type = IdlType('DOMString') 286 method.idl_type = IdlType('DOMString')
285 method.extended_attributes.update(stringifier.extended_attributes) 287 method.extended_attributes.update(stringifier.extended_attributes)
286 if stringifier.attribute: 288 if stringifier.attribute:
287 method.extended_attributes['ImplementedAs'] = stringifier.attribute. name 289 method.extended_attributes['ImplementedAs'] = stringifier.attribute. name
288 elif stringifier.operation: 290 elif stringifier.operation:
289 method.extended_attributes['ImplementedAs'] = stringifier.operation. name 291 method.extended_attributes['ImplementedAs'] = stringifier.operation. name
290 methods.append(v8_methods.method_context(interface, method)) 292 methods.append(v8_methods.method_context(interface, method))
291 293
292 conditionally_enabled_methods = [] 294 conditionally_enabled_methods = []
293 custom_registration_methods = [] 295 custom_registration_methods = []
294 method_configuration_methods = [] 296 method_configuration_methods = []
295 297
296 for method in methods: 298 for method in methods:
297 # Skip all but one method in each set of overloaded methods. 299 # Skip all but one method in each set of overloaded methods.
298 if 'overload_index' in method and 'overloads' not in method: 300 if 'overload_index' in method and 'overloads' not in method:
299 continue 301 continue
300 302
301 if 'overloads' in method: 303 if 'overloads' in method:
302 overloads = method['overloads'] 304 overloads = method['overloads']
305 if not overloads['visible']:
306 continue
307 # original interface will register instead of partial interface.
308 if overloads['has_partial_overloads'] and interface.is_partial:
309 continue
303 per_context_enabled_function = overloads['per_context_enabled_functi on_all'] 310 per_context_enabled_function = overloads['per_context_enabled_functi on_all']
304 conditionally_exposed_function = overloads['exposed_test_all'] 311 conditionally_exposed_function = overloads['exposed_test_all']
305 runtime_enabled_function = overloads['runtime_enabled_function_all'] 312 runtime_enabled_function = overloads['runtime_enabled_function_all']
306 has_custom_registration = overloads['has_custom_registration_all'] 313 has_custom_registration = overloads['has_custom_registration_all']
307 else: 314 else:
315 if not method['visible']:
316 continue
308 per_context_enabled_function = method['per_context_enabled_function' ] 317 per_context_enabled_function = method['per_context_enabled_function' ]
309 conditionally_exposed_function = method['exposed_test'] 318 conditionally_exposed_function = method['exposed_test']
310 runtime_enabled_function = method['runtime_enabled_function'] 319 runtime_enabled_function = method['runtime_enabled_function']
311 has_custom_registration = method['has_custom_registration'] 320 has_custom_registration = method['has_custom_registration']
312 321
313 if per_context_enabled_function or conditionally_exposed_function: 322 if per_context_enabled_function or conditionally_exposed_function:
314 conditionally_enabled_methods.append(method) 323 conditionally_enabled_methods.append(method)
315 continue 324 continue
316 if runtime_enabled_function or has_custom_registration: 325 if runtime_enabled_function or has_custom_registration:
317 custom_registration_methods.append(method) 326 custom_registration_methods.append(method)
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 'indexed_property_deleter': indexed_property_deleter(interface), 361 'indexed_property_deleter': indexed_property_deleter(interface),
353 'is_override_builtins': 'OverrideBuiltins' in extended_attributes, 362 'is_override_builtins': 'OverrideBuiltins' in extended_attributes,
354 'named_property_getter': named_property_getter(interface), 363 'named_property_getter': named_property_getter(interface),
355 'named_property_setter': named_property_setter(interface), 364 'named_property_setter': named_property_setter(interface),
356 'named_property_deleter': named_property_deleter(interface), 365 'named_property_deleter': named_property_deleter(interface),
357 }) 366 })
358 367
359 return context 368 return context
360 369
361 370
371 def update_interface_constructor_context(interface, context):
bashi 2014/10/15 05:29:23 Question: is there any change except for factoring
tasak 2014/10/15 11:24:19 Done.
372 constructors = [constructor_context(interface, constructor)
373 for constructor in interface.constructors
374 # FIXME: shouldn't put named constructors with constructors
375 # (currently needed for Perl compatibility)
376 # Handle named constructors separately
377 if constructor.name == 'Constructor']
378 if len(constructors) > 1:
379 context['constructor_overloads'] = overloads_context(interface, construc tors)
380
381 # [CustomConstructor]
382 custom_constructors = [{ # Only needed for computing interface length
383 'number_of_required_arguments':
384 number_of_required_arguments(constructor),
385 } for constructor in interface.custom_constructors]
386
387 # [EventConstructor]
388 has_event_constructor = 'EventConstructor' in interface.extended_attributes
389 # [NamedConstructor]
390 named_constructor = named_constructor_context(interface)
391
392 if constructors or custom_constructors or has_event_constructor or named_con structor:
393 if interface.is_partial:
394 raise Exception('[Constructor] and [NamedConstructor] MUST NOT be'
395 ' specified on partial interface definitions:'
396 '%s' % interface.name)
397
398 includes.add('bindings/core/v8/V8ObjectConstructor.h')
399 includes.add('core/frame/LocalDOMWindow.h')
400
401 any_type_attributes = [attribute for attribute in interface.attributes
402 if attribute.idl_type.name == 'Any']
403 if has_event_constructor:
404 includes.add('bindings/core/v8/Dictionary.h')
405 if any_type_attributes:
406 includes.add('bindings/core/v8/SerializedScriptValue.h')
407
408 context.update({
409 'any_type_attributes': any_type_attributes,
410 'constructors': constructors,
411 'has_custom_constructor': bool(custom_constructors),
412 'has_event_constructor': has_event_constructor,
413 'interface_length':
414 interface_length(interface, constructors + custom_constructors),
415 'is_constructor_raises_exception':
416 interface.extended_attributes.get('RaisesException') == 'Constructor ', # [RaisesException=Constructor]
417 'named_constructor': named_constructor,
418 })
419
420
362 # [DeprecateAs], [Reflect], [RuntimeEnabled] 421 # [DeprecateAs], [Reflect], [RuntimeEnabled]
363 def constant_context(constant): 422 def constant_context(constant):
364 extended_attributes = constant.extended_attributes 423 extended_attributes = constant.extended_attributes
365 return { 424 return {
366 'cpp_class': extended_attributes.get('PartialInterfaceImplementedAs'), 425 'cpp_class': extended_attributes.get('PartialInterfaceImplementedAs'),
367 'deprecate_as': v8_utilities.deprecate_as(constant), # [DeprecateAs] 426 'deprecate_as': v8_utilities.deprecate_as(constant), # [DeprecateAs]
368 'idl_type': constant.idl_type.name, 427 'idl_type': constant.idl_type.name,
369 'measure_as': v8_utilities.measure_as(constant), # [MeasureAs] 428 'measure_as': v8_utilities.measure_as(constant), # [MeasureAs]
370 'name': constant.name, 429 'name': constant.name,
371 # FIXME: use 'reflected_name' as correct 'name' 430 # FIXME: use 'reflected_name' as correct 'name'
372 'reflected_name': extended_attributes.get('Reflect', constant.name), 431 'reflected_name': extended_attributes.get('Reflect', constant.name),
373 'runtime_enabled_function': runtime_enabled_function_name(constant), 432 'runtime_enabled_function': runtime_enabled_function_name(constant),
374 'value': constant.value, 433 'value': constant.value,
375 } 434 }
376 435
377 436
378 ################################################################################ 437 ################################################################################
379 # Overloads 438 # Overloads
380 ################################################################################ 439 ################################################################################
381 440
382 def compute_method_overloads_context(methods): 441 def compute_method_overloads_context(interface, methods):
383 # Regular methods 442 # Regular methods
384 compute_method_overloads_context_by_type([method for method in methods 443 compute_method_overloads_context_by_type(
385 if not method['is_static']]) 444 interface, [method for method in methods if not method['is_static']])
386 # Static methods 445 # Static methods
387 compute_method_overloads_context_by_type([method for method in methods 446 compute_method_overloads_context_by_type(
388 if method['is_static']]) 447 interface, [method for method in methods if method['is_static']])
389 448
390 449
391 def compute_method_overloads_context_by_type(methods): 450 def compute_method_overloads_context_by_type(interface, methods):
392 """Computes |method.overload*| template values. 451 """Computes |method.overload*| template values.
393 452
394 Called separately for static and non-static (regular) methods, 453 Called separately for static and non-static (regular) methods,
395 as these are overloaded separately. 454 as these are overloaded separately.
396 Modifies |method| in place for |method| in |methods|. 455 Modifies |method| in place for |method| in |methods|.
397 Doesn't change the |methods| list itself (only the values, i.e. individual 456 Doesn't change the |methods| list itself (only the values, i.e. individual
398 methods), so ok to treat these separately. 457 methods), so ok to treat these separately.
399 """ 458 """
400 # Add overload information only to overloaded methods, so template code can 459 # Add overload information only to overloaded methods, so template code can
401 # easily verify if a function is overloaded 460 # easily verify if a function is overloaded
402 for name, overloads in method_overloads_by_name(methods): 461 for name, overloads in method_overloads_by_name(methods):
403 # Resolution function is generated after last overloaded function; 462 # Resolution function is generated after last overloaded function;
404 # package necessary information into |method.overloads| for that method. 463 # package necessary information into |method.overloads| for that method.
405 overloads[-1]['overloads'] = overloads_context(overloads) 464 overloads[-1]['overloads'] = overloads_context(interface, overloads)
406 overloads[-1]['overloads']['name'] = name 465 overloads[-1]['overloads']['name'] = name
407 466
408 467
409 def method_overloads_by_name(methods): 468 def method_overloads_by_name(methods):
410 """Returns generator of overloaded methods by name: [name, [method]]""" 469 """Returns generator of overloaded methods by name: [name, [method]]"""
411 # Filter to only methods that are actually overloaded 470 # Filter to only methods that are actually overloaded
412 method_counts = Counter(method['name'] for method in methods) 471 method_counts = Counter(method['name'] for method in methods)
413 overloaded_method_names = set(name 472 overloaded_method_names = set(name
414 for name, count in method_counts.iteritems() 473 for name, count in method_counts.iteritems()
415 if count > 1) 474 if count > 1)
416 overloaded_methods = [method for method in methods 475 overloaded_methods = [method for method in methods
417 if method['name'] in overloaded_method_names] 476 if method['name'] in overloaded_method_names]
418 477
419 # Group by name (generally will be defined together, but not necessarily) 478 # Group by name (generally will be defined together, but not necessarily)
420 return sort_and_groupby(overloaded_methods, itemgetter('name')) 479 return sort_and_groupby(overloaded_methods, itemgetter('name'))
421 480
422 481
423 def overloads_context(overloads): 482 def overloads_context(interface, overloads):
424 """Returns |overloads| template values for a single name. 483 """Returns |overloads| template values for a single name.
425 484
426 Sets |method.overload_index| in place for |method| in |overloads| 485 Sets |method.overload_index| in place for |method| in |overloads|
427 and returns dict of overall overload template values. 486 and returns dict of overall overload template values.
428 """ 487 """
488 # partial overloads breaks this assumption.
bashi 2014/10/15 05:29:23 Should we remove or change the assert then?
tasak 2014/10/15 11:24:19 Removed the comment. This assert is correct now.
429 assert len(overloads) > 1 # only apply to overloaded names 489 assert len(overloads) > 1 # only apply to overloaded names
430 for index, method in enumerate(overloads, 1): 490 for index, method in enumerate(overloads, 1):
431 method['overload_index'] = index 491 method['overload_index'] = index
432 492
433 effective_overloads_by_length = effective_overload_set_by_length(overloads) 493 effective_overloads_by_length = effective_overload_set_by_length(overloads)
434 lengths = [length for length, _ in effective_overloads_by_length] 494 lengths = [length for length, _ in effective_overloads_by_length]
435 name = overloads[0].get('name', '<constructor>') 495 name = overloads[0].get('name', '<constructor>')
436 496
437 # Check and fail if all overloads with the shortest acceptable arguments 497 # Check and fail if all overloads with the shortest acceptable arguments
438 # list are runtime enabled, since we would otherwise set 'length' on the 498 # list are runtime enabled, since we would otherwise set 'length' on the
(...skipping 20 matching lines...) Expand all
459 raise ValueError('Overloads of %s have conflicting extended attr ibute %s' 519 raise ValueError('Overloads of %s have conflicting extended attr ibute %s'
460 % (name, extended_attribute)) 520 % (name, extended_attribute))
461 521
462 # Check and fail if overloads disagree about whether the return type 522 # Check and fail if overloads disagree about whether the return type
463 # is a Promise or not. 523 # is a Promise or not.
464 promise_overload_count = sum(1 for method in overloads if method.get('idl_ty pe') == 'Promise') 524 promise_overload_count = sum(1 for method in overloads if method.get('idl_ty pe') == 'Promise')
465 if promise_overload_count not in (0, len(overloads)): 525 if promise_overload_count not in (0, len(overloads)):
466 raise ValueError('Overloads of %s have conflicting Promise/non-Promise t ypes' 526 raise ValueError('Overloads of %s have conflicting Promise/non-Promise t ypes'
467 % (name)) 527 % (name))
468 528
529 overloads_visibles = set([method.get('visible', True) for method in overload s])
bashi 2014/10/15 05:29:23 Use method['visible'] instead of get()? It seems t
tasak 2014/10/15 11:24:19 |method| always has. However, |constructor| never
bashi 2014/10/17 02:23:24 It will help make code simple, IMO.
530 if len(overloads_visibles) > 1:
531 overloads_visible = True
532 has_partial_overloads = True
533 else:
534 overloads_visible = overloads_visibles.pop()
535 has_partial_overloads = False
536
469 return { 537 return {
470 'deprecate_all_as': common_value(overloads, 'deprecate_as'), # [Depreca teAs] 538 'deprecate_all_as': common_value(overloads, 'deprecate_as'), # [Depreca teAs]
471 'exposed_test_all': common_value(overloads, 'exposed_test'), # [Exposed ] 539 'exposed_test_all': common_value(overloads, 'exposed_test'), # [Exposed ]
472 'has_custom_registration_all': common_value(overloads, 'has_custom_regis tration'), 540 'has_custom_registration_all': common_value(overloads, 'has_custom_regis tration'),
473 'length_tests_methods': length_tests_methods(effective_overloads_by_leng th), 541 'length_tests_methods': length_tests_methods(effective_overloads_by_leng th),
474 # 1. Let maxarg be the length of the longest type list of the 542 # 1. Let maxarg be the length of the longest type list of the
475 # entries in S. 543 # entries in S.
476 'maxarg': lengths[-1], 544 'maxarg': lengths[-1],
477 'measure_all_as': common_value(overloads, 'measure_as'), # [MeasureAs] 545 'measure_all_as': common_value(overloads, 'measure_as'), # [MeasureAs]
478 'minarg': lengths[0], 546 'minarg': lengths[0],
479 'per_context_enabled_function_all': common_value(overloads, 'per_context _enabled_function'), # [PerContextEnabled] 547 'per_context_enabled_function_all': common_value(overloads, 'per_context _enabled_function'), # [PerContextEnabled]
480 'runtime_enabled_function_all': common_value(overloads, 'runtime_enabled _function'), # [RuntimeEnabled] 548 'runtime_enabled_function_all': common_value(overloads, 'runtime_enabled _function'), # [RuntimeEnabled]
481 'valid_arities': lengths 549 'valid_arities': lengths
482 # Only need to report valid arities if there is a gap in the 550 # Only need to report valid arities if there is a gap in the
483 # sequence of possible lengths, otherwise invalid length means 551 # sequence of possible lengths, otherwise invalid length means
484 # "not enough arguments". 552 # "not enough arguments".
485 if lengths[-1] - lengths[0] != len(lengths) - 1 else None, 553 if lengths[-1] - lengths[0] != len(lengths) - 1 else None,
554 'visible': overloads_visible,
555 'has_partial_overloads': has_partial_overloads,
486 } 556 }
487 557
488 558
489 def effective_overload_set(F): 559 def effective_overload_set(F):
490 """Returns the effective overload set of an overloaded function. 560 """Returns the effective overload set of an overloaded function.
491 561
492 An effective overload set is the set of overloaded functions + signatures 562 An effective overload set is the set of overloaded functions + signatures
493 (type list of arguments, with optional and variadic arguments included or 563 (type list of arguments, with optional and variadic arguments included or
494 not), and is used in the overload resolution algorithm. 564 not), and is used in the overload resolution algorithm.
495 565
(...skipping 637 matching lines...) Expand 10 before | Expand all | Expand 10 after
1133 deleter = next( 1203 deleter = next(
1134 method 1204 method
1135 for method in interface.operations 1205 for method in interface.operations
1136 if ('deleter' in method.specials and 1206 if ('deleter' in method.specials and
1137 len(method.arguments) == 1 and 1207 len(method.arguments) == 1 and
1138 str(method.arguments[0].idl_type) == 'DOMString')) 1208 str(method.arguments[0].idl_type) == 'DOMString'))
1139 except StopIteration: 1209 except StopIteration:
1140 return None 1210 return None
1141 1211
1142 return property_deleter(deleter) 1212 return property_deleter(deleter)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698