| Index: tools/dom/scripts/idlnode.py
|
| diff --git a/tools/dom/scripts/idlnode.py b/tools/dom/scripts/idlnode.py
|
| index 5e4d156ae223621680bf4d479b3e0a4d39683e6c..b88db3ae497ba2e440021e1621b8bd472450c797 100755
|
| --- a/tools/dom/scripts/idlnode.py
|
| +++ b/tools/dom/scripts/idlnode.py
|
| @@ -58,10 +58,13 @@ class IDLNode(object):
|
| etc.
|
| """
|
|
|
| - def __init__(self, ast):
|
| + def __init__(self, ast, id=None):
|
| """Initializes an IDLNode from a PegParser AST output."""
|
| - self.id = self._find_first(ast, 'Id') if ast is not None else None
|
| -
|
| + if ast:
|
| + self.id = self._find_first(ast, 'Id') if ast is not None else None
|
| + else:
|
| + # Support synthesized IDLNode created w/o an AST (e.g., setlike support).
|
| + self.id = id
|
|
|
| def __repr__(self):
|
| """Generates string of the form <class id extra extra ... 0x12345678>."""
|
| @@ -570,90 +573,95 @@ class IDLExtAttrFunctionValue(IDLNode):
|
| class IDLType(IDLNode):
|
| """IDLType is used to describe constants, attributes and operations'
|
| return and input types. IDLType matches AST labels such as ScopedName,
|
| - StringType, VoidType, IntegerType, etc."""
|
| + StringType, VoidType, IntegerType, etc.
|
| + NOTE: AST of None implies synthesize IDLType the id is passed in used by
|
| + setlike."""
|
|
|
| - def __init__(self, ast):
|
| + def __init__(self, ast, id=None):
|
| global _unions_to_any
|
|
|
| - IDLNode.__init__(self, ast)
|
| + IDLNode.__init__(self, ast, id)
|
|
|
| - if ast:
|
| - self.nullable = self._has(ast, 'Nullable')
|
| - # Search for a 'ScopedName' or any label ending with 'Type'.
|
| - if isinstance(ast, list):
|
| - self.id = self._find_first(ast, 'ScopedName')
|
| - if not self.id:
|
| - # FIXME: use regexp search instead
|
| - def findType(ast):
|
| - for label, childAst in ast:
|
| - if label.endswith('Type'):
|
| - type = self._label_to_type(label, ast)
|
| - if type != 'sequence':
|
| - return type
|
| - type_ast = self._find_first(childAst, 'Type')
|
| - if not type_ast:
|
| - return type
|
| - return 'sequence<%s>' % findType(type_ast)
|
| - raise Exception('No type declaration found in %s' % ast)
|
| - self.id = findType(ast)
|
| - # TODO(terry): Remove array_modifiers id has [] appended, keep for old
|
| - # parsing.
|
| - array_modifiers = self._find_first(ast, 'ArrayModifiers')
|
| - if array_modifiers:
|
| - self.id += array_modifiers
|
| - elif isinstance(ast, tuple):
|
| - (label, value) = ast
|
| - if label == 'ScopedName':
|
| - self.id = value
|
| - else:
|
| - self.id = self._label_to_type(label, ast)
|
| - elif isinstance(ast, str):
|
| - self.id = ast
|
| - # New blink handling.
|
| - elif ast.__module__ == "idl_types":
|
| - if isinstance(ast, IdlType) or isinstance(ast, IdlArrayOrSequenceType) or \
|
| - isinstance(ast, IdlNullableType):
|
| - if isinstance(ast, IdlNullableType) and ast.inner_type.is_union_type:
|
| - # Report of union types mapped to any.
|
| - if not(self.id in _unions_to_any):
|
| - _unions_to_any.append(self.id)
|
| - # TODO(terry): For union types use any otherwise type is unionType is
|
| - # not found and is removed during merging.
|
| - self.id = 'any'
|
| - else:
|
| - type_name = str(ast)
|
| - # TODO(terry): For now don't handle unrestricted types see
|
| - # https://code.google.com/p/chromium/issues/detail?id=354298
|
| - type_name = type_name.replace('unrestricted ', '', 1);
|
| -
|
| - # TODO(terry): Handled USVString as a DOMString.
|
| - type_name = type_name.replace('USVString', 'DOMString', 1)
|
| -
|
| - # TODO(terry); WindowTimers setInterval/setTimeout overloads with a
|
| - # Function type - map to any until the IDL uses union.
|
| - type_name = type_name.replace('Function', 'any', 1)
|
| -
|
| - self.id = type_name
|
| - else:
|
| - # IdlUnionType
|
| - if ast.is_union_type:
|
| - if not(self.id in _unions_to_any):
|
| - _unions_to_any.append(self.id)
|
| - # TODO(terry): For union types use any otherwise type is unionType is
|
| - # not found and is removed during merging.
|
| - self.id = 'any'
|
| - # TODO(terry): Any union type e.g. 'type1 or type2 or type2',
|
| - # 'typedef (Type1 or Type2) UnionType'
|
| - # Is a problem we need to extend IDLType and IDLTypeDef to handle more
|
| - # than one type.
|
| - #
|
| - # Also for typedef's e.g.,
|
| - # typedef (Type1 or Type2) UnionType
|
| - # should consider synthesizing a new interface (e.g., UnionType) that's
|
| - # both Type1 and Type2.
|
| + if not ast:
|
| + # Support synthesized IDLType with no AST (e.g., setlike support).
|
| + return
|
| +
|
| + self.nullable = self._has(ast, 'Nullable')
|
| + # Search for a 'ScopedName' or any label ending with 'Type'.
|
| + if isinstance(ast, list):
|
| + self.id = self._find_first(ast, 'ScopedName')
|
| if not self.id:
|
| - print '>>>> __module__ %s' % ast.__module__
|
| - raise SyntaxError('Could not parse type %s' % (ast))
|
| + # FIXME: use regexp search instead
|
| + def findType(ast):
|
| + for label, childAst in ast:
|
| + if label.endswith('Type'):
|
| + type = self._label_to_type(label, ast)
|
| + if type != 'sequence':
|
| + return type
|
| + type_ast = self._find_first(childAst, 'Type')
|
| + if not type_ast:
|
| + return type
|
| + return 'sequence<%s>' % findType(type_ast)
|
| + raise Exception('No type declaration found in %s' % ast)
|
| + self.id = findType(ast)
|
| + # TODO(terry): Remove array_modifiers id has [] appended, keep for old
|
| + # parsing.
|
| + array_modifiers = self._find_first(ast, 'ArrayModifiers')
|
| + if array_modifiers:
|
| + self.id += array_modifiers
|
| + elif isinstance(ast, tuple):
|
| + (label, value) = ast
|
| + if label == 'ScopedName':
|
| + self.id = value
|
| + else:
|
| + self.id = self._label_to_type(label, ast)
|
| + elif isinstance(ast, str):
|
| + self.id = ast
|
| + # New blink handling.
|
| + elif ast.__module__ == "idl_types":
|
| + if isinstance(ast, IdlType) or isinstance(ast, IdlArrayOrSequenceType) or \
|
| + isinstance(ast, IdlNullableType):
|
| + if isinstance(ast, IdlNullableType) and ast.inner_type.is_union_type:
|
| + # Report of union types mapped to any.
|
| + if not(self.id in _unions_to_any):
|
| + _unions_to_any.append(self.id)
|
| + # TODO(terry): For union types use any otherwise type is unionType is
|
| + # not found and is removed during merging.
|
| + self.id = 'any'
|
| + else:
|
| + type_name = str(ast)
|
| + # TODO(terry): For now don't handle unrestricted types see
|
| + # https://code.google.com/p/chromium/issues/detail?id=354298
|
| + type_name = type_name.replace('unrestricted ', '', 1);
|
| +
|
| + # TODO(terry): Handled USVString as a DOMString.
|
| + type_name = type_name.replace('USVString', 'DOMString', 1)
|
| +
|
| + # TODO(terry); WindowTimers setInterval/setTimeout overloads with a
|
| + # Function type - map to any until the IDL uses union.
|
| + type_name = type_name.replace('Function', 'any', 1)
|
| +
|
| + self.id = type_name
|
| + else:
|
| + # IdlUnionType
|
| + if ast.is_union_type:
|
| + if not(self.id in _unions_to_any):
|
| + _unions_to_any.append(self.id)
|
| + # TODO(terry): For union types use any otherwise type is unionType is
|
| + # not found and is removed during merging.
|
| + self.id = 'any'
|
| + # TODO(terry): Any union type e.g. 'type1 or type2 or type2',
|
| + # 'typedef (Type1 or Type2) UnionType'
|
| + # Is a problem we need to extend IDLType and IDLTypeDef to handle more
|
| + # than one type.
|
| + #
|
| + # Also for typedef's e.g.,
|
| + # typedef (Type1 or Type2) UnionType
|
| + # should consider synthesizing a new interface (e.g., UnionType) that's
|
| + # both Type1 and Type2.
|
| + if not self.id:
|
| + print '>>>> __module__ %s' % ast.__module__
|
| + raise SyntaxError('Could not parse type %s' % (ast))
|
|
|
| def _label_to_type(self, label, ast):
|
| if label == 'LongLongType':
|
| @@ -717,6 +725,72 @@ class IDLDictionaryMembers(IDLDictNode):
|
| value = IDLDictionaryMember(member, js_name)
|
| self[name] = value
|
|
|
| +def generate_operation(interface_name, result_type_name, oper_name, arguments):
|
| + """ Synthesize an IDLOperation with no AST used for support of setlike."""
|
| + """ Arguments is a list of argument where each argument is:
|
| + [IDLType, argument_name, optional_boolean] """
|
| +
|
| + syn_op = IDLOperation(None, interface_name, oper_name)
|
| +
|
| + syn_op.type = IDLType(None, result_type_name)
|
| + syn_op.type = resolveTypedef(syn_op.type)
|
| +
|
| + for argument in arguments:
|
| + arg = IDLArgument(None, argument[1]);
|
| + arg.type = argument[0];
|
| + arg.optional = argument[2] if len(argument) > 2 else False
|
| + syn_op.arguments.append(arg)
|
| +
|
| + return syn_op
|
| +
|
| +def generate_setLike_operations_properties(interface, set_like):
|
| + """
|
| + Need to create (in our database) a number of operations. This is a new IDL
|
| + syntax, the implied operations for a set now use setlike<T> where T is a known
|
| + type e.g., setlike<FontFace> setlike implies these operations are generated:
|
| +
|
| + void forEach(any callback, optional any thisArg);
|
| + boolean has(FontFace fontFace);
|
| + boolean has(FontFace fontFace);
|
| +
|
| + if setlike is not read-only these operations are generated:
|
| +
|
| + FontFaceSet add(FontFace value);
|
| + boolean delete(FontFace value);
|
| + void clear();
|
| + """
|
| + setlike_ops = []
|
| + """
|
| + Need to create a typedef for a function callback e.g.,
|
| + a setlike will need a callback that has the proper args in FontFaceSet that is
|
| + three arguments, etc.
|
| +
|
| + typedef void FontFaceSetForEachCallback(
|
| + FontFace fontFace, FontFace fontFaceAgain, FontFaceSet set);
|
| +
|
| + void forEach(FontFaceSetForEachCallback callback, [Object thisArg]);
|
| + """
|
| + callback_name = '%sForEachCallback' % interface.id
|
| + set_op = generate_operation(interface.id, 'void', 'forEach',
|
| + [[IDLType(None, callback_name), 'callback'],
|
| + [IDLType(None, 'any'), 'thisArg', True]])
|
| + setlike_ops.append(set_op)
|
| +
|
| + set_op = generate_operation(interface.id, 'boolean', 'has',
|
| + [[IDLType(None, set_like.value_type.base_type), 'arg']])
|
| + setlike_ops.append(set_op)
|
| +
|
| + if not set_like.is_read_only:
|
| + set_op = generate_operation(interface.id, interface.id, 'add',
|
| + [[IDLType(None, set_like.value_type.base_type), 'arg']])
|
| + setlike_ops.append(set_op)
|
| + set_op = generate_operation(interface.id, 'boolean', 'delete',
|
| + [[IDLType(None, set_like.value_type.base_type), 'arg']])
|
| + setlike_ops.append(set_op)
|
| + set_op = generate_operation(interface.id, 'void', 'clear', [])
|
| + setlike_ops.append(set_op)
|
| +
|
| + return setlike_ops
|
|
|
| class IDLInterface(IDLNode):
|
| """IDLInterface node contains operations, attributes, constants,
|
| @@ -742,6 +816,12 @@ class IDLInterface(IDLNode):
|
|
|
| self.operations = self._convert_all(ast, 'Operation',
|
| lambda ast: IDLOperation(ast, self.doc_js_name))
|
| +
|
| + if ast.setlike:
|
| + setlike_ops = generate_setLike_operations_properties(self, ast.setlike)
|
| + for op in setlike_ops:
|
| + self.operations.append(op)
|
| +
|
| self.attributes = self._convert_all(ast, 'Attribute',
|
| lambda ast: IDLAttribute(ast, self.doc_js_name))
|
| self.constants = self._convert_all(ast, 'Const',
|
| @@ -752,7 +832,6 @@ class IDLInterface(IDLNode):
|
| self.is_fc_suppressed = 'Suppressed' in self.ext_attrs or \
|
| 'DartSuppress' in self.ext_attrs
|
|
|
| -
|
| def reset_id(self, new_id):
|
| """Reset the id of the Interface and corresponding the JS names."""
|
| if self.id != new_id:
|
| @@ -785,9 +864,16 @@ class IDLParentInterface(IDLNode):
|
|
|
| class IDLMember(IDLNode):
|
| """A base class for constants, attributes and operations."""
|
| -
|
| - def __init__(self, ast, doc_js_interface_name):
|
| - IDLNode.__init__(self, ast)
|
| + def __init__(self, ast, doc_js_interface_name, member_id=None):
|
| + if ast:
|
| + IDLNode.__init__(self, ast)
|
| + else:
|
| + # The ast is None to support synthesizing an IDLMember, member_id is only
|
| + # used when ast is None.
|
| + IDLNode.__init__(self, ast, member_id)
|
| + self.type = None
|
| + self.doc_js_interface_name = doc_js_interface_name
|
| + return
|
|
|
| self.type = self._convert_first(ast, 'Type', IDLType)
|
| self.type = resolveTypedef(self.type)
|
| @@ -802,8 +888,18 @@ class IDLMember(IDLNode):
|
|
|
| class IDLOperation(IDLMember):
|
| """IDLNode specialization for 'type name(args)' declarations."""
|
| - def __init__(self, ast, doc_js_interface_name):
|
| - IDLMember.__init__(self, ast, doc_js_interface_name)
|
| + def __init__(self, ast, doc_js_interface_name, id=None):
|
| + IDLMember.__init__(self, ast, doc_js_interface_name, id)
|
| +
|
| + if not ast:
|
| + # Synthesize an IDLOperation with no ast used for setlike.
|
| + self.ext_attrs = IDLExtAttrs()
|
| + self.annotations = IDLAnnotations()
|
| + self.is_fc_suppressed = False
|
| + self.specials = []
|
| + self.is_static = False
|
| + self.arguments = []
|
| + return;
|
|
|
| self.type = self._convert_first(ast, 'ReturnType', IDLType)
|
| self.type = resolveTypedef(self.type)
|
| @@ -837,6 +933,9 @@ class IDLOperation(IDLMember):
|
| operation_category = 'Named' if arg.type.id == 'DOMString' else 'Indexed'
|
| self.ext_attrs.setdefault('ImplementedAs', 'anonymous%s%s' % (operation_category, _operation_suffix_map[self.id]))
|
|
|
| + def __repr__(self):
|
| + return '<IDLOperation(id = %s)>' % (self.id)
|
| +
|
| def _extra_repr(self):
|
| return [self.arguments]
|
|
|
| @@ -867,8 +966,16 @@ class IDLConstant(IDLMember):
|
|
|
| class IDLArgument(IDLNode):
|
| """IDLNode specialization for operation arguments."""
|
| - def __init__(self, ast):
|
| - IDLNode.__init__(self, ast)
|
| + def __init__(self, ast, id=None):
|
| + if ast:
|
| + IDLNode.__init__(self, ast)
|
| + else:
|
| + # Synthesize an IDLArgument with no ast used for setlike.
|
| + IDLNode.__init__(self, ast, id)
|
| + self.ext_attrs = IDLExtAttrs()
|
| + self.default_value = None
|
| + self.default_value_is_null = False
|
| + return
|
|
|
| self.default_value = None
|
| self.default_value_is_null = False
|
|
|