| #!/usr/bin/python | |
| # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
| # for details. All rights reserved. Use of this source code is governed by a | |
| # BSD-style license that can be found in the LICENSE file. | |
| """This module generates Elemental APIs from the IDL database.""" | |
| import emitter | |
| import idlnode | |
| import logging | |
| import multiemitter | |
| import os | |
| import re | |
| import shutil | |
| from generator_java import * | |
| from systembaseelemental import * | |
| from systemgwt import * | |
| from systemgwtjso import * | |
| from templateloader import TemplateLoader | |
| _logger = logging.getLogger('elementalgenerator') | |
| def MergeNodes(node, other): | |
| node.operations.extend(other.operations) | |
| for attribute in other.attributes: | |
| if not node.has_attribute(attribute): | |
| node.attributes.append(attribute) | |
| node.constants.extend(other.constants) | |
| class ElementalGenerator(object): | |
| """Utilities to generate Elemental APIs and corresponding JavaScript.""" | |
| def __init__(self, auxiliary_dir, template_dir, base_package): | |
| """Constructor for the DartGenerator. | |
| Args: | |
| auxiliary_dir -- location of auxiliary handwritten classes | |
| template_dir -- location of template files | |
| base_package -- the base package name for the generated code. | |
| """ | |
| self._auxiliary_dir = auxiliary_dir | |
| self._template_dir = template_dir | |
| self._base_package = base_package | |
| self._auxiliary_files = {} | |
| self._dart_templates_re = re.compile(r'[\w.:]+<([\w\.<>:]+)>') | |
| self._emitters = None # set later | |
| def _StripModules(self, type_name): | |
| return type_name.split('::')[-1] | |
| def _IsCompoundType(self, database, type_name): | |
| if IsPrimitiveType(type_name): | |
| return True | |
| striped_type_name = self._StripModules(type_name) | |
| if database.HasInterface(striped_type_name): | |
| return True | |
| dart_template_match = self._dart_templates_re.match(type_name) | |
| if dart_template_match: | |
| # Dart templates | |
| parent_type_name = type_name[0 : dart_template_match.start(1) - 1] | |
| sub_type_name = dart_template_match.group(1) | |
| return (self._IsCompoundType(database, parent_type_name) and | |
| self._IsCompoundType(database, sub_type_name)) | |
| return False | |
| def _IsDartType(self, type_name): | |
| return '.' in type_name | |
| def LoadAuxiliary(self): | |
| def Visitor(_, dirname, names): | |
| for name in names: | |
| if name.endswith('.dart'): | |
| name = name[0:-5] # strip off ".dart" | |
| self._auxiliary_files[name] = os.path.join(dirname, name) | |
| os.path.walk(self._auxiliary_dir, Visitor, None) | |
| def RenameTypes(self, database, conversion_table, rename_javascript_binding_names): | |
| """Renames interfaces using the given conversion table. | |
| References through all interfaces will be renamed as well. | |
| Args: | |
| database: the database to apply the renames to. | |
| conversion_table: maps old names to new names. | |
| """ | |
| if conversion_table is None: | |
| conversion_table = {} | |
| # Rename interfaces: | |
| for old_name, new_name in conversion_table.items(): | |
| if database.HasInterface(old_name): | |
| _logger.info('renaming interface %s to %s' % (old_name, new_name)) | |
| interface = database.GetInterface(old_name) | |
| database.DeleteInterface(old_name) | |
| if not database.HasInterface(new_name): | |
| interface.id = new_name | |
| database.AddInterface(interface) | |
| else: | |
| new_interface = database.GetInterface(new_name) | |
| MergeNodes(new_interface, interface) | |
| if rename_javascript_binding_names: | |
| interface.javascript_binding_name = new_name | |
| interface.doc_js_name = new_name | |
| for member in (interface.operations + interface.constants | |
| + interface.attributes): | |
| member.doc_js_interface_name = new_name | |
| # Fix references: | |
| for interface in database.GetInterfaces(): | |
| for idl_type in interface.all(idlnode.IDLType): | |
| type_name = self._StripModules(idl_type.id) | |
| if type_name in conversion_table: | |
| idl_type.id = conversion_table[type_name] | |
| def FilterMembersWithUnidentifiedTypes(self, database): | |
| """Removes unidentified types. | |
| Removes constants, attributes, operations and parents with unidentified | |
| types. | |
| """ | |
| for interface in database.GetInterfaces(): | |
| def IsIdentified(idl_node): | |
| node_name = idl_node.id if idl_node.id else 'parent' | |
| for idl_type in idl_node.all(idlnode.IDLType): | |
| type_name = idl_type.id | |
| if (type_name is not None and | |
| self._IsCompoundType(database, type_name)): | |
| continue | |
| _logger.warn('removing %s in %s which has unidentified type %s' % | |
| (node_name, interface.id, type_name)) | |
| return False | |
| return True | |
| interface.constants = filter(IsIdentified, interface.constants) | |
| interface.attributes = filter(IsIdentified, interface.attributes) | |
| interface.operations = filter(IsIdentified, interface.operations) | |
| interface.parents = filter(IsIdentified, interface.parents) | |
| def FilterInterfaces(self, database, | |
| and_annotations=[], | |
| or_annotations=[], | |
| exclude_displaced=[], | |
| exclude_suppressed=[]): | |
| """Filters a database to remove interfaces and members that are missing | |
| annotations. | |
| The FremontCut IDLs use annotations to specify implementation | |
| status in various platforms. For example, if a member is annotated | |
| with @WebKit, this means that the member is supported by WebKit. | |
| Args: | |
| database -- the database to filter | |
| all_annotations -- a list of annotation names a member has to | |
| have or it will be filtered. | |
| or_annotations -- if a member has one of these annotations, it | |
| won't be filtered even if it is missing some of the | |
| all_annotations. | |
| exclude_displaced -- if a member has this annotation and it | |
| is marked as displaced it will always be filtered. | |
| exclude_suppressed -- if a member has this annotation and it | |
| is marked as suppressed it will always be filtered. | |
| """ | |
| # Filter interfaces and members whose annotations don't match. | |
| for interface in database.GetInterfaces(): | |
| def HasAnnotations(idl_node): | |
| """Utility for determining if an IDLNode has all | |
| the required annotations""" | |
| for a in exclude_displaced: | |
| if (a in idl_node.annotations | |
| and 'via' in idl_node.annotations[a]): | |
| return False | |
| for a in exclude_suppressed: | |
| if (a in idl_node.annotations | |
| and 'suppressed' in idl_node.annotations[a]): | |
| return False | |
| for a in or_annotations: | |
| if a in idl_node.annotations: | |
| return True | |
| if and_annotations == []: | |
| return False | |
| for a in and_annotations: | |
| if a not in idl_node.annotations: | |
| return False | |
| return True | |
| if HasAnnotations(interface): | |
| interface.constants = filter(HasAnnotations, interface.constants) | |
| interface.attributes = filter(HasAnnotations, interface.attributes) | |
| interface.operations = filter(HasAnnotations, interface.operations) | |
| interface.parents = filter(HasAnnotations, interface.parents) | |
| else: | |
| database.DeleteInterface(interface.id) | |
| self.FilterMembersWithUnidentifiedTypes(database) | |
| def Generate(self, database, output_dir, | |
| module_source_preference=[], source_filter=None, | |
| super_database=None, common_prefix=None, super_map={}, | |
| html_map={}, lib_dir=None, systems=[]): | |
| """Generates Dart and JS files for the loaded interfaces. | |
| Args: | |
| database -- database containing interfaces to generate code for. | |
| output_dir -- directory to write generated files to. | |
| module_source_preference -- priority order list of source annotations to | |
| use when choosing a module name, if none specified uses the module name | |
| from the database. | |
| source_filter -- if specified, only outputs interfaces that have one of | |
| these source annotation and rewrites the names of superclasses not | |
| marked with this source to use the common prefix. | |
| super_database -- database containing super interfaces that the generated | |
| interfaces should extend. | |
| common_prefix -- prefix for the common library, if any. | |
| lib_file_path -- filename for generated .lib file, None if not required. | |
| lib_template -- template file in this directory for generated lib file. | |
| """ | |
| self._emitters = multiemitter.MultiEmitter() | |
| self._database = database | |
| self._output_dir = output_dir | |
| self._FixEventTargets() | |
| self._ComputeInheritanceClosure() | |
| self._systems = [] | |
| # TODO(jmesserly): only create these if needed | |
| if ('gwtjso' in systems): | |
| jso_system = ElementalJsoSystem( | |
| TemplateLoader(self._template_dir, ['dom/jso', 'dom', '']), | |
| self._database, self._emitters, self._output_dir) | |
| self._systems.append(jso_system) | |
| if ('gwt' in systems): | |
| interface_system = ElementalInterfacesSystem( | |
| TemplateLoader(self._template_dir, ['dom/interface', 'dom', '']), | |
| self._database, self._emitters, self._output_dir) | |
| self._systems.append(interface_system) | |
| # if 'gwt' in systems: | |
| # elemental_system = ElementalSystem( | |
| # TemplateLoader(self._template_dir, ['dom/elemental', 'dom', '']), | |
| # self._database, self._emitters, self._output_dir) | |
| # elemental_system._interface_system = interface_system | |
| # self._systems.append(elemental_system) | |
| # Collect interfaces | |
| interfaces = [] | |
| for interface in database.GetInterfaces(): | |
| if not MatchSourceFilter(source_filter, interface): | |
| # Skip this interface since it's not present in the required source | |
| _logger.info('Omitting interface - %s' % interface.id) | |
| continue | |
| interfaces.append(interface) | |
| # TODO(sra): Use this list of exception names to generate information to | |
| # tell Frog which exceptions can be passed from JS to Dart code. | |
| exceptions = self._CollectExceptions(interfaces) | |
| mixins = self._ComputeMixins(self._PreOrderInterfaces(interfaces)) | |
| for system in self._systems: | |
| # give outputters a chance to see the mixin list before starting | |
| system.ProcessMixins(mixins) | |
| # copy all mixin methods from every interface to this base interface | |
| self.PopulateMixinBase(self._database.GetInterface('ElementalMixinBase'), mixins) | |
| # Render all interfaces into Dart and save them in files. | |
| for interface in self._PreOrderInterfaces(interfaces): | |
| super_interface = None | |
| super_name = interface.id | |
| if super_name in super_map: | |
| super_name = super_map[super_name] | |
| if (super_database is not None and | |
| super_database.HasInterface(super_name)): | |
| super_interface = super_name | |
| interface_name = interface.id | |
| auxiliary_file = self._auxiliary_files.get(interface_name) | |
| if auxiliary_file is not None: | |
| _logger.info('Skipping %s because %s exists' % ( | |
| interface_name, auxiliary_file)) | |
| continue | |
| info = RecognizeCallback(interface) | |
| if info: | |
| for system in self._systems: | |
| system.ProcessCallback(interface, info) | |
| else: | |
| if 'Callback' in interface.ext_attrs: | |
| _logger.info('Malformed callback: %s' % interface.id) | |
| self._ProcessInterface(interface, super_interface, | |
| source_filter, common_prefix) | |
| for system in self._systems: | |
| system.Finish() | |
| def PopulateMixinBase(self, mixinbase, mixins): | |
| """Copy all mixin attributes and operations to mixin base class""" | |
| for mixin_name in mixins: | |
| if self._database.HasInterface(mixin_name): | |
| mixin = self._database.GetInterface(mixin_name) | |
| mixinbase.attributes.extend(mixin.attributes) | |
| mixinbase.operations.extend(mixin.operations) | |
| for extattr in mixin.ext_attrs.keys(): | |
| mixinbase.ext_attrs[extattr] = mixin.ext_attrs[extattr] | |
| # compute all interfaces which are in disjoint type hierarchies | |
| # that is, cannot be SingleImplJSO without hoisting | |
| def _ComputeMixins(self, interfaces): | |
| implementors = {} | |
| mixins = {} | |
| parents = {} | |
| # first compute the set of all inherited super-interfaces of every interface | |
| for interface in interfaces: | |
| if interface.parents: | |
| # the first parent interface is the superclass | |
| parent = interface.parents[0] | |
| # if we haven't processed this one before | |
| if not interface.id in parents: | |
| # compute a list of all of the direct superclass this interface | |
| parents[interface.id] = [] | |
| parents[interface.id].append(parent) | |
| if parent.type.id in parents: | |
| # inherit all the super-interfaces | |
| parents[interface.id].extend(parents[parent.type.id]) | |
| implemented_by = None | |
| for interface in interfaces: | |
| # now, examining secondary interfaces | |
| for secondary in interface.parents[1:]: | |
| if secondary.type.id in implementors: | |
| implemented_by = implementors[secondary.type.id] | |
| # if the interface is implemented by someone else who is not one of my parents, it is not SingleJsoImpl | |
| if not implemented_by in parents[interface.id]: | |
| mixins[secondary.type.id]=implemented_by | |
| print "Mixin detected %s, previously implemented by %s, but also implemented by %s" % (secondary.type.id, implemented_by, interface.id) | |
| # add all parents of the mixin as well | |
| superparents = [] | |
| superiface = secondary.type.id | |
| if self._database.HasInterface(superiface): | |
| self.getParents(self._database.GetInterface(superiface), superparents) | |
| for parent in superparents: | |
| mixins[parent.id]=implemented_by | |
| print "Super Mixin detected %s, previously implemented by %s, but also implemented by %s" % (parent.id, implemented_by, interface.id) | |
| else: | |
| implementors[secondary.type.id] = interface.id | |
| # manual patch for outliers not picked up by this logic | |
| mixins['ElementTimeControl']=1 | |
| mixins['ElementTraversal']=1 | |
| return mixins.keys() | |
| def _PreOrderInterfaces(self, interfaces): | |
| """Returns the interfaces in pre-order, i.e. parents first.""" | |
| seen = set() | |
| ordered = [] | |
| def visit(interface): | |
| if interface.id in seen: | |
| return | |
| seen.add(interface.id) | |
| for parent in interface.parents: | |
| if IsDartCollectionType(parent.type.id): | |
| continue | |
| if self._database.HasInterface(parent.type.id): | |
| parent_interface = self._database.GetInterface(parent.type.id) | |
| visit(parent_interface) | |
| ordered.append(interface) | |
| for interface in interfaces: | |
| visit(interface) | |
| return ordered | |
| def _ProcessInterface(self, interface, super_interface_name, | |
| source_filter, | |
| common_prefix): | |
| """.""" | |
| _logger.info('Generating %s' % interface.id) | |
| generators = [system.InterfaceGenerator(interface, | |
| common_prefix, | |
| super_interface_name, | |
| source_filter) | |
| for system in self._systems] | |
| generators = filter(None, generators) | |
| mixinbase = self._database.GetInterface("ElementalMixinBase") | |
| parentops = [] | |
| parentattrs = [] | |
| directParents = [] | |
| mixinOps = [] | |
| # compute the immediate parents of each interface (not including secondary interfaces) | |
| self.getParents(interface, directParents) | |
| # if not the mixin base, add its parents | |
| if interface.id != 'ElementalMixinBase': | |
| self.getParents(mixinbase, directParents) | |
| # add the mixin base class itself as the parent of everything | |
| directParents.insert(0, mixinbase) | |
| # for each parent interface | |
| for pint in directParents: | |
| for op in pint.operations: | |
| # compute unique method signatures for each operation : | |
| op_name = op.ext_attrs.get('DartName', op.id) | |
| sig = "%s %s(" % (op.type.id, op_name) | |
| for arg in op.arguments: | |
| sig += arg.type.id | |
| parentops.append(sig) | |
| for attr in pint.attributes: | |
| # compute attributes | |
| if attr.is_fc_getter: | |
| parentattrs.append("getter_" + DartDomNameOfAttribute(attr)) | |
| if attr.is_fc_setter: | |
| parentattrs.append("setter_" + DartDomNameOfAttribute(attr)) | |
| for generator in generators: | |
| generator.StartInterface() | |
| for const in sorted(interface.constants, ConstantOutputOrder): | |
| for generator in generators: | |
| generator.AddConstant(const) | |
| attributes = [attr for attr in interface.attributes] | |
| for (getter, setter) in _PairUpAttributes(attributes): | |
| for generator in generators: | |
| # detect if attribute is inherited (as opposed to just redeclared) | |
| inheritedGetter = ("getter_" + DartDomNameOfAttribute(getter)) in parentattrs | |
| inheritedSetter = setter and ("setter_" + DartDomNameOfAttribute(setter)) in parentattrs | |
| generator.AddAttribute(getter, setter, inheritedGetter, inheritedSetter) | |
| # The implementation should define an indexer if the interface directly | |
| # extends List. | |
| element_type = MaybeListElementType(interface) | |
| if element_type: | |
| for generator in generators: | |
| generator.AddIndexer(element_type) | |
| # Generate operations | |
| alreadyGenerated = [] | |
| for operation in interface.operations: | |
| op_name = operation.ext_attrs.get('DartName', operation.id) | |
| sig = "%s %s(" % (operation.type.id, op_name) | |
| for arg in operation.arguments: | |
| sig += arg.type.id | |
| if sig in alreadyGenerated: | |
| continue | |
| alreadyGenerated.append(sig) | |
| # hacks, should be able to compute this from IDL database | |
| if operation.id == 'toString': | |
| # implemented on JSO.toString() | |
| continue | |
| operations = [] | |
| operations.append(operation) | |
| info = AnalyzeOperation(interface, operations) | |
| for generator in generators: | |
| # don't override stuff hoisted to mixin base in implementors | |
| inherited = sig in parentops | |
| if info.IsStatic(): | |
| generator.AddStaticOperation(info, inherited) | |
| else: | |
| generator.AddOperation(info, inherited) | |
| # With multiple inheritance, attributes and operations of non-first | |
| # interfaces need to be added. Sometimes the attribute or operation is | |
| # defined in the current interface as well as a parent. In that case we | |
| # avoid making a duplicate definition and pray that the signatures match. | |
| for parent_interface in self._TransitiveSecondaryParents(interface): | |
| if isinstance(parent_interface, str): # IsDartCollectionType(parent_interface) | |
| continue | |
| attributes = [attr for attr in parent_interface.attributes | |
| if not FindMatchingAttribute(interface, attr)] | |
| for (getter, setter) in _PairUpAttributes(attributes): | |
| for generator in generators: | |
| generator.AddSecondaryAttribute(parent_interface, getter, setter) | |
| # Group overloaded operations by id | |
| operationsById = {} | |
| for operation in parent_interface.operations: | |
| if operation.id not in operationsById: | |
| operationsById[operation.id] = [] | |
| operationsById[operation.id].append(operation) | |
| # Generate operations | |
| for id in sorted(operationsById.keys()): | |
| if not any(op.id == id for op in interface.operations): | |
| operations = operationsById[id] | |
| info = AnalyzeOperation(interface, operations) | |
| for generator in generators: | |
| generator.AddSecondaryOperation(parent_interface, info) | |
| for generator in generators: | |
| generator.FinishInterface() | |
| return | |
| def getParents(self, interface, results): | |
| if interface.parents: | |
| pid = interface.parents[0].type.id | |
| if self._database.HasInterface(pid): | |
| pint = self._database.GetInterface(interface.parents[0].type.id) | |
| results.append(pint) | |
| self.getParents(pint, results) | |
| def _TransitiveSecondaryParents(self, interface): | |
| """Returns a list of all non-primary parents. | |
| The list contains the interface objects for interfaces defined in the | |
| database, and the name for undefined interfaces. | |
| """ | |
| def walk(parents): | |
| for parent in parents: | |
| if IsDartCollectionType(parent.type.id): | |
| result.append(parent.type.id) | |
| continue | |
| if self._database.HasInterface(parent.type.id): | |
| parent_interface = self._database.GetInterface(parent.type.id) | |
| result.append(parent_interface) | |
| walk(parent_interface.parents) | |
| result = [] | |
| walk(interface.parents[1:]) | |
| return result; | |
| def _CollectExceptions(self, interfaces): | |
| """Returns the names of all exception classes raised.""" | |
| exceptions = set() | |
| for interface in interfaces: | |
| for attribute in interface.attributes: | |
| if attribute.get_raises: | |
| exceptions.add(attribute.get_raises.id) | |
| if attribute.set_raises: | |
| exceptions.add(attribute.set_raises.id) | |
| for operation in interface.operations: | |
| if operation.raises: | |
| exceptions.add(operation.raises.id) | |
| return exceptions | |
| def Flush(self): | |
| """Write out all pending files.""" | |
| _logger.info('Flush...') | |
| self._emitters.Flush() | |
| def _FixEventTargets(self): | |
| for interface in self._database.GetInterfaces(): | |
| # Create fake EventTarget parent interface for interfaces that have | |
| # 'EventTarget' extended attribute. | |
| if 'EventTarget' in interface.ext_attrs: | |
| ast = [('Annotation', [('Id', 'WebKit')]), | |
| ('InterfaceType', ('ScopedName', 'EventTarget'))] | |
| interface.parents.append(idlnode.IDLParentInterface(ast)) | |
| def _ComputeInheritanceClosure(self): | |
| def Collect(interface, seen, collected): | |
| name = interface.id | |
| if '<' in name: | |
| # TODO(sra): Handle parameterized types. | |
| return | |
| if not name in seen: | |
| seen.add(name) | |
| collected.append(name) | |
| for parent in interface.parents: | |
| # TODO(sra): Handle parameterized types. | |
| if not '<' in parent.type.id: | |
| if self._database.HasInterface(parent.type.id): | |
| Collect(self._database.GetInterface(parent.type.id), | |
| seen, collected) | |
| self._inheritance_closure = {} | |
| for interface in self._database.GetInterfaces(): | |
| seen = set() | |
| collected = [] | |
| Collect(interface, seen, collected) | |
| self._inheritance_closure[interface.id] = collected | |
| def _AllImplementedInterfaces(self, interface): | |
| """Returns a list of the names of all interfaces implemented by 'interface'. | |
| List includes the name of 'interface'. | |
| """ | |
| return self._inheritance_closure[interface.id] | |
| def _PairUpAttributes(attributes): | |
| """Returns a list of (getter, setter) pairs sorted by name. | |
| One element of the pair may be None. | |
| """ | |
| names = sorted(set(attr.id for attr in attributes)) | |
| getters = {} | |
| setters = {} | |
| for attr in attributes: | |
| if attr.is_fc_getter: | |
| getters[attr.id] = attr | |
| elif attr.is_fc_setter and 'Replaceable' not in attr.ext_attrs: | |
| setters[attr.id] = attr | |
| return [(getters.get(id), setters.get(id)) for id in names] | |
| # ------------------------------------------------------------------------------ | |
| class DummyImplementationSystem(SystemElemental): | |
| """Generates a dummy implementation for use by the editor analysis. | |
| All the code comes from hand-written library files. | |
| """ | |
| def __init__(self, templates, database, emitters, output_dir): | |
| super(DummyImplementationSystem, self).__init__( | |
| templates, database, emitters, output_dir) | |
| factory_providers_file = os.path.join(self._output_dir, 'src', 'dummy', | |
| 'RegularFactoryProviders.dart') | |
| self._factory_providers_emitter = self._emitters.FileEmitter( | |
| factory_providers_file) | |
| self._impl_file_paths = [factory_providers_file] | |
| def InterfaceGenerator(self, | |
| interface, | |
| common_prefix, | |
| super_interface_name, | |
| source_filter): | |
| return DummyInterfaceGenerator(self, interface) | |
| def ProcessCallback(self, interface, info): | |
| pass | |
| def GenerateLibraries(self, lib_dir): | |
| # Library generated for implementation. | |
| self._GenerateLibFile( | |
| 'dom_dummy.darttemplate', | |
| os.path.join(lib_dir, 'dom_dummy.dart'), | |
| (self._interface_system._dart_interface_file_paths + | |
| self._interface_system._dart_callback_file_paths + | |
| self._impl_file_paths)) | |
| # ------------------------------------------------------------------------------ | |
| class DummyInterfaceGenerator(object): | |
| """Generates dummy implementation.""" | |
| def __init__(self, system, interface): | |
| self._system = system | |
| self._interface = interface | |
| def StartInterface(self): | |
| # There is no implementation to match the interface, but there might be a | |
| # factory constructor for the Dart interface. | |
| constructor_info = AnalyzeConstructor(self._interface) | |
| if constructor_info: | |
| dart_interface_name = self._interface.id | |
| self._EmitFactoryProvider(dart_interface_name, constructor_info) | |
| def _EmitFactoryProvider(self, interface_name, constructor_info): | |
| factory_provider = '_' + interface_name + 'FactoryProvider' | |
| self._system._factory_providers_emitter.Emit( | |
| self._system._templates.Load('factoryprovider.darttemplate'), | |
| FACTORYPROVIDER=factory_provider, | |
| CONSTRUCTOR=interface_name, | |
| PARAMETERS=constructor_info.ParametersImplementationDeclaration()) | |
| def FinishInterface(self): | |
| pass | |
| def AddConstant(self, constant): | |
| pass | |
| def AddAttribute(self, getter, setter, inheritedGetter, inheritedSetter): | |
| pass | |
| def AddSecondaryAttribute(self, interface, getter, setter): | |
| pass | |
| def AddSecondaryOperation(self, interface, info): | |
| pass | |
| def AddIndexer(self, element_type): | |
| pass | |
| def AddTypedArrayConstructors(self, element_type): | |
| pass | |
| def AddOperation(self, info, inherited): | |
| pass | |
| def AddStaticOperation(self, info, inherited): | |
| pass | |
| def AddEventAttributes(self, event_attrs): | |
| pass |