def create_method(self, idl_operation, arguments): name_converter = NameStyleConverter(idl_operation.name) return_type = self.type_resolver.type_from_definition(idl_operation) return { 'name': name_converter.to_upper_camel_case(), 'type': return_type, 'arguments': arguments }
def test_in_origin_trials_flag(self): features = [ { 'name': NameStyleConverter('a'), 'depends_on': [], 'origin_trial_feature_name': None }, { 'name': NameStyleConverter('b'), 'depends_on': ['a'], 'origin_trial_feature_name': 'OriginTrials' }, { 'name': NameStyleConverter('c'), 'depends_on': ['b'], 'origin_trial_feature_name': None }, { 'name': NameStyleConverter('d'), 'depends_on': ['b'], 'origin_trial_feature_name': None }, { 'name': NameStyleConverter('e'), 'depends_on': ['d'], 'origin_trial_feature_name': None }, ] self.assertSetEqual(util.origin_trials(features), {'b', 'c', 'd', 'e'}) features = [{ 'name': 'a', 'depends_on': ['x'], 'origin_trial_feature_name': None }, { 'name': 'b', 'depends_on': ['x', 'y'], 'origin_trial_feature_name': None }, { 'name': 'c', 'depends_on': ['y', 'z'], 'origin_trial_feature_name': None }, { 'name': 'x', 'depends_on': [], 'origin_trial_feature_name': None }, { 'name': 'y', 'depends_on': ['x'], 'origin_trial_feature_name': 'y' }, { 'name': 'z', 'depends_on': ['y'], 'origin_trial_feature_name': None }] self.assertSetEqual(util.origin_trials(features), {'b', 'c', 'y', 'z'})
def agent_name_to_include(config, agent_name): include_path = agent_config( config, agent_name, "include_path") or config["settings"]["include_path"] agent_class = agent_name_to_class(config, agent_name) return os.path.join(include_path, NameStyleConverter(agent_class).to_snake_case() + ".h")
def cpp_content_attribute_value_name(interface, value): if value == '': return 'g_empty_atom' if not value: return value includes.add('core/keywords.h') return 'keywords::' + NameStyleConverter(value).to_enum_value()
class MakeMediaFeaturesWriter(json5_generator.Writer): default_metadata = { 'namespace': '', 'export': '', } filters = { 'symbol': media_feature_symbol.getMediaFeatureSymbolWithSuffix(''), 'to_function_name': lambda symbol: NameStyleConverter(symbol).to_function_name(), } def __init__(self, json5_file_path, output_dir): super(MakeMediaFeaturesWriter, self).__init__(json5_file_path, output_dir) self._outputs = { ('media_features.h'): self.generate_header, } self._template_context = { 'entries': self.json5_file.name_dictionaries, 'input_files': self._input_files, 'header_guard': self.make_header_guard(self._relative_output_dir + 'media_festures.h') } @template_expander.use_jinja('core/css/templates/media_features.h.tmpl', filters=filters) def generate_header(self): return self._template_context
def v8_value_to_local_cpp_value(interface_name, method, argument, index): extended_attributes = argument.extended_attributes idl_type = argument.idl_type name = NameStyleConverter(argument.name).to_snake_case() v8_value = 'info[{index}]'.format(index=index) # History.pushState and History.replaceState are explicitly specified as # serializing the value for storage. The default is to not serialize for # storage. See https://html.spec.whatwg.org/C/#dom-history-pushstate if idl_type.name == 'SerializedScriptValue': for_storage = (interface_name == 'History' and method.name in ('pushState', 'replaceState')) return v8_value_to_local_cpp_ssv_value(extended_attributes, idl_type, v8_value, name, for_storage=for_storage) if argument.is_variadic: return v8_value_to_local_cpp_variadic_value(argument, index) return idl_type.v8_value_to_local_cpp_value( extended_attributes, v8_value, name, declare_variable=False, use_exception_state=method.returns_promise)
def _determine_blink_headers(self): irs = self._ir_map.irs_of_kinds( IRMap.IR.Kind.INTERFACE, IRMap.IR.Kind.INTERFACE_MIXIN, IRMap.IR.Kind.NAMESPACE, IRMap.IR.Kind.PARTIAL_INTERFACE, IRMap.IR.Kind.PARTIAL_INTERFACE_MIXIN, IRMap.IR.Kind.PARTIAL_NAMESPACE) self._ir_map.move_to_new_phase() for old_ir in irs: new_ir = self._maybe_make_copy(old_ir) self._ir_map.add(new_ir) if (new_ir.is_mixin and 'LegacyTreatAsPartialInterface' not in new_ir.extended_attributes): continue basepath, _ = posixpath.splitext( new_ir.debug_info.location.filepath) dirpath, filename = posixpath.split(basepath) impl_class = new_ir.extended_attributes.value_of('ImplementedAs') if impl_class: filename = NameStyleConverter(impl_class).to_snake_case() header = posixpath.join(dirpath, posixpath.extsep.join([filename, 'h'])) new_ir.code_generator_info.set_blink_headers([header])
def argument_context(interface, method, argument, index, is_visible=True): extended_attributes = argument.extended_attributes idl_type = argument.idl_type if is_visible: idl_type.add_includes_for_type(extended_attributes) this_cpp_value = cpp_value(interface, method, index) is_variadic_wrapper_type = argument.is_variadic and idl_type.is_wrapper_type has_type_checking_interface = idl_type.is_wrapper_type set_default_value = argument.set_default_value this_cpp_type = idl_type.cpp_type_args(extended_attributes=extended_attributes, raw_type=True, used_as_variadic_argument=argument.is_variadic) snake_case_name = NameStyleConverter(argument.name).to_snake_case() context = { 'cpp_type': ( v8_types.cpp_template_type('base::Optional', this_cpp_type) if idl_type.is_explicit_nullable and not argument.is_variadic else this_cpp_type), 'cpp_value': this_cpp_value, # FIXME: check that the default value's type is compatible with the argument's 'enum_type': idl_type.enum_type, 'enum_values': idl_type.enum_values, 'handle': '%s_handle' % snake_case_name, # TODO(peria): remove once [DefaultValue] removed and just use # argument.default_value. https://crbug.com/924419 'has_default': 'DefaultValue' in extended_attributes or set_default_value, 'has_type_checking_interface': has_type_checking_interface, # Dictionary is special-cased, but arrays and sequences shouldn't be 'idl_type': idl_type.base_type, 'idl_type_object': idl_type, 'index': index, 'is_callback_function': idl_type.is_callback_function, 'is_callback_interface': idl_type.is_callback_interface, # FIXME: Remove generic 'Dictionary' special-casing 'is_dictionary': idl_type.is_dictionary or idl_type.base_type == 'Dictionary', 'is_explicit_nullable': idl_type.is_explicit_nullable, 'is_nullable': idl_type.is_nullable, 'is_optional': argument.is_optional, 'is_variadic': argument.is_variadic, 'is_variadic_wrapper_type': is_variadic_wrapper_type, 'is_wrapper_type': idl_type.is_wrapper_type, 'local_cpp_variable': snake_case_name, 'name': argument.name, 'set_default_value': set_default_value, 'use_permissive_dictionary_conversion': 'PermissiveDictionaryConversion' in extended_attributes, 'v8_set_return_value': v8_set_return_value(interface.name, method, this_cpp_value), 'v8_set_return_value_for_main_world': v8_set_return_value(interface.name, method, this_cpp_value, for_main_world=True), 'v8_value_to_local_cpp_value': v8_value_to_local_cpp_value(interface.name, method, argument, index), } context.update({ 'is_optional_without_default_value': context['is_optional'] and not context['has_default'] and not context['is_dictionary'] and not context['is_callback_interface'], }) return context
def test_init_graph(self): features = [ { 'name': NameStyleConverter('a') }, { 'name': NameStyleConverter('b') }, { 'name': NameStyleConverter('c') }, ] graph = util.init_graph(features) self.assertEqual(len(features), len(graph)) for node in graph: self.assertEqual(len(graph[node]), 0)
def agent_name_to_include(config, agent_name): include_path = agent_config( config, agent_name, "include_path") or config["settings"]["include_path"] agent_class = agent_name_to_class(config, agent_name) include_file = os.path.join( include_path, NameStyleConverter(agent_class).to_snake_case() + ".h") return include_file.replace("dev_tools", "devtools")
def __init__(self, field_role, name_for_methods, property_name, type_name, wrapper_pointer_name, field_template, size, default_value, custom_copy, custom_compare, mutable, getter_method_name, setter_method_name, initial_method_name, computed_style_custom_functions, **kwargs): name_source = NameStyleConverter(name_for_methods) self.name = name_source.to_class_data_member() self.property_name = property_name self.type_name = type_name self.wrapper_pointer_name = wrapper_pointer_name self.alignment_type = self.wrapper_pointer_name or self.type_name self.field_template = field_template self.size = size self.default_value = default_value self.custom_copy = custom_copy self.custom_compare = custom_compare self.mutable = mutable self.group = None # Method names self.getter_method_name = getter_method_name self.setter_method_name = setter_method_name self.internal_getter_method_name = name_source.to_function_name( suffix='internal') self.internal_mutable_method_name = name_source.to_function_name( prefix='mutable', suffix='internal') self.internal_setter_method_name = NameStyleConverter( setter_method_name).to_function_name(suffix='internal') self.initial_method_name = initial_method_name self.resetter_method_name = name_source.to_function_name( prefix='reset') self.computed_style_custom_functions = computed_style_custom_functions # Only bitfields have sizes. self.is_bit_field = self.size is not None # Field role: one of these must be true self.is_property = field_role == 'property' self.is_inherited_flag = field_role == 'inherited_flag' assert (self.is_property, self.is_inherited_flag).count(True) == 1, \ 'Field role has to be exactly one of: property, inherited_flag' if not self.is_inherited_flag: self.is_inherited = kwargs.pop('inherited') self.is_independent = kwargs.pop('independent') self.is_semi_independent_variable = kwargs.pop( 'semi_independent_variable') assert self.is_inherited or not self.is_independent, \ 'Only inherited fields can be independent' self.is_inherited_method_name = name_source.to_function_name( suffix=['is', 'inherited']) assert len(kwargs) == 0, \ 'Unexpected arguments provided to Field: ' + str(kwargs)
def scoped_content_attribute_name(interface, attribute): content_attribute_name = attribute.extended_attributes['Reflect'] or attribute.name.lower() symbol_name = 'k' + NameStyleConverter(content_attribute_name).to_upper_camel_case() if interface.name.startswith('SVG'): namespace = 'svg_names' includes.add('core/svg_names.h') else: namespace = 'html_names' includes.add('core/html_names.h') return '%s::%sAttr' % (namespace, symbol_name)
def cpp_name(definition_or_member): extended_attributes = definition_or_member.extended_attributes if extended_attributes and 'ImplementedAs' in extended_attributes: return extended_attributes['ImplementedAs'] # WebIDL identifiers can contain hyphens[1], but C++ identifiers cannot. # Therefore camelCase hyphen-containing identifiers. # # [1] https://heycam.github.io/webidl/#prod-identifier if '-' in definition_or_member.name: return NameStyleConverter(definition_or_member.name).to_lower_camel_case() return definition_or_member.name
def v8_value_to_local_cpp_variadic_value(argument, index): assert argument.is_variadic idl_type = v8_types.native_value_traits_type_name(argument.idl_type, argument.extended_attributes, True) return { 'assign_expression': 'ToImplArguments<%s>(info, %s, exception_state)' % (idl_type, index), 'check_expression': 'exception_state.HadException()', 'cpp_name': NameStyleConverter(argument.name).to_snake_case(), 'declare_variable': False, }
def _replace_include_path(self, match): include_or_import = match.group(1) path = match.group(2) # If |path| starts with 'blink/public/resources', we should prepend # 'third_party/'. # # If |path| starts with 'third_party/WebKit', we should adjust the # directory name for third_party/blink, and replace its basename by # self._basename_map. # # If |path| starts with a Blink-internal directory such as bindings, # core, modules, platform, public, it refers to a checked-in file, or a # generated file. For the former, we should add 'third_party/blink/' and # replace the basename. For the latter, we should update the basename # for a name mapped from an IDL renaming, and should add # 'third_party/blink/'. if path.startswith('blink/public/resources'): path = path.replace('blink/public', 'third_party/blink/public') return '#%s "%s"' % (include_or_import, path) if path.startswith('third_party/WebKit'): path = path.replace('third_party/WebKit/Source', 'third_party/blink/renderer') path = path.replace('third_party/WebKit/common', 'third_party/blink/common') path = path.replace('third_party/WebKit/public', 'third_party/blink/public') path = self._update_basename(path) return '#%s "%s"' % (include_or_import, path) match = None for regex in self._checked_in_header_re_list: match = regex.search(path) if match: break if match: if match.group(1) in self._basename_map: path = path[:match.start(1)] + self._basename_map[match.group( 1)] elif 'core/inspector/protocol/' not in path: basename_start = path.rfind('/') + 1 basename = path[basename_start:] if basename in self._idl_generated_impl_headers: path = path[:basename_start] + self._basename_map[basename] elif basename.startswith('V8'): path = path[:basename_start] + NameStyleConverter( basename[:len(basename) - 2]).to_snake_case() + '.h' if path.startswith('public'): path = 'third_party/blink/' + path else: path = 'third_party/blink/renderer/' + path return '#%s "%s"' % (include_or_import, path)
class ElementLookupTrieWriter(json5_generator.Writer): # FIXME: Inherit all these from somewhere. default_parameters = { 'JSInterfaceName': {}, 'constructorNeedsCreateElementFlags': {}, 'interfaceHeaderDir': {}, 'interfaceName': {}, 'noConstructor': {}, 'noTypeHelpers': {}, 'runtimeEnabled': {}, } default_metadata = { 'attrsNullNamespace': None, 'export': '', 'fallbackInterfaceName': '', 'fallbackJSInterfaceName': '', 'namespace': '', 'namespacePrefix': '', 'namespaceURI': '', } filters = { 'symbol': lambda symbol: 'k' + NameStyleConverter(symbol).to_upper_camel_case() } def __init__(self, json5_file_paths, output_dir): super(ElementLookupTrieWriter, self).__init__(json5_file_paths, output_dir) self._tags = {} for entry in self.json5_file.name_dictionaries: self._tags[entry['name'].original] = entry['name'].original self._namespace = self.json5_file.metadata['namespace'].strip('"') basename = self._namespace.lower() + '_element_lookup_trie' self._outputs = { (basename + '.h'): self.generate_header, (basename + '.cc'): self.generate_implementation, } @template_expander.use_jinja('templates/element_lookup_trie.h.tmpl') def generate_header(self): return { 'input_files': self._input_files, 'namespace': self._namespace, } @template_expander.use_jinja( 'templates/element_lookup_trie.cc.tmpl', filters=filters) def generate_implementation(self): return { 'input_files': self._input_files, 'namespace': self._namespace, 'length_tries': trie_builder.trie_list_by_str_length(self._tags) }
def test_origin_trials(self): features = [ _feature(NameStyleConverter('a')), _feature(NameStyleConverter('b'), depends_on=['a'], origin_trial_feature_name='b'), _feature(NameStyleConverter('c'), depends_on=['b']), _feature(NameStyleConverter('d'), depends_on=['b']), _feature(NameStyleConverter('e'), depends_on=['d']) ] self.assertSetEqual(util.origin_trials(features), {'b', 'c', 'd', 'e'}) features = [ _feature('a'), _feature('b', depends_on=['x', 'y']), _feature('c', depends_on=['y', 'z']), _feature('x', depends_on=['a']), _feature('y', depends_on=['x'], origin_trial_feature_name='y'), _feature('z', depends_on=['y']) ] self.assertSetEqual(util.origin_trials(features), {'b', 'c', 'y', 'z'})
def _create_inherited_flag_field(property_): """ Create the field used for an inheritance fast path from an independent CSS property, and return the Field object. """ name_for_methods = NameStyleConverter( property_['name_for_methods']).to_function_name( suffix=['is', 'inherited']) name_source = NameStyleConverter(name_for_methods) return Field( 'inherited_flag', name_for_methods, property_name=property_['name'].original, type_name='bool', wrapper_pointer_name=None, field_template='primitive', size=1, default_value='true', custom_copy=False, custom_compare=False, mutable=False, getter_method_name=name_source.to_function_name(), setter_method_name=name_source.to_function_name(prefix='set'), initial_method_name=name_source.to_function_name(prefix='initial'), computed_style_custom_functions=property_[ "computed_style_custom_functions"], )
def _get_entry(self, item): entry = copy.deepcopy(self._defaults) if type(item) is not dict: entry["name"] = NameStyleConverter(item) return entry if "name" not in item: raise Exception("Missing name in item: %s" % item) if not self.parameters: entry.update(item) return entry assert "name" not in self.parameters, "The parameter 'name' is reserved, use a different name." entry["name"] = NameStyleConverter(item.pop("name")) # Validate parameters if it's specified. for key, value in item.items(): if key not in self.parameters: raise Exception("Unknown parameter: '%s'\nKnown params: %s" % (key, self.parameters.keys())) assert self.parameters[key] is not None, \ "Specification for parameter 'key' cannot be None. Use {} instead." self._validate_parameter(self.parameters[key], value) entry[key] = value return entry
def __init__(self, name, subgroups, fields): self.name = name self.subgroups = subgroups self.fields = fields self.parent = None converter = NameStyleConverter(name or '') self.type_name = converter.to_class_name(prefix='style', suffix='data') self.member_name = converter.to_class_data_member(suffix='data') self.num_32_bit_words_for_bit_fields = _num_32_bit_words_for_bit_fields( field for field in fields if field.is_bit_field) # Recursively get all the fields in the subgroups as well self.all_fields = _flatten_list(subgroup.all_fields for subgroup in subgroups) + fields # Ensure that all fields/subgroups on this group link to it for field in fields: field.group = self for subgroup in subgroups: subgroup.parent = self
def main(): assert len(sys.argv) == 4 input_file = sys.argv[1] output_dir = sys.argv[2] bison_exe = sys.argv[3] path_to_bison = os.path.split(bison_exe)[0] if path_to_bison: # Make sure this path is in the path so that it can find its auxiliary # binaries (in particular, m4). To avoid other 'm4's being found, insert # at head, rather than tail. os.environ['PATH'] = path_to_bison + os.pathsep + os.environ['PATH'] input_name = os.path.basename(input_file) assert input_name == 'xpath_grammar.y' prefix = {'xpath_grammar.y': 'xpathyy'}[input_name] # Output name without directory and extension. output_basename = os.path.splitext(input_name)[0] + '_generated' output_cc = os.path.join(output_dir, output_basename + '.cc') BISON_HEADER_EXT = '.hh' original_output_h = os.path.join(output_dir, output_basename + BISON_HEADER_EXT) return_code = subprocess.call( [bison_exe, '-d', '-p', prefix, input_file, '-o', output_cc]) assert return_code == 0 # If the file doesn't exist, this raise an OSError. os.stat(original_output_h) # The generated files contain references to the original "foo.hh" for # #include and #line. We replace them with "foo.h". common_replace_list = [(output_basename + BISON_HEADER_EXT, output_basename + '.h')] # Rewrite the generated header with #include guards. CLANG_FORMAT_DISABLE_LINE = "// clang-format off" output_h = os.path.join(output_dir, output_basename + '.h') header_guard = NameStyleConverter(output_h).to_header_guard() modify_file(original_output_h, [ CLANG_FORMAT_DISABLE_LINE, '#ifndef %s' % header_guard, '#define %s' % header_guard ], ['#endif // %s' % header_guard], replace_list=common_replace_list) os.rename(original_output_h, output_h) modify_file(output_cc, [CLANG_FORMAT_DISABLE_LINE], [], replace_list=common_replace_list)
def v8_value_to_local_cpp_value(interface_name, method, argument, index): extended_attributes = argument.extended_attributes idl_type = argument.idl_type name = NameStyleConverter(argument.name).to_snake_case() v8_value = 'info[{index}]'.format(index=index) if argument.is_variadic: return v8_value_to_local_cpp_variadic_value(argument, index) return idl_type.v8_value_to_local_cpp_value( extended_attributes, v8_value, name, declare_variable=False, use_exception_state=method.returns_promise)
def __init__(self, name, source): self.name = NameStyleConverter(name).to_snake_case() self.header_name = self.name + "_inl.h" self.forward_declarations = [] self.declarations = [] for line in map(str.strip, source.split("\n")): line = re.sub(r"\s{2,}", " ", line).strip() # Collapse whitespace if len(line) == 0: continue elif line.startswith("class ") or line.startswith("struct "): self.forward_declarations.append(line) else: self.declarations.append(Method(line)) self.forward_declarations.sort()
def _find_enum_longest_continuous_segment(property_, name_to_position_dictionary): """Find the longest continuous segment in the list of keywords Finding the continuous segment will allows us to do the subtraction between keywords so that the distance between 2 keywords in this enum is equal to the distance of corresponding keywords in another enum. Step 1: Convert keyword enums into number. Sort and find all continuous segment in the list of enums. Step 2: Get the longest segment. Step 3: Compose a list of keyword enums and their respective numbers in the sorted order. Step 4: Build the switch case statements of other enums not in the segment. Enums in the segment will be computed in default clause. """ property_enum_order = range(len(property_['keywords'])) css_enum_order = [ name_to_position_dictionary[x] for x in property_['keywords'] ] enum_pair_list = zip(css_enum_order, property_enum_order) enum_segment, enum_pair_list = _find_continuous_segment(enum_pair_list) longest_segment = _find_largest_segment(enum_segment) enum_tuple_list = [] for x in enum_pair_list: keyword = NameStyleConverter(property_['keywords'][x[1]]) enum_tuple_list.append((keyword.to_enum_value(), x[1], enum_for_css_keyword(keyword), x[0])) return enum_tuple_list, enum_segment, longest_segment
def v8_value_to_local_cpp_variadic_value(argument, index): assert argument.is_variadic idl_type = v8_types.native_value_traits_type_name( argument.idl_type, argument.extended_attributes, True) execution_context_if_needed = '' if argument.idl_type.has_string_context: execution_context_if_needed = ', bindings::ExecutionContextFromV8Wrappable(impl)' assign_expression = 'ToImplArguments<%s>(info, %s, exception_state%s)' % ( idl_type, index, execution_context_if_needed) return { 'assign_expression': assign_expression, 'check_expression': 'exception_state.HadException()', 'cpp_name': NameStyleConverter(argument.name).to_snake_case(), 'declare_variable': False, }
def argument_set_default_value(argument): idl_type = argument.idl_type default_value = argument.default_value variable_name = NameStyleConverter(argument.name).to_snake_case() if not default_value: return None if idl_type.is_dictionary: if argument.default_value.is_null: return None if argument.default_value.value == '{}': return None raise Exception('invalid default value for dictionary type') if idl_type.is_array_or_sequence_type: if default_value.value != '[]': raise Exception('invalid default value for sequence type: %s' % default_value.value) # Nothing to do when we set an empty sequence as default value, but we # need to return non-empty value so that we don't generate method calls # without this argument. return '/* Nothing to do */' if idl_type.is_union_type: if argument.default_value.is_null: if not idl_type.includes_nullable_type: raise Exception( 'invalid default value for union type: null for %s' % idl_type.name) # Union container objects are "null" initially. return '/* null default value */' if default_value.value == "{}": member_type = idl_type.dictionary_member_type elif isinstance(default_value.value, basestring): member_type = idl_type.string_member_type elif isinstance(default_value.value, (int, float)): member_type = idl_type.numeric_member_type elif isinstance(default_value.value, bool): member_type = idl_type.boolean_member_type else: member_type = None if member_type is None: raise Exception('invalid default value for union type: %r for %s' % (default_value.value, idl_type.name)) member_type_name = (member_type.inner_type.name if member_type.is_nullable else member_type.name) return '%s.Set%s(%s)' % (variable_name, member_type_name, member_type.literal_cpp_value(default_value)) return '%s = %s' % (variable_name, idl_type.literal_cpp_value(default_value))
def cpp_value(interface, method, number_of_arguments): # Truncate omitted optional arguments arguments = method.arguments[:number_of_arguments] cpp_arguments = [] if method.is_constructor: call_with_values = interface.extended_attributes.get( 'ConstructorCallWith') else: call_with_values = method.extended_attributes.get('CallWith') cpp_arguments.extend(v8_utilities.call_with_arguments(call_with_values)) # Members of IDL partial interface definitions are implemented in C++ as # static member functions, which for instance members (non-static members) # take *impl as their first argument if ('PartialInterfaceImplementedAs' in method.extended_attributes and not method.is_static): cpp_arguments.append('*impl') for argument in arguments: variable_name = NameStyleConverter(argument.name).to_snake_case() if argument.idl_type.base_type == 'SerializedScriptValue': cpp_arguments.append('std::move(%s)' % variable_name) else: cpp_arguments.append(variable_name) if ('RaisesException' in method.extended_attributes or (method.is_constructor and has_extended_attribute_value( interface, 'RaisesException', 'Constructor'))): cpp_arguments.append('exception_state') # If a method returns an IDL dictionary or union type, the return value is # passed as an argument to impl classes. idl_type = method.idl_type if idl_type and idl_type.use_output_parameter_for_result: cpp_arguments.append('result') if method.name == 'Constructor': base_name = 'Create' elif method.name == 'NamedConstructor': base_name = 'CreateForJSConstructor' else: base_name = v8_utilities.cpp_name(method) cpp_method_name = v8_utilities.scoped_name(interface, method, base_name) return '%s(%s)' % (cpp_method_name, ', '.join(cpp_arguments))
def __init__(self, json5_file_path, output_dir): super(MakeElementTypeHelpersWriter, self).__init__(json5_file_path, output_dir) self.namespace = self.json5_file.metadata['namespace'].strip('"') self.fallback_interface = self.json5_file.metadata[ 'fallbackInterfaceName'].strip('"') assert self.namespace, 'A namespace is required.' basename = self.namespace.lower() + '_element_type_helpers' self._outputs = { (basename + '.h'): self.generate_helper_header, (basename + '.cc'): self.generate_helper_implementation, } base_element_header = 'third_party/blink/renderer/core/{}/{}_element.h'.format( self.namespace.lower(), NameStyleConverter(self.namespace).to_snake_case()) self._template_context = { 'base_element_header': base_element_header, 'cpp_namespace': self.namespace.lower() + '_names', 'input_files': self._input_files, 'namespace': self.namespace, 'tags': self.json5_file.name_dictionaries, 'elements': set(), } tags = self._template_context['tags'] elements = self._template_context['elements'] interface_counts = defaultdict(int) for tag in tags: tag['interface'] = self._interface(tag) interface_counts[tag['interface']] += 1 tag['js_interface'] = tag['interface'] if tag['JSInterfaceName']: tag['js_interface'] = tag['JSInterfaceName'] elements.add(tag['js_interface']) for tag in tags: tag['multipleTagNames'] = (interface_counts[tag['interface']] > 1 or tag['interface'] == self.fallback_interface)
def relative_dest(fs, filename): """Returns a destination path string for given filename. |filename| is a path relative to third_party/WebKit, and the resultant path is relative to third_party/blink. """ dest = None if filename.startswith('Source'): dest = re.sub(r'^Source', 'renderer', filename) elif filename.startswith('common') or filename.startswith('public'): dest = filename else: raise ValueError( '|filename| must start with "common", "public", or "Source": %s' % filename) if filename.endswith( ('.h', '.cpp', '.mm', '.idl', '.typemap', '.proto', 'Settings.json5')): dirname, basename = fs.split(dest) basename, ext = fs.splitext(basename) # Skip some inspector-related files. #includes for these files are # generated by a script outside of Blink. if (re.match(r'Inspector.*Agent', basename) or basename.startswith('AdTracker') or basename == 'InspectorTraceEvents' or basename == 'PerformanceMonitor' or basename == 'PlatformTraceEventsAgent'): return dest if filename.endswith('.cpp'): ext = '.cc' # WebKit.h should be renamed to blink.h. if basename == 'WebKit' and ext == '.h': basename = 'blink' if basename.lower() != basename: basename = NameStyleConverter(basename).to_snake_case() return fs.join(dirname, basename + ext) return dest
def attribute_context(interface, attribute, interfaces, component_info): """Creates a Jinja template context for an attribute of an interface. Args: interface: An interface which |attribute| belongs to attribute: An attribute to create the context for interfaces: A dict which maps an interface name to the definition which can be referred if needed component_info: A dict containing component wide information Returns: A Jinja template context for |attribute| """ idl_type = attribute.idl_type base_idl_type = idl_type.base_type extended_attributes = attribute.extended_attributes idl_type.add_includes_for_type(extended_attributes) if idl_type.enum_values: includes.add('core/inspector/console_message.h') includes.add('platform/heap/heap.h') # [CheckSecurity] is_cross_origin = 'CrossOrigin' in extended_attributes is_check_security_for_receiver = (has_extended_attribute_value( interface, 'CheckSecurity', 'Receiver') and is_cross_origin) is_check_security_for_return_value = (has_extended_attribute_value( attribute, 'CheckSecurity', 'ReturnValue')) if is_check_security_for_receiver or is_check_security_for_return_value: includes.add('bindings/core/v8/binding_security.h') if is_check_security_for_return_value: includes.add('core/frame/web_feature.h') includes.add('platform/instrumentation/use_counter.h') # [CrossOrigin] if has_extended_attribute_value(attribute, 'CrossOrigin', 'Setter'): includes.add('platform/bindings/v8_cross_origin_callback_info.h') # [Constructor] # TODO(yukishiino): Constructors are much like methods although constructors # are not methods. Constructors must be data-type properties, and we can # support them as a kind of methods. constructor_type = idl_type.constructor_type_name if is_constructor_attribute( attribute) else None # [CEReactions] is_ce_reactions = 'CEReactions' in extended_attributes if is_ce_reactions: includes.add('core/html/custom/ce_reactions_scope.h') # [CustomElementCallbacks], [Reflect] is_custom_element_callbacks = 'CustomElementCallbacks' in extended_attributes is_reflect = 'Reflect' in extended_attributes # [ReflectOnly] reflect_only = extended_attribute_value_as_list(attribute, 'ReflectOnly') if reflect_only: reflect_only = map( lambda v: cpp_content_attribute_value_name(interface, v), reflect_only) if is_custom_element_callbacks or is_reflect: includes.add('core/html/custom/v0_custom_element_processing_stack.h') # [PerWorldBindings] if 'PerWorldBindings' in extended_attributes: assert idl_type.is_wrapper_type or 'LogActivity' in \ extended_attributes, \ '[PerWorldBindings] should only be used with wrapper types: %s.%s' % \ (interface.name, attribute.name) # [SaveSameObject] is_save_same_object = ('SameObject' in attribute.extended_attributes and 'SaveSameObject' in attribute.extended_attributes) # [StringContext] if idl_type.has_string_context: includes.add('bindings/core/v8/generated_code_helper.h') # [CachedAccessor] is_cached_accessor = 'CachedAccessor' in extended_attributes # [LenientSetter] is_lenient_setter = 'LenientSetter' in extended_attributes # [CachedAttribute] cached_attribute_validation_method = extended_attributes.get( 'CachedAttribute') keep_alive_for_gc = is_keep_alive_for_gc(interface, attribute) does_generate_getter = (not has_custom_getter(attribute) and not constructor_type) does_generate_setter = ( has_setter(interface, attribute) and not (has_custom_setter(attribute) or is_lenient_setter)) use_private_property_in_getter = (does_generate_getter and (cached_attribute_validation_method or is_save_same_object or keep_alive_for_gc)) use_private_property_in_setter = (does_generate_setter and cached_attribute_validation_method) private_property_is_shared_between_getter_and_setter = ( use_private_property_in_getter and use_private_property_in_setter) does_use_private_property = (use_private_property_in_getter or use_private_property_in_setter or is_cached_accessor) if does_use_private_property: includes.add('platform/bindings/v8_private_property.h') # [LogActivity] if 'LogActivity' in extended_attributes: includes.add('platform/bindings/v8_per_context_data.h') # [DeprecateAs], [MeasureAs] deprecate_as = v8_utilities.deprecate_as(attribute) measure_as = v8_utilities.measure_as(attribute, interface) # [HighEntropy] high_entropy = v8_utilities.high_entropy(attribute) is_lazy_data_attribute = \ (constructor_type and not (measure_as or deprecate_as)) or \ (str(idl_type) == 'Window' and attribute.name in ('frames', 'self', 'window')) runtime_features = component_info['runtime_enabled_features'] internal_name = cpp_encoded_property_name(attribute) cpp_type = idl_type.cpp_type if idl_type.is_explicit_nullable: cpp_type = v8_types.cpp_template_type('base::Optional', cpp_type) context = { # [ActivityLogging] 'activity_logging_world_list_for_getter': v8_utilities.activity_logging_world_list(attribute, 'Getter'), # [ActivityLogging] 'activity_logging_world_list_for_setter': v8_utilities.activity_logging_world_list(attribute, 'Setter'), # [ActivityLogging] 'activity_logging_world_check': v8_utilities.activity_logging_world_check(attribute), 'cached_accessor_name': 'k%s%s' % (interface.name, attribute.name.capitalize()), 'cached_attribute_validation_method': cached_attribute_validation_method, 'camel_case_name': NameStyleConverter(internal_name).to_upper_camel_case(), 'constructor_type': constructor_type, 'context_enabled_feature_name': v8_utilities.context_enabled_feature_name(attribute), 'cpp_name': cpp_name(attribute), 'cpp_type': cpp_type, 'cpp_type_initializer': idl_type.cpp_type_initializer, 'deprecate_as': deprecate_as, 'does_generate_getter': does_generate_getter, 'does_generate_setter': does_generate_setter, 'enum_type': idl_type.enum_type, 'enum_values': idl_type.enum_values, # [Exposed] 'exposed_test': v8_utilities.exposed(attribute, interface), 'getter_has_no_side_effect': has_extended_attribute_value(attribute, 'Affects', 'Nothing'), 'has_cross_origin_getter': has_extended_attribute_value(attribute, 'CrossOrigin', None) or has_extended_attribute_value(attribute, 'CrossOrigin', 'Getter'), 'has_cross_origin_setter': has_extended_attribute_value(attribute, 'CrossOrigin', 'Setter'), 'has_custom_getter': has_custom_getter(attribute), 'has_custom_setter': has_custom_setter(attribute), 'has_promise_type': idl_type.name == 'Promise', 'has_setter': has_setter(interface, attribute), 'high_entropy': high_entropy, 'idl_type': str(idl_type), 'is_cached_accessor': is_cached_accessor, 'is_call_with_execution_context': has_extended_attribute_value(attribute, 'CallWith', 'ExecutionContext'), 'is_call_with_script_state': has_extended_attribute_value(attribute, 'CallWith', 'ScriptState'), 'is_ce_reactions': is_ce_reactions, 'is_check_security_for_receiver': is_check_security_for_receiver, 'is_check_security_for_return_value': is_check_security_for_return_value, 'is_custom_element_callbacks': is_custom_element_callbacks, # TODO(yukishiino): Make all DOM attributes accessor-type properties. 'is_data_type_property': is_data_type_property(interface, attribute), 'is_getter_raises_exception': # [RaisesException] 'RaisesException' in extended_attributes and extended_attributes['RaisesException'] in (None, 'Getter'), 'is_keep_alive_for_gc': keep_alive_for_gc, 'is_lazy_data_attribute': is_lazy_data_attribute, 'is_lenient_setter': is_lenient_setter, 'is_lenient_this': 'LegacyLenientThis' in extended_attributes, 'is_nullable': idl_type.is_nullable, 'is_explicit_nullable': idl_type.is_explicit_nullable, 'is_named_constructor': is_named_constructor_attribute(attribute), 'is_partial_interface_member': 'PartialInterfaceImplementedAs' in extended_attributes, 'is_per_world_bindings': 'PerWorldBindings' in extended_attributes, 'is_put_forwards': 'PutForwards' in extended_attributes, 'is_read_only': attribute.is_read_only, 'is_reflect': is_reflect, 'is_replaceable': 'Replaceable' in attribute.extended_attributes, 'is_save_same_object': is_save_same_object, 'is_static': attribute.is_static, 'is_url': 'URL' in extended_attributes, 'is_unforgeable': is_unforgeable(attribute), 'measure_as': measure_as, 'name': attribute.name, 'on_instance': v8_utilities.on_instance(interface, attribute), 'on_interface': v8_utilities.on_interface(interface, attribute), 'on_prototype': v8_utilities.on_prototype(interface, attribute), # [RuntimeEnabled] for origin trial 'origin_trial_feature_name': v8_utilities.origin_trial_feature_name(attribute, runtime_features), 'private_property_is_shared_between_getter_and_setter': private_property_is_shared_between_getter_and_setter, 'property_attributes': property_attributes(interface, attribute), 'reflect_empty': cpp_content_attribute_value_name( interface, extended_attributes.get('ReflectEmpty')), 'reflect_invalid': cpp_content_attribute_value_name( interface, extended_attributes.get('ReflectInvalid', '')), 'reflect_missing': cpp_content_attribute_value_name( interface, extended_attributes.get('ReflectMissing')), 'reflect_only': reflect_only, # [RuntimeEnabled] if not in origin trial 'runtime_enabled_feature_name': v8_utilities.runtime_enabled_feature_name(attribute, runtime_features), # [SecureContext] 'secure_context_test': v8_utilities.secure_context(attribute, interface), 'use_output_parameter_for_result': idl_type.use_output_parameter_for_result, 'world_suffixes': ( ['', 'ForMainWorld'] if 'PerWorldBindings' in extended_attributes else ['']), # [PerWorldBindings] } if not has_custom_getter(attribute): getter_context(interface, attribute, context) if not has_custom_setter(attribute) and has_setter(interface, attribute): setter_context(interface, attribute, interfaces, context) # [RuntimeCallStatsCounter] runtime_call_stats_context(interface, attribute, context) # [CrossOrigin] is incompatible with a number of other attributes, so check # for them here. if is_cross_origin: if context['has_cross_origin_setter'] and context['has_custom_setter']: raise Exception( '[CrossOrigin] and [Custom] are incompatible on the same setter: %s.%s', interface.name, attribute.name) if context['is_per_world_bindings']: raise Exception( '[CrossOrigin] and [PerWorldBindings] are incompatible: %s.%s', interface.name, attribute.name) if context['constructor_type']: raise Exception( '[CrossOrigin] cannot be used for constructors: %s.%s', interface.name, attribute.name) return context