| Index: Source/bindings/scripts/v8_functions.py
|
| diff --git a/Source/bindings/scripts/v8_functions.py b/Source/bindings/scripts/v8_functions.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..585fe31cc05da05b6c2350946a33c4b2f6f6792f
|
| --- /dev/null
|
| +++ b/Source/bindings/scripts/v8_functions.py
|
| @@ -0,0 +1,421 @@
|
| +# 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 functions.
|
| +
|
| +FIXME: rename "parameter/parameters":
|
| +"template parameters" is easily confused with "function parameters"
|
| +Also, "parameter*s*", not "parameter".
|
| +"""
|
| +
|
| +
|
| +from code_generator_idl_reader import implemented_as_from_implemented_by
|
| +from v8_includes import *
|
| +from v8_types import *
|
| +from v8_utilities import extended_attribute_contains, generate_conditional_string, get_raises_exception, runtime_enable_function_name, implemented_as_cpp_name
|
| +from v8_values import get_js_value_to_native_statement, get_native_to_js_value_statement, get_pass_owner_expression
|
| +
|
| +from v8_utilities import ACTIVITY_LOGGING_INCLUDES, get_call_with_parameter, get_custom_element_invocation_scope_parameter, get_deprecation_notification_parameter, get_function_mandatory_parameters, get_feature_observation_parameter, has_activity_logging
|
| +
|
| +
|
| +def generate_functions(interface):
|
| + # FIXME: clearer with a list comprehension + nested function to handle includes
|
| + functions = []
|
| + includes = []
|
| + for function in interface.operations:
|
| + function_contents, function_includes = generate_function(interface, function)
|
| +# print '[FUNC]', function_contents
|
| + functions.append(function_contents)
|
| + includes += function_includes
|
| + return functions, includes
|
| +
|
| +
|
| +def generate_function(interface, function):
|
| + includes = []
|
| + name = function.name
|
| + cpp_class_name = implemented_as_cpp_name(interface)
|
| + is_normal_function = function.name and 'EnabledPerContext' not in function.extended_attributes
|
| + is_standard_function = get_is_standard_function(interface, function)
|
| + is_custom = has_custom_implementation(function)
|
| +
|
| + per_world_bindings = 'PerWorldBindings' in function.extended_attributes
|
| + for_main_world_suffixes = ['']
|
| + if per_world_bindings:
|
| + for_main_world_suffixes.append('ForMainWorld')
|
| +
|
| + activity_logging = set()
|
| + setter_function_call_parameter = {}
|
| + for for_main_world_suffix in for_main_world_suffixes:
|
| + if has_activity_logging(for_main_world_suffix, function.extended_attributes, 'Method'):
|
| + activity_logging.add(for_main_world_suffix)
|
| + includes += ACTIVITY_LOGGING_INCLUDES
|
| +
|
| + check_security_for_node = 'CheckSecurityForNode' in function.extended_attributes
|
| + if check_security_for_node:
|
| + includes.append('bindings/v8/BindingSecurity.h')
|
| +
|
| + method_for_main_world = '0'
|
| + if 'PerWorldBindings' in function.extended_attributes:
|
| + method_for_main_world = '%sV8Internal::%sMethodCallbackForMainWorld' % (implemented_as_cpp_name(interface), function.name)
|
| + mandatory_parameters = get_function_mandatory_parameters(function)
|
| +
|
| + if len(function.overloads) > 1:
|
| + name = '%s%d' % (name, function.overload_index)
|
| + is_representative = function.overload_index == 1
|
| + conditional_runtime = ''
|
| + enable_function = ''
|
| + if 'EnabledAtRuntime' in function.extended_attributes:
|
| + # Only call Set()/SetAccessor() if this method should be enabled
|
| + enable_function = runtime_enable_function_name(function)
|
| + conditional_runtime = 'if (%s())\n ' % enable_function
|
| + if function.extended_attributes.get('EnabledPerContext'):
|
| + # Only call Set()/SetAccessor() if this method should be enabled
|
| + enable_function = get_context_enable_function(function)
|
| + conditional_runtime = 'if (%s(impl->document()))' % enable_function
|
| +
|
| + template = 'proto'
|
| + if 'Unforgeable' in function.extended_attributes:
|
| + template = 'instance'
|
| + if function.is_static:
|
| + template = 'desc'
|
| +
|
| + setter = '%sV8Internal::%sDomainSafeFunctionSetter' % (cpp_class_name, cpp_class_name) if 'ReadOnly' not in function.extended_attributes else '0'
|
| +
|
| + signature = 'defaultSignature'
|
| + if 'DoNotCheckSignature' in function.extended_attributes or function.is_static:
|
| + signature = 'v8::Local<v8::Signature>()'
|
| + requires_custom_signature = get_requires_custom_signature(function)
|
| + if requires_custom_signature:
|
| + signature = function.name + 'Signature'
|
| +
|
| + # FIXME: simplify: additional_property_attributes_list, ' | '.join(...)
|
| + property_attributes = 'v8::DontDelete'
|
| + if 'NotEnumerable' in function.extended_attributes:
|
| + property_attributes += ' | v8::DontEnum'
|
| + if 'ReadOnly' in function.extended_attributes:
|
| + property_attributes += ' | v8::ReadOnly'
|
| +
|
| + if property_attributes == 'v8::DontDelete':
|
| + property_attributes = ''
|
| + else:
|
| + property_attributes = ', static_cast<v8::PropertyAttribute>(%s)' % property_attributes
|
| +
|
| + custom_signatures = []
|
| + if requires_custom_signature:
|
| + for parameter in function.arguments:
|
| + if is_wrapper_type(parameter.data_type):
|
| + if parameter.data_type == 'XPathNSResolver':
|
| + # Special case for XPathNSResolver. All other browsers accepts a callable,
|
| + # so, even though it's against IDL, accept objects here.
|
| + custom_signatures.append('v8::Handle<v8::FunctionTemplate>()')
|
| + else:
|
| + array_or_sequence_type = get_array_or_sequence_type(parameter.data_type)
|
| +
|
| + if array_or_sequence_type:
|
| + if is_ref_ptr_type(array_or_sequence_type):
|
| + includes += get_includes_for_type(array_or_sequence_type)
|
| + else:
|
| + custom_signatures.append('v8::Handle<v8::FunctionTemplate>()')
|
| + continue
|
| + else:
|
| +# print '[FOO]', parameter.data_type, 'AS', array_or_sequence_type
|
| + includes += get_includes_for_type(parameter.data_type)
|
| + custom_signatures.append('V8PerIsolateData::from(isolate)->rawTemplate(&V8%s::info, currentWorldType)' % parameter.data_type)
|
| + else:
|
| + custom_signatures.append('v8::Handle<v8::FunctionTemplate>()')
|
| + custom_signature = ', '.join(custom_signatures)
|
| + function_call_parameters = {}
|
| + raises_exception = get_raises_exception(function)
|
| + if any(['IsIndex' in parameter.extended_attributes
|
| + for parameter in function.arguments]):
|
| + raises_exception = True
|
| + feature_observation_parameter = {}
|
| + deprecation_notification_parameter = {}
|
| + custom_element_invocation_scope_parameter = {}
|
| + parameter_check_parameters = {}
|
| +
|
| + if not is_custom and name:
|
| + if raises_exception:
|
| + includes.append('bindings/v8/ExceptionState.h')
|
| +
|
| + parameter_check_parameters, parameter_check_includes, replacements = get_parameter_check_parameters(interface, function)
|
| + includes += parameter_check_includes
|
| +
|
| + for for_main_world_suffix in for_main_world_suffixes:
|
| + function_call_parameter, function_call_includes = get_function_call_parameter(interface, function, len(function.arguments), for_main_world_suffix=for_main_world_suffix, replacements=replacements)
|
| + function_call_parameters[for_main_world_suffix] = function_call_parameter
|
| + includes += function_call_includes
|
| +
|
| + comment_info = 'Function "%s" (ExtAttr: "%s")' % (function.name, ' '.join(function.extended_attributes.keys()))
|
| +
|
| +# if template == 'proto' and conditional_runtime == '' and signature == 'defaultSignature' and property_attributes == '':
|
| +# raise Exception('This shouldn't happen: Class '%s' %s' % (cpp_class_name, comment_info))
|
| +
|
| + custom_element_invocation_scope_parameter, custom_element_invocation_scope_includes = get_custom_element_invocation_scope_parameter(function)
|
| + includes += custom_element_invocation_scope_includes
|
| +
|
| + feature_observation_parameter, feature_observation_includes = get_feature_observation_parameter(function)
|
| + includes += feature_observation_includes
|
| +
|
| + deprecation_notification_parameter, deprecation_notification_includes = get_deprecation_notification_parameter(function)
|
| + includes += deprecation_notification_includes
|
| +
|
| + # print
|
| + # print '#'*30
|
| + # print '[get_function_parameter] ', function.data_type, name
|
| + contents = {
|
| + 'name': name,
|
| + 'is_static': function.is_static,
|
| + 'is_custom': is_custom,
|
| + 'create_callback': is_representative and is_normal_function and is_standard_function,
|
| + 'is_representative': is_representative,
|
| + 'conditional_runtime': conditional_runtime,
|
| + 'template': template,
|
| + 'setter': setter,
|
| + 'signature': signature,
|
| + 'property_attributes': property_attributes,
|
| + 'requires_custom_signature': requires_custom_signature,
|
| + 'custom_signature': custom_signature,
|
| + 'conditional_string': generate_conditional_string(function),
|
| + 'mandatory_parameters': mandatory_parameters,
|
| + 'length': get_function_mandatory_parameters(function, count_variadic=True),
|
| + 'parameters': parameter_check_parameters,
|
| + 'function_call_parameter': function_call_parameters,
|
| + 'method_for_main_world': method_for_main_world,
|
| + 'is_normal_function': is_normal_function,
|
| + 'is_standard_function': is_standard_function,
|
| + 'is_enabled_per_context_function': function.name and 'EnabledPerContext' in function.extended_attributes,
|
| + 'raises_exception': raises_exception,
|
| + 'do_not_check_security': 'DoNotCheckSecurity' in function.extended_attributes,
|
| + 'for_main_world_suffixes': for_main_world_suffixes,
|
| + 'cpp_name': implemented_as_cpp_name(function),
|
| + 'check_security_for_node': check_security_for_node,
|
| + 'enable_function': enable_function,
|
| + 'activity_logging': activity_logging,
|
| + }
|
| + contents.update(feature_observation_parameter)
|
| + contents.update(deprecation_notification_parameter)
|
| + contents.update(custom_element_invocation_scope_parameter)
|
| + return contents, includes
|
| +
|
| +
|
| +def get_function_call_parameter(interface, function, number_of_parameters=None, for_main_world_suffix='', replacements=None):
|
| + # return parameter for function_call macro, includes
|
| + replacements = replacements or {}
|
| + if number_of_parameters is None:
|
| + number_of_parameters = len(function.arguments)
|
| +
|
| + includes = []
|
| + arguments = []
|
| + cpp_class_name = implemented_as_cpp_name(interface)
|
| + implemented_by = function.extended_attributes.get('ImplementedBy')
|
| + ### TODO Similar to attribute. merge!
|
| + 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)
|
| + function_name = '%s::%s' % (implemented_by_cpp_name, implemented_as_cpp_name(function))
|
| + if not function.is_static:
|
| + arguments.append('imp')
|
| + elif function.is_static:
|
| + function_name = '%s::%s' % (cpp_class_name, implemented_as_cpp_name(function))
|
| + else:
|
| + function_name = 'imp->%s' % implemented_as_cpp_name(function)
|
| +
|
| + call_with = function.extended_attributes.get('CallWith')
|
| + call_with_arguments, call_with_parameter, call_with_includes = get_call_with_parameter(call_with, return_void=True, function=function)
|
| + includes += call_with_includes
|
| + arguments = call_with_arguments + arguments
|
| +
|
| + parameters = []
|
| + for index, parameter in enumerate(function.arguments):
|
| + svg_tear_off_and_not_list = False
|
| + if index == number_of_parameters:
|
| + break
|
| + if replacements.get(parameter.name):
|
| + arguments.append(replacements.get(parameter.name))
|
| + elif parameter.data_type == 'NodeFilter' or parameter.data_type == 'XPathNSResolver':
|
| + arguments.append('%s.get()' % parameter.name)
|
| + elif get_svg_type_needing_tear_off(parameter.data_type) and not interface.name.endswith('List'):
|
| + includes.append('core/dom/ExceptionCode.h')
|
| + arguments.append('%s->propertyReference()' % parameter.name)
|
| + svg_tear_off_and_not_list = True
|
| + elif parameter.data_type == 'SVGMatrix' and interface.name == 'SVGTransformList':
|
| + arguments.append('%s.get()' % parameter.name)
|
| + else:
|
| + arguments.append(parameter.name)
|
| + parameter = {
|
| + 'svg_tear_off_and_not_list': svg_tear_off_and_not_list,
|
| + 'name': parameter.name,
|
| + }
|
| + parameters.append(parameter)
|
| +
|
| + if get_raises_exception(function):
|
| + arguments.append('es')
|
| +
|
| + function_call_expression = '%s(%s)' % (function_name, ', '.join(arguments))
|
| + native_value_expression = get_pass_owner_expression(function.data_type, 'result')
|
| + function_call_statement = ''
|
| + if function.data_type == 'void':
|
| + function_call_statement = '%s;' % function_call_expression
|
| + elif extended_attribute_contains(function.extended_attributes.get('CallWith'), 'ScriptState') or get_raises_exception(function):
|
| + function_call_statement = '%s result = %s;' % (get_native_type(function.data_type, extended_attributes=function.extended_attributes), function_call_expression)
|
| + else:
|
| + native_value_expression = function_call_expression
|
| +
|
| + extended_attribute_contains_script_state = extended_attribute_contains(call_with, 'ScriptState')
|
| +
|
| + script_wrappable = is_dom_node_type(interface.name) and 'imp' or 0
|
| + return_js_value_statement = ''
|
| + return_js_value_statement, native_to_js_value_includes = get_native_to_js_value_statement(function.data_type, function.extended_attributes, native_value_expression, creation_context='args.Holder()', isolate='args.GetIsolate()', callback_info='args', script_wrappable=script_wrappable, for_main_world_suffix=for_main_world_suffix, used_as_return_value=True)
|
| + includes += native_to_js_value_includes
|
| +# print '[----]', function.name
|
| +
|
| + svg_native_type = svg_tear_off = get_svg_type_needing_tear_off(function.data_type)
|
| + svg_tear_off_and_not_list = svg_tear_off and not interface.name.endswith('List')
|
| + dom_node_type = is_dom_node_type(interface.name)
|
| + if svg_tear_off_and_not_list:
|
| + includes.append('V8%s.h' % function.data_type)
|
| + includes.append('core/svg/properties/SVGPropertyTearOff.h')
|
| +
|
| + parameter = {
|
| + 'statement': function_call_statement,
|
| + 'raises_exception': get_raises_exception(function),
|
| + 'return_js_value_statement': return_js_value_statement,
|
| + 'extended_attribute_contains_script_state': extended_attribute_contains_script_state,
|
| + 'call_with': call_with_parameter,
|
| + 'parameters': parameters,
|
| + 'svg_tear_off_and_not_list': svg_tear_off_and_not_list,
|
| + 'svg_tear_off': svg_tear_off,
|
| + 'is_dom_node_type': dom_node_type,
|
| + 'for_main_world_suffix': for_main_world_suffix,
|
| + 'svg_native_type': svg_native_type,
|
| + 'native_value_expression': native_value_expression,
|
| + }
|
| + return parameter, includes
|
| +
|
| +
|
| +def get_function_mandatory_parameters(function, count_variadic=False):
|
| + allow_non_optional = True
|
| + for parameter in function.arguments:
|
| + if parameter.is_optional or parameter.is_variadic:
|
| + allow_non_optional = False
|
| + else:
|
| + if not allow_non_optional:
|
| + raise Exception()
|
| + mandatory_parameters = 0
|
| + for parameter in function.arguments:
|
| + if parameter.is_optional:
|
| + break
|
| + if parameter.is_variadic and not count_variadic:
|
| + break
|
| + mandatory_parameters += 1
|
| +# print '[]', function.name, mandatory_parameters
|
| + return mandatory_parameters
|
| +
|
| +
|
| +def get_parameter_check_parameters(interface, function, for_main_world_suffix=''):
|
| + # GenerateParametersCheck in perl
|
| + includes = []
|
| + parameters_check_parameter = []
|
| + for parameter_index in range(len(function.arguments)):
|
| + parameter_check_parameter, parameter_check_includes = get_parameter_check_parameter(interface, function, parameter_index)
|
| + parameters_check_parameter.append(parameter_check_parameter)
|
| + includes += parameter_check_includes
|
| + replacements = {} # TODO
|
| + return parameters_check_parameter, includes, replacements
|
| +
|
| +
|
| +def get_parameter_check_parameter(interface, function, parameter_index, for_main_world_suffix=''):
|
| + # corresponds to for loop in GenerateParametersCheck in perl
|
| + includes = ['bindings/v8/ExceptionState.h']
|
| + parameter = function.arguments[parameter_index]
|
| + is_callback_interface = is_callback_interface_etc(parameter.data_type)
|
| + if is_callback_interface:
|
| + includes.append('V8%s.h' % parameter.data_type)
|
| + if parameter.data_type == 'SerializedScriptValue':
|
| + includes.append('bindings/v8/SerializedScriptValue.h')
|
| + is_index = 'IsIndex' in parameter.extended_attributes
|
| + if is_index:
|
| + includes.append('core/dom/ExceptionCode.h')
|
| +
|
| + native_type = get_native_type(parameter.data_type, extended_attributes=parameter.extended_attributes, used_to_assign_js_value=True)
|
| + native_element_type = get_native_type(parameter.data_type)
|
| + if native_element_type.endswith('>'):
|
| + native_element_type += ' '
|
| +
|
| +# print '[[]]', native_type
|
| + default = ''
|
| + if 'Default' in parameter.extended_attributes:
|
| + default = parameter.extended_attributes.get('Default')
|
| +
|
| + if parameter.is_optional and default == 'NullString':
|
| + js_value = 'argumentOrNull(args, %d)' % parameter_index
|
| + else:
|
| + js_value = 'args[%d]' % parameter_index
|
| +
|
| + js_to_native_statement, js_value_to_native_includes = get_js_value_to_native_statement(parameter.data_type, parameter.extended_attributes, js_value, parameter.name, 'args.GetIsolate()')
|
| + includes += js_value_to_native_includes
|
| +
|
| + enum_values = get_enum_values(parameter.data_type)
|
| + enum_validation_terms = ['string == "%s"' % enum_value for enum_value in enum_values]
|
| + enum_validation_expression = ' || '.join(enum_validation_terms)
|
| +
|
| + # Optional arguments without [Default=...] should generate an early call with fewer arguments.
|
| + # Optional arguments with [Optional=...] should not generate the early call.
|
| + # Optional Dictionary arguments always considered to have default of empty dictionary.
|
| + early_call = parameter.is_optional and 'Default' not in parameter.extended_attributes and native_type != 'Dictionary' and not is_callback_interface
|
| + early_call_multi_line = False
|
| + early_call_statements = {}
|
| + if early_call:
|
| + # TODO
|
| + early_call_statements, early_call_includes = get_function_call_parameter(interface, function, parameter_index, for_main_world_suffix=for_main_world_suffix)
|
| + includes += early_call_includes
|
| + early_call_multi_line = len([c for c in early_call_statements if c == '\n']) > 1
|
| +
|
| + parameter_check_parameter = {
|
| + 'index': parameter_index,
|
| + 'name': parameter.name,
|
| + 'type': parameter.data_type,
|
| + 'early_call': early_call,
|
| + 'early_call_statement_parameter': early_call_statements,
|
| + 'early_call_multi_line': early_call_multi_line,
|
| + 'is_callback_interface': is_callback_interface,
|
| + 'is_optional': parameter.is_optional,
|
| + 'is_variadic': parameter.is_variadic,
|
| + 'is_index': is_index,
|
| + 'is_wrapper_type': is_wrapper_type(parameter.data_type),
|
| + 'clamp': parameter.extended_attributes.get('Clamp'),
|
| + 'strict_type_checking': parameter.extended_attributes.get('StrictTypeChecking'),
|
| + 'enforce_range': 'EnforceRange' in parameter.extended_attributes,
|
| + 'js_to_native_statement': js_to_native_statement,
|
| + 'native_type': native_type,
|
| + 'native_element_type': native_element_type,
|
| + 'enum_validation_expression': enum_validation_expression,
|
| + 'is_enum_type': is_enum_type(parameter.data_type),
|
| + }
|
| + return parameter_check_parameter, includes
|
|
|