webidl2.js (125228B)
1 (function webpackUniversalModuleDefinition(root, factory) { 2 if(typeof exports === 'object' && typeof module === 'object') 3 module.exports = factory(); 4 else if(typeof define === 'function' && define.amd) 5 define([], factory); 6 else if(typeof exports === 'object') 7 exports["WebIDL2"] = factory(); 8 else 9 root["WebIDL2"] = factory(); 10 })(globalThis, () => { 11 return /******/ (() => { // webpackBootstrap 12 /******/ "use strict"; 13 /******/ var __webpack_modules__ = ([ 14 /* 0 */, 15 /* 1 */ 16 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 17 18 __webpack_require__.r(__webpack_exports__); 19 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 20 /* harmony export */ parse: () => (/* binding */ parse) 21 /* harmony export */ }); 22 /* harmony import */ var _tokeniser_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); 23 /* harmony import */ var _productions_enum_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(15); 24 /* harmony import */ var _productions_includes_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(16); 25 /* harmony import */ var _productions_extended_attributes_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(8); 26 /* harmony import */ var _productions_typedef_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(17); 27 /* harmony import */ var _productions_callback_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(18); 28 /* harmony import */ var _productions_interface_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(19); 29 /* harmony import */ var _productions_mixin_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(25); 30 /* harmony import */ var _productions_dictionary_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(26); 31 /* harmony import */ var _productions_namespace_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(28); 32 /* harmony import */ var _productions_callback_interface_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(29); 33 /* harmony import */ var _productions_helpers_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(4); 34 /* harmony import */ var _productions_token_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(10); 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 /** @typedef {'callbackInterface'|'dictionary'|'interface'|'mixin'|'namespace'} ExtendableInterfaces */ 50 /** @typedef {{ extMembers?: import("./productions/container.js").AllowedMember[]}} Extension */ 51 /** @typedef {Partial<Record<ExtendableInterfaces, Extension>>} Extensions */ 52 53 /** 54 * Parser options. 55 * @typedef {Object} ParserOptions 56 * @property {string} [sourceName] 57 * @property {boolean} [concrete] 58 * @property {Function[]} [productions] 59 * @property {Extensions} [extensions] 60 */ 61 62 /** 63 * @param {Tokeniser} tokeniser 64 * @param {ParserOptions} options 65 */ 66 function parseByTokens(tokeniser, options) { 67 const source = tokeniser.source; 68 69 function error(str) { 70 tokeniser.error(str); 71 } 72 73 function consume(...candidates) { 74 return tokeniser.consume(...candidates); 75 } 76 77 function callback() { 78 const callback = consume("callback"); 79 if (!callback) return; 80 if (tokeniser.probe("interface")) { 81 return _productions_callback_interface_js__WEBPACK_IMPORTED_MODULE_10__.CallbackInterface.parse(tokeniser, callback, { 82 ...options?.extensions?.callbackInterface, 83 }); 84 } 85 return _productions_callback_js__WEBPACK_IMPORTED_MODULE_5__.CallbackFunction.parse(tokeniser, callback); 86 } 87 88 function interface_(opts) { 89 const base = consume("interface"); 90 if (!base) return; 91 return ( 92 _productions_mixin_js__WEBPACK_IMPORTED_MODULE_7__.Mixin.parse(tokeniser, base, { 93 ...opts, 94 ...options?.extensions?.mixin, 95 }) || 96 _productions_interface_js__WEBPACK_IMPORTED_MODULE_6__.Interface.parse(tokeniser, base, { 97 ...opts, 98 ...options?.extensions?.interface, 99 }) || 100 error("Interface has no proper body") 101 ); 102 } 103 104 function partial() { 105 const partial = consume("partial"); 106 if (!partial) return; 107 return ( 108 _productions_dictionary_js__WEBPACK_IMPORTED_MODULE_8__.Dictionary.parse(tokeniser, { 109 partial, 110 ...options?.extensions?.dictionary, 111 }) || 112 interface_({ partial }) || 113 _productions_namespace_js__WEBPACK_IMPORTED_MODULE_9__.Namespace.parse(tokeniser, { 114 partial, 115 ...options?.extensions?.namespace, 116 }) || 117 error("Partial doesn't apply to anything") 118 ); 119 } 120 121 function definition() { 122 if (options.productions) { 123 for (const production of options.productions) { 124 const result = production(tokeniser); 125 if (result) { 126 return result; 127 } 128 } 129 } 130 131 return ( 132 callback() || 133 interface_() || 134 partial() || 135 _productions_dictionary_js__WEBPACK_IMPORTED_MODULE_8__.Dictionary.parse(tokeniser, options?.extensions?.dictionary) || 136 _productions_enum_js__WEBPACK_IMPORTED_MODULE_1__.Enum.parse(tokeniser) || 137 _productions_typedef_js__WEBPACK_IMPORTED_MODULE_4__.Typedef.parse(tokeniser) || 138 _productions_includes_js__WEBPACK_IMPORTED_MODULE_2__.Includes.parse(tokeniser) || 139 _productions_namespace_js__WEBPACK_IMPORTED_MODULE_9__.Namespace.parse(tokeniser, options?.extensions?.namespace) 140 ); 141 } 142 143 function definitions() { 144 if (!source.length) return []; 145 const defs = []; 146 while (true) { 147 const ea = _productions_extended_attributes_js__WEBPACK_IMPORTED_MODULE_3__.ExtendedAttributes.parse(tokeniser); 148 const def = definition(); 149 if (!def) { 150 if (ea.length) error("Stray extended attributes"); 151 break; 152 } 153 (0,_productions_helpers_js__WEBPACK_IMPORTED_MODULE_11__.autoParenter)(def).extAttrs = ea; 154 defs.push(def); 155 } 156 const eof = _productions_token_js__WEBPACK_IMPORTED_MODULE_12__.Eof.parse(tokeniser); 157 if (options.concrete) { 158 defs.push(eof); 159 } 160 return defs; 161 } 162 163 const res = definitions(); 164 if (tokeniser.position < source.length) error("Unrecognised tokens"); 165 return res; 166 } 167 168 /** 169 * @param {string} str 170 * @param {ParserOptions} [options] 171 */ 172 function parse(str, options = {}) { 173 const tokeniser = new _tokeniser_js__WEBPACK_IMPORTED_MODULE_0__.Tokeniser(str); 174 if (typeof options.sourceName !== "undefined") { 175 // @ts-ignore (See Tokeniser.source in supplement.d.ts) 176 tokeniser.source.name = options.sourceName; 177 } 178 return parseByTokens(tokeniser, options); 179 } 180 181 182 /***/ }), 183 /* 2 */ 184 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 185 186 __webpack_require__.r(__webpack_exports__); 187 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 188 /* harmony export */ Tokeniser: () => (/* binding */ Tokeniser), 189 /* harmony export */ WebIDLParseError: () => (/* binding */ WebIDLParseError), 190 /* harmony export */ argumentNameKeywords: () => (/* binding */ argumentNameKeywords), 191 /* harmony export */ stringTypes: () => (/* binding */ stringTypes), 192 /* harmony export */ typeNameKeywords: () => (/* binding */ typeNameKeywords) 193 /* harmony export */ }); 194 /* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3); 195 /* harmony import */ var _productions_helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); 196 197 198 199 // These regular expressions use the sticky flag so they will only match at 200 // the current location (ie. the offset of lastIndex). 201 const tokenRe = { 202 // This expression uses a lookahead assertion to catch false matches 203 // against integers early. 204 decimal: 205 /-?(?=[0-9]*\.|[0-9]+[eE])(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][-+]?[0-9]+)?|[0-9]+[Ee][-+]?[0-9]+)/y, 206 integer: /-?(0([Xx][0-9A-Fa-f]+|[0-7]*)|[1-9][0-9]*)/y, 207 identifier: /[_-]?[A-Za-z][0-9A-Z_a-z-]*/y, 208 string: /"[^"]*"/y, 209 whitespace: /[\t\n\r ]+/y, 210 comment: /\/\/.*|\/\*[\s\S]*?\*\//y, 211 other: /[^\t\n\r 0-9A-Za-z]/y, 212 }; 213 214 const typeNameKeywords = [ 215 "ArrayBuffer", 216 "SharedArrayBuffer", 217 "DataView", 218 "Int8Array", 219 "Int16Array", 220 "Int32Array", 221 "Uint8Array", 222 "Uint16Array", 223 "Uint32Array", 224 "Uint8ClampedArray", 225 "BigInt64Array", 226 "BigUint64Array", 227 "Float16Array", 228 "Float32Array", 229 "Float64Array", 230 "any", 231 "object", 232 "symbol", 233 ]; 234 235 const stringTypes = ["ByteString", "DOMString", "USVString"]; 236 237 const argumentNameKeywords = [ 238 "async", 239 "attribute", 240 "callback", 241 "const", 242 "constructor", 243 "deleter", 244 "dictionary", 245 "enum", 246 "getter", 247 "includes", 248 "inherit", 249 "interface", 250 "iterable", 251 "maplike", 252 "namespace", 253 "partial", 254 "required", 255 "setlike", 256 "setter", 257 "static", 258 "stringifier", 259 "typedef", 260 "unrestricted", 261 ]; 262 263 const nonRegexTerminals = [ 264 "-Infinity", 265 "FrozenArray", 266 "Infinity", 267 "NaN", 268 "ObservableArray", 269 "Promise", 270 "async_iterable", 271 "async_sequence", 272 "bigint", 273 "boolean", 274 "byte", 275 "double", 276 "false", 277 "float", 278 "long", 279 "mixin", 280 "null", 281 "octet", 282 "optional", 283 "or", 284 "readonly", 285 "record", 286 "sequence", 287 "short", 288 "true", 289 "undefined", 290 "unsigned", 291 "void", 292 ].concat(argumentNameKeywords, stringTypes, typeNameKeywords); 293 294 const punctuations = [ 295 "(", 296 ")", 297 ",", 298 "...", 299 ":", 300 ";", 301 "<", 302 "=", 303 ">", 304 "?", 305 "*", 306 "[", 307 "]", 308 "{", 309 "}", 310 ]; 311 312 const reserved = [ 313 // "constructor" is now a keyword 314 "_constructor", 315 "toString", 316 "_toString", 317 ]; 318 319 /** 320 * @typedef {ArrayItemType<ReturnType<typeof tokenise>>} Token 321 * @param {string} str 322 */ 323 function tokenise(str) { 324 const tokens = []; 325 let lastCharIndex = 0; 326 let trivia = ""; 327 let line = 1; 328 let index = 0; 329 while (lastCharIndex < str.length) { 330 const nextChar = str.charAt(lastCharIndex); 331 let result = -1; 332 333 if (/[\t\n\r ]/.test(nextChar)) { 334 result = attemptTokenMatch("whitespace", { noFlushTrivia: true }); 335 } else if (nextChar === "/") { 336 result = attemptTokenMatch("comment", { noFlushTrivia: true }); 337 } 338 339 if (result !== -1) { 340 const currentTrivia = tokens.pop().value; 341 line += (currentTrivia.match(/\n/g) || []).length; 342 trivia += currentTrivia; 343 index -= 1; 344 } else if (/[-0-9.A-Z_a-z]/.test(nextChar)) { 345 result = attemptTokenMatch("decimal"); 346 if (result === -1) { 347 result = attemptTokenMatch("integer"); 348 } 349 if (result === -1) { 350 result = attemptTokenMatch("identifier"); 351 const lastIndex = tokens.length - 1; 352 const token = tokens[lastIndex]; 353 if (result !== -1) { 354 if (reserved.includes(token.value)) { 355 const message = `${(0,_productions_helpers_js__WEBPACK_IMPORTED_MODULE_1__.unescape)( 356 token.value, 357 )} is a reserved identifier and must not be used.`; 358 throw new WebIDLParseError( 359 (0,_error_js__WEBPACK_IMPORTED_MODULE_0__.syntaxError)(tokens, lastIndex, null, message), 360 ); 361 } else if (nonRegexTerminals.includes(token.value)) { 362 token.type = "inline"; 363 } 364 } 365 } 366 } else if (nextChar === '"') { 367 result = attemptTokenMatch("string"); 368 } 369 370 for (const punctuation of punctuations) { 371 if (str.startsWith(punctuation, lastCharIndex)) { 372 tokens.push({ 373 type: "inline", 374 value: punctuation, 375 trivia, 376 line, 377 index, 378 }); 379 trivia = ""; 380 lastCharIndex += punctuation.length; 381 result = lastCharIndex; 382 break; 383 } 384 } 385 386 // other as the last try 387 if (result === -1) { 388 result = attemptTokenMatch("other"); 389 } 390 if (result === -1) { 391 throw new Error("Token stream not progressing"); 392 } 393 lastCharIndex = result; 394 index += 1; 395 } 396 397 // remaining trivia as eof 398 tokens.push({ 399 type: "eof", 400 value: "", 401 trivia, 402 line, 403 index, 404 }); 405 406 return tokens; 407 408 /** 409 * @param {keyof typeof tokenRe} type 410 * @param {object} options 411 * @param {boolean} [options.noFlushTrivia] 412 */ 413 function attemptTokenMatch(type, { noFlushTrivia } = {}) { 414 const re = tokenRe[type]; 415 re.lastIndex = lastCharIndex; 416 const result = re.exec(str); 417 if (result) { 418 tokens.push({ type, value: result[0], trivia, line, index }); 419 if (!noFlushTrivia) { 420 trivia = ""; 421 } 422 return re.lastIndex; 423 } 424 return -1; 425 } 426 } 427 428 class Tokeniser { 429 /** 430 * @param {string} idl 431 */ 432 constructor(idl) { 433 this.source = tokenise(idl); 434 this.position = 0; 435 } 436 437 /** 438 * @param {string} message 439 * @return {never} 440 */ 441 error(message) { 442 throw new WebIDLParseError( 443 (0,_error_js__WEBPACK_IMPORTED_MODULE_0__.syntaxError)(this.source, this.position, this.current, message), 444 ); 445 } 446 447 /** 448 * @param {string} type 449 */ 450 probeKind(type) { 451 return ( 452 this.source.length > this.position && 453 this.source[this.position].type === type 454 ); 455 } 456 457 /** 458 * @param {string} value 459 */ 460 probe(value) { 461 return ( 462 this.probeKind("inline") && this.source[this.position].value === value 463 ); 464 } 465 466 /** 467 * @param {...string} candidates 468 */ 469 consumeKind(...candidates) { 470 for (const type of candidates) { 471 if (!this.probeKind(type)) continue; 472 const token = this.source[this.position]; 473 this.position++; 474 return token; 475 } 476 } 477 478 /** 479 * @param {...string} candidates 480 */ 481 consume(...candidates) { 482 if (!this.probeKind("inline")) return; 483 const token = this.source[this.position]; 484 for (const value of candidates) { 485 if (token.value !== value) continue; 486 this.position++; 487 return token; 488 } 489 } 490 491 /** 492 * @param {string} value 493 */ 494 consumeIdentifier(value) { 495 if (!this.probeKind("identifier")) { 496 return; 497 } 498 if (this.source[this.position].value !== value) { 499 return; 500 } 501 return this.consumeKind("identifier"); 502 } 503 504 /** 505 * @param {number} position 506 */ 507 unconsume(position) { 508 this.position = position; 509 } 510 } 511 512 class WebIDLParseError extends Error { 513 /** 514 * @param {object} options 515 * @param {string} options.message 516 * @param {string} options.bareMessage 517 * @param {string} options.context 518 * @param {number} options.line 519 * @param {*} options.sourceName 520 * @param {string} options.input 521 * @param {*[]} options.tokens 522 */ 523 constructor({ 524 message, 525 bareMessage, 526 context, 527 line, 528 sourceName, 529 input, 530 tokens, 531 }) { 532 super(message); 533 534 this.name = "WebIDLParseError"; // not to be mangled 535 this.bareMessage = bareMessage; 536 this.context = context; 537 this.line = line; 538 this.sourceName = sourceName; 539 this.input = input; 540 this.tokens = tokens; 541 } 542 } 543 544 545 /***/ }), 546 /* 3 */ 547 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 548 549 __webpack_require__.r(__webpack_exports__); 550 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 551 /* harmony export */ syntaxError: () => (/* binding */ syntaxError), 552 /* harmony export */ validationError: () => (/* binding */ validationError) 553 /* harmony export */ }); 554 /** 555 * @param {string} text 556 */ 557 function lastLine(text) { 558 const splitted = text.split("\n"); 559 return splitted[splitted.length - 1]; 560 } 561 562 function appendIfExist(base, target) { 563 let result = base; 564 if (target) { 565 result += ` ${target}`; 566 } 567 return result; 568 } 569 570 function contextAsText(node) { 571 const hierarchy = [node]; 572 while (node && node.parent) { 573 const { parent } = node; 574 hierarchy.unshift(parent); 575 node = parent; 576 } 577 return hierarchy.map((n) => appendIfExist(n.type, n.name)).join(" -> "); 578 } 579 580 /** 581 * @typedef {object} WebIDL2ErrorOptions 582 * @property {"error" | "warning"} [level] 583 * @property {Function} [autofix] 584 * @property {string} [ruleName] 585 * 586 * @typedef {ReturnType<typeof error>} WebIDLErrorData 587 * 588 * @param {string} message error message 589 * @param {*} position 590 * @param {*} current 591 * @param {*} message 592 * @param {"Syntax" | "Validation"} kind error type 593 * @param {WebIDL2ErrorOptions=} options 594 */ 595 function error( 596 source, 597 position, 598 current, 599 message, 600 kind, 601 { level = "error", autofix, ruleName } = {}, 602 ) { 603 /** 604 * @param {number} count 605 */ 606 function sliceTokens(count) { 607 return count > 0 608 ? source.slice(position, position + count) 609 : source.slice(Math.max(position + count, 0), position); 610 } 611 612 /** 613 * @param {import("./tokeniser.js").Token[]} inputs 614 * @param {object} [options] 615 * @param {boolean} [options.precedes] 616 * @returns 617 */ 618 function tokensToText(inputs, { precedes } = {}) { 619 const text = inputs.map((t) => t.trivia + t.value).join(""); 620 const nextToken = source[position]; 621 if (nextToken.type === "eof") { 622 return text; 623 } 624 if (precedes) { 625 return text + nextToken.trivia; 626 } 627 return text.slice(nextToken.trivia.length); 628 } 629 630 const maxTokens = 5; // arbitrary but works well enough 631 const line = 632 source[position].type !== "eof" 633 ? source[position].line 634 : source.length > 1 635 ? source[position - 1].line 636 : 1; 637 638 const precedingLastLine = lastLine( 639 tokensToText(sliceTokens(-maxTokens), { precedes: true }), 640 ); 641 642 const subsequentTokens = sliceTokens(maxTokens); 643 const subsequentText = tokensToText(subsequentTokens); 644 const subsequentFirstLine = subsequentText.split("\n")[0]; 645 646 const spaced = " ".repeat(precedingLastLine.length) + "^"; 647 const sourceContext = precedingLastLine + subsequentFirstLine + "\n" + spaced; 648 649 const contextType = kind === "Syntax" ? "since" : "inside"; 650 const inSourceName = source.name ? ` in ${source.name}` : ""; 651 const grammaticalContext = 652 current && current.name 653 ? `, ${contextType} \`${current.partial ? "partial " : ""}${contextAsText( 654 current, 655 )}\`` 656 : ""; 657 const context = `${kind} error at line ${line}${inSourceName}${grammaticalContext}:\n${sourceContext}`; 658 return { 659 message: `${context} ${message}`, 660 bareMessage: message, 661 context, 662 line, 663 sourceName: source.name, 664 level, 665 ruleName, 666 autofix, 667 input: subsequentText, 668 tokens: subsequentTokens, 669 }; 670 } 671 672 /** 673 * @param {string} message error message 674 */ 675 function syntaxError(source, position, current, message) { 676 return error(source, position, current, message, "Syntax"); 677 } 678 679 /** 680 * @param {string} message error message 681 * @param {WebIDL2ErrorOptions} [options] 682 */ 683 function validationError( 684 token, 685 current, 686 ruleName, 687 message, 688 options = {}, 689 ) { 690 options.ruleName = ruleName; 691 return error( 692 current.source, 693 token.index, 694 current, 695 message, 696 "Validation", 697 options, 698 ); 699 } 700 701 702 /***/ }), 703 /* 4 */ 704 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 705 706 __webpack_require__.r(__webpack_exports__); 707 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 708 /* harmony export */ argument_list: () => (/* binding */ argument_list), 709 /* harmony export */ autoParenter: () => (/* binding */ autoParenter), 710 /* harmony export */ autofixAddExposedWindow: () => (/* binding */ autofixAddExposedWindow), 711 /* harmony export */ const_data: () => (/* binding */ const_data), 712 /* harmony export */ const_value: () => (/* binding */ const_value), 713 /* harmony export */ findLastIndex: () => (/* binding */ findLastIndex), 714 /* harmony export */ getFirstToken: () => (/* binding */ getFirstToken), 715 /* harmony export */ getLastIndentation: () => (/* binding */ getLastIndentation), 716 /* harmony export */ getMemberIndentation: () => (/* binding */ getMemberIndentation), 717 /* harmony export */ list: () => (/* binding */ list), 718 /* harmony export */ primitive_type: () => (/* binding */ primitive_type), 719 /* harmony export */ return_type: () => (/* binding */ return_type), 720 /* harmony export */ stringifier: () => (/* binding */ stringifier), 721 /* harmony export */ type_with_extended_attributes: () => (/* binding */ type_with_extended_attributes), 722 /* harmony export */ unescape: () => (/* binding */ unescape) 723 /* harmony export */ }); 724 /* harmony import */ var _type_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5); 725 /* harmony import */ var _argument_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(11); 726 /* harmony import */ var _extended_attributes_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(8); 727 /* harmony import */ var _operation_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(13); 728 /* harmony import */ var _attribute_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(14); 729 /* harmony import */ var _tokeniser_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(2); 730 731 732 733 734 735 736 737 /** 738 * @param {string} identifier 739 */ 740 function unescape(identifier) { 741 return identifier.startsWith("_") ? identifier.slice(1) : identifier; 742 } 743 744 /** 745 * Parses comma-separated list 746 * @param {import("../tokeniser.js").Tokeniser} tokeniser 747 * @param {object} args 748 * @param {Function} args.parser parser function for each item 749 * @param {boolean} [args.allowDangler] whether to allow dangling comma 750 * @param {string} [args.listName] the name to be shown on error messages 751 */ 752 function list(tokeniser, { parser, allowDangler, listName = "list" }) { 753 const first = parser(tokeniser); 754 if (!first) { 755 return []; 756 } 757 first.tokens.separator = tokeniser.consume(","); 758 const items = [first]; 759 while (first.tokens.separator) { 760 const item = parser(tokeniser); 761 if (!item) { 762 if (!allowDangler) { 763 tokeniser.error(`Trailing comma in ${listName}`); 764 } 765 break; 766 } 767 item.tokens.separator = tokeniser.consume(","); 768 items.push(item); 769 if (!item.tokens.separator) break; 770 } 771 return items; 772 } 773 774 /** 775 * @param {import("../tokeniser.js").Tokeniser} tokeniser 776 */ 777 function const_value(tokeniser) { 778 return ( 779 tokeniser.consumeKind("decimal", "integer") || 780 tokeniser.consume("true", "false", "Infinity", "-Infinity", "NaN") 781 ); 782 } 783 784 /** 785 * @param {object} token 786 * @param {string} token.type 787 * @param {string} token.value 788 */ 789 function const_data({ type, value }) { 790 switch (type) { 791 case "decimal": 792 case "integer": 793 return { type: "number", value }; 794 case "string": 795 return { type: "string", value: value.slice(1, -1) }; 796 } 797 798 switch (value) { 799 case "true": 800 case "false": 801 return { type: "boolean", value: value === "true" }; 802 case "Infinity": 803 case "-Infinity": 804 return { type: "Infinity", negative: value.startsWith("-") }; 805 case "[": 806 return { type: "sequence", value: [] }; 807 case "{": 808 return { type: "dictionary" }; 809 default: 810 return { type: value }; 811 } 812 } 813 814 /** 815 * @param {import("../tokeniser.js").Tokeniser} tokeniser 816 */ 817 function primitive_type(tokeniser) { 818 function integer_type() { 819 const prefix = tokeniser.consume("unsigned"); 820 const base = tokeniser.consume("short", "long"); 821 if (base) { 822 const postfix = tokeniser.consume("long"); 823 return new _type_js__WEBPACK_IMPORTED_MODULE_0__.Type({ source, tokens: { prefix, base, postfix } }); 824 } 825 if (prefix) tokeniser.error("Failed to parse integer type"); 826 } 827 828 function decimal_type() { 829 const prefix = tokeniser.consume("unrestricted"); 830 const base = tokeniser.consume("float", "double"); 831 if (base) { 832 return new _type_js__WEBPACK_IMPORTED_MODULE_0__.Type({ source, tokens: { prefix, base } }); 833 } 834 if (prefix) tokeniser.error("Failed to parse float type"); 835 } 836 837 const { source } = tokeniser; 838 const num_type = integer_type() || decimal_type(); 839 if (num_type) return num_type; 840 const base = tokeniser.consume( 841 "bigint", 842 "boolean", 843 "byte", 844 "octet", 845 "undefined", 846 ); 847 if (base) { 848 return new _type_js__WEBPACK_IMPORTED_MODULE_0__.Type({ source, tokens: { base } }); 849 } 850 } 851 852 /** 853 * @param {import("../tokeniser.js").Tokeniser} tokeniser 854 */ 855 function argument_list(tokeniser) { 856 return list(tokeniser, { 857 parser: _argument_js__WEBPACK_IMPORTED_MODULE_1__.Argument.parse, 858 listName: "arguments list", 859 }); 860 } 861 862 /** 863 * @param {import("../tokeniser.js").Tokeniser} tokeniser 864 * @param {string=} typeName (TODO: See Type.type for more details) 865 */ 866 function type_with_extended_attributes(tokeniser, typeName) { 867 const extAttrs = _extended_attributes_js__WEBPACK_IMPORTED_MODULE_2__.ExtendedAttributes.parse(tokeniser); 868 const ret = _type_js__WEBPACK_IMPORTED_MODULE_0__.Type.parse(tokeniser, typeName); 869 if (ret) autoParenter(ret).extAttrs = extAttrs; 870 return ret; 871 } 872 873 /** 874 * @param {import("../tokeniser.js").Tokeniser} tokeniser 875 * @param {string=} typeName (TODO: See Type.type for more details) 876 */ 877 function return_type(tokeniser, typeName) { 878 const typ = _type_js__WEBPACK_IMPORTED_MODULE_0__.Type.parse(tokeniser, typeName || "return-type"); 879 if (typ) { 880 return typ; 881 } 882 const voidToken = tokeniser.consume("void"); 883 if (voidToken) { 884 const ret = new _type_js__WEBPACK_IMPORTED_MODULE_0__.Type({ 885 source: tokeniser.source, 886 tokens: { base: voidToken }, 887 }); 888 ret.type = "return-type"; 889 return ret; 890 } 891 } 892 893 /** 894 * @param {import("../tokeniser.js").Tokeniser} tokeniser 895 */ 896 function stringifier(tokeniser) { 897 const special = tokeniser.consume("stringifier"); 898 if (!special) return; 899 const member = 900 _attribute_js__WEBPACK_IMPORTED_MODULE_4__.Attribute.parse(tokeniser, { special }) || 901 _operation_js__WEBPACK_IMPORTED_MODULE_3__.Operation.parse(tokeniser, { special }) || 902 tokeniser.error("Unterminated stringifier"); 903 return member; 904 } 905 906 /** 907 * @param {string} str 908 */ 909 function getLastIndentation(str) { 910 const lines = str.split("\n"); 911 // the first line visually binds to the preceding token 912 if (lines.length) { 913 const match = lines[lines.length - 1].match(/^\s+/); 914 if (match) { 915 return match[0]; 916 } 917 } 918 return ""; 919 } 920 921 /** 922 * @param {string} parentTrivia 923 */ 924 function getMemberIndentation(parentTrivia) { 925 const indentation = getLastIndentation(parentTrivia); 926 const indentCh = indentation.includes("\t") ? "\t" : " "; 927 return indentation + indentCh; 928 } 929 930 /** 931 * @param {import("./interface.js").Interface} def 932 */ 933 function autofixAddExposedWindow(def) { 934 return () => { 935 if (def.extAttrs.length) { 936 const tokeniser = new _tokeniser_js__WEBPACK_IMPORTED_MODULE_5__.Tokeniser("Exposed=Window,"); 937 const exposed = _extended_attributes_js__WEBPACK_IMPORTED_MODULE_2__.SimpleExtendedAttribute.parse(tokeniser); 938 exposed.tokens.separator = tokeniser.consume(","); 939 const existing = def.extAttrs[0]; 940 if (!/^\s/.test(existing.tokens.name.trivia)) { 941 existing.tokens.name.trivia = ` ${existing.tokens.name.trivia}`; 942 } 943 def.extAttrs.unshift(exposed); 944 } else { 945 autoParenter(def).extAttrs = _extended_attributes_js__WEBPACK_IMPORTED_MODULE_2__.ExtendedAttributes.parse( 946 new _tokeniser_js__WEBPACK_IMPORTED_MODULE_5__.Tokeniser("[Exposed=Window]"), 947 ); 948 const trivia = def.tokens.base.trivia; 949 def.extAttrs.tokens.open.trivia = trivia; 950 def.tokens.base.trivia = `\n${getLastIndentation(trivia)}`; 951 } 952 }; 953 } 954 955 /** 956 * Get the first syntax token for the given IDL object. 957 * @param {*} data 958 */ 959 function getFirstToken(data) { 960 if (data.extAttrs.length) { 961 return data.extAttrs.tokens.open; 962 } 963 if (data.type === "operation" && !data.special) { 964 return getFirstToken(data.idlType); 965 } 966 const tokens = Object.values(data.tokens).sort((x, y) => x.index - y.index); 967 return tokens[0]; 968 } 969 970 /** 971 * @template T 972 * @param {T[]} array 973 * @param {(item: T) => boolean} predicate 974 */ 975 function findLastIndex(array, predicate) { 976 const index = array.slice().reverse().findIndex(predicate); 977 if (index === -1) { 978 return index; 979 } 980 return array.length - index - 1; 981 } 982 983 /** 984 * Returns a proxy that auto-assign `parent` field. 985 * @template {Record<string | symbol, any>} T 986 * @param {T} data 987 * @param {*} [parent] The object that will be assigned to `parent`. 988 * If absent, it will be `data` by default. 989 * @return {T} 990 */ 991 function autoParenter(data, parent) { 992 if (!parent) { 993 // Defaults to `data` unless specified otherwise. 994 parent = data; 995 } 996 if (!data) { 997 // This allows `autoParenter(undefined)` which again allows 998 // `autoParenter(parse())` where the function may return nothing. 999 return data; 1000 } 1001 const proxy = new Proxy(data, { 1002 get(target, p) { 1003 const value = target[p]; 1004 if (Array.isArray(value) && p !== "source") { 1005 // Wraps the array so that any added items will also automatically 1006 // get their `parent` values. 1007 return autoParenter(value, target); 1008 } 1009 return value; 1010 }, 1011 set(target, p, value) { 1012 // @ts-ignore https://github.com/microsoft/TypeScript/issues/47357 1013 target[p] = value; 1014 if (!value) { 1015 return true; 1016 } else if (Array.isArray(value)) { 1017 // Assigning an array will add `parent` to its items. 1018 for (const item of value) { 1019 if (typeof item.parent !== "undefined") { 1020 item.parent = parent; 1021 } 1022 } 1023 } else if (typeof value.parent !== "undefined") { 1024 value.parent = parent; 1025 } 1026 return true; 1027 }, 1028 }); 1029 return proxy; 1030 } 1031 1032 1033 /***/ }), 1034 /* 5 */ 1035 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 1036 1037 __webpack_require__.r(__webpack_exports__); 1038 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 1039 /* harmony export */ Type: () => (/* binding */ Type) 1040 /* harmony export */ }); 1041 /* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); 1042 /* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); 1043 /* harmony import */ var _tokeniser_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2); 1044 /* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3); 1045 /* harmony import */ var _validators_helpers_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(7); 1046 /* harmony import */ var _extended_attributes_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(8); 1047 1048 1049 1050 1051 1052 1053 1054 /** 1055 * @param {import("../tokeniser.js").Tokeniser} tokeniser 1056 * @param {string} typeName 1057 */ 1058 function generic_type(tokeniser, typeName) { 1059 const base = tokeniser.consume( 1060 "FrozenArray", 1061 "ObservableArray", 1062 "Promise", 1063 "async_sequence", 1064 "sequence", 1065 "record", 1066 ); 1067 if (!base) { 1068 return; 1069 } 1070 const ret = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.autoParenter)( 1071 new Type({ source: tokeniser.source, tokens: { base } }), 1072 ); 1073 ret.tokens.open = 1074 tokeniser.consume("<") || 1075 tokeniser.error(`No opening bracket after ${base.value}`); 1076 switch (base.value) { 1077 case "Promise": { 1078 if (tokeniser.probe("[")) 1079 tokeniser.error("Promise type cannot have extended attribute"); 1080 const subtype = 1081 (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.return_type)(tokeniser, typeName) || 1082 tokeniser.error("Missing Promise subtype"); 1083 ret.subtype.push(subtype); 1084 break; 1085 } 1086 case "async_sequence": 1087 case "sequence": 1088 case "FrozenArray": 1089 case "ObservableArray": { 1090 const subtype = 1091 (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.type_with_extended_attributes)(tokeniser, typeName) || 1092 tokeniser.error(`Missing ${base.value} subtype`); 1093 ret.subtype.push(subtype); 1094 break; 1095 } 1096 case "record": { 1097 if (tokeniser.probe("[")) 1098 tokeniser.error("Record key cannot have extended attribute"); 1099 const keyType = 1100 tokeniser.consume(..._tokeniser_js__WEBPACK_IMPORTED_MODULE_2__.stringTypes) || 1101 tokeniser.error(`Record key must be one of: ${_tokeniser_js__WEBPACK_IMPORTED_MODULE_2__.stringTypes.join(", ")}`); 1102 const keyIdlType = new Type({ 1103 source: tokeniser.source, 1104 tokens: { base: keyType }, 1105 }); 1106 keyIdlType.tokens.separator = 1107 tokeniser.consume(",") || 1108 tokeniser.error("Missing comma after record key type"); 1109 keyIdlType.type = typeName; 1110 const valueType = 1111 (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.type_with_extended_attributes)(tokeniser, typeName) || 1112 tokeniser.error("Error parsing generic type record"); 1113 ret.subtype.push(keyIdlType, valueType); 1114 break; 1115 } 1116 } 1117 if (!ret.idlType) tokeniser.error(`Error parsing generic type ${base.value}`); 1118 ret.tokens.close = 1119 tokeniser.consume(">") || 1120 tokeniser.error(`Missing closing bracket after ${base.value}`); 1121 return ret.this; 1122 } 1123 1124 /** 1125 * @param {import("../tokeniser.js").Tokeniser} tokeniser 1126 */ 1127 function type_suffix(tokeniser, obj) { 1128 const nullable = tokeniser.consume("?"); 1129 if (nullable) { 1130 obj.tokens.nullable = nullable; 1131 } 1132 if (tokeniser.probe("?")) tokeniser.error("Can't nullable more than once"); 1133 } 1134 1135 /** 1136 * @param {import("../tokeniser.js").Tokeniser} tokeniser 1137 * @param {string} typeName 1138 */ 1139 function single_type(tokeniser, typeName) { 1140 let ret = generic_type(tokeniser, typeName) || (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.primitive_type)(tokeniser); 1141 if (!ret) { 1142 const base = 1143 tokeniser.consumeKind("identifier") || 1144 tokeniser.consume(..._tokeniser_js__WEBPACK_IMPORTED_MODULE_2__.stringTypes, ..._tokeniser_js__WEBPACK_IMPORTED_MODULE_2__.typeNameKeywords); 1145 if (!base) { 1146 return; 1147 } 1148 ret = new Type({ source: tokeniser.source, tokens: { base } }); 1149 if (tokeniser.probe("<")) 1150 tokeniser.error(`Unsupported generic type ${base.value}`); 1151 } 1152 if (ret.generic === "Promise" && tokeniser.probe("?")) { 1153 tokeniser.error("Promise type cannot be nullable"); 1154 } 1155 ret.type = typeName || null; 1156 type_suffix(tokeniser, ret); 1157 if (ret.nullable && ret.idlType === "any") 1158 tokeniser.error("Type `any` cannot be made nullable"); 1159 return ret; 1160 } 1161 1162 /** 1163 * @param {import("../tokeniser.js").Tokeniser} tokeniser 1164 * @param {string} type 1165 */ 1166 function union_type(tokeniser, type) { 1167 const tokens = {}; 1168 tokens.open = tokeniser.consume("("); 1169 if (!tokens.open) return; 1170 const ret = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.autoParenter)(new Type({ source: tokeniser.source, tokens })); 1171 ret.type = type || null; 1172 while (true) { 1173 const typ = 1174 (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.type_with_extended_attributes)(tokeniser, type) || 1175 tokeniser.error("No type after open parenthesis or 'or' in union type"); 1176 if (typ.idlType === "any") 1177 tokeniser.error("Type `any` cannot be included in a union type"); 1178 if (typ.generic === "Promise") 1179 tokeniser.error("Type `Promise` cannot be included in a union type"); 1180 ret.subtype.push(typ); 1181 const or = tokeniser.consume("or"); 1182 if (or) { 1183 typ.tokens.separator = or; 1184 } else break; 1185 } 1186 if (ret.idlType.length < 2) { 1187 tokeniser.error( 1188 "At least two types are expected in a union type but found less", 1189 ); 1190 } 1191 tokens.close = 1192 tokeniser.consume(")") || tokeniser.error("Unterminated union type"); 1193 type_suffix(tokeniser, ret); 1194 return ret.this; 1195 } 1196 1197 class Type extends _base_js__WEBPACK_IMPORTED_MODULE_0__.Base { 1198 /** 1199 * @param {import("../tokeniser.js").Tokeniser} tokeniser 1200 * @param {string} typeName 1201 */ 1202 static parse(tokeniser, typeName) { 1203 return single_type(tokeniser, typeName) || union_type(tokeniser, typeName); 1204 } 1205 1206 constructor({ source, tokens }) { 1207 super({ source, tokens }); 1208 Object.defineProperty(this, "subtype", { value: [], writable: true }); 1209 this.extAttrs = new _extended_attributes_js__WEBPACK_IMPORTED_MODULE_5__.ExtendedAttributes({ source, tokens: {} }); 1210 } 1211 1212 get generic() { 1213 if (this.subtype.length && this.tokens.base) { 1214 return this.tokens.base.value; 1215 } 1216 return ""; 1217 } 1218 get nullable() { 1219 return Boolean(this.tokens.nullable); 1220 } 1221 get union() { 1222 return Boolean(this.subtype.length) && !this.tokens.base; 1223 } 1224 get idlType() { 1225 if (this.subtype.length) { 1226 return this.subtype; 1227 } 1228 // Adding prefixes/postfixes for "unrestricted float", etc. 1229 const name = [this.tokens.prefix, this.tokens.base, this.tokens.postfix] 1230 .filter((t) => t) 1231 .map((t) => t.value) 1232 .join(" "); 1233 return (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.unescape)(name); 1234 } 1235 1236 *validate(defs) { 1237 yield* this.extAttrs.validate(defs); 1238 1239 if (this.idlType === "BufferSource") { 1240 // XXX: For now this is a hack. Consider moving parents' extAttrs into types as the spec says: 1241 // https://webidl.spec.whatwg.org/#idl-annotated-types 1242 for (const extAttrs of [this.extAttrs, this.parent?.extAttrs]) { 1243 for (const extAttr of extAttrs) { 1244 if (extAttr.name !== "AllowShared") { 1245 continue; 1246 } 1247 const message = `\`[AllowShared] BufferSource\` is now replaced with AllowSharedBufferSource.`; 1248 yield (0,_error_js__WEBPACK_IMPORTED_MODULE_3__.validationError)( 1249 this.tokens.base, 1250 this, 1251 "migrate-allowshared", 1252 message, 1253 { autofix: replaceAllowShared(this, extAttr, extAttrs) }, 1254 ); 1255 } 1256 } 1257 } 1258 1259 if (this.idlType === "void") { 1260 const message = `\`void\` is now replaced by \`undefined\`. Refer to the \ 1261 [relevant GitHub issue](https://github.com/whatwg/webidl/issues/60) \ 1262 for more information.`; 1263 yield (0,_error_js__WEBPACK_IMPORTED_MODULE_3__.validationError)(this.tokens.base, this, "replace-void", message, { 1264 autofix: replaceVoid(this), 1265 }); 1266 } 1267 1268 /* 1269 * If a union is nullable, its subunions cannot include a dictionary 1270 * If not, subunions may include dictionaries if each union is not nullable 1271 */ 1272 const typedef = !this.union && defs.unique.get(this.idlType); 1273 const target = this.union 1274 ? this 1275 : typedef && typedef.type === "typedef" 1276 ? typedef.idlType 1277 : undefined; 1278 if (target && this.nullable) { 1279 // do not allow any dictionary 1280 const { reference } = (0,_validators_helpers_js__WEBPACK_IMPORTED_MODULE_4__.idlTypeIncludesDictionary)(target, defs) || {}; 1281 if (reference) { 1282 const targetToken = (this.union ? reference : this).tokens.base; 1283 const message = "Nullable union cannot include a dictionary type."; 1284 yield (0,_error_js__WEBPACK_IMPORTED_MODULE_3__.validationError)( 1285 targetToken, 1286 this, 1287 "no-nullable-union-dict", 1288 message, 1289 ); 1290 } 1291 } else { 1292 // allow some dictionary 1293 for (const subtype of this.subtype) { 1294 yield* subtype.validate(defs); 1295 } 1296 } 1297 } 1298 1299 /** @param {import("../writer.js").Writer} w */ 1300 write(w) { 1301 const type_body = () => { 1302 if (this.union || this.generic) { 1303 return w.ts.wrap([ 1304 w.token(this.tokens.base, w.ts.generic), 1305 w.token(this.tokens.open), 1306 ...this.subtype.map((t) => t.write(w)), 1307 w.token(this.tokens.close), 1308 ]); 1309 } 1310 const firstToken = this.tokens.prefix || this.tokens.base; 1311 const prefix = this.tokens.prefix 1312 ? [this.tokens.prefix.value, w.ts.trivia(this.tokens.base.trivia)] 1313 : []; 1314 const ref = w.reference( 1315 w.ts.wrap([ 1316 ...prefix, 1317 this.tokens.base.value, 1318 w.token(this.tokens.postfix), 1319 ]), 1320 { 1321 unescaped: /** @type {string} (because it's not union) */ ( 1322 this.idlType 1323 ), 1324 context: this, 1325 }, 1326 ); 1327 return w.ts.wrap([w.ts.trivia(firstToken.trivia), ref]); 1328 }; 1329 return w.ts.wrap([ 1330 this.extAttrs.write(w), 1331 type_body(), 1332 w.token(this.tokens.nullable), 1333 w.token(this.tokens.separator), 1334 ]); 1335 } 1336 } 1337 1338 /** 1339 * @param {Type} type 1340 * @param {import("./extended-attributes.js").SimpleExtendedAttribute} extAttr 1341 * @param {ExtendedAttributes} extAttrs 1342 */ 1343 function replaceAllowShared(type, extAttr, extAttrs) { 1344 return () => { 1345 const index = extAttrs.indexOf(extAttr); 1346 extAttrs.splice(index, 1); 1347 if (!extAttrs.length && type.tokens.base.trivia.match(/^\s$/)) { 1348 type.tokens.base.trivia = ""; // (let's not remove comments) 1349 } 1350 1351 type.tokens.base.value = "AllowSharedBufferSource"; 1352 }; 1353 } 1354 1355 /** 1356 * @param {Type} type 1357 */ 1358 function replaceVoid(type) { 1359 return () => { 1360 type.tokens.base.value = "undefined"; 1361 }; 1362 } 1363 1364 1365 /***/ }), 1366 /* 6 */ 1367 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 1368 1369 __webpack_require__.r(__webpack_exports__); 1370 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 1371 /* harmony export */ Base: () => (/* binding */ Base) 1372 /* harmony export */ }); 1373 class Base { 1374 /** 1375 * @param {object} initializer 1376 * @param {Base["source"]} initializer.source 1377 * @param {Base["tokens"]} initializer.tokens 1378 */ 1379 constructor({ source, tokens }) { 1380 Object.defineProperties(this, { 1381 source: { value: source }, 1382 tokens: { value: tokens, writable: true }, 1383 parent: { value: null, writable: true }, 1384 this: { value: this }, // useful when escaping from proxy 1385 }); 1386 } 1387 1388 toJSON() { 1389 const json = { type: undefined, name: undefined, inheritance: undefined }; 1390 let proto = this; 1391 while (proto !== Object.prototype) { 1392 const descMap = Object.getOwnPropertyDescriptors(proto); 1393 for (const [key, value] of Object.entries(descMap)) { 1394 if (value.enumerable || value.get) { 1395 // @ts-ignore - allow indexing here 1396 json[key] = this[key]; 1397 } 1398 } 1399 proto = Object.getPrototypeOf(proto); 1400 } 1401 return json; 1402 } 1403 } 1404 1405 1406 /***/ }), 1407 /* 7 */ 1408 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 1409 1410 __webpack_require__.r(__webpack_exports__); 1411 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 1412 /* harmony export */ dictionaryIncludesRequiredField: () => (/* binding */ dictionaryIncludesRequiredField), 1413 /* harmony export */ idlTypeIncludesDictionary: () => (/* binding */ idlTypeIncludesDictionary), 1414 /* harmony export */ idlTypeIncludesEnforceRange: () => (/* binding */ idlTypeIncludesEnforceRange) 1415 /* harmony export */ }); 1416 /** 1417 * @typedef {import("../validator.js").Definitions} Definitions 1418 * @typedef {import("../productions/dictionary.js").Dictionary} Dictionary 1419 * @typedef {import("../../lib/productions/type").Type} Type 1420 * 1421 * @param {Type} idlType 1422 * @param {Definitions} defs 1423 * @param {object} [options] 1424 * @param {boolean} [options.useNullableInner] use when the input idlType is nullable and you want to use its inner type 1425 * @return {{ reference: *, dictionary: Dictionary }} the type reference that ultimately includes dictionary. 1426 */ 1427 function idlTypeIncludesDictionary( 1428 idlType, 1429 defs, 1430 { useNullableInner } = {}, 1431 ) { 1432 if (!idlType.union) { 1433 const def = defs.unique.get(idlType.idlType); 1434 if (!def) { 1435 return; 1436 } 1437 if (def.type === "typedef") { 1438 const { typedefIncludesDictionary } = defs.cache; 1439 if (typedefIncludesDictionary.has(def)) { 1440 // Note that this also halts when it met indeterminate state 1441 // to prevent infinite recursion 1442 return typedefIncludesDictionary.get(def); 1443 } 1444 defs.cache.typedefIncludesDictionary.set(def, undefined); // indeterminate state 1445 const result = idlTypeIncludesDictionary(def.idlType, defs); 1446 defs.cache.typedefIncludesDictionary.set(def, result); 1447 if (result) { 1448 return { 1449 reference: idlType, 1450 dictionary: result.dictionary, 1451 }; 1452 } 1453 } 1454 if (def.type === "dictionary" && (useNullableInner || !idlType.nullable)) { 1455 return { 1456 reference: idlType, 1457 dictionary: def, 1458 }; 1459 } 1460 } 1461 for (const subtype of idlType.subtype) { 1462 const result = idlTypeIncludesDictionary(subtype, defs); 1463 if (result) { 1464 if (subtype.union) { 1465 return result; 1466 } 1467 return { 1468 reference: subtype, 1469 dictionary: result.dictionary, 1470 }; 1471 } 1472 } 1473 } 1474 1475 /** 1476 * @param {Dictionary} dict dictionary type 1477 * @param {Definitions} defs 1478 * @return {boolean} 1479 */ 1480 function dictionaryIncludesRequiredField(dict, defs) { 1481 if (defs.cache.dictionaryIncludesRequiredField.has(dict)) { 1482 return defs.cache.dictionaryIncludesRequiredField.get(dict); 1483 } 1484 // Set cached result to indeterminate to short-circuit circular definitions. 1485 // The final result will be updated to true or false. 1486 defs.cache.dictionaryIncludesRequiredField.set(dict, undefined); 1487 let result = dict.members.some((field) => field.required); 1488 if (!result && dict.inheritance) { 1489 const superdict = defs.unique.get(dict.inheritance); 1490 if (!superdict) { 1491 // Assume required members in the supertype if it is unknown. 1492 result = true; 1493 } else if (dictionaryIncludesRequiredField(superdict, defs)) { 1494 result = true; 1495 } 1496 } 1497 defs.cache.dictionaryIncludesRequiredField.set(dict, result); 1498 return result; 1499 } 1500 1501 /** 1502 * For now this only checks the most frequent cases: 1503 * 1. direct inclusion of [EnforceRange] 1504 * 2. typedef of that 1505 * 1506 * More complex cases with dictionaries and records are not covered yet. 1507 * 1508 * @param {Type} idlType 1509 * @param {Definitions} defs 1510 */ 1511 function idlTypeIncludesEnforceRange(idlType, defs) { 1512 if (idlType.union) { 1513 // TODO: This should ideally be checked too 1514 return false; 1515 } 1516 1517 if (idlType.extAttrs.some((e) => e.name === "EnforceRange")) { 1518 return true; 1519 } 1520 1521 const def = defs.unique.get(idlType.idlType); 1522 if (def?.type !== "typedef") { 1523 return false; 1524 } 1525 1526 return def.idlType.extAttrs.some((e) => e.name === "EnforceRange"); 1527 } 1528 1529 1530 /***/ }), 1531 /* 8 */ 1532 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 1533 1534 __webpack_require__.r(__webpack_exports__); 1535 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 1536 /* harmony export */ ExtendedAttributeParameters: () => (/* binding */ ExtendedAttributeParameters), 1537 /* harmony export */ ExtendedAttributes: () => (/* binding */ ExtendedAttributes), 1538 /* harmony export */ SimpleExtendedAttribute: () => (/* binding */ SimpleExtendedAttribute) 1539 /* harmony export */ }); 1540 /* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); 1541 /* harmony import */ var _array_base_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9); 1542 /* harmony import */ var _token_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(10); 1543 /* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4); 1544 /* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(3); 1545 1546 1547 1548 1549 1550 1551 /** 1552 * @param {import("../tokeniser.js").Tokeniser} tokeniser 1553 * @param {string} tokenName 1554 */ 1555 function tokens(tokeniser, tokenName) { 1556 return (0,_helpers_js__WEBPACK_IMPORTED_MODULE_3__.list)(tokeniser, { 1557 parser: _token_js__WEBPACK_IMPORTED_MODULE_2__.WrappedToken.parser(tokeniser, tokenName), 1558 listName: tokenName + " list", 1559 }); 1560 } 1561 1562 const extAttrValueSyntax = ["identifier", "decimal", "integer", "string"]; 1563 1564 const shouldBeLegacyPrefixed = [ 1565 "NoInterfaceObject", 1566 "LenientSetter", 1567 "LenientThis", 1568 "TreatNonObjectAsNull", 1569 "Unforgeable", 1570 ]; 1571 1572 const renamedLegacies = new Map([ 1573 .../** @type {[string, string][]} */ ( 1574 shouldBeLegacyPrefixed.map((name) => [name, `Legacy${name}`]) 1575 ), 1576 ["NamedConstructor", "LegacyFactoryFunction"], 1577 ["OverrideBuiltins", "LegacyOverrideBuiltIns"], 1578 ["TreatNullAs", "LegacyNullToEmptyString"], 1579 ]); 1580 1581 /** 1582 * This will allow a set of extended attribute values to be parsed. 1583 * @param {import("../tokeniser.js").Tokeniser} tokeniser 1584 */ 1585 function extAttrListItems(tokeniser) { 1586 for (const syntax of extAttrValueSyntax) { 1587 const toks = tokens(tokeniser, syntax); 1588 if (toks.length) { 1589 return toks; 1590 } 1591 } 1592 tokeniser.error( 1593 `Expected identifiers, strings, decimals, or integers but none found`, 1594 ); 1595 } 1596 1597 class ExtendedAttributeParameters extends _base_js__WEBPACK_IMPORTED_MODULE_0__.Base { 1598 /** 1599 * @param {import("../tokeniser.js").Tokeniser} tokeniser 1600 */ 1601 static parse(tokeniser) { 1602 const tokens = { assign: tokeniser.consume("=") }; 1603 const ret = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_3__.autoParenter)( 1604 new ExtendedAttributeParameters({ source: tokeniser.source, tokens }), 1605 ); 1606 ret.list = []; 1607 if (tokens.assign) { 1608 tokens.asterisk = tokeniser.consume("*"); 1609 if (tokens.asterisk) { 1610 return ret.this; 1611 } 1612 tokens.secondaryName = tokeniser.consumeKind(...extAttrValueSyntax); 1613 } 1614 tokens.open = tokeniser.consume("("); 1615 if (tokens.open) { 1616 ret.list = ret.rhsIsList 1617 ? // [Exposed=(Window,Worker)] 1618 extAttrListItems(tokeniser) 1619 : // [LegacyFactoryFunction=Audio(DOMString src)] or [Constructor(DOMString str)] 1620 (0,_helpers_js__WEBPACK_IMPORTED_MODULE_3__.argument_list)(tokeniser); 1621 tokens.close = 1622 tokeniser.consume(")") || 1623 tokeniser.error("Unexpected token in extended attribute argument list"); 1624 } else if (tokens.assign && !tokens.secondaryName) { 1625 tokeniser.error("No right hand side to extended attribute assignment"); 1626 } 1627 return ret.this; 1628 } 1629 1630 get rhsIsList() { 1631 return ( 1632 this.tokens.assign && !this.tokens.asterisk && !this.tokens.secondaryName 1633 ); 1634 } 1635 1636 get rhsType() { 1637 if (this.rhsIsList) { 1638 return this.list[0].tokens.value.type + "-list"; 1639 } 1640 if (this.tokens.asterisk) { 1641 return "*"; 1642 } 1643 if (this.tokens.secondaryName) { 1644 return this.tokens.secondaryName.type; 1645 } 1646 return null; 1647 } 1648 1649 /** @param {import("../writer.js").Writer} w */ 1650 write(w) { 1651 const { rhsType } = this; 1652 return w.ts.wrap([ 1653 w.token(this.tokens.assign), 1654 w.token(this.tokens.asterisk), 1655 w.reference_token(this.tokens.secondaryName, this.parent), 1656 w.token(this.tokens.open), 1657 ...this.list.map((p) => { 1658 return rhsType === "identifier-list" 1659 ? w.identifier(p, this.parent) 1660 : p.write(w); 1661 }), 1662 w.token(this.tokens.close), 1663 ]); 1664 } 1665 } 1666 1667 class SimpleExtendedAttribute extends _base_js__WEBPACK_IMPORTED_MODULE_0__.Base { 1668 /** 1669 * @param {import("../tokeniser.js").Tokeniser} tokeniser 1670 */ 1671 static parse(tokeniser) { 1672 const name = tokeniser.consumeKind("identifier"); 1673 if (name) { 1674 return new SimpleExtendedAttribute({ 1675 source: tokeniser.source, 1676 tokens: { name }, 1677 params: ExtendedAttributeParameters.parse(tokeniser), 1678 }); 1679 } 1680 } 1681 1682 constructor({ source, tokens, params }) { 1683 super({ source, tokens }); 1684 params.parent = this; 1685 Object.defineProperty(this, "params", { value: params }); 1686 } 1687 1688 get type() { 1689 return "extended-attribute"; 1690 } 1691 get name() { 1692 return this.tokens.name.value; 1693 } 1694 get rhs() { 1695 const { rhsType: type, tokens, list } = this.params; 1696 if (!type) { 1697 return null; 1698 } 1699 const value = this.params.rhsIsList 1700 ? list 1701 : this.params.tokens.secondaryName 1702 ? (0,_helpers_js__WEBPACK_IMPORTED_MODULE_3__.unescape)(tokens.secondaryName.value) 1703 : null; 1704 return { type, value }; 1705 } 1706 get arguments() { 1707 const { rhsIsList, list } = this.params; 1708 if (!list || rhsIsList) { 1709 return []; 1710 } 1711 return list; 1712 } 1713 1714 *validate(defs) { 1715 const { name } = this; 1716 if (name === "LegacyNoInterfaceObject") { 1717 const message = `\`[LegacyNoInterfaceObject]\` extended attribute is an \ 1718 undesirable feature that may be removed from Web IDL in the future. Refer to the \ 1719 [relevant upstream PR](https://github.com/whatwg/webidl/pull/609) for more \ 1720 information.`; 1721 yield (0,_error_js__WEBPACK_IMPORTED_MODULE_4__.validationError)( 1722 this.tokens.name, 1723 this, 1724 "no-nointerfaceobject", 1725 message, 1726 { level: "warning" }, 1727 ); 1728 } else if (renamedLegacies.has(name)) { 1729 const message = `\`[${name}]\` extended attribute is a legacy feature \ 1730 that is now renamed to \`[${renamedLegacies.get(name)}]\`. Refer to the \ 1731 [relevant upstream PR](https://github.com/whatwg/webidl/pull/870) for more \ 1732 information.`; 1733 yield (0,_error_js__WEBPACK_IMPORTED_MODULE_4__.validationError)(this.tokens.name, this, "renamed-legacy", message, { 1734 level: "warning", 1735 autofix: renameLegacyExtendedAttribute(this), 1736 }); 1737 } 1738 for (const arg of this.arguments) { 1739 yield* arg.validate(defs); 1740 } 1741 } 1742 1743 /** @param {import("../writer.js").Writer} w */ 1744 write(w) { 1745 return w.ts.wrap([ 1746 w.ts.trivia(this.tokens.name.trivia), 1747 w.ts.extendedAttribute( 1748 w.ts.wrap([ 1749 w.ts.extendedAttributeReference(this.name), 1750 this.params.write(w), 1751 ]), 1752 ), 1753 w.token(this.tokens.separator), 1754 ]); 1755 } 1756 } 1757 1758 /** 1759 * @param {SimpleExtendedAttribute} extAttr 1760 */ 1761 function renameLegacyExtendedAttribute(extAttr) { 1762 return () => { 1763 const { name } = extAttr; 1764 extAttr.tokens.name.value = renamedLegacies.get(name); 1765 if (name === "TreatNullAs") { 1766 extAttr.params.tokens = {}; 1767 } 1768 }; 1769 } 1770 1771 // Note: we parse something simpler than the official syntax. It's all that ever 1772 // seems to be used 1773 class ExtendedAttributes extends _array_base_js__WEBPACK_IMPORTED_MODULE_1__.ArrayBase { 1774 /** 1775 * @param {import("../tokeniser.js").Tokeniser} tokeniser 1776 */ 1777 static parse(tokeniser) { 1778 const tokens = {}; 1779 tokens.open = tokeniser.consume("["); 1780 const ret = new ExtendedAttributes({ source: tokeniser.source, tokens }); 1781 if (!tokens.open) return ret; 1782 ret.push( 1783 ...(0,_helpers_js__WEBPACK_IMPORTED_MODULE_3__.list)(tokeniser, { 1784 parser: SimpleExtendedAttribute.parse, 1785 listName: "extended attribute", 1786 }), 1787 ); 1788 tokens.close = 1789 tokeniser.consume("]") || 1790 tokeniser.error( 1791 "Expected a closing token for the extended attribute list", 1792 ); 1793 if (!ret.length) { 1794 tokeniser.unconsume(tokens.close.index); 1795 tokeniser.error("An extended attribute list must not be empty"); 1796 } 1797 if (tokeniser.probe("[")) { 1798 tokeniser.error( 1799 "Illegal double extended attribute lists, consider merging them", 1800 ); 1801 } 1802 return ret; 1803 } 1804 1805 *validate(defs) { 1806 for (const extAttr of this) { 1807 yield* extAttr.validate(defs); 1808 } 1809 } 1810 1811 /** @param {import("../writer.js").Writer} w */ 1812 write(w) { 1813 if (!this.length) return ""; 1814 return w.ts.wrap([ 1815 w.token(this.tokens.open), 1816 ...this.map((ea) => ea.write(w)), 1817 w.token(this.tokens.close), 1818 ]); 1819 } 1820 } 1821 1822 1823 /***/ }), 1824 /* 9 */ 1825 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 1826 1827 __webpack_require__.r(__webpack_exports__); 1828 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 1829 /* harmony export */ ArrayBase: () => (/* binding */ ArrayBase) 1830 /* harmony export */ }); 1831 class ArrayBase extends Array { 1832 constructor({ source, tokens }) { 1833 super(); 1834 Object.defineProperties(this, { 1835 source: { value: source }, 1836 tokens: { value: tokens }, 1837 parent: { value: null, writable: true }, 1838 }); 1839 } 1840 } 1841 1842 1843 /***/ }), 1844 /* 10 */ 1845 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 1846 1847 __webpack_require__.r(__webpack_exports__); 1848 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 1849 /* harmony export */ Eof: () => (/* binding */ Eof), 1850 /* harmony export */ WrappedToken: () => (/* binding */ WrappedToken) 1851 /* harmony export */ }); 1852 /* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); 1853 /* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); 1854 1855 1856 1857 class WrappedToken extends _base_js__WEBPACK_IMPORTED_MODULE_0__.Base { 1858 /** 1859 * @param {import("../tokeniser.js").Tokeniser} tokeniser 1860 * @param {string} type 1861 */ 1862 static parser(tokeniser, type) { 1863 return () => { 1864 const value = tokeniser.consumeKind(type); 1865 if (value) { 1866 return new WrappedToken({ 1867 source: tokeniser.source, 1868 tokens: { value }, 1869 }); 1870 } 1871 }; 1872 } 1873 1874 get type() { 1875 return this.tokens.value.type; 1876 } 1877 1878 get value() { 1879 return (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.unescape)(this.tokens.value.value); 1880 } 1881 1882 /** @param {import("../writer.js").Writer} w */ 1883 write(w) { 1884 return w.ts.wrap([ 1885 w.token(this.tokens.value), 1886 w.token(this.tokens.separator), 1887 ]); 1888 } 1889 } 1890 1891 class Eof extends WrappedToken { 1892 /** 1893 * @param {import("../tokeniser.js").Tokeniser} tokeniser 1894 */ 1895 static parse(tokeniser) { 1896 const value = tokeniser.consumeKind("eof"); 1897 if (value) { 1898 return new Eof({ source: tokeniser.source, tokens: { value } }); 1899 } 1900 } 1901 1902 get type() { 1903 return "eof"; 1904 } 1905 } 1906 1907 1908 /***/ }), 1909 /* 11 */ 1910 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 1911 1912 __webpack_require__.r(__webpack_exports__); 1913 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 1914 /* harmony export */ Argument: () => (/* binding */ Argument) 1915 /* harmony export */ }); 1916 /* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); 1917 /* harmony import */ var _default_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); 1918 /* harmony import */ var _extended_attributes_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(8); 1919 /* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4); 1920 /* harmony import */ var _tokeniser_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(2); 1921 /* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(3); 1922 /* harmony import */ var _validators_helpers_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(7); 1923 1924 1925 1926 1927 1928 1929 1930 1931 class Argument extends _base_js__WEBPACK_IMPORTED_MODULE_0__.Base { 1932 /** 1933 * @param {import("../tokeniser.js").Tokeniser} tokeniser 1934 */ 1935 static parse(tokeniser) { 1936 const start_position = tokeniser.position; 1937 /** @type {Base["tokens"]} */ 1938 const tokens = {}; 1939 const ret = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_3__.autoParenter)( 1940 new Argument({ source: tokeniser.source, tokens }), 1941 ); 1942 ret.extAttrs = _extended_attributes_js__WEBPACK_IMPORTED_MODULE_2__.ExtendedAttributes.parse(tokeniser); 1943 tokens.optional = tokeniser.consume("optional"); 1944 ret.idlType = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_3__.type_with_extended_attributes)(tokeniser, "argument-type"); 1945 if (!ret.idlType) { 1946 return tokeniser.unconsume(start_position); 1947 } 1948 if (!tokens.optional) { 1949 tokens.variadic = tokeniser.consume("..."); 1950 } 1951 tokens.name = 1952 tokeniser.consumeKind("identifier") || 1953 tokeniser.consume(..._tokeniser_js__WEBPACK_IMPORTED_MODULE_4__.argumentNameKeywords); 1954 if (!tokens.name) { 1955 return tokeniser.unconsume(start_position); 1956 } 1957 ret.default = tokens.optional ? _default_js__WEBPACK_IMPORTED_MODULE_1__.Default.parse(tokeniser) : null; 1958 return ret.this; 1959 } 1960 1961 get type() { 1962 return "argument"; 1963 } 1964 get optional() { 1965 return !!this.tokens.optional; 1966 } 1967 get variadic() { 1968 return !!this.tokens.variadic; 1969 } 1970 get name() { 1971 return (0,_helpers_js__WEBPACK_IMPORTED_MODULE_3__.unescape)(this.tokens.name.value); 1972 } 1973 1974 /** 1975 * @param {import("../validator.js").Definitions} defs 1976 */ 1977 *validate(defs) { 1978 yield* this.extAttrs.validate(defs); 1979 yield* this.idlType.validate(defs); 1980 const result = (0,_validators_helpers_js__WEBPACK_IMPORTED_MODULE_6__.idlTypeIncludesDictionary)(this.idlType, defs, { 1981 useNullableInner: true, 1982 }); 1983 if (result) { 1984 if (this.idlType.nullable) { 1985 const message = `Dictionary arguments cannot be nullable.`; 1986 yield (0,_error_js__WEBPACK_IMPORTED_MODULE_5__.validationError)( 1987 this.tokens.name, 1988 this, 1989 "no-nullable-dict-arg", 1990 message, 1991 ); 1992 } else if (!this.optional) { 1993 if ( 1994 this.parent && 1995 !(0,_validators_helpers_js__WEBPACK_IMPORTED_MODULE_6__.dictionaryIncludesRequiredField)(result.dictionary, defs) && 1996 isLastRequiredArgument(this) 1997 ) { 1998 const message = `Dictionary argument must be optional if it has no required fields`; 1999 yield (0,_error_js__WEBPACK_IMPORTED_MODULE_5__.validationError)( 2000 this.tokens.name, 2001 this, 2002 "dict-arg-optional", 2003 message, 2004 { 2005 autofix: autofixDictionaryArgumentOptionality(this), 2006 }, 2007 ); 2008 } 2009 } else if (!this.default) { 2010 const message = `Optional dictionary arguments must have a default value of \`{}\`.`; 2011 yield (0,_error_js__WEBPACK_IMPORTED_MODULE_5__.validationError)( 2012 this.tokens.name, 2013 this, 2014 "dict-arg-default", 2015 message, 2016 { 2017 autofix: autofixOptionalDictionaryDefaultValue(this), 2018 }, 2019 ); 2020 } 2021 } 2022 } 2023 2024 /** @param {import("../writer.js").Writer} w */ 2025 write(w) { 2026 return w.ts.wrap([ 2027 this.extAttrs.write(w), 2028 w.token(this.tokens.optional), 2029 w.ts.type(this.idlType.write(w)), 2030 w.token(this.tokens.variadic), 2031 w.name_token(this.tokens.name, { data: this }), 2032 this.default ? this.default.write(w) : "", 2033 w.token(this.tokens.separator), 2034 ]); 2035 } 2036 } 2037 2038 /** 2039 * @param {Argument} arg 2040 */ 2041 function isLastRequiredArgument(arg) { 2042 const list = arg.parent.arguments || arg.parent.list; 2043 const index = list.indexOf(arg); 2044 const requiredExists = list.slice(index + 1).some((a) => !a.optional); 2045 return !requiredExists; 2046 } 2047 2048 /** 2049 * @param {Argument} arg 2050 */ 2051 function autofixDictionaryArgumentOptionality(arg) { 2052 return () => { 2053 const firstToken = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_3__.getFirstToken)(arg.idlType); 2054 arg.tokens.optional = { 2055 ...firstToken, 2056 type: "optional", 2057 value: "optional", 2058 }; 2059 firstToken.trivia = " "; 2060 autofixOptionalDictionaryDefaultValue(arg)(); 2061 }; 2062 } 2063 2064 /** 2065 * @param {Argument} arg 2066 */ 2067 function autofixOptionalDictionaryDefaultValue(arg) { 2068 return () => { 2069 arg.default = _default_js__WEBPACK_IMPORTED_MODULE_1__.Default.parse(new _tokeniser_js__WEBPACK_IMPORTED_MODULE_4__.Tokeniser(" = {}")); 2070 }; 2071 } 2072 2073 2074 /***/ }), 2075 /* 12 */ 2076 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 2077 2078 __webpack_require__.r(__webpack_exports__); 2079 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 2080 /* harmony export */ Default: () => (/* binding */ Default) 2081 /* harmony export */ }); 2082 /* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); 2083 /* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); 2084 2085 2086 2087 class Default extends _base_js__WEBPACK_IMPORTED_MODULE_0__.Base { 2088 /** 2089 * @param {import("../tokeniser.js").Tokeniser} tokeniser 2090 */ 2091 static parse(tokeniser) { 2092 const assign = tokeniser.consume("="); 2093 if (!assign) { 2094 return null; 2095 } 2096 const def = 2097 (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.const_value)(tokeniser) || 2098 tokeniser.consumeKind("string") || 2099 tokeniser.consume("null", "[", "{") || 2100 tokeniser.error("No value for default"); 2101 const expression = [def]; 2102 if (def.value === "[") { 2103 const close = 2104 tokeniser.consume("]") || 2105 tokeniser.error("Default sequence value must be empty"); 2106 expression.push(close); 2107 } else if (def.value === "{") { 2108 const close = 2109 tokeniser.consume("}") || 2110 tokeniser.error("Default dictionary value must be empty"); 2111 expression.push(close); 2112 } 2113 return new Default({ 2114 source: tokeniser.source, 2115 tokens: { assign }, 2116 expression, 2117 }); 2118 } 2119 2120 constructor({ source, tokens, expression }) { 2121 super({ source, tokens }); 2122 expression.parent = this; 2123 Object.defineProperty(this, "expression", { value: expression }); 2124 } 2125 2126 get type() { 2127 return (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.const_data)(this.expression[0]).type; 2128 } 2129 get value() { 2130 return (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.const_data)(this.expression[0]).value; 2131 } 2132 get negative() { 2133 return (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.const_data)(this.expression[0]).negative; 2134 } 2135 2136 /** @param {import("../writer.js").Writer} w */ 2137 write(w) { 2138 return w.ts.wrap([ 2139 w.token(this.tokens.assign), 2140 ...this.expression.map((t) => w.token(t)), 2141 ]); 2142 } 2143 } 2144 2145 2146 /***/ }), 2147 /* 13 */ 2148 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 2149 2150 __webpack_require__.r(__webpack_exports__); 2151 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 2152 /* harmony export */ Operation: () => (/* binding */ Operation) 2153 /* harmony export */ }); 2154 /* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); 2155 /* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); 2156 /* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3); 2157 2158 2159 2160 2161 class Operation extends _base_js__WEBPACK_IMPORTED_MODULE_0__.Base { 2162 /** 2163 * @param {import("../tokeniser.js").Tokeniser} tokeniser 2164 * @param {object} [options] 2165 * @param {import("../tokeniser.js").Token} [options.special] 2166 * @param {import("../tokeniser.js").Token} [options.regular] 2167 */ 2168 static parse(tokeniser, { special, regular } = {}) { 2169 const tokens = { special }; 2170 const ret = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.autoParenter)( 2171 new Operation({ source: tokeniser.source, tokens }), 2172 ); 2173 if (special && special.value === "stringifier") { 2174 tokens.termination = tokeniser.consume(";"); 2175 if (tokens.termination) { 2176 ret.arguments = []; 2177 return ret; 2178 } 2179 } 2180 if (!special && !regular) { 2181 tokens.special = tokeniser.consume("getter", "setter", "deleter"); 2182 } 2183 ret.idlType = 2184 (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.return_type)(tokeniser) || tokeniser.error("Missing return type"); 2185 tokens.name = 2186 tokeniser.consumeKind("identifier") || tokeniser.consume("includes"); 2187 tokens.open = 2188 tokeniser.consume("(") || tokeniser.error("Invalid operation"); 2189 ret.arguments = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.argument_list)(tokeniser); 2190 tokens.close = 2191 tokeniser.consume(")") || tokeniser.error("Unterminated operation"); 2192 tokens.termination = 2193 tokeniser.consume(";") || 2194 tokeniser.error("Unterminated operation, expected `;`"); 2195 return ret.this; 2196 } 2197 2198 get type() { 2199 return "operation"; 2200 } 2201 get name() { 2202 const { name } = this.tokens; 2203 if (!name) { 2204 return ""; 2205 } 2206 return (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.unescape)(name.value); 2207 } 2208 get special() { 2209 if (!this.tokens.special) { 2210 return ""; 2211 } 2212 return this.tokens.special.value; 2213 } 2214 2215 *validate(defs) { 2216 yield* this.extAttrs.validate(defs); 2217 if (!this.name && ["", "static"].includes(this.special)) { 2218 const message = `Regular or static operations must have both a return type and an identifier.`; 2219 yield (0,_error_js__WEBPACK_IMPORTED_MODULE_2__.validationError)(this.tokens.open, this, "incomplete-op", message); 2220 } 2221 if (this.idlType) { 2222 if (this.idlType.generic === "async_sequence") { 2223 const message = `async_sequence types cannot be returned by an operation.`; 2224 yield (0,_error_js__WEBPACK_IMPORTED_MODULE_2__.validationError)( 2225 this.idlType.tokens.base, 2226 this, 2227 "async-sequence-idl-to-js", 2228 message, 2229 ); 2230 } 2231 yield* this.idlType.validate(defs); 2232 } 2233 for (const argument of this.arguments) { 2234 yield* argument.validate(defs); 2235 } 2236 } 2237 2238 /** @param {import("../writer.js").Writer} w */ 2239 write(w) { 2240 const { parent } = this; 2241 const body = this.idlType 2242 ? [ 2243 w.ts.type(this.idlType.write(w)), 2244 w.name_token(this.tokens.name, { data: this, parent }), 2245 w.token(this.tokens.open), 2246 w.ts.wrap(this.arguments.map((arg) => arg.write(w))), 2247 w.token(this.tokens.close), 2248 ] 2249 : []; 2250 return w.ts.definition( 2251 w.ts.wrap([ 2252 this.extAttrs.write(w), 2253 this.tokens.name 2254 ? w.token(this.tokens.special) 2255 : w.token(this.tokens.special, w.ts.nameless, { data: this, parent }), 2256 ...body, 2257 w.token(this.tokens.termination), 2258 ]), 2259 { data: this, parent }, 2260 ); 2261 } 2262 } 2263 2264 2265 /***/ }), 2266 /* 14 */ 2267 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 2268 2269 __webpack_require__.r(__webpack_exports__); 2270 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 2271 /* harmony export */ Attribute: () => (/* binding */ Attribute) 2272 /* harmony export */ }); 2273 /* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3); 2274 /* harmony import */ var _validators_helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7); 2275 /* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6); 2276 /* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4); 2277 2278 2279 2280 2281 2282 class Attribute extends _base_js__WEBPACK_IMPORTED_MODULE_2__.Base { 2283 /** 2284 * @param {import("../tokeniser.js").Tokeniser} tokeniser 2285 * @param {object} [options] 2286 * @param {import("../tokeniser.js").Token} [options.special] 2287 * @param {boolean} [options.noInherit] 2288 * @param {boolean} [options.readonly] 2289 */ 2290 static parse( 2291 tokeniser, 2292 { special, noInherit = false, readonly = false } = {}, 2293 ) { 2294 const start_position = tokeniser.position; 2295 const tokens = { special }; 2296 const ret = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_3__.autoParenter)( 2297 new Attribute({ source: tokeniser.source, tokens }), 2298 ); 2299 if (!special && !noInherit) { 2300 tokens.special = tokeniser.consume("inherit"); 2301 } 2302 if (ret.special === "inherit" && tokeniser.probe("readonly")) { 2303 tokeniser.error("Inherited attributes cannot be read-only"); 2304 } 2305 tokens.readonly = tokeniser.consume("readonly"); 2306 if (readonly && !tokens.readonly && tokeniser.probe("attribute")) { 2307 tokeniser.error("Attributes must be readonly in this context"); 2308 } 2309 tokens.base = tokeniser.consume("attribute"); 2310 if (!tokens.base) { 2311 tokeniser.unconsume(start_position); 2312 return; 2313 } 2314 ret.idlType = 2315 (0,_helpers_js__WEBPACK_IMPORTED_MODULE_3__.type_with_extended_attributes)(tokeniser, "attribute-type") || 2316 tokeniser.error("Attribute lacks a type"); 2317 tokens.name = 2318 tokeniser.consumeKind("identifier") || 2319 tokeniser.consume("async", "required") || 2320 tokeniser.error("Attribute lacks a name"); 2321 tokens.termination = 2322 tokeniser.consume(";") || 2323 tokeniser.error("Unterminated attribute, expected `;`"); 2324 return ret.this; 2325 } 2326 2327 get type() { 2328 return "attribute"; 2329 } 2330 get special() { 2331 if (!this.tokens.special) { 2332 return ""; 2333 } 2334 return this.tokens.special.value; 2335 } 2336 get readonly() { 2337 return !!this.tokens.readonly; 2338 } 2339 get name() { 2340 return (0,_helpers_js__WEBPACK_IMPORTED_MODULE_3__.unescape)(this.tokens.name.value); 2341 } 2342 2343 *validate(defs) { 2344 yield* this.extAttrs.validate(defs); 2345 yield* this.idlType.validate(defs); 2346 2347 if ( 2348 ["async_sequence", "sequence", "record"].includes(this.idlType.generic) 2349 ) { 2350 const message = `Attributes cannot accept ${this.idlType.generic} types.`; 2351 yield (0,_error_js__WEBPACK_IMPORTED_MODULE_0__.validationError)( 2352 this.tokens.name, 2353 this, 2354 "attr-invalid-type", 2355 message, 2356 ); 2357 } 2358 2359 { 2360 const { reference } = (0,_validators_helpers_js__WEBPACK_IMPORTED_MODULE_1__.idlTypeIncludesDictionary)(this.idlType, defs) || {}; 2361 if (reference) { 2362 const targetToken = (this.idlType.union ? reference : this.idlType) 2363 .tokens.base; 2364 const message = "Attributes cannot accept dictionary types."; 2365 yield (0,_error_js__WEBPACK_IMPORTED_MODULE_0__.validationError)(targetToken, this, "attr-invalid-type", message); 2366 } 2367 } 2368 2369 if (this.readonly) { 2370 if ((0,_validators_helpers_js__WEBPACK_IMPORTED_MODULE_1__.idlTypeIncludesEnforceRange)(this.idlType, defs)) { 2371 const targetToken = this.idlType.tokens.base; 2372 const message = 2373 "Readonly attributes cannot accept [EnforceRange] extended attribute."; 2374 yield (0,_error_js__WEBPACK_IMPORTED_MODULE_0__.validationError)(targetToken, this, "attr-invalid-type", message); 2375 } 2376 } 2377 } 2378 2379 /** @param {import("../writer.js").Writer} w */ 2380 write(w) { 2381 const { parent } = this; 2382 return w.ts.definition( 2383 w.ts.wrap([ 2384 this.extAttrs.write(w), 2385 w.token(this.tokens.special), 2386 w.token(this.tokens.readonly), 2387 w.token(this.tokens.base), 2388 w.ts.type(this.idlType.write(w)), 2389 w.name_token(this.tokens.name, { data: this, parent }), 2390 w.token(this.tokens.termination), 2391 ]), 2392 { data: this, parent }, 2393 ); 2394 } 2395 } 2396 2397 2398 /***/ }), 2399 /* 15 */ 2400 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 2401 2402 __webpack_require__.r(__webpack_exports__); 2403 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 2404 /* harmony export */ Enum: () => (/* binding */ Enum), 2405 /* harmony export */ EnumValue: () => (/* binding */ EnumValue) 2406 /* harmony export */ }); 2407 /* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4); 2408 /* harmony import */ var _token_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(10); 2409 /* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6); 2410 2411 2412 2413 2414 class EnumValue extends _token_js__WEBPACK_IMPORTED_MODULE_1__.WrappedToken { 2415 /** 2416 * @param {import("../tokeniser.js").Tokeniser} tokeniser 2417 */ 2418 static parse(tokeniser) { 2419 const value = tokeniser.consumeKind("string"); 2420 if (value) { 2421 return new EnumValue({ source: tokeniser.source, tokens: { value } }); 2422 } 2423 } 2424 2425 get type() { 2426 return "enum-value"; 2427 } 2428 get value() { 2429 return super.value.slice(1, -1); 2430 } 2431 2432 /** @param {import("../writer.js").Writer} w */ 2433 write(w) { 2434 const { parent } = this; 2435 return w.ts.wrap([ 2436 w.ts.trivia(this.tokens.value.trivia), 2437 w.ts.definition( 2438 w.ts.wrap(['"', w.ts.name(this.value, { data: this, parent }), '"']), 2439 { data: this, parent }, 2440 ), 2441 w.token(this.tokens.separator), 2442 ]); 2443 } 2444 } 2445 2446 class Enum extends _base_js__WEBPACK_IMPORTED_MODULE_2__.Base { 2447 /** 2448 * @param {import("../tokeniser.js").Tokeniser} tokeniser 2449 */ 2450 static parse(tokeniser) { 2451 /** @type {Base["tokens"]} */ 2452 const tokens = {}; 2453 tokens.base = tokeniser.consume("enum"); 2454 if (!tokens.base) { 2455 return; 2456 } 2457 tokens.name = 2458 tokeniser.consumeKind("identifier") || 2459 tokeniser.error("No name for enum"); 2460 const ret = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_0__.autoParenter)(new Enum({ source: tokeniser.source, tokens })); 2461 tokeniser.current = ret.this; 2462 tokens.open = tokeniser.consume("{") || tokeniser.error("Bodyless enum"); 2463 ret.values = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_0__.list)(tokeniser, { 2464 parser: EnumValue.parse, 2465 allowDangler: true, 2466 listName: "enumeration", 2467 }); 2468 if (tokeniser.probeKind("string")) { 2469 tokeniser.error("No comma between enum values"); 2470 } 2471 tokens.close = 2472 tokeniser.consume("}") || tokeniser.error("Unexpected value in enum"); 2473 if (!ret.values.length) { 2474 tokeniser.error("No value in enum"); 2475 } 2476 tokens.termination = 2477 tokeniser.consume(";") || tokeniser.error("No semicolon after enum"); 2478 return ret.this; 2479 } 2480 2481 get type() { 2482 return "enum"; 2483 } 2484 get name() { 2485 return (0,_helpers_js__WEBPACK_IMPORTED_MODULE_0__.unescape)(this.tokens.name.value); 2486 } 2487 2488 /** @param {import("../writer.js").Writer} w */ 2489 write(w) { 2490 return w.ts.definition( 2491 w.ts.wrap([ 2492 this.extAttrs.write(w), 2493 w.token(this.tokens.base), 2494 w.name_token(this.tokens.name, { data: this }), 2495 w.token(this.tokens.open), 2496 w.ts.wrap(this.values.map((v) => v.write(w))), 2497 w.token(this.tokens.close), 2498 w.token(this.tokens.termination), 2499 ]), 2500 { data: this }, 2501 ); 2502 } 2503 } 2504 2505 2506 /***/ }), 2507 /* 16 */ 2508 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 2509 2510 __webpack_require__.r(__webpack_exports__); 2511 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 2512 /* harmony export */ Includes: () => (/* binding */ Includes) 2513 /* harmony export */ }); 2514 /* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); 2515 /* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); 2516 2517 2518 2519 class Includes extends _base_js__WEBPACK_IMPORTED_MODULE_0__.Base { 2520 /** 2521 * @param {import("../tokeniser.js").Tokeniser} tokeniser 2522 */ 2523 static parse(tokeniser) { 2524 const target = tokeniser.consumeKind("identifier"); 2525 if (!target) { 2526 return; 2527 } 2528 const tokens = { target }; 2529 tokens.includes = tokeniser.consume("includes"); 2530 if (!tokens.includes) { 2531 tokeniser.unconsume(target.index); 2532 return; 2533 } 2534 tokens.mixin = 2535 tokeniser.consumeKind("identifier") || 2536 tokeniser.error("Incomplete includes statement"); 2537 tokens.termination = 2538 tokeniser.consume(";") || 2539 tokeniser.error("No terminating ; for includes statement"); 2540 return new Includes({ source: tokeniser.source, tokens }); 2541 } 2542 2543 get type() { 2544 return "includes"; 2545 } 2546 get target() { 2547 return (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.unescape)(this.tokens.target.value); 2548 } 2549 get includes() { 2550 return (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.unescape)(this.tokens.mixin.value); 2551 } 2552 2553 /** @param {import("../writer.js").Writer} w */ 2554 write(w) { 2555 return w.ts.definition( 2556 w.ts.wrap([ 2557 this.extAttrs.write(w), 2558 w.reference_token(this.tokens.target, this), 2559 w.token(this.tokens.includes), 2560 w.reference_token(this.tokens.mixin, this), 2561 w.token(this.tokens.termination), 2562 ]), 2563 { data: this }, 2564 ); 2565 } 2566 } 2567 2568 2569 /***/ }), 2570 /* 17 */ 2571 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 2572 2573 __webpack_require__.r(__webpack_exports__); 2574 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 2575 /* harmony export */ Typedef: () => (/* binding */ Typedef) 2576 /* harmony export */ }); 2577 /* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); 2578 /* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); 2579 2580 2581 2582 class Typedef extends _base_js__WEBPACK_IMPORTED_MODULE_0__.Base { 2583 /** 2584 * @param {import("../tokeniser.js").Tokeniser} tokeniser 2585 */ 2586 static parse(tokeniser) { 2587 /** @type {Base["tokens"]} */ 2588 const tokens = {}; 2589 const ret = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.autoParenter)(new Typedef({ source: tokeniser.source, tokens })); 2590 tokens.base = tokeniser.consume("typedef"); 2591 if (!tokens.base) { 2592 return; 2593 } 2594 ret.idlType = 2595 (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.type_with_extended_attributes)(tokeniser, "typedef-type") || 2596 tokeniser.error("Typedef lacks a type"); 2597 tokens.name = 2598 tokeniser.consumeKind("identifier") || 2599 tokeniser.error("Typedef lacks a name"); 2600 tokeniser.current = ret.this; 2601 tokens.termination = 2602 tokeniser.consume(";") || 2603 tokeniser.error("Unterminated typedef, expected `;`"); 2604 return ret.this; 2605 } 2606 2607 get type() { 2608 return "typedef"; 2609 } 2610 get name() { 2611 return (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.unescape)(this.tokens.name.value); 2612 } 2613 2614 *validate(defs) { 2615 yield* this.idlType.validate(defs); 2616 } 2617 2618 /** @param {import("../writer.js").Writer} w */ 2619 write(w) { 2620 return w.ts.definition( 2621 w.ts.wrap([ 2622 this.extAttrs.write(w), 2623 w.token(this.tokens.base), 2624 w.ts.type(this.idlType.write(w)), 2625 w.name_token(this.tokens.name, { data: this }), 2626 w.token(this.tokens.termination), 2627 ]), 2628 { data: this }, 2629 ); 2630 } 2631 } 2632 2633 2634 /***/ }), 2635 /* 18 */ 2636 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 2637 2638 __webpack_require__.r(__webpack_exports__); 2639 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 2640 /* harmony export */ CallbackFunction: () => (/* binding */ CallbackFunction) 2641 /* harmony export */ }); 2642 /* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); 2643 /* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); 2644 /* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3); 2645 2646 2647 2648 2649 class CallbackFunction extends _base_js__WEBPACK_IMPORTED_MODULE_0__.Base { 2650 /** 2651 * @param {import("../tokeniser.js").Tokeniser} tokeniser 2652 */ 2653 static parse(tokeniser, base) { 2654 const tokens = { base }; 2655 const ret = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.autoParenter)( 2656 new CallbackFunction({ source: tokeniser.source, tokens }), 2657 ); 2658 tokens.name = 2659 tokeniser.consumeKind("identifier") || 2660 tokeniser.error("Callback lacks a name"); 2661 tokeniser.current = ret.this; 2662 tokens.assign = 2663 tokeniser.consume("=") || tokeniser.error("Callback lacks an assignment"); 2664 ret.idlType = 2665 (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.return_type)(tokeniser) || tokeniser.error("Callback lacks a return type"); 2666 tokens.open = 2667 tokeniser.consume("(") || 2668 tokeniser.error("Callback lacks parentheses for arguments"); 2669 ret.arguments = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.argument_list)(tokeniser); 2670 tokens.close = 2671 tokeniser.consume(")") || tokeniser.error("Unterminated callback"); 2672 tokens.termination = 2673 tokeniser.consume(";") || 2674 tokeniser.error("Unterminated callback, expected `;`"); 2675 return ret.this; 2676 } 2677 2678 get type() { 2679 return "callback"; 2680 } 2681 get name() { 2682 return (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.unescape)(this.tokens.name.value); 2683 } 2684 2685 *validate(defs) { 2686 yield* this.extAttrs.validate(defs); 2687 for (const arg of this.arguments) { 2688 yield* arg.validate(defs); 2689 if (arg.idlType.generic === "async_sequence") { 2690 const message = `async_sequence types cannot be returned as a callback argument.`; 2691 yield (0,_error_js__WEBPACK_IMPORTED_MODULE_2__.validationError)( 2692 arg.tokens.name, 2693 arg, 2694 "async-sequence-idl-to-js", 2695 message, 2696 ); 2697 } 2698 } 2699 yield* this.idlType.validate(defs); 2700 } 2701 2702 /** @param {import("../writer.js").Writer} w */ 2703 write(w) { 2704 return w.ts.definition( 2705 w.ts.wrap([ 2706 this.extAttrs.write(w), 2707 w.token(this.tokens.base), 2708 w.name_token(this.tokens.name, { data: this }), 2709 w.token(this.tokens.assign), 2710 w.ts.type(this.idlType.write(w)), 2711 w.token(this.tokens.open), 2712 ...this.arguments.map((arg) => arg.write(w)), 2713 w.token(this.tokens.close), 2714 w.token(this.tokens.termination), 2715 ]), 2716 { data: this }, 2717 ); 2718 } 2719 } 2720 2721 2722 /***/ }), 2723 /* 19 */ 2724 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 2725 2726 __webpack_require__.r(__webpack_exports__); 2727 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 2728 /* harmony export */ Interface: () => (/* binding */ Interface) 2729 /* harmony export */ }); 2730 /* harmony import */ var _container_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(20); 2731 /* harmony import */ var _attribute_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); 2732 /* harmony import */ var _operation_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(13); 2733 /* harmony import */ var _constant_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(21); 2734 /* harmony import */ var _iterable_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(22); 2735 /* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(4); 2736 /* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(3); 2737 /* harmony import */ var _validators_interface_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(23); 2738 /* harmony import */ var _constructor_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(24); 2739 /* harmony import */ var _tokeniser_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(2); 2740 /* harmony import */ var _extended_attributes_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(8); 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 /** 2754 * @param {import("../tokeniser.js").Tokeniser} tokeniser 2755 */ 2756 function static_member(tokeniser) { 2757 const special = tokeniser.consume("static"); 2758 if (!special) return; 2759 const member = 2760 _attribute_js__WEBPACK_IMPORTED_MODULE_1__.Attribute.parse(tokeniser, { special }) || 2761 _operation_js__WEBPACK_IMPORTED_MODULE_2__.Operation.parse(tokeniser, { special }) || 2762 tokeniser.error("No body in static member"); 2763 return member; 2764 } 2765 2766 class Interface extends _container_js__WEBPACK_IMPORTED_MODULE_0__.Container { 2767 /** 2768 * @param {import("../tokeniser.js").Tokeniser} tokeniser 2769 * @param {import("../tokeniser.js").Token} base 2770 * @param {object} [options] 2771 * @param {import("./container.js").AllowedMember[]} [options.extMembers] 2772 * @param {import("../tokeniser.js").Token|null} [options.partial] 2773 */ 2774 static parse(tokeniser, base, { extMembers = [], partial = null } = {}) { 2775 const tokens = { partial, base }; 2776 return _container_js__WEBPACK_IMPORTED_MODULE_0__.Container.parse( 2777 tokeniser, 2778 new Interface({ source: tokeniser.source, tokens }), 2779 { 2780 inheritable: !partial, 2781 allowedMembers: [ 2782 ...extMembers, 2783 [_constant_js__WEBPACK_IMPORTED_MODULE_3__.Constant.parse], 2784 [_constructor_js__WEBPACK_IMPORTED_MODULE_8__.Constructor.parse], 2785 [static_member], 2786 [_helpers_js__WEBPACK_IMPORTED_MODULE_5__.stringifier], 2787 [_iterable_js__WEBPACK_IMPORTED_MODULE_4__.IterableLike.parse], 2788 [_attribute_js__WEBPACK_IMPORTED_MODULE_1__.Attribute.parse], 2789 [_operation_js__WEBPACK_IMPORTED_MODULE_2__.Operation.parse], 2790 ], 2791 }, 2792 ); 2793 } 2794 2795 get type() { 2796 return "interface"; 2797 } 2798 2799 *validate(defs) { 2800 yield* this.extAttrs.validate(defs); 2801 if ( 2802 !this.partial && 2803 this.extAttrs.every((extAttr) => extAttr.name !== "Exposed") 2804 ) { 2805 const message = `Interfaces must have \`[Exposed]\` extended attribute. \ 2806 To fix, add, for example, \`[Exposed=Window]\`. Please also consider carefully \ 2807 if your interface should also be exposed in a Worker scope. Refer to the \ 2808 [WebIDL spec section on Exposed](https://heycam.github.io/webidl/#Exposed) \ 2809 for more information.`; 2810 yield (0,_error_js__WEBPACK_IMPORTED_MODULE_6__.validationError)( 2811 this.tokens.name, 2812 this, 2813 "require-exposed", 2814 message, 2815 { 2816 autofix: (0,_helpers_js__WEBPACK_IMPORTED_MODULE_5__.autofixAddExposedWindow)(this), 2817 }, 2818 ); 2819 } 2820 const oldConstructors = this.extAttrs.filter( 2821 (extAttr) => extAttr.name === "Constructor", 2822 ); 2823 for (const constructor of oldConstructors) { 2824 const message = `Constructors should now be represented as a \`constructor()\` operation on the interface \ 2825 instead of \`[Constructor]\` extended attribute. Refer to the \ 2826 [WebIDL spec section on constructor operations](https://heycam.github.io/webidl/#idl-constructors) \ 2827 for more information.`; 2828 yield (0,_error_js__WEBPACK_IMPORTED_MODULE_6__.validationError)( 2829 constructor.tokens.name, 2830 this, 2831 "constructor-member", 2832 message, 2833 { 2834 autofix: autofixConstructor(this, constructor), 2835 }, 2836 ); 2837 } 2838 2839 const isGlobal = this.extAttrs.some((extAttr) => extAttr.name === "Global"); 2840 if (isGlobal) { 2841 const factoryFunctions = this.extAttrs.filter( 2842 (extAttr) => extAttr.name === "LegacyFactoryFunction", 2843 ); 2844 for (const named of factoryFunctions) { 2845 const message = `Interfaces marked as \`[Global]\` cannot have factory functions.`; 2846 yield (0,_error_js__WEBPACK_IMPORTED_MODULE_6__.validationError)( 2847 named.tokens.name, 2848 this, 2849 "no-constructible-global", 2850 message, 2851 ); 2852 } 2853 2854 const constructors = this.members.filter( 2855 (member) => member.type === "constructor", 2856 ); 2857 for (const named of constructors) { 2858 const message = `Interfaces marked as \`[Global]\` cannot have constructors.`; 2859 yield (0,_error_js__WEBPACK_IMPORTED_MODULE_6__.validationError)( 2860 named.tokens.base, 2861 this, 2862 "no-constructible-global", 2863 message, 2864 ); 2865 } 2866 } 2867 2868 yield* super.validate(defs); 2869 if (!this.partial) { 2870 yield* (0,_validators_interface_js__WEBPACK_IMPORTED_MODULE_7__.checkInterfaceMemberDuplication)(defs, this); 2871 } 2872 } 2873 } 2874 2875 function autofixConstructor(interfaceDef, constructorExtAttr) { 2876 interfaceDef = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_5__.autoParenter)(interfaceDef); 2877 return () => { 2878 const indentation = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_5__.getLastIndentation)( 2879 interfaceDef.extAttrs.tokens.open.trivia, 2880 ); 2881 const memberIndent = interfaceDef.members.length 2882 ? (0,_helpers_js__WEBPACK_IMPORTED_MODULE_5__.getLastIndentation)((0,_helpers_js__WEBPACK_IMPORTED_MODULE_5__.getFirstToken)(interfaceDef.members[0]).trivia) 2883 : (0,_helpers_js__WEBPACK_IMPORTED_MODULE_5__.getMemberIndentation)(indentation); 2884 const constructorOp = _constructor_js__WEBPACK_IMPORTED_MODULE_8__.Constructor.parse( 2885 new _tokeniser_js__WEBPACK_IMPORTED_MODULE_9__.Tokeniser(`\n${memberIndent}constructor();`), 2886 ); 2887 constructorOp.extAttrs = new _extended_attributes_js__WEBPACK_IMPORTED_MODULE_10__.ExtendedAttributes({ 2888 source: interfaceDef.source, 2889 tokens: {}, 2890 }); 2891 (0,_helpers_js__WEBPACK_IMPORTED_MODULE_5__.autoParenter)(constructorOp).arguments = constructorExtAttr.arguments; 2892 2893 const existingIndex = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_5__.findLastIndex)( 2894 interfaceDef.members, 2895 (m) => m.type === "constructor", 2896 ); 2897 interfaceDef.members.splice(existingIndex + 1, 0, constructorOp); 2898 2899 const { close } = interfaceDef.tokens; 2900 if (!close.trivia.includes("\n")) { 2901 close.trivia += `\n${indentation}`; 2902 } 2903 2904 const { extAttrs } = interfaceDef; 2905 const index = extAttrs.indexOf(constructorExtAttr); 2906 const removed = extAttrs.splice(index, 1); 2907 if (!extAttrs.length) { 2908 extAttrs.tokens.open = extAttrs.tokens.close = undefined; 2909 } else if (extAttrs.length === index) { 2910 extAttrs[index - 1].tokens.separator = undefined; 2911 } else if (!extAttrs[index].tokens.name.trivia.trim()) { 2912 extAttrs[index].tokens.name.trivia = removed[0].tokens.name.trivia; 2913 } 2914 }; 2915 } 2916 2917 2918 /***/ }), 2919 /* 20 */ 2920 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 2921 2922 __webpack_require__.r(__webpack_exports__); 2923 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 2924 /* harmony export */ Container: () => (/* binding */ Container) 2925 /* harmony export */ }); 2926 /* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); 2927 /* harmony import */ var _extended_attributes_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8); 2928 /* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4); 2929 2930 2931 2932 2933 /** 2934 * @param {import("../tokeniser.js").Tokeniser} tokeniser 2935 */ 2936 function inheritance(tokeniser) { 2937 const colon = tokeniser.consume(":"); 2938 if (!colon) { 2939 return {}; 2940 } 2941 const inheritance = 2942 tokeniser.consumeKind("identifier") || 2943 tokeniser.error("Inheritance lacks a type"); 2944 return { colon, inheritance }; 2945 } 2946 2947 /** 2948 * Parser callback. 2949 * @callback ParserCallback 2950 * @param {import("../tokeniser.js").Tokeniser} tokeniser 2951 * @param {...*} args 2952 */ 2953 2954 /** 2955 * A parser callback and optional option object. 2956 * @typedef AllowedMember 2957 * @type {[ParserCallback, object?]} 2958 */ 2959 2960 class Container extends _base_js__WEBPACK_IMPORTED_MODULE_0__.Base { 2961 /** 2962 * @param {import("../tokeniser.js").Tokeniser} tokeniser 2963 * @param {*} instance TODO: This should be {T extends Container}, but see https://github.com/microsoft/TypeScript/issues/4628 2964 * @param {*} args 2965 */ 2966 static parse(tokeniser, instance, { inheritable, allowedMembers }) { 2967 const { tokens, type } = instance; 2968 tokens.name = 2969 tokeniser.consumeKind("identifier") || 2970 tokeniser.error(`Missing name in ${type}`); 2971 tokeniser.current = instance; 2972 instance = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_2__.autoParenter)(instance); 2973 if (inheritable) { 2974 Object.assign(tokens, inheritance(tokeniser)); 2975 } 2976 tokens.open = tokeniser.consume("{") || tokeniser.error(`Bodyless ${type}`); 2977 instance.members = []; 2978 while (true) { 2979 tokens.close = tokeniser.consume("}"); 2980 if (tokens.close) { 2981 tokens.termination = 2982 tokeniser.consume(";") || 2983 tokeniser.error(`Missing semicolon after ${type}`); 2984 return instance.this; 2985 } 2986 const ea = _extended_attributes_js__WEBPACK_IMPORTED_MODULE_1__.ExtendedAttributes.parse(tokeniser); 2987 let mem; 2988 for (const [parser, ...args] of allowedMembers) { 2989 mem = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_2__.autoParenter)(parser(tokeniser, ...args)); 2990 if (mem) { 2991 break; 2992 } 2993 } 2994 if (!mem) { 2995 tokeniser.error("Unknown member"); 2996 } 2997 mem.extAttrs = ea; 2998 instance.members.push(mem.this); 2999 } 3000 } 3001 3002 get partial() { 3003 return !!this.tokens.partial; 3004 } 3005 get name() { 3006 return (0,_helpers_js__WEBPACK_IMPORTED_MODULE_2__.unescape)(this.tokens.name.value); 3007 } 3008 get inheritance() { 3009 if (!this.tokens.inheritance) { 3010 return null; 3011 } 3012 return (0,_helpers_js__WEBPACK_IMPORTED_MODULE_2__.unescape)(this.tokens.inheritance.value); 3013 } 3014 3015 *validate(defs) { 3016 for (const member of this.members) { 3017 if (member.validate) { 3018 yield* member.validate(defs); 3019 } 3020 } 3021 } 3022 3023 /** @param {import("../writer.js").Writer} w */ 3024 write(w) { 3025 const inheritance = () => { 3026 if (!this.tokens.inheritance) { 3027 return ""; 3028 } 3029 return w.ts.wrap([ 3030 w.token(this.tokens.colon), 3031 w.ts.trivia(this.tokens.inheritance.trivia), 3032 w.ts.inheritance( 3033 w.reference(this.tokens.inheritance.value, { context: this }), 3034 ), 3035 ]); 3036 }; 3037 3038 return w.ts.definition( 3039 w.ts.wrap([ 3040 this.extAttrs.write(w), 3041 w.token(this.tokens.callback), 3042 w.token(this.tokens.partial), 3043 w.token(this.tokens.base), 3044 w.token(this.tokens.mixin), 3045 w.name_token(this.tokens.name, { data: this }), 3046 inheritance(), 3047 w.token(this.tokens.open), 3048 w.ts.wrap(this.members.map((m) => m.write(w))), 3049 w.token(this.tokens.close), 3050 w.token(this.tokens.termination), 3051 ]), 3052 { data: this }, 3053 ); 3054 } 3055 } 3056 3057 3058 /***/ }), 3059 /* 21 */ 3060 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 3061 3062 __webpack_require__.r(__webpack_exports__); 3063 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 3064 /* harmony export */ Constant: () => (/* binding */ Constant) 3065 /* harmony export */ }); 3066 /* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); 3067 /* harmony import */ var _type_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5); 3068 /* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4); 3069 3070 3071 3072 3073 class Constant extends _base_js__WEBPACK_IMPORTED_MODULE_0__.Base { 3074 /** 3075 * @param {import("../tokeniser.js").Tokeniser} tokeniser 3076 */ 3077 static parse(tokeniser) { 3078 /** @type {Base["tokens"]} */ 3079 const tokens = {}; 3080 tokens.base = tokeniser.consume("const"); 3081 if (!tokens.base) { 3082 return; 3083 } 3084 let idlType = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_2__.primitive_type)(tokeniser); 3085 if (!idlType) { 3086 const base = 3087 tokeniser.consumeKind("identifier") || 3088 tokeniser.error("Const lacks a type"); 3089 idlType = new _type_js__WEBPACK_IMPORTED_MODULE_1__.Type({ source: tokeniser.source, tokens: { base } }); 3090 } 3091 if (tokeniser.probe("?")) { 3092 tokeniser.error("Unexpected nullable constant type"); 3093 } 3094 idlType.type = "const-type"; 3095 tokens.name = 3096 tokeniser.consumeKind("identifier") || 3097 tokeniser.error("Const lacks a name"); 3098 tokens.assign = 3099 tokeniser.consume("=") || tokeniser.error("Const lacks value assignment"); 3100 tokens.value = 3101 (0,_helpers_js__WEBPACK_IMPORTED_MODULE_2__.const_value)(tokeniser) || tokeniser.error("Const lacks a value"); 3102 tokens.termination = 3103 tokeniser.consume(";") || 3104 tokeniser.error("Unterminated const, expected `;`"); 3105 const ret = new Constant({ source: tokeniser.source, tokens }); 3106 (0,_helpers_js__WEBPACK_IMPORTED_MODULE_2__.autoParenter)(ret).idlType = idlType; 3107 return ret; 3108 } 3109 3110 get type() { 3111 return "const"; 3112 } 3113 get name() { 3114 return (0,_helpers_js__WEBPACK_IMPORTED_MODULE_2__.unescape)(this.tokens.name.value); 3115 } 3116 get value() { 3117 return (0,_helpers_js__WEBPACK_IMPORTED_MODULE_2__.const_data)(this.tokens.value); 3118 } 3119 3120 /** @param {import("../writer.js").Writer} w */ 3121 write(w) { 3122 const { parent } = this; 3123 return w.ts.definition( 3124 w.ts.wrap([ 3125 this.extAttrs.write(w), 3126 w.token(this.tokens.base), 3127 w.ts.type(this.idlType.write(w)), 3128 w.name_token(this.tokens.name, { data: this, parent }), 3129 w.token(this.tokens.assign), 3130 w.token(this.tokens.value), 3131 w.token(this.tokens.termination), 3132 ]), 3133 { data: this, parent }, 3134 ); 3135 } 3136 } 3137 3138 3139 /***/ }), 3140 /* 22 */ 3141 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 3142 3143 __webpack_require__.r(__webpack_exports__); 3144 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 3145 /* harmony export */ IterableLike: () => (/* binding */ IterableLike) 3146 /* harmony export */ }); 3147 /* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3); 3148 /* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6); 3149 /* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4); 3150 3151 3152 3153 3154 class IterableLike extends _base_js__WEBPACK_IMPORTED_MODULE_1__.Base { 3155 /** 3156 * @param {import("../tokeniser.js").Tokeniser} tokeniser 3157 */ 3158 static parse(tokeniser) { 3159 const start_position = tokeniser.position; 3160 const ret = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_2__.autoParenter)( 3161 new IterableLike({ source: tokeniser.source, tokens: {} }), 3162 ); 3163 const { tokens } = ret; 3164 tokens.readonly = tokeniser.consume("readonly"); 3165 if (!tokens.readonly) { 3166 tokens.async = tokeniser.consume("async"); 3167 } 3168 tokens.base = tokens.readonly 3169 ? tokeniser.consume("maplike", "setlike") 3170 : tokens.async 3171 ? tokeniser.consume("iterable") 3172 : tokeniser.consume("iterable", "async_iterable", "maplike", "setlike"); 3173 if (!tokens.base) { 3174 tokeniser.unconsume(start_position); 3175 return; 3176 } 3177 3178 const { type } = ret; 3179 const secondTypeRequired = type === "maplike"; 3180 const secondTypeAllowed = 3181 secondTypeRequired || type === "iterable" || type === "async_iterable"; 3182 const argumentAllowed = 3183 type === "async_iterable" || (ret.async && type === "iterable"); 3184 3185 tokens.open = 3186 tokeniser.consume("<") || 3187 tokeniser.error(`Missing less-than sign \`<\` in ${type} declaration`); 3188 const first = 3189 (0,_helpers_js__WEBPACK_IMPORTED_MODULE_2__.type_with_extended_attributes)(tokeniser) || 3190 tokeniser.error(`Missing a type argument in ${type} declaration`); 3191 ret.idlType = [first]; 3192 ret.arguments = []; 3193 3194 if (secondTypeAllowed) { 3195 first.tokens.separator = tokeniser.consume(","); 3196 if (first.tokens.separator) { 3197 ret.idlType.push((0,_helpers_js__WEBPACK_IMPORTED_MODULE_2__.type_with_extended_attributes)(tokeniser)); 3198 } else if (secondTypeRequired) { 3199 tokeniser.error(`Missing second type argument in ${type} declaration`); 3200 } 3201 } 3202 3203 tokens.close = 3204 tokeniser.consume(">") || 3205 tokeniser.error(`Missing greater-than sign \`>\` in ${type} declaration`); 3206 3207 if (tokeniser.probe("(")) { 3208 if (argumentAllowed) { 3209 tokens.argsOpen = tokeniser.consume("("); 3210 ret.arguments.push(...(0,_helpers_js__WEBPACK_IMPORTED_MODULE_2__.argument_list)(tokeniser)); 3211 tokens.argsClose = 3212 tokeniser.consume(")") || 3213 tokeniser.error("Unterminated async iterable argument list"); 3214 } else { 3215 tokeniser.error(`Arguments are only allowed for \`async iterable\``); 3216 } 3217 } 3218 3219 tokens.termination = 3220 tokeniser.consume(";") || 3221 tokeniser.error(`Missing semicolon after ${type} declaration`); 3222 3223 return ret.this; 3224 } 3225 3226 get type() { 3227 return this.tokens.base.value; 3228 } 3229 get readonly() { 3230 return !!this.tokens.readonly; 3231 } 3232 get async() { 3233 return !!this.tokens.async; 3234 } 3235 3236 *validate(defs) { 3237 if (this.async && this.type === "iterable") { 3238 const message = "`async iterable` is now changed to `async_iterable`."; 3239 yield (0,_error_js__WEBPACK_IMPORTED_MODULE_0__.validationError)( 3240 this.tokens.async, 3241 this, 3242 "obsolete-async-iterable-syntax", 3243 message, 3244 { 3245 autofix: autofixAsyncIterableSyntax(this), 3246 }, 3247 ); 3248 } 3249 for (const type of this.idlType) { 3250 yield* type.validate(defs); 3251 } 3252 for (const argument of this.arguments) { 3253 yield* argument.validate(defs); 3254 } 3255 } 3256 3257 /** @param {import("../writer.js").Writer} w */ 3258 write(w) { 3259 return w.ts.definition( 3260 w.ts.wrap([ 3261 this.extAttrs.write(w), 3262 w.token(this.tokens.readonly), 3263 w.token(this.tokens.async), 3264 w.token(this.tokens.base, w.ts.generic), 3265 w.token(this.tokens.open), 3266 w.ts.wrap(this.idlType.map((t) => t.write(w))), 3267 w.token(this.tokens.close), 3268 w.token(this.tokens.argsOpen), 3269 w.ts.wrap(this.arguments.map((arg) => arg.write(w))), 3270 w.token(this.tokens.argsClose), 3271 w.token(this.tokens.termination), 3272 ]), 3273 { data: this, parent: this.parent }, 3274 ); 3275 } 3276 } 3277 3278 /** 3279 * @param {IterableLike} iterableLike 3280 */ 3281 function autofixAsyncIterableSyntax(iterableLike) { 3282 return () => { 3283 const async = iterableLike.tokens.async; 3284 iterableLike.tokens.base = { 3285 ...async, 3286 type: "async_iterable", 3287 value: "async_iterable", 3288 }; 3289 delete iterableLike.tokens.async; 3290 }; 3291 } 3292 3293 3294 /***/ }), 3295 /* 23 */ 3296 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 3297 3298 __webpack_require__.r(__webpack_exports__); 3299 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 3300 /* harmony export */ checkInterfaceMemberDuplication: () => (/* binding */ checkInterfaceMemberDuplication) 3301 /* harmony export */ }); 3302 /* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3); 3303 3304 3305 /** 3306 * @param {import("../validator.js").Definitions} defs 3307 * @param {import("../productions/container.js").Container} i 3308 */ 3309 function* checkInterfaceMemberDuplication(defs, i) { 3310 const opNames = groupOperationNames(i); 3311 const partials = defs.partials.get(i.name) || []; 3312 const mixins = defs.mixinMap.get(i.name) || []; 3313 for (const ext of [...partials, ...mixins]) { 3314 const additions = getOperations(ext); 3315 const statics = additions.filter((a) => a.special === "static"); 3316 const nonstatics = additions.filter((a) => a.special !== "static"); 3317 yield* checkAdditions(statics, opNames.statics, ext, i); 3318 yield* checkAdditions(nonstatics, opNames.nonstatics, ext, i); 3319 statics.forEach((op) => opNames.statics.add(op.name)); 3320 nonstatics.forEach((op) => opNames.nonstatics.add(op.name)); 3321 } 3322 3323 /** 3324 * @param {import("../productions/operation.js").Operation[]} additions 3325 * @param {Set<string>} existings 3326 * @param {import("../productions/container.js").Container} ext 3327 * @param {import("../productions/container.js").Container} base 3328 */ 3329 function* checkAdditions(additions, existings, ext, base) { 3330 for (const addition of additions) { 3331 const { name } = addition; 3332 if (name && existings.has(name)) { 3333 const isStatic = addition.special === "static" ? "static " : ""; 3334 const message = `The ${isStatic}operation "${name}" has already been defined for the base interface "${base.name}" either in itself or in a mixin`; 3335 yield (0,_error_js__WEBPACK_IMPORTED_MODULE_0__.validationError)( 3336 addition.tokens.name, 3337 ext, 3338 "no-cross-overload", 3339 message, 3340 ); 3341 } 3342 } 3343 } 3344 3345 /** 3346 * @param {import("../productions/container.js").Container} i 3347 * @returns {import("../productions/operation.js").Operation[]} 3348 */ 3349 function getOperations(i) { 3350 return i.members.filter(({ type }) => type === "operation"); 3351 } 3352 3353 /** 3354 * @param {import("../productions/container.js").Container} i 3355 */ 3356 function groupOperationNames(i) { 3357 const ops = getOperations(i); 3358 return { 3359 statics: new Set( 3360 ops.filter((op) => op.special === "static").map((op) => op.name), 3361 ), 3362 nonstatics: new Set( 3363 ops.filter((op) => op.special !== "static").map((op) => op.name), 3364 ), 3365 }; 3366 } 3367 } 3368 3369 3370 /***/ }), 3371 /* 24 */ 3372 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 3373 3374 __webpack_require__.r(__webpack_exports__); 3375 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 3376 /* harmony export */ Constructor: () => (/* binding */ Constructor) 3377 /* harmony export */ }); 3378 /* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); 3379 /* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); 3380 3381 3382 3383 class Constructor extends _base_js__WEBPACK_IMPORTED_MODULE_0__.Base { 3384 /** 3385 * @param {import("../tokeniser.js").Tokeniser} tokeniser 3386 */ 3387 static parse(tokeniser) { 3388 const base = tokeniser.consume("constructor"); 3389 if (!base) { 3390 return; 3391 } 3392 /** @type {Base["tokens"]} */ 3393 const tokens = { base }; 3394 tokens.open = 3395 tokeniser.consume("(") || 3396 tokeniser.error("No argument list in constructor"); 3397 const args = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.argument_list)(tokeniser); 3398 tokens.close = 3399 tokeniser.consume(")") || tokeniser.error("Unterminated constructor"); 3400 tokens.termination = 3401 tokeniser.consume(";") || 3402 tokeniser.error("No semicolon after constructor"); 3403 const ret = new Constructor({ source: tokeniser.source, tokens }); 3404 (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.autoParenter)(ret).arguments = args; 3405 return ret; 3406 } 3407 3408 get type() { 3409 return "constructor"; 3410 } 3411 3412 *validate(defs) { 3413 for (const argument of this.arguments) { 3414 yield* argument.validate(defs); 3415 } 3416 } 3417 3418 /** @param {import("../writer.js").Writer} w */ 3419 write(w) { 3420 const { parent } = this; 3421 return w.ts.definition( 3422 w.ts.wrap([ 3423 this.extAttrs.write(w), 3424 w.token(this.tokens.base, w.ts.nameless, { data: this, parent }), 3425 w.token(this.tokens.open), 3426 w.ts.wrap(this.arguments.map((arg) => arg.write(w))), 3427 w.token(this.tokens.close), 3428 w.token(this.tokens.termination), 3429 ]), 3430 { data: this, parent }, 3431 ); 3432 } 3433 } 3434 3435 3436 /***/ }), 3437 /* 25 */ 3438 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 3439 3440 __webpack_require__.r(__webpack_exports__); 3441 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 3442 /* harmony export */ Mixin: () => (/* binding */ Mixin) 3443 /* harmony export */ }); 3444 /* harmony import */ var _container_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(20); 3445 /* harmony import */ var _constant_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(21); 3446 /* harmony import */ var _attribute_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(14); 3447 /* harmony import */ var _operation_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(13); 3448 /* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(4); 3449 3450 3451 3452 3453 3454 3455 class Mixin extends _container_js__WEBPACK_IMPORTED_MODULE_0__.Container { 3456 /** 3457 * @param {import("../tokeniser.js").Tokeniser} tokeniser 3458 * @param {import("../tokeniser.js").Token} base 3459 * @param {object} [options] 3460 * @param {import("./container.js").AllowedMember[]} [options.extMembers] 3461 * @param {import("../tokeniser.js").Token} [options.partial] 3462 */ 3463 static parse(tokeniser, base, { extMembers = [], partial } = {}) { 3464 const tokens = { partial, base }; 3465 tokens.mixin = tokeniser.consume("mixin"); 3466 if (!tokens.mixin) { 3467 return; 3468 } 3469 return _container_js__WEBPACK_IMPORTED_MODULE_0__.Container.parse( 3470 tokeniser, 3471 new Mixin({ source: tokeniser.source, tokens }), 3472 { 3473 allowedMembers: [ 3474 ...extMembers, 3475 [_constant_js__WEBPACK_IMPORTED_MODULE_1__.Constant.parse], 3476 [_helpers_js__WEBPACK_IMPORTED_MODULE_4__.stringifier], 3477 [_attribute_js__WEBPACK_IMPORTED_MODULE_2__.Attribute.parse, { noInherit: true }], 3478 [_operation_js__WEBPACK_IMPORTED_MODULE_3__.Operation.parse, { regular: true }], 3479 ], 3480 }, 3481 ); 3482 } 3483 3484 get type() { 3485 return "interface mixin"; 3486 } 3487 } 3488 3489 3490 /***/ }), 3491 /* 26 */ 3492 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 3493 3494 __webpack_require__.r(__webpack_exports__); 3495 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 3496 /* harmony export */ Dictionary: () => (/* binding */ Dictionary) 3497 /* harmony export */ }); 3498 /* harmony import */ var _container_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(20); 3499 /* harmony import */ var _field_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(27); 3500 3501 3502 3503 class Dictionary extends _container_js__WEBPACK_IMPORTED_MODULE_0__.Container { 3504 /** 3505 * @param {import("../tokeniser.js").Tokeniser} tokeniser 3506 * @param {object} [options] 3507 * @param {import("./container.js").AllowedMember[]} [options.extMembers] 3508 * @param {import("../tokeniser.js").Token} [options.partial] 3509 */ 3510 static parse(tokeniser, { extMembers = [], partial } = {}) { 3511 const tokens = { partial }; 3512 tokens.base = tokeniser.consume("dictionary"); 3513 if (!tokens.base) { 3514 return; 3515 } 3516 return _container_js__WEBPACK_IMPORTED_MODULE_0__.Container.parse( 3517 tokeniser, 3518 new Dictionary({ source: tokeniser.source, tokens }), 3519 { 3520 inheritable: !partial, 3521 allowedMembers: [...extMembers, [_field_js__WEBPACK_IMPORTED_MODULE_1__.Field.parse]], 3522 }, 3523 ); 3524 } 3525 3526 get type() { 3527 return "dictionary"; 3528 } 3529 } 3530 3531 3532 /***/ }), 3533 /* 27 */ 3534 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 3535 3536 __webpack_require__.r(__webpack_exports__); 3537 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 3538 /* harmony export */ Field: () => (/* binding */ Field) 3539 /* harmony export */ }); 3540 /* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); 3541 /* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); 3542 /* harmony import */ var _extended_attributes_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(8); 3543 /* harmony import */ var _default_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(12); 3544 3545 3546 3547 3548 3549 class Field extends _base_js__WEBPACK_IMPORTED_MODULE_0__.Base { 3550 /** 3551 * @param {import("../tokeniser.js").Tokeniser} tokeniser 3552 */ 3553 static parse(tokeniser) { 3554 /** @type {Base["tokens"]} */ 3555 const tokens = {}; 3556 const ret = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.autoParenter)(new Field({ source: tokeniser.source, tokens })); 3557 ret.extAttrs = _extended_attributes_js__WEBPACK_IMPORTED_MODULE_2__.ExtendedAttributes.parse(tokeniser); 3558 tokens.required = tokeniser.consume("required"); 3559 ret.idlType = 3560 (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.type_with_extended_attributes)(tokeniser, "dictionary-type") || 3561 tokeniser.error("Dictionary member lacks a type"); 3562 tokens.name = 3563 tokeniser.consumeKind("identifier") || 3564 tokeniser.error("Dictionary member lacks a name"); 3565 ret.default = _default_js__WEBPACK_IMPORTED_MODULE_3__.Default.parse(tokeniser); 3566 if (tokens.required && ret.default) 3567 tokeniser.error("Required member must not have a default"); 3568 tokens.termination = 3569 tokeniser.consume(";") || 3570 tokeniser.error("Unterminated dictionary member, expected `;`"); 3571 return ret.this; 3572 } 3573 3574 get type() { 3575 return "field"; 3576 } 3577 get name() { 3578 return (0,_helpers_js__WEBPACK_IMPORTED_MODULE_1__.unescape)(this.tokens.name.value); 3579 } 3580 get required() { 3581 return !!this.tokens.required; 3582 } 3583 3584 *validate(defs) { 3585 yield* this.idlType.validate(defs); 3586 } 3587 3588 /** @param {import("../writer.js").Writer} w */ 3589 write(w) { 3590 const { parent } = this; 3591 return w.ts.definition( 3592 w.ts.wrap([ 3593 this.extAttrs.write(w), 3594 w.token(this.tokens.required), 3595 w.ts.type(this.idlType.write(w)), 3596 w.name_token(this.tokens.name, { data: this, parent }), 3597 this.default ? this.default.write(w) : "", 3598 w.token(this.tokens.termination), 3599 ]), 3600 { data: this, parent }, 3601 ); 3602 } 3603 } 3604 3605 3606 /***/ }), 3607 /* 28 */ 3608 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 3609 3610 __webpack_require__.r(__webpack_exports__); 3611 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 3612 /* harmony export */ Namespace: () => (/* binding */ Namespace) 3613 /* harmony export */ }); 3614 /* harmony import */ var _container_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(20); 3615 /* harmony import */ var _attribute_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); 3616 /* harmony import */ var _operation_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(13); 3617 /* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3); 3618 /* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(4); 3619 /* harmony import */ var _constant_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(21); 3620 3621 3622 3623 3624 3625 3626 3627 class Namespace extends _container_js__WEBPACK_IMPORTED_MODULE_0__.Container { 3628 /** 3629 * @param {import("../tokeniser.js").Tokeniser} tokeniser 3630 * @param {object} [options] 3631 * @param {import("./container.js").AllowedMember[]} [options.extMembers] 3632 * @param {import("../tokeniser.js").Token} [options.partial] 3633 */ 3634 static parse(tokeniser, { extMembers = [], partial } = {}) { 3635 const tokens = { partial }; 3636 tokens.base = tokeniser.consume("namespace"); 3637 if (!tokens.base) { 3638 return; 3639 } 3640 return _container_js__WEBPACK_IMPORTED_MODULE_0__.Container.parse( 3641 tokeniser, 3642 new Namespace({ source: tokeniser.source, tokens }), 3643 { 3644 allowedMembers: [ 3645 ...extMembers, 3646 [_attribute_js__WEBPACK_IMPORTED_MODULE_1__.Attribute.parse, { noInherit: true, readonly: true }], 3647 [_constant_js__WEBPACK_IMPORTED_MODULE_5__.Constant.parse], 3648 [_operation_js__WEBPACK_IMPORTED_MODULE_2__.Operation.parse, { regular: true }], 3649 ], 3650 }, 3651 ); 3652 } 3653 3654 get type() { 3655 return "namespace"; 3656 } 3657 3658 *validate(defs) { 3659 if ( 3660 !this.partial && 3661 this.extAttrs.every((extAttr) => extAttr.name !== "Exposed") 3662 ) { 3663 const message = `Namespaces must have [Exposed] extended attribute. \ 3664 To fix, add, for example, [Exposed=Window]. Please also consider carefully \ 3665 if your namespace should also be exposed in a Worker scope. Refer to the \ 3666 [WebIDL spec section on Exposed](https://heycam.github.io/webidl/#Exposed) \ 3667 for more information.`; 3668 yield (0,_error_js__WEBPACK_IMPORTED_MODULE_3__.validationError)( 3669 this.tokens.name, 3670 this, 3671 "require-exposed", 3672 message, 3673 { 3674 autofix: (0,_helpers_js__WEBPACK_IMPORTED_MODULE_4__.autofixAddExposedWindow)(this), 3675 }, 3676 ); 3677 } 3678 yield* super.validate(defs); 3679 } 3680 } 3681 3682 3683 /***/ }), 3684 /* 29 */ 3685 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 3686 3687 __webpack_require__.r(__webpack_exports__); 3688 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 3689 /* harmony export */ CallbackInterface: () => (/* binding */ CallbackInterface) 3690 /* harmony export */ }); 3691 /* harmony import */ var _container_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(20); 3692 /* harmony import */ var _operation_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(13); 3693 /* harmony import */ var _constant_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(21); 3694 3695 3696 3697 3698 class CallbackInterface extends _container_js__WEBPACK_IMPORTED_MODULE_0__.Container { 3699 /** 3700 * @param {import("../tokeniser.js").Tokeniser} tokeniser 3701 * @param {*} callback 3702 * @param {object} [options] 3703 * @param {import("./container.js").AllowedMember[]} [options.extMembers] 3704 */ 3705 static parse(tokeniser, callback, { extMembers = [] } = {}) { 3706 const tokens = { callback }; 3707 tokens.base = tokeniser.consume("interface"); 3708 if (!tokens.base) { 3709 return; 3710 } 3711 return _container_js__WEBPACK_IMPORTED_MODULE_0__.Container.parse( 3712 tokeniser, 3713 new CallbackInterface({ source: tokeniser.source, tokens }), 3714 { 3715 allowedMembers: [ 3716 ...extMembers, 3717 [_constant_js__WEBPACK_IMPORTED_MODULE_2__.Constant.parse], 3718 [_operation_js__WEBPACK_IMPORTED_MODULE_1__.Operation.parse, { regular: true }], 3719 ], 3720 }, 3721 ); 3722 } 3723 3724 get type() { 3725 return "callback interface"; 3726 } 3727 } 3728 3729 3730 /***/ }), 3731 /* 30 */ 3732 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 3733 3734 __webpack_require__.r(__webpack_exports__); 3735 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 3736 /* harmony export */ Writer: () => (/* binding */ Writer), 3737 /* harmony export */ write: () => (/* binding */ write) 3738 /* harmony export */ }); 3739 function noop(arg) { 3740 return arg; 3741 } 3742 3743 const templates = { 3744 wrap: (items) => items.join(""), 3745 trivia: noop, 3746 name: noop, 3747 reference: noop, 3748 type: noop, 3749 generic: noop, 3750 nameless: noop, 3751 inheritance: noop, 3752 definition: noop, 3753 extendedAttribute: noop, 3754 extendedAttributeReference: noop, 3755 }; 3756 3757 class Writer { 3758 constructor(ts) { 3759 this.ts = Object.assign({}, templates, ts); 3760 } 3761 3762 /** 3763 * @param {string} raw 3764 * @param {object} options 3765 * @param {string} [options.unescaped] 3766 * @param {import("./productions/base.js").Base} [options.context] 3767 * @returns 3768 */ 3769 reference(raw, { unescaped, context }) { 3770 if (!unescaped) { 3771 unescaped = raw.startsWith("_") ? raw.slice(1) : raw; 3772 } 3773 return this.ts.reference(raw, unescaped, context); 3774 } 3775 3776 /** 3777 * @param {import("./tokeniser.js").Token} t 3778 * @param {Function} wrapper 3779 * @param {...any} args 3780 * @returns 3781 */ 3782 token(t, wrapper = noop, ...args) { 3783 if (!t) { 3784 return ""; 3785 } 3786 const value = wrapper(t.value, ...args); 3787 return this.ts.wrap([this.ts.trivia(t.trivia), value]); 3788 } 3789 3790 reference_token(t, context) { 3791 return this.token(t, this.reference.bind(this), { context }); 3792 } 3793 3794 name_token(t, arg) { 3795 return this.token(t, this.ts.name, arg); 3796 } 3797 3798 identifier(id, context) { 3799 return this.ts.wrap([ 3800 this.reference_token(id.tokens.value, context), 3801 this.token(id.tokens.separator), 3802 ]); 3803 } 3804 } 3805 3806 function write(ast, { templates: ts = templates } = {}) { 3807 ts = Object.assign({}, templates, ts); 3808 3809 const w = new Writer(ts); 3810 3811 return ts.wrap(ast.map((it) => it.write(w))); 3812 } 3813 3814 3815 /***/ }), 3816 /* 31 */ 3817 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 3818 3819 __webpack_require__.r(__webpack_exports__); 3820 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 3821 /* harmony export */ validate: () => (/* binding */ validate) 3822 /* harmony export */ }); 3823 /* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3); 3824 3825 3826 function getMixinMap(all, unique) { 3827 const map = new Map(); 3828 const includes = all.filter((def) => def.type === "includes"); 3829 for (const include of includes) { 3830 const mixin = unique.get(include.includes); 3831 if (!mixin) { 3832 continue; 3833 } 3834 const array = map.get(include.target); 3835 if (array) { 3836 array.push(mixin); 3837 } else { 3838 map.set(include.target, [mixin]); 3839 } 3840 } 3841 return map; 3842 } 3843 3844 /** 3845 * @typedef {ReturnType<typeof groupDefinitions>} Definitions 3846 */ 3847 function groupDefinitions(all) { 3848 const unique = new Map(); 3849 const duplicates = new Set(); 3850 const partials = new Map(); 3851 for (const def of all) { 3852 if (def.partial) { 3853 const array = partials.get(def.name); 3854 if (array) { 3855 array.push(def); 3856 } else { 3857 partials.set(def.name, [def]); 3858 } 3859 continue; 3860 } 3861 if (!def.name) { 3862 continue; 3863 } 3864 if (!unique.has(def.name)) { 3865 unique.set(def.name, def); 3866 } else { 3867 duplicates.add(def); 3868 } 3869 } 3870 return { 3871 all, 3872 unique, 3873 partials, 3874 duplicates, 3875 mixinMap: getMixinMap(all, unique), 3876 cache: { 3877 typedefIncludesDictionary: new WeakMap(), 3878 dictionaryIncludesRequiredField: new WeakMap(), 3879 }, 3880 }; 3881 } 3882 3883 function* checkDuplicatedNames({ unique, duplicates }) { 3884 for (const dup of duplicates) { 3885 const { name } = dup; 3886 const message = `The name "${name}" of type "${ 3887 unique.get(name).type 3888 }" was already seen`; 3889 yield (0,_error_js__WEBPACK_IMPORTED_MODULE_0__.validationError)(dup.tokens.name, dup, "no-duplicate", message); 3890 } 3891 } 3892 3893 function* validateIterable(ast) { 3894 const defs = groupDefinitions(ast); 3895 for (const def of defs.all) { 3896 if (def.validate) { 3897 yield* def.validate(defs); 3898 } 3899 } 3900 yield* checkDuplicatedNames(defs); 3901 } 3902 3903 // Remove this once all of our support targets expose `.flat()` by default 3904 function flatten(array) { 3905 if (array.flat) { 3906 return array.flat(); 3907 } 3908 return [].concat(...array); 3909 } 3910 3911 /** 3912 * @param {import("./productions/base.js").Base[]} ast 3913 * @return {import("./error.js").WebIDLErrorData[]} validation errors 3914 */ 3915 function validate(ast) { 3916 return [...validateIterable(flatten(ast))]; 3917 } 3918 3919 3920 /***/ }) 3921 /******/ ]); 3922 /************************************************************************/ 3923 /******/ // The module cache 3924 /******/ var __webpack_module_cache__ = {}; 3925 /******/ 3926 /******/ // The require function 3927 /******/ function __webpack_require__(moduleId) { 3928 /******/ // Check if module is in cache 3929 /******/ var cachedModule = __webpack_module_cache__[moduleId]; 3930 /******/ if (cachedModule !== undefined) { 3931 /******/ return cachedModule.exports; 3932 /******/ } 3933 /******/ // Create a new module (and put it into the cache) 3934 /******/ var module = __webpack_module_cache__[moduleId] = { 3935 /******/ // no module.id needed 3936 /******/ // no module.loaded needed 3937 /******/ exports: {} 3938 /******/ }; 3939 /******/ 3940 /******/ // Execute the module function 3941 /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); 3942 /******/ 3943 /******/ // Return the exports of the module 3944 /******/ return module.exports; 3945 /******/ } 3946 /******/ 3947 /************************************************************************/ 3948 /******/ /* webpack/runtime/define property getters */ 3949 /******/ (() => { 3950 /******/ // define getter functions for harmony exports 3951 /******/ __webpack_require__.d = (exports, definition) => { 3952 /******/ for(var key in definition) { 3953 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { 3954 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); 3955 /******/ } 3956 /******/ } 3957 /******/ }; 3958 /******/ })(); 3959 /******/ 3960 /******/ /* webpack/runtime/hasOwnProperty shorthand */ 3961 /******/ (() => { 3962 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) 3963 /******/ })(); 3964 /******/ 3965 /******/ /* webpack/runtime/make namespace object */ 3966 /******/ (() => { 3967 /******/ // define __esModule on exports 3968 /******/ __webpack_require__.r = (exports) => { 3969 /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 3970 /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 3971 /******/ } 3972 /******/ Object.defineProperty(exports, '__esModule', { value: true }); 3973 /******/ }; 3974 /******/ })(); 3975 /******/ 3976 /************************************************************************/ 3977 var __webpack_exports__ = {}; 3978 // This entry needs to be wrapped in an IIFE because it needs to be isolated against other modules in the chunk. 3979 (() => { 3980 __webpack_require__.r(__webpack_exports__); 3981 /* harmony export */ __webpack_require__.d(__webpack_exports__, { 3982 /* harmony export */ WebIDLParseError: () => (/* reexport safe */ _lib_tokeniser_js__WEBPACK_IMPORTED_MODULE_3__.WebIDLParseError), 3983 /* harmony export */ parse: () => (/* reexport safe */ _lib_webidl2_js__WEBPACK_IMPORTED_MODULE_0__.parse), 3984 /* harmony export */ validate: () => (/* reexport safe */ _lib_validator_js__WEBPACK_IMPORTED_MODULE_2__.validate), 3985 /* harmony export */ write: () => (/* reexport safe */ _lib_writer_js__WEBPACK_IMPORTED_MODULE_1__.write) 3986 /* harmony export */ }); 3987 /* harmony import */ var _lib_webidl2_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); 3988 /* harmony import */ var _lib_writer_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(30); 3989 /* harmony import */ var _lib_validator_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(31); 3990 /* harmony import */ var _lib_tokeniser_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(2); 3991 3992 3993 3994 3995 3996 })(); 3997 3998 /******/ return __webpack_exports__; 3999 /******/ })() 4000 ; 4001 }); 4002 //# sourceMappingURL=webidl2.js.map