Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(186)

Unified Diff: Source/bindings/scripts/v8_functions.py

Issue 17572008: WIP IDL compiler rewrite (Closed) Base URL: https://chromium.googlesource.com/chromium/blink@master
Patch Set: Branch: const + primitive type readonly attributes Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/bindings/scripts/v8_constructors.py ('k') | Source/bindings/scripts/v8_includes.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « Source/bindings/scripts/v8_constructors.py ('k') | Source/bindings/scripts/v8_includes.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698