()
| 188 | }; |
| 189 | |
| 190 | var single_type = function() { |
| 191 | var prim = primitive_type(), |
| 192 | ret = { sequence: false, generic: null, nullable: false, array: false, union: false }, |
| 193 | name, value; |
| 194 | if (prim) { |
| 195 | ret.idlType = prim; |
| 196 | } else if (name = consume(ID)) { |
| 197 | value = name.value; |
| 198 | all_ws(); |
| 199 | // Generic types |
| 200 | if (consume(OTHER, "<")) { |
| 201 | // backwards compat |
| 202 | if (value === "sequence") { |
| 203 | ret.sequence = true; |
| 204 | } |
| 205 | ret.generic = value; |
| 206 | var types = []; |
| 207 | do { |
| 208 | all_ws(); |
| 209 | types.push(type() || error("Error parsing generic type " + value)); |
| 210 | all_ws(); |
| 211 | } |
| 212 | while (consume(OTHER, ",")); |
| 213 | if (value === "sequence") { |
| 214 | if (types.length !== 1) error("A sequence must have exactly one subtype"); |
| 215 | } else if (value === "record") { |
| 216 | if (types.length !== 2) error("A record must have exactly two subtypes"); |
| 217 | if (!/^(DOMString|USVString|ByteString)$/.test(types[0].idlType)) { |
| 218 | error("Record key must be DOMString, USVString, or ByteString"); |
| 219 | } |
| 220 | } |
| 221 | ret.idlType = types.length === 1 ? types[0] : types; |
| 222 | all_ws(); |
| 223 | if (!consume(OTHER, ">")) error("Unterminated generic type " + value); |
| 224 | type_suffix(ret); |
| 225 | return ret; |
| 226 | } else { |
| 227 | ret.idlType = value; |
| 228 | } |
| 229 | } else { |
| 230 | return; |
| 231 | } |
| 232 | type_suffix(ret); |
| 233 | if (ret.nullable && !ret.array && ret.idlType === "any") error("Type any cannot be made nullable"); |
| 234 | return ret; |
| 235 | }; |
| 236 | |
| 237 | var union_type = function() { |
| 238 | all_ws(); |
no test coverage detected