in bindings/scripts/v8_interface.py [0:0]
def methods_context(interface):
"""Creates a list of Jinja template contexts for methods of an interface.
Args:
interface: An interface to create contexts for
Returns:
A dictionary with 3 keys:
'iterator_method': An iterator context if available or None.
'iterator_method_alias': A string that can also be used to refer to the
@@iterator symbol or None.
'methods': A list of method contexts.
"""
methods = []
if interface.original_interface:
methods.extend([v8_methods.method_context(interface, operation, is_visible=False)
for operation in interface.original_interface.operations
if operation.name])
methods.extend([v8_methods.method_context(interface, method)
for method in interface.operations
if method.name]) # Skip anonymous special operations (methods)
if interface.partial_interfaces:
assert len(interface.partial_interfaces) == len(set(interface.partial_interfaces))
for partial_interface in interface.partial_interfaces:
methods.extend([v8_methods.method_context(interface, operation, is_visible=False)
for operation in partial_interface.operations
if operation.name])
compute_method_overloads_context(interface, methods)
def generated_method(return_type, name, arguments=None, extended_attributes=None, implemented_as=None):
operation = IdlOperation()
operation.idl_type = return_type
operation.name = name
if arguments:
operation.arguments = arguments
if extended_attributes:
operation.extended_attributes.update(extended_attributes)
if implemented_as is None:
implemented_as = name + 'ForBinding'
operation.extended_attributes['ImplementedAs'] = implemented_as
return v8_methods.method_context(interface, operation)
def generated_argument(idl_type, name, is_optional=False, extended_attributes=None):
argument = IdlArgument()
argument.idl_type = idl_type
argument.name = name
argument.is_optional = is_optional
if extended_attributes:
argument.extended_attributes.update(extended_attributes)
return argument
# iterable<>, maplike<> and setlike<>
iterator_method = None
# Depending on the declaration, @@iterator may be a synonym for e.g.
# 'entries' or 'values'.
iterator_method_alias = None
# FIXME: support Iterable in partial interfaces. However, we don't
# need to support iterator overloads between interface and
# partial interface definitions.
# http://heycam.github.io/webidl/#idl-overloading
if (not interface.is_partial and (
interface.iterable or interface.maplike or interface.setlike or
interface.has_indexed_elements)):
used_extended_attributes = {}
if interface.iterable:
used_extended_attributes.update(interface.iterable.extended_attributes)
elif interface.maplike:
used_extended_attributes.update(interface.maplike.extended_attributes)
elif interface.setlike:
used_extended_attributes.update(interface.setlike.extended_attributes)
if 'RaisesException' in used_extended_attributes:
raise ValueError('[RaisesException] is implied for iterable<>/maplike<>/setlike<>')
if 'CallWith' in used_extended_attributes:
raise ValueError('[CallWith=ScriptState] is implied for iterable<>/maplike<>/setlike<>')
used_extended_attributes.update({
'RaisesException': None,
'CallWith': 'ScriptState',
})
forEach_extended_attributes = used_extended_attributes.copy()
forEach_extended_attributes.update({
'CallWith': ['ScriptState', 'ThisValue'],
})
def generated_iterator_method(name, implemented_as=None):
return generated_method(
return_type=IdlType('Iterator'),
name=name,
extended_attributes=used_extended_attributes,
implemented_as=implemented_as)
if not interface.has_indexed_elements:
iterator_method = generated_iterator_method('iterator', implemented_as='GetIterator')
if interface.iterable or interface.maplike or interface.setlike:
non_overridable_methods = []
overridable_methods = []
is_value_iterator = interface.iterable and interface.iterable.key_type is None
# For value iterators, the |entries|, |forEach|, |keys| and |values| are originally set
# to corresponding properties in %ArrayPrototype%.
# For pair iterators and maplike declarations, |entries| is an alias for @@iterator
# itself. For setlike declarations, |values| is an alias for @@iterator.
if not is_value_iterator:
if not interface.setlike:
iterator_method_alias = 'entries'
entries_or_values_method = generated_iterator_method('values')
else:
iterator_method_alias = 'values'
entries_or_values_method = generated_iterator_method('entries')
non_overridable_methods.extend([
generated_iterator_method('keys'),
entries_or_values_method,
# void forEach(Function callback, [Default=Undefined] optional any thisArg)
generated_method(IdlType('void'), 'forEach',
arguments=[generated_argument(IdlType('Function'), 'callback'),
generated_argument(IdlType('any'), 'thisArg',
is_optional=True,
extended_attributes={'Default': 'Undefined'})],
extended_attributes=forEach_extended_attributes),
])
if interface.maplike:
key_argument = generated_argument(interface.maplike.key_type, 'key')
value_argument = generated_argument(interface.maplike.value_type, 'value')
non_overridable_methods.extend([
generated_method(IdlType('boolean'), 'has',
arguments=[key_argument],
extended_attributes=used_extended_attributes),
generated_method(IdlType('any'), 'get',
arguments=[key_argument],
extended_attributes=used_extended_attributes),
])
if not interface.maplike.is_read_only:
overridable_methods.extend([
generated_method(IdlType('void'), 'clear',
extended_attributes=used_extended_attributes),
generated_method(IdlType('boolean'), 'delete',
arguments=[key_argument],
extended_attributes=used_extended_attributes),
generated_method(IdlType(interface.name), 'set',
arguments=[key_argument, value_argument],
extended_attributes=used_extended_attributes),
])
if interface.setlike:
value_argument = generated_argument(interface.setlike.value_type, 'value')
non_overridable_methods.extend([
generated_method(IdlType('boolean'), 'has',
arguments=[value_argument],
extended_attributes=used_extended_attributes),
])
if not interface.setlike.is_read_only:
overridable_methods.extend([
generated_method(IdlType(interface.name), 'add',
arguments=[value_argument],
extended_attributes=used_extended_attributes),
generated_method(IdlType('void'), 'clear',
extended_attributes=used_extended_attributes),
generated_method(IdlType('boolean'), 'delete',
arguments=[value_argument],
extended_attributes=used_extended_attributes),
])
methods_by_name = {}
for method in methods:
methods_by_name.setdefault(method['name'], []).append(method)
for non_overridable_method in non_overridable_methods:
if non_overridable_method['name'] in methods_by_name:
raise ValueError(
'An interface cannot define an operation called "%s()", it '
'comes from the iterable, maplike or setlike declaration '
'in the IDL.' % non_overridable_method['name'])
methods.append(non_overridable_method)
for overridable_method in overridable_methods:
if overridable_method['name'] in methods_by_name:
# FIXME: Check that the existing method is compatible.
continue
methods.append(overridable_method)
# FIXME: maplike<> and setlike<> should also imply the presence of a
# 'size' attribute.
# Serializer
if interface.serializer:
serializer = interface.serializer
serializer_ext_attrs = serializer.extended_attributes.copy()
if serializer.operation:
return_type = serializer.operation.idl_type
implemented_as = serializer.operation.name
else:
return_type = IdlType('any')
implemented_as = None
if 'CallWith' not in serializer_ext_attrs:
serializer_ext_attrs['CallWith'] = 'ScriptState'
methods.append(generated_method(
return_type=return_type,
name='toJSON',
extended_attributes=serializer_ext_attrs,
implemented_as=implemented_as))
# Stringifier
if interface.stringifier:
stringifier = interface.stringifier
stringifier_ext_attrs = stringifier.extended_attributes.copy()
if stringifier.attribute:
implemented_as = stringifier.attribute.name
elif stringifier.operation:
implemented_as = stringifier.operation.name
else:
implemented_as = 'toString'
methods.append(generated_method(
return_type=IdlType('DOMString'),
name='toString',
extended_attributes=stringifier_ext_attrs,
implemented_as=implemented_as))
for method in methods:
# The value of the Function object’s “length” property is a Number
# determined as follows:
# 1. Let S be the effective overload set for regular operations (if the
# operation is a regular operation) or for static operations (if the
# operation is a static operation) with identifier id on interface I and
# with argument count 0.
# 2. Return the length of the shortest argument list of the entries in S.
# FIXME: This calculation doesn't take into account whether runtime
# enabled overloads are actually enabled, so length may be incorrect.
# E.g., [RuntimeEnabled=Foo] void f(); void f(long x);
# should have length 1 if Foo is not enabled, but length 0 if it is.
method['length'] = (method['overloads']['length'] if 'overloads' in method else
method['number_of_required_arguments'])
return {
'iterator_method': iterator_method,
'iterator_method_alias': iterator_method_alias,
'methods': methods,
}