Index: Source/bindings/scripts/v8_attributes.py
|
diff --git a/Source/bindings/scripts/v8_attributes.py b/Source/bindings/scripts/v8_attributes.py
|
new file mode 100644
|
index 0000000000000000000000000000000000000000..eaf9ff36300820da4fe007cfaa62cc15af2cc363
|
--- /dev/null
|
+++ b/Source/bindings/scripts/v8_attributes.py
|
@@ -0,0 +1,618 @@
|
+# 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.
|
+
|
+"""Generate template values for attributes.
|
+
|
+FIXME: rename "parameter/parameters":
|
+"template parameters" is easily confused with "function parameters"
|
+Also, "parameter*s*", not "parameter".
|
+"""
|
+
|
+import v8_types
|
+from v8_types import cpp_type, v8_type
|
+from v8_utilities import generate_conditional_string, implemented_as_cpp_name, uncapitalize
|
+import v8_values
|
+
|
+# WIP
|
+import re
|
+
|
+from code_generator_idl_reader import inherits_interface, implemented_as_from_implemented_by
|
+from v8_includes import *
|
+from v8_types import *
|
+from v8_utilities import capitalize, runtime_enable_function_name, strip_suffix
|
+from v8_utilities import ACTIVITY_LOGGING_INCLUDES, get_call_with_parameter, get_custom_element_invocation_scope_parameter, get_feature_observation_parameter, get_deprecation_notification_parameter, has_activity_logging
|
+from v8_values import get_js_value_to_native_statement, get_native_to_js_value_statement, get_pass_owner_expression
|
+
|
+
|
+def generate_attributes(interface):
|
+ def generate_attribute(attribute):
|
+ attribute_contents, attribute_includes = generate_attribute_and_includes(interface, attribute)
|
+ includes.update(attribute_includes)
|
+ return attribute_contents
|
+
|
+ includes = set()
|
+ contents = generate_attributes_common(interface)
|
+ contents['attributes'] = [generate_attribute(attribute) for attribute in interface.attributes]
|
+ return contents, includes
|
+
|
+
|
+def generate_attributes_common(interface):
|
+ attributes = interface.attributes
|
+ v8_class_name = v8_types.get_v8_class_name(interface)
|
+ return {
|
+ # Size 0 constant array is not allowed in VC++
|
+ # FIXME: rename Attrs to Attributes
|
+ 'number_of_attributes': 'WTF_ARRAY_LENGTH(%sAttrs)' % v8_class_name if attributes else '0',
|
+ 'attribute_templates': v8_class_name + 'Attrs' if attributes else '0',
|
+ }
|
+
|
+
|
+def generate_attribute_and_includes(interface, attribute):
|
+ data_type = attribute.data_type
|
+ # FIXME: need to check should_keep_attribute_alive, but for now sufficient
|
+ # to check if primitive.
|
+ should_keep_attribute_alive = not v8_types.primitive_type(data_type)
|
+ # FIXME: eliminate should_keep_attribute_alive
|
+ if should_keep_attribute_alive:
|
+ return_js_value_statement = None # unused
|
+ includes = includes_for_type(data_type)
|
+ includes.add('bindings/v8/V8HiddenPropertyName.h')
|
+ else:
|
+ cpp_value = getter_expression(interface, attribute)
|
+ return_js_value_statement = v8_values.cpp_value_to_js_value_return(data_type, cpp_value, callback_info='info')
|
+ includes = []
|
+ contents = {
|
+ 'name': attribute.name,
|
+ 'conditional_string': generate_conditional_string(attribute),
|
+ 'cpp_method_name': implemented_as_cpp_name(attribute),
|
+ 'cpp_type': cpp_type(data_type, pointer_type='RefPtr'),
|
+ 'should_keep_attribute_alive': should_keep_attribute_alive,
|
+ 'return_js_value_statement': return_js_value_statement,
|
+ 'v8_type': v8_type(data_type),
|
+ }
|
+ return contents, includes
|
+
|
+
|
+def getter_expression(interface, attribute):
|
+ # FIXME: very incomplete
|
+ return 'imp->%s()' % uncapitalize(attribute.name)
|
+
|
+
|
+################################################################################
|
+# WIP
|
+################################################################################
|
+
|
+
|
+def generate_attributes_wip(interface):
|
+ def generate_attribute(attribute):
|
+ attribute_contents, attribute_includes = generate_attribute_and_includes_wip(interface, attribute)
|
+ includes.extend(attribute_includes)
|
+ return attribute_contents
|
+
|
+ includes = []
|
+ contents = [generate_attribute(attribute) for attribute in interface.attributes]
|
+ return contents, includes
|
+
|
+
|
+def generate_attribute_and_includes_wip(interface, attribute):
|
+ cpp_class_name = implemented_as_cpp_name(interface)
|
+ per_world_bindings = 'PerWorldBindings' in attribute.extended_attributes
|
+ for_main_world_suffixes = ['']
|
+ if per_world_bindings:
|
+ for_main_world_suffixes.append('ForMainWorld')
|
+
|
+ includes = []
|
+ # print
|
+ # print '#'*30
|
+ # print '[get_attribute_parameter] ', attribute.data_type, attribute.name
|
+
|
+ check_security_for_node = 'CheckSecurityForNode' in attribute.extended_attributes
|
+ if check_security_for_node:
|
+ includes.append('bindings/v8/BindingSecurity.h')
|
+ if attribute.data_type == 'SerializedScriptValue':
|
+ includes.append('bindings/v8/SerializedScriptValue.h')
|
+
|
+ getter_activity_logging = set()
|
+ for for_main_world_suffix in for_main_world_suffixes:
|
+ if has_activity_logging(for_main_world_suffix, attribute.extended_attributes, 'Getter'):
|
+ getter_activity_logging.add(for_main_world_suffix)
|
+ includes += ACTIVITY_LOGGING_INCLUDES
|
+
|
+ custom_element_invocation_scope_parameter, custom_element_invocation_scope_includes = get_custom_element_invocation_scope_parameter(attribute)
|
+ includes += custom_element_invocation_scope_includes
|
+# print '[[]]', custom_element_invocation_scope_parameter
|
+
|
+ enable_function = runtime_enable_function_name(attribute)
|
+
|
+ replaceable = 'Replaceable' in attribute.extended_attributes
|
+ custom_getter = has_custom_getter(attribute)
|
+ custom_setter = has_custom_setter(attribute)
|
+ has_replaceable = not custom_setter and replaceable
|
+ has_normal_setter = (custom_setter or not has_replaceable) and not is_read_only(attribute)
|
+
|
+ should_keep_attribute_alive = get_should_keep_attribute_alive(interface, attribute)
|
+# print '[] should_keep_attribute_alive', should_keep_attribute_alive
|
+
|
+ native_type = ''
|
+ array_type = ''
|
+ if not custom_getter:
|
+ native_type = get_native_type(attribute.data_type, extended_attributes=attribute.extended_attributes)
|
+ # currently array_type is always False
|
+ array_type = get_array_type(native_type)
|
+ if should_keep_attribute_alive:
|
+ if array_type:
|
+ includes.append('V8%s.h' % array_type)
|
+ else:
|
+ includes += get_includes_for_type(attribute.data_type)
|
+ includes.append('bindings/v8/V8HiddenPropertyName.h')
|
+ if (setter_use_exception(attribute) and not custom_setter) or getter_use_exception(attribute):
|
+ includes.append('bindings/v8/ExceptionState.h')
|
+
|
+ batched_attribute, batched_attribute_includes = generate_batched_attribute(interface, attribute, ',')
|
+ includes += batched_attribute_includes
|
+
|
+ enabled_at_runtime = False
|
+ enabled_per_context = False
|
+ if interface.name == 'Window' and 'Unforgeable' in attribute.extended_attributes:
|
+ pass
|
+ elif 'EnabledPerContext' in attribute.extended_attributes:
|
+ enabled_per_context = True
|
+ elif 'EnabledAtRuntime' in attribute.extended_attributes:
|
+ enabled_at_runtime = True
|
+ else:
|
+ pass
|
+
|
+ if enabled_at_runtime:
|
+ batched_attribute, batched_attribute_includes = generate_batched_attribute(interface, attribute, ';')
|
+ includes += batched_attribute_includes
|
+
|
+ compact_getter = 'Reflect' in attribute.extended_attributes and 'URL' not in attribute.extended_attributes and inherits_interface(interface, 'Node') and attribute.data_type == 'DOMString'
|
+ compact_setter = 'Reflect' in attribute.extended_attributes and inherits_interface(interface, 'Node') and attribute.data_type == 'DOMString'
|
+ compact_setter_namespace = ''
|
+ compact_setter_content_attribute_name = ''
|
+ if compact_setter:
|
+ compact_setter_content_attribute_name = attribute.name.lower()
|
+ if attribute.extended_attributes.get('Reflect'):
|
+ compact_setter_content_attribute_name = attribute.extended_attributes.get('Reflect')
|
+ compact_setter_namespace = namespace_for_attribute_name(interface.name, compact_setter_content_attribute_name)
|
+ includes.append('%s.h' % compact_setter_namespace)
|
+
|
+ 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(attribute)
|
+ includes += deprecation_notification_includes
|
+
|
+ getter_function = ''
|
+ event_listener_setter_function_name = ''
|
+ event_listener_setter_function_name_not_inherits_node = ''
|
+ not_inherits_node = False
|
+ if attribute.data_type == 'EventListener':
|
+ # FIXME: Pass the main world ID for main-world-only getters.
|
+ includes.append('bindings/v8/V8AbstractEventListener.h')
|
+ includes.append('bindings/v8/V8EventListenerList.h')
|
+ getter_function = uncapitalize(attribute.name)
|
+ event_listener_setter_function_name = capitalize(attribute.name)
|
+ not_inherits_node = not inherits_interface(interface, 'Node')
|
+ if not_inherits_node:
|
+ event_listener_setter_function_name_not_inherits_node = implemented_as_cpp_name(attribute)
|
+ event_listener_on_error = (interface.name == 'Window' or interface.name == 'WorkerGlobalScope') and attribute.name == 'onerror'
|
+ if event_listener_on_error:
|
+ includes.append('bindings/v8/V8ErrorHandler.h')
|
+
|
+ svg_animated_type = is_svg_animated_type(interface.name)
|
+ svg_type_needing_tear_off = get_svg_type_needing_tear_off(attribute.data_type)
|
+
|
+ ##################### Getter
|
+ getter_native_value_expression, getter_function_call_parameter, getter_includes = get_attribute_function_call_expression(interface, attribute)
|
+ includes += getter_includes
|
+# print '[]', getter_native_value_expression
|
+
|
+ tear_off_and_not_list = svg_type_needing_tear_off and not interface.name.endswith('List')
|
+
|
+ wrapped_value = ''
|
+ return_js_value_statements = {}
|
+ assign_native_value_to_local_variable_statement = ''
|
+ if not custom_getter:
|
+ if (svg_animated_type or interface.name == 'SVGViewSpec') and svg_type_needing_tear_off:
|
+ includes.append('V8%s.h' % attribute.data_type)
|
+ elif tear_off_and_not_list:
|
+ includes.append('V8%s.h' % attribute.data_type)
|
+ includes.append('core/svg/properties/SVGPropertyTearOff.h')
|
+ if svg_type_with_writable_properties_needing_tear_off(attribute.data_type) and 'Immutable' not in attribute.extended_attributes:
|
+ getter = getter_native_value_expression
|
+ getter = getter.replace('imp->', '')
|
+ getter = getter.replace('\(\)', '')
|
+
|
+ update_method = '&%s::update%s' % (cpp_class_name, capitalize(getter))
|
+
|
+ self_is_tear_off_type = get_svg_type_needing_tear_off(interface.name)
|
+ if self_is_tear_off_type:
|
+ includes.append('core/svg/properties/SVGStaticPropertyWithParentTearOff.h')
|
+ svg_type_needing_tear_off = svg_type_needing_tear_off.replace('SVGPropertyTearOff<', 'SVGStaticPropertyWithParentTearOff<%s, ' % cpp_class_name)
|
+ wrapped_value = 'WTF::getPtr(%s::create(wrapper, %s, %s))' % (svg_type_needing_tear_off, getter_native_value_expression, update_method)
|
+ else:
|
+ includes.append('core/svg/properties/SVGStaticPropertyTearOff.h')
|
+ svg_type_needing_tear_off = svg_type_needing_tear_off.replace('SVGPropertyTearOff<', 'SVGStaticPropertyTearOff<%s, ' % cpp_class_name)
|
+ wrapped_value = 'WTF::getPtr(%s::create(imp, %s, %s))' % (svg_type_needing_tear_off, getter_native_value_expression, update_method)
|
+ elif 'SVGStaticListPropertyTearOff' in svg_type_needing_tear_off:
|
+ wrapped_value = 'WTF::getPtr(%s::create(imp, %s))' % (svg_type_needing_tear_off, getter_native_value_expression)
|
+ elif re.search('SVG(Point|PathSeg)List', svg_type_needing_tear_off):
|
+ wrapped_value = 'WTF::getPtr(%s)' % getter_native_value_expression
|
+ else:
|
+ wrapped_value = 'WTF::getPtr(%s::create(%s))' % (svg_type_needing_tear_off, getter_native_value_expression)
|
+ elif attribute.data_type == 'SerializedScriptValue' and 'CachedAttribute' in attribute.extended_attributes:
|
+ pass
|
+ elif attribute.data_type == 'EventListener':
|
+ pass
|
+ else:
|
+ original_getter_native_value_expression = getter_native_value_expression
|
+ # Fix amigious conversion problem, by casting to the base type first ($getterString returns a type that inherits from SVGAnimatedEnumeration, not the base class directly).
|
+ if attribute.data_type == 'SVGAnimatedEnumeration':
|
+ getter_native_value_expression = 'static_pointer_cast<SVGAnimatedEnumeration>(%s)' % getter_native_value_expression
|
+
|
+ # print '[get_attribute_parameter] native_type', native_type
|
+ if attribute.is_nullable or getter_use_exception(attribute):
|
+ # used in local variable type
|
+ assign_native_value_to_local_variable_statement = '%s v = %s;' % (native_type, getter_native_value_expression)
|
+ getter_native_value_expression = get_pass_owner_expression(attribute.data_type, 'v')
|
+
|
+ for for_main_world_suffix in for_main_world_suffixes:
|
+ if attribute.data_type != 'EventListener':
|
+ return_js_value_statement, native_to_js_value_includes = get_native_to_js_value_statement(attribute.data_type, attribute.extended_attributes, getter_native_value_expression, creation_context='info.Holder()', isolate='info.GetIsolate()', callback_info='info', script_wrappable='imp', for_main_world_suffix=for_main_world_suffix, used_as_return_value=True)
|
+ return_js_value_statements[for_main_world_suffix] = return_js_value_statement
|
+ if should_keep_attribute_alive:
|
+ assign_native_value_to_local_variable_statement = '%s v = %s;' % (native_type, original_getter_native_value_expression)
|
+ getter_native_value_expression = original_getter_native_value_expression
|
+ else:
|
+ includes += native_to_js_value_includes
|
+
|
+ ##################### Setter
|
+ # native to JS (getter)
|
+ assign_js_value_to_local_variable_statement = ''
|
+ setter_native_value_expression = ''
|
+ set_value_statement = ''
|
+ setter_activity_logging = set()
|
+ setter_function_call_parameter = {}
|
+ if has_normal_setter:
|
+ for for_main_world_suffix in for_main_world_suffixes:
|
+ if has_activity_logging(for_main_world_suffix, attribute.extended_attributes, 'Setter'):
|
+ setter_activity_logging.add(for_main_world_suffix)
|
+ includes += ACTIVITY_LOGGING_INCLUDES
|
+
|
+ # JS to native (setter)
|
+ if attribute.data_type != 'EventListener':
|
+ assign_js_value_to_local_variable_statement, js_value_to_native_includes = get_js_value_to_native_statement(attribute.data_type, attribute.extended_attributes, 'value', 'v', 'info.GetIsolate()')
|
+ includes += js_value_to_native_includes
|
+
|
+ setter_native_value_expression = 'v'
|
+ if is_ref_ptr_type(attribute.data_type) and not get_array_type(attribute.data_type):
|
+ setter_native_value_expression = 'WTF::getPtr(%s)' % setter_native_value_expression
|
+
|
+ # set native value statement
|
+ setter_native_value_expression, setter_function_call_parameter, setter_includes = get_attribute_function_call_expression(interface, attribute, is_setter=True, setter_native_value_expression=setter_native_value_expression)
|
+ includes += setter_includes
|
+
|
+ set_value_statement = '%s;' % setter_native_value_expression
|
+# print '[attribute] set_value_statement', set_value_statement
|
+
|
+ is_normal = False
|
+ if interface.name == 'Window' and 'Unforgeable' in attribute.extended_attributes:
|
+ pass
|
+ elif 'EnabledAtRuntime' in attribute.extended_attributes or 'EnabledPerContext' in attribute.extended_attributes:
|
+ pass
|
+ else:
|
+ is_normal = True
|
+
|
+ parameter = {
|
+ 'name': attribute.name,
|
+ 'type': attribute.data_type,
|
+ 'is_static': attribute.is_static,
|
+ 'is_normal': is_normal,
|
+ 'native_type': native_type,
|
+ 'svg_animated_type': svg_animated_type,
|
+ 'svg_type_needing_tear_off': svg_type_needing_tear_off,
|
+ 'tear_off_and_not_list': tear_off_and_not_list,
|
+ 'check_security_for_node': check_security_for_node,
|
+ 'enable_function': enable_function,
|
+
|
+ # EventListner hack
|
+ 'getter_function': getter_function,
|
+ 'event_listener_setter_function_name': event_listener_setter_function_name,
|
+ 'event_listener_setter_function_name_not_inherits_node': event_listener_setter_function_name_not_inherits_node,
|
+ 'not_inherits_node': not_inherits_node,
|
+
|
+ 'getter_native_value_expression': getter_native_value_expression,
|
+ 'setter_native_value_expression': setter_native_value_expression,
|
+ 'return_js_value_statements': return_js_value_statements,
|
+ 'set_value_statement': set_value_statement,
|
+ 'conditional_string': generate_conditional_string(attribute),
|
+ 'batched_attribute': batched_attribute,
|
+ 'getter_use_exceptions': getter_use_exception(attribute),
|
+ 'setter_use_exceptions': setter_use_exception(attribute),
|
+ 'is_nullable': attribute.is_nullable,
|
+ 'assign_native_value_to_local_variable_statement': assign_native_value_to_local_variable_statement,
|
+ 'assign_js_value_to_local_variable_statement': assign_js_value_to_local_variable_statement,
|
+ 'has_replaceable': has_replaceable,
|
+ 'has_normal_setter': has_normal_setter,
|
+ 'has_custom_getter': custom_getter,
|
+ 'has_custom_setter': custom_setter,
|
+ 'per_world_bindings': per_world_bindings,
|
+ 'for_main_world_suffixes': for_main_world_suffixes,
|
+ 'should_keep_attribute_alive': should_keep_attribute_alive,
|
+ 'array_type': array_type,
|
+ 'getter_activity_logging': getter_activity_logging,
|
+ 'setter_activity_logging': setter_activity_logging,
|
+ 'enabled_at_runtime': enabled_at_runtime,
|
+ 'enabled_per_context': enabled_per_context,
|
+ 'compact_getter': compact_getter,
|
+ 'compact_setter': compact_setter,
|
+ 'compact_setter_namespace': compact_setter_namespace,
|
+ 'compact_setter_content_attribute_name': compact_setter_content_attribute_name,
|
+ 'cached_attribute': 'CachedAttribute' in attribute.extended_attributes,
|
+ 'wrapped_value': wrapped_value,
|
+ 'cpp_name': implemented_as_cpp_name(attribute),
|
+ 'initialized_by_event_constructor': 'InitializedByEventConstructor' in attribute.extended_attributes,
|
+ 'setter': 'setSerialized' + capitalize(attribute.name),
|
+ }
|
+ parameter.update(feature_observation_parameter)
|
+ parameter.update(deprecation_notification_parameter)
|
+ parameter.update(custom_element_invocation_scope_parameter)
|
+ parameter.update(getter_function_call_parameter)
|
+ parameter.update(setter_function_call_parameter)
|
+ return parameter, includes
|
+
|
+
|
+def generate_batched_attribute(interface, attribute, delimiter, indent=''):
|
+ # GenerateSingleBatchedAttribute in perl
|
+ cpp_class_name = implemented_as_cpp_name(interface)
|
+ v8_class_name = get_v8_class_name(interface)
|
+ is_constructor = attribute.data_type.endswith('Constructor')
|
+# print '[--]', attribute.name, attribute.data_type, is_constructor
|
+ includes = []
|
+
|
+ access_control = 'v8::DEFAULT'
|
+ if attribute.extended_attributes.get('DoNotCheckSecurityOnGetter'):
|
+ access_control = 'v8::ALL_CAN_READ'
|
+ elif attribute.extended_attributes.get('DoNotCheckSecurityOnSetter'):
|
+ access_control = 'v8::ALL_CAN_WRITE'
|
+ elif attribute.extended_attributes.get('DoNotCheckSecurity'):
|
+ access_control = 'v8::ALL_CAN_READ'
|
+ if not is_read_only(attribute):
|
+ access_control += ' | v8::ALL_CAN_WRITE'
|
+ if attribute.extended_attributes.get('Unforgeable'):
|
+ access_control += ' | v8::PROHIBITS_OVERWRITING'
|
+ access_control = 'static_cast<v8::AccessControl>(%s)' % access_control
|
+
|
+ prop_attr = 'v8::None'
|
+ # Check attributes.
|
+ # As per Web IDL specification, constructor properties on the ECMAScript global object should be
|
+ # configurable and should not be enumerable.
|
+ if 'NotEnumerable' in attribute.extended_attributes or is_constructor:
|
+ prop_attr += ' | v8::DontEnum'
|
+ if 'Unforgeable' in attribute.extended_attributes and not is_constructor:
|
+ prop_attr += ' | v8::DontDelete'
|
+
|
+ on_proto = '0 /* on instance */'
|
+ if is_constructor:
|
+ constructor_type = strip_suffix(attribute.data_type, 'Constructor')
|
+ # $constructorType ~= /Constructor$/ indicates that it is NamedConstructor.
|
+ # We do not generate the header file for NamedConstructor of class XXXX,
|
+ # since we generate the NamedConstructor declaration into the header file of class XXXX.
|
+ # FIXME: We just stripped the 'Constructor' suffix!
|
+ if not constructor_type.endswith('Constructor') or attribute.extended_attributes.get('CustomConstructor'):
|
+ includes.append('V8%s.h' % constructor_type)
|
+ getter = '%sV8Internal::%sConstructorGetter' % (cpp_class_name, cpp_class_name)
|
+ setter = '%sV8Internal::%sReplaceableAttrSetterCallback' % (cpp_class_name, cpp_class_name)
|
+ getter_for_main_world = '0'
|
+ setter_for_main_world = '0'
|
+ data = '&V8${constructorType}::info'
|
+ else:
|
+ # Default Getter and Setter
|
+ getter = '%sV8Internal::%sAttrGetterCallback' % (cpp_class_name, attribute.name)
|
+ setter = '%sV8Internal::%sAttrSetterCallback' % (cpp_class_name, attribute.name)
|
+ getter_for_main_world = getter + 'ForMainWorld'
|
+ setter_for_main_world = setter + 'ForMainWorld'
|
+ data = '0 /* no data */'
|
+ if not has_custom_setter(attribute) and attribute.extended_attributes.get('Replaceable'):
|
+ setter = '%sV8Internal::%sReplaceableAttrSetterCallback' % (cpp_class_name, cpp_class_name)
|
+ setter_for_main_world = '0'
|
+ # Read only attributes
|
+ if is_read_only(attribute):
|
+ setter = '0'
|
+ setter_for_main_world = '0'
|
+ if 'PerWorldBindings' not in attribute.extended_attributes:
|
+ getter_for_main_world = '0'
|
+ setter_for_main_world = '0'
|
+
|
+ # An accessor can be installed on the proto
|
+ if attribute.extended_attributes.get('OnProto'):
|
+ on_proto = '1 /* on proto */'
|
+
|
+ code = (
|
+ '{"%s", %s, %s, %s, %s, %s, %s, static_cast<v8::PropertyAttribute>(%s), %s}%s' %
|
+ (attribute.name, getter, setter, getter_for_main_world, setter_for_main_world, data, access_control, prop_attr, on_proto, delimiter))
|
+ return code, includes
|
+
|
+
|
+# Auxiliary functions
|
+
|
+
|
+def get_should_keep_attribute_alive(interface, attribute):
|
+ return (
|
+ 'KeepAttributeAliveForGC' in attribute.extended_attributes or
|
+ # Basically, for readonly or replaceable attributes, we have to
|
+ # guarantee that JS wrappers don't get garbage-collected prematually
|
+ # when their lifetime is strongly tied to their owner.
|
+ ((is_wrapper_type(attribute.data_type) and
|
+ (is_read_only(attribute) or
|
+ 'Replaceable' in attribute.extended_attributes)) and
|
+ # However, there are a couple of exceptions.
|
+ not(
|
+ # Node lifetime is managed by object grouping.
|
+ inherits_interface(interface, 'Node') or
|
+ is_dom_node_type(attribute.data_type) or
|
+ # To avoid adding a reference to itself.
|
+ # FIXME: Introduce [DoNotKeepAttributeAliveForGC] and remove
|
+ # this hack of depending on the attribute name.
|
+ attribute.name == 'self' or
|
+ # FIXME: Remove these hard-coded hacks.
|
+ attribute.data_type in ['EventTarget', 'SerializedScriptValue', 'Window'] or
|
+ 'SVG' in attribute.data_type or
|
+ 'HTML' in attribute.data_type)))
|
+
|
+
|
+def get_attribute_function_call_expression(interface, attribute, is_setter=False, setter_native_value_expression=None):
|
+ """
|
+ @return function_call_expression, includes
|
+ """
|
+ # GetterExpression / SetterExpression in perl
|
+ includes = []
|
+ arguments = []
|
+ interface_name = interface.name
|
+ cpp_class_name = implemented_as_cpp_name(interface)
|
+ content_attribute_name, additional_includes = get_content_attribute_name(interface_name, attribute)
|
+ includes += additional_includes
|
+
|
+ function_name = ''
|
+ if is_setter:
|
+ if content_attribute_name:
|
+ if attribute.data_type == 'boolean':
|
+ function_name = 'setBooleanAttribute'
|
+ elif attribute.data_type == 'long':
|
+ function_name = 'setIntegralAttribute'
|
+ elif attribute.data_type == 'unsigned long':
|
+ function_name = 'setUnsignedIntegralAttribute'
|
+ else:
|
+ function_name = 'setAttribute'
|
+ else:
|
+ function_name = 'set' + capitalize(implemented_as_cpp_name(attribute))
|
+ else:
|
+ if content_attribute_name:
|
+ if 'URL' in attribute.extended_attributes:
|
+ function_name = 'getURLAttribute'
|
+ elif attribute.data_type == 'boolean':
|
+ function_name = 'fastHasAttribute'
|
+ elif attribute.data_type == 'long':
|
+ function_name = 'getIntegralAttribute'
|
+ elif attribute.data_type == 'unsigned long':
|
+ function_name = 'getUnsignedIntegralAttribute'
|
+ elif content_attribute_name == 'WebCore::HTMLNames::idAttr':
|
+ function_name = 'getIdAttribute'
|
+ content_attribute_name = ''
|
+ elif content_attribute_name == 'WebCore::HTMLNames::nameAttr':
|
+ function_name = 'getNameAttribute'
|
+ content_attribute_name = ''
|
+ elif content_attribute_name == 'WebCore::HTMLNames::classAttr':
|
+ function_name = 'getClassAttribute'
|
+ content_attribute_name = ''
|
+ elif is_svg_animated_type(attribute.data_type):
|
+ # We cannot use fast attributes for animated SVG types.
|
+ function_name = 'getAttribute'
|
+ else:
|
+ function_name = 'fastGetAttribute'
|
+ else:
|
+ function_name = uncapitalize(implemented_as_cpp_name(attribute))
|
+# print '[[]]', function_name
|
+ if content_attribute_name:
|
+ arguments.append(content_attribute_name)
|
+
|
+ implemented_by = attribute.extended_attributes.get('ImplementedBy')
|
+ if implemented_by:
|
+ implemented_by_cpp_name = implemented_as_from_implemented_by(implemented_by)
|
+ includes += header_files_for_interface(implemented_by, implemented_by_cpp_name)
|
+ if not attribute.is_static:
|
+ arguments = ['imp'] + arguments
|
+ function_name = '%s::%s' % (implemented_by_cpp_name, function_name)
|
+ elif attribute.is_static:
|
+ function_name = '%s::%s' % (cpp_class_name, function_name)
|
+ else:
|
+ function_name = 'imp->%s' % function_name
|
+
|
+ if is_setter:
|
+ arguments.append(setter_native_value_expression)
|
+ if setter_use_exception(attribute):
|
+ arguments.append('es')
|
+ call_with = attribute.extended_attributes.get('SetterCallWith') or attribute.extended_attributes.get('CallWith')
|
+ else:
|
+ if attribute.is_nullable:
|
+ arguments.append('isNull')
|
+ if getter_use_exception(attribute):
|
+ arguments.append('es')
|
+ call_with = attribute.extended_attributes.get('CallWith')
|
+
|
+ call_with_arguments, call_with_parameter, call_with_includes = get_call_with_parameter(call_with)
|
+ includes += call_with_includes
|
+ arguments = call_with_arguments + arguments
|
+
|
+ function_call_expression = '%s(%s)' % (function_name, ', '.join(arguments))
|
+ return function_call_expression, call_with_parameter, includes
|
+
|
+
|
+def get_custom_element_invocation_scope_parameter(interface_or_attribute_or_function):
|
+# print '[[]]', interface_or_attribute_or_function.extended_attributes
|
+ custom_element_invocation_scope = has_extended_attribute(interface_or_attribute_or_function, ['DeliverCustomElementCallbacks', 'Reflect'])
|
+ parameter = {
|
+ 'custom_element_invocation_scope': custom_element_invocation_scope,
|
+ }
|
+ if custom_element_invocation_scope:
|
+ includes = ['core/dom/CustomElementCallbackDispatcher.h']
|
+ else:
|
+ includes = []
|
+ return parameter, includes
|
+
|
+
|
+def has_extended_attribute(item, extended_attribute_list):
|
+ # FIXME: useful function, use widely
|
+ return any([extended_attribute in item.extended_attributes
|
+ for extended_attribute in extended_attribute_list])
|
+
|
+
|
+def getter_use_exception(attribute):
|
+ return has_extended_attribute(attribute, ['GetterRaisesException', 'RaisesException'])
|
+
|
+
|
+def setter_use_exception(attribute):
|
+ return has_extended_attribute(attribute, ['SetterRaisesException', 'RaisesException'])
|
+
|
+
|
+def namespace_for_attribute_name(interface_name, attribute_name):
|
+ if (interface_name.startswith('SVG') and
|
+ attribute_name not in SVG_ATTRIBUTES_IN_HTML):
|
+ return 'SVGNames'
|
+ return 'HTMLNames'
|
+
|
+
|
+def get_content_attribute_name(interface_name, attribute):
|
+ if 'Reflect' not in attribute.extended_attributes:
|
+ return None, []
|
+ default_content_attribute_name = implemented_as_cpp_name(attribute).lower()
|
+ content_attribute_name = attribute.extended_attributes['Reflect'] or default_content_attribute_name
|
+ namespace = namespace_for_attribute_name(interface_name, content_attribute_name)
|
+ scoped_name = 'WebCore::%s::%sAttr' % (namespace, content_attribute_name)
|
+ includes = [namespace + '.h']
|
+ return scoped_name, includes
|
|