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

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

Issue 328663003: IDL: restructure logic handling registration of methods (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: rebased Created 6 years, 6 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
« no previous file with comments | « no previous file | Source/bindings/scripts/v8_methods.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 'has_constructor_attributes': any(attribute['constructor_type'] for attr ibute in attributes), 243 'has_constructor_attributes': any(attribute['constructor_type'] for attr ibute in attributes),
244 'has_per_context_enabled_attributes': any(attribute['per_context_enabled _function'] for attribute in attributes), 244 'has_per_context_enabled_attributes': any(attribute['per_context_enabled _function'] for attribute in attributes),
245 'has_replaceable_attributes': any(attribute['is_replaceable'] for attrib ute in attributes), 245 'has_replaceable_attributes': any(attribute['is_replaceable'] for attrib ute in attributes),
246 }) 246 })
247 247
248 # Methods 248 # Methods
249 methods = [v8_methods.generate_method(interface, method) 249 methods = [v8_methods.generate_method(interface, method)
250 for method in interface.operations 250 for method in interface.operations
251 if method.name] # Skip anonymous special operations (methods) 251 if method.name] # Skip anonymous special operations (methods)
252 generate_method_overloads(methods) 252 generate_method_overloads(methods)
253
254 per_context_enabled_methods = []
255 custom_registration_methods = []
256 method_configuration_methods = []
257
253 for method in methods: 258 for method in methods:
254 method['do_generate_method_configuration'] = ( 259 # Skip all but one method in each set of overloaded methods.
255 method['do_not_check_signature'] and 260 if 'overload_index' in method and 'overloads' not in method:
256 not method['per_context_enabled_function'] and 261 continue
257 # For overloaded methods, only generate one accessor
258 ('overload_index' not in method or method['overload_index'] == 1))
259 262
263 if 'overloads' in method:
264 overloads = method['overloads']
265 per_context_enabled_function = overloads['per_context_enabled_functi on_all']
266 runtime_enabled_function = overloads['runtime_enabled_function_all']
267 has_custom_registration = overloads['has_custom_registration_all']
268 else:
269 per_context_enabled_function = method['per_context_enabled_function' ]
270 runtime_enabled_function = method['runtime_enabled_function']
271 has_custom_registration = method['has_custom_registration']
272
273 if per_context_enabled_function:
274 per_context_enabled_methods.append(method)
275 continue
276 if runtime_enabled_function or has_custom_registration:
277 custom_registration_methods.append(method)
278 continue
279 method_configuration_methods.append(method)
280
281 for method in methods:
260 # The value of the Function object’s “length” property is a Number 282 # The value of the Function object’s “length” property is a Number
261 # determined as follows: 283 # determined as follows:
262 # 1. Let S be the effective overload set for regular operations (if the 284 # 1. Let S be the effective overload set for regular operations (if the
263 # operation is a regular operation) or for static operations (if the 285 # operation is a regular operation) or for static operations (if the
264 # operation is a static operation) with identifier id on interface I and 286 # operation is a static operation) with identifier id on interface I and
265 # with argument count 0. 287 # with argument count 0.
266 # 2. Return the length of the shortest argument list of the entries in S . 288 # 2. Return the length of the shortest argument list of the entries in S .
267 # FIXME: This calculation doesn't take into account whether runtime 289 # FIXME: This calculation doesn't take into account whether runtime
268 # enabled overloads are actually enabled, so length may be incorrect. 290 # enabled overloads are actually enabled, so length may be incorrect.
269 # E.g., [RuntimeEnabled=Foo] void f(); void f(long x); 291 # E.g., [RuntimeEnabled=Foo] void f(); void f(long x);
270 # should have length 1 if Foo is not enabled, but length 0 if it is. 292 # should have length 1 if Foo is not enabled, but length 0 if it is.
271 method['length'] = (method['overloads']['minarg'] if 'overloads' in meth od else 293 method['length'] = (method['overloads']['minarg'] if 'overloads' in meth od else
272 method['number_of_required_arguments']) 294 method['number_of_required_arguments'])
273 295
274 template_contents.update({ 296 template_contents.update({
297 'custom_registration_methods': custom_registration_methods,
275 'has_origin_safe_method_setter': any( 298 'has_origin_safe_method_setter': any(
276 method['is_check_security_for_frame'] and not method['is_read_only'] 299 method['is_check_security_for_frame'] and not method['is_read_only']
277 for method in methods), 300 for method in methods),
278 'has_method_configuration': any(method['do_generate_method_configuration '] for method in methods), 301 'method_configuration_methods': method_configuration_methods,
279 'has_per_context_enabled_methods': any(method['per_context_enabled_funct ion'] for method in methods), 302 'per_context_enabled_methods': per_context_enabled_methods,
280 'methods': methods, 303 'methods': methods,
281 }) 304 })
282 305
283 template_contents.update({ 306 template_contents.update({
284 'indexed_property_getter': indexed_property_getter(interface), 307 'indexed_property_getter': indexed_property_getter(interface),
285 'indexed_property_setter': indexed_property_setter(interface), 308 'indexed_property_setter': indexed_property_setter(interface),
286 'indexed_property_deleter': indexed_property_deleter(interface), 309 'indexed_property_deleter': indexed_property_deleter(interface),
287 'is_override_builtins': 'OverrideBuiltins' in extended_attributes, 310 'is_override_builtins': 'OverrideBuiltins' in extended_attributes,
288 'named_property_getter': named_property_getter(interface), 311 'named_property_getter': named_property_getter(interface),
289 'named_property_setter': named_property_setter(interface), 312 'named_property_setter': named_property_setter(interface),
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 386
364 Sets |method.overload_index| in place for |method| in |overloads| 387 Sets |method.overload_index| in place for |method| in |overloads|
365 and returns dict of overall overload template values. 388 and returns dict of overall overload template values.
366 """ 389 """
367 assert len(overloads) > 1 # only apply to overloaded names 390 assert len(overloads) > 1 # only apply to overloaded names
368 for index, method in enumerate(overloads, 1): 391 for index, method in enumerate(overloads, 1):
369 method['overload_index'] = index 392 method['overload_index'] = index
370 393
371 effective_overloads_by_length = effective_overload_set_by_length(overloads) 394 effective_overloads_by_length = effective_overload_set_by_length(overloads)
372 lengths = [length for length, _ in effective_overloads_by_length] 395 lengths = [length for length, _ in effective_overloads_by_length]
396 name = overloads[0].get('name', '<constructor>')
373 397
374 # Check and fail if all overloads with the shortest acceptable arguments 398 # Check and fail if all overloads with the shortest acceptable arguments
375 # list are runtime enabled, since we would otherwise set 'length' on the 399 # list are runtime enabled, since we would otherwise set 'length' on the
376 # function object to an incorrect value when none of those overloads were 400 # function object to an incorrect value when none of those overloads were
377 # actually enabled at runtime. The exception is if all overloads are 401 # actually enabled at runtime. The exception is if all overloads are
378 # controlled by the same runtime enabled feature, in which case there would 402 # controlled by the same runtime enabled feature, in which case there would
379 # be no function object at all if it is not enabled. 403 # be no function object at all if it is not enabled.
380 shortest_overloads = effective_overloads_by_length[0][1] 404 shortest_overloads = effective_overloads_by_length[0][1]
381 if (all(method.get('runtime_enabled_function') 405 if (all(method.get('runtime_enabled_function')
382 for method, _, _ in shortest_overloads) and 406 for method, _, _ in shortest_overloads) and
383 not common_value(overloads, 'runtime_enabled_function')): 407 not common_value(overloads, 'runtime_enabled_function')):
384 raise ValueError('Function.length of %s depends on runtime enabled featu res' % overloads[0]['name']) 408 raise ValueError('Function.length of %s depends on runtime enabled featu res' % name)
409
410 # Check and fail if overloads disagree on any of the extended attributes
411 # that affect how the method should be registered.
412 # Skip the check for overloaded constructors, since they don't support any
413 # of the extended attributes in question.
414 if not overloads[0].get('is_constructor'):
415 overload_extended_attributes = [
416 method['custom_registration_extended_attributes']
417 for method in overloads]
418 for extended_attribute in v8_methods.CUSTOM_REGISTRATION_EXTENDED_ATTRIB UTES:
419 if common_key(overload_extended_attributes, extended_attribute) is N one:
420 raise ValueError('Overloads of %s have conflicting extended attr ibute %s'
421 % (name, extended_attribute))
385 422
386 return { 423 return {
387 'deprecate_all_as': common_value(overloads, 'deprecate_as'), # [Depreca teAs] 424 'deprecate_all_as': common_value(overloads, 'deprecate_as'), # [Depreca teAs]
388 'length_tests_methods': length_tests_methods(effective_overloads_by_leng th), 425 'length_tests_methods': length_tests_methods(effective_overloads_by_leng th),
389 'minarg': lengths[0], 426 'minarg': lengths[0],
390 # 1. Let maxarg be the length of the longest type list of the 427 # 1. Let maxarg be the length of the longest type list of the
391 # entries in S. 428 # entries in S.
392 'maxarg': lengths[-1], 429 'maxarg': lengths[-1],
393 'measure_all_as': common_value(overloads, 'measure_as'), # [MeasureAs] 430 'measure_all_as': common_value(overloads, 'measure_as'), # [MeasureAs]
431 'has_custom_registration_all': common_value(overloads, 'has_custom_regis tration'),
432 'per_context_enabled_function_all': common_value(overloads, 'per_context _enabled_function'), # [PerContextEnabled]
433 'runtime_enabled_function_all': common_value(overloads, 'runtime_enabled _function'), # [RuntimeEnabled]
394 'valid_arities': lengths 434 'valid_arities': lengths
395 # Only need to report valid arities if there is a gap in the 435 # Only need to report valid arities if there is a gap in the
396 # sequence of possible lengths, otherwise invalid length means 436 # sequence of possible lengths, otherwise invalid length means
397 # "not enough arguments". 437 # "not enough arguments".
398 if lengths[-1] - lengths[0] != len(lengths) - 1 else None, 438 if lengths[-1] - lengths[0] != len(lengths) - 1 else None,
399 } 439 }
400 440
401 441
402 def effective_overload_set(F): 442 def effective_overload_set(F):
403 """Returns the effective overload set of an overloaded function. 443 """Returns the effective overload set of an overloaded function.
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after
744 ################################################################################ 784 ################################################################################
745 785
746 def Counter(iterable): 786 def Counter(iterable):
747 # Once using Python 2.7, using collections.Counter 787 # Once using Python 2.7, using collections.Counter
748 counter = defaultdict(lambda: 0) 788 counter = defaultdict(lambda: 0)
749 for item in iterable: 789 for item in iterable:
750 counter[item] += 1 790 counter[item] += 1
751 return counter 791 return counter
752 792
753 793
794 def common(dicts, f):
795 """Returns common result of f across an iterable of dicts, or None.
796
797 Call f for each dict and return its result if the same across all dicts.
798 """
799 values = (f(d) for d in dicts)
800 first_value = next(values)
801 if all(value == first_value for value in values):
802 return first_value
803 return None
804
805
806 def common_key(dicts, key):
807 """Returns common presence of a key across an iterable of dicts, or None.
808
809 True if all dicts have the key, False if none of the dicts have the key,
810 and None if some but not all dicts have the key.
811 """
812 return common(dicts, lambda d: key in d)
813
814
754 def common_value(dicts, key): 815 def common_value(dicts, key):
755 """Returns common value of a key across an iterable of dicts, or None. 816 """Returns common value of a key across an iterable of dicts, or None.
756 817
757 Auxiliary function for overloads, so can consolidate an extended attribute 818 Auxiliary function for overloads, so can consolidate an extended attribute
758 that appears with the same value on all items in an overload set. 819 that appears with the same value on all items in an overload set.
759 """ 820 """
760 values = (d.get(key) for d in dicts) 821 return common(dicts, lambda d: d.get(key))
761 first_value = next(values)
762 if all(value == first_value for value in values):
763 return first_value
764 return None
765 822
766 823
767 def sort_and_groupby(l, key=None): 824 def sort_and_groupby(l, key=None):
768 """Returns a generator of (key, list), sorting and grouping list by key.""" 825 """Returns a generator of (key, list), sorting and grouping list by key."""
769 l.sort(key=key) 826 l.sort(key=key)
770 return ((k, list(g)) for k, g in itertools.groupby(l, key)) 827 return ((k, list(g)) for k, g in itertools.groupby(l, key))
771 828
772 829
773 ################################################################################ 830 ################################################################################
774 # Constructors 831 # Constructors
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
1033 deleter = next( 1090 deleter = next(
1034 method 1091 method
1035 for method in interface.operations 1092 for method in interface.operations
1036 if ('deleter' in method.specials and 1093 if ('deleter' in method.specials and
1037 len(method.arguments) == 1 and 1094 len(method.arguments) == 1 and
1038 str(method.arguments[0].idl_type) == 'DOMString')) 1095 str(method.arguments[0].idl_type) == 'DOMString'))
1039 except StopIteration: 1096 except StopIteration:
1040 return None 1097 return None
1041 1098
1042 return property_deleter(deleter) 1099 return property_deleter(deleter)
OLDNEW
« no previous file with comments | « no previous file | Source/bindings/scripts/v8_methods.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698