| Index: Source/bindings/scripts/v8_interface.py
|
| diff --git a/Source/bindings/scripts/v8_interface.py b/Source/bindings/scripts/v8_interface.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..0cae79dab4826c5acbd66902d919eecd48260d17
|
| --- /dev/null
|
| +++ b/Source/bindings/scripts/v8_interface.py
|
| @@ -0,0 +1,286 @@
|
| +# Copyright (C) 2013 Google Inc. All rights reserved.
|
| +#
|
| +# Redistribution and use in source and binary forms, with or without
|
| +# modification, are permitted provided that the following conditions are
|
| +# met:
|
| +#
|
| +# * Redistributions of source code must retain the above copyright
|
| +# notice, this list of conditions and the following disclaimer.
|
| +# * Redistributions in binary form must reproduce the above
|
| +# copyright notice, this list of conditions and the following disclaimer
|
| +# in the documentation and/or other materials provided with the
|
| +# distribution.
|
| +# * Neither the name of Google Inc. nor the names of its
|
| +# contributors may be used to endorse or promote products derived from
|
| +# this software without specific prior written permission.
|
| +#
|
| +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| +# 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
| +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
| +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
| +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| +
|
| +
|
| +import struct
|
| +
|
| +from v8_utilities import generate_conditional_string, runtime_enable_function_name
|
| +
|
| +# WIP
|
| +from code_generator_idl_reader import base_interface_name, inherits_interface, interface_inherits_extended_attribute
|
| +# from v8_includes import includes_for_type
|
| +from v8_includes import *
|
| +import v8_attributes
|
| +import v8_functions
|
| +import v8_constructors
|
| +from v8_utilities import get_function_mandatory_parameters, get_feature_observation_parameter, get_deprecation_notification_parameter
|
| +import v8_special_accessors
|
| +import v8_types
|
| +# from v8_types import cpp_type, v8_type
|
| +from v8_types import *
|
| +from v8_utilities import implemented_as_cpp_name
|
| +
|
| +
|
| +################################################################################
|
| +# BRANCH
|
| +################################################################################
|
| +
|
| +
|
| +def generate_constants(interface):
|
| + return [generate_constant(constant) for constant in interface.constants]
|
| +
|
| +
|
| +def generate_constant(constant):
|
| + # Extended Attributes: Conditional, DeprecateAs, EnabledAtRuntime, Reflect
|
| + # FIXME: Conditional and DeprecateAs are only used in tests, so remove
|
| + name = constant.extended_attributes.get('Reflect', constant.name)
|
| + value_raw = constant.value
|
| + # If the value we're dealing with is a hex literal, statically cast it to a
|
| + # signed integer here, rather than dynamically casting via
|
| + # static_cast<signed int> in the generated code.
|
| + # FIXME: why are we casting to signed?
|
| + # NodeFilter has unsigned 0xFFFFFFFF, which is converted to -1.
|
| + # FIXME: is this necessary? Hex literals are valid C.
|
| + # (only semantic difference is casting to signed)
|
| + # FIXME: what about octal? decimal?
|
| + # FIXME: what if we have a negative literal?
|
| + # FIXME: BUG: Perl only checks '0x', not '0X',
|
| + # but we have a test case using 0X.
|
| + if value_raw.startswith('0x'):
|
| + value = struct.unpack('i', struct.pack('I', int(value_raw, 16)))[0]
|
| + else:
|
| + value = value_raw
|
| +
|
| + constant_parameter = {
|
| + 'name': constant.name,
|
| + 'name_reflect': name, # FIXME: use name_reflect as correct 'name'
|
| + 'value': value,
|
| + 'value_raw': value_raw,
|
| + # FIXME: remove conditional: only used in tests
|
| + 'conditional_string': generate_conditional_string(constant),
|
| + 'enabled_at_runtime': 'EnabledAtRuntime' in constant.extended_attributes,
|
| + 'enable_function': runtime_enable_function_name(constant),
|
| + }
|
| + return constant_parameter
|
| +
|
| +
|
| +################################################################################
|
| +# WIP
|
| +################################################################################
|
| +
|
| +
|
| +def generate_implementation(interface):
|
| + # __IMPL__ in Perl
|
| + cpp_class_name = implemented_as_cpp_name(interface)
|
| + v8_class_name = get_v8_class_name(interface)
|
| + includes = [
|
| + 'bindings/v8/V8Binding.h',
|
| + 'bindings/v8/V8DOMWrapper.h',
|
| + 'core/dom/ContextFeatures.h',
|
| + 'core/dom/Document.h',
|
| + 'RuntimeEnabledFeatures.h',
|
| + 'wtf/UnusedParam.h',
|
| + 'bindings/v8/V8DOMConfiguration.h',
|
| + 'core/platform/chromium/TraceEvent.h',
|
| + ]
|
| +
|
| + # FIXME: is this only to determine has_callbacks?
|
| + normal_functions = []
|
| + enabled_per_context_functions = [] # FIXME: unused
|
| + for operation in interface.operations:
|
| + if not operation.name:
|
| + continue
|
| + if 'EnabledPerContext' in operation.extended_attributes:
|
| + enabled_per_context_functions.append(operation)
|
| + else:
|
| + normal_functions.append(operation)
|
| + has_callbacks = any([
|
| + # Only one table entry is needed for overloaded methods:
|
| + operation.overload_index <= 1 and
|
| + # Don't put any nonstandard functions into this table:
|
| + get_is_standard_function(interface, operation)
|
| + for operation in normal_functions])
|
| +
|
| + inherits_extended_attribute_active_dom_object = interface_inherits_extended_attribute(interface, 'ActiveDOMObject')
|
| + inherits_event_target = inherits_interface(interface, 'EventTarget')
|
| + # has_attributes = bool(interface.attributes) # FIXME: unused
|
| + cpp_class_name_as_parameter = get_native_type(interface.name, used_as_parameter=True)
|
| +
|
| + includes += get_includes_for_type(interface.name)
|
| +
|
| + if interface.name == 'ArrayBuffer' or is_typed_array_type(interface.name):
|
| + includes.append('bindings/v8/custom/V8ArrayBufferCustom.h')
|
| +
|
| + attribute_parameters, attribute_includes = v8_attributes.generate_attributes_wip(interface)
|
| + includes += attribute_includes
|
| + function_parameters, function_includes = v8_functions.generate_functions(interface)
|
| + includes += function_includes
|
| + constructor_parameters, constructor_includes = v8_constructors.generate_constructor_contents(interface)
|
| + includes += constructor_includes
|
| + special_accessors_parameter, special_accessors_includes = v8_special_accessors.get_special_accessors_parameter(interface)
|
| + includes += special_accessors_includes
|
| + feature_observation_parameter, feature_observation_includes = get_feature_observation_parameter(interface)
|
| + includes += feature_observation_includes
|
| + deprecation_notification_parameter, deprecation_notification_includes = get_deprecation_notification_parameter(interface)
|
| + includes += deprecation_notification_includes
|
| + template_parameters_for_create_wrapper, includes_for_create_wrapper = generate_to_v8_converters(interface, v8_class_name, cpp_class_name)
|
| + includes += includes_for_create_wrapper
|
| +
|
| + if interface.parent:
|
| + parent_class_name = 'V8' + interface.parent
|
| +# print 'ADD H', interface.parent
|
| + includes.append('V8%s.h' % interface.parent)
|
| + parent_class_template = parent_class_name + '::GetTemplate(isolate, currentWorldType)'
|
| + else:
|
| + parent_class_name = ''
|
| + parent_class_template = 'v8::Local<v8::FunctionTemplate>()'
|
| +
|
| + if interface.name == 'MessagePort':
|
| + # MessagePort is handled like an active dom object even though it doesn't inherit
|
| + # from ActiveDOMObject, so don't try to cast it to ActiveDOMObject.
|
| + active_dom_object_return_value = '0'
|
| + else:
|
| + active_dom_object_return_value = 'toNative(object)'
|
| +
|
| + interface_length = get_interface_length(interface)
|
| +
|
| + is_reachable_method = interface.extended_attributes.get('GenerateIsReachable')
|
| + generate_opaque_root_for_gc = 'CustomIsReachable' not in interface.extended_attributes
|
| + if generate_opaque_root_for_gc and is_reachable_method:
|
| + includes.append('bindings/v8/V8GCController.h')
|
| + includes.append('core/dom/Element.h')
|
| +
|
| + number_of_normal_attributes = len([attribute for attribute in attribute_parameters if attribute.get('is_normal')])
|
| +
|
| + includes_set = set(includes)
|
| + includes_set.discard(v8_class_name + '.h')
|
| + includes = sorted(includes_set)
|
| + template_parameters = {
|
| + 'interface_name': interface.name,
|
| + 'interface_length': interface_length,
|
| + 'needs_opaque_root_for_gc': needs_opaque_root_for_gc(interface),
|
| + 'generate_opaque_root_for_gc': generate_opaque_root_for_gc,
|
| + 'is_reachable_method': is_reachable_method,
|
| + 'inherits_extended_attribute_active_dom_object': inherits_extended_attribute_active_dom_object,
|
| + 'active_dom_object_return_value': active_dom_object_return_value,
|
| + 'inherits_event_target': inherits_event_target,
|
| + 'namespace_for_interface': 'WTF' if is_typed_array_type(interface.name) else 'WebCore',
|
| + ### only DOMException isException==True. TODO support exception
|
| +# 'wrapper_type_prototype': interface.is_exception and 'WrapperTypeErrorPrototype' or 'WrapperTypeObjectPrototype',
|
| + 'wrapper_type_prototype': 'WrapperTypeObjectPrototype',
|
| + 'enabled_at_runtime': 'EnabledAtRuntime' in interface.extended_attributes,
|
| + 'enable_function': runtime_enable_function_name(interface),
|
| + 'configure_template_batched_attribute': v8_class_name + 'Attrs' if number_of_normal_attributes else '0',
|
| + 'configure_template_attribute_count': 'WTF_ARRAY_LENGTH(%sAttrs)' % v8_class_name if number_of_normal_attributes else '0',
|
| + 'configure_template_batched_method': v8_class_name + 'Methods' if has_callbacks else '0',
|
| + 'configure_template_method_count': 'WTF_ARRAY_LENGTH(%sMethods)' % v8_class_name if has_callbacks else '0',
|
| + # FIXME: replace with conditional expressions
|
| + 'to_active_dom_object': v8_class_name + '::toActiveDOMObject' if inherits_extended_attribute_active_dom_object else '0',
|
| + 'to_event_target': v8_class_name + '::toEventTarget' if inherits_event_target else '0',
|
| + 'root_for_gc': v8_class_name + '::opaqueRootForGC' if needs_opaque_root_for_gc(interface) else '0',
|
| + 'check_security': interface.extended_attributes.get('CheckSecurity'),
|
| + 'parent_class_info': '&%s::info' % parent_class_name if parent_class_name else '0',
|
| + 'parent_class_template': parent_class_template,
|
| + 'parent': interface.parent,
|
| + 'attributes': attribute_parameters,
|
| + 'functions': function_parameters,
|
| + 'function_callbacks': len([f for f in function_parameters if f.get('create_callback')]),
|
| + 'cpp_includes': includes,
|
| + 'number_of_enabled_at_runtime_attributes': len([attribute for attribute in attribute_parameters if attribute['enabled_at_runtime']]),
|
| + 'number_of_enabled_per_context_functions': len([function for function in function_parameters if function['is_enabled_per_context_function']]),
|
| + 'number_of_normal_functions': len([function for function in function_parameters if function.get('is_normal_function')]),
|
| + 'number_of_normal_attributes': number_of_normal_attributes,
|
| + 'number_of_any_attributes': len([attribute for attribute in attribute_parameters if attribute.get('type') == 'any']),
|
| + 'do_not_check_constants': 'DoNotCheckConstants' in interface.extended_attributes,
|
| + 'special_accessors': special_accessors_parameter,
|
| + 'custom_legacy_call': 'CustomLegacyCall' in interface.extended_attributes,
|
| + }
|
| + template_parameters.update(template_parameters_for_create_wrapper)
|
| + template_parameters.update(constructor_parameters)
|
| + template_parameters.update(feature_observation_parameter)
|
| + template_parameters.update(deprecation_notification_parameter)
|
| + return template_parameters
|
| +
|
| +
|
| +def get_convert_to_v8_string_resource(attribute_or_parameter, native_type, variable_name, native_value):
|
| + # FIXME: unused
|
| + if not native_type.startswith('V8StringResource'):
|
| + raise Exception('Wrong native type passed: %s' % native_type)
|
| + if attribute_or_parameter.data_type == 'DOMString' or is_enum_type(attribute_or_parameter.data_type):
|
| + return 'V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(%s, %s, %s);' % (native_type, variable_name, native_value)
|
| + # print '[get_convert_to_V8StringResource] not DOMString nor enum', native_type, get_convert_to_V8StringResource, native_value
|
| + return '%s %s(%s, true);' % (native_type, variable_name, native_value)
|
| +
|
| +
|
| +def get_interface_length(interface):
|
| + # The Web IDL specification states that Interface objects for interfaces MUST have a property named
|
| + # 'length' that returns the length of the shortest argument list of the entries in the effective
|
| + # overload set for constructors. In other words, use the lowest number of mandatory arguments among
|
| + # all constructors.
|
| + if is_constructor_template(interface, 'Event') or is_constructor_template(interface, 'TypedArray'):
|
| + return 1
|
| + # FIXME: once generate constructors properly, replace with:
|
| + # if not constructors: return 0
|
| + if all(extended_attribute not in interface.extended_attributes
|
| + for extended_attribute in ['Constructor', 'CustomConstructor']):
|
| + return 0
|
| + constructors = interface.constructors + interface.custom_constructors
|
| + return min([get_function_mandatory_parameters(constructor)
|
| + for constructor in constructors])
|
| +
|
| +
|
| +def generate_to_v8_converters(interface, v8_class_name, cpp_class_name):
|
| + # print '[]', cpp_class_name
|
| + includes = []
|
| + create_wrapper = not ('DoNotGenerateWrap' in interface.extended_attributes or 'DoNotGenerateToV8' in interface.extended_attributes)
|
| + if not create_wrapper:
|
| + return {}, includes
|
| +
|
| + includes = [
|
| + 'bindings/v8/ScriptController.h',
|
| + 'core/page/Frame.h',
|
| + ]
|
| + # TODO make attribute instead of hard code
|
| + if ('SVG' in v8_class_name or
|
| + any([interface_inherits_extended_attribute(interface, attribute)
|
| + for attribute in ['ActiveDOMObject', 'DependentLifetime', 'GenerateIsReachable', 'CustomIsReachable']])):
|
| + wrapper_configuration = 'WrapperConfiguration::Dependent'
|
| + else:
|
| + wrapper_configuration = 'WrapperConfiguration::Independent'
|
| + # Used in: C++ calls function f(PassRefPtr<XXX>* impl, ...) -> can be replaced to get_type_as_function_parameter(native_type)
|
| + template_parameters = {
|
| + 'create_wrapper': create_wrapper,
|
| + 'wrapper_configuration': wrapper_configuration,
|
| +# 'create_wrapper_argument_type': get_native_type(cpp_class_name, used_as_parameter=True),
|
| + 'create_wrapper_argument_type': cpp_class_name,
|
| + 'base_interface_name': base_interface_name(interface),
|
| + 'inherit_document': inherits_interface(interface, 'Document'),
|
| + 'is_typed_array_type': is_typed_array_type(interface.name),
|
| + }
|
| +
|
| + return template_parameters, includes
|
|
|