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 |