Commit 98e95e3a authored by jl@opera.com's avatar jl@opera.com

IDL: Use IdlArrayOrSequenceType for array/sequence IDL types

Representing array and sequence types this way, rather than via auxiliary
flags on the member type, means exotic types like array-of-arrays,
array-of-sequences, arrays-of-nullables and similar can be supported.

More importantly, this also means that an array or sequence type can't be
mistaken for its member type if you forget to check the "is array" and
"is sequence" flags, and thus lets us remove a bunch of "is this an array
or sequence type" checks from code that has nothing to do with supporting
arrays or sequences.

This patch doesn't change code generation.

Review URL: https://codereview.chromium.org/470063003

git-svn-id: svn://svn.chromium.org/blink/trunk@180298 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 76388fcd
...@@ -62,7 +62,7 @@ Design doc: http://www.chromium.org/developers/design-documents/idl-compiler ...@@ -62,7 +62,7 @@ Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
import abc import abc
from idl_types import IdlType, IdlUnionType from idl_types import IdlType, IdlUnionType, IdlArrayType, IdlSequenceType
SPECIAL_KEYWORD_LIST = ['GETTER', 'SETTER', 'DELETER'] SPECIAL_KEYWORD_LIST = ['GETTER', 'SETTER', 'DELETER']
STANDARD_TYPEDEFS = { STANDARD_TYPEDEFS = {
...@@ -755,25 +755,23 @@ def type_node_to_type(node): ...@@ -755,25 +755,23 @@ def type_node_to_type(node):
if len(children) < 1 or len(children) > 2: if len(children) < 1 or len(children) > 2:
raise ValueError('Type node expects 1 or 2 children (type + optional array []), got %s (multi-dimensional arrays are not supported).' % len(children)) raise ValueError('Type node expects 1 or 2 children (type + optional array []), got %s (multi-dimensional arrays are not supported).' % len(children))
is_nullable = node.GetProperty('NULLABLE') or False # syntax: T?
type_node_child = children[0] type_node_child = children[0]
base_type = type_node_inner_to_type(type_node_child, is_nullable=is_nullable)
if len(children) == 2: if len(children) == 2:
array_node = children[1] array_node = children[1]
array_node_class = array_node.GetClass() array_node_class = array_node.GetClass()
if array_node_class != 'Array': if array_node_class != 'Array':
raise ValueError('Expected Array node as TypeSuffix, got %s node.' % array_node_class) raise ValueError('Expected Array node as TypeSuffix, got %s node.' % array_node_class)
# FIXME: use IdlArrayType instead of is_array, once have that array_is_nullable = array_node.GetProperty('NULLABLE') or False
is_array = True return IdlArrayType(base_type, is_nullable=array_is_nullable)
else:
is_array = False
is_nullable = node.GetProperty('NULLABLE') or False # syntax: T?
return type_node_inner_to_type(type_node_child, is_array=is_array, is_nullable=is_nullable) return base_type
def type_node_inner_to_type(node, is_array=False, is_nullable=False): def type_node_inner_to_type(node, is_nullable=False):
# FIXME: remove is_array and is_nullable once have IdlArrayType and IdlNullableType # FIXME: remove is_nullable once have IdlNullableType
node_class = node.GetClass() node_class = node.GetClass()
# Note Type*r*ef, not Typedef, meaning the type is an identifier, thus # Note Type*r*ef, not Typedef, meaning the type is an identifier, thus
# either a typedef shorthand (but not a Typedef declaration itself) or an # either a typedef shorthand (but not a Typedef declaration itself) or an
...@@ -781,17 +779,13 @@ def type_node_inner_to_type(node, is_array=False, is_nullable=False): ...@@ -781,17 +779,13 @@ def type_node_inner_to_type(node, is_array=False, is_nullable=False):
if node_class in ['PrimitiveType', 'Typeref']: if node_class in ['PrimitiveType', 'Typeref']:
# unrestricted syntax: unrestricted double | unrestricted float # unrestricted syntax: unrestricted double | unrestricted float
is_unrestricted = node.GetProperty('UNRESTRICTED') or False is_unrestricted = node.GetProperty('UNRESTRICTED') or False
return IdlType(node.GetName(), is_array=is_array, is_nullable=is_nullable, is_unrestricted=is_unrestricted) return IdlType(node.GetName(), is_nullable=is_nullable, is_unrestricted=is_unrestricted)
elif node_class == 'Any': elif node_class == 'Any':
return IdlType('any', is_array=is_array, is_nullable=is_nullable) return IdlType('any', is_nullable=is_nullable)
elif node_class == 'Sequence': elif node_class == 'Sequence':
if is_array:
raise ValueError('Arrays of sequences are not supported')
sequence_is_nullable = node.GetProperty('NULLABLE') or False sequence_is_nullable = node.GetProperty('NULLABLE') or False
return sequence_node_to_type(node, is_nullable=sequence_is_nullable) return sequence_node_to_type(node, is_nullable=sequence_is_nullable)
elif node_class == 'UnionType': elif node_class == 'UnionType':
if is_array:
raise ValueError('Arrays of unions are not supported')
return union_type_node_to_idl_union_type(node, is_nullable=is_nullable) return union_type_node_to_idl_union_type(node, is_nullable=is_nullable)
raise ValueError('Unrecognized node class: %s' % node_class) raise ValueError('Unrecognized node class: %s' % node_class)
...@@ -804,8 +798,8 @@ def sequence_node_to_type(node, is_nullable=False): ...@@ -804,8 +798,8 @@ def sequence_node_to_type(node, is_nullable=False):
sequence_child_class = sequence_child.GetClass() sequence_child_class = sequence_child.GetClass()
if sequence_child_class != 'Type': if sequence_child_class != 'Type':
raise ValueError('Unrecognized node class: %s' % sequence_child_class) raise ValueError('Unrecognized node class: %s' % sequence_child_class)
element_type = type_node_to_type(sequence_child).base_type element_type = type_node_to_type(sequence_child)
return IdlType(element_type, is_sequence=True, is_nullable=is_nullable) return IdlSequenceType(element_type, is_nullable=is_nullable)
def typedef_node_to_type(node): def typedef_node_to_type(node):
......
...@@ -140,7 +140,6 @@ def attribute_context(interface, attribute): ...@@ -140,7 +140,6 @@ def attribute_context(interface, attribute):
'runtime_enabled_function': v8_utilities.runtime_enabled_function_name(attribute), # [RuntimeEnabled] 'runtime_enabled_function': v8_utilities.runtime_enabled_function_name(attribute), # [RuntimeEnabled]
'setter_callback': setter_callback_name(interface, attribute), 'setter_callback': setter_callback_name(interface, attribute),
'should_be_exposed_to_script': not (is_implemented_in_private_script and is_only_exposed_to_private_script), 'should_be_exposed_to_script': not (is_implemented_in_private_script and is_only_exposed_to_private_script),
'v8_type': v8_types.v8_type(base_idl_type),
'world_suffixes': ['', 'ForMainWorld'] 'world_suffixes': ['', 'ForMainWorld']
if 'PerWorldBindings' in extended_attributes if 'PerWorldBindings' in extended_attributes
else [''], # [PerWorldBindings] else [''], # [PerWorldBindings]
...@@ -375,7 +374,7 @@ def setter_expression(interface, attribute, context): ...@@ -375,7 +374,7 @@ def setter_expression(interface, attribute, context):
arguments.append('V8EventListenerList::findOrCreateWrapper<V8ErrorHandler>(v8Value, true, ScriptState::current(info.GetIsolate()))') arguments.append('V8EventListenerList::findOrCreateWrapper<V8ErrorHandler>(v8Value, true, ScriptState::current(info.GetIsolate()))')
else: else:
arguments.append('V8EventListenerList::getEventListener(ScriptState::current(info.GetIsolate()), v8Value, true, ListenerFindOrCreate)') arguments.append('V8EventListenerList::getEventListener(ScriptState::current(info.GetIsolate()), v8Value, true, ListenerFindOrCreate)')
elif idl_type.is_interface_type and not idl_type.array_element_type: elif idl_type.is_interface_type:
# FIXME: should be able to eliminate WTF::getPtr in most or all cases # FIXME: should be able to eliminate WTF::getPtr in most or all cases
arguments.append('WTF::getPtr(cppValue)') arguments.append('WTF::getPtr(cppValue)')
else: else:
...@@ -496,7 +495,7 @@ idl_types.IdlType.constructor_type_name = property( ...@@ -496,7 +495,7 @@ idl_types.IdlType.constructor_type_name = property(
def is_constructor_attribute(attribute): def is_constructor_attribute(attribute):
# FIXME: replace this with [ConstructorAttribute] extended attribute # FIXME: replace this with [ConstructorAttribute] extended attribute
return attribute.idl_type.base_type.endswith('Constructor') return attribute.idl_type.name.endswith('Constructor')
def constructor_getter_context(interface, attribute, context): def constructor_getter_context(interface, attribute, context):
......
...@@ -83,7 +83,6 @@ def member_context(member): ...@@ -83,7 +83,6 @@ def member_context(member):
'name': member.name, 'name': member.name,
'setter_name': setter_name_for_dictionary_member(member), 'setter_name': setter_name_for_dictionary_member(member),
'v8_default_value': v8_default_value, 'v8_default_value': v8_default_value,
'v8_type': v8_types.v8_type(idl_type.base_type),
} }
......
...@@ -54,7 +54,7 @@ CUSTOM_REGISTRATION_EXTENDED_ATTRIBUTES = frozenset([ ...@@ -54,7 +54,7 @@ CUSTOM_REGISTRATION_EXTENDED_ATTRIBUTES = frozenset([
def argument_needs_try_catch(argument, return_promise): def argument_needs_try_catch(argument, return_promise):
idl_type = argument.idl_type idl_type = argument.idl_type
base_type = not idl_type.native_array_element_type and idl_type.base_type base_type = idl_type.base_type
return not ( return not (
# These cases are handled by separate code paths in the # These cases are handled by separate code paths in the
...@@ -234,7 +234,7 @@ def argument_context(interface, method, argument, index): ...@@ -234,7 +234,7 @@ def argument_context(interface, method, argument, index):
has_extended_attribute_value(method, 'TypeChecking', 'Unrestricted')) and has_extended_attribute_value(method, 'TypeChecking', 'Unrestricted')) and
idl_type.name in ('Float', 'Double'), idl_type.name in ('Float', 'Double'),
# Dictionary is special-cased, but arrays and sequences shouldn't be # Dictionary is special-cased, but arrays and sequences shouldn't be
'idl_type': not idl_type.native_array_element_type and idl_type.base_type, 'idl_type': idl_type.base_type,
'idl_type_object': idl_type, 'idl_type_object': idl_type,
'index': index, 'index': index,
'is_clamp': 'Clamp' in extended_attributes, 'is_clamp': 'Clamp' in extended_attributes,
......
...@@ -39,7 +39,7 @@ Design doc: http://www.chromium.org/developers/design-documents/idl-compiler ...@@ -39,7 +39,7 @@ Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
import posixpath import posixpath
from idl_types import IdlTypeBase, IdlType, IdlUnionType from idl_types import IdlTypeBase, IdlType, IdlUnionType, IdlArrayOrSequenceType
import v8_attributes # for IdlType.constructor_type_name import v8_attributes # for IdlType.constructor_type_name
from v8_globals import includes from v8_globals import includes
...@@ -152,7 +152,7 @@ def cpp_type(idl_type, extended_attributes=None, raw_type=False, used_as_rvalue_ ...@@ -152,7 +152,7 @@ def cpp_type(idl_type, extended_attributes=None, raw_type=False, used_as_rvalue_
extended_attributes = extended_attributes or {} extended_attributes = extended_attributes or {}
idl_type = idl_type.preprocessed_type idl_type = idl_type.preprocessed_type
# Composite types # Array or sequence types
if used_as_variadic_argument: if used_as_variadic_argument:
native_array_element_type = idl_type native_array_element_type = idl_type
else: else:
...@@ -227,6 +227,11 @@ IdlUnionType.cpp_type_initializer = property(cpp_type_initializer_union) ...@@ -227,6 +227,11 @@ IdlUnionType.cpp_type_initializer = property(cpp_type_initializer_union)
IdlUnionType.cpp_type_args = cpp_type_union IdlUnionType.cpp_type_args = cpp_type_union
IdlTypeBase.native_array_element_type = None
IdlArrayOrSequenceType.native_array_element_type = property(
lambda self: self.element_type)
def cpp_template_type(template, inner_type): def cpp_template_type(template, inner_type):
"""Returns C++ template specialized to type, with space added if needed.""" """Returns C++ template specialized to type, with space added if needed."""
if inner_type.endswith('>'): if inner_type.endswith('>'):
...@@ -347,11 +352,6 @@ INCLUDES_FOR_TYPE = { ...@@ -347,11 +352,6 @@ INCLUDES_FOR_TYPE = {
def includes_for_type(idl_type): def includes_for_type(idl_type):
idl_type = idl_type.preprocessed_type idl_type = idl_type.preprocessed_type
# Composite types
native_array_element_type = idl_type.native_array_element_type
if native_array_element_type:
return includes_for_type(native_array_element_type)
# Simple types # Simple types
base_idl_type = idl_type.base_type base_idl_type = idl_type.base_type
if base_idl_type in INCLUDES_FOR_TYPE: if base_idl_type in INCLUDES_FOR_TYPE:
...@@ -379,6 +379,8 @@ IdlType.includes_for_type = property(includes_for_type) ...@@ -379,6 +379,8 @@ IdlType.includes_for_type = property(includes_for_type)
IdlUnionType.includes_for_type = property( IdlUnionType.includes_for_type = property(
lambda self: set.union(*[includes_for_type(member_type) lambda self: set.union(*[includes_for_type(member_type)
for member_type in self.member_types])) for member_type in self.member_types]))
IdlArrayOrSequenceType.includes_for_type = property(
lambda self: self.element_type.includes_for_type)
def add_includes_for_type(idl_type): def add_includes_for_type(idl_type):
...@@ -472,7 +474,7 @@ def v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, index, isolat ...@@ -472,7 +474,7 @@ def v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, index, isolat
if idl_type.name == 'void': if idl_type.name == 'void':
return '' return ''
# Composite types # Array or sequence types
native_array_element_type = idl_type.native_array_element_type native_array_element_type = idl_type.native_array_element_type
if native_array_element_type: if native_array_element_type:
return v8_value_to_cpp_value_array_or_sequence(native_array_element_type, v8_value, index) return v8_value_to_cpp_value_array_or_sequence(native_array_element_type, v8_value, index)
...@@ -537,7 +539,7 @@ def v8_value_to_local_cpp_value(idl_type, extended_attributes, v8_value, variabl ...@@ -537,7 +539,7 @@ def v8_value_to_local_cpp_value(idl_type, extended_attributes, v8_value, variabl
idl_type = idl_type.preprocessed_type idl_type = idl_type.preprocessed_type
cpp_value = v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, index, isolate) cpp_value = v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, index, isolate)
args = [variable_name, cpp_value] args = [variable_name, cpp_value]
if idl_type.base_type == 'DOMString' and not idl_type.native_array_element_type: if idl_type.base_type == 'DOMString':
macro = 'TOSTRING_DEFAULT' if used_in_private_script else 'TOSTRING_VOID' macro = 'TOSTRING_DEFAULT' if used_in_private_script else 'TOSTRING_VOID'
elif idl_type.may_raise_exception_on_conversion: elif idl_type.may_raise_exception_on_conversion:
macro = 'TONATIVE_DEFAULT_EXCEPTIONSTATE' if used_in_private_script else 'TONATIVE_VOID_EXCEPTIONSTATE' macro = 'TONATIVE_DEFAULT_EXCEPTIONSTATE' if used_in_private_script else 'TONATIVE_VOID_EXCEPTIONSTATE'
...@@ -614,7 +616,11 @@ def v8_conversion_type(idl_type, extended_attributes): ...@@ -614,7 +616,11 @@ def v8_conversion_type(idl_type, extended_attributes):
""" """
extended_attributes = extended_attributes or {} extended_attributes = extended_attributes or {}
# Composite types # FIXME: Support union type.
if idl_type.is_union_type:
return ''
# Array or sequence types
native_array_element_type = idl_type.native_array_element_type native_array_element_type = idl_type.native_array_element_type
if native_array_element_type: if native_array_element_type:
if native_array_element_type.is_interface_type: if native_array_element_type.is_interface_type:
...@@ -733,6 +739,7 @@ IdlType.release = property(lambda self: self.is_interface_type) ...@@ -733,6 +739,7 @@ IdlType.release = property(lambda self: self.is_interface_type)
IdlUnionType.release = property( IdlUnionType.release = property(
lambda self: [member_type.is_interface_type lambda self: [member_type.is_interface_type
for member_type in self.member_types]) for member_type in self.member_types])
IdlArrayOrSequenceType.release = False
CPP_VALUE_TO_V8_VALUE = { CPP_VALUE_TO_V8_VALUE = {
...@@ -795,8 +802,7 @@ def cpp_type_has_null_value(idl_type): ...@@ -795,8 +802,7 @@ def cpp_type_has_null_value(idl_type):
# i.e. one for which String::isNull() returns true. # i.e. one for which String::isNull() returns true.
# - Wrapper types (raw pointer or RefPtr/PassRefPtr) represent null as # - Wrapper types (raw pointer or RefPtr/PassRefPtr) represent null as
# a null pointer. # a null pointer.
return ((idl_type.is_string_type or idl_type.is_wrapper_type) and return idl_type.is_string_type or idl_type.is_wrapper_type
not idl_type.native_array_element_type)
IdlTypeBase.cpp_type_has_null_value = property(cpp_type_has_null_value) IdlTypeBase.cpp_type_has_null_value = property(cpp_type_has_null_value)
......
...@@ -85,7 +85,7 @@ const v8::PropertyCallbackInfo<v8::Value>& info ...@@ -85,7 +85,7 @@ const v8::PropertyCallbackInfo<v8::Value>& info
{% endif %} {% endif %}
{# v8SetReturnValue #} {# v8SetReturnValue #}
{% if attribute.is_keep_alive_for_gc %} {% if attribute.is_keep_alive_for_gc %}
if ({{attribute.cpp_value}} && DOMDataStore::setReturnValueFromWrapper{{world_suffix}}<{{attribute.v8_type}}>(info.GetReturnValue(), {{attribute.cpp_value}}.get())) if ({{attribute.cpp_value}} && DOMDataStore::setReturnValueFromWrapper{{world_suffix}}<V8{{attribute.idl_type}}>(info.GetReturnValue(), {{attribute.cpp_value}}.get()))
return; return;
v8::Handle<v8::Value> wrapper = toV8({{attribute.cpp_value}}.get(), holder, info.GetIsolate()); v8::Handle<v8::Value> wrapper = toV8({{attribute.cpp_value}}.get(), holder, info.GetIsolate());
if (!wrapper.IsEmpty()) { if (!wrapper.IsEmpty()) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment