from v8_globals import includes
import v8_methods
import v8_types
-from v8_types import inherits_interface
+from v8_types import inherits_interface, is_interface_type
import v8_utilities
-from v8_utilities import capitalize, conditional_string, cpp_name, has_extended_attribute, has_extended_attribute_value, runtime_enabled_function_name
+from v8_utilities import capitalize, conditional_string, cpp_name, has_extended_attribute_value, runtime_enabled_function_name
INTERFACE_H_INCLUDES = set([
'bindings/v8/V8Binding.h',
'bindings/v8/V8DOMWrapper.h',
'bindings/v8/WrapperTypeInfo.h',
+ 'heap/Handle.h',
])
INTERFACE_CPP_INCLUDES = set([
'RuntimeEnabledFeatures.h',
'core/dom/ContextFeatures.h',
'core/dom/Document.h',
'platform/TraceEvent.h',
+ 'wtf/GetPtr.h', # FIXME: remove if can eliminate WTF::getPtr
+ 'wtf/RefPtr.h',
])
if is_check_security:
includes.add('bindings/v8/BindingSecurity.h')
+ # [MeasureAs]
+ is_measure_as = 'MeasureAs' in extended_attributes
+ if is_measure_as:
+ includes.add('core/frame/UseCounter.h')
+
# [SetWrapperReferenceFrom]
reachable_node_function = extended_attributes.get('SetWrapperReferenceFrom')
if reachable_node_function:
includes.update(['bindings/v8/V8GCController.h',
'core/dom/Element.h'])
- # [MeasureAs]
- is_measure_as = 'MeasureAs' in extended_attributes
- if is_measure_as:
- includes.add('core/frame/UseCounter.h')
-
# [SetWrapperReferenceTo]
set_wrapper_reference_to_list = [{
'name': argument.name,
for special_wrap_interface in special_wrap_for:
v8_types.add_includes_for_type(special_wrap_interface)
+ # [WillBeGarbageCollected]
+ is_will_be_garbage_collected = 'WillBeGarbageCollected' in extended_attributes
+
template_contents = {
'conditional_string': conditional_string(interface), # [Conditional]
'cpp_class': cpp_name(interface),
'is_document': is_document,
'is_event_target': inherits_interface(interface.name, 'EventTarget'),
'is_exception': interface.is_exception,
+ 'is_will_be_garbage_collected': is_will_be_garbage_collected,
'is_node': inherits_interface(interface.name, 'Node'),
'measure_as': v8_utilities.measure_as(interface), # [MeasureAs]
'parent_interface': parent_interface,
+ 'pass_ref_ptr': 'PassRefPtrWillBeRawPtr'
+ if is_will_be_garbage_collected else 'PassRefPtr',
'reachable_node_function': reachable_node_function,
+ 'ref_ptr': 'RefPtrWillBeRawPtr'
+ if is_will_be_garbage_collected else 'RefPtr',
'runtime_enabled_function': runtime_enabled_function_name(interface), # [RuntimeEnabled]
'set_wrapper_reference_to_list': set_wrapper_reference_to_list,
'special_wrap_for': special_wrap_for,
template_contents.update({
'attributes': attributes,
'has_accessors': any(attribute['is_expose_js_accessors'] for attribute in attributes),
+ 'has_attribute_configuration': any(
+ not (attribute['is_expose_js_accessors'] or
+ attribute['is_static'] or
+ attribute['runtime_enabled_function'] or
+ attribute['per_context_enabled_function'])
+ for attribute in attributes),
'has_constructor_attributes': any(attribute['constructor_type'] for attribute in attributes),
'has_per_context_enabled_attributes': any(attribute['per_context_enabled_function'] for attribute in attributes),
'has_replaceable_attributes': any(attribute['is_replaceable'] for attribute in attributes),
# Methods
methods = [v8_methods.generate_method(interface, method)
- for method in interface.operations]
+ for method in interface.operations
+ if method.name] # Skip anonymous special operations (methods)
generate_overloads(methods)
for method in methods:
method['do_generate_method_configuration'] = (
'methods': methods,
})
+ template_contents.update({
+ 'indexed_property_getter': indexed_property_getter(interface),
+ 'indexed_property_setter': indexed_property_setter(interface),
+ 'indexed_property_deleter': indexed_property_deleter(interface),
+ 'is_override_builtins': 'OverrideBuiltins' in extended_attributes,
+ 'named_property_getter': named_property_getter(interface),
+ 'named_property_setter': named_property_setter(interface),
+ 'named_property_deleter': named_property_deleter(interface),
+ })
+
return template_contents
def overload_check_argument(index, argument):
+ def null_or_optional_check():
+ # If undefined is passed for an optional argument, the argument should
+ # be treated as missing; otherwise undefined is not allowed.
+ if argument['is_nullable']:
+ if argument['is_optional']:
+ return 'isUndefinedOrNull(%s)'
+ return '%s->IsNull()'
+ if argument['is_optional']:
+ return '%s->IsUndefined()'
+ return None
+
cpp_value = 'info[%s]' % index
idl_type = argument['idl_type']
# FIXME: proper type checking, sharing code with attributes and methods
if argument['is_nullable']:
type_check = ' || '.join(['%s->IsNull()' % cpp_value, type_check])
return type_check
- if v8_types.is_interface_type(idl_type):
+ if is_interface_type(idl_type):
# Non-wrapper types are just objects: we don't distinguish type
+ # We only allow undefined for non-wrapper types (notably Dictionary),
+ # as we need it for optional Dictionary arguments, but we don't want to
+ # change behavior of existing bindings for other types.
type_check = '%s->IsObject()' % cpp_value
- if argument['is_nullable']:
- type_check = ' || '.join(['%s->IsNull()' % cpp_value, type_check])
+ added_check_template = null_or_optional_check()
+ if added_check_template:
+ type_check = ' || '.join([added_check_template % cpp_value,
+ type_check])
return type_check
return None
'argument_list': constructor_argument_list(interface, constructor),
'arguments': [constructor_argument(argument, index)
for index, argument in enumerate(constructor.arguments)],
- 'has_exception_state': interface.extended_attributes.get('RaisesException') == 'Constructor', # [RaisesException=Constructor]
+ 'has_exception_state':
+ # [RaisesException=Constructor]
+ interface.extended_attributes.get('RaisesException') == 'Constructor' or
+ any(argument for argument in constructor.arguments
+ if argument.idl_type == 'SerializedScriptValue' or
+ v8_types.is_integer_type(argument.idl_type)),
'is_constructor': True,
'is_variadic': False, # Required for overload resolution
'number_of_required_arguments':
return 0
return min(constructor['number_of_required_arguments']
for constructor in constructors)
+
+
+################################################################################
+# Special operations (methods)
+# http://heycam.github.io/webidl/#idl-special-operations
+################################################################################
+
+def property_getter(getter, cpp_arguments):
+ def is_null_expression(idl_type):
+ if v8_types.is_union_type(idl_type):
+ return ' && '.join('!result%sEnabled' % i
+ for i, _ in
+ enumerate(idl_type.union_member_types))
+ if idl_type == 'DOMString':
+ return 'result.isNull()'
+ if is_interface_type(idl_type):
+ return '!result'
+ return ''
+
+ idl_type = getter.idl_type
+ extended_attributes = getter.extended_attributes
+ is_raises_exception = 'RaisesException' in extended_attributes
+
+ if v8_types.is_union_type(idl_type):
+ release = [v8_types.is_interface_type(union_member_type)
+ for union_member_type in idl_type.union_member_types]
+ else:
+ release = v8_types.is_interface_type(idl_type)
+
+ # FIXME: make more generic, so can use v8_methods.cpp_value
+ cpp_method_name = 'imp->%s' % cpp_name(getter)
+
+ if is_raises_exception:
+ cpp_arguments.append('exceptionState')
+ this_union_arguments = v8_methods.union_arguments(idl_type)
+ if this_union_arguments:
+ cpp_arguments.extend(this_union_arguments)
+
+ cpp_value = '%s(%s)' % (cpp_method_name, ', '.join(cpp_arguments))
+
+ return {
+ 'cpp_type': v8_types.cpp_type(idl_type),
+ 'cpp_value': cpp_value,
+ 'is_custom':
+ 'Custom' in extended_attributes and
+ (not extended_attributes['Custom'] or
+ has_extended_attribute_value(getter, 'Custom', 'PropertyGetter')),
+ 'is_custom_property_enumerator': has_extended_attribute_value(
+ getter, 'Custom', 'PropertyEnumerator'),
+ 'is_custom_property_query': has_extended_attribute_value(
+ getter, 'Custom', 'PropertyQuery'),
+ 'is_enumerable': 'NotEnumerable' not in extended_attributes,
+ 'is_null_expression': is_null_expression(idl_type),
+ 'is_raises_exception': is_raises_exception,
+ 'name': cpp_name(getter),
+ 'union_arguments': v8_methods.union_arguments(idl_type),
+ 'v8_set_return_value': v8_types.v8_set_return_value(idl_type, 'result', extended_attributes=extended_attributes, script_wrappable='imp', release=release),
+ }
+
+
+def property_setter(setter):
+ idl_type = setter.arguments[1].idl_type
+ extended_attributes = setter.extended_attributes
+ is_raises_exception = 'RaisesException' in extended_attributes
+ return {
+ 'has_strict_type_checking':
+ 'StrictTypeChecking' in extended_attributes and
+ v8_types.is_wrapper_type(idl_type),
+ 'idl_type': idl_type,
+ 'is_custom': 'Custom' in extended_attributes,
+ 'has_exception_state': is_raises_exception or
+ v8_types.is_integer_type(idl_type),
+ 'is_raises_exception': is_raises_exception,
+ 'name': cpp_name(setter),
+ 'v8_value_to_local_cpp_value': v8_types.v8_value_to_local_cpp_value(
+ idl_type, extended_attributes, 'jsValue', 'propertyValue'),
+ }
+
+
+def property_deleter(deleter):
+ idl_type = deleter.idl_type
+ if idl_type != 'boolean':
+ raise Exception(
+ 'Only deleters with boolean type are allowed, but type is "%s"' %
+ idl_type)
+ extended_attributes = deleter.extended_attributes
+ return {
+ 'is_custom': 'Custom' in extended_attributes,
+ 'is_raises_exception': 'RaisesException' in extended_attributes,
+ 'name': cpp_name(deleter),
+ }
+
+
+################################################################################
+# Indexed properties
+# http://heycam.github.io/webidl/#idl-indexed-properties
+################################################################################
+
+def indexed_property_getter(interface):
+ try:
+ # Find indexed property getter, if present; has form:
+ # getter TYPE [OPTIONAL_IDENTIFIER](unsigned long ARG1)
+ getter = next(
+ method
+ for method in interface.operations
+ if ('getter' in method.specials and
+ len(method.arguments) == 1 and
+ method.arguments[0].idl_type == 'unsigned long'))
+ except StopIteration:
+ return None
+
+ return property_getter(getter, ['index'])
+
+
+def indexed_property_setter(interface):
+ try:
+ # Find indexed property setter, if present; has form:
+ # setter RETURN_TYPE [OPTIONAL_IDENTIFIER](unsigned long ARG1, ARG_TYPE ARG2)
+ setter = next(
+ method
+ for method in interface.operations
+ if ('setter' in method.specials and
+ len(method.arguments) == 2 and
+ method.arguments[0].idl_type == 'unsigned long'))
+ except StopIteration:
+ return None
+
+ return property_setter(setter)
+
+
+def indexed_property_deleter(interface):
+ try:
+ # Find indexed property deleter, if present; has form:
+ # deleter TYPE [OPTIONAL_IDENTIFIER](unsigned long ARG)
+ deleter = next(
+ method
+ for method in interface.operations
+ if ('deleter' in method.specials and
+ len(method.arguments) == 1 and
+ method.arguments[0].idl_type == 'unsigned long'))
+ except StopIteration:
+ return None
+
+ return property_deleter(deleter)
+
+
+################################################################################
+# Named properties
+# http://heycam.github.io/webidl/#idl-named-properties
+################################################################################
+
+def named_property_getter(interface):
+ try:
+ # Find named property getter, if present; has form:
+ # getter TYPE [OPTIONAL_IDENTIFIER](DOMString ARG1)
+ getter = next(
+ method
+ for method in interface.operations
+ if ('getter' in method.specials and
+ len(method.arguments) == 1 and
+ method.arguments[0].idl_type == 'DOMString'))
+ except StopIteration:
+ return None
+
+ getter.name = getter.name or 'anonymousNamedGetter'
+ return property_getter(getter, ['propertyName'])
+
+
+def named_property_setter(interface):
+ try:
+ # Find named property setter, if present; has form:
+ # setter RETURN_TYPE [OPTIONAL_IDENTIFIER](DOMString ARG1, ARG_TYPE ARG2)
+ setter = next(
+ method
+ for method in interface.operations
+ if ('setter' in method.specials and
+ len(method.arguments) == 2 and
+ method.arguments[0].idl_type == 'DOMString'))
+ except StopIteration:
+ return None
+
+ return property_setter(setter)
+
+
+def named_property_deleter(interface):
+ try:
+ # Find named property deleter, if present; has form:
+ # deleter TYPE [OPTIONAL_IDENTIFIER](DOMString ARG)
+ deleter = next(
+ method
+ for method in interface.operations
+ if ('deleter' in method.specials and
+ len(method.arguments) == 1 and
+ method.arguments[0].idl_type == 'DOMString'))
+ except StopIteration:
+ return None
+
+ return property_deleter(deleter)