• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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