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
|
|