def sequence_node_to_type(node):
    children = node.GetChildren()
    class_name = node.GetClass()
    if len(children) != 1:
        raise ValueError('%s node expects exactly 1 child, got %s' %
                         (class_name, 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)
    if class_name == 'Sequence':
        sequence_type = IdlSequenceType(element_type)
    elif class_name == 'FrozenArray':
        sequence_type = IdlFrozenArrayType(element_type)
    else:
        raise ValueError('Unexpected node: %s' % class_name)
    if node.GetProperty('NULLABLE'):
        return IdlNullableType(sequence_type)
    return sequence_type
    def test_idl_types(self):
        idl_type = IdlRecordType(IdlType('USVString'), IdlType('long'))
        idl_types = list(idl_type.idl_types())
        self.assertEqual(len(idl_types), 3)
        self.assertIs(idl_types[0], idl_type)
        self.assertEqual(idl_types[1].name, 'USVString')
        self.assertEqual(idl_types[2].name, 'Long')
        self.assertListEqual(
            list(idl_type.idl_types()),
            [idl_type, idl_type.key_type, idl_type.value_type])

        idl_type = IdlRecordType(
            IdlType('DOMString'),
            IdlSequenceType(IdlType('unrestricted float')))
        idl_types = list(idl_type.idl_types())
        self.assertEqual(len(idl_types), 4)
        self.assertIs(idl_types[0], idl_type)
        self.assertEqual(idl_types[1].name, 'String')
        self.assertEqual(idl_types[2].name, 'UnrestrictedFloatSequence')
        self.assertEqual(idl_types[3].name, 'UnrestrictedFloat')
        self.assertListEqual(list(idl_type.idl_types()), [
            idl_type, idl_type.key_type, idl_type.value_type,
            idl_type.value_type.element_type
        ])

        idl_type = IdlRecordType(
            IdlType('ByteString'),
            IdlRecordType(IdlType('DOMString'), IdlType('octet')))
        idl_types = list(idl_type.idl_types())
        self.assertEqual(len(idl_types), 5)
        self.assertIs(idl_types[0], idl_type)
        self.assertEqual(idl_types[1].name, 'ByteString')
        self.assertEqual(idl_types[2].name, 'StringOctetRecord')
        self.assertEqual(idl_types[3].name, 'String')
        self.assertEqual(idl_types[4].name, 'Octet')
        self.assertListEqual(list(idl_type.idl_types()), [
            idl_type, idl_type.key_type, idl_type.value_type,
            idl_type.value_type.key_type, idl_type.value_type.value_type
        ])
    def test_flattened_member_types(self):
        # We are only testing the algorithm here, so we do create some ambiguous union types.

        def compare_flattened_members(actual, expected):
            """Compare a set of IDL types by name, as the objects are different"""
            actual_names = set([member.name for member in actual])
            expected_names = set([member.name for member in expected])
            self.assertEqual(actual_names, expected_names)

        idl_type = IdlUnionType([IdlType('long'), IdlType('SomeInterface')])
        compare_flattened_members(
            idl_type.flattened_member_types,
            set([IdlType('long'), IdlType('SomeInterface')]))

        idl_type = IdlUnionType([
            IdlUnionType([IdlType('ByteString'),
                          IdlType('float')]),
            IdlType('boolean')
        ])
        compare_flattened_members(
            idl_type.flattened_member_types,
            set([IdlType('float'),
                 IdlType('boolean'),
                 IdlType('ByteString')]))

        idl_type = IdlUnionType([
            IdlUnionType([IdlType('ByteString'),
                          IdlType('DOMString')]),
            IdlType('DOMString')
        ])
        compare_flattened_members(
            idl_type.flattened_member_types,
            set([IdlType('DOMString'),
                 IdlType('ByteString')]))

        idl_type = IdlUnionType(
            [IdlNullableType(IdlType('ByteString')),
             IdlType('byte')])
        compare_flattened_members(
            idl_type.flattened_member_types,
            set([IdlType('ByteString'), IdlType('byte')]))

        idl_type = IdlUnionType([
            IdlNullableType(IdlType('ByteString')),
            IdlType('byte'),
            IdlUnionType([IdlType('ByteString'),
                          IdlType('float')])
        ])
        self.assertEqual(len(idl_type.flattened_member_types), 3)
        compare_flattened_members(
            idl_type.flattened_member_types,
            set([IdlType('ByteString'),
                 IdlType('byte'),
                 IdlType('float')]))

        # From the example in the spec: "the flattened member types of the union type (Node or (sequence<long> or Event) or
        # (XMLHttpRequest or DOMString)? or sequence<(sequence<double> or NodeList)>) are the six types Node, sequence<long>,
        # Event, XMLHttpRequest, DOMString and sequence<(sequence<double> or NodeList)>"
        idl_type = IdlUnionType([
            IdlType('Node'),
            IdlUnionType([IdlSequenceType(IdlType('long')),
                          IdlType('Event')]),
            IdlNullableType(
                IdlUnionType([IdlType('XMLHttpRequest'),
                              IdlType('DOMString')])),
            IdlSequenceType(
                IdlUnionType(
                    [IdlSequenceType(IdlType('double')),
                     IdlType('NodeList')]))
        ])
        self.assertEqual(len(idl_type.flattened_member_types), 6)
        compare_flattened_members(
            idl_type.flattened_member_types,
            set([
                IdlType('Node'),
                IdlSequenceType(IdlType('long')),
                IdlType('Event'),
                IdlType('XMLHttpRequest'),
                IdlType('DOMString'),
                IdlSequenceType(
                    IdlUnionType([
                        IdlSequenceType(IdlType('double')),
                        IdlType('NodeList')
                    ]))
            ]))