1"use strict"; 2 3(() => { 4 function write(ast, opt = {}) { 5 const noop = str => str; 6 const optNames = "type".split(" "); 7 const context = []; 8 for (const o of optNames) { 9 if (!opt[o]) opt[o] = noop; 10 } 11 12 function literal(it) { 13 return it.value; 14 }; 15 function type(it) { 16 if (typeof it === "string") return opt.type(it); // XXX should maintain some context 17 let ret = extended_attributes(it.extAttrs); 18 if (it.union) ret += `(${it.idlType.map(type).join(" or ")})`; 19 else { 20 if (it.generic) ret += `${it.generic}<`; 21 if (Array.isArray(it.idlType)) ret += it.idlType.map(type).join(", "); 22 else ret += type(it.idlType); 23 if (it.generic) ret += ">"; 24 } 25 if (it.nullable) ret += "?"; 26 27 return ret; 28 }; 29 function const_value(it) { 30 const tp = it.type; 31 if (tp === "boolean") return it.value ? "true" : "false"; 32 else if (tp === "null") return "null"; 33 else if (tp === "Infinity") return (it.negative ? "-" : "") + "Infinity"; 34 else if (tp === "NaN") return "NaN"; 35 else if (tp === "number") return it.value; 36 else if (tp === "sequence") return "[]"; 37 else return `"${it.value}"`; 38 }; 39 function argument(arg) { 40 let ret = extended_attributes(arg.extAttrs); 41 if (arg.optional) ret += "optional "; 42 ret += type(arg.idlType); 43 if (arg.variadic) ret += "..."; 44 ret += ` ${arg.escapedName}`; 45 if (arg.default) ret += ` = ${const_value(arg.default)}`; 46 return ret; 47 }; 48 function make_ext_at(it) { 49 context.unshift(it); 50 let ret = it.name; 51 if (it.rhs) { 52 if (it.rhs.type === "identifier-list") ret += `=(${it.rhs.value.join(",")})`; 53 else ret += `=${it.rhs.value}`; 54 } 55 if (it.arguments) ret += `(${it.arguments.length ? it.arguments.map(argument).join(",") : ""})`; 56 context.shift(); // XXX need to add more contexts, but not more than needed for ReSpec 57 return ret; 58 }; 59 function extended_attributes(eats) { 60 if (!eats || !eats.length) return ""; 61 return `[${eats.map(make_ext_at).join(", ")}]`; 62 }; 63 64 const modifiers = "getter setter deleter stringifier static".split(" "); 65 function operation(it) { 66 let ret = extended_attributes(it.extAttrs); 67 if (it.stringifier && !it.idlType) return "stringifier;"; 68 for (const mod of modifiers) { 69 if (it[mod]) ret += mod + " "; 70 } 71 ret += type(it.idlType) + " "; 72 if (it.name) ret += it.escapedName; 73 ret += `(${it.arguments.map(argument).join(",")});`; 74 return ret; 75 }; 76 77 function attribute(it) { 78 let ret = extended_attributes(it.extAttrs); 79 if (it.static) ret += "static "; 80 if (it.stringifier) ret += "stringifier "; 81 if (it.inherit) ret += "inherit "; 82 if (it.readonly) ret += "readonly "; 83 ret += `attribute ${type(it.idlType)} ${it.escapedName};`; 84 return ret; 85 }; 86 87 function interface_(it) { 88 let ret = extended_attributes(it.extAttrs); 89 if (it.partial) ret += "partial "; 90 ret += `interface ${it.name} `; 91 if (it.inheritance) ret += `: ${it.inheritance} `; 92 ret += `{${iterate(it.members)}};`; 93 return ret; 94 }; 95 96 function interface_mixin(it) { 97 let ret = extended_attributes(it.extAttrs); 98 if (it.partial) ret += "partial "; 99 ret += `interface mixin ${it.name} `; 100 ret += `{${iterate(it.members)}};`; 101 return ret; 102 } 103 104 function namespace(it) { 105 let ret = extended_attributes(it.extAttrs); 106 if (it.partial) ret += "partial "; 107 ret += `namespace ${it.name} `; 108 ret += `{${iterate(it.members)}};`; 109 return ret; 110 } 111 112 function dictionary(it) { 113 let ret = extended_attributes(it.extAttrs); 114 if (it.partial) ret += "partial "; 115 ret += `dictionary ${it.name} `; 116 if (it.inheritance) ret += `: ${it.inheritance} `; 117 ret += `{${iterate(it.members)}};`; 118 return ret; 119 }; 120 function field(it) { 121 let ret = extended_attributes(it.extAttrs); 122 if (it.required) ret += "required "; 123 ret += `${type(it.idlType)} ${it.escapedName}`; 124 if (it.default) ret += ` = ${const_value(it.default)}`; 125 ret += ";"; 126 return ret; 127 }; 128 function const_(it) { 129 const ret = extended_attributes(it.extAttrs); 130 return `${ret}const ${type(it.idlType)}${it.nullable ? "?" : ""} ${it.name} = ${const_value(it.value)};`; 131 }; 132 function typedef(it) { 133 let ret = extended_attributes(it.extAttrs); 134 ret += `typedef ${extended_attributes(it.typeExtAttrs)}`; 135 return `${ret}${type(it.idlType)} ${it.name};`; 136 }; 137 function implements_(it) { 138 const ret = extended_attributes(it.extAttrs); 139 return `${ret}${it.target} implements ${it.implements};`; 140 }; 141 function includes(it) { 142 const ret = extended_attributes(it.extAttrs); 143 return `${ret}${it.target} includes ${it.includes};`; 144 }; 145 function callback(it) { 146 const ret = extended_attributes(it.extAttrs); 147 return `${ret}callback ${it.name} = ${type(it.idlType)}(${it.arguments.map(argument).join(",")});`; 148 }; 149 function enum_(it) { 150 let ret = extended_attributes(it.extAttrs); 151 ret += `enum ${it.name} {`; 152 for (const v of it.values) { 153 ret += `"${v.value}",`; 154 } 155 return ret + "};"; 156 }; 157 function iterable(it) { 158 return `iterable<${Array.isArray(it.idlType) ? it.idlType.map(type).join(", ") : type(it.idlType)}>;`; 159 }; 160 function legacyiterable(it) { 161 return `legacyiterable<${Array.isArray(it.idlType) ? it.idlType.map(type).join(", ") : type(it.idlType)}>;`; 162 }; 163 function maplike(it) { 164 return `${it.readonly ? "readonly " : ""}maplike<${it.idlType.map(type).join(", ")}>;`; 165 }; 166 function setlike(it) { 167 return `${it.readonly ? "readonly " : ""}setlike<${type(it.idlType[0])}>;`; 168 }; 169 function callbackInterface(it) { 170 return `callback ${interface_(it)}`; 171 }; 172 173 const table = { 174 interface: interface_, 175 "interface mixin": interface_mixin, 176 namespace, 177 operation, 178 attribute, 179 dictionary, 180 field, 181 const: const_, 182 typedef, 183 implements: implements_, 184 includes, 185 callback, 186 enum: enum_, 187 iterable, 188 legacyiterable, 189 maplike, 190 setlike, 191 "callback interface": callbackInterface 192 }; 193 function dispatch(it) { 194 const dispatcher = table[it.type]; 195 if (!dispatcher) { 196 throw new Error(`Type "${it.type}" is unsupported`) 197 } 198 return table[it.type](it); 199 }; 200 function iterate(things) { 201 if (!things) return; 202 let ret = ""; 203 for (const thing of things) ret += dispatch(thing); 204 return ret; 205 }; 206 return iterate(ast); 207 }; 208 209 210 const obj = { 211 write 212 }; 213 214 if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { 215 module.exports = obj; 216 } else if (typeof define === 'function' && define.amd) { 217 define([], () => obj); 218 } else { 219 (self || window).WebIDL2Writer = obj; 220 } 221})(); 222