def generate_code(self, definitions, definition_name): """Returns .h/.cpp code as ((path, content)...).""" # Set local type info IdlType.set_callback_functions(definitions.callback_functions.keys()) IdlType.set_enums((enum.name, enum.values) for enum in definitions.enumerations.values()) return self.generate_code_internal(definitions, definition_name)
def __init__(self, interfaces_info, cache_dir, output_dir): interfaces_info = interfaces_info or {} self.interfaces_info = interfaces_info self.jinja_env = initialize_jinja_env(cache_dir) self.output_dir = output_dir # Set global type info idl_types.set_ancestors(dict( (interface_name, interface_info['ancestors']) for interface_name, interface_info in interfaces_info.iteritems() if interface_info['ancestors'])) IdlType.set_callback_interfaces(set( interface_name for interface_name, interface_info in interfaces_info.iteritems() if interface_info['is_callback_interface'])) IdlType.set_dictionaries(set( dictionary_name for dictionary_name, interface_info in interfaces_info.iteritems() if interface_info['is_dictionary'])) IdlType.set_implemented_as_interfaces(dict( (interface_name, interface_info['implemented_as']) for interface_name, interface_info in interfaces_info.iteritems() if interface_info['implemented_as'])) IdlType.set_garbage_collected_types(set( interface_name for interface_name, interface_info in interfaces_info.iteritems() if 'GarbageCollected' in interface_info['inherited_extended_attributes'])) IdlType.set_will_be_garbage_collected_types(set( interface_name for interface_name, interface_info in interfaces_info.iteritems() if 'WillBeGarbageCollected' in interface_info['inherited_extended_attributes'])) v8_types.set_component_dirs(dict( (interface_name, interface_info['component_dir']) for interface_name, interface_info in interfaces_info.iteritems()))
def set_global_type_info(interfaces_info): idl_types.set_ancestors(interfaces_info['ancestors']) IdlType.set_callback_interfaces(interfaces_info['callback_interfaces']) IdlType.set_dictionaries(interfaces_info['dictionaries']) IdlType.set_implemented_as_interfaces(interfaces_info['implemented_as_interfaces']) IdlType.set_garbage_collected_types(interfaces_info['garbage_collected_interfaces']) IdlType.set_will_be_garbage_collected_types(interfaces_info['will_be_garbage_collected_interfaces']) v8_types.set_component_dirs(interfaces_info['component_dirs'])
def set_global_type_info(info_provider): interfaces_info = info_provider.interfaces_info idl_types.set_ancestors(interfaces_info['ancestors']) IdlType.set_callback_interfaces(interfaces_info['callback_interfaces']) IdlType.set_dictionaries(interfaces_info['dictionaries']) IdlType.set_enums(info_provider.enumerations) IdlType.set_implemented_as_interfaces(interfaces_info['implemented_as_interfaces']) IdlType.set_garbage_collected_types(interfaces_info['garbage_collected_interfaces']) v8_types.set_component_dirs(interfaces_info['component_dirs'])
def generate_code(self, definitions, definition_name): """Returns .h/.cpp code as ((path, content)...).""" # Set local type info IdlType.set_callback_functions(definitions.callback_functions.keys()) IdlType.set_enums((enum.name, enum.values) for enum in definitions.enumerations.values()) # Resolve typedefs definitions.resolve_typedefs(self.info_provider.component_info['typedefs']) return self.generate_code_internal(definitions, definition_name)
def generate_code(self, definitions, definition_name): """Returns .h/.cpp code as ((path, content)...).""" # Set local type info if not should_generate_code(definitions): return set() IdlType.set_callback_functions(definitions.callback_functions.keys()) # Resolve typedefs self.typedef_resolver.resolve(definitions, definition_name) return self.generate_code_internal(definitions, definition_name)
def preprocess_idl_type(idl_type): if idl_type.is_nullable: return IdlNullableType(idl_type.inner_type.preprocessed_type) if idl_type.is_enum: # Enumerations are internally DOMStrings return IdlType('DOMString') if idl_type.base_type in ['any', 'object' ] or idl_type.is_callback_function: return IdlType('ScriptValue') return idl_type
def set_global_type_info(info_provider): interfaces_info = info_provider.interfaces_info idl_types.set_ancestors(interfaces_info['ancestors']) IdlType.set_callback_interfaces(interfaces_info['callback_interfaces']) IdlType.set_dictionaries(interfaces_info['dictionaries']) IdlType.set_enums(info_provider.enumerations) IdlType.set_implemented_as_interfaces( interfaces_info['implemented_as_interfaces']) IdlType.set_garbage_collected_types( interfaces_info['garbage_collected_interfaces']) v8_types.set_component_dirs(interfaces_info['component_dirs'])
def set_global_type_info(interfaces_info): idl_types.set_ancestors(interfaces_info['ancestors']) IdlType.set_callback_interfaces(interfaces_info['callback_interfaces']) IdlType.set_dictionaries(interfaces_info['dictionaries']) IdlType.set_implemented_as_interfaces( interfaces_info['implemented_as_interfaces']) IdlType.set_garbage_collected_types( interfaces_info['garbage_collected_interfaces']) IdlType.set_will_be_garbage_collected_types( interfaces_info['will_be_garbage_collected_interfaces']) v8_types.set_component_dirs(interfaces_info['component_dirs'])
def preprocess_idl_type(idl_type): extended_attributes = idl_type.extended_attributes if idl_type.is_nullable: return IdlNullableType(idl_type.inner_type.preprocessed_type) if idl_type.is_enum: # Enumerations are internally DOMStrings return IdlType('DOMString', extended_attributes) if idl_type.base_type in ['any', 'object'] or idl_type.is_custom_callback_function: return IdlType('ScriptValue', extended_attributes) if idl_type.is_callback_function: return idl_type return idl_type
def preprocess_idl_type_and_value(idl_type, cpp_value, extended_attributes): """Returns IDL type and value, with preliminary type conversions applied.""" idl_type = idl_type.preprocessed_type if idl_type.name == 'Promise': idl_type = IdlType('ScriptValue') if idl_type.base_type in ['long long', 'unsigned long long']: # long long and unsigned long long are not representable in ECMAScript; # we represent them as doubles. is_nullable = idl_type.is_nullable idl_type = IdlType('double') if is_nullable: idl_type = IdlNullableType(idl_type) cpp_value = 'static_cast<double>(%s)' % cpp_value return idl_type, cpp_value
def __init__(self, interfaces_info, cache_dir, output_dir): interfaces_info = interfaces_info or {} self.interfaces_info = interfaces_info self.jinja_env = initialize_jinja_env(cache_dir) self.output_dir = output_dir # Set global type info idl_types.set_ancestors(interfaces_info['ancestors']) IdlType.set_callback_interfaces(interfaces_info['callback_interfaces']) IdlType.set_dictionaries(interfaces_info['dictionaries']) IdlType.set_implemented_as_interfaces(interfaces_info['implemented_as_interfaces']) IdlType.set_garbage_collected_types(interfaces_info['garbage_collected_interfaces']) IdlType.set_will_be_garbage_collected_types(interfaces_info['will_be_garbage_collected_interfaces']) v8_types.set_component_dirs(interfaces_info['component_dirs'])
def __init__(self, interfaces_info, cache_dir): interfaces_info = interfaces_info or {} self.interfaces_info = interfaces_info self.jinja_env = initialize_jinja_env(cache_dir) # Set global type info idl_types.set_ancestors( dict((interface_name, interface_info['ancestors']) for interface_name, interface_info in interfaces_info.iteritems() if interface_info['ancestors'])) IdlType.set_callback_interfaces( set(interface_name for interface_name, interface_info in interfaces_info.iteritems() if interface_info['is_callback_interface'])) IdlType.set_implemented_as_interfaces( dict((interface_name, interface_info['implemented_as']) for interface_name, interface_info in interfaces_info.iteritems() if interface_info['implemented_as'])) IdlType.set_garbage_collected_types( set(interface_name for interface_name, interface_info in interfaces_info.iteritems() if 'GarbageCollected' in interface_info['inherited_extended_attributes'])) IdlType.set_will_be_garbage_collected_types( set(interface_name for interface_name, interface_info in interfaces_info.iteritems() if 'WillBeGarbageCollected' in interface_info['inherited_extended_attributes'])) v8_types.set_component_dirs( dict((interface_name, interface_info['component_dir']) for interface_name, interface_info in interfaces_info.iteritems()))
def generate_code(self, definitions, interface_name): """Returns .h/.cpp code as (header_text, cpp_text).""" try: interface = definitions.interfaces[interface_name] except KeyError: raise Exception('%s not in IDL definitions' % interface_name) # Store other interfaces for introspection interfaces.update(definitions.interfaces) # Set local type info IdlType.set_callback_functions(definitions.callback_functions.keys()) IdlType.set_enums((enum.name, enum.values) for enum in definitions.enumerations.values()) # Select appropriate Jinja template and contents function if interface.is_callback: header_template_filename = 'callback_interface.h' cpp_template_filename = 'callback_interface.cpp' interface_context = v8_callback_interface.callback_interface_context elif 'PrivateScriptInterface' in interface.extended_attributes: # Currently private scripts don't have dependencies. Once private scripts have dependencies, # we should add them to interface_info. header_template_filename = 'private_script_interface.h' cpp_template_filename = 'private_script_interface.cpp' interface_context = v8_private_script_interface.private_script_interface_context else: header_template_filename = 'interface.h' cpp_template_filename = 'interface.cpp' interface_context = v8_interface.interface_context header_template = self.jinja_env.get_template(header_template_filename) cpp_template = self.jinja_env.get_template(cpp_template_filename) # Compute context (input values for Jinja) template_context = interface_context(interface) template_context['code_generator'] = module_pyname # Add includes for interface itself and any dependencies interface_info = self.interfaces_info[interface_name] if 'PrivateScriptInterface' not in interface.extended_attributes: template_context['header_includes'].add(interface_info['include_path']) template_context['header_includes'] = sorted(template_context['header_includes']) includes.update(interface_info.get('dependencies_include_paths', [])) template_context['cpp_includes'] = sorted(includes) # Render Jinja templates header_text = header_template.render(template_context) cpp_text = cpp_template.render(template_context) return header_text, cpp_text
def __init__(self, node): # Exceptions are similar to Interfaces, but simpler IdlInterface.__init__(self) self.is_callback = False self.is_exception = True self.is_partial = False self.name = node.GetName() self.idl_type = IdlType(self.name) children = node.GetChildren() for child in children: child_class = child.GetClass() if child_class == 'Attribute': attribute = IdlAttribute(child) self.attributes.append(attribute) elif child_class == 'Const': self.constants.append(IdlConstant(child)) elif child_class == 'ExtAttributes': extended_attributes = ext_attributes_node_to_extended_attributes( child) self.constructors, self.custom_constructors = ( extended_attributes_to_constructors(extended_attributes)) clear_constructor_attributes(extended_attributes) self.extended_attributes = extended_attributes elif child_class == 'ExceptionOperation': self.operations.append( IdlOperation.from_exception_operation_node(child)) else: raise ValueError('Unrecognized node class: %s' % child_class)
def generate_interface_code(self, definitions, interface_name, interface): interface_info = self.info_provider.interfaces_info[interface_name] full_path = interface_info.get('full_path') component = idl_filename_to_component(full_path) include_paths = interface_info.get('dependencies_include_paths') # Select appropriate Jinja template and contents function if interface.is_callback: header_template_filename = 'callback_interface.h.tmpl' cpp_template_filename = 'callback_interface.cc.tmpl' interface_context = v8_callback_interface.callback_interface_context elif interface.is_partial: interface_context = v8_interface.interface_context header_template_filename = 'partial_interface.h.tmpl' cpp_template_filename = 'partial_interface.cc.tmpl' interface_name += 'Partial' assert component == 'core' component = 'modules' include_paths = interface_info.get( 'dependencies_other_component_include_paths') else: header_template_filename = 'interface.h.tmpl' cpp_template_filename = 'interface.cc.tmpl' interface_context = v8_interface.interface_context template_context = interface_context(interface, definitions.interfaces) includes.update( interface_info.get('cpp_includes', {}).get(component, set())) if not interface.is_partial and not is_testing_target(full_path): template_context['header_includes'].add( self.info_provider.include_path_for_export) template_context[ 'exported'] = self.info_provider.specifier_for_export # Add the include for interface itself if IdlType(interface_name).is_typed_array: template_context['header_includes'].add( 'core/typed_arrays/dom_typed_array.h') elif interface.is_callback: pass else: template_context['header_includes'].add( interface_info['include_path']) template_context['header_includes'].update( interface_info.get('additional_header_includes', [])) header_path, cpp_path = self.output_paths(interface_name) this_include_header_path = self.normalize_this_header_path(header_path) template_context['this_include_header_path'] = this_include_header_path template_context['header_guard'] = to_header_guard( this_include_header_path) header_template = self.jinja_env.get_template(header_template_filename) cpp_template = self.jinja_env.get_template(cpp_template_filename) header_text, cpp_text = self.render_templates(include_paths, header_template, cpp_template, template_context, component) return ( (header_path, header_text), (cpp_path, cpp_text), )
def generate_code(self, definitions, definition_name): """Returns .h/.cpp code as (header_text, cpp_text).""" # Set local type info IdlType.set_callback_functions(definitions.callback_functions.keys()) IdlType.set_enums((enum.name, enum.values) for enum in definitions.enumerations.values()) if definition_name in definitions.interfaces: return self.generate_interface_code( definitions, definition_name, definitions.interfaces[definition_name]) if definition_name in definitions.dictionaries: return self.generate_dictionary_code( definitions, definition_name, definitions.dictionaries[definition_name]) raise ValueError('%s is not in IDL definitions' % definition_name)
def dictionary_context(dictionary, interfaces_info): includes.clear() includes.update(DICTIONARY_CPP_INCLUDES) cpp_class = v8_utilities.cpp_name(dictionary) context = { 'cpp_class': cpp_class, 'header_includes': set(DICTIONARY_H_INCLUDES), 'members': [ member_context(dictionary, member) for member in sorted(dictionary.members, key=operator.attrgetter('name')) ], 'use_permissive_dictionary_conversion': 'PermissiveDictionaryConversion' in dictionary.extended_attributes, 'v8_class': v8_types.v8_type(cpp_class), 'v8_original_class': v8_types.v8_type(dictionary.name), } if dictionary.parent: IdlType(dictionary.parent).add_includes_for_type() parent_cpp_class = v8_utilities.cpp_name_from_interfaces_info( dictionary.parent, interfaces_info) context.update({ 'parent_cpp_class': parent_cpp_class, 'parent_v8_class': v8_types.v8_type(parent_cpp_class), }) return context
def __init__(self, idl_name, node=None): self.attributes = [] self.constants = [] self.constructors = [] self.custom_constructors = [] self.extended_attributes = {} self.operations = [] self.parent = None self.stringifier = None self.iterable = None self.maplike = None self.setlike = None self.original_interface = None self.partial_interfaces = [] if not node: # Early exit for IdlException.__init__ return self.is_callback = bool(node.GetProperty('CALLBACK')) self.is_exception = False # FIXME: uppercase 'Partial' => 'PARTIAL' in base IDL parser self.is_partial = bool(node.GetProperty('Partial')) self.idl_name = idl_name self.name = node.GetName() self.idl_type = IdlType(self.name) children = node.GetChildren() for child in children: child_class = child.GetClass() if child_class == 'Attribute': self.attributes.append(IdlAttribute(idl_name, child)) elif child_class == 'Const': self.constants.append(IdlConstant(idl_name, child)) elif child_class == 'ExtAttributes': extended_attributes = ext_attributes_node_to_extended_attributes( idl_name, child) self.constructors, self.custom_constructors = ( extended_attributes_to_constructors( idl_name, extended_attributes)) clear_constructor_attributes(extended_attributes) self.extended_attributes = extended_attributes elif child_class == 'Operation': self.operations.append(IdlOperation(idl_name, child)) elif child_class == 'Inherit': self.parent = child.GetName() elif child_class == 'Stringifier': self.stringifier = IdlStringifier(idl_name, child) self.process_stringifier() elif child_class == 'Iterable': self.iterable = IdlIterable(idl_name, child) elif child_class == 'Maplike': self.maplike = IdlMaplike(idl_name, child) elif child_class == 'Setlike': self.setlike = IdlSetlike(idl_name, child) else: raise ValueError('Unrecognized node class: %s' % child_class) if len(filter(None, [self.iterable, self.maplike, self.setlike])) > 1: raise ValueError( 'Interface can only have one of iterable<>, maplike<> and setlike<>.' )
def type_node_inner_to_type(node): node_class = node.GetClass() # Note Type*r*ef, not Typedef, meaning the type is an identifier, thus # either a typedef shorthand (but not a Typedef declaration itself) or an # interface type. We do not distinguish these, and just use the type name. if node_class in ['PrimitiveType', 'Typeref']: # unrestricted syntax: unrestricted double | unrestricted float is_unrestricted = node.GetProperty('UNRESTRICTED') or False return IdlType(node.GetName(), is_unrestricted=is_unrestricted) elif node_class == 'Any': return IdlType('any') elif node_class == 'Sequence': return sequence_node_to_type(node) elif node_class == 'UnionType': return union_type_node_to_idl_union_type(node) raise ValueError('Unrecognized node class: %s' % node_class)
def generate_interface_code(self, definitions, interface_name, interface): interface_info = self.info_provider.interfaces_info[interface_name] full_path = interface_info.get('full_path') component = idl_filename_to_component(full_path) include_paths = interface_info.get('dependencies_include_paths') # Select appropriate Jinja template and contents function # # A callback interface with constants needs a special handling. # https://heycam.github.io/webidl/#legacy-callback-interface-object if interface.is_callback and len(interface.constants) > 0: header_template_filename = 'legacy_callback_interface.h.tmpl' cpp_template_filename = 'legacy_callback_interface.cpp.tmpl' interface_context = v8_callback_interface.legacy_callback_interface_context elif interface.is_callback: header_template_filename = 'callback_interface.h.tmpl' cpp_template_filename = 'callback_interface.cpp.tmpl' interface_context = v8_callback_interface.callback_interface_context elif interface.is_partial: interface_context = v8_interface.interface_context header_template_filename = 'partial_interface.h.tmpl' cpp_template_filename = 'partial_interface.cpp.tmpl' interface_name += 'Partial' assert component == 'core' component = 'modules' include_paths = interface_info.get('dependencies_other_component_include_paths') else: header_template_filename = 'interface.h.tmpl' cpp_template_filename = 'interface.cpp.tmpl' interface_context = v8_interface.interface_context template_context = interface_context(interface, definitions.interfaces) includes.update(interface_info.get('cpp_includes', {}).get(component, set())) if not interface.is_partial and not is_testing_target(full_path): template_context['header_includes'].add(self.info_provider.include_path_for_export) template_context['exported'] = self.info_provider.specifier_for_export # Add the include for interface itself if IdlType(interface_name).is_typed_array: template_context['header_includes'].add('core/typed_arrays/dom_typed_array.h') elif interface.is_callback: if len(interface.constants) > 0: # legacy callback interface includes.add(interface_info['include_path']) else: template_context['header_includes'].add(interface_info['include_path']) template_context['header_includes'].update( interface_info.get('additional_header_includes', [])) header_path, cpp_path = self.output_paths(interface_name) template_context['this_include_header_name'] = posixpath.basename(header_path) header_template = self.jinja_env.get_template(header_template_filename) cpp_template = self.jinja_env.get_template(cpp_template_filename) header_text, cpp_text = self.render_template( include_paths, header_template, cpp_template, template_context, component) return ( (header_path, header_text), (cpp_path, cpp_text), )
def generate_code(self, definitions, interface_name): """Returns .h/.cpp code as (header_text, cpp_text).""" try: interface = definitions.interfaces[interface_name] except KeyError: raise Exception('%s not in IDL definitions' % interface_name) # Store other interfaces for introspection interfaces.update(definitions.interfaces) # Set local type info IdlType.set_callback_functions(definitions.callback_functions.keys()) IdlType.set_enums((enum.name, enum.values) for enum in definitions.enumerations.values()) # Select appropriate Jinja template and contents function if interface.is_callback: header_template_filename = 'callback_interface.h' cpp_template_filename = 'callback_interface.cpp' generate_contents = v8_callback_interface.generate_callback_interface else: header_template_filename = 'interface.h' cpp_template_filename = 'interface.cpp' generate_contents = v8_interface.generate_interface header_template = self.jinja_env.get_template(header_template_filename) cpp_template = self.jinja_env.get_template(cpp_template_filename) # Generate contents (input parameters for Jinja) template_contents = generate_contents(interface) template_contents['code_generator'] = module_pyname # Add includes for interface itself and any dependencies interface_info = self.interfaces_info[interface_name] template_contents['header_includes'].add( interface_info['include_path']) template_contents['header_includes'] = sorted( template_contents['header_includes']) includes.update(interface_info.get('dependencies_include_paths', [])) template_contents['cpp_includes'] = sorted(includes) # Render Jinja templates header_text = header_template.render(template_contents) cpp_text = cpp_template.render(template_contents) return header_text, cpp_text
def dictionary_context(dictionary, interfaces_info): includes.clear() includes.update(DICTIONARY_CPP_INCLUDES) if 'RuntimeEnabled' in dictionary.extended_attributes: raise Exception('Dictionary cannot be RuntimeEnabled: %s' % dictionary.name) members = [ member_context(dictionary, member) for member in sorted(dictionary.members, key=operator.attrgetter('name')) ] for member in members: if member['runtime_enabled_feature_name']: includes.add('platform/runtime_enabled_features.h') break has_origin_trial_members = False for member in members: if member['origin_trial_feature_name']: has_origin_trial_members = True includes.add('core/origin_trials/origin_trials.h') break cpp_class = v8_utilities.cpp_name(dictionary) context = { 'cpp_class': cpp_class, 'has_origin_trial_members': has_origin_trial_members, 'header_includes': set(DICTIONARY_H_INCLUDES), 'members': members, 'required_member_names': sorted([ member.name for member in dictionary.members if member.is_required ]), 'use_permissive_dictionary_conversion': 'PermissiveDictionaryConversion' in dictionary.extended_attributes, 'v8_class': v8_types.v8_type(cpp_class), 'v8_original_class': v8_types.v8_type(dictionary.name), } if dictionary.parent: IdlType(dictionary.parent).add_includes_for_type() parent_cpp_class = v8_utilities.cpp_name_from_interfaces_info( dictionary.parent, interfaces_info) context.update({ 'parent_cpp_class': parent_cpp_class, 'parent_v8_class': v8_types.v8_type(parent_cpp_class), }) return context
def preprocess_idl_type_and_value(idl_type, cpp_value, extended_attributes): """Returns IDL type and value, with preliminary type conversions applied.""" idl_type = idl_type.preprocessed_type if idl_type.name == 'Promise': idl_type = IdlType('ScriptPromise') # FIXME(vsm): V8 maps 'long long' and 'unsigned long long' to double # as they are not representable in ECMAScript. Should we do the same? return idl_type, cpp_value
def resolve_typedefs(self, typedefs): # Resolve typedefs with the actual types. # http://www.w3.org/TR/WebIDL/#idl-typedefs typedefs.update( dict((typedef_name, IdlType(type_name)) for typedef_name, type_name in STANDARD_TYPEDEFS.iteritems())) for callback_function in self.callback_functions.itervalues(): callback_function.resolve_typedefs(typedefs) for interface in self.interfaces.itervalues(): interface.resolve_typedefs(typedefs)
def generate_code(self, definitions, interface_name): """Returns .h/.cpp code as (header_text, cpp_text).""" try: interface = definitions.interfaces[interface_name] except KeyError: raise Exception('%s not in IDL definitions' % interface_name) # Store other interfaces for introspection interfaces.update(definitions.interfaces) # Set local type info IdlType.set_callback_functions(definitions.callback_functions.keys()) IdlType.set_enums((enum.name, enum.values) for enum in definitions.enumerations.values()) # Select appropriate Jinja template and contents function if interface.is_callback: header_template_filename = 'callback_interface.h' cpp_template_filename = 'callback_interface.cpp' generate_contents = v8_callback_interface.generate_callback_interface else: header_template_filename = 'interface.h' cpp_template_filename = 'interface.cpp' generate_contents = v8_interface.generate_interface header_template = self.jinja_env.get_template(header_template_filename) cpp_template = self.jinja_env.get_template(cpp_template_filename) # Generate contents (input parameters for Jinja) template_contents = generate_contents(interface) template_contents['code_generator'] = module_pyname # Add includes for interface itself and any dependencies interface_info = self.interfaces_info[interface_name] template_contents['header_includes'].add(interface_info['include_path']) template_contents['header_includes'] = sorted(template_contents['header_includes']) includes.update(interface_info.get('dependencies_include_paths', [])) template_contents['cpp_includes'] = sorted(includes) # Render Jinja templates header_text = header_template.render(template_contents) cpp_text = cpp_template.render(template_contents) return header_text, cpp_text
def test_resolve_typedefs(self): # This is a simplification of the typedef mechanism to avoid having to # use idl_definitions and use actual nodes from //tools/idl_parser. typedefs = { 'Foo': IdlType('unsigned short'), 'MyBooleanType': IdlType('boolean'), 'SomeInterfaceT': IdlType('MyInterface'), } # (long long or MyBooleanType) union = IdlUnionType([IdlType('long long'), IdlType('MyBooleanType') ]).resolve_typedefs(typedefs) self.assertEqual(union.name, 'LongLongOrBoolean') self.assertEqual(union.member_types[0].name, 'LongLong') self.assertEqual(union.member_types[1].name, 'Boolean') # (Foo or SomeInterfaceT) union = IdlUnionType([IdlType('Foo'), IdlType('SomeInterfaceT') ]).resolve_typedefs(typedefs) self.assertEqual(union.name, 'UnsignedShortOrMyInterface') self.assertEqual(union.member_types[0].name, 'UnsignedShort') self.assertEqual(union.member_types[1].name, 'MyInterface') # (Foo or sequence<(MyBooleanType or double)>) union = IdlUnionType([ IdlType('Foo'), IdlSequenceType( IdlUnionType([IdlType('MyBooleanType'), IdlType('double')])) ]).resolve_typedefs(typedefs) self.assertEqual(union.name, 'UnsignedShortOrBooleanOrDoubleSequence') self.assertEqual(union.member_types[0].name, 'UnsignedShort') self.assertEqual(union.member_types[1].name, 'BooleanOrDoubleSequence') self.assertEqual(union.member_types[1].element_type.name, 'BooleanOrDouble') self.assertEqual( union.member_types[1].element_type.member_types[0].name, 'Boolean') self.assertEqual( union.member_types[1].element_type.member_types[1].name, 'Double') self.assertEqual(2, len(union.flattened_member_types))
def preprocess_idl_type_and_value(idl_type, cpp_value, extended_attributes): """Returns IDL type and value, with preliminary type conversions applied.""" idl_type = idl_type.preprocessed_type if idl_type.name == 'Promise': idl_type = IdlType('ScriptValue') if idl_type.base_type in ['long long', 'unsigned long long']: # long long and unsigned long long are not representable in ECMAScript; # we represent them as doubles. idl_type = IdlType('double', is_nullable=idl_type.is_nullable) cpp_value = 'static_cast<double>(%s)' % cpp_value # HTML5 says that unsigned reflected attributes should be in the range # [0, 2^31). When a value isn't in this range, a default value (or 0) # should be returned instead. extended_attributes = extended_attributes or {} if ('Reflect' in extended_attributes and idl_type.base_type in ['unsigned long', 'unsigned short']): cpp_value = cpp_value.replace('getUnsignedIntegralAttribute', 'getIntegralAttribute') cpp_value = 'std::max(0, %s)' % cpp_value return idl_type, cpp_value
def record_node_to_type(node): children = node.GetChildren() if len(children) != 2: raise ValueError('record<K,V> node expects exactly 2 children, got %d' % (len(children))) key_child = children[0] value_child = children[1] if key_child.GetClass() != 'StringType': raise ValueError('Keys in record<K,V> nodes must be string types.') if value_child.GetClass() != 'Type': raise ValueError('Unrecognized node class for record<K,V> value: %s' % value_child.GetClass()) return IdlRecordType(IdlType(key_child.GetName()), type_node_to_type(value_child))
def sequence_node_to_type(node, is_nullable=False): children = node.GetChildren() if len(children) != 1: raise ValueError('Sequence node expects exactly 1 child, got %s' % len(children)) sequence_child = children[0] sequence_child_class = sequence_child.GetClass() if sequence_child_class != 'Type': raise ValueError('Unrecognized node class: %s' % sequence_child_class) element_type = type_node_to_type(sequence_child).base_type return IdlType(element_type, is_sequence=True, is_nullable=is_nullable)
def __init__(self, interfaces_info, cache_dir): interfaces_info = interfaces_info or {} self.interfaces_info = interfaces_info self.jinja_env = initialize_jinja_env(cache_dir) # Set global type info idl_types.set_ancestors(dict( (interface_name, interface_info['ancestors']) for interface_name, interface_info in interfaces_info.iteritems() if interface_info['ancestors'])) IdlType.set_callback_interfaces(set( interface_name for interface_name, interface_info in interfaces_info.iteritems() if interface_info['is_callback_interface'])) IdlType.set_implemented_as_interfaces(dict( (interface_name, interface_info['implemented_as']) for interface_name, interface_info in interfaces_info.iteritems() if interface_info['implemented_as'])) dart_types.set_component_dirs(dict( (interface_name, interface_info['component_dir']) for interface_name, interface_info in interfaces_info.iteritems()))
def generate_code(self, module_definitions): definitions = module_definitions['dom'] # Note: callback functions aren't visible out side defined IDL. IdlType.set_callback_interfaces(definitions.callback_functions) global global_definitions global_definitions = definitions return list( chain(*[ self.generate_cc_h(context) for context in [ dictionary_context(dictionary) for dictionary in definitions.dictionaries.values() ] + # interface context must be generated after dictionary context # for include files. [ build_interface_context(interface) for interface in definitions.interfaces.values() ] ]))
def __init__(self, interfaces_info, cache_dir, output_dir): interfaces_info = interfaces_info or {} self.interfaces_info = interfaces_info self.jinja_env = initialize_jinja_env(cache_dir) self.output_dir = output_dir # Set global type info idl_types.set_ancestors(dict( (interface_name, interface_info['ancestors']) for interface_name, interface_info in interfaces_info.iteritems() if interface_info['ancestors'])) IdlType.set_callback_interfaces(set( interface_name for interface_name, interface_info in interfaces_info.iteritems() if interface_info['is_callback_interface'])) IdlType.set_dictionaries(set( dictionary_name for dictionary_name, interface_info in interfaces_info.iteritems() if interface_info['is_dictionary'])) IdlType.set_implemented_as_interfaces(dict( (interface_name, interface_info['implemented_as']) for interface_name, interface_info in interfaces_info.iteritems() if interface_info['implemented_as'])) v8_types.set_component_dirs(dict( (interface_name, interface_info['component_dir']) for interface_name, interface_info in interfaces_info.iteritems()))
def test_is_record(self): idl_type = IdlType('USVString') self.assertFalse(idl_type.is_record_type) idl_type = IdlSequenceType( IdlRecordType(IdlType('DOMString'), IdlType('byte'))) self.assertFalse(idl_type.is_record_type) idl_type = IdlRecordType(IdlType('USVString'), IdlType('long')) self.assertTrue(idl_type.is_record_type) idl_type = IdlRecordType(IdlType('USVString'), IdlSequenceType(IdlType('boolean'))) self.assertTrue(idl_type.is_record_type)
def test_name(self): idl_type = IdlRecordType(IdlType('ByteString'), IdlType('octet')) self.assertEqual(idl_type.name, 'ByteStringOctetRecord') idl_type = IdlRecordType(IdlType('USVString'), IdlSequenceType(IdlType('double'))) self.assertEqual(idl_type.name, 'USVStringDoubleSequenceRecord') idl_type = IdlRecordType( IdlType('DOMString'), IdlRecordType(IdlType('ByteString'), IdlSequenceType(IdlType('unsigned short')))) self.assertEqual(idl_type.name, 'StringByteStringUnsignedShortSequenceRecordRecord')
def generate_interface_code(self, definitions, interface_name, interface): # Store other interfaces for introspection interfaces.update(definitions.interfaces) interface_info = self.info_provider.interfaces_info[interface_name] full_path = interface_info.get('full_path') component = idl_filename_to_component(full_path) include_paths = interface_info.get('dependencies_include_paths') # Select appropriate Jinja template and contents function if interface.is_callback: header_template_filename = 'callback_interface.h' cpp_template_filename = 'callback_interface.cpp' interface_context = v8_callback_interface.callback_interface_context elif interface.is_partial: interface_context = v8_interface.interface_context header_template_filename = 'partial_interface.h' cpp_template_filename = 'partial_interface.cpp' interface_name += 'Partial' assert component == 'core' component = 'modules' include_paths = interface_info.get( 'dependencies_other_component_include_paths') else: header_template_filename = 'interface.h' cpp_template_filename = 'interface.cpp' interface_context = v8_interface.interface_context header_template = self.jinja_env.get_template(header_template_filename) cpp_template = self.jinja_env.get_template(cpp_template_filename) template_context = interface_context(interface) if not interface.is_partial and not is_testing_target(full_path): template_context['header_includes'].add( self.info_provider.include_path_for_export) template_context[ 'exported'] = self.info_provider.specifier_for_export # Add the include for interface itself if IdlType(interface_name).is_typed_array: template_context['header_includes'].add('core/dom/DOMTypedArray.h') elif interface_info['include_path']: template_context['header_includes'].add( interface_info['include_path']) header_text, cpp_text = render_template(include_paths, header_template, cpp_template, template_context, component) header_path, cpp_path = self.output_paths(interface_name) return ( (header_path, header_text), (cpp_path, cpp_text), )
def __init__(self, idl_name, node): """Args: node: AST root node, class == 'File'""" self.callback_functions = {} self.dictionaries = {} self.enumerations = {} self.interfaces = {} self.idl_name = idl_name node_class = node.GetClass() if node_class != 'File': raise ValueError('Unrecognized node class: %s' % node_class) typedefs = dict( (typedef_name, IdlType(type_name)) for typedef_name, type_name in STANDARD_TYPEDEFS.iteritems()) children = node.GetChildren() for child in children: child_class = child.GetClass() if child_class == 'Interface': interface = IdlInterface(idl_name, child) self.interfaces[interface.name] = interface elif child_class == 'Exception': exception = IdlException(idl_name, child) # For simplicity, treat exceptions as interfaces self.interfaces[exception.name] = exception elif child_class == 'Typedef': type_name = child.GetName() typedefs[type_name] = typedef_node_to_type(child) elif child_class == 'Enum': enumeration = IdlEnum(idl_name, child) self.enumerations[enumeration.name] = enumeration elif child_class == 'Callback': callback_function = IdlCallbackFunction(idl_name, child) self.callback_functions[ callback_function.name] = callback_function elif child_class == 'Implements': # Implements is handled at the interface merging step pass elif child_class == 'Dictionary': dictionary = IdlDictionary(idl_name, child) self.dictionaries[dictionary.name] = dictionary else: raise ValueError('Unrecognized node class: %s' % child_class) # Typedefs are not stored in IR: # Resolve typedefs with the actual types and then discard the Typedefs. # http://www.w3.org/TR/WebIDL/#idl-typedefs self.resolve_typedefs(typedefs)
def type_node_inner_to_type(node, is_array=False, is_nullable=False): # FIXME: remove is_array and is_nullable once have IdlArrayType and IdlNullableType node_class = node.GetClass() # Note Type*r*ef, not Typedef, meaning the type is an identifier, thus # either a typedef shorthand (but not a Typedef declaration itself) or an # interface type. We do not distinguish these, and just use the type name. if node_class in ['PrimitiveType', 'Typeref']: # unrestricted syntax: unrestricted double | unrestricted float is_unrestricted = node.GetProperty('UNRESTRICTED') or False return IdlType(node.GetName(), is_array=is_array, is_nullable=is_nullable, is_unrestricted=is_unrestricted) elif node_class == 'Any': return IdlType('any', is_array=is_array, is_nullable=is_nullable) elif node_class == 'Sequence': if is_array: raise ValueError('Arrays of sequences are not supported') return sequence_node_to_type(node, is_nullable=is_nullable) elif node_class == 'UnionType': if is_array: raise ValueError('Arrays of unions are not supported') return union_type_node_to_idl_union_type(node, is_nullable=is_nullable) raise ValueError('Unrecognized node class: %s' % node_class)
def test_add_method(self): helper = IdlTestingHelper() builder = InterfaceContextBuilder( 'test', TypeResolver( helper.make_stub_interfaces_info({ 'foo': 'path_to_foo', 'bar': 'path_to_bar', 'garply': 'path_to_garply', }))) operation = helper.make_stub_idl_operation('foo', 'bar') builder.add_operation(operation) self.assertEqual( { 'code_generator': 'test', 'cpp_includes': set(['path_to_bar']), 'methods': [{ 'arguments': [], 'name': 'Foo', 'type': 'bar' }], }, builder.build()) operation = helper.make_stub_idl_operation('quux', 'garply') operation.arguments = [ helper.make_stub_idl_argument('barBaz', IdlType('qux')) ] builder.add_operation(operation) self.assertEqual( { 'code_generator': 'test', 'cpp_includes': set(['path_to_bar', 'path_to_garply']), 'methods': [{ 'arguments': [], 'name': 'Foo', 'type': 'bar' }, { 'arguments': [{ 'name': 'bar_baz', 'type': 'qux' }], 'name': 'Quux', 'type': 'garply' }], }, builder.build())
def __init__(self, interfaces_info, cache_dir): interfaces_info = interfaces_info or {} self.interfaces_info = interfaces_info self.jinja_env = initialize_jinja_env(cache_dir) # Set global type info idl_types.set_ancestors(dict( (interface_name, interface_info['ancestors']) for interface_name, interface_info in interfaces_info.iteritems() if interface_info['ancestors'])) IdlType.set_callback_interfaces(set( interface_name for interface_name, interface_info in interfaces_info.iteritems() if interface_info['is_callback_interface'])) IdlType.set_implemented_as_interfaces(dict( (interface_name, interface_info['implemented_as']) for interface_name, interface_info in interfaces_info.iteritems() if interface_info['implemented_as'])) IdlType.set_garbage_collected_types(set( interface_name for interface_name, interface_info in interfaces_info.iteritems() if 'GarbageCollected' in interface_info['inherited_extended_attributes']))
def generate_code(self, definitions, interface_name, idl_pickle_filename, only_if_changed): """Returns .h/.cpp code as (header_text, cpp_text).""" try: interface = definitions.interfaces[interface_name] except KeyError: raise Exception('%s not in IDL definitions' % interface_name) # Store other interfaces for introspection interfaces.update(definitions.interfaces) # Set local type info IdlType.set_callback_functions(definitions.callback_functions.keys()) IdlType.set_enums((enum.name, enum.values) for enum in definitions.enumerations.values()) # Select appropriate Jinja template and contents function if interface.is_callback: header_template_filename = 'callback_interface_h.template' cpp_template_filename = 'callback_interface_cpp.template' generate_contents = dart_callback_interface.generate_callback_interface else: header_template_filename = 'interface_h.template' cpp_template_filename = 'interface_cpp.template' generate_contents = dart_interface.generate_interface header_template = self.jinja_env.get_template(header_template_filename) cpp_template = self.jinja_env.get_template(cpp_template_filename) # Generate contents (input parameters for Jinja) template_contents = generate_contents(interface) template_contents['code_generator'] = module_pyname # Add includes for interface itself and any dependencies interface_info = self.interfaces_info[interface_name] template_contents['header_includes'].add(interface_info['include_path']) template_contents['header_includes'] = sorted(template_contents['header_includes']) includes.update(interface_info.get('dependencies_include_paths', [])) # Remove includes that are not needed for Dart and trigger fatal # compile warnings if included. These IDL files need to be # imported by Dart to generate the list of events but the # associated header files do not contain any code used by Dart. includes.discard('core/dom/GlobalEventHandlers.h') includes.discard('core/frame/DOMWindowEventHandlers.h') template_contents['cpp_includes'] = sorted(includes) idl_world = {'interface': None, 'callback': None} # Load the pickle file for this IDL. if os.path.isfile(idl_pickle_filename): with open(idl_pickle_filename) as idl_pickle_file: idl_global_data = pickle.load(idl_pickle_file) idl_pickle_file.close() idl_world['interface'] = idl_global_data['interface'] idl_world['callback'] = idl_global_data['callback'] if 'interface_name' in template_contents: interface_global = {'name': template_contents['interface_name'], 'parent_interface': template_contents['parent_interface'], 'is_active_dom_object': template_contents['is_active_dom_object'], 'is_event_target': template_contents['is_event_target'], 'has_resolver': template_contents['interface_name'] not in INTERFACES_WITHOUT_RESOLVERS, 'is_node': template_contents['is_node'], 'conditional_string': template_contents['conditional_string'], } idl_world['interface'] = interface_global else: callback_global = {'name': template_contents['cpp_class']} idl_world['callback'] = callback_global write_pickle_file(idl_pickle_filename, idl_world, only_if_changed) # Render Jinja templates header_text = header_template.render(template_contents) cpp_text = cpp_template.render(template_contents) return header_text, cpp_text
def generate_code(self, definitions, interface_name, idl_filename, idl_pickle_filename, only_if_changed): """Returns .h/.cpp/.dart code as (header_text, cpp_text, dart_text).""" try: interface = definitions.interfaces[interface_name] except KeyError: raise Exception('%s not in IDL definitions' % interface_name) # Store other interfaces for introspection interfaces.update(definitions.interfaces) # Set local type info IdlType.set_callback_functions(definitions.callback_functions.keys()) IdlType.set_enums((enum.name, enum.values) for enum in definitions.enumerations.values()) # Select appropriate Jinja template and contents function if interface.is_callback: header_template_filename = 'callback_interface_h.template' cpp_template_filename = 'callback_interface_cpp.template' dart_template_filename = 'callback_interface_dart.template' generate_contents = dart_callback_interface.generate_callback_interface else: header_template_filename = 'interface_h.template' cpp_template_filename = 'interface_cpp.template' dart_template_filename = 'interface_dart.template' generate_contents = dart_interface.interface_context header_template = self.jinja_env.get_template(header_template_filename) cpp_template = self.jinja_env.get_template(cpp_template_filename) dart_template = self.jinja_env.get_template(dart_template_filename) # Generate contents (input parameters for Jinja) template_contents = generate_contents(interface) template_contents['code_generator'] = module_pyname # Add includes for interface itself and any dependencies interface_info = self.interfaces_info[interface_name] template_contents['header_includes'].add(interface_info['include_path']) template_contents['header_includes'] = sorted(template_contents['header_includes']) includes.update(interface_info.get('dependencies_include_paths', [])) template_contents['cpp_includes'] = sorted(includes) # If PrivateDart is set, read the custom dart file and add it to our # template parameters. if 'PrivateDart' in interface.extended_attributes: template_contents['private_dart'] = True idl_world = {'interface': None, 'callback': None} # Load the pickle file for this IDL. if os.path.isfile(idl_pickle_filename): with open(idl_pickle_filename) as idl_pickle_file: idl_global_data = pickle.load(idl_pickle_file) idl_pickle_file.close() idl_world['interface'] = idl_global_data['interface'] idl_world['callback'] = idl_global_data['callback'] if 'interface_name' in template_contents: interface_global = {'component_dir': interface_info['component_dir'], 'name': template_contents['interface_name'], 'parent_interface': template_contents['parent_interface'], 'is_active_dom_object': template_contents['is_active_dom_object'], 'has_resolver': template_contents['interface_name'], 'native_entries': sorted(template_contents['native_entries'], key=lambda(x): x['blink_entry']), } idl_world['interface'] = interface_global else: callback_global = {'name': template_contents['cpp_class']} idl_world['callback'] = callback_global write_pickle_file(idl_pickle_filename, idl_world, only_if_changed) # Render Jinja templates header_text = header_template.render(template_contents) cpp_text = cpp_template.render(template_contents) dart_text = dart_template.render(template_contents) return header_text, cpp_text, dart_text