diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py')
-rw-r--r-- | chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py | 303 |
1 files changed, 199 insertions, 104 deletions
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py index 8c63a4998bd..1d7ae802659 100644 --- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py +++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py @@ -2,7 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import exceptions import functools from blinkbuild.name_style_converter import NameStyleConverter @@ -48,13 +47,8 @@ class IdlTypeFactory(object): def __init__(self): self._idl_types = [] # Factory to initialize instances of ReferenceType. - attrs_to_be_proxied = ( - set(RefById.get_all_attributes(IdlType)).difference( - # attributes not to be proxied - set(('debug_info', 'extended_attributes', 'is_optional', - 'optionality')))) self._ref_by_id_factory = RefByIdFactory( - target_attrs_with_priority=attrs_to_be_proxied) + target_attrs_with_priority=RefById.get_all_attributes(IdlType)) # |_is_frozen| is initially False and you can create new instances of # IdlType. The first invocation of |for_each| freezes the factory and # you can no longer create a new instance of IdlType. @@ -167,7 +161,8 @@ class IdlType(WithExtendedAttributes, WithDebugInfo): pass_key=None): assert isinstance(is_optional, bool) assert pass_key is _IDL_TYPE_PASS_KEY - WithExtendedAttributes.__init__(self, extended_attributes) + WithExtendedAttributes.__init__( + self, extended_attributes, readonly=True) WithDebugInfo.__init__(self, debug_info) self._is_optional = is_optional @@ -182,7 +177,7 @@ class IdlType(WithExtendedAttributes, WithDebugInfo): return not self == other def __hash__(self): - raise exceptions.NotImplementedError() + raise NotImplementedError() def make_copy(self, memo): return self @@ -192,7 +187,7 @@ class IdlType(WithExtendedAttributes, WithDebugInfo): """ Returns a text representation of the type in the form of Web IDL syntax. """ - raise exceptions.NotImplementedError() + raise NotImplementedError() @property def type_name(self): @@ -201,7 +196,23 @@ class IdlType(WithExtendedAttributes, WithDebugInfo): https://heycam.github.io/webidl/#dfn-type-name Note that a type name is not necessarily unique. """ - raise exceptions.NotImplementedError() + return '{}{}'.format( + self.type_name_without_extended_attributes, ''.join( + sorted(self.effective_annotations.keys()))) + + @property + def type_name_with_extended_attribute_key_values(self): + name_pieces = [] + name_pieces.append(self.type_name_without_extended_attributes) + annotations = self.effective_annotations + for key in sorted(annotations.keys()): + name_pieces.append(key) + name_pieces.extend(annotations.values_of(key)) + return ''.join(name_pieces) + + @property + def type_name_without_extended_attributes(self): + raise NotImplementedError() @property def keyword_typename(self): @@ -220,8 +231,16 @@ class IdlType(WithExtendedAttributes, WithDebugInfo): In case of x.apply_to_all_composing_elements(callback), |callback| will be recursively called back on x, x.inner_type, x.element_type, x.result_type.original_type, etc. if any. + + If |callback| raises a StopIteration, then this function stops + traversing deeper than this type (inner type, etc.), however, siblings + are still traversed. E.g. For record<K, V>, raising a StopIteration at + K doesn't prevent from traversing V. """ - callback(self) + try: + callback(self) + except StopIteration: + return def unwrap(self, nullable=None, typedef=None, variadic=None): """ @@ -231,6 +250,7 @@ class IdlType(WithExtendedAttributes, WithDebugInfo): Args: nullable: typedef: + variadic: All these arguments take tri-state value: True, False, or None. True unwraps that type, False stops unwrapping that type. All of specified arguments' values must be consistent, and mixture @@ -245,25 +265,51 @@ class IdlType(WithExtendedAttributes, WithDebugInfo): } value_counts = {None: 0, False: 0, True: 0} - for value in switches.itervalues(): + for value in switches.values(): assert value is None or isinstance(value, bool) value_counts[value] += 1 assert value_counts[False] == 0 or value_counts[True] == 0, ( "Specify only True or False arguments. Unspecified arguments are " "automatically set to the opposite value.") default = value_counts[True] == 0 - for arg, value in switches.iteritems(): + for arg, value in switches.items(): if value is None: switches[arg] = default return self._unwrap(switches) @property + def effective_annotations(self): + """ + Returns the extended attributes associated with this IDL type. + https://heycam.github.io/webidl/#idl-type-extended-attribute-associated-with + + For example, given the following IDL fragments, + + typedef [ExtAttr1] long NewLong; + void f([ExtAttr2] NewLong arg); + + arg.idl_type.extended_attributes returns [ExtAttr2], + arg.idl_type.unwrap().extended_attributes returns [ExtAttr1], and + arg.idl_type.effective_annotations returns [ExtAttr1, ExtAttr2]. + """ + return self.extended_attributes + + @property def does_include_nullable_type(self): """ - Returns True if |self| includes a nulllable type. + Returns True if this type includes a nulllable type. https://heycam.github.io/webidl/#dfn-includes-a-nullable-type - @return bool + """ + return False + + @property + def does_include_nullable_or_dict(self): + """ + Returns True if this type includes a nullable type or a dictionary type. + + IdlType's own definition of "includes a dictionary type" just follows + the definition of "includes a nullable type". """ return False @@ -307,6 +353,11 @@ class IdlType(WithExtendedAttributes, WithDebugInfo): return False @property + def is_array_buffer_view(self): + """Returns True if this is ArrayBufferView.""" + return False + + @property def is_data_view(self): """Returns True if this is DataView.""" return False @@ -414,11 +465,6 @@ class IdlType(WithExtendedAttributes, WithDebugInfo): return False @property - def is_annotated(self): - """Returns True if this is annotated.""" - return bool(self.extended_attributes) - - @property def is_optional(self): """ Returns True if this type is used for a non-required dictionary member @@ -506,6 +552,15 @@ class IdlType(WithExtendedAttributes, WithDebugInfo): """ return None + @property + def union_definition_object(self): + """ + Returns an object that represents an union or None. + + Note that a returned object is not an IdlType. It's of type Union. + """ + return None + def _format_syntactic_form(self, syntactic_form_inner): """Helper function to implement |syntactic_form|.""" optional_form = 'optional ' if self.is_optional else '' @@ -514,11 +569,6 @@ class IdlType(WithExtendedAttributes, WithDebugInfo): return '{}{}{}'.format(optional_form, ext_attr_form, syntactic_form_inner) - def _format_type_name(self, type_name_inner): - """Helper function to implement |type_name|.""" - return '{}{}'.format(type_name_inner, ''.join( - sorted(self.extended_attributes.keys()))) - def _unwrap(self, switches): return self @@ -539,7 +589,17 @@ class SimpleType(IdlType): _TYPED_ARRAY_TYPES = ('Int8Array', 'Int16Array', 'Int32Array', 'Uint8Array', 'Uint16Array', 'Uint32Array', 'Uint8ClampedArray', 'Float32Array', 'Float64Array') - _BUFFER_SOURCE_TYPES = ('ArrayBuffer', 'DataView') + _TYPED_ARRAY_TYPES + # ArrayBufferView is not defined as a buffer source type in Web IDL, it's + # defined as an union type of all typed array types. However, practically + # it's much more convenient and reasonable for most of (if not all) use + # cases to treat ArrayBufferView as a buffer source type than as an union + # type. + # https://heycam.github.io/webidl/#ArrayBufferView + # + # Note that BufferSource is an union type as defined in Web IDL. + # https://heycam.github.io/webidl/#BufferSource + _BUFFER_SOURCE_TYPES = ( + ('ArrayBuffer', 'ArrayBufferView', 'DataView') + _TYPED_ARRAY_TYPES) _MISC_TYPES = ('any', 'boolean', 'object', 'symbol', 'void') _VALID_TYPES = set(_NUMERIC_TYPES + _STRING_TYPES + _BUFFER_SOURCE_TYPES + _MISC_TYPES) @@ -567,16 +627,14 @@ class SimpleType(IdlType): def __hash__(self): return hash(self._name) - # IdlType overrides @property def syntactic_form(self): return self._format_syntactic_form(self._name) @property - def type_name(self): + def type_name_without_extended_attributes(self): name = 'String' if self._name == 'DOMString' else self._name - return self._format_type_name( - NameStyleConverter(name).to_upper_camel_case()) + return NameStyleConverter(name).to_upper_camel_case() @property def keyword_typename(self): @@ -611,6 +669,10 @@ class SimpleType(IdlType): return self._name == 'ArrayBuffer' @property + def is_array_buffer_view(self): + return self._name == 'ArrayBufferView' + + @property def is_data_view(self): return self._name == 'DataView' @@ -672,6 +734,9 @@ class ReferenceType(IdlType, RefById): def __hash__(self): return hash(self.identifier) + def _unwrap(self, switches): + return self.target_object._unwrap(switches) + class DefinitionType(IdlType, WithIdentifier): """ @@ -682,14 +747,14 @@ class DefinitionType(IdlType, WithIdentifier): TypedefType and UnionType respectively. """ - def __init__(self, - user_defined_type, - debug_info=None, - pass_key=None): + def __init__(self, reference_type, user_defined_type, pass_key=None): + assert isinstance(reference_type, ReferenceType) assert isinstance(user_defined_type, UserDefinedType) IdlType.__init__( self, - debug_info=debug_info, + is_optional=reference_type.is_optional, + extended_attributes=reference_type.extended_attributes, + debug_info=reference_type.debug_info, pass_key=pass_key) WithIdentifier.__init__(self, user_defined_type.identifier) self._type_definition_object = user_defined_type @@ -701,20 +766,19 @@ class DefinitionType(IdlType, WithIdentifier): def __hash__(self): return hash(self.identifier) - # IdlType overrides @property def syntactic_form(self): - assert not self.extended_attributes - assert not self.is_optional - return self.identifier + return self._format_syntactic_form(self.identifier) @property - def type_name(self): - assert not self.extended_attributes - assert not self.is_optional + def type_name_without_extended_attributes(self): return self.identifier @property + def does_include_nullable_or_dict(self): + return self.is_dictionary + + @property def is_interface(self): return self.type_definition_object.is_interface @@ -750,14 +814,14 @@ class TypedefType(IdlType, WithIdentifier): can track down the typedef'ed type to |original_type|. """ - def __init__(self, - typedef, - debug_info=None, - pass_key=None): + def __init__(self, reference_type, typedef, pass_key=None): + assert isinstance(reference_type, ReferenceType) assert isinstance(typedef, Typedef) IdlType.__init__( self, - debug_info=debug_info, + is_optional=reference_type.is_optional, + extended_attributes=reference_type.extended_attributes, + debug_info=reference_type.debug_info, pass_key=pass_key) WithIdentifier.__init__(self, typedef.identifier) self._typedef = typedef @@ -769,28 +833,40 @@ class TypedefType(IdlType, WithIdentifier): def __hash__(self): return hash(self.identifier) - # IdlType overrides @property def syntactic_form(self): - assert not self.extended_attributes - assert not self.is_optional - return self.identifier + return self._format_syntactic_form(self.identifier) @property - def type_name(self): - assert not self.extended_attributes - assert not self.is_optional - return self.original_type.type_name + def type_name_without_extended_attributes(self): + return self.original_type.type_name_without_extended_attributes def apply_to_all_composing_elements(self, callback): - callback(self) + try: + callback(self) + except StopIteration: + return self.original_type.apply_to_all_composing_elements(callback) @property + def effective_annotations(self): + original_annotations = self.original_type.effective_annotations + if not self.extended_attributes: + return original_annotations + if not original_annotations: + return self.extended_attributes + return ExtendedAttributes( + list(self.extended_attributes) + list(original_annotations)) + + @property def does_include_nullable_type(self): return self.original_type.does_include_nullable_type @property + def does_include_nullable_or_dict(self): + return self.original_type.does_include_nullable_or_dict + + @property def is_typedef(self): return True @@ -827,9 +903,11 @@ class _ArrayLikeType(IdlType): def __hash__(self): return hash((self.__class__, self.element_type)) - # IdlType overrides def apply_to_all_composing_elements(self, callback): - callback(self) + try: + callback(self) + except StopIteration: + return self.element_type.apply_to_all_composing_elements(callback) @property @@ -854,16 +932,14 @@ class SequenceType(_ArrayLikeType): debug_info=debug_info, pass_key=pass_key) - # IdlType overrides @property def syntactic_form(self): return self._format_syntactic_form('sequence<{}>'.format( self.element_type.syntactic_form)) @property - def type_name(self): - return self._format_type_name('{}Sequence'.format( - self.element_type.type_name)) + def type_name_without_extended_attributes(self): + return '{}Sequence'.format(self.element_type.type_name) @property def is_sequence(self): @@ -887,16 +963,14 @@ class FrozenArrayType(_ArrayLikeType): debug_info=debug_info, pass_key=pass_key) - # IdlType overrides @property def syntactic_form(self): return self._format_syntactic_form('FrozenArray<{}>'.format( self.element_type.syntactic_form)) @property - def type_name(self): - return self._format_type_name('{}Array'.format( - self.element_type.type_name)) + def type_name_without_extended_attributes(self): + return '{}Array'.format(self.element_type.type_name) @property def is_frozen_array(self): @@ -906,17 +980,10 @@ class FrozenArrayType(_ArrayLikeType): class VariadicType(_ArrayLikeType): """Represents a type used for variadic arguments.""" - def __init__(self, - element_type, - debug_info=None, - pass_key=None): + def __init__(self, element_type, debug_info=None, pass_key=None): _ArrayLikeType.__init__( - self, - element_type, - debug_info=debug_info, - pass_key=pass_key) + self, element_type, debug_info=debug_info, pass_key=pass_key) - # IdlType overrides @property def syntactic_form(self): assert not self.extended_attributes @@ -924,10 +991,11 @@ class VariadicType(_ArrayLikeType): return '{}...'.format(self.element_type.syntactic_form) @property - def type_name(self): + def type_name_without_extended_attributes(self): # Blink-specific expansion of type name # The type name of a variadic type is the concatenation of the type # name of the element type and the string "Variadic". + assert not self.extended_attributes return '{}Variadic'.format(self.element_type.type_name) @property @@ -968,19 +1036,21 @@ class RecordType(IdlType): def __hash__(self): return hash((self.__class__, self.key_type, self.value_type)) - # IdlType overrides @property def syntactic_form(self): return self._format_syntactic_form('record<{}, {}>'.format( self.key_type.syntactic_form, self.value_type.syntactic_form)) @property - def type_name(self): - return self._format_type_name('{}{}Record'.format( - self.key_type.type_name, self.value_type.type_name)) + def type_name_without_extended_attributes(self): + return '{}{}Record'.format(self.key_type.type_name, + self.value_type.type_name) def apply_to_all_composing_elements(self, callback): - callback(self) + try: + callback(self) + except StopIteration: + return self.key_type.apply_to_all_composing_elements(callback) self.value_type.apply_to_all_composing_elements(callback) @@ -1022,19 +1092,20 @@ class PromiseType(IdlType): def __hash__(self): return hash((self.__class__, self.result_type)) - # IdlType overrides @property def syntactic_form(self): return self._format_syntactic_form('Promise<{}>'.format( self.result_type.syntactic_form)) @property - def type_name(self): - return self._format_type_name('{}Promise'.format( - self.result_type.type_name)) + def type_name_without_extended_attributes(self): + return '{}Promise'.format(self.result_type.type_name) def apply_to_all_composing_elements(self, callback): - callback(self) + try: + callback(self) + except StopIteration: + return self.result_type.apply_to_all_composing_elements(callback) @property @@ -1043,10 +1114,7 @@ class PromiseType(IdlType): @property def result_type(self): - """ - Returns the result type. - @return IdlType - """ + """Returns the result type.""" return self._result_type @@ -1068,6 +1136,7 @@ class UnionType(IdlType): debug_info=debug_info, pass_key=pass_key) self._member_types = tuple(member_types) + self._union_definition_object = None def __eq__(self, other): """ @@ -1089,19 +1158,20 @@ class UnionType(IdlType): functools.reduce(lambda x, idl_type: x + hash(idl_type), self.member_types, 0))) - # IdlType overrides @property def syntactic_form(self): return self._format_syntactic_form('({})'.format(' or '.join( [member.syntactic_form for member in self.member_types]))) @property - def type_name(self): - return self._format_type_name('Or'.join( - [member.type_name for member in self.member_types])) + def type_name_without_extended_attributes(self): + return 'Or'.join([member.type_name for member in self.member_types]) def apply_to_all_composing_elements(self, callback): - callback(self) + try: + callback(self) + except StopIteration: + return for member_type in self.member_types: member_type.apply_to_all_composing_elements(callback) @@ -1111,6 +1181,11 @@ class UnionType(IdlType): member.does_include_nullable_type for member in self.member_types) @property + def does_include_nullable_or_dict(self): + return any(member.does_include_nullable_or_dict + for member in self.member_types) + + @property def is_union(self): return True @@ -1134,6 +1209,17 @@ class UnionType(IdlType): return set(flatten(self)) + @property + def union_definition_object(self): + return self._union_definition_object + + def set_union_definition_object(self, union_definition_object): + # In Python2, we need to avoid circular imports. + from .union import Union + assert isinstance(union_definition_object, Union) + assert self._union_definition_object is None + self._union_definition_object = union_definition_object + class NullableType(IdlType): """https://heycam.github.io/webidl/#idl-nullable-type""" @@ -1160,35 +1246,44 @@ class NullableType(IdlType): def __hash__(self): return hash((self.__class__, self.inner_type)) - # IdlType overrides @property def syntactic_form(self): assert not self.extended_attributes return '{}?'.format(self.inner_type.syntactic_form) @property - def type_name(self): - assert not self.extended_attributes + def type_name_without_extended_attributes(self): # https://heycam.github.io/webidl/#idl-annotated-types # Web IDL seems not supposing a case of [X] ([Y] Type)?, i.e. something # like [X] nullable<[Y] Type>, which should turn into "TypeYOrNullX". # # In case of '[Clamp] long?', it's interpreted as '([Clamp] long)?' but # the type name must be "LongOrNullClamp" instead of "LongClampOrNull". - name = self.inner_type.type_name - ext_attrs = ''.join(sorted(self.inner_type.extended_attributes.keys())) - sep_index = len(name) - len(ext_attrs) - return '{}OrNull{}'.format(name[0:sep_index], name[sep_index:]) + assert not self.extended_attributes + return '{}OrNull'.format( + self.inner_type.type_name_without_extended_attributes) def apply_to_all_composing_elements(self, callback): - callback(self) + try: + callback(self) + except StopIteration: + return self.inner_type.apply_to_all_composing_elements(callback) @property + def effective_annotations(self): + assert not self.extended_attributes + return self.inner_type.effective_annotations + + @property def does_include_nullable_type(self): return True @property + def does_include_nullable_or_dict(self): + return True + + @property def is_nullable(self): return True |