| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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) |
| OLD | NEW |